
The core part of this change is an extension to the tablegen language to allow conditional definition of records using if-statements based on !exists conditions. The RISCV td file change is mostly to illustrate the potential use of conditional definitions. I am deliberately not maximally simplifying in this change to make merging with downstream code (or simply rebasing while this on review) easier. Some background to make the change understandable. TableGen does not have an if statement internally. It has if expressions - in the form of TernInitOp with IF opcode - and foreach statements. It implements an if-statement as a foreach which iterates either 0 or 1 times. Foreach nodes are then evaluated via unrolling inside the parser. Specifically, they are evaluated, at latest, when the outermost multiclass or loop containing them reaches end of scope. The unrolled statements remain (potentially) unresolved after unrolling, but the number of iterations must be known at this point. An !exists clause can only evaluate at final evaluation. (Specifically, forward references to definitions are allowed - up to the end of the containing scope at least.) The existing code did not set the final flag on the resolver, and thus would leave the !exists clause in an unresolved state. This would then cause an error since we don't know how many iterations on which to unroll the (synthetic) foreach loop. I chose to only finally-evaluate the condition of the if-expression. This allows us to pick an arm at scope exit without inhibiting definitions in the arm from having self references. Differential Revision: https://reviews.llvm.org/D145108
102 lines
2.0 KiB
TableGen
102 lines
2.0 KiB
TableGen
// RUN: llvm-tblgen --no-warn-on-unused-template-args %s | FileCheck %s
|
|
// XFAIL: vg_leak
|
|
|
|
class A;
|
|
def a0 : A;
|
|
|
|
class A_check<string name>{
|
|
int exists = !exists<A>(name);
|
|
}
|
|
|
|
def a0_exists : A_check<"a0">;
|
|
def a1_missing : A_check<"a1">;
|
|
|
|
|
|
// Subclasses are allowed.
|
|
|
|
class B;
|
|
class SubOfB : B;
|
|
class B_check<string name> {
|
|
int exists = !exists<B>(name);
|
|
}
|
|
|
|
def sub : SubOfB;
|
|
|
|
def sub_exists : B_check<"sub">;
|
|
def a0_is_not_sub_of_B : B_check<"a0">;
|
|
|
|
|
|
// Self-references are allowed.
|
|
|
|
class Self_check<string name> {
|
|
int exists = !exists<Self_check>(name);
|
|
}
|
|
|
|
def self_reference : Self_check<"self_reference">; // Self-reference
|
|
// There is no record called `current` in current context though we will define it below.
|
|
def current_missing : Self_check<"current">;
|
|
def current : Self_check<"current">;
|
|
|
|
|
|
// Check that conditional definitions dependent on the resolution of an
|
|
// exists clause work as expected.
|
|
// Reminder: a0 exists, a1 does not.
|
|
class C {
|
|
int exists = 1;
|
|
}
|
|
if !exists<A>("a0") then
|
|
def if_exists : C;
|
|
if !exists<A>("a1") then
|
|
def if_no_exists: C;
|
|
foreach e = ["a0", "a1"] in {
|
|
if !exists<A>(e) then
|
|
def for_exists_ # e: C;
|
|
}
|
|
multiclass mc {
|
|
foreach e = ["a0", "a1"] in {
|
|
if !exists<A>(e) then
|
|
def _ # e: C;
|
|
}
|
|
}
|
|
defm multiclass_exists : mc<>;
|
|
|
|
|
|
// CHECK: def a0_exists {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
|
|
// CHECK: def a0_is_not_sub_of_B {
|
|
// CHECK: int exists = 0;
|
|
// CHECK: }
|
|
|
|
// CHECK: def a1_missing {
|
|
// CHECK: int exists = 0;
|
|
// CHECK: }
|
|
|
|
// CHECK: def current {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
|
|
// `current` doesn't exist because we define it below `current_missing`.
|
|
// CHECK: def current_missing {
|
|
// CHECK: int exists = 0;
|
|
// CHECK: }
|
|
|
|
// CHECK: def for_exists_a0 {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
// CHECK: def if_exists {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
// CHECK: def multiclass_exists_a0 {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
|
|
// CHECK: def self_reference {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|
|
|
|
// CHECK: def sub_exists {
|
|
// CHECK: int exists = 1;
|
|
// CHECK: }
|