|  | // RUN: llvm-tblgen -gen-searchable-tables -I %p/../../include %s | FileCheck %s | 
|  | // XFAIL: vg_leak | 
|  |  | 
|  | include "llvm/TableGen/SearchableTable.td" | 
|  | include "llvm/Target/Target.td" | 
|  |  | 
|  | def ArchInstrInfo : InstrInfo { } | 
|  | def Arch : Target { let InstructionSet = ArchInstrInfo; } | 
|  |  | 
|  | // CHECK-LABEL: GET_InstrTable_IMPL | 
|  | // CHECK: constexpr MyInstr InstrTable[] = { | 
|  | // CHECK:   { B, 0xA }, | 
|  | // CHECK:   { C, 0x0 }, | 
|  | // CHECK:   { A, 0x5 }, | 
|  | // CHECK:   { D, 0x8 }, | 
|  | // CHECK: }; | 
|  |  | 
|  | // A contiguous primary (Instruction) key should get a direct lookup instead of | 
|  | // binary search. | 
|  | // CHECK: const MyInstr *getCustomEncodingHelper(unsigned Opcode) { | 
|  | // CHECK: if ((unsigned)Opcode != std::clamp((unsigned)Opcode, (unsigned)B, (unsigned)D)) | 
|  | // CHECK:   return nullptr; | 
|  | // CHECK:   auto Table = ArrayRef(InstrTable); | 
|  | // CHECK:   size_t Idx = Opcode - B; | 
|  | // CHECK:   return &Table[Idx]; | 
|  |  | 
|  | class MyInstr<int op> : Instruction { | 
|  | let OutOperandList = (outs); | 
|  | let InOperandList = (ins); | 
|  | Instruction Opcode = !cast<Instruction>(NAME); | 
|  | bits<16> CustomEncoding = op; | 
|  | } | 
|  |  | 
|  | def A : MyInstr<5>; | 
|  | def D : MyInstr<8>; | 
|  | let isPseudo = 1 in { | 
|  | def C : MyInstr<0>; | 
|  | def B : MyInstr<10>; | 
|  | } | 
|  |  | 
|  | def InstrTable : GenericTable { | 
|  | let FilterClass = "MyInstr"; | 
|  | let Fields = ["Opcode", "CustomEncoding"]; | 
|  |  | 
|  | let PrimaryKey = ["Opcode"]; | 
|  | let PrimaryKeyName = "getCustomEncodingHelper"; | 
|  | } | 
|  |  | 
|  |  | 
|  | // Non-contiguous instructions should get a binary search instead of direct | 
|  | // lookup. | 
|  | // CHECK: const MyInfoEntry *getTable2ByOpcode(unsigned Opcode) { | 
|  | // CHECK:   auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, | 
|  | // | 
|  | // Verify contiguous check for SearchIndex. | 
|  | // const MyInfoEntry *getTable2ByValue(uint8_t Value) { | 
|  | // CHECK:   if ((uint8_t)Value != std::clamp((uint8_t)Value, (uint8_t)0xB, (uint8_t)0xD)) | 
|  | // CHECK:    return nullptr; | 
|  | // CHECK:  auto Table = ArrayRef(Index); | 
|  | // CHECK:  size_t Idx = Value - 0xB; | 
|  | // CHECK:  return &InstrTable2[Table[Idx]._index]; | 
|  |  | 
|  |  | 
|  | class MyInfoEntry<int V, string S> { | 
|  | Instruction Opcode = !cast<Instruction>(NAME); | 
|  | bits<4> Value = V; | 
|  | string Name = S; | 
|  | } | 
|  |  | 
|  | let OutOperandList = (outs), InOperandList = (ins) in { | 
|  | def W : Instruction, MyInfoEntry<12, "IW">; | 
|  | def X : Instruction; | 
|  | def Y : Instruction, MyInfoEntry<13, "IY">; | 
|  | def Z : Instruction, MyInfoEntry<11, "IZ">; | 
|  | } | 
|  |  | 
|  | def InstrTable2 : GenericTable { | 
|  | let FilterClass = "MyInfoEntry"; | 
|  | let Fields = ["Opcode", "Value", "Name"]; | 
|  |  | 
|  | let PrimaryKey = ["Opcode"]; | 
|  | let PrimaryKeyName = "getTable2ByOpcode"; | 
|  | } | 
|  |  | 
|  | def getTable2ByValue : SearchIndex { | 
|  | let Table = InstrTable2; | 
|  | let Key = ["Value"]; | 
|  | } |