[TableGen] Print assert message inline with assert failure (#111184)

Print assert message after the "assertion failed" message instead of
printing it as a separate note. This makes the assert failure reporting
less verbose and also more useful to see the failure message inline with
the "assertion failed" message.
This commit is contained in:
Rahul Joshi 2024-10-04 13:21:50 -07:00 committed by GitHub
parent 72f38040dd
commit e31e6f259e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 65 deletions

View File

@ -168,11 +168,10 @@ bool CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
return true;
}
if (!CondValue->getValue()) {
PrintError(Loc, "assertion failed");
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(MessageInit->getValue());
else
PrintNote("(assert message is not a string)");
auto *MessageInit = dyn_cast<StringInit>(Message);
StringRef AssertMsg = MessageInit ? MessageInit->getValue()
: "(assert message is not a string)";
PrintError(Loc, "assertion failed: " + AssertMsg);
return true;
}
return false;
@ -180,12 +179,10 @@ bool CheckAssert(SMLoc Loc, Init *Condition, Init *Message) {
// Dump a message to stderr.
void dumpMessage(SMLoc Loc, Init *Message) {
auto *MessageInit = dyn_cast<StringInit>(Message);
if (!MessageInit) {
PrintError(Loc, "dump value is not of type string");
} else {
if (auto *MessageInit = dyn_cast<StringInit>(Message))
PrintNote(Loc, MessageInit->getValue());
}
else
PrintError(Loc, "dump value is not of type string");
}
} // end namespace llvm

View File

@ -4,18 +4,13 @@
// Test the assert statement at top level.
// -----------------------------------------------------------------------------
// CHECK: assertion failed
// CHECK: [[FILE]]:[[@LINE+4]]:8: error: assertion failed: primary name is too long
// CHECK-NOT: note: primary name is too short
// CHECK: note: primary name is too long
defvar Name = "Grace Brewster Murray Hopper";
assert !ge(!size(Name), 20), "primary name is too short: " # Name;
assert !le(!size(Name), 20), "primary name is too long: " # Name;
// CHECK: assertion failed
// CHECK: note: first name is incorrect
// CHECK: assertion failed: first name is incorrect
def Rec01 {
string name = "Fred Smith";
}
@ -23,28 +18,21 @@ def Rec01 {
assert !eq(!substr(Rec01.name, 0, 3), "Jane"),
!strconcat("first name is incorrect: ", Rec01.name);
// CHECK: assertion failed
// CHECK: note: record Rec02 is broken
// CHECK: assertion failed: record Rec02 is broken
def Rec02 {
bit broken = true;
}
assert !not(Rec02.broken), "record Rec02 is broken";
// CHECK: assertion failed
// CHECK: note: cube of 9
// CHECK: assertion failed: cube of 9 should be 729
class Cube<int n> {
int result = !mul(n, n, n);
}
assert !eq(Cube<9>.result, 81), "cube of 9 should be 729";
// CHECK: assertion failed
// CHECK: note: foreach i cannot be 2
// CHECK-NOT: note: foreach i cannot be 2
// Verify that the assert fails only once.
// CHECK: assertion failed: foreach i cannot be 2
// CHECK-NOT: assertion failed: foreach i cannot be 2
foreach i = 1...3 in {
assert !ne(i, 2), "foreach i cannot be 2";
def bar_ # i;
@ -54,11 +42,9 @@ foreach i = 1...3 in {
// Test the assert statement in a record definition.
// -----------------------------------------------------------------------------
// CHECK: [[FILE]]:[[@LINE+8]]:10: error: assertion failed
// CHECK: [[FILE]]:[[@LINE+6]]:10: error: assertion failed: primary first name is not "Grack"
// CHECK-NOT: primary first name is not "Grace"
// CHECK: note: primary first name is not "Grack"
// CHECK: [[FILE]]:[[@LINE+7]]:10: error: assertion failed
// CHECK: note: foo field should be
// CHECK: [[FILE]]:[[@LINE+6]]:10: error: assertion failed: foo field should be
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec10 {
assert !eq(!substr(Name, 0, 5), "Grace"), "primary first name is not \"Grace\"";
@ -67,8 +53,7 @@ def Rec10 {
assert !eq(foo, "foo"), "foo field should be \"Foo\"";
}
// CHECK: [[FILE]]:[[@LINE+5]]:10: error: assertion failed
// CHECK: note: magic field is incorrect: 42
// CHECK: [[FILE]]:[[@LINE+4]]:10: error: assertion failed: magic field is incorrect: 42
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec11 {
int magic = 13;
@ -76,8 +61,7 @@ def Rec11 {
let magic = 42;
}
// CHECK: [[FILE]]:[[@LINE+6]]:10: error: assertion failed
// CHECK: note: var field has wrong value
// CHECK: [[FILE]]:[[@LINE+5]]:10: error: assertion failed: var field has wrong value
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec12 {
defvar prefix = "foo_";
@ -85,8 +69,7 @@ def Rec12 {
assert !eq(var, "foo_snorx"), "var field has wrong value: " # var;
}
// CHECK: assertion failed
// CHECK: note: kind field has wrong value
// CHECK: assertion failed: kind field has wrong value
class Kind {
int kind = 7;
}
@ -97,8 +80,7 @@ def Rec13 : Kind {
assert !eq(kind, 7), "kind field has wrong value: " # kind;
}
// CHECK: assertion failed
// CHECK: note: double_result should be
// CHECK: assertion failed: double_result should be
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec14 : Cube<3> {
int double_result = !mul(result, 2);
@ -122,13 +104,11 @@ class Person<string name, int age> : PersonName<name> {
def Rec20 : Person<"Donald Knuth", 60>;
// CHECK: assertion failed
// CHECK: note: person name is too long
// CHECK: assertion failed: person name is too long
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec21 : Person<"Donald Uh Oh This Name Is Too Long Knuth", 50>;
// CHECK: assertion failed
// CHECK: note: person age is invalid
// CHECK: assertion failed: person age is invalid
// CHECK: [[FILE]]:[[@LINE+1]]:5: error: assertion failed in this record
def Rec22 : Person<"Donald Knuth", 150>;
@ -138,16 +118,14 @@ def Rec30 {
int Age = Person<"Margaret Heafield Hamilton", 25>.Age;
}
// CHECK: assertion failed
// CHECK: note: person name is too long
// CHECK: assertion failed: person name is too long
// CHECK: [[FILE]]:[[@LINE+2]]:17: error: assertion failed in this record
def Rec31 {
string Name = Person<"Margaret Heafield And More Middle Names Hamilton", 25>.Name;
int Age = Person<"Margaret Heafield Hamilton", 25>.Age;
}
// CHECK: assertion failed
// CHECK: note: person age is invalid: 0
// CHECK: assertion failed: person age is invalid: 0
// CHECK: [[FILE]]:[[@LINE+3]]:13: error: assertion failed in this record
def Rec32 {
string Name = Person<"Margaret Heafield Hamilton", 25>.Name;
@ -158,11 +136,8 @@ def Rec32 {
// Test the assert statement in a multiclass.
// -----------------------------------------------------------------------------
// CHECK: assertion failed
// CHECK: note: MC1 id string is too long
// CHECK: assertion failed
// CHECK: note: MC1 seq is too high
// CHECK: assertion failed: MC1 id string is too long
// CHECK: assertion failed: MC1 seq is too high
multiclass MC1<string id, int seq> {
assert !le(!size(id), 5), "MC1 id string is too long";
assert !le(seq, 999999), "MC1 seq is too high";
@ -177,9 +152,7 @@ defm Rec40 : MC1<"ILISP", 999>;
defm Rec41 : MC1<"ILISPX", 999>;
defm Rec42 : MC1<"ILISP", 999999999>;
// CHECK: assertion failed
// CHECK: note: MC2 phrase must be secret: secrex code
// CHECK: assertion failed: MC2 phrase must be secret: secrex code
multiclass MC2<string phr> {
assert !eq(!substr(phr, 0, 6), "secret"), "MC2 phrase must be secret: " # phr;
@ -194,9 +167,7 @@ multiclass MC3<string phr> {
defm Rec43 : MC3<"secrex code">;
// CHECK: assertion failed
// CHECK: note: MC2 phrase must be secret: xecret code
// CHECK: assertion failed: MC2 phrase must be secret: xecret code
multiclass MC4<string phr> : MC2<phr> {
def _def;
}
@ -205,11 +176,8 @@ defm Rec44 : MC4<"xecret code">;
// Test a defm in a multiclass that inherits from a class with asserts.
// CHECK: assertion failed
// CHECK: note: MC5 name must include a space: Ada_Lovelace
// CHECK: assertion failed
// CHECK: note: person age is invalid: 666
// CHECK: assertion failed: MC5 name must include a space: Ada_Lovelace
// CHECK: assertion failed: person age is invalid: 666
multiclass MC5<string phr, string name, int age> {
assert !ne(!find(name, " "), -1), "MC5 name must include a space: " # name;