Index: test/TableGen/searchabletables-intrinsic.td =================================================================== --- /dev/null +++ test/TableGen/searchabletables-intrinsic.td @@ -0,0 +1,85 @@ +// RUN: llvm-tblgen -gen-searchable-tables -I %p/../../include %s | FileCheck %s +// XFAIL: vg_leak + +include "llvm/TableGen/SearchableTable.td" + +class IntrinsicProperty; +class SDNodeProperty; + +class ValueType { + string Namespace = "MVT"; + int Size = size; + int Value = value; +} + +class LLVMType { + ValueType VT = vt; +} + +class Intrinsic param_types = []> { + string LLVMName = ""; + bit isTarget = 0; + string TargetPrefix = ""; + list RetTypes = []; + list ParamTypes = param_types; + list IntrProperties = []; + list Properties = []; +} + +def iAny : ValueType<0, 253>; +def llvm_anyint_ty : LLVMType; + +def int_abc : Intrinsic<[llvm_anyint_ty]>; +def int_xyz : Intrinsic<[llvm_anyint_ty]>; + +let isTarget = 1, TargetPrefix = "gtarget" in { + def int_gtarget_def : Intrinsic<[llvm_anyint_ty]>; + def int_gtarget_defg : Intrinsic<[llvm_anyint_ty]>; + def int_gtarget_uvw : Intrinsic<[llvm_anyint_ty]>; +} + +let isTarget = 1, TargetPrefix = "ftarget" in { + def int_ftarget_ghi : Intrinsic<[llvm_anyint_ty]>; + def int_ftarget_ghi_x : Intrinsic<[llvm_anyint_ty]>; + def int_ftarget_rst : Intrinsic<[llvm_anyint_ty]>; +} + +class Table : SearchableTable { + let SearchableFields = ["Intr"]; + let EnumNameField = ?; + + Intrinsic Intr = !cast(intr); + bits<16> Payload = payload; +} + +// CHECK-LABEL: TablesList[] = { +// CHECK-DAG: { Intrinsic::abc, 0x0}, +// CHECK-DAG: { Intrinsic::xyz, 0x1}, +// CHECK-DAG: { Intrinsic::gtarget_def, 0x10}, +// CHECK-DAG: { Intrinsic::gtarget_defg, 0x11}, +// CHECK-DAG: { Intrinsic::gtarget_uvw, 0x12}, +// CHECK-DAG: { Intrinsic::ftarget_ghi, 0x20}, +// CHECK-DAG: { Intrinsic::ftarget_ghi_x, 0x21}, +// CHECK-DAG: { Intrinsic::ftarget_rst, 0x22}, + +// Check that the index is in the correct order, consistent with the ordering +// of enums: alphabetically, but target intrinsics after generic intrinsics +// +// CHECK-LABEL: TablesByIntr[] = { +// CHECK-NEXT: Intrinsic::abc +// CHECK-NEXT: Intrinsic::xyz +// CHECK-NEXT: Intrinsic::ftarget_ghi +// CHECK-NEXT: Intrinsic::ftarget_ghi_x +// CHECK-NEXT: Intrinsic::ftarget_rst +// CHECK-NEXT: Intrinsic::gtarget_def +// CHECK-NEXT: Intrinsic::gtarget_defg +// CHECK-NEXT: Intrinsic::gtarget_uvw + +def : Table; +def : Table; +def : Table; +def : Table; +def : Table; +def : Table; +def : Table; +def : Table; Index: utils/TableGen/SearchableTableEmitter.cpp =================================================================== --- utils/TableGen/SearchableTableEmitter.cpp +++ utils/TableGen/SearchableTableEmitter.cpp @@ -13,12 +13,14 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include "CodeGenIntrinsics.h" #include #include #include @@ -30,6 +32,7 @@ class SearchableTableEmitter { RecordKeeper &Records; + DenseMap> Intrinsics; public: SearchableTableEmitter(RecordKeeper &R) : Records(R) {} @@ -53,8 +56,11 @@ return "0x" + utohexstr(getAsInt(BI)); else if (BitInit *BI = dyn_cast(I)) return BI->getValue() ? "true" : "false"; - else if (CodeInit *CI = dyn_cast(I)) { + else if (CodeInit *CI = dyn_cast(I)) return CI->getValue(); + else if (DefInit *DI = dyn_cast(I)) { + if (DI->getDef()->isSubClassOf("Intrinsic")) + return "Intrinsic::" + getIntrinsic(I).EnumName; } PrintFatalError(SMLoc(), "invalid field type, expected: string, bits, bit or code"); @@ -67,6 +73,23 @@ return StringRef(PrimaryRep).upper(); } + bool isIntrinsic(Init *I) { + if (DefInit *DI = dyn_cast(I)) + return DI->getDef()->isSubClassOf("Intrinsic"); + return false; + } + + CodeGenIntrinsic &getIntrinsic(Init *I) { + std::unique_ptr &Intr = Intrinsics[I]; + if (!Intr) + Intr = make_unique(cast(I)->getDef()); + return *Intr; + } + + bool isIntegral(Init *I) { + return isa(I) || isIntrinsic(I); + } + std::string searchableFieldType(Init *I) { if (isa(I)) return "const char *"; @@ -83,7 +106,8 @@ else PrintFatalError(SMLoc(), "bitfield too large to search"); return "uint" + utostr(NumBits) + "_t"; - } + } else if (isIntrinsic(I)) + return "unsigned"; PrintFatalError(SMLoc(), "Unknown type to search by"); } @@ -158,6 +182,15 @@ return getAsInt(cast(LHS.first)) < getAsInt(cast(RHS.first)); }); + } else if (isIntrinsic(SearchTable[0].first)) { + std::stable_sort(SearchTable.begin(), SearchTable.end(), + [this](const SearchTableEntry &LHS, + const SearchTableEntry &RHS) { + CodeGenIntrinsic &LHSi = getIntrinsic(LHS.first); + CodeGenIntrinsic &RHSi = getIntrinsic(RHS.first); + return std::tie(LHSi.TargetPrefix, LHSi.Name) < + std::tie(RHSi.TargetPrefix, RHSi.Name); + }); } else { std::stable_sort(SearchTable.begin(), SearchTable.end(), [this](const SearchTableEntry &LHS, @@ -176,7 +209,7 @@ void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field, Init *I, raw_ostream &OS) { - bool IsIntegral = isa(I); + bool IsIntegral = isIntegral(I); std::string FieldType = searchableFieldType(I); std::string PairType = "std::pair<" + FieldType + ", int>"; @@ -219,7 +252,7 @@ void SearchableTableEmitter::emitLookupDeclaration(StringRef Name, StringRef Field, Init *I, raw_ostream &OS) { - bool IsIntegral = isa(I); + bool IsIntegral = isIntegral(I); std::string FieldType = searchableFieldType(I); OS << "const " << Name << " *" << "lookup" << Name << "By" << Field;