| // RUN: llvm-tblgen -gen-searchable-tables -I %p/../../include %s | FileCheck %s |
| // RUN: not llvm-tblgen -gen-searchable-tables -I %p/../../include -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s |
| // XFAIL: vg_leak |
| |
| include "llvm/TableGen/SearchableTable.td" |
| |
| // CHECK-LABEL: GET_BValues_DECL |
| // CHECK: enum BValues { |
| // CHECK: BAlice = 172, |
| // CHECK: BBob = 20, |
| // CHECK: BCharlie = 128, |
| // CHECK: BEve = 76, |
| // CHECK: } |
| |
| // CHECK-LABEL: GET_CEnum_DECL |
| // CHECK: enum CEnum { |
| // CHECK: CBar |
| // CHECK: CBaz |
| // CHECK: CFoo |
| // CHECK: } |
| |
| // CHECK-LABEL: GET_ATable_DECL |
| // CHECK: const AEntry *lookupATableByValues(uint8_t Val1, uint16_t Val2); |
| |
| // CHECK-LABEL: GET_ATable_IMPL |
| // CHECK: constexpr AEntry ATable[] = { |
| // CHECK-NOT: { "aaa" |
| // CHECK: { "baz", 0x2, 0x6, 0xFFFFFFFF00000000 }, |
| // CHECK: { "foo", 0x4, 0x4, 0x100000000 }, |
| // CHECK: { "foobar", 0x4, 0x5, 0x100000000 }, |
| // CHECK: { "bar", 0x5, 0x3, 0x100000000 }, |
| // CHECK: }; |
| |
| // CHECK: const AEntry *lookupATableByValues(uint8_t Val1, uint16_t Val2) { |
| // CHECK: return &*Idx; |
| // CHECK: } |
| |
| class AEntry<string str, int val1, int val2, bits<64> val3> { |
| string Str = str; |
| bits<8> Val1 = val1; |
| bits<10> Val2 = val2; |
| bits<64> Val3 = val3; |
| bit IsNeeded = 1; |
| } |
| |
| def : AEntry<"aaa", 0, 0, 0> { let IsNeeded = 0; } |
| def : AEntry<"bar", 5, 3, 0x100000000>; |
| def : AEntry<"baz", 2, 6, 0xFFFFFFFF00000000>; |
| def : AEntry<"foo", 4, 4, 0b0000000000000000000000000000000100000000000000000000000000000000>; |
| def : AEntry<"foobar", 4, 5, 4294967296>; |
| |
| def ATable : GenericTable { |
| let FilterClass = "AEntry"; |
| let FilterClassField = "IsNeeded"; |
| let Fields = ["Str", "Val1", "Val2", "Val3"]; |
| |
| let PrimaryKey = ["Val1", "Val2"]; |
| let PrimaryKeyName = "lookupATableByValues"; |
| } |
| |
| |
| // CHECK-LABEL: GET_BTable_IMPL |
| // CHECK: constexpr BTypeName BTable[] = { |
| // CHECK: { "BAlice", 0xAC, false, }, |
| // CHECK: { "BBob", 0x14, false, Bob == 13 }, |
| // CHECK: { "BCharlie", 0x80, true, Charlie == 42 }, |
| // CHECK: { "BEve", 0x4C, true, Eve == 108 }, |
| // CHECK: }; |
| // CHECK: const BTypeName *lookupBTableByName(StringRef Name) { |
| // CHECK: return &BTable[Idx->_index]; |
| // CHECK: } |
| // CHECK: const BTypeName *lookupBTableByNameAndFlag(StringRef Name, bool Flag) { |
| // CHECK: return &BTable[Idx->_index]; |
| // CHECK: } |
| |
| class BEntry<bits<16> enc, bit flag = 0, code test = [{}]> { |
| string Name = NAME; |
| bits<16> Encoding = enc; |
| bit Flag = flag; |
| code Test = test; |
| } |
| |
| def BAlice : BEntry<0xac>; |
| def BBob : BEntry<0x14, 0, [{Bob == 13}]>; |
| def BCharlie : BEntry<0x80, 1, "Charlie == 42">; |
| def BEve : BEntry<0x4c, 1, [{Eve == }] # 108>; |
| |
| def BValues : GenericEnum { |
| let FilterClass = "BEntry"; |
| let NameField = "Name"; |
| let ValueField = "Encoding"; |
| } |
| |
| def BTable : GenericTable { |
| let FilterClass = "BEntry"; |
| string CppTypeName = "BTypeName"; |
| let Fields = ["Name", "Encoding", "Flag", "Test"]; |
| string TypeOf_Test = "code"; |
| } |
| |
| def lookupBTableByName : SearchIndex { |
| let Table = BTable; |
| let Key = ["Name"]; |
| } |
| |
| def lookupBTableByNameAndFlag : SearchIndex { |
| let Table = BTable; |
| let Key = ["Name", "Flag"]; |
| } |
| |
| // CHECK-LABEL: GET_CTable_DECL |
| // CHECK: const CEntry *lookupCEntryByEncoding(uint16_t Encoding); |
| // CHECK: const CEntry *lookupCEntry(StringRef Name, unsigned Kind); |
| // CHECK-LABEL: GET_CTable_IMPL |
| // CHECK: const CEntry *lookupCEntryByEncoding(uint16_t Encoding) { |
| // CHECK: if ((Encoding < 0xA) || |
| // CHECK: (Encoding > 0xF)) |
| // CHECK: return nullptr; |
| |
| // CHECK: const CEntry *lookupCEntry(StringRef Name, unsigned Kind) { |
| // CHECK: Index[] = { |
| // CHECK: { "ALICE", CBar, 1 }, |
| // CHECK: { "ALICE", CFoo, 0 }, |
| // CHECK: { "BOB", CBaz, 2 }, |
| |
| class CEnum; |
| |
| def CFoo : CEnum; |
| def CBar : CEnum; |
| def CBaz : CEnum; |
| |
| def CEnum : GenericEnum { |
| let FilterClass = "CEnum"; |
| } |
| |
| class CEntry<string name, CEnum kind, int enc> { |
| string Name = name; |
| CEnum Kind = kind; |
| bits<16> Encoding = enc; |
| } |
| |
| def : CEntry<"alice", CFoo, 10>; |
| def : CEntry<"alice", CBar, 13>; |
| def : CEntry<"bob", CBaz, 15>; |
| |
| def CTable : GenericTable { |
| let FilterClass = "CEntry"; |
| let Fields = ["Name", "Kind", "Encoding"]; |
| |
| string TypeOf_Kind = "CEnum"; |
| |
| let PrimaryKey = ["Encoding"]; |
| let PrimaryKeyName = "lookupCEntryByEncoding"; |
| let PrimaryKeyEarlyOut = 1; |
| } |
| |
| def lookupCEntry : SearchIndex { |
| let Table = CTable; |
| let Key = ["Name", "Kind"]; |
| } |
| |
| #ifdef ERROR1 |
| |
| class DEntry<string str, int val1> { |
| string Str = str; |
| bits<8> Val1 = val1; |
| } |
| |
| def DFoo : DEntry<"foo", 1>; |
| // ERROR1: [[@LINE+1]]:5: error: Record 'DBar' for table 'DTable' is missing field 'Val1' |
| def DBar : DEntry<"bar", ?>; |
| |
| def DTable : GenericTable { |
| let FilterClass = "DEntry"; |
| let Fields = ["Str", "Val1"]; |
| } |
| |
| #endif // ERROR1 |
| |
| // CHECK-LABEL: GET_EEntryEvenTable_DECL |
| // CHECK: const EEntry *lookupEEntryEvenTableByValue(uint8_t Value); |
| |
| // CHECK-LABEL: GET_EEntryEvenTable_IMPL |
| // CHECK: constexpr EEntry EEntryEvenTable[] = { |
| // CHECK: { 0x2 |
| // CHECK: { 0x4 |
| // CHECK: { 0x6 |
| // CHECK: { 0x8 |
| // CHECK: { 0xA |
| // CHECK: }; |
| |
| // CHECK: const EEntry *lookupEEntryEvenTableByValue(uint8_t Value) { |
| // CHECK: return &*Idx; |
| // CHECK: } |
| |
| // CHECK-LABEL: GET_EEntryOddTable_DECL |
| // CHECK: const EEntry *lookupEEntryOddTableByValue(uint8_t Value); |
| |
| // CHECK-LABEL: GET_EEntryOddTable_IMPL |
| // CHECK: constexpr EEntry EEntryOddTable[] = { |
| // CHECK: { 0x1 |
| // CHECK: { 0x3 |
| // CHECK: { 0x5 |
| // CHECK: { 0x7 |
| // CHECK: { 0x9 |
| // CHECK: }; |
| |
| // CHECK: const EEntry *lookupEEntryOddTableByValue(uint8_t Value) { |
| // CHECK: return &*Idx; |
| // CHECK: } |
| |
| // We can construct two GenericTables with the same FilterClass, so that they |
| // select from the same overall set of records, but assign them with different |
| // FilterClassField values so that they include different subsets of the records |
| // of that class. |
| class EEntry<bits<8> value> { |
| bits<8> Value = value; |
| bit IsEven = !eq(!and(value, 1), 0); |
| bit IsOdd = !not(IsEven); |
| } |
| |
| foreach i = {1-10} in { |
| def : EEntry<i>; |
| } |
| |
| def EEntryEvenTable : GenericTable { |
| let FilterClass = "EEntry"; |
| let FilterClassField = "IsEven"; |
| let Fields = ["Value"]; |
| let PrimaryKey = ["Value"]; |
| let PrimaryKeyName = "lookupEEntryEvenTableByValue"; |
| } |
| |
| def EEntryOddTable : GenericTable { |
| let FilterClass = "EEntry"; |
| let FilterClassField = "IsOdd"; |
| let Fields = ["Value"]; |
| let PrimaryKey = ["Value"]; |
| let PrimaryKeyName = "lookupEEntryOddTableByValue"; |
| } |