1435897b4Spython3kgae //===- DXILEmitter.cpp - DXIL operation Emitter ---------------------------===// 2435897b4Spython3kgae // 3435897b4Spython3kgae // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4435897b4Spython3kgae // See https://llvm.org/LICENSE.txt for license information. 5435897b4Spython3kgae // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6435897b4Spython3kgae // 7435897b4Spython3kgae //===----------------------------------------------------------------------===// 8435897b4Spython3kgae // 9435897b4Spython3kgae // DXILEmitter uses the descriptions of DXIL operation to construct enum and 10435897b4Spython3kgae // helper functions for DXIL operation. 11435897b4Spython3kgae // 12435897b4Spython3kgae //===----------------------------------------------------------------------===// 13435897b4Spython3kgae 140d2dde20SXiang Li #include "SequenceToOffsetTable.h" 15435897b4Spython3kgae #include "llvm/ADT/STLExtras.h" 16435897b4Spython3kgae #include "llvm/ADT/SmallVector.h" 17435897b4Spython3kgae #include "llvm/ADT/StringSet.h" 180d2dde20SXiang Li #include "llvm/ADT/StringSwitch.h" 19*57006b14SXiang Li #include "llvm/Support/DXILOperationCommon.h" 20435897b4Spython3kgae #include "llvm/TableGen/Error.h" 21435897b4Spython3kgae #include "llvm/TableGen/Record.h" 22435897b4Spython3kgae 23435897b4Spython3kgae using namespace llvm; 24*57006b14SXiang Li using namespace llvm::DXIL; 25435897b4Spython3kgae 26435897b4Spython3kgae namespace { 27435897b4Spython3kgae 28435897b4Spython3kgae struct DXILShaderModel { 29435897b4Spython3kgae int Major; 30435897b4Spython3kgae int Minor; 31435897b4Spython3kgae }; 32*57006b14SXiang Li 33435897b4Spython3kgae struct DXILParam { 34435897b4Spython3kgae int Pos; // position in parameter list 35*57006b14SXiang Li ParameterKind Kind; 36435897b4Spython3kgae StringRef Name; // short, unique name 37435897b4Spython3kgae StringRef Doc; // the documentation description of this parameter 38435897b4Spython3kgae bool IsConst; // whether this argument requires a constant value in the IR 39435897b4Spython3kgae StringRef EnumName; // the name of the enum type if applicable 40435897b4Spython3kgae int MaxValue; // the maximum value for this parameter if applicable 41*57006b14SXiang Li DXILParam(const Record *R); 42435897b4Spython3kgae }; 43435897b4Spython3kgae 44435897b4Spython3kgae struct DXILOperationData { 45435897b4Spython3kgae StringRef Name; // short, unique name 46435897b4Spython3kgae 47435897b4Spython3kgae StringRef DXILOp; // name of DXIL operation 48435897b4Spython3kgae int DXILOpID; // ID of DXIL operation 49435897b4Spython3kgae StringRef DXILClass; // name of the opcode class 50435897b4Spython3kgae StringRef Category; // classification for this instruction 51435897b4Spython3kgae StringRef Doc; // the documentation description of this instruction 52435897b4Spython3kgae 53435897b4Spython3kgae SmallVector<DXILParam> Params; // the operands that this instruction takes 54435897b4Spython3kgae StringRef OverloadTypes; // overload types if applicable 55435897b4Spython3kgae StringRef FnAttr; // attribute shorthands: rn=does not access 56264c09b7SXiang Li // memory,ro=only reads from memory 57264c09b7SXiang Li StringRef Intrinsic; // The llvm intrinsic map to DXILOp. Default is "" which 58264c09b7SXiang Li // means no map exist 59435897b4Spython3kgae bool IsDeriv; // whether this is some kind of derivative 60435897b4Spython3kgae bool IsGradient; // whether this requires a gradient calculation 61435897b4Spython3kgae bool IsFeedback; // whether this is a sampler feedback op 62435897b4Spython3kgae bool IsWave; // whether this requires in-wave, cross-lane functionality 63435897b4Spython3kgae bool RequiresUniformInputs; // whether this operation requires that all 64435897b4Spython3kgae // of its inputs are uniform across the wave 65435897b4Spython3kgae SmallVector<StringRef, 4> 66435897b4Spython3kgae ShaderStages; // shader stages to which this applies, empty for all. 67435897b4Spython3kgae DXILShaderModel ShaderModel; // minimum shader model required 68435897b4Spython3kgae DXILShaderModel ShaderModelTranslated; // minimum shader model required with 69435897b4Spython3kgae // translation by linker 70*57006b14SXiang Li int OverloadParamIndex; // parameter index which control the overload. 71*57006b14SXiang Li // When < 0, should be only 1 overload type. 72435897b4Spython3kgae SmallVector<StringRef, 4> counters; // counters for this inst. 73435897b4Spython3kgae DXILOperationData(const Record *R) { 74435897b4Spython3kgae Name = R->getValueAsString("name"); 75435897b4Spython3kgae DXILOp = R->getValueAsString("dxil_op"); 76435897b4Spython3kgae DXILOpID = R->getValueAsInt("dxil_opid"); 77435897b4Spython3kgae DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); 78435897b4Spython3kgae Category = R->getValueAsDef("category")->getValueAsString("name"); 79435897b4Spython3kgae 80264c09b7SXiang Li if (R->getValue("llvm_intrinsic")) { 81264c09b7SXiang Li auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); 82264c09b7SXiang Li auto DefName = IntrinsicDef->getName(); 83264c09b7SXiang Li assert(DefName.startswith("int_") && "invalid intrinsic name"); 84264c09b7SXiang Li // Remove the int_ from intrinsic name. 85264c09b7SXiang Li Intrinsic = DefName.substr(4); 86264c09b7SXiang Li } 87264c09b7SXiang Li 88435897b4Spython3kgae Doc = R->getValueAsString("doc"); 89264c09b7SXiang Li 90435897b4Spython3kgae ListInit *ParamList = R->getValueAsListInit("ops"); 91*57006b14SXiang Li OverloadParamIndex = -1; 92*57006b14SXiang Li for (unsigned I = 0; I < ParamList->size(); ++I) { 93*57006b14SXiang Li Record *Param = ParamList->getElementAsRecord(I); 94435897b4Spython3kgae Params.emplace_back(DXILParam(Param)); 95*57006b14SXiang Li auto &CurParam = Params.back(); 96*57006b14SXiang Li if (CurParam.Kind >= ParameterKind::OVERLOAD) 97*57006b14SXiang Li OverloadParamIndex = I; 98435897b4Spython3kgae } 99435897b4Spython3kgae OverloadTypes = R->getValueAsString("oload_types"); 100435897b4Spython3kgae FnAttr = R->getValueAsString("fn_attr"); 101435897b4Spython3kgae } 102435897b4Spython3kgae }; 103435897b4Spython3kgae } // end anonymous namespace 104435897b4Spython3kgae 105*57006b14SXiang Li DXILParam::DXILParam(const Record *R) { 106*57006b14SXiang Li Name = R->getValueAsString("name"); 107*57006b14SXiang Li Pos = R->getValueAsInt("pos"); 108*57006b14SXiang Li Kind = parameterTypeNameToKind(R->getValueAsString("llvm_type")); 109*57006b14SXiang Li if (R->getValue("doc")) 110*57006b14SXiang Li Doc = R->getValueAsString("doc"); 111*57006b14SXiang Li IsConst = R->getValueAsBit("is_const"); 112*57006b14SXiang Li EnumName = R->getValueAsString("enum_name"); 113*57006b14SXiang Li MaxValue = R->getValueAsInt("max_value"); 114*57006b14SXiang Li } 115*57006b14SXiang Li 116*57006b14SXiang Li static std::string parameterKindToString(ParameterKind Kind) { 117*57006b14SXiang Li switch (Kind) { 118*57006b14SXiang Li case ParameterKind::INVALID: 119*57006b14SXiang Li return "INVALID"; 120*57006b14SXiang Li case ParameterKind::VOID: 121*57006b14SXiang Li return "VOID"; 122*57006b14SXiang Li case ParameterKind::HALF: 123*57006b14SXiang Li return "HALF"; 124*57006b14SXiang Li case ParameterKind::FLOAT: 125*57006b14SXiang Li return "FLOAT"; 126*57006b14SXiang Li case ParameterKind::DOUBLE: 127*57006b14SXiang Li return "DOUBLE"; 128*57006b14SXiang Li case ParameterKind::I1: 129*57006b14SXiang Li return "I1"; 130*57006b14SXiang Li case ParameterKind::I8: 131*57006b14SXiang Li return "I8"; 132*57006b14SXiang Li case ParameterKind::I16: 133*57006b14SXiang Li return "I16"; 134*57006b14SXiang Li case ParameterKind::I32: 135*57006b14SXiang Li return "I32"; 136*57006b14SXiang Li case ParameterKind::I64: 137*57006b14SXiang Li return "I64"; 138*57006b14SXiang Li case ParameterKind::OVERLOAD: 139*57006b14SXiang Li return "OVERLOAD"; 140*57006b14SXiang Li case ParameterKind::CBUFFER_RET: 141*57006b14SXiang Li return "CBUFFER_RET"; 142*57006b14SXiang Li case ParameterKind::RESOURCE_RET: 143*57006b14SXiang Li return "RESOURCE_RET"; 144*57006b14SXiang Li case ParameterKind::DXIL_HANDLE: 145*57006b14SXiang Li return "DXIL_HANDLE"; 146*57006b14SXiang Li } 147*57006b14SXiang Li } 148*57006b14SXiang Li 149435897b4Spython3kgae static void emitDXILOpEnum(DXILOperationData &DXILOp, raw_ostream &OS) { 150435897b4Spython3kgae // Name = ID, // Doc 151435897b4Spython3kgae OS << DXILOp.Name << " = " << DXILOp.DXILOpID << ", // " << DXILOp.Doc 152435897b4Spython3kgae << "\n"; 153435897b4Spython3kgae } 154435897b4Spython3kgae 155435897b4Spython3kgae static std::string buildCategoryStr(StringSet<> &Cetegorys) { 156435897b4Spython3kgae std::string Str; 157435897b4Spython3kgae raw_string_ostream OS(Str); 158435897b4Spython3kgae for (auto &It : Cetegorys) { 159435897b4Spython3kgae OS << " " << It.getKey(); 160435897b4Spython3kgae } 161435897b4Spython3kgae return OS.str(); 162435897b4Spython3kgae } 163435897b4Spython3kgae 164435897b4Spython3kgae // Emit enum declaration for DXIL. 165435897b4Spython3kgae static void emitDXILEnums(std::vector<DXILOperationData> &DXILOps, 166435897b4Spython3kgae raw_ostream &OS) { 167435897b4Spython3kgae // Sort by Category + OpName. 168aba43035SDmitri Gribenko llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 169435897b4Spython3kgae // Group by Category first. 170435897b4Spython3kgae if (A.Category == B.Category) 171435897b4Spython3kgae // Inside same Category, order by OpName. 172435897b4Spython3kgae return A.DXILOp < B.DXILOp; 173435897b4Spython3kgae else 174435897b4Spython3kgae return A.Category < B.Category; 175435897b4Spython3kgae }); 176435897b4Spython3kgae 177435897b4Spython3kgae OS << "// Enumeration for operations specified by DXIL\n"; 178435897b4Spython3kgae OS << "enum class OpCode : unsigned {\n"; 179435897b4Spython3kgae 180435897b4Spython3kgae StringMap<StringSet<>> ClassMap; 181435897b4Spython3kgae StringRef PrevCategory = ""; 182435897b4Spython3kgae for (auto &DXILOp : DXILOps) { 183435897b4Spython3kgae StringRef Category = DXILOp.Category; 184435897b4Spython3kgae if (Category != PrevCategory) { 185435897b4Spython3kgae OS << "\n// " << Category << "\n"; 186435897b4Spython3kgae PrevCategory = Category; 187435897b4Spython3kgae } 188435897b4Spython3kgae emitDXILOpEnum(DXILOp, OS); 189435897b4Spython3kgae auto It = ClassMap.find(DXILOp.DXILClass); 190435897b4Spython3kgae if (It != ClassMap.end()) { 191435897b4Spython3kgae It->second.insert(DXILOp.Category); 192435897b4Spython3kgae } else { 193435897b4Spython3kgae ClassMap[DXILOp.DXILClass].insert(DXILOp.Category); 194435897b4Spython3kgae } 195435897b4Spython3kgae } 196435897b4Spython3kgae 197435897b4Spython3kgae OS << "\n};\n\n"; 198435897b4Spython3kgae 199435897b4Spython3kgae std::vector<std::pair<std::string, std::string>> ClassVec; 200435897b4Spython3kgae for (auto &It : ClassMap) { 201435897b4Spython3kgae ClassVec.emplace_back( 202435897b4Spython3kgae std::make_pair(It.getKey().str(), buildCategoryStr(It.second))); 203435897b4Spython3kgae } 204435897b4Spython3kgae // Sort by Category + ClassName. 205aba43035SDmitri Gribenko llvm::sort(ClassVec, [](std::pair<std::string, std::string> &A, 206435897b4Spython3kgae std::pair<std::string, std::string> &B) { 207435897b4Spython3kgae StringRef ClassA = A.first; 208435897b4Spython3kgae StringRef CategoryA = A.second; 209435897b4Spython3kgae StringRef ClassB = B.first; 210435897b4Spython3kgae StringRef CategoryB = B.second; 211435897b4Spython3kgae // Group by Category first. 212435897b4Spython3kgae if (CategoryA == CategoryB) 213435897b4Spython3kgae // Inside same Category, order by ClassName. 214435897b4Spython3kgae return ClassA < ClassB; 215435897b4Spython3kgae else 216435897b4Spython3kgae return CategoryA < CategoryB; 217435897b4Spython3kgae }); 218435897b4Spython3kgae 219435897b4Spython3kgae OS << "// Groups for DXIL operations with equivalent function templates\n"; 220435897b4Spython3kgae OS << "enum class OpCodeClass : unsigned {\n"; 221435897b4Spython3kgae PrevCategory = ""; 222435897b4Spython3kgae for (auto &It : ClassVec) { 223435897b4Spython3kgae 224435897b4Spython3kgae StringRef Category = It.second; 225435897b4Spython3kgae if (Category != PrevCategory) { 226435897b4Spython3kgae OS << "\n// " << Category << "\n"; 227435897b4Spython3kgae PrevCategory = Category; 228435897b4Spython3kgae } 229435897b4Spython3kgae StringRef Name = It.first; 230435897b4Spython3kgae OS << Name << ",\n"; 231435897b4Spython3kgae } 232435897b4Spython3kgae OS << "\n};\n\n"; 233435897b4Spython3kgae } 234435897b4Spython3kgae 235264c09b7SXiang Li // Emit map from llvm intrinsic to DXIL operation. 2360d2dde20SXiang Li static void emitDXILIntrinsicMap(std::vector<DXILOperationData> &DXILOps, 237264c09b7SXiang Li raw_ostream &OS) { 238264c09b7SXiang Li OS << "\n"; 239264c09b7SXiang Li // FIXME: use array instead of SmallDenseMap. 240264c09b7SXiang Li OS << "static const SmallDenseMap<Intrinsic::ID, DXIL::OpCode> LowerMap = " 241264c09b7SXiang Li "{\n"; 242264c09b7SXiang Li for (auto &DXILOp : DXILOps) { 243264c09b7SXiang Li if (DXILOp.Intrinsic.empty()) 244264c09b7SXiang Li continue; 245264c09b7SXiang Li // {Intrinsic::sin, DXIL::OpCode::Sin}, 246264c09b7SXiang Li OS << " { Intrinsic::" << DXILOp.Intrinsic 247264c09b7SXiang Li << ", DXIL::OpCode::" << DXILOp.DXILOp << "},\n"; 248264c09b7SXiang Li } 249264c09b7SXiang Li OS << "};\n"; 250264c09b7SXiang Li OS << "\n"; 251264c09b7SXiang Li } 252264c09b7SXiang Li 2530d2dde20SXiang Li static std::string emitDXILOperationFnAttr(StringRef FnAttr) { 2540d2dde20SXiang Li return StringSwitch<std::string>(FnAttr) 2550d2dde20SXiang Li .Case("rn", "Attribute::ReadNone") 2560d2dde20SXiang Li .Case("ro", "Attribute::ReadOnly") 2570d2dde20SXiang Li .Default("Attribute::None"); 2580d2dde20SXiang Li } 2590d2dde20SXiang Li 2600d2dde20SXiang Li static std::string getOverloadKind(StringRef Overload) { 2610d2dde20SXiang Li return StringSwitch<std::string>(Overload) 2620d2dde20SXiang Li .Case("half", "OverloadKind::HALF") 2630d2dde20SXiang Li .Case("float", "OverloadKind::FLOAT") 2640d2dde20SXiang Li .Case("double", "OverloadKind::DOUBLE") 2650d2dde20SXiang Li .Case("i1", "OverloadKind::I1") 2660d2dde20SXiang Li .Case("i16", "OverloadKind::I16") 2670d2dde20SXiang Li .Case("i32", "OverloadKind::I32") 2680d2dde20SXiang Li .Case("i64", "OverloadKind::I64") 2690d2dde20SXiang Li .Case("udt", "OverloadKind::UserDefineType") 2700d2dde20SXiang Li .Case("obj", "OverloadKind::ObjectType") 2710d2dde20SXiang Li .Default("OverloadKind::VOID"); 2720d2dde20SXiang Li } 2730d2dde20SXiang Li 2740d2dde20SXiang Li static std::string getDXILOperationOverload(StringRef Overloads) { 2750d2dde20SXiang Li SmallVector<StringRef> OverloadStrs; 2760d2dde20SXiang Li Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false); 2770d2dde20SXiang Li // Format is: OverloadKind::FLOAT | OverloadKind::HALF 2780d2dde20SXiang Li assert(!OverloadStrs.empty() && "Invalid overloads"); 2790d2dde20SXiang Li auto It = OverloadStrs.begin(); 2800d2dde20SXiang Li std::string Result; 2810d2dde20SXiang Li raw_string_ostream OS(Result); 2820d2dde20SXiang Li OS << getOverloadKind(*It); 2830d2dde20SXiang Li for (++It; It != OverloadStrs.end(); ++It) { 2840d2dde20SXiang Li OS << " | " << getOverloadKind(*It); 2850d2dde20SXiang Li } 2860d2dde20SXiang Li return OS.str(); 2870d2dde20SXiang Li } 2880d2dde20SXiang Li 2890d2dde20SXiang Li static std::string lowerFirstLetter(StringRef Name) { 2900d2dde20SXiang Li if (Name.empty()) 2910d2dde20SXiang Li return ""; 2920d2dde20SXiang Li 2930d2dde20SXiang Li std::string LowerName = Name.str(); 2940d2dde20SXiang Li LowerName[0] = llvm::toLower(Name[0]); 2950d2dde20SXiang Li return LowerName; 2960d2dde20SXiang Li } 2970d2dde20SXiang Li 2980d2dde20SXiang Li static std::string getDXILOpClassName(StringRef DXILOpClass) { 2990d2dde20SXiang Li // Lower first letter expect for special case. 3000d2dde20SXiang Li return StringSwitch<std::string>(DXILOpClass) 3010d2dde20SXiang Li .Case("CBufferLoad", "cbufferLoad") 3020d2dde20SXiang Li .Case("CBufferLoadLegacy", "cbufferLoadLegacy") 3030d2dde20SXiang Li .Case("GSInstanceID", "gsInstanceID") 3040d2dde20SXiang Li .Default(lowerFirstLetter(DXILOpClass)); 3050d2dde20SXiang Li } 3060d2dde20SXiang Li 3070d2dde20SXiang Li static void emitDXILOperationTable(std::vector<DXILOperationData> &DXILOps, 3080d2dde20SXiang Li raw_ostream &OS) { 3090d2dde20SXiang Li // Sort by DXILOpID. 310aba43035SDmitri Gribenko llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 3110d2dde20SXiang Li return A.DXILOpID < B.DXILOpID; 3120d2dde20SXiang Li }); 3130d2dde20SXiang Li 3140d2dde20SXiang Li // Collect Names. 3150d2dde20SXiang Li SequenceToOffsetTable<std::string> OpClassStrings; 3160d2dde20SXiang Li SequenceToOffsetTable<std::string> OpStrings; 317*57006b14SXiang Li SequenceToOffsetTable<SmallVector<ParameterKind>> Parameters; 3180d2dde20SXiang Li 319*57006b14SXiang Li StringMap<SmallVector<ParameterKind>> ParameterMap; 3200d2dde20SXiang Li StringSet<> ClassSet; 3210d2dde20SXiang Li for (auto &DXILOp : DXILOps) { 3220d2dde20SXiang Li OpStrings.add(DXILOp.DXILOp.str()); 3230d2dde20SXiang Li 3240d2dde20SXiang Li if (ClassSet.find(DXILOp.DXILClass) != ClassSet.end()) 3250d2dde20SXiang Li continue; 3260d2dde20SXiang Li ClassSet.insert(DXILOp.DXILClass); 3270d2dde20SXiang Li OpClassStrings.add(getDXILOpClassName(DXILOp.DXILClass)); 328*57006b14SXiang Li SmallVector<ParameterKind> ParamKindVec; 329*57006b14SXiang Li for (auto &Param : DXILOp.Params) { 330*57006b14SXiang Li ParamKindVec.emplace_back(Param.Kind); 331*57006b14SXiang Li } 332*57006b14SXiang Li ParameterMap[DXILOp.DXILClass] = ParamKindVec; 333*57006b14SXiang Li Parameters.add(ParamKindVec); 3340d2dde20SXiang Li } 3350d2dde20SXiang Li 3360d2dde20SXiang Li // Layout names. 3370d2dde20SXiang Li OpStrings.layout(); 3380d2dde20SXiang Li OpClassStrings.layout(); 339*57006b14SXiang Li Parameters.layout(); 3400d2dde20SXiang Li 3410d2dde20SXiang Li // Emit the DXIL operation table. 3420d2dde20SXiang Li //{DXIL::OpCode::Sin, OpCodeNameIndex, OpCodeClass::Unary, 3430d2dde20SXiang Li // OpCodeClassNameIndex, 344*57006b14SXiang Li // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone, 0, 345*57006b14SXiang Li // 3, ParameterTableOffset}, 3460d2dde20SXiang Li OS << "static const OpCodeProperty *getOpCodeProperty(DXIL::OpCode DXILOp) " 3470d2dde20SXiang Li "{\n"; 3480d2dde20SXiang Li 3490d2dde20SXiang Li OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 3500d2dde20SXiang Li for (auto &DXILOp : DXILOps) { 3510d2dde20SXiang Li OS << " { DXIL::OpCode::" << DXILOp.DXILOp << ", " 3520d2dde20SXiang Li << OpStrings.get(DXILOp.DXILOp.str()) 3530d2dde20SXiang Li << ", OpCodeClass::" << DXILOp.DXILClass << ", " 3540d2dde20SXiang Li << OpClassStrings.get(getDXILOpClassName(DXILOp.DXILClass)) << ", " 3550d2dde20SXiang Li << getDXILOperationOverload(DXILOp.OverloadTypes) << ", " 356*57006b14SXiang Li << emitDXILOperationFnAttr(DXILOp.FnAttr) << ", " 357*57006b14SXiang Li << DXILOp.OverloadParamIndex << ", " << DXILOp.Params.size() << ", " 358*57006b14SXiang Li << Parameters.get(ParameterMap[DXILOp.DXILClass]) << " },\n"; 3590d2dde20SXiang Li } 3600d2dde20SXiang Li OS << " };\n"; 3610d2dde20SXiang Li 3620d2dde20SXiang Li OS << " // FIXME: change search to indexing with\n"; 3630d2dde20SXiang Li OS << " // DXILOp once all DXIL op is added.\n"; 3640d2dde20SXiang Li OS << " OpCodeProperty TmpProp;\n"; 3650d2dde20SXiang Li OS << " TmpProp.OpCode = DXILOp;\n"; 3660d2dde20SXiang Li OS << " const OpCodeProperty *Prop =\n"; 3670d2dde20SXiang Li OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 3680d2dde20SXiang Li OS << " [](const OpCodeProperty &A, const " 3690d2dde20SXiang Li "OpCodeProperty &B) {\n"; 3700d2dde20SXiang Li OS << " return A.OpCode < B.OpCode;\n"; 3710d2dde20SXiang Li OS << " });\n"; 3720d2dde20SXiang Li OS << " assert(Prop && \"fail to find OpCodeProperty\");\n"; 3730d2dde20SXiang Li OS << " return Prop;\n"; 3740d2dde20SXiang Li OS << "}\n\n"; 3750d2dde20SXiang Li 3760d2dde20SXiang Li // Emit the string tables. 3770d2dde20SXiang Li OS << "static const char *getOpCodeName(DXIL::OpCode DXILOp) {\n\n"; 3780d2dde20SXiang Li 3790d2dde20SXiang Li OpStrings.emitStringLiteralDef(OS, 3800d2dde20SXiang Li " static const char DXILOpCodeNameTable[]"); 3810d2dde20SXiang Li 3820d2dde20SXiang Li OS << " auto *Prop = getOpCodeProperty(DXILOp);\n"; 3830d2dde20SXiang Li OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 3840d2dde20SXiang Li OS << " return DXILOpCodeNameTable + Index;\n"; 3850d2dde20SXiang Li OS << "}\n\n"; 3860d2dde20SXiang Li 3870d2dde20SXiang Li OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 3880d2dde20SXiang Li "{\n\n"; 3890d2dde20SXiang Li 3900d2dde20SXiang Li OpClassStrings.emitStringLiteralDef( 3910d2dde20SXiang Li OS, " static const char DXILOpCodeClassNameTable[]"); 3920d2dde20SXiang Li 3930d2dde20SXiang Li OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 3940d2dde20SXiang Li OS << " return DXILOpCodeClassNameTable + Index;\n"; 3950d2dde20SXiang Li OS << "}\n "; 396*57006b14SXiang Li 397*57006b14SXiang Li OS << "static const ParameterKind *getOpCodeParameterKind(const " 398*57006b14SXiang Li "OpCodeProperty &Prop) " 399*57006b14SXiang Li "{\n\n"; 400*57006b14SXiang Li OS << " static const ParameterKind DXILOpParameterKindTable[] = {\n"; 401*57006b14SXiang Li Parameters.emit( 402*57006b14SXiang Li OS, 403*57006b14SXiang Li [](raw_ostream &ParamOS, ParameterKind Kind) { 404*57006b14SXiang Li ParamOS << "ParameterKind::" << parameterKindToString(Kind); 405*57006b14SXiang Li }, 406*57006b14SXiang Li "ParameterKind::INVALID"); 407*57006b14SXiang Li OS << " };\n\n"; 408*57006b14SXiang Li OS << " unsigned Index = Prop.ParameterTableOffset;\n"; 409*57006b14SXiang Li OS << " return DXILOpParameterKindTable + Index;\n"; 410*57006b14SXiang Li OS << "}\n "; 4110d2dde20SXiang Li } 4120d2dde20SXiang Li 413435897b4Spython3kgae namespace llvm { 414435897b4Spython3kgae 415435897b4Spython3kgae void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { 416435897b4Spython3kgae std::vector<Record *> Ops = Records.getAllDerivedDefinitions("dxil_op"); 417435897b4Spython3kgae OS << "// Generated code, do not edit.\n"; 418435897b4Spython3kgae OS << "\n"; 419435897b4Spython3kgae 420435897b4Spython3kgae std::vector<DXILOperationData> DXILOps; 421435897b4Spython3kgae DXILOps.reserve(Ops.size()); 422435897b4Spython3kgae for (auto *Record : Ops) { 423435897b4Spython3kgae DXILOps.emplace_back(DXILOperationData(Record)); 424435897b4Spython3kgae } 425435897b4Spython3kgae 426435897b4Spython3kgae OS << "#ifdef DXIL_OP_ENUM\n"; 427435897b4Spython3kgae emitDXILEnums(DXILOps, OS); 428435897b4Spython3kgae OS << "#endif\n\n"; 429435897b4Spython3kgae 430264c09b7SXiang Li OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; 4310d2dde20SXiang Li emitDXILIntrinsicMap(DXILOps, OS); 432264c09b7SXiang Li OS << "#endif\n\n"; 433264c09b7SXiang Li 4340d2dde20SXiang Li OS << "#ifdef DXIL_OP_OPERATION_TABLE\n"; 4350d2dde20SXiang Li emitDXILOperationTable(DXILOps, OS); 4360d2dde20SXiang Li OS << "#endif\n\n"; 437264c09b7SXiang Li 438435897b4Spython3kgae OS << "\n"; 439435897b4Spython3kgae } 440435897b4Spython3kgae 441435897b4Spython3kgae } // namespace llvm 442