1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// RUN: llvm-tblgen %s | FileCheck %s
// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s
// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s
// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s
#ifdef ERROR1
// Refer to a variable we haven't defined *yet*, expecting an error.
// ERROR1: [[@LINE+1]]:22: error: Variable not defined: 'myvar'
def bad { dag x = (? myvar); }
#endif
// Define a global variable.
defvar myvar = "foo";
#ifdef ERROR2
// Demonstrate an error when a global variable is redefined.
// ERROR2: [[@LINE+1]]:8: error: def or global variable of this name already exists
defvar myvar = "another value";
#endif
multiclass Test<int x> {
// Refer to a global variable, while inside a local scope like a multiclass.
def _with_global_string { string s = myvar; }
// Define some variables local to this multiclass, and prove we can refer to
// those too.
defvar myvar = !add(x, 100);
defvar myvar2 = "string of " # myvar;
def _with_local_int { int i = myvar; string s = myvar2; }
#ifdef ERROR3
// Demonstrate an error when a local variable is redefined.
// ERROR3: [[@LINE+1]]:10: error: local variable of this name already exists
defvar myvar = "another value";
#endif
}
// Instantiate the above multiclass, and expect all the right outputs.
// CHECK: def aaa_with_global_string {
// CHECK-NEXT: string s = "foo";
// CHECK: def aaa_with_local_int {
// CHECK-NEXT: int i = 101;
// CHECK-NEXT: string s = "string of 101";
// CHECK: def bbb_with_global_string {
// CHECK-NEXT: string s = "foo";
// CHECK: def bbb_with_local_int {
// CHECK-NEXT: int i = 102;
// CHECK-NEXT: string s = "string of 102";
defm aaa: Test<1>;
defm bbb: Test<2>;
// Test that local variables can be defined inside a foreach block, and inside
// an object body.
//
// The scopes nest (you can refer to variables in an outer block from an inner
// one), and the variables go out of scope again at the end of the block (in
// particular, you don't get a redefinition error the next time round the
// loop).
// CHECK: def nest_f1_s3 {
// CHECK-NEXT: int member = 113;
// CHECK-NEXT: }
// CHECK: def nest_f1_s4 {
// CHECK-NEXT: int member = 114;
// CHECK-NEXT: }
// CHECK: def nest_f2_s3 {
// CHECK-NEXT: int member = 123;
// CHECK-NEXT: }
// CHECK: def nest_f2_s4 {
// CHECK-NEXT: int member = 124;
// CHECK-NEXT: }
foreach first = [ 1, 2 ] in {
defvar firstStr = "f" # first;
foreach second = [ 3, 4 ] in {
defvar secondStr = "s" # second;
def "nest_" # firstStr # "_" # secondStr {
defvar defLocalVariable = !add(!mul(first, 10), second);
int member = !add(100, defLocalVariable);
}
}
}
defvar firstStr = "now define this at the top level and still expect no error";
// Test that you can shadow an outer declaration with an inner one. Here, we
// expect all the shadowOuter records (both above and below the inner foreach)
// to get the value 1 from the outer definition of shadowedVariable, and the
// shadowInner ones to get 2 from the inner definition.
// CHECK: def shadowInner11 {
// CHECK-NEXT: int var = 2;
// CHECK: def shadowInner12 {
// CHECK-NEXT: int var = 2;
// CHECK: def shadowInner21 {
// CHECK-NEXT: int var = 2;
// CHECK: def shadowInner22 {
// CHECK-NEXT: int var = 2;
// CHECK: def shadowInnerIf1 {
// CHECK-NEXT: int var = 3;
// CHECK: def shadowOuterAbove1 {
// CHECK-NEXT: int var = 1;
// CHECK: def shadowOuterAbove2 {
// CHECK-NEXT: int var = 1;
// CHECK: def shadowOuterBelowForeach1 {
// CHECK-NEXT: int var = 1;
// CHECK: def shadowOuterBelowForeach2 {
// CHECK-NEXT: int var = 1;
// CHECK: def shadowOuterBelowIf1 {
// CHECK-NEXT: int var = 1;
// CHECK: def shadowOuterBelowIf2 {
// CHECK-NEXT: int var = 1;
foreach first = [ 1, 2 ] in {
defvar shadowedVariable = 1;
def shadowOuterAbove # first { int var = shadowedVariable; }
// The foreach statement opens a new scope, in which a new variable of the
// same name can be defined without clashing with the outer one.
foreach second = [ 1, 2 ] in {
defvar shadowedVariable = 2;
def shadowInner # first # second { int var = shadowedVariable; }
}
// Now the outer variable is back in scope.
def shadowOuterBelowForeach # first { int var = shadowedVariable; }
// An if statement also opens a new scope.
if !eq(first, 1) then {
defvar shadowedVariable = 3;
def shadowInnerIf # first { int var = shadowedVariable; }
}
// Now the outer variable is back in scope again.
def shadowOuterBelowIf # first { int var = shadowedVariable; }
}
// Test that a top-level let statement also makes a variable scope (on the
// general principle of consistency, because it defines a braced sub-block).
let someVariable = "some value" in {
defvar myvar = "override the definition from above and expect no error";
}
// CHECK: def topLevelLetTest {
// CHECK-NEXT: string val = "foo";
def topLevelLetTest { string val = myvar; }
|