[TableGen] Add PrintError family overload that take a print function (#107333)

Add PrintError and family overload that accepts a print function. This
avoids constructing potentially long strings for passing into these
print functions.
This commit is contained in:
Rahul Joshi 2024-09-07 05:13:54 -07:00 committed by GitHub
parent 6df1291296
commit 0ceffd362b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 69 additions and 47 deletions

View File

@ -14,12 +14,16 @@
#ifndef LLVM_TABLEGEN_ERROR_H
#define LLVM_TABLEGEN_ERROR_H
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/TableGen/Record.h"
namespace llvm {
class Record;
class RecordVal;
class Init;
void PrintNote(const Twine &Msg);
void PrintNote(function_ref<void(raw_ostream &OS)> PrintMsg);
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg);
[[noreturn]] void PrintFatalNote(const Twine &Msg);
@ -32,6 +36,7 @@ void PrintWarning(ArrayRef<SMLoc> WarningLoc, const Twine &Msg);
void PrintWarning(const char *Loc, const Twine &Msg);
void PrintError(const Twine &Msg);
void PrintError(function_ref<void(raw_ostream &OS)> PrintMsg);
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
void PrintError(const char *Loc, const Twine &Msg);
void PrintError(const Record *Rec, const Twine &Msg);
@ -41,6 +46,7 @@ void PrintError(const RecordVal *RecVal, const Twine &Msg);
[[noreturn]] void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg);
[[noreturn]] void PrintFatalError(const Record *Rec, const Twine &Msg);
[[noreturn]] void PrintFatalError(const RecordVal *RecVal, const Twine &Msg);
[[noreturn]] void PrintFatalError(function_ref<void(raw_ostream &OS)> PrintMsg);
void CheckAssert(SMLoc Loc, Init *Condition, Init *Message);
void dumpMessage(SMLoc Loc, Init *Message);

View File

@ -40,12 +40,23 @@ static void PrintMessage(ArrayRef<SMLoc> Loc, SourceMgr::DiagKind Kind,
"instantiated from multiclass");
}
// Run file cleanup handlers and then exit fatally (with non-zero exit code).
[[noreturn]] inline static void fatal_exit() {
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
}
// Functions to print notes.
void PrintNote(const Twine &Msg) {
WithColor::note() << Msg << "\n";
}
void PrintNote(function_ref<void(raw_ostream &OS)> PrintMsg) {
PrintMsg(WithColor::note());
}
void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
PrintMessage(NoteLoc, SourceMgr::DK_Note, Msg);
}
@ -54,34 +65,26 @@ void PrintNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
void PrintFatalNote(const Twine &Msg) {
PrintNote(Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
void PrintFatalNote(ArrayRef<SMLoc> NoteLoc, const Twine &Msg) {
PrintNote(NoteLoc, Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// This method takes a Record and uses the source location
// stored in it.
void PrintFatalNote(const Record *Rec, const Twine &Msg) {
PrintNote(Rec->getLoc(), Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// This method takes a RecordVal and uses the source location
// stored in it.
void PrintFatalNote(const RecordVal *RecVal, const Twine &Msg) {
PrintNote(RecVal->getLoc(), Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// Functions to print warnings.
@ -100,6 +103,10 @@ void PrintWarning(const char *Loc, const Twine &Msg) {
void PrintError(const Twine &Msg) { WithColor::error() << Msg << "\n"; }
void PrintError(function_ref<void(raw_ostream &OS)> PrintMsg) {
PrintMsg(WithColor::error());
}
void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
PrintMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
}
@ -124,34 +131,31 @@ void PrintError(const RecordVal *RecVal, const Twine &Msg) {
void PrintFatalError(const Twine &Msg) {
PrintError(Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
void PrintFatalError(function_ref<void(raw_ostream &OS)> PrintMsg) {
PrintError(PrintMsg);
fatal_exit();
}
void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg) {
PrintError(ErrorLoc, Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// This method takes a Record and uses the source location
// stored in it.
void PrintFatalError(const Record *Rec, const Twine &Msg) {
PrintError(Rec->getLoc(), Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// This method takes a RecordVal and uses the source location
// stored in it.
void PrintFatalError(const RecordVal *RecVal, const Twine &Msg) {
PrintError(RecVal->getLoc(), Msg);
// The following call runs the file cleanup handlers.
sys::RunInterruptHandlers();
std::exit(1);
fatal_exit();
}
// Check an assertion: Obtain the condition value and be sure it is true.

View File

@ -0,0 +1,14 @@
// RUN: not llvm-tblgen -gen-intrinsic-enums --intrinsic-prefix=gen3 -I %p/../../include %s -DTEST_INTRINSICS_SUPPRESS_DEFS 2>&1 | FileCheck %s
include "llvm/IR/Intrinsics.td"
// CHECK: error: tried to generate intrinsics for unknown target gen3
// CHECK-NEXT: Known targets are: gen1, gen2
let TargetPrefix = "gen1" in {
def int_gen1_int0 : Intrinsic<[llvm_i32_ty]>;
}
let TargetPrefix = "gen2" in {
def int_gen2_int0 : Intrinsic<[llvm_i32_ty]>;
}

View File

@ -1603,14 +1603,11 @@ static TreePatternNode &getOperandNum(unsigned OpNo, TreePatternNode &N,
OpNo -= NumResults;
if (OpNo >= N.getNumChildren()) {
std::string S;
raw_string_ostream OS(S);
OS << "Invalid operand number in type constraint " << (OpNo + NumResults)
<< " ";
N.print(OS);
PrintFatalError(S);
PrintFatalError([&N, OpNo, NumResults](raw_ostream &OS) {
OS << "Invalid operand number in type constraint " << (OpNo + NumResults);
N.print(OS);
});
}
return N.getChild(OpNo);
}

View File

@ -1961,12 +1961,11 @@ void parseVarLenInstOperand(const Record &Def,
}
static void debugDumpRecord(const Record &Rec) {
// Dump the record, so we can see what's going on...
std::string E;
raw_string_ostream S(E);
S << "Dumping record for previous error:\n";
S << Rec;
PrintNote(E);
// Dump the record, so we can see what's going on.
PrintNote([&Rec](raw_ostream &OS) {
OS << "Dumping record for previous error:\n";
OS << Rec;
});
}
/// For an operand field named OpName: populate OpInfo.InitValue with the

View File

@ -14,7 +14,6 @@
#include "Basic/SequenceToOffsetTable.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
@ -122,7 +121,8 @@ void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
// Find the TargetSet for which to generate enums. There will be an initial
// set with an empty target prefix which will include target independent
// intrinsics like dbg.value.
const CodeGenIntrinsicTable::TargetSet *Set = nullptr;
using TargetSet = CodeGenIntrinsicTable::TargetSet;
const TargetSet *Set = nullptr;
for (const auto &Target : Ints.Targets) {
if (Target.Name == IntrinsicPrefix) {
Set = &Target;
@ -130,13 +130,15 @@ void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
}
}
if (!Set) {
std::vector<std::string> KnownTargets;
for (const auto &Target : Ints.Targets)
if (!Target.Name.empty())
KnownTargets.push_back(Target.Name.str());
PrintFatalError("tried to generate intrinsics for unknown target " +
IntrinsicPrefix +
"\nKnown targets are: " + join(KnownTargets, ", ") + "\n");
// The first entry is for target independent intrinsics, so drop it.
auto KnowTargets = ArrayRef<TargetSet>(Ints.Targets).drop_front();
PrintFatalError([KnowTargets](raw_ostream &OS) {
OS << "tried to generate intrinsics for unknown target "
<< IntrinsicPrefix << "\nKnown targets are: ";
interleaveComma(KnowTargets, OS,
[&OS](const TargetSet &Target) { OS << Target.Name; });
OS << '\n';
});
}
// Generate a complete header for target specific intrinsics.