blob: 1b811a7e91dacf38d21dddfbf86ba4da2470a9f5 [file] [log] [blame] [edit]
// RUN: llvm-tblgen %s | FileCheck %s
// Test 'let append' and 'let prepend' syntax in body items.
def op;
class Base {
list<int> items = [1, 2];
string text = "hello";
dag d = (op);
}
class WithCode {
code body = [{ int x = 0; }];
}
class WithUnset {
list<int> vals = ?;
string msg = ?;
}
// Multi-level inheritance accumulation.
class Middle : Base {
let append items = [3];
let append text = " world";
}
// Multiple inheritance classes.
class BaseA {
list<int> items = [1, 2];
string text = "a";
}
class BaseB {
list<int> items = [3, 4];
string text = "b";
}
// Diamond inheritance classes.
class DiamondBase {
list<int> items = [1];
}
class Left : DiamondBase {
let append items = [2]; // items = [1, 2]
}
class Right : DiamondBase {
let append items = [3]; // items = [1, 3]
}
// Template argument class.
class Parameterized<list<int> init> {
list<int> items = init;
}
// Multiclass with append/prepend in body.
multiclass MC<list<int> extra> {
def _a : Base {
let append items = extra;
}
def _b : Base {
let prepend items = extra;
}
}
// Test that 'append' and 'prepend' can be used as field names
// (contextual keywords, not reserved).
class HasAppendField {
list<int> append = [1, 2];
list<int> prepend = [3, 4];
int other = 0;
}
// Test that scalar fields named 'append'/'prepend' work with plain let.
class HasScalarAppendField {
int append = 0;
int prepend = 0;
}
// --- Definitions (CHECK lines in alphabetical order of def names) ---
// CHECK: def AppendCode
// CHECK: code body = [{ int x = 0; int y = 1; }]
def AppendCode : WithCode {
let append body = [{ int y = 1; }];
}
// CHECK: def AppendDag
// CHECK: dag d = (op 3:$a);
def AppendDag : Base {
let append d = (op 3:$a);
}
// CHECK: def AppendList
// CHECK: list<int> items = [1, 2, 3, 4];
def AppendList : Base {
let append items = [3, 4];
}
// CHECK: def AppendString
// CHECK: string text = "hello world";
def AppendString : Base {
let append text = " world";
}
// CHECK: def AppendUnset
// CHECK: list<int> vals = [1];
// CHECK: string msg = "hi";
def AppendUnset : WithUnset {
let append vals = [1];
let append msg = "hi";
}
// Test 'let append = ...' on a scalar (int) field named 'append'.
// CHECK: def AssignScalarAppend
// CHECK: int append = 42;
// CHECK: int prepend = 99;
def AssignScalarAppend : HasScalarAppendField {
let append = 42;
let prepend = 99;
}
// Test sequential append + prepend on the same field.
// CHECK: def Both
// CHECK: list<int> items = [0, 1, 2, 3];
def Both : Base {
let append items = [3];
let prepend items = [0];
}
// Test 'let append append' where the second 'append' is the field name.
// CHECK: def ContextualKeyword
// CHECK: list<int> append = [1, 2, 5];
// CHECK: list<int> prepend = [0, 3, 4];
// CHECK: int other = 0;
def ContextualKeyword : HasAppendField {
let append append = [5];
let prepend prepend = [0];
}
// Test diamond inheritance: Right is the last parent, so only Right's
// accumulated value survives. Left's append is lost.
// CHECK: def Diamond
// CHECK: list<int> items = [1, 3, 4];
def Diamond : Left, Right {
let append items = [4];
}
// Test 'let append = ...' where 'append' is the field name (no mode keyword).
// CHECK: def FieldNamedAppend
// CHECK: list<int> append = [10, 20];
// CHECK: list<int> prepend = [30, 40];
// CHECK: int other = 5;
def FieldNamedAppend : HasAppendField {
let append = [10, 20];
let prepend = [30, 40];
let other = 5;
}
// Test let append on a field set by a template argument.
// CHECK: def FromTemplateArg
// CHECK: list<int> items = [1, 2, 3];
def FromTemplateArg : Parameterized<[1, 2]> {
let append items = [3];
}
// Test let append in multiclass body with defm.
// CHECK: def MCTest_a
// CHECK: list<int> items = [1, 2, 10, 20];
// CHECK: def MCTest_b
// CHECK: list<int> items = [10, 20, 1, 2];
defm MCTest : MC<[10, 20]>;
// Test multiple inheritance: last parent class wins, then append applies.
// CHECK: def MultiInherit
// CHECK: list<int> items = [3, 4, 5];
// CHECK: string text = "b!";
def MultiInherit : BaseA, BaseB {
let append items = [5];
let append text = "!";
}
// CHECK: def MultiLevel
// CHECK: list<int> items = [1, 2, 3, 4];
// CHECK: string text = "hello world!";
def MultiLevel : Middle {
let append items = [4];
let append text = "!";
}
// CHECK: def OverrideAfterAppend
// CHECK: list<int> items = [10];
def OverrideAfterAppend : Base {
let append items = [3];
let items = [10];
}
// CHECK: def PrependDag
// CHECK: dag d = (op 0:$z);
def PrependDag : Base {
let prepend d = (op 0:$z);
}
// CHECK: def PrependList
// CHECK: list<int> items = [0, 1, 2];
def PrependList : Base {
let prepend items = [0];
}
// CHECK: def PrependString
// CHECK: string text = "say hello";
def PrependString : Base {
let prepend text = "say ";
}
// Test prepend on unset fields.
// CHECK: def PrependUnset
// CHECK: list<int> vals = [1];
// CHECK: string msg = "hi";
def PrependUnset : WithUnset {
let prepend vals = [1];
let prepend msg = "hi";
}