xref: /freebsd/contrib/llvm-project/llvm/lib/TableGen/Error.cpp (revision a7beca6fb113986839de73b7cf73d933464898c6)
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