Home | History | Annotate | Line # | Download | only in TableGen
      1 //===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file contains error handling helper routines to pretty-print diagnostic
     10 // messages from tblgen.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/ADT/Twine.h"
     15 #include "llvm/Support/raw_ostream.h"
     16 #include "llvm/Support/Signals.h"
     17 #include "llvm/Support/WithColor.h"
     18 #include "llvm/TableGen/Error.h"
     19 #include "llvm/TableGen/Record.h"
     20 #include <cstdlib>
     21 
     22 namespace llvm {
     23 
     24 SourceMgr SrcMgr;
     25 unsigned ErrorsPrinted = 0;
     26 
     27 static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
     28                          const Twine &Msg) {
     29   // Count the total number of errors printed.
     30   // This is used to exit with an error code if there were any errors.
     31   if (Kind == SourceMgr::DK_Error)
     32     ++ErrorsPrinted;
     33 
     34   SMLoc NullLoc;
     35   if (Loc.empty())
     36     Loc = NullLoc;
     37   SrcMgr.PrintMessage(Loc.front(), Kind, Msg);
     38   for (unsigned i = 1; i < Loc.size(); ++i)
     39     SrcMgr.PrintMessage(Loc[i], SourceMgr::DK_Note,
     40                         "instantiated from multiclass");
     41 }
     42 
     43 // Functions to print notes.
     44 
     45 void PrintNote(const Twine &Msg) {
     46   WithColor::note() << Msg << "\n";
     47 }
     48 
     49 void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
     50   PrintMessage(NoteLoc, SourceMgr::DK_Note, Msg);
     51 }
     52 
     53 // Functions to print fatal notes.
     54 
     55 void PrintFatalNote(const Twine &Msg) {
     56   PrintNote(Msg);
     57   // The following call runs the file cleanup handlers.
     58   sys::RunInterruptHandlers();
     59   std::exit(1);
     60 }
     61 
     62 void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
     63   PrintNote(NoteLoc, Msg);
     64   // The following call runs the file cleanup handlers.
     65   sys::RunInterruptHandlers();
     66   std::exit(1);
     67 }
     68 
     69 // This method takes a Record and uses the source location
     70 // stored in it.
     71 void PrintFatalNote(const Record *Rec, const Twine &Msg) {
     72   PrintNote(Rec->getLoc(), Msg);
     73   // The following call runs the file cleanup handlers.
     74   sys::RunInterruptHandlers();
     75   std::exit(1);
     76 }
     77 
     78 // This method takes a RecordVal and uses the source location
     79 // stored in it.
     80 void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg) {
     81   PrintNote(RecVal->getLoc(), Msg);
     82   // The following call runs the file cleanup handlers.
     83   sys::RunInterruptHandlers();
     84   std::exit(1);
     85 }
     86 
     87 // Functions to print warnings.
     88 
     89 void PrintWarning(const Twine &Msg) { WithColor::warning() << Msg << "\n"; }
     90 
     91 void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg) {
     92   PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
     93 }
     94 
     95 void PrintWarning(const char *Loc, const Twine &Msg) {
     96   SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg);
     97 }
     98 
     99 // Functions to print errors.
    100 
    101 void PrintError(const Twine &Msg) { WithColor::error() << Msg << "\n"; }
    102 
    103 void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
    104   PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
    105 }
    106 
    107 void PrintError(const char *Loc, const Twine &Msg) {
    108   SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg);
    109 }
    110 
    111 // This method takes a Record and uses the source location
    112 // stored in it.
    113 void PrintError(const Record *Rec, const Twine &Msg) {
    114   PrintMessage(Rec->getLoc(), SourceMgr::DK_Error, Msg);
    115 }
    116 
    117 // This method takes a RecordVal and uses the source location
    118 // stored in it.
    119 void PrintError(const RecordVal *RecVal, const Twine &Msg) {
    120   PrintMessage(RecVal->getLoc(), SourceMgr::DK_Error, Msg);
    121 }
    122 
    123 // Functions to print fatal errors.
    124 
    125 void PrintFatalError(const Twine &Msg) {
    126   PrintError(Msg);
    127   // The following call runs the file cleanup handlers.
    128   sys::RunInterruptHandlers();
    129   std::exit(1);
    130 }
    131 
    132 void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
    133   PrintError(ErrorLoc, Msg);
    134   // The following call runs the file cleanup handlers.
    135   sys::RunInterruptHandlers();
    136   std::exit(1);
    137 }
    138 
    139 // This method takes a Record and uses the source location
    140 // stored in it.
    141 void PrintFatalError(const Record *Rec, const Twine &Msg) {
    142   PrintError(Rec->getLoc(), Msg);
    143   // The following call runs the file cleanup handlers.
    144   sys::RunInterruptHandlers();
    145   std::exit(1);
    146 }
    147 
    148 // This method takes a RecordVal and uses the source location
    149 // stored in it.
    150 void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) {
    151   PrintError(RecVal->getLoc(), Msg);
    152   // The following call runs the file cleanup handlers.
    153   sys::RunInterruptHandlers();
    154   std::exit(1);
    155 }
    156 
    157 // Check an assertion: Obtain the condition value and be sure it is true.
    158 // If not, print a nonfatal error along with the message.
    159 void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
    160   auto *CondValue = dyn_cast_or_null<IntInit>(
    161                         Condition->convertInitializerTo(IntRecTy::get()));
    162   if (!CondValue)
    163     PrintError(Loc, "assert condition must of type bit, bits, or int.");
    164   else if (!CondValue->getValue()) {
    165     PrintError(Loc, "assertion failed");
    166     if (auto *MessageInit = dyn_cast<StringInit>(Message))
    167       PrintNote(MessageInit->getValue());
    168     else
    169       PrintNote("(assert message is not a string)");
    170   }
    171 }
    172 
    173 } // end namespace llvm
    174