From 18f1998a00492bb70de37aaab4441ea9cea306f5 Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Mon, 19 Mar 2018 14:14:10 +0000 Subject: [PATCH] TableGen: Explicitly test some cases of self-references and !cast errors Summary: These are cases of self-references that exist today in practice. Let's add tests for them to avoid regressions. The self-references in PPCInstrInfo.td can be expressed in a simpler way. Allowing this type of self-reference while at the same time consistently doing late-resolve even for self-references is problematic because there are references to fields that aren't in any class. Since there's no need for this type of self-reference anyway, let's just remove it. Change-Id: I914e0b3e1ae7adae33855fac409b536879bc3f62 Reviewers: arsenm, craig.topper, tra, MartinO Subscribers: nemanjai, wdng, kbarton, llvm-commits Differential Revision: https://reviews.llvm.org/D44474 llvm-svn: 327848 --- llvm/lib/TableGen/Record.cpp | 2 +- llvm/lib/Target/PowerPC/PPCInstrInfo.td | 12 +++---- llvm/test/TableGen/cast-typeerror.td | 14 ++++++++ llvm/test/TableGen/self-reference-typeerror.td | 13 ++++++++ llvm/test/TableGen/self-reference.td | 44 ++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 llvm/test/TableGen/cast-typeerror.td create mode 100644 llvm/test/TableGen/self-reference-typeerror.td create mode 100644 llvm/test/TableGen/self-reference.td diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp index 331e2bc..8b78f22 100644 --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -1887,7 +1887,7 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) { PrintFatalError(getLoc(), Twine("Invalid value ") + Type + "is found when setting '" + Value.getNameInitAsString() + - " of type '" + + "' of type '" + Value.getType()->getAsString() + "' after resolving references: " + VR->getAsUnquotedString() + "\n"); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index d51a0e50..4030ca4 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -4695,10 +4695,10 @@ def DWMaskValues { def DWSwapInByte { dag Swap1 = (OR8 (AND8 (RLDICL $A, 63, 1), DWMaskValues.Lo1), (AND8 (RLDICR $A, 1, 62), DWMaskValues.Hi1)); - dag Swap2 = (OR8 (AND8 (RLDICL DWSwapInByte.Swap1, 62, 2), DWMaskValues.Lo2), - (AND8 (RLDICR DWSwapInByte.Swap1, 2, 61), DWMaskValues.Hi2)); - dag Swap4 = (OR8 (AND8 (RLDICL DWSwapInByte.Swap2, 60, 4), DWMaskValues.Lo4), - (AND8 (RLDICR DWSwapInByte.Swap2, 4, 59), DWMaskValues.Hi4)); + dag Swap2 = (OR8 (AND8 (RLDICL Swap1, 62, 2), DWMaskValues.Lo2), + (AND8 (RLDICR Swap1, 2, 61), DWMaskValues.Hi2)); + dag Swap4 = (OR8 (AND8 (RLDICL Swap2, 60, 4), DWMaskValues.Lo4), + (AND8 (RLDICR Swap2, 4, 59), DWMaskValues.Hi4)); } // Intra-byte swap is done, now start inter-byte swap. @@ -4718,7 +4718,7 @@ def DWBytes7656 { def DWBytes7654 { dag Word = (RLWIMI DWBytes7656.Word, DWBytes4567.Word, 8, 24, 31); dag DWord = - (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), DWBytes7654.Word, sub_32)); + (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), Word, sub_32)); } def DWBytes0123 { @@ -4737,7 +4737,7 @@ def DWBytes3212 { def DWBytes3210 { dag Word = (RLWIMI DWBytes3212.Word, DWBytes0123.Word, 8, 24, 31); dag DWord = - (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), DWBytes3210.Word, sub_32)); + (i64 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), Word, sub_32)); } // Now both high word and low word are reversed, next diff --git a/llvm/test/TableGen/cast-typeerror.td b/llvm/test/TableGen/cast-typeerror.td new file mode 100644 index 0000000..4cda44b --- /dev/null +++ b/llvm/test/TableGen/cast-typeerror.td @@ -0,0 +1,14 @@ +// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s +// XFAIL: vg_leak + +class A; +class B; + +def A0 : A; + +class C { + B b = !cast(name); +} + +// CHECK: error: Invalid value of type 'A' is found when setting 'b' of type 'B' +def Test : C<"A0">; diff --git a/llvm/test/TableGen/self-reference-typeerror.td b/llvm/test/TableGen/self-reference-typeerror.td new file mode 100644 index 0000000..43fb062 --- /dev/null +++ b/llvm/test/TableGen/self-reference-typeerror.td @@ -0,0 +1,13 @@ +// RUN: not llvm-tblgen %s 2>&1 | FileCheck %s +// XFAIL: vg_leak + +class A { + A a = x; +} + +// At the time A0 is referenced, A has not yet been established as a superclass. +// This kind of self-reference is discourage, but if you *really* want it, you +// can force it with !cast. +// +// CHECK: Value 'A:x' of type 'A' is incompatible with initializer +def A0 : A; diff --git a/llvm/test/TableGen/self-reference.td b/llvm/test/TableGen/self-reference.td new file mode 100644 index 0000000..a4f1d9a --- /dev/null +++ b/llvm/test/TableGen/self-reference.td @@ -0,0 +1,44 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +// CHECK: --- Defs --- + +// CHECK: def A0 { +// CHECK: dag a = (ops A0); +// CHECK: } + +// CHECK: def B0 { +// CHECK: dag a = (ops); +// CHECK: A b = B0; +// CHECK: } + +// CHECK: def C0 { +// CHECK: dag q = (ops C0); +// CHECK: } + +def ops; + +class A { + dag a = d; +} + +// This type of self-reference is used in various places defining register +// classes. +def A0 : A<(ops A0)>; + +class B { + A b = !cast(self); +} + +// A stronger form of this type of self-reference is used at least in the +// SystemZ backend to define a record which is a ComplexPattern and an Operand +// at the same time. +def B0 : A<(ops)>, B<"B0">; + +// Casting C0 to C by name here is tricky, because it happens while (or rather: +// before) adding C as a superclass. However, SystemZ uses this pattern. +class C { + dag q = (ops !cast(self)); +} + +def C0 : C<"C0">; -- 2.7.4