llvm/llvm/test/TableGen/generic-tables.td

// 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";
}