181ad6265SDimitry Andric //===- DXILEmitter.cpp - DXIL operation Emitter ---------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // DXILEmitter uses the descriptions of DXIL operation to construct enum and 1081ad6265SDimitry Andric // helper functions for DXIL operation. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #include "SequenceToOffsetTable.h" 1581ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 1681ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 1781ad6265SDimitry Andric #include "llvm/ADT/StringSet.h" 1881ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 19972a253aSDimitry Andric #include "llvm/Support/DXILOperationCommon.h" 2081ad6265SDimitry Andric #include "llvm/TableGen/Record.h" 21*06c3fb27SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 2281ad6265SDimitry Andric 2381ad6265SDimitry Andric using namespace llvm; 24bdd1243dSDimitry Andric using namespace llvm::dxil; 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric namespace { 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric struct DXILShaderModel { 29*06c3fb27SDimitry Andric int Major = 0; 30*06c3fb27SDimitry Andric int Minor = 0; 3181ad6265SDimitry Andric }; 32972a253aSDimitry Andric 3381ad6265SDimitry Andric struct DXILParam { 3481ad6265SDimitry Andric int Pos; // position in parameter list 35972a253aSDimitry Andric ParameterKind Kind; 3681ad6265SDimitry Andric StringRef Name; // short, unique name 3781ad6265SDimitry Andric StringRef Doc; // the documentation description of this parameter 3881ad6265SDimitry Andric bool IsConst; // whether this argument requires a constant value in the IR 3981ad6265SDimitry Andric StringRef EnumName; // the name of the enum type if applicable 4081ad6265SDimitry Andric int MaxValue; // the maximum value for this parameter if applicable 41972a253aSDimitry Andric DXILParam(const Record *R); 4281ad6265SDimitry Andric }; 4381ad6265SDimitry Andric 4481ad6265SDimitry Andric struct DXILOperationData { 4581ad6265SDimitry Andric StringRef Name; // short, unique name 4681ad6265SDimitry Andric 4781ad6265SDimitry Andric StringRef DXILOp; // name of DXIL operation 4881ad6265SDimitry Andric int DXILOpID; // ID of DXIL operation 4981ad6265SDimitry Andric StringRef DXILClass; // name of the opcode class 5081ad6265SDimitry Andric StringRef Category; // classification for this instruction 5181ad6265SDimitry Andric StringRef Doc; // the documentation description of this instruction 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric SmallVector<DXILParam> Params; // the operands that this instruction takes 5481ad6265SDimitry Andric StringRef OverloadTypes; // overload types if applicable 5581ad6265SDimitry Andric StringRef FnAttr; // attribute shorthands: rn=does not access 5681ad6265SDimitry Andric // memory,ro=only reads from memory 5781ad6265SDimitry Andric StringRef Intrinsic; // The llvm intrinsic map to DXILOp. Default is "" which 5881ad6265SDimitry Andric // means no map exist 59*06c3fb27SDimitry Andric bool IsDeriv = false; // whether this is some kind of derivative 60*06c3fb27SDimitry Andric bool IsGradient = false; // whether this requires a gradient calculation 61*06c3fb27SDimitry Andric bool IsFeedback = false; // whether this is a sampler feedback op 62*06c3fb27SDimitry Andric bool IsWave = false; // whether this requires in-wave, cross-lane functionality 63*06c3fb27SDimitry Andric bool RequiresUniformInputs = false; // whether this operation requires that 64*06c3fb27SDimitry Andric // all of its inputs are uniform across 65*06c3fb27SDimitry Andric // the wave 6681ad6265SDimitry Andric SmallVector<StringRef, 4> 6781ad6265SDimitry Andric ShaderStages; // shader stages to which this applies, empty for all. 6881ad6265SDimitry Andric DXILShaderModel ShaderModel; // minimum shader model required 6981ad6265SDimitry Andric DXILShaderModel ShaderModelTranslated; // minimum shader model required with 7081ad6265SDimitry Andric // translation by linker 71972a253aSDimitry Andric int OverloadParamIndex; // parameter index which control the overload. 72972a253aSDimitry Andric // When < 0, should be only 1 overload type. 7381ad6265SDimitry Andric SmallVector<StringRef, 4> counters; // counters for this inst. 7481ad6265SDimitry Andric DXILOperationData(const Record *R) { 7581ad6265SDimitry Andric Name = R->getValueAsString("name"); 7681ad6265SDimitry Andric DXILOp = R->getValueAsString("dxil_op"); 7781ad6265SDimitry Andric DXILOpID = R->getValueAsInt("dxil_opid"); 7881ad6265SDimitry Andric DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); 7981ad6265SDimitry Andric Category = R->getValueAsDef("category")->getValueAsString("name"); 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric if (R->getValue("llvm_intrinsic")) { 8281ad6265SDimitry Andric auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); 8381ad6265SDimitry Andric auto DefName = IntrinsicDef->getName(); 8481ad6265SDimitry Andric assert(DefName.startswith("int_") && "invalid intrinsic name"); 8581ad6265SDimitry Andric // Remove the int_ from intrinsic name. 8681ad6265SDimitry Andric Intrinsic = DefName.substr(4); 8781ad6265SDimitry Andric } 8881ad6265SDimitry Andric 8981ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 9081ad6265SDimitry Andric 9181ad6265SDimitry Andric ListInit *ParamList = R->getValueAsListInit("ops"); 92972a253aSDimitry Andric OverloadParamIndex = -1; 93972a253aSDimitry Andric for (unsigned I = 0; I < ParamList->size(); ++I) { 94972a253aSDimitry Andric Record *Param = ParamList->getElementAsRecord(I); 9581ad6265SDimitry Andric Params.emplace_back(DXILParam(Param)); 96972a253aSDimitry Andric auto &CurParam = Params.back(); 97972a253aSDimitry Andric if (CurParam.Kind >= ParameterKind::OVERLOAD) 98972a253aSDimitry Andric OverloadParamIndex = I; 9981ad6265SDimitry Andric } 10081ad6265SDimitry Andric OverloadTypes = R->getValueAsString("oload_types"); 10181ad6265SDimitry Andric FnAttr = R->getValueAsString("fn_attr"); 10281ad6265SDimitry Andric } 10381ad6265SDimitry Andric }; 10481ad6265SDimitry Andric } // end anonymous namespace 10581ad6265SDimitry Andric 106972a253aSDimitry Andric DXILParam::DXILParam(const Record *R) { 107972a253aSDimitry Andric Name = R->getValueAsString("name"); 108972a253aSDimitry Andric Pos = R->getValueAsInt("pos"); 109972a253aSDimitry Andric Kind = parameterTypeNameToKind(R->getValueAsString("llvm_type")); 110972a253aSDimitry Andric if (R->getValue("doc")) 111972a253aSDimitry Andric Doc = R->getValueAsString("doc"); 112972a253aSDimitry Andric IsConst = R->getValueAsBit("is_const"); 113972a253aSDimitry Andric EnumName = R->getValueAsString("enum_name"); 114972a253aSDimitry Andric MaxValue = R->getValueAsInt("max_value"); 115972a253aSDimitry Andric } 116972a253aSDimitry Andric 117972a253aSDimitry Andric static std::string parameterKindToString(ParameterKind Kind) { 118972a253aSDimitry Andric switch (Kind) { 119972a253aSDimitry Andric case ParameterKind::INVALID: 120972a253aSDimitry Andric return "INVALID"; 121972a253aSDimitry Andric case ParameterKind::VOID: 122972a253aSDimitry Andric return "VOID"; 123972a253aSDimitry Andric case ParameterKind::HALF: 124972a253aSDimitry Andric return "HALF"; 125972a253aSDimitry Andric case ParameterKind::FLOAT: 126972a253aSDimitry Andric return "FLOAT"; 127972a253aSDimitry Andric case ParameterKind::DOUBLE: 128972a253aSDimitry Andric return "DOUBLE"; 129972a253aSDimitry Andric case ParameterKind::I1: 130972a253aSDimitry Andric return "I1"; 131972a253aSDimitry Andric case ParameterKind::I8: 132972a253aSDimitry Andric return "I8"; 133972a253aSDimitry Andric case ParameterKind::I16: 134972a253aSDimitry Andric return "I16"; 135972a253aSDimitry Andric case ParameterKind::I32: 136972a253aSDimitry Andric return "I32"; 137972a253aSDimitry Andric case ParameterKind::I64: 138972a253aSDimitry Andric return "I64"; 139972a253aSDimitry Andric case ParameterKind::OVERLOAD: 140972a253aSDimitry Andric return "OVERLOAD"; 141972a253aSDimitry Andric case ParameterKind::CBUFFER_RET: 142972a253aSDimitry Andric return "CBUFFER_RET"; 143972a253aSDimitry Andric case ParameterKind::RESOURCE_RET: 144972a253aSDimitry Andric return "RESOURCE_RET"; 145972a253aSDimitry Andric case ParameterKind::DXIL_HANDLE: 146972a253aSDimitry Andric return "DXIL_HANDLE"; 147972a253aSDimitry Andric } 148bdd1243dSDimitry Andric llvm_unreachable("Unknown llvm::dxil::ParameterKind enum"); 149972a253aSDimitry Andric } 150972a253aSDimitry Andric 15181ad6265SDimitry Andric static void emitDXILOpEnum(DXILOperationData &DXILOp, raw_ostream &OS) { 15281ad6265SDimitry Andric // Name = ID, // Doc 15381ad6265SDimitry Andric OS << DXILOp.Name << " = " << DXILOp.DXILOpID << ", // " << DXILOp.Doc 15481ad6265SDimitry Andric << "\n"; 15581ad6265SDimitry Andric } 15681ad6265SDimitry Andric 15781ad6265SDimitry Andric static std::string buildCategoryStr(StringSet<> &Cetegorys) { 15881ad6265SDimitry Andric std::string Str; 15981ad6265SDimitry Andric raw_string_ostream OS(Str); 16081ad6265SDimitry Andric for (auto &It : Cetegorys) { 16181ad6265SDimitry Andric OS << " " << It.getKey(); 16281ad6265SDimitry Andric } 16381ad6265SDimitry Andric return OS.str(); 16481ad6265SDimitry Andric } 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric // Emit enum declaration for DXIL. 16781ad6265SDimitry Andric static void emitDXILEnums(std::vector<DXILOperationData> &DXILOps, 16881ad6265SDimitry Andric raw_ostream &OS) { 16981ad6265SDimitry Andric // Sort by Category + OpName. 170fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 17181ad6265SDimitry Andric // Group by Category first. 17281ad6265SDimitry Andric if (A.Category == B.Category) 17381ad6265SDimitry Andric // Inside same Category, order by OpName. 17481ad6265SDimitry Andric return A.DXILOp < B.DXILOp; 17581ad6265SDimitry Andric else 17681ad6265SDimitry Andric return A.Category < B.Category; 17781ad6265SDimitry Andric }); 17881ad6265SDimitry Andric 17981ad6265SDimitry Andric OS << "// Enumeration for operations specified by DXIL\n"; 18081ad6265SDimitry Andric OS << "enum class OpCode : unsigned {\n"; 18181ad6265SDimitry Andric 18281ad6265SDimitry Andric StringMap<StringSet<>> ClassMap; 18381ad6265SDimitry Andric StringRef PrevCategory = ""; 18481ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 18581ad6265SDimitry Andric StringRef Category = DXILOp.Category; 18681ad6265SDimitry Andric if (Category != PrevCategory) { 18781ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 18881ad6265SDimitry Andric PrevCategory = Category; 18981ad6265SDimitry Andric } 19081ad6265SDimitry Andric emitDXILOpEnum(DXILOp, OS); 19181ad6265SDimitry Andric auto It = ClassMap.find(DXILOp.DXILClass); 19281ad6265SDimitry Andric if (It != ClassMap.end()) { 19381ad6265SDimitry Andric It->second.insert(DXILOp.Category); 19481ad6265SDimitry Andric } else { 19581ad6265SDimitry Andric ClassMap[DXILOp.DXILClass].insert(DXILOp.Category); 19681ad6265SDimitry Andric } 19781ad6265SDimitry Andric } 19881ad6265SDimitry Andric 19981ad6265SDimitry Andric OS << "\n};\n\n"; 20081ad6265SDimitry Andric 20181ad6265SDimitry Andric std::vector<std::pair<std::string, std::string>> ClassVec; 20281ad6265SDimitry Andric for (auto &It : ClassMap) { 20381ad6265SDimitry Andric ClassVec.emplace_back( 20481ad6265SDimitry Andric std::make_pair(It.getKey().str(), buildCategoryStr(It.second))); 20581ad6265SDimitry Andric } 20681ad6265SDimitry Andric // Sort by Category + ClassName. 207fcaf7f86SDimitry Andric llvm::sort(ClassVec, [](std::pair<std::string, std::string> &A, 20881ad6265SDimitry Andric std::pair<std::string, std::string> &B) { 20981ad6265SDimitry Andric StringRef ClassA = A.first; 21081ad6265SDimitry Andric StringRef CategoryA = A.second; 21181ad6265SDimitry Andric StringRef ClassB = B.first; 21281ad6265SDimitry Andric StringRef CategoryB = B.second; 21381ad6265SDimitry Andric // Group by Category first. 21481ad6265SDimitry Andric if (CategoryA == CategoryB) 21581ad6265SDimitry Andric // Inside same Category, order by ClassName. 21681ad6265SDimitry Andric return ClassA < ClassB; 21781ad6265SDimitry Andric else 21881ad6265SDimitry Andric return CategoryA < CategoryB; 21981ad6265SDimitry Andric }); 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric OS << "// Groups for DXIL operations with equivalent function templates\n"; 22281ad6265SDimitry Andric OS << "enum class OpCodeClass : unsigned {\n"; 22381ad6265SDimitry Andric PrevCategory = ""; 22481ad6265SDimitry Andric for (auto &It : ClassVec) { 22581ad6265SDimitry Andric 22681ad6265SDimitry Andric StringRef Category = It.second; 22781ad6265SDimitry Andric if (Category != PrevCategory) { 22881ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 22981ad6265SDimitry Andric PrevCategory = Category; 23081ad6265SDimitry Andric } 23181ad6265SDimitry Andric StringRef Name = It.first; 23281ad6265SDimitry Andric OS << Name << ",\n"; 23381ad6265SDimitry Andric } 23481ad6265SDimitry Andric OS << "\n};\n\n"; 23581ad6265SDimitry Andric } 23681ad6265SDimitry Andric 23781ad6265SDimitry Andric // Emit map from llvm intrinsic to DXIL operation. 23881ad6265SDimitry Andric static void emitDXILIntrinsicMap(std::vector<DXILOperationData> &DXILOps, 23981ad6265SDimitry Andric raw_ostream &OS) { 24081ad6265SDimitry Andric OS << "\n"; 24181ad6265SDimitry Andric // FIXME: use array instead of SmallDenseMap. 242bdd1243dSDimitry Andric OS << "static const SmallDenseMap<Intrinsic::ID, dxil::OpCode> LowerMap = " 24381ad6265SDimitry Andric "{\n"; 24481ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 24581ad6265SDimitry Andric if (DXILOp.Intrinsic.empty()) 24681ad6265SDimitry Andric continue; 247bdd1243dSDimitry Andric // {Intrinsic::sin, dxil::OpCode::Sin}, 24881ad6265SDimitry Andric OS << " { Intrinsic::" << DXILOp.Intrinsic 249bdd1243dSDimitry Andric << ", dxil::OpCode::" << DXILOp.DXILOp << "},\n"; 25081ad6265SDimitry Andric } 25181ad6265SDimitry Andric OS << "};\n"; 25281ad6265SDimitry Andric OS << "\n"; 25381ad6265SDimitry Andric } 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric static std::string emitDXILOperationFnAttr(StringRef FnAttr) { 25681ad6265SDimitry Andric return StringSwitch<std::string>(FnAttr) 25781ad6265SDimitry Andric .Case("rn", "Attribute::ReadNone") 25881ad6265SDimitry Andric .Case("ro", "Attribute::ReadOnly") 25981ad6265SDimitry Andric .Default("Attribute::None"); 26081ad6265SDimitry Andric } 26181ad6265SDimitry Andric 26281ad6265SDimitry Andric static std::string getOverloadKind(StringRef Overload) { 26381ad6265SDimitry Andric return StringSwitch<std::string>(Overload) 26481ad6265SDimitry Andric .Case("half", "OverloadKind::HALF") 26581ad6265SDimitry Andric .Case("float", "OverloadKind::FLOAT") 26681ad6265SDimitry Andric .Case("double", "OverloadKind::DOUBLE") 26781ad6265SDimitry Andric .Case("i1", "OverloadKind::I1") 26881ad6265SDimitry Andric .Case("i16", "OverloadKind::I16") 26981ad6265SDimitry Andric .Case("i32", "OverloadKind::I32") 27081ad6265SDimitry Andric .Case("i64", "OverloadKind::I64") 27181ad6265SDimitry Andric .Case("udt", "OverloadKind::UserDefineType") 27281ad6265SDimitry Andric .Case("obj", "OverloadKind::ObjectType") 27381ad6265SDimitry Andric .Default("OverloadKind::VOID"); 27481ad6265SDimitry Andric } 27581ad6265SDimitry Andric 27681ad6265SDimitry Andric static std::string getDXILOperationOverload(StringRef Overloads) { 27781ad6265SDimitry Andric SmallVector<StringRef> OverloadStrs; 27881ad6265SDimitry Andric Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false); 27981ad6265SDimitry Andric // Format is: OverloadKind::FLOAT | OverloadKind::HALF 28081ad6265SDimitry Andric assert(!OverloadStrs.empty() && "Invalid overloads"); 28181ad6265SDimitry Andric auto It = OverloadStrs.begin(); 28281ad6265SDimitry Andric std::string Result; 28381ad6265SDimitry Andric raw_string_ostream OS(Result); 28481ad6265SDimitry Andric OS << getOverloadKind(*It); 28581ad6265SDimitry Andric for (++It; It != OverloadStrs.end(); ++It) { 28681ad6265SDimitry Andric OS << " | " << getOverloadKind(*It); 28781ad6265SDimitry Andric } 28881ad6265SDimitry Andric return OS.str(); 28981ad6265SDimitry Andric } 29081ad6265SDimitry Andric 29181ad6265SDimitry Andric static std::string lowerFirstLetter(StringRef Name) { 29281ad6265SDimitry Andric if (Name.empty()) 29381ad6265SDimitry Andric return ""; 29481ad6265SDimitry Andric 29581ad6265SDimitry Andric std::string LowerName = Name.str(); 29681ad6265SDimitry Andric LowerName[0] = llvm::toLower(Name[0]); 29781ad6265SDimitry Andric return LowerName; 29881ad6265SDimitry Andric } 29981ad6265SDimitry Andric 30081ad6265SDimitry Andric static std::string getDXILOpClassName(StringRef DXILOpClass) { 30181ad6265SDimitry Andric // Lower first letter expect for special case. 30281ad6265SDimitry Andric return StringSwitch<std::string>(DXILOpClass) 30381ad6265SDimitry Andric .Case("CBufferLoad", "cbufferLoad") 30481ad6265SDimitry Andric .Case("CBufferLoadLegacy", "cbufferLoadLegacy") 30581ad6265SDimitry Andric .Case("GSInstanceID", "gsInstanceID") 30681ad6265SDimitry Andric .Default(lowerFirstLetter(DXILOpClass)); 30781ad6265SDimitry Andric } 30881ad6265SDimitry Andric 30981ad6265SDimitry Andric static void emitDXILOperationTable(std::vector<DXILOperationData> &DXILOps, 31081ad6265SDimitry Andric raw_ostream &OS) { 31181ad6265SDimitry Andric // Sort by DXILOpID. 312fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 31381ad6265SDimitry Andric return A.DXILOpID < B.DXILOpID; 31481ad6265SDimitry Andric }); 31581ad6265SDimitry Andric 31681ad6265SDimitry Andric // Collect Names. 31781ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpClassStrings; 31881ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpStrings; 319972a253aSDimitry Andric SequenceToOffsetTable<SmallVector<ParameterKind>> Parameters; 32081ad6265SDimitry Andric 321972a253aSDimitry Andric StringMap<SmallVector<ParameterKind>> ParameterMap; 32281ad6265SDimitry Andric StringSet<> ClassSet; 32381ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 32481ad6265SDimitry Andric OpStrings.add(DXILOp.DXILOp.str()); 32581ad6265SDimitry Andric 326*06c3fb27SDimitry Andric if (ClassSet.contains(DXILOp.DXILClass)) 32781ad6265SDimitry Andric continue; 32881ad6265SDimitry Andric ClassSet.insert(DXILOp.DXILClass); 32981ad6265SDimitry Andric OpClassStrings.add(getDXILOpClassName(DXILOp.DXILClass)); 330972a253aSDimitry Andric SmallVector<ParameterKind> ParamKindVec; 331972a253aSDimitry Andric for (auto &Param : DXILOp.Params) { 332972a253aSDimitry Andric ParamKindVec.emplace_back(Param.Kind); 333972a253aSDimitry Andric } 334972a253aSDimitry Andric ParameterMap[DXILOp.DXILClass] = ParamKindVec; 335972a253aSDimitry Andric Parameters.add(ParamKindVec); 33681ad6265SDimitry Andric } 33781ad6265SDimitry Andric 33881ad6265SDimitry Andric // Layout names. 33981ad6265SDimitry Andric OpStrings.layout(); 34081ad6265SDimitry Andric OpClassStrings.layout(); 341972a253aSDimitry Andric Parameters.layout(); 34281ad6265SDimitry Andric 34381ad6265SDimitry Andric // Emit the DXIL operation table. 344bdd1243dSDimitry Andric //{dxil::OpCode::Sin, OpCodeNameIndex, OpCodeClass::Unary, 34581ad6265SDimitry Andric // OpCodeClassNameIndex, 346972a253aSDimitry Andric // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone, 0, 347972a253aSDimitry Andric // 3, ParameterTableOffset}, 348bdd1243dSDimitry Andric OS << "static const OpCodeProperty *getOpCodeProperty(dxil::OpCode DXILOp) " 34981ad6265SDimitry Andric "{\n"; 35081ad6265SDimitry Andric 35181ad6265SDimitry Andric OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 35281ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 353bdd1243dSDimitry Andric OS << " { dxil::OpCode::" << DXILOp.DXILOp << ", " 35481ad6265SDimitry Andric << OpStrings.get(DXILOp.DXILOp.str()) 35581ad6265SDimitry Andric << ", OpCodeClass::" << DXILOp.DXILClass << ", " 35681ad6265SDimitry Andric << OpClassStrings.get(getDXILOpClassName(DXILOp.DXILClass)) << ", " 35781ad6265SDimitry Andric << getDXILOperationOverload(DXILOp.OverloadTypes) << ", " 358972a253aSDimitry Andric << emitDXILOperationFnAttr(DXILOp.FnAttr) << ", " 359972a253aSDimitry Andric << DXILOp.OverloadParamIndex << ", " << DXILOp.Params.size() << ", " 360972a253aSDimitry Andric << Parameters.get(ParameterMap[DXILOp.DXILClass]) << " },\n"; 36181ad6265SDimitry Andric } 36281ad6265SDimitry Andric OS << " };\n"; 36381ad6265SDimitry Andric 36481ad6265SDimitry Andric OS << " // FIXME: change search to indexing with\n"; 36581ad6265SDimitry Andric OS << " // DXILOp once all DXIL op is added.\n"; 36681ad6265SDimitry Andric OS << " OpCodeProperty TmpProp;\n"; 36781ad6265SDimitry Andric OS << " TmpProp.OpCode = DXILOp;\n"; 36881ad6265SDimitry Andric OS << " const OpCodeProperty *Prop =\n"; 36981ad6265SDimitry Andric OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 37081ad6265SDimitry Andric OS << " [](const OpCodeProperty &A, const " 37181ad6265SDimitry Andric "OpCodeProperty &B) {\n"; 37281ad6265SDimitry Andric OS << " return A.OpCode < B.OpCode;\n"; 37381ad6265SDimitry Andric OS << " });\n"; 37481ad6265SDimitry Andric OS << " assert(Prop && \"fail to find OpCodeProperty\");\n"; 37581ad6265SDimitry Andric OS << " return Prop;\n"; 37681ad6265SDimitry Andric OS << "}\n\n"; 37781ad6265SDimitry Andric 37881ad6265SDimitry Andric // Emit the string tables. 379bdd1243dSDimitry Andric OS << "static const char *getOpCodeName(dxil::OpCode DXILOp) {\n\n"; 38081ad6265SDimitry Andric 38181ad6265SDimitry Andric OpStrings.emitStringLiteralDef(OS, 38281ad6265SDimitry Andric " static const char DXILOpCodeNameTable[]"); 38381ad6265SDimitry Andric 38481ad6265SDimitry Andric OS << " auto *Prop = getOpCodeProperty(DXILOp);\n"; 38581ad6265SDimitry Andric OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 38681ad6265SDimitry Andric OS << " return DXILOpCodeNameTable + Index;\n"; 38781ad6265SDimitry Andric OS << "}\n\n"; 38881ad6265SDimitry Andric 38981ad6265SDimitry Andric OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 39081ad6265SDimitry Andric "{\n\n"; 39181ad6265SDimitry Andric 39281ad6265SDimitry Andric OpClassStrings.emitStringLiteralDef( 39381ad6265SDimitry Andric OS, " static const char DXILOpCodeClassNameTable[]"); 39481ad6265SDimitry Andric 39581ad6265SDimitry Andric OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 39681ad6265SDimitry Andric OS << " return DXILOpCodeClassNameTable + Index;\n"; 39781ad6265SDimitry Andric OS << "}\n "; 398972a253aSDimitry Andric 399972a253aSDimitry Andric OS << "static const ParameterKind *getOpCodeParameterKind(const " 400972a253aSDimitry Andric "OpCodeProperty &Prop) " 401972a253aSDimitry Andric "{\n\n"; 402972a253aSDimitry Andric OS << " static const ParameterKind DXILOpParameterKindTable[] = {\n"; 403972a253aSDimitry Andric Parameters.emit( 404972a253aSDimitry Andric OS, 405972a253aSDimitry Andric [](raw_ostream &ParamOS, ParameterKind Kind) { 406972a253aSDimitry Andric ParamOS << "ParameterKind::" << parameterKindToString(Kind); 407972a253aSDimitry Andric }, 408972a253aSDimitry Andric "ParameterKind::INVALID"); 409972a253aSDimitry Andric OS << " };\n\n"; 410972a253aSDimitry Andric OS << " unsigned Index = Prop.ParameterTableOffset;\n"; 411972a253aSDimitry Andric OS << " return DXILOpParameterKindTable + Index;\n"; 412972a253aSDimitry Andric OS << "}\n "; 41381ad6265SDimitry Andric } 41481ad6265SDimitry Andric 415*06c3fb27SDimitry Andric static void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { 41681ad6265SDimitry Andric std::vector<Record *> Ops = Records.getAllDerivedDefinitions("dxil_op"); 41781ad6265SDimitry Andric OS << "// Generated code, do not edit.\n"; 41881ad6265SDimitry Andric OS << "\n"; 41981ad6265SDimitry Andric 42081ad6265SDimitry Andric std::vector<DXILOperationData> DXILOps; 42181ad6265SDimitry Andric DXILOps.reserve(Ops.size()); 42281ad6265SDimitry Andric for (auto *Record : Ops) { 42381ad6265SDimitry Andric DXILOps.emplace_back(DXILOperationData(Record)); 42481ad6265SDimitry Andric } 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric OS << "#ifdef DXIL_OP_ENUM\n"; 42781ad6265SDimitry Andric emitDXILEnums(DXILOps, OS); 42881ad6265SDimitry Andric OS << "#endif\n\n"; 42981ad6265SDimitry Andric 43081ad6265SDimitry Andric OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; 43181ad6265SDimitry Andric emitDXILIntrinsicMap(DXILOps, OS); 43281ad6265SDimitry Andric OS << "#endif\n\n"; 43381ad6265SDimitry Andric 43481ad6265SDimitry Andric OS << "#ifdef DXIL_OP_OPERATION_TABLE\n"; 43581ad6265SDimitry Andric emitDXILOperationTable(DXILOps, OS); 43681ad6265SDimitry Andric OS << "#endif\n\n"; 43781ad6265SDimitry Andric 43881ad6265SDimitry Andric OS << "\n"; 43981ad6265SDimitry Andric } 44081ad6265SDimitry Andric 441*06c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-dxil-operation", EmitDXILOperation, 442*06c3fb27SDimitry Andric "Generate DXIL operation information"); 443