17330f729Sjoerg //===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file contains error handling helper routines to pretty-print diagnostic
107330f729Sjoerg // messages from tblgen.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "llvm/ADT/Twine.h"
15*82d56013Sjoerg #include "llvm/Support/raw_ostream.h"
167330f729Sjoerg #include "llvm/Support/Signals.h"
177330f729Sjoerg #include "llvm/Support/WithColor.h"
18*82d56013Sjoerg #include "llvm/TableGen/Error.h"
19*82d56013Sjoerg #include "llvm/TableGen/Record.h"
207330f729Sjoerg #include <cstdlib>
217330f729Sjoerg
227330f729Sjoerg namespace llvm {
237330f729Sjoerg
247330f729Sjoerg SourceMgr SrcMgr;
257330f729Sjoerg unsigned ErrorsPrinted = 0;
267330f729Sjoerg
PrintMessage(ArrayRef<SMLoc> Loc,SourceMgr::DiagKind Kind,const Twine & Msg)277330f729Sjoerg static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
287330f729Sjoerg const Twine &Msg) {
297330f729Sjoerg // Count the total number of errors printed.
307330f729Sjoerg // This is used to exit with an error code if there were any errors.
317330f729Sjoerg if (Kind == SourceMgr::DK_Error)
327330f729Sjoerg ++ErrorsPrinted;
337330f729Sjoerg
347330f729Sjoerg SMLoc NullLoc;
357330f729Sjoerg if (Loc.empty())
367330f729Sjoerg Loc = NullLoc;
377330f729Sjoerg SrcMgr.PrintMessage(Loc.front(), Kind, Msg);
387330f729Sjoerg for (unsigned i = 1; i < Loc.size(); ++i)
397330f729Sjoerg SrcMgr.PrintMessage(Loc[i], SourceMgr::DK_Note,
407330f729Sjoerg "instantiated from multiclass");
417330f729Sjoerg }
427330f729Sjoerg
43*82d56013Sjoerg // Functions to print notes.
44*82d56013Sjoerg
PrintNote(const Twine & Msg)45*82d56013Sjoerg void PrintNote(const Twine &Msg) {
46*82d56013Sjoerg WithColor::note() << Msg << "\n";
47*82d56013Sjoerg }
487330f729Sjoerg
PrintNote(ArrayRef<SMLoc> NoteLoc,const Twine & Msg)497330f729Sjoerg void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
507330f729Sjoerg PrintMessage(NoteLoc, SourceMgr::DK_Note, Msg);
517330f729Sjoerg }
527330f729Sjoerg
53*82d56013Sjoerg // Functions to print fatal notes.
54*82d56013Sjoerg
PrintFatalNote(const Twine & Msg)55*82d56013Sjoerg void PrintFatalNote(const Twine &Msg) {
56*82d56013Sjoerg PrintNote(Msg);
57*82d56013Sjoerg // The following call runs the file cleanup handlers.
58*82d56013Sjoerg sys::RunInterruptHandlers();
59*82d56013Sjoerg std::exit(1);
60*82d56013Sjoerg }
61*82d56013Sjoerg
PrintFatalNote(ArrayRef<SMLoc> NoteLoc,const Twine & Msg)62*82d56013Sjoerg void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
63*82d56013Sjoerg PrintNote(NoteLoc, Msg);
64*82d56013Sjoerg // The following call runs the file cleanup handlers.
65*82d56013Sjoerg sys::RunInterruptHandlers();
66*82d56013Sjoerg std::exit(1);
67*82d56013Sjoerg }
68*82d56013Sjoerg
69*82d56013Sjoerg // This method takes a Record and uses the source location
70*82d56013Sjoerg // stored in it.
PrintFatalNote(const Record * Rec,const Twine & Msg)71*82d56013Sjoerg void PrintFatalNote(const Record *Rec, const Twine &Msg) {
72*82d56013Sjoerg PrintNote(Rec->getLoc(), Msg);
73*82d56013Sjoerg // The following call runs the file cleanup handlers.
74*82d56013Sjoerg sys::RunInterruptHandlers();
75*82d56013Sjoerg std::exit(1);
76*82d56013Sjoerg }
77*82d56013Sjoerg
78*82d56013Sjoerg // This method takes a RecordVal and uses the source location
79*82d56013Sjoerg // stored in it.
PrintFatalNote(const RecordVal * RecVal,const Twine & Msg)80*82d56013Sjoerg void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg) {
81*82d56013Sjoerg PrintNote(RecVal->getLoc(), Msg);
82*82d56013Sjoerg // The following call runs the file cleanup handlers.
83*82d56013Sjoerg sys::RunInterruptHandlers();
84*82d56013Sjoerg std::exit(1);
85*82d56013Sjoerg }
86*82d56013Sjoerg
87*82d56013Sjoerg // Functions to print warnings.
88*82d56013Sjoerg
PrintWarning(const Twine & Msg)89*82d56013Sjoerg void PrintWarning(const Twine &Msg) { WithColor::warning() << Msg << "\n"; }
90*82d56013Sjoerg
PrintWarning(ArrayRef<SMLoc> WarningLoc,const Twine & Msg)917330f729Sjoerg void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg) {
927330f729Sjoerg PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
937330f729Sjoerg }
947330f729Sjoerg
PrintWarning(const char * Loc,const Twine & Msg)957330f729Sjoerg void PrintWarning(const char *Loc, const Twine &Msg) {
967330f729Sjoerg SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg);
977330f729Sjoerg }
987330f729Sjoerg
99*82d56013Sjoerg // Functions to print errors.
100*82d56013Sjoerg
PrintError(const Twine & Msg)101*82d56013Sjoerg void PrintError(const Twine &Msg) { WithColor::error() << Msg << "\n"; }
1027330f729Sjoerg
PrintError(ArrayRef<SMLoc> ErrorLoc,const Twine & Msg)1037330f729Sjoerg void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
1047330f729Sjoerg PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
1057330f729Sjoerg }
1067330f729Sjoerg
PrintError(const char * Loc,const Twine & Msg)1077330f729Sjoerg void PrintError(const char *Loc, const Twine &Msg) {
1087330f729Sjoerg SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg);
1097330f729Sjoerg }
1107330f729Sjoerg
111*82d56013Sjoerg // This method takes a Record and uses the source location
112*82d56013Sjoerg // stored in it.
PrintError(const Record * Rec,const Twine & Msg)113*82d56013Sjoerg void PrintError(const Record *Rec, const Twine &Msg) {
114*82d56013Sjoerg PrintMessage(Rec->getLoc(), SourceMgr::DK_Error, Msg);
115*82d56013Sjoerg }
116*82d56013Sjoerg
117*82d56013Sjoerg // This method takes a RecordVal and uses the source location
118*82d56013Sjoerg // stored in it.
PrintError(const RecordVal * RecVal,const Twine & Msg)119*82d56013Sjoerg void PrintError(const RecordVal *RecVal, const Twine &Msg) {
120*82d56013Sjoerg PrintMessage(RecVal->getLoc(), SourceMgr::DK_Error, Msg);
121*82d56013Sjoerg }
122*82d56013Sjoerg
123*82d56013Sjoerg // Functions to print fatal errors.
1247330f729Sjoerg
PrintFatalError(const Twine & Msg)1257330f729Sjoerg void PrintFatalError(const Twine &Msg) {
1267330f729Sjoerg PrintError(Msg);
1277330f729Sjoerg // The following call runs the file cleanup handlers.
1287330f729Sjoerg sys::RunInterruptHandlers();
1297330f729Sjoerg std::exit(1);
1307330f729Sjoerg }
1317330f729Sjoerg
PrintFatalError(ArrayRef<SMLoc> ErrorLoc,const Twine & Msg)1327330f729Sjoerg void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
1337330f729Sjoerg PrintError(ErrorLoc, Msg);
1347330f729Sjoerg // The following call runs the file cleanup handlers.
1357330f729Sjoerg sys::RunInterruptHandlers();
1367330f729Sjoerg std::exit(1);
1377330f729Sjoerg }
1387330f729Sjoerg
139*82d56013Sjoerg // This method takes a Record and uses the source location
140*82d56013Sjoerg // stored in it.
PrintFatalError(const Record * Rec,const Twine & Msg)141*82d56013Sjoerg void PrintFatalError(const Record *Rec, const Twine &Msg) {
142*82d56013Sjoerg PrintError(Rec->getLoc(), Msg);
143*82d56013Sjoerg // The following call runs the file cleanup handlers.
144*82d56013Sjoerg sys::RunInterruptHandlers();
145*82d56013Sjoerg std::exit(1);
146*82d56013Sjoerg }
147*82d56013Sjoerg
148*82d56013Sjoerg // This method takes a RecordVal and uses the source location
149*82d56013Sjoerg // stored in it.
PrintFatalError(const RecordVal * RecVal,const Twine & Msg)150*82d56013Sjoerg void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) {
151*82d56013Sjoerg PrintError(RecVal->getLoc(), Msg);
152*82d56013Sjoerg // The following call runs the file cleanup handlers.
153*82d56013Sjoerg sys::RunInterruptHandlers();
154*82d56013Sjoerg std::exit(1);
155*82d56013Sjoerg }
156*82d56013Sjoerg
157*82d56013Sjoerg // Check an assertion: Obtain the condition value and be sure it is true.
158*82d56013Sjoerg // If not, print a nonfatal error along with the message.
CheckAssert(SMLoc Loc,Init * Condition,Init * Message)159*82d56013Sjoerg void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
160*82d56013Sjoerg auto *CondValue = dyn_cast_or_null<IntInit>(
161*82d56013Sjoerg Condition->convertInitializerTo(IntRecTy::get()));
162*82d56013Sjoerg if (!CondValue)
163*82d56013Sjoerg PrintError(Loc, "assert condition must of type bit, bits, or int.");
164*82d56013Sjoerg else if (!CondValue->getValue()) {
165*82d56013Sjoerg PrintError(Loc, "assertion failed");
166*82d56013Sjoerg if (auto *MessageInit = dyn_cast<StringInit>(Message))
167*82d56013Sjoerg PrintNote(MessageInit->getValue());
168*82d56013Sjoerg else
169*82d56013Sjoerg PrintNote("(assert message is not a string)");
170*82d56013Sjoerg }
171*82d56013Sjoerg }
172*82d56013Sjoerg
1737330f729Sjoerg } // end namespace llvm
174