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>(Condition->convertInitializerTo( 161 IntRecTy::get(Condition->getRecordKeeper()))); 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 // Dump a message to stderr. 174 void dumpMessage(SMLoc Loc, Init *Message) { 175 auto *MessageInit = dyn_cast<StringInit>(Message); 176 assert(MessageInit && "no debug message to print"); 177 PrintNote(Loc, MessageInit->getValue()); 178 } 179 180 } // end namespace llvm 181