184c287e3SPeter Collingbourne //===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===//
284c287e3SPeter Collingbourne //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
684c287e3SPeter Collingbourne //
784c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
884c287e3SPeter Collingbourne //
984c287e3SPeter Collingbourne // This file contains error handling helper routines to pretty-print diagnostic
1084c287e3SPeter Collingbourne // messages from tblgen.
1184c287e3SPeter Collingbourne //
1284c287e3SPeter Collingbourne //===----------------------------------------------------------------------===//
1384c287e3SPeter Collingbourne 
1484c287e3SPeter Collingbourne #include "llvm/ADT/Twine.h"
15b3931188SPaul C. Anagnostopoulos #include "llvm/Support/raw_ostream.h"
16e452e271SJames Y Knight #include "llvm/Support/Signals.h"
17c02bf01fSJonas Devlieghere #include "llvm/Support/WithColor.h"
18b3931188SPaul C. Anagnostopoulos #include "llvm/TableGen/Error.h"
19b3931188SPaul C. Anagnostopoulos #include "llvm/TableGen/Record.h"
20356f797dSJoerg Sonnenberger #include <cstdlib>
21356f797dSJoerg Sonnenberger 
2284c287e3SPeter Collingbourne namespace llvm {
2384c287e3SPeter Collingbourne 
2484c287e3SPeter Collingbourne SourceMgr SrcMgr;
25a1214e76SJakob Stoklund Olesen unsigned ErrorsPrinted = 0;
2684c287e3SPeter Collingbourne 
PrintMessage(ArrayRef<SMLoc> Loc,SourceMgr::DiagKind Kind,const Twine & Msg)27d7b66968SJakob Stoklund Olesen static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
28d7b66968SJakob Stoklund Olesen                          const Twine &Msg) {
29a1214e76SJakob Stoklund Olesen   // Count the total number of errors printed.
30a1214e76SJakob Stoklund Olesen   // This is used to exit with an error code if there were any errors.
31a1214e76SJakob Stoklund Olesen   if (Kind == SourceMgr::DK_Error)
32a1214e76SJakob Stoklund Olesen     ++ErrorsPrinted;
33a1214e76SJakob Stoklund Olesen 
34d7b66968SJakob Stoklund Olesen   SMLoc NullLoc;
35d7b66968SJakob Stoklund Olesen   if (Loc.empty())
36d7b66968SJakob Stoklund Olesen     Loc = NullLoc;
37d7b66968SJakob Stoklund Olesen   SrcMgr.PrintMessage(Loc.front(), Kind, Msg);
38d7b66968SJakob Stoklund Olesen   for (unsigned i = 1; i < Loc.size(); ++i)
39d7b66968SJakob Stoklund Olesen     SrcMgr.PrintMessage(Loc[i], SourceMgr::DK_Note,
40d7b66968SJakob Stoklund Olesen                         "instantiated from multiclass");
41d7b66968SJakob Stoklund Olesen }
42d7b66968SJakob Stoklund Olesen 
43c372809fSPaul C. Anagnostopoulos // Functions to print notes.
44c372809fSPaul C. Anagnostopoulos 
PrintNote(const Twine & Msg)45c372809fSPaul C. Anagnostopoulos void PrintNote(const Twine &Msg) {
46c372809fSPaul C. Anagnostopoulos   WithColor::note() << Msg << "\n";
47c372809fSPaul C. Anagnostopoulos }
48ec5208fdSDaniel Sanders 
PrintNote(ArrayRef<SMLoc> NoteLoc,const Twine & Msg)49466fe399SDaniel Sanders void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
50466fe399SDaniel Sanders   PrintMessage(NoteLoc, SourceMgr::DK_Note, Msg);
51466fe399SDaniel Sanders }
52466fe399SDaniel Sanders 
53c372809fSPaul C. Anagnostopoulos // Functions to print fatal notes.
54c372809fSPaul C. Anagnostopoulos 
PrintFatalNote(const Twine & Msg)55415fab6fSPaul C. Anagnostopoulos void PrintFatalNote(const Twine &Msg) {
56415fab6fSPaul C. Anagnostopoulos   PrintNote(Msg);
57415fab6fSPaul C. Anagnostopoulos   // The following call runs the file cleanup handlers.
58415fab6fSPaul C. Anagnostopoulos   sys::RunInterruptHandlers();
59415fab6fSPaul C. Anagnostopoulos   std::exit(1);
60415fab6fSPaul C. Anagnostopoulos }
61415fab6fSPaul C. Anagnostopoulos 
PrintFatalNote(ArrayRef<SMLoc> NoteLoc,const Twine & Msg)6288ce9f9bSJon Roelofs void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
6388ce9f9bSJon Roelofs   PrintNote(NoteLoc, Msg);
6488ce9f9bSJon Roelofs   // The following call runs the file cleanup handlers.
6588ce9f9bSJon Roelofs   sys::RunInterruptHandlers();
6688ce9f9bSJon Roelofs   std::exit(1);
6788ce9f9bSJon Roelofs }
6888ce9f9bSJon Roelofs 
69c372809fSPaul C. Anagnostopoulos // This method takes a Record and uses the source location
70c372809fSPaul C. Anagnostopoulos // stored in it.
PrintFatalNote(const Record * Rec,const Twine & Msg)71c372809fSPaul C. Anagnostopoulos void PrintFatalNote(const Record *Rec, const Twine &Msg) {
72c372809fSPaul C. Anagnostopoulos   PrintNote(Rec->getLoc(), Msg);
73c372809fSPaul C. Anagnostopoulos   // The following call runs the file cleanup handlers.
74c372809fSPaul C. Anagnostopoulos   sys::RunInterruptHandlers();
75c372809fSPaul C. Anagnostopoulos   std::exit(1);
76c372809fSPaul C. Anagnostopoulos }
77c372809fSPaul C. Anagnostopoulos 
78c372809fSPaul C. Anagnostopoulos // This method takes a RecordVal and uses the source location
79c372809fSPaul C. Anagnostopoulos // stored in it.
PrintFatalNote(const RecordVal * RecVal,const Twine & Msg)80c372809fSPaul C. Anagnostopoulos void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg) {
81c372809fSPaul C. Anagnostopoulos   PrintNote(RecVal->getLoc(), Msg);
82c372809fSPaul C. Anagnostopoulos   // The following call runs the file cleanup handlers.
83c372809fSPaul C. Anagnostopoulos   sys::RunInterruptHandlers();
84c372809fSPaul C. Anagnostopoulos   std::exit(1);
85c372809fSPaul C. Anagnostopoulos }
86c372809fSPaul C. Anagnostopoulos 
87c372809fSPaul C. Anagnostopoulos // Functions to print warnings.
88c372809fSPaul C. Anagnostopoulos 
PrintWarning(const Twine & Msg)89c372809fSPaul C. Anagnostopoulos void PrintWarning(const Twine &Msg) { WithColor::warning() << Msg << "\n"; }
90c372809fSPaul C. Anagnostopoulos 
PrintWarning(ArrayRef<SMLoc> WarningLoc,const Twine & Msg)91d7b66968SJakob Stoklund Olesen void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg) {
92d7b66968SJakob Stoklund Olesen   PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
93cc6cbf05SJim Grosbach }
94cc6cbf05SJim Grosbach 
PrintWarning(const char * Loc,const Twine & Msg)95cc6cbf05SJim Grosbach void PrintWarning(const char *Loc, const Twine &Msg) {
96cc6cbf05SJim Grosbach   SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg);
97cc6cbf05SJim Grosbach }
98cc6cbf05SJim Grosbach 
99c372809fSPaul C. Anagnostopoulos // Functions to print errors.
100c372809fSPaul C. Anagnostopoulos 
PrintError(const Twine & Msg)101c372809fSPaul C. Anagnostopoulos void PrintError(const Twine &Msg) { WithColor::error() << Msg << "\n"; }
102cc6cbf05SJim Grosbach 
PrintError(ArrayRef<SMLoc> ErrorLoc,const Twine & Msg)103d7b66968SJakob Stoklund Olesen void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
104d7b66968SJakob Stoklund Olesen   PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
10584c287e3SPeter Collingbourne }
10684c287e3SPeter Collingbourne 
PrintError(const char * Loc,const Twine & Msg)10784c287e3SPeter Collingbourne void PrintError(const char *Loc, const Twine &Msg) {
10803b80a40SChris Lattner   SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg);
10984c287e3SPeter Collingbourne }
11084c287e3SPeter Collingbourne 
111c372809fSPaul C. Anagnostopoulos // This method takes a Record and uses the source location
112c372809fSPaul C. Anagnostopoulos // stored in it.
PrintError(const Record * Rec,const Twine & Msg)113c372809fSPaul C. Anagnostopoulos void PrintError(const Record *Rec, const Twine &Msg) {
114c372809fSPaul C. Anagnostopoulos   PrintMessage(Rec->getLoc(), SourceMgr::DK_Error, Msg);
115c372809fSPaul C. Anagnostopoulos }
116c372809fSPaul C. Anagnostopoulos 
117415fab6fSPaul C. Anagnostopoulos // This method takes a RecordVal and uses the source location
118415fab6fSPaul C. Anagnostopoulos // stored in it.
PrintError(const RecordVal * RecVal,const Twine & Msg)119415fab6fSPaul C. Anagnostopoulos void PrintError(const RecordVal *RecVal, const Twine &Msg) {
120415fab6fSPaul C. Anagnostopoulos   PrintMessage(RecVal->getLoc(), SourceMgr::DK_Error, Msg);
121415fab6fSPaul C. Anagnostopoulos }
122415fab6fSPaul C. Anagnostopoulos 
123c372809fSPaul C. Anagnostopoulos // Functions to print fatal errors.
12484c287e3SPeter Collingbourne 
PrintFatalError(const Twine & Msg)12548e7e85dSBenjamin Kramer void PrintFatalError(const Twine &Msg) {
12648e7e85dSBenjamin Kramer   PrintError(Msg);
127e452e271SJames Y Knight   // The following call runs the file cleanup handlers.
128e452e271SJames Y Knight   sys::RunInterruptHandlers();
129356f797dSJoerg Sonnenberger   std::exit(1);
130356f797dSJoerg Sonnenberger }
131356f797dSJoerg Sonnenberger 
PrintFatalError(ArrayRef<SMLoc> ErrorLoc,const Twine & Msg)13248e7e85dSBenjamin Kramer void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
133356f797dSJoerg Sonnenberger   PrintError(ErrorLoc, Msg);
134e452e271SJames Y Knight   // The following call runs the file cleanup handlers.
135e452e271SJames Y Knight   sys::RunInterruptHandlers();
136356f797dSJoerg Sonnenberger   std::exit(1);
137356f797dSJoerg Sonnenberger }
138356f797dSJoerg Sonnenberger 
139b3931188SPaul C. Anagnostopoulos // This method takes a Record and uses the source location
140b3931188SPaul C. Anagnostopoulos // stored in it.
PrintFatalError(const Record * Rec,const Twine & Msg)141b3931188SPaul C. Anagnostopoulos void PrintFatalError(const Record *Rec, const Twine &Msg) {
142b3931188SPaul C. Anagnostopoulos   PrintError(Rec->getLoc(), Msg);
143b3931188SPaul C. Anagnostopoulos   // The following call runs the file cleanup handlers.
144b3931188SPaul C. Anagnostopoulos   sys::RunInterruptHandlers();
145b3931188SPaul C. Anagnostopoulos   std::exit(1);
146b3931188SPaul C. Anagnostopoulos }
147b3931188SPaul C. Anagnostopoulos 
148b3931188SPaul C. Anagnostopoulos // This method takes a RecordVal and uses the source location
149b3931188SPaul C. Anagnostopoulos // stored in it.
PrintFatalError(const RecordVal * RecVal,const Twine & Msg)150b3931188SPaul C. Anagnostopoulos void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) {
151b3931188SPaul C. Anagnostopoulos   PrintError(RecVal->getLoc(), Msg);
152b3931188SPaul C. Anagnostopoulos   // The following call runs the file cleanup handlers.
153b3931188SPaul C. Anagnostopoulos   sys::RunInterruptHandlers();
154b3931188SPaul C. Anagnostopoulos   std::exit(1);
155b3931188SPaul C. Anagnostopoulos }
156b3931188SPaul C. Anagnostopoulos 
1575f473a04SPaul C. Anagnostopoulos // Check an assertion: Obtain the condition value and be sure it is true.
1585f473a04SPaul C. Anagnostopoulos // If not, print a nonfatal error along with the message.
CheckAssert(SMLoc Loc,Init * Condition,Init * Message)1595f473a04SPaul C. Anagnostopoulos void CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
160*2ac3cd20SRiver Riddle   auto *CondValue = dyn_cast_or_null<IntInit>(Condition->convertInitializerTo(
161*2ac3cd20SRiver Riddle       IntRecTy::get(Condition->getRecordKeeper())));
1625f473a04SPaul C. Anagnostopoulos   if (!CondValue)
1635f473a04SPaul C. Anagnostopoulos     PrintError(Loc, "assert condition must of type bit, bits, or int.");
1645f473a04SPaul C. Anagnostopoulos   else if (!CondValue->getValue()) {
1655f473a04SPaul C. Anagnostopoulos     PrintError(Loc, "assertion failed");
1665f473a04SPaul C. Anagnostopoulos     if (auto *MessageInit = dyn_cast<StringInit>(Message))
1675f473a04SPaul C. Anagnostopoulos       PrintNote(MessageInit->getValue());
1685f473a04SPaul C. Anagnostopoulos     else
1695f473a04SPaul C. Anagnostopoulos       PrintNote("(assert message is not a string)");
1705f473a04SPaul C. Anagnostopoulos   }
1715f473a04SPaul C. Anagnostopoulos }
1725f473a04SPaul C. Anagnostopoulos 
17384c287e3SPeter Collingbourne } // end namespace llvm
174