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" 19*972a253aSDimitry Andric #include "llvm/Support/DXILOperationCommon.h" 2081ad6265SDimitry Andric #include "llvm/TableGen/Error.h" 2181ad6265SDimitry Andric #include "llvm/TableGen/Record.h" 2281ad6265SDimitry Andric 2381ad6265SDimitry Andric using namespace llvm; 24*972a253aSDimitry Andric using namespace llvm::DXIL; 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric namespace { 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric struct DXILShaderModel { 2981ad6265SDimitry Andric int Major; 3081ad6265SDimitry Andric int Minor; 3181ad6265SDimitry Andric }; 32*972a253aSDimitry Andric 3381ad6265SDimitry Andric struct DXILParam { 3481ad6265SDimitry Andric int Pos; // position in parameter list 35*972a253aSDimitry 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 41*972a253aSDimitry 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 5981ad6265SDimitry Andric bool IsDeriv; // whether this is some kind of derivative 6081ad6265SDimitry Andric bool IsGradient; // whether this requires a gradient calculation 6181ad6265SDimitry Andric bool IsFeedback; // whether this is a sampler feedback op 6281ad6265SDimitry Andric bool IsWave; // whether this requires in-wave, cross-lane functionality 6381ad6265SDimitry Andric bool RequiresUniformInputs; // whether this operation requires that all 6481ad6265SDimitry Andric // of its inputs are uniform across the wave 6581ad6265SDimitry Andric SmallVector<StringRef, 4> 6681ad6265SDimitry Andric ShaderStages; // shader stages to which this applies, empty for all. 6781ad6265SDimitry Andric DXILShaderModel ShaderModel; // minimum shader model required 6881ad6265SDimitry Andric DXILShaderModel ShaderModelTranslated; // minimum shader model required with 6981ad6265SDimitry Andric // translation by linker 70*972a253aSDimitry Andric int OverloadParamIndex; // parameter index which control the overload. 71*972a253aSDimitry Andric // When < 0, should be only 1 overload type. 7281ad6265SDimitry Andric SmallVector<StringRef, 4> counters; // counters for this inst. 7381ad6265SDimitry Andric DXILOperationData(const Record *R) { 7481ad6265SDimitry Andric Name = R->getValueAsString("name"); 7581ad6265SDimitry Andric DXILOp = R->getValueAsString("dxil_op"); 7681ad6265SDimitry Andric DXILOpID = R->getValueAsInt("dxil_opid"); 7781ad6265SDimitry Andric DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); 7881ad6265SDimitry Andric Category = R->getValueAsDef("category")->getValueAsString("name"); 7981ad6265SDimitry Andric 8081ad6265SDimitry Andric if (R->getValue("llvm_intrinsic")) { 8181ad6265SDimitry Andric auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); 8281ad6265SDimitry Andric auto DefName = IntrinsicDef->getName(); 8381ad6265SDimitry Andric assert(DefName.startswith("int_") && "invalid intrinsic name"); 8481ad6265SDimitry Andric // Remove the int_ from intrinsic name. 8581ad6265SDimitry Andric Intrinsic = DefName.substr(4); 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric ListInit *ParamList = R->getValueAsListInit("ops"); 91*972a253aSDimitry Andric OverloadParamIndex = -1; 92*972a253aSDimitry Andric for (unsigned I = 0; I < ParamList->size(); ++I) { 93*972a253aSDimitry Andric Record *Param = ParamList->getElementAsRecord(I); 9481ad6265SDimitry Andric Params.emplace_back(DXILParam(Param)); 95*972a253aSDimitry Andric auto &CurParam = Params.back(); 96*972a253aSDimitry Andric if (CurParam.Kind >= ParameterKind::OVERLOAD) 97*972a253aSDimitry Andric OverloadParamIndex = I; 9881ad6265SDimitry Andric } 9981ad6265SDimitry Andric OverloadTypes = R->getValueAsString("oload_types"); 10081ad6265SDimitry Andric FnAttr = R->getValueAsString("fn_attr"); 10181ad6265SDimitry Andric } 10281ad6265SDimitry Andric }; 10381ad6265SDimitry Andric } // end anonymous namespace 10481ad6265SDimitry Andric 105*972a253aSDimitry Andric DXILParam::DXILParam(const Record *R) { 106*972a253aSDimitry Andric Name = R->getValueAsString("name"); 107*972a253aSDimitry Andric Pos = R->getValueAsInt("pos"); 108*972a253aSDimitry Andric Kind = parameterTypeNameToKind(R->getValueAsString("llvm_type")); 109*972a253aSDimitry Andric if (R->getValue("doc")) 110*972a253aSDimitry Andric Doc = R->getValueAsString("doc"); 111*972a253aSDimitry Andric IsConst = R->getValueAsBit("is_const"); 112*972a253aSDimitry Andric EnumName = R->getValueAsString("enum_name"); 113*972a253aSDimitry Andric MaxValue = R->getValueAsInt("max_value"); 114*972a253aSDimitry Andric } 115*972a253aSDimitry Andric 116*972a253aSDimitry Andric static std::string parameterKindToString(ParameterKind Kind) { 117*972a253aSDimitry Andric switch (Kind) { 118*972a253aSDimitry Andric case ParameterKind::INVALID: 119*972a253aSDimitry Andric return "INVALID"; 120*972a253aSDimitry Andric case ParameterKind::VOID: 121*972a253aSDimitry Andric return "VOID"; 122*972a253aSDimitry Andric case ParameterKind::HALF: 123*972a253aSDimitry Andric return "HALF"; 124*972a253aSDimitry Andric case ParameterKind::FLOAT: 125*972a253aSDimitry Andric return "FLOAT"; 126*972a253aSDimitry Andric case ParameterKind::DOUBLE: 127*972a253aSDimitry Andric return "DOUBLE"; 128*972a253aSDimitry Andric case ParameterKind::I1: 129*972a253aSDimitry Andric return "I1"; 130*972a253aSDimitry Andric case ParameterKind::I8: 131*972a253aSDimitry Andric return "I8"; 132*972a253aSDimitry Andric case ParameterKind::I16: 133*972a253aSDimitry Andric return "I16"; 134*972a253aSDimitry Andric case ParameterKind::I32: 135*972a253aSDimitry Andric return "I32"; 136*972a253aSDimitry Andric case ParameterKind::I64: 137*972a253aSDimitry Andric return "I64"; 138*972a253aSDimitry Andric case ParameterKind::OVERLOAD: 139*972a253aSDimitry Andric return "OVERLOAD"; 140*972a253aSDimitry Andric case ParameterKind::CBUFFER_RET: 141*972a253aSDimitry Andric return "CBUFFER_RET"; 142*972a253aSDimitry Andric case ParameterKind::RESOURCE_RET: 143*972a253aSDimitry Andric return "RESOURCE_RET"; 144*972a253aSDimitry Andric case ParameterKind::DXIL_HANDLE: 145*972a253aSDimitry Andric return "DXIL_HANDLE"; 146*972a253aSDimitry Andric } 147*972a253aSDimitry Andric llvm_unreachable("Unknown llvm::DXIL::ParameterKind enum"); 148*972a253aSDimitry Andric } 149*972a253aSDimitry Andric 15081ad6265SDimitry Andric static void emitDXILOpEnum(DXILOperationData &DXILOp, raw_ostream &OS) { 15181ad6265SDimitry Andric // Name = ID, // Doc 15281ad6265SDimitry Andric OS << DXILOp.Name << " = " << DXILOp.DXILOpID << ", // " << DXILOp.Doc 15381ad6265SDimitry Andric << "\n"; 15481ad6265SDimitry Andric } 15581ad6265SDimitry Andric 15681ad6265SDimitry Andric static std::string buildCategoryStr(StringSet<> &Cetegorys) { 15781ad6265SDimitry Andric std::string Str; 15881ad6265SDimitry Andric raw_string_ostream OS(Str); 15981ad6265SDimitry Andric for (auto &It : Cetegorys) { 16081ad6265SDimitry Andric OS << " " << It.getKey(); 16181ad6265SDimitry Andric } 16281ad6265SDimitry Andric return OS.str(); 16381ad6265SDimitry Andric } 16481ad6265SDimitry Andric 16581ad6265SDimitry Andric // Emit enum declaration for DXIL. 16681ad6265SDimitry Andric static void emitDXILEnums(std::vector<DXILOperationData> &DXILOps, 16781ad6265SDimitry Andric raw_ostream &OS) { 16881ad6265SDimitry Andric // Sort by Category + OpName. 169fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 17081ad6265SDimitry Andric // Group by Category first. 17181ad6265SDimitry Andric if (A.Category == B.Category) 17281ad6265SDimitry Andric // Inside same Category, order by OpName. 17381ad6265SDimitry Andric return A.DXILOp < B.DXILOp; 17481ad6265SDimitry Andric else 17581ad6265SDimitry Andric return A.Category < B.Category; 17681ad6265SDimitry Andric }); 17781ad6265SDimitry Andric 17881ad6265SDimitry Andric OS << "// Enumeration for operations specified by DXIL\n"; 17981ad6265SDimitry Andric OS << "enum class OpCode : unsigned {\n"; 18081ad6265SDimitry Andric 18181ad6265SDimitry Andric StringMap<StringSet<>> ClassMap; 18281ad6265SDimitry Andric StringRef PrevCategory = ""; 18381ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 18481ad6265SDimitry Andric StringRef Category = DXILOp.Category; 18581ad6265SDimitry Andric if (Category != PrevCategory) { 18681ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 18781ad6265SDimitry Andric PrevCategory = Category; 18881ad6265SDimitry Andric } 18981ad6265SDimitry Andric emitDXILOpEnum(DXILOp, OS); 19081ad6265SDimitry Andric auto It = ClassMap.find(DXILOp.DXILClass); 19181ad6265SDimitry Andric if (It != ClassMap.end()) { 19281ad6265SDimitry Andric It->second.insert(DXILOp.Category); 19381ad6265SDimitry Andric } else { 19481ad6265SDimitry Andric ClassMap[DXILOp.DXILClass].insert(DXILOp.Category); 19581ad6265SDimitry Andric } 19681ad6265SDimitry Andric } 19781ad6265SDimitry Andric 19881ad6265SDimitry Andric OS << "\n};\n\n"; 19981ad6265SDimitry Andric 20081ad6265SDimitry Andric std::vector<std::pair<std::string, std::string>> ClassVec; 20181ad6265SDimitry Andric for (auto &It : ClassMap) { 20281ad6265SDimitry Andric ClassVec.emplace_back( 20381ad6265SDimitry Andric std::make_pair(It.getKey().str(), buildCategoryStr(It.second))); 20481ad6265SDimitry Andric } 20581ad6265SDimitry Andric // Sort by Category + ClassName. 206fcaf7f86SDimitry Andric llvm::sort(ClassVec, [](std::pair<std::string, std::string> &A, 20781ad6265SDimitry Andric std::pair<std::string, std::string> &B) { 20881ad6265SDimitry Andric StringRef ClassA = A.first; 20981ad6265SDimitry Andric StringRef CategoryA = A.second; 21081ad6265SDimitry Andric StringRef ClassB = B.first; 21181ad6265SDimitry Andric StringRef CategoryB = B.second; 21281ad6265SDimitry Andric // Group by Category first. 21381ad6265SDimitry Andric if (CategoryA == CategoryB) 21481ad6265SDimitry Andric // Inside same Category, order by ClassName. 21581ad6265SDimitry Andric return ClassA < ClassB; 21681ad6265SDimitry Andric else 21781ad6265SDimitry Andric return CategoryA < CategoryB; 21881ad6265SDimitry Andric }); 21981ad6265SDimitry Andric 22081ad6265SDimitry Andric OS << "// Groups for DXIL operations with equivalent function templates\n"; 22181ad6265SDimitry Andric OS << "enum class OpCodeClass : unsigned {\n"; 22281ad6265SDimitry Andric PrevCategory = ""; 22381ad6265SDimitry Andric for (auto &It : ClassVec) { 22481ad6265SDimitry Andric 22581ad6265SDimitry Andric StringRef Category = It.second; 22681ad6265SDimitry Andric if (Category != PrevCategory) { 22781ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 22881ad6265SDimitry Andric PrevCategory = Category; 22981ad6265SDimitry Andric } 23081ad6265SDimitry Andric StringRef Name = It.first; 23181ad6265SDimitry Andric OS << Name << ",\n"; 23281ad6265SDimitry Andric } 23381ad6265SDimitry Andric OS << "\n};\n\n"; 23481ad6265SDimitry Andric } 23581ad6265SDimitry Andric 23681ad6265SDimitry Andric // Emit map from llvm intrinsic to DXIL operation. 23781ad6265SDimitry Andric static void emitDXILIntrinsicMap(std::vector<DXILOperationData> &DXILOps, 23881ad6265SDimitry Andric raw_ostream &OS) { 23981ad6265SDimitry Andric OS << "\n"; 24081ad6265SDimitry Andric // FIXME: use array instead of SmallDenseMap. 24181ad6265SDimitry Andric OS << "static const SmallDenseMap<Intrinsic::ID, DXIL::OpCode> LowerMap = " 24281ad6265SDimitry Andric "{\n"; 24381ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 24481ad6265SDimitry Andric if (DXILOp.Intrinsic.empty()) 24581ad6265SDimitry Andric continue; 24681ad6265SDimitry Andric // {Intrinsic::sin, DXIL::OpCode::Sin}, 24781ad6265SDimitry Andric OS << " { Intrinsic::" << DXILOp.Intrinsic 24881ad6265SDimitry Andric << ", DXIL::OpCode::" << DXILOp.DXILOp << "},\n"; 24981ad6265SDimitry Andric } 25081ad6265SDimitry Andric OS << "};\n"; 25181ad6265SDimitry Andric OS << "\n"; 25281ad6265SDimitry Andric } 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric static std::string emitDXILOperationFnAttr(StringRef FnAttr) { 25581ad6265SDimitry Andric return StringSwitch<std::string>(FnAttr) 25681ad6265SDimitry Andric .Case("rn", "Attribute::ReadNone") 25781ad6265SDimitry Andric .Case("ro", "Attribute::ReadOnly") 25881ad6265SDimitry Andric .Default("Attribute::None"); 25981ad6265SDimitry Andric } 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric static std::string getOverloadKind(StringRef Overload) { 26281ad6265SDimitry Andric return StringSwitch<std::string>(Overload) 26381ad6265SDimitry Andric .Case("half", "OverloadKind::HALF") 26481ad6265SDimitry Andric .Case("float", "OverloadKind::FLOAT") 26581ad6265SDimitry Andric .Case("double", "OverloadKind::DOUBLE") 26681ad6265SDimitry Andric .Case("i1", "OverloadKind::I1") 26781ad6265SDimitry Andric .Case("i16", "OverloadKind::I16") 26881ad6265SDimitry Andric .Case("i32", "OverloadKind::I32") 26981ad6265SDimitry Andric .Case("i64", "OverloadKind::I64") 27081ad6265SDimitry Andric .Case("udt", "OverloadKind::UserDefineType") 27181ad6265SDimitry Andric .Case("obj", "OverloadKind::ObjectType") 27281ad6265SDimitry Andric .Default("OverloadKind::VOID"); 27381ad6265SDimitry Andric } 27481ad6265SDimitry Andric 27581ad6265SDimitry Andric static std::string getDXILOperationOverload(StringRef Overloads) { 27681ad6265SDimitry Andric SmallVector<StringRef> OverloadStrs; 27781ad6265SDimitry Andric Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false); 27881ad6265SDimitry Andric // Format is: OverloadKind::FLOAT | OverloadKind::HALF 27981ad6265SDimitry Andric assert(!OverloadStrs.empty() && "Invalid overloads"); 28081ad6265SDimitry Andric auto It = OverloadStrs.begin(); 28181ad6265SDimitry Andric std::string Result; 28281ad6265SDimitry Andric raw_string_ostream OS(Result); 28381ad6265SDimitry Andric OS << getOverloadKind(*It); 28481ad6265SDimitry Andric for (++It; It != OverloadStrs.end(); ++It) { 28581ad6265SDimitry Andric OS << " | " << getOverloadKind(*It); 28681ad6265SDimitry Andric } 28781ad6265SDimitry Andric return OS.str(); 28881ad6265SDimitry Andric } 28981ad6265SDimitry Andric 29081ad6265SDimitry Andric static std::string lowerFirstLetter(StringRef Name) { 29181ad6265SDimitry Andric if (Name.empty()) 29281ad6265SDimitry Andric return ""; 29381ad6265SDimitry Andric 29481ad6265SDimitry Andric std::string LowerName = Name.str(); 29581ad6265SDimitry Andric LowerName[0] = llvm::toLower(Name[0]); 29681ad6265SDimitry Andric return LowerName; 29781ad6265SDimitry Andric } 29881ad6265SDimitry Andric 29981ad6265SDimitry Andric static std::string getDXILOpClassName(StringRef DXILOpClass) { 30081ad6265SDimitry Andric // Lower first letter expect for special case. 30181ad6265SDimitry Andric return StringSwitch<std::string>(DXILOpClass) 30281ad6265SDimitry Andric .Case("CBufferLoad", "cbufferLoad") 30381ad6265SDimitry Andric .Case("CBufferLoadLegacy", "cbufferLoadLegacy") 30481ad6265SDimitry Andric .Case("GSInstanceID", "gsInstanceID") 30581ad6265SDimitry Andric .Default(lowerFirstLetter(DXILOpClass)); 30681ad6265SDimitry Andric } 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric static void emitDXILOperationTable(std::vector<DXILOperationData> &DXILOps, 30981ad6265SDimitry Andric raw_ostream &OS) { 31081ad6265SDimitry Andric // Sort by DXILOpID. 311fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 31281ad6265SDimitry Andric return A.DXILOpID < B.DXILOpID; 31381ad6265SDimitry Andric }); 31481ad6265SDimitry Andric 31581ad6265SDimitry Andric // Collect Names. 31681ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpClassStrings; 31781ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpStrings; 318*972a253aSDimitry Andric SequenceToOffsetTable<SmallVector<ParameterKind>> Parameters; 31981ad6265SDimitry Andric 320*972a253aSDimitry Andric StringMap<SmallVector<ParameterKind>> ParameterMap; 32181ad6265SDimitry Andric StringSet<> ClassSet; 32281ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 32381ad6265SDimitry Andric OpStrings.add(DXILOp.DXILOp.str()); 32481ad6265SDimitry Andric 32581ad6265SDimitry Andric if (ClassSet.find(DXILOp.DXILClass) != ClassSet.end()) 32681ad6265SDimitry Andric continue; 32781ad6265SDimitry Andric ClassSet.insert(DXILOp.DXILClass); 32881ad6265SDimitry Andric OpClassStrings.add(getDXILOpClassName(DXILOp.DXILClass)); 329*972a253aSDimitry Andric SmallVector<ParameterKind> ParamKindVec; 330*972a253aSDimitry Andric for (auto &Param : DXILOp.Params) { 331*972a253aSDimitry Andric ParamKindVec.emplace_back(Param.Kind); 332*972a253aSDimitry Andric } 333*972a253aSDimitry Andric ParameterMap[DXILOp.DXILClass] = ParamKindVec; 334*972a253aSDimitry Andric Parameters.add(ParamKindVec); 33581ad6265SDimitry Andric } 33681ad6265SDimitry Andric 33781ad6265SDimitry Andric // Layout names. 33881ad6265SDimitry Andric OpStrings.layout(); 33981ad6265SDimitry Andric OpClassStrings.layout(); 340*972a253aSDimitry Andric Parameters.layout(); 34181ad6265SDimitry Andric 34281ad6265SDimitry Andric // Emit the DXIL operation table. 34381ad6265SDimitry Andric //{DXIL::OpCode::Sin, OpCodeNameIndex, OpCodeClass::Unary, 34481ad6265SDimitry Andric // OpCodeClassNameIndex, 345*972a253aSDimitry Andric // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone, 0, 346*972a253aSDimitry Andric // 3, ParameterTableOffset}, 34781ad6265SDimitry Andric OS << "static const OpCodeProperty *getOpCodeProperty(DXIL::OpCode DXILOp) " 34881ad6265SDimitry Andric "{\n"; 34981ad6265SDimitry Andric 35081ad6265SDimitry Andric OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 35181ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 35281ad6265SDimitry Andric OS << " { DXIL::OpCode::" << DXILOp.DXILOp << ", " 35381ad6265SDimitry Andric << OpStrings.get(DXILOp.DXILOp.str()) 35481ad6265SDimitry Andric << ", OpCodeClass::" << DXILOp.DXILClass << ", " 35581ad6265SDimitry Andric << OpClassStrings.get(getDXILOpClassName(DXILOp.DXILClass)) << ", " 35681ad6265SDimitry Andric << getDXILOperationOverload(DXILOp.OverloadTypes) << ", " 357*972a253aSDimitry Andric << emitDXILOperationFnAttr(DXILOp.FnAttr) << ", " 358*972a253aSDimitry Andric << DXILOp.OverloadParamIndex << ", " << DXILOp.Params.size() << ", " 359*972a253aSDimitry Andric << Parameters.get(ParameterMap[DXILOp.DXILClass]) << " },\n"; 36081ad6265SDimitry Andric } 36181ad6265SDimitry Andric OS << " };\n"; 36281ad6265SDimitry Andric 36381ad6265SDimitry Andric OS << " // FIXME: change search to indexing with\n"; 36481ad6265SDimitry Andric OS << " // DXILOp once all DXIL op is added.\n"; 36581ad6265SDimitry Andric OS << " OpCodeProperty TmpProp;\n"; 36681ad6265SDimitry Andric OS << " TmpProp.OpCode = DXILOp;\n"; 36781ad6265SDimitry Andric OS << " const OpCodeProperty *Prop =\n"; 36881ad6265SDimitry Andric OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 36981ad6265SDimitry Andric OS << " [](const OpCodeProperty &A, const " 37081ad6265SDimitry Andric "OpCodeProperty &B) {\n"; 37181ad6265SDimitry Andric OS << " return A.OpCode < B.OpCode;\n"; 37281ad6265SDimitry Andric OS << " });\n"; 37381ad6265SDimitry Andric OS << " assert(Prop && \"fail to find OpCodeProperty\");\n"; 37481ad6265SDimitry Andric OS << " return Prop;\n"; 37581ad6265SDimitry Andric OS << "}\n\n"; 37681ad6265SDimitry Andric 37781ad6265SDimitry Andric // Emit the string tables. 37881ad6265SDimitry Andric OS << "static const char *getOpCodeName(DXIL::OpCode DXILOp) {\n\n"; 37981ad6265SDimitry Andric 38081ad6265SDimitry Andric OpStrings.emitStringLiteralDef(OS, 38181ad6265SDimitry Andric " static const char DXILOpCodeNameTable[]"); 38281ad6265SDimitry Andric 38381ad6265SDimitry Andric OS << " auto *Prop = getOpCodeProperty(DXILOp);\n"; 38481ad6265SDimitry Andric OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 38581ad6265SDimitry Andric OS << " return DXILOpCodeNameTable + Index;\n"; 38681ad6265SDimitry Andric OS << "}\n\n"; 38781ad6265SDimitry Andric 38881ad6265SDimitry Andric OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 38981ad6265SDimitry Andric "{\n\n"; 39081ad6265SDimitry Andric 39181ad6265SDimitry Andric OpClassStrings.emitStringLiteralDef( 39281ad6265SDimitry Andric OS, " static const char DXILOpCodeClassNameTable[]"); 39381ad6265SDimitry Andric 39481ad6265SDimitry Andric OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 39581ad6265SDimitry Andric OS << " return DXILOpCodeClassNameTable + Index;\n"; 39681ad6265SDimitry Andric OS << "}\n "; 397*972a253aSDimitry Andric 398*972a253aSDimitry Andric OS << "static const ParameterKind *getOpCodeParameterKind(const " 399*972a253aSDimitry Andric "OpCodeProperty &Prop) " 400*972a253aSDimitry Andric "{\n\n"; 401*972a253aSDimitry Andric OS << " static const ParameterKind DXILOpParameterKindTable[] = {\n"; 402*972a253aSDimitry Andric Parameters.emit( 403*972a253aSDimitry Andric OS, 404*972a253aSDimitry Andric [](raw_ostream &ParamOS, ParameterKind Kind) { 405*972a253aSDimitry Andric ParamOS << "ParameterKind::" << parameterKindToString(Kind); 406*972a253aSDimitry Andric }, 407*972a253aSDimitry Andric "ParameterKind::INVALID"); 408*972a253aSDimitry Andric OS << " };\n\n"; 409*972a253aSDimitry Andric OS << " unsigned Index = Prop.ParameterTableOffset;\n"; 410*972a253aSDimitry Andric OS << " return DXILOpParameterKindTable + Index;\n"; 411*972a253aSDimitry Andric OS << "}\n "; 41281ad6265SDimitry Andric } 41381ad6265SDimitry Andric 41481ad6265SDimitry Andric namespace llvm { 41581ad6265SDimitry Andric 41681ad6265SDimitry Andric void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { 41781ad6265SDimitry Andric std::vector<Record *> Ops = Records.getAllDerivedDefinitions("dxil_op"); 41881ad6265SDimitry Andric OS << "// Generated code, do not edit.\n"; 41981ad6265SDimitry Andric OS << "\n"; 42081ad6265SDimitry Andric 42181ad6265SDimitry Andric std::vector<DXILOperationData> DXILOps; 42281ad6265SDimitry Andric DXILOps.reserve(Ops.size()); 42381ad6265SDimitry Andric for (auto *Record : Ops) { 42481ad6265SDimitry Andric DXILOps.emplace_back(DXILOperationData(Record)); 42581ad6265SDimitry Andric } 42681ad6265SDimitry Andric 42781ad6265SDimitry Andric OS << "#ifdef DXIL_OP_ENUM\n"; 42881ad6265SDimitry Andric emitDXILEnums(DXILOps, OS); 42981ad6265SDimitry Andric OS << "#endif\n\n"; 43081ad6265SDimitry Andric 43181ad6265SDimitry Andric OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; 43281ad6265SDimitry Andric emitDXILIntrinsicMap(DXILOps, OS); 43381ad6265SDimitry Andric OS << "#endif\n\n"; 43481ad6265SDimitry Andric 43581ad6265SDimitry Andric OS << "#ifdef DXIL_OP_OPERATION_TABLE\n"; 43681ad6265SDimitry Andric emitDXILOperationTable(DXILOps, OS); 43781ad6265SDimitry Andric OS << "#endif\n\n"; 43881ad6265SDimitry Andric 43981ad6265SDimitry Andric OS << "\n"; 44081ad6265SDimitry Andric } 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric } // namespace llvm 443