1*81ad6265SDimitry Andric //===- DXILEmitter.cpp - DXIL operation Emitter ---------------------------===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // DXILEmitter uses the descriptions of DXIL operation to construct enum and 10*81ad6265SDimitry Andric // helper functions for DXIL operation. 11*81ad6265SDimitry Andric // 12*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 13*81ad6265SDimitry Andric 14*81ad6265SDimitry Andric #include "SequenceToOffsetTable.h" 15*81ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 16*81ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 17*81ad6265SDimitry Andric #include "llvm/ADT/StringSet.h" 18*81ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 19*81ad6265SDimitry Andric #include "llvm/TableGen/Error.h" 20*81ad6265SDimitry Andric #include "llvm/TableGen/Record.h" 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric using namespace llvm; 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric namespace { 25*81ad6265SDimitry Andric 26*81ad6265SDimitry Andric struct DXILShaderModel { 27*81ad6265SDimitry Andric int Major; 28*81ad6265SDimitry Andric int Minor; 29*81ad6265SDimitry Andric }; 30*81ad6265SDimitry Andric struct DXILParam { 31*81ad6265SDimitry Andric int Pos; // position in parameter list 32*81ad6265SDimitry Andric StringRef Type; // llvm type name, $o for overload, $r for resource 33*81ad6265SDimitry Andric // type, $cb for legacy cbuffer, $u4 for u4 struct 34*81ad6265SDimitry Andric StringRef Name; // short, unique name 35*81ad6265SDimitry Andric StringRef Doc; // the documentation description of this parameter 36*81ad6265SDimitry Andric bool IsConst; // whether this argument requires a constant value in the IR 37*81ad6265SDimitry Andric StringRef EnumName; // the name of the enum type if applicable 38*81ad6265SDimitry Andric int MaxValue; // the maximum value for this parameter if applicable 39*81ad6265SDimitry Andric DXILParam(const Record *R) { 40*81ad6265SDimitry Andric Name = R->getValueAsString("name"); 41*81ad6265SDimitry Andric Pos = R->getValueAsInt("pos"); 42*81ad6265SDimitry Andric Type = R->getValueAsString("llvm_type"); 43*81ad6265SDimitry Andric if (R->getValue("doc")) 44*81ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 45*81ad6265SDimitry Andric IsConst = R->getValueAsBit("is_const"); 46*81ad6265SDimitry Andric EnumName = R->getValueAsString("enum_name"); 47*81ad6265SDimitry Andric MaxValue = R->getValueAsInt("max_value"); 48*81ad6265SDimitry Andric } 49*81ad6265SDimitry Andric }; 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric struct DXILOperationData { 52*81ad6265SDimitry Andric StringRef Name; // short, unique name 53*81ad6265SDimitry Andric 54*81ad6265SDimitry Andric StringRef DXILOp; // name of DXIL operation 55*81ad6265SDimitry Andric int DXILOpID; // ID of DXIL operation 56*81ad6265SDimitry Andric StringRef DXILClass; // name of the opcode class 57*81ad6265SDimitry Andric StringRef Category; // classification for this instruction 58*81ad6265SDimitry Andric StringRef Doc; // the documentation description of this instruction 59*81ad6265SDimitry Andric 60*81ad6265SDimitry Andric SmallVector<DXILParam> Params; // the operands that this instruction takes 61*81ad6265SDimitry Andric StringRef OverloadTypes; // overload types if applicable 62*81ad6265SDimitry Andric StringRef FnAttr; // attribute shorthands: rn=does not access 63*81ad6265SDimitry Andric // memory,ro=only reads from memory 64*81ad6265SDimitry Andric StringRef Intrinsic; // The llvm intrinsic map to DXILOp. Default is "" which 65*81ad6265SDimitry Andric // means no map exist 66*81ad6265SDimitry Andric bool IsDeriv; // whether this is some kind of derivative 67*81ad6265SDimitry Andric bool IsGradient; // whether this requires a gradient calculation 68*81ad6265SDimitry Andric bool IsFeedback; // whether this is a sampler feedback op 69*81ad6265SDimitry Andric bool IsWave; // whether this requires in-wave, cross-lane functionality 70*81ad6265SDimitry Andric bool RequiresUniformInputs; // whether this operation requires that all 71*81ad6265SDimitry Andric // of its inputs are uniform across the wave 72*81ad6265SDimitry Andric SmallVector<StringRef, 4> 73*81ad6265SDimitry Andric ShaderStages; // shader stages to which this applies, empty for all. 74*81ad6265SDimitry Andric DXILShaderModel ShaderModel; // minimum shader model required 75*81ad6265SDimitry Andric DXILShaderModel ShaderModelTranslated; // minimum shader model required with 76*81ad6265SDimitry Andric // translation by linker 77*81ad6265SDimitry Andric SmallVector<StringRef, 4> counters; // counters for this inst. 78*81ad6265SDimitry Andric DXILOperationData(const Record *R) { 79*81ad6265SDimitry Andric Name = R->getValueAsString("name"); 80*81ad6265SDimitry Andric DXILOp = R->getValueAsString("dxil_op"); 81*81ad6265SDimitry Andric DXILOpID = R->getValueAsInt("dxil_opid"); 82*81ad6265SDimitry Andric DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); 83*81ad6265SDimitry Andric Category = R->getValueAsDef("category")->getValueAsString("name"); 84*81ad6265SDimitry Andric 85*81ad6265SDimitry Andric if (R->getValue("llvm_intrinsic")) { 86*81ad6265SDimitry Andric auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); 87*81ad6265SDimitry Andric auto DefName = IntrinsicDef->getName(); 88*81ad6265SDimitry Andric assert(DefName.startswith("int_") && "invalid intrinsic name"); 89*81ad6265SDimitry Andric // Remove the int_ from intrinsic name. 90*81ad6265SDimitry Andric Intrinsic = DefName.substr(4); 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric 93*81ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric ListInit *ParamList = R->getValueAsListInit("ops"); 96*81ad6265SDimitry Andric for (unsigned i = 0; i < ParamList->size(); ++i) { 97*81ad6265SDimitry Andric Record *Param = ParamList->getElementAsRecord(i); 98*81ad6265SDimitry Andric Params.emplace_back(DXILParam(Param)); 99*81ad6265SDimitry Andric } 100*81ad6265SDimitry Andric OverloadTypes = R->getValueAsString("oload_types"); 101*81ad6265SDimitry Andric FnAttr = R->getValueAsString("fn_attr"); 102*81ad6265SDimitry Andric } 103*81ad6265SDimitry Andric }; 104*81ad6265SDimitry Andric } // end anonymous namespace 105*81ad6265SDimitry Andric 106*81ad6265SDimitry Andric static void emitDXILOpEnum(DXILOperationData &DXILOp, raw_ostream &OS) { 107*81ad6265SDimitry Andric // Name = ID, // Doc 108*81ad6265SDimitry Andric OS << DXILOp.Name << " = " << DXILOp.DXILOpID << ", // " << DXILOp.Doc 109*81ad6265SDimitry Andric << "\n"; 110*81ad6265SDimitry Andric } 111*81ad6265SDimitry Andric 112*81ad6265SDimitry Andric static std::string buildCategoryStr(StringSet<> &Cetegorys) { 113*81ad6265SDimitry Andric std::string Str; 114*81ad6265SDimitry Andric raw_string_ostream OS(Str); 115*81ad6265SDimitry Andric for (auto &It : Cetegorys) { 116*81ad6265SDimitry Andric OS << " " << It.getKey(); 117*81ad6265SDimitry Andric } 118*81ad6265SDimitry Andric return OS.str(); 119*81ad6265SDimitry Andric } 120*81ad6265SDimitry Andric 121*81ad6265SDimitry Andric // Emit enum declaration for DXIL. 122*81ad6265SDimitry Andric static void emitDXILEnums(std::vector<DXILOperationData> &DXILOps, 123*81ad6265SDimitry Andric raw_ostream &OS) { 124*81ad6265SDimitry Andric // Sort by Category + OpName. 125*81ad6265SDimitry Andric std::sort(DXILOps.begin(), DXILOps.end(), 126*81ad6265SDimitry Andric [](DXILOperationData &A, DXILOperationData &B) { 127*81ad6265SDimitry Andric // Group by Category first. 128*81ad6265SDimitry Andric if (A.Category == B.Category) 129*81ad6265SDimitry Andric // Inside same Category, order by OpName. 130*81ad6265SDimitry Andric return A.DXILOp < B.DXILOp; 131*81ad6265SDimitry Andric else 132*81ad6265SDimitry Andric return A.Category < B.Category; 133*81ad6265SDimitry Andric }); 134*81ad6265SDimitry Andric 135*81ad6265SDimitry Andric OS << "// Enumeration for operations specified by DXIL\n"; 136*81ad6265SDimitry Andric OS << "enum class OpCode : unsigned {\n"; 137*81ad6265SDimitry Andric 138*81ad6265SDimitry Andric StringMap<StringSet<>> ClassMap; 139*81ad6265SDimitry Andric StringRef PrevCategory = ""; 140*81ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 141*81ad6265SDimitry Andric StringRef Category = DXILOp.Category; 142*81ad6265SDimitry Andric if (Category != PrevCategory) { 143*81ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 144*81ad6265SDimitry Andric PrevCategory = Category; 145*81ad6265SDimitry Andric } 146*81ad6265SDimitry Andric emitDXILOpEnum(DXILOp, OS); 147*81ad6265SDimitry Andric auto It = ClassMap.find(DXILOp.DXILClass); 148*81ad6265SDimitry Andric if (It != ClassMap.end()) { 149*81ad6265SDimitry Andric It->second.insert(DXILOp.Category); 150*81ad6265SDimitry Andric } else { 151*81ad6265SDimitry Andric ClassMap[DXILOp.DXILClass].insert(DXILOp.Category); 152*81ad6265SDimitry Andric } 153*81ad6265SDimitry Andric } 154*81ad6265SDimitry Andric 155*81ad6265SDimitry Andric OS << "\n};\n\n"; 156*81ad6265SDimitry Andric 157*81ad6265SDimitry Andric std::vector<std::pair<std::string, std::string>> ClassVec; 158*81ad6265SDimitry Andric for (auto &It : ClassMap) { 159*81ad6265SDimitry Andric ClassVec.emplace_back( 160*81ad6265SDimitry Andric std::make_pair(It.getKey().str(), buildCategoryStr(It.second))); 161*81ad6265SDimitry Andric } 162*81ad6265SDimitry Andric // Sort by Category + ClassName. 163*81ad6265SDimitry Andric std::sort(ClassVec.begin(), ClassVec.end(), 164*81ad6265SDimitry Andric [](std::pair<std::string, std::string> &A, 165*81ad6265SDimitry Andric std::pair<std::string, std::string> &B) { 166*81ad6265SDimitry Andric StringRef ClassA = A.first; 167*81ad6265SDimitry Andric StringRef CategoryA = A.second; 168*81ad6265SDimitry Andric StringRef ClassB = B.first; 169*81ad6265SDimitry Andric StringRef CategoryB = B.second; 170*81ad6265SDimitry Andric // Group by Category first. 171*81ad6265SDimitry Andric if (CategoryA == CategoryB) 172*81ad6265SDimitry Andric // Inside same Category, order by ClassName. 173*81ad6265SDimitry Andric return ClassA < ClassB; 174*81ad6265SDimitry Andric else 175*81ad6265SDimitry Andric return CategoryA < CategoryB; 176*81ad6265SDimitry Andric }); 177*81ad6265SDimitry Andric 178*81ad6265SDimitry Andric OS << "// Groups for DXIL operations with equivalent function templates\n"; 179*81ad6265SDimitry Andric OS << "enum class OpCodeClass : unsigned {\n"; 180*81ad6265SDimitry Andric PrevCategory = ""; 181*81ad6265SDimitry Andric for (auto &It : ClassVec) { 182*81ad6265SDimitry Andric 183*81ad6265SDimitry Andric StringRef Category = It.second; 184*81ad6265SDimitry Andric if (Category != PrevCategory) { 185*81ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 186*81ad6265SDimitry Andric PrevCategory = Category; 187*81ad6265SDimitry Andric } 188*81ad6265SDimitry Andric StringRef Name = It.first; 189*81ad6265SDimitry Andric OS << Name << ",\n"; 190*81ad6265SDimitry Andric } 191*81ad6265SDimitry Andric OS << "\n};\n\n"; 192*81ad6265SDimitry Andric } 193*81ad6265SDimitry Andric 194*81ad6265SDimitry Andric // Emit map from llvm intrinsic to DXIL operation. 195*81ad6265SDimitry Andric static void emitDXILIntrinsicMap(std::vector<DXILOperationData> &DXILOps, 196*81ad6265SDimitry Andric raw_ostream &OS) { 197*81ad6265SDimitry Andric OS << "\n"; 198*81ad6265SDimitry Andric // FIXME: use array instead of SmallDenseMap. 199*81ad6265SDimitry Andric OS << "static const SmallDenseMap<Intrinsic::ID, DXIL::OpCode> LowerMap = " 200*81ad6265SDimitry Andric "{\n"; 201*81ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 202*81ad6265SDimitry Andric if (DXILOp.Intrinsic.empty()) 203*81ad6265SDimitry Andric continue; 204*81ad6265SDimitry Andric // {Intrinsic::sin, DXIL::OpCode::Sin}, 205*81ad6265SDimitry Andric OS << " { Intrinsic::" << DXILOp.Intrinsic 206*81ad6265SDimitry Andric << ", DXIL::OpCode::" << DXILOp.DXILOp << "},\n"; 207*81ad6265SDimitry Andric } 208*81ad6265SDimitry Andric OS << "};\n"; 209*81ad6265SDimitry Andric OS << "\n"; 210*81ad6265SDimitry Andric } 211*81ad6265SDimitry Andric 212*81ad6265SDimitry Andric static std::string emitDXILOperationFnAttr(StringRef FnAttr) { 213*81ad6265SDimitry Andric return StringSwitch<std::string>(FnAttr) 214*81ad6265SDimitry Andric .Case("rn", "Attribute::ReadNone") 215*81ad6265SDimitry Andric .Case("ro", "Attribute::ReadOnly") 216*81ad6265SDimitry Andric .Default("Attribute::None"); 217*81ad6265SDimitry Andric } 218*81ad6265SDimitry Andric 219*81ad6265SDimitry Andric static std::string getOverloadKind(StringRef Overload) { 220*81ad6265SDimitry Andric return StringSwitch<std::string>(Overload) 221*81ad6265SDimitry Andric .Case("half", "OverloadKind::HALF") 222*81ad6265SDimitry Andric .Case("float", "OverloadKind::FLOAT") 223*81ad6265SDimitry Andric .Case("double", "OverloadKind::DOUBLE") 224*81ad6265SDimitry Andric .Case("i1", "OverloadKind::I1") 225*81ad6265SDimitry Andric .Case("i16", "OverloadKind::I16") 226*81ad6265SDimitry Andric .Case("i32", "OverloadKind::I32") 227*81ad6265SDimitry Andric .Case("i64", "OverloadKind::I64") 228*81ad6265SDimitry Andric .Case("udt", "OverloadKind::UserDefineType") 229*81ad6265SDimitry Andric .Case("obj", "OverloadKind::ObjectType") 230*81ad6265SDimitry Andric .Default("OverloadKind::VOID"); 231*81ad6265SDimitry Andric } 232*81ad6265SDimitry Andric 233*81ad6265SDimitry Andric static std::string getDXILOperationOverload(StringRef Overloads) { 234*81ad6265SDimitry Andric SmallVector<StringRef> OverloadStrs; 235*81ad6265SDimitry Andric Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false); 236*81ad6265SDimitry Andric // Format is: OverloadKind::FLOAT | OverloadKind::HALF 237*81ad6265SDimitry Andric assert(!OverloadStrs.empty() && "Invalid overloads"); 238*81ad6265SDimitry Andric auto It = OverloadStrs.begin(); 239*81ad6265SDimitry Andric std::string Result; 240*81ad6265SDimitry Andric raw_string_ostream OS(Result); 241*81ad6265SDimitry Andric OS << getOverloadKind(*It); 242*81ad6265SDimitry Andric for (++It; It != OverloadStrs.end(); ++It) { 243*81ad6265SDimitry Andric OS << " | " << getOverloadKind(*It); 244*81ad6265SDimitry Andric } 245*81ad6265SDimitry Andric return OS.str(); 246*81ad6265SDimitry Andric } 247*81ad6265SDimitry Andric 248*81ad6265SDimitry Andric static std::string lowerFirstLetter(StringRef Name) { 249*81ad6265SDimitry Andric if (Name.empty()) 250*81ad6265SDimitry Andric return ""; 251*81ad6265SDimitry Andric 252*81ad6265SDimitry Andric std::string LowerName = Name.str(); 253*81ad6265SDimitry Andric LowerName[0] = llvm::toLower(Name[0]); 254*81ad6265SDimitry Andric return LowerName; 255*81ad6265SDimitry Andric } 256*81ad6265SDimitry Andric 257*81ad6265SDimitry Andric static std::string getDXILOpClassName(StringRef DXILOpClass) { 258*81ad6265SDimitry Andric // Lower first letter expect for special case. 259*81ad6265SDimitry Andric return StringSwitch<std::string>(DXILOpClass) 260*81ad6265SDimitry Andric .Case("CBufferLoad", "cbufferLoad") 261*81ad6265SDimitry Andric .Case("CBufferLoadLegacy", "cbufferLoadLegacy") 262*81ad6265SDimitry Andric .Case("GSInstanceID", "gsInstanceID") 263*81ad6265SDimitry Andric .Default(lowerFirstLetter(DXILOpClass)); 264*81ad6265SDimitry Andric } 265*81ad6265SDimitry Andric 266*81ad6265SDimitry Andric static void emitDXILOperationTable(std::vector<DXILOperationData> &DXILOps, 267*81ad6265SDimitry Andric raw_ostream &OS) { 268*81ad6265SDimitry Andric // Sort by DXILOpID. 269*81ad6265SDimitry Andric std::sort(DXILOps.begin(), DXILOps.end(), 270*81ad6265SDimitry Andric [](DXILOperationData &A, DXILOperationData &B) { 271*81ad6265SDimitry Andric return A.DXILOpID < B.DXILOpID; 272*81ad6265SDimitry Andric }); 273*81ad6265SDimitry Andric 274*81ad6265SDimitry Andric // Collect Names. 275*81ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpClassStrings; 276*81ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpStrings; 277*81ad6265SDimitry Andric 278*81ad6265SDimitry Andric StringSet<> ClassSet; 279*81ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 280*81ad6265SDimitry Andric OpStrings.add(DXILOp.DXILOp.str()); 281*81ad6265SDimitry Andric 282*81ad6265SDimitry Andric if (ClassSet.find(DXILOp.DXILClass) != ClassSet.end()) 283*81ad6265SDimitry Andric continue; 284*81ad6265SDimitry Andric ClassSet.insert(DXILOp.DXILClass); 285*81ad6265SDimitry Andric OpClassStrings.add(getDXILOpClassName(DXILOp.DXILClass)); 286*81ad6265SDimitry Andric } 287*81ad6265SDimitry Andric 288*81ad6265SDimitry Andric // Layout names. 289*81ad6265SDimitry Andric OpStrings.layout(); 290*81ad6265SDimitry Andric OpClassStrings.layout(); 291*81ad6265SDimitry Andric 292*81ad6265SDimitry Andric // Emit the DXIL operation table. 293*81ad6265SDimitry Andric //{DXIL::OpCode::Sin, OpCodeNameIndex, OpCodeClass::Unary, 294*81ad6265SDimitry Andric // OpCodeClassNameIndex, 295*81ad6265SDimitry Andric // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone}, 296*81ad6265SDimitry Andric OS << "static const OpCodeProperty *getOpCodeProperty(DXIL::OpCode DXILOp) " 297*81ad6265SDimitry Andric "{\n"; 298*81ad6265SDimitry Andric 299*81ad6265SDimitry Andric OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 300*81ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 301*81ad6265SDimitry Andric OS << " { DXIL::OpCode::" << DXILOp.DXILOp << ", " 302*81ad6265SDimitry Andric << OpStrings.get(DXILOp.DXILOp.str()) 303*81ad6265SDimitry Andric << ", OpCodeClass::" << DXILOp.DXILClass << ", " 304*81ad6265SDimitry Andric << OpClassStrings.get(getDXILOpClassName(DXILOp.DXILClass)) << ", " 305*81ad6265SDimitry Andric << getDXILOperationOverload(DXILOp.OverloadTypes) << ", " 306*81ad6265SDimitry Andric << emitDXILOperationFnAttr(DXILOp.FnAttr) << " },\n"; 307*81ad6265SDimitry Andric } 308*81ad6265SDimitry Andric OS << " };\n"; 309*81ad6265SDimitry Andric 310*81ad6265SDimitry Andric OS << " // FIXME: change search to indexing with\n"; 311*81ad6265SDimitry Andric OS << " // DXILOp once all DXIL op is added.\n"; 312*81ad6265SDimitry Andric OS << " OpCodeProperty TmpProp;\n"; 313*81ad6265SDimitry Andric OS << " TmpProp.OpCode = DXILOp;\n"; 314*81ad6265SDimitry Andric OS << " const OpCodeProperty *Prop =\n"; 315*81ad6265SDimitry Andric OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 316*81ad6265SDimitry Andric OS << " [](const OpCodeProperty &A, const " 317*81ad6265SDimitry Andric "OpCodeProperty &B) {\n"; 318*81ad6265SDimitry Andric OS << " return A.OpCode < B.OpCode;\n"; 319*81ad6265SDimitry Andric OS << " });\n"; 320*81ad6265SDimitry Andric OS << " assert(Prop && \"fail to find OpCodeProperty\");\n"; 321*81ad6265SDimitry Andric OS << " return Prop;\n"; 322*81ad6265SDimitry Andric OS << "}\n\n"; 323*81ad6265SDimitry Andric 324*81ad6265SDimitry Andric // Emit the string tables. 325*81ad6265SDimitry Andric OS << "static const char *getOpCodeName(DXIL::OpCode DXILOp) {\n\n"; 326*81ad6265SDimitry Andric 327*81ad6265SDimitry Andric OpStrings.emitStringLiteralDef(OS, 328*81ad6265SDimitry Andric " static const char DXILOpCodeNameTable[]"); 329*81ad6265SDimitry Andric 330*81ad6265SDimitry Andric OS << " auto *Prop = getOpCodeProperty(DXILOp);\n"; 331*81ad6265SDimitry Andric OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 332*81ad6265SDimitry Andric OS << " return DXILOpCodeNameTable + Index;\n"; 333*81ad6265SDimitry Andric OS << "}\n\n"; 334*81ad6265SDimitry Andric 335*81ad6265SDimitry Andric OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 336*81ad6265SDimitry Andric "{\n\n"; 337*81ad6265SDimitry Andric 338*81ad6265SDimitry Andric OpClassStrings.emitStringLiteralDef( 339*81ad6265SDimitry Andric OS, " static const char DXILOpCodeClassNameTable[]"); 340*81ad6265SDimitry Andric 341*81ad6265SDimitry Andric OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 342*81ad6265SDimitry Andric OS << " return DXILOpCodeClassNameTable + Index;\n"; 343*81ad6265SDimitry Andric OS << "}\n "; 344*81ad6265SDimitry Andric } 345*81ad6265SDimitry Andric 346*81ad6265SDimitry Andric namespace llvm { 347*81ad6265SDimitry Andric 348*81ad6265SDimitry Andric void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { 349*81ad6265SDimitry Andric std::vector<Record *> Ops = Records.getAllDerivedDefinitions("dxil_op"); 350*81ad6265SDimitry Andric OS << "// Generated code, do not edit.\n"; 351*81ad6265SDimitry Andric OS << "\n"; 352*81ad6265SDimitry Andric 353*81ad6265SDimitry Andric std::vector<DXILOperationData> DXILOps; 354*81ad6265SDimitry Andric DXILOps.reserve(Ops.size()); 355*81ad6265SDimitry Andric for (auto *Record : Ops) { 356*81ad6265SDimitry Andric DXILOps.emplace_back(DXILOperationData(Record)); 357*81ad6265SDimitry Andric } 358*81ad6265SDimitry Andric 359*81ad6265SDimitry Andric OS << "#ifdef DXIL_OP_ENUM\n"; 360*81ad6265SDimitry Andric emitDXILEnums(DXILOps, OS); 361*81ad6265SDimitry Andric OS << "#endif\n\n"; 362*81ad6265SDimitry Andric 363*81ad6265SDimitry Andric OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; 364*81ad6265SDimitry Andric emitDXILIntrinsicMap(DXILOps, OS); 365*81ad6265SDimitry Andric OS << "#endif\n\n"; 366*81ad6265SDimitry Andric 367*81ad6265SDimitry Andric OS << "#ifdef DXIL_OP_OPERATION_TABLE\n"; 368*81ad6265SDimitry Andric emitDXILOperationTable(DXILOps, OS); 369*81ad6265SDimitry Andric OS << "#endif\n\n"; 370*81ad6265SDimitry Andric 371*81ad6265SDimitry Andric OS << "\n"; 372*81ad6265SDimitry Andric } 373*81ad6265SDimitry Andric 374*81ad6265SDimitry Andric } // namespace llvm 375