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" 1981ad6265SDimitry Andric #include "llvm/TableGen/Error.h" 2081ad6265SDimitry Andric #include "llvm/TableGen/Record.h" 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric using namespace llvm; 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric namespace { 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric struct DXILShaderModel { 2781ad6265SDimitry Andric int Major; 2881ad6265SDimitry Andric int Minor; 2981ad6265SDimitry Andric }; 3081ad6265SDimitry Andric struct DXILParam { 3181ad6265SDimitry Andric int Pos; // position in parameter list 3281ad6265SDimitry Andric StringRef Type; // llvm type name, $o for overload, $r for resource 3381ad6265SDimitry Andric // type, $cb for legacy cbuffer, $u4 for u4 struct 3481ad6265SDimitry Andric StringRef Name; // short, unique name 3581ad6265SDimitry Andric StringRef Doc; // the documentation description of this parameter 3681ad6265SDimitry Andric bool IsConst; // whether this argument requires a constant value in the IR 3781ad6265SDimitry Andric StringRef EnumName; // the name of the enum type if applicable 3881ad6265SDimitry Andric int MaxValue; // the maximum value for this parameter if applicable 3981ad6265SDimitry Andric DXILParam(const Record *R) { 4081ad6265SDimitry Andric Name = R->getValueAsString("name"); 4181ad6265SDimitry Andric Pos = R->getValueAsInt("pos"); 4281ad6265SDimitry Andric Type = R->getValueAsString("llvm_type"); 4381ad6265SDimitry Andric if (R->getValue("doc")) 4481ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 4581ad6265SDimitry Andric IsConst = R->getValueAsBit("is_const"); 4681ad6265SDimitry Andric EnumName = R->getValueAsString("enum_name"); 4781ad6265SDimitry Andric MaxValue = R->getValueAsInt("max_value"); 4881ad6265SDimitry Andric } 4981ad6265SDimitry Andric }; 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric struct DXILOperationData { 5281ad6265SDimitry Andric StringRef Name; // short, unique name 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric StringRef DXILOp; // name of DXIL operation 5581ad6265SDimitry Andric int DXILOpID; // ID of DXIL operation 5681ad6265SDimitry Andric StringRef DXILClass; // name of the opcode class 5781ad6265SDimitry Andric StringRef Category; // classification for this instruction 5881ad6265SDimitry Andric StringRef Doc; // the documentation description of this instruction 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric SmallVector<DXILParam> Params; // the operands that this instruction takes 6181ad6265SDimitry Andric StringRef OverloadTypes; // overload types if applicable 6281ad6265SDimitry Andric StringRef FnAttr; // attribute shorthands: rn=does not access 6381ad6265SDimitry Andric // memory,ro=only reads from memory 6481ad6265SDimitry Andric StringRef Intrinsic; // The llvm intrinsic map to DXILOp. Default is "" which 6581ad6265SDimitry Andric // means no map exist 6681ad6265SDimitry Andric bool IsDeriv; // whether this is some kind of derivative 6781ad6265SDimitry Andric bool IsGradient; // whether this requires a gradient calculation 6881ad6265SDimitry Andric bool IsFeedback; // whether this is a sampler feedback op 6981ad6265SDimitry Andric bool IsWave; // whether this requires in-wave, cross-lane functionality 7081ad6265SDimitry Andric bool RequiresUniformInputs; // whether this operation requires that all 7181ad6265SDimitry Andric // of its inputs are uniform across the wave 7281ad6265SDimitry Andric SmallVector<StringRef, 4> 7381ad6265SDimitry Andric ShaderStages; // shader stages to which this applies, empty for all. 7481ad6265SDimitry Andric DXILShaderModel ShaderModel; // minimum shader model required 7581ad6265SDimitry Andric DXILShaderModel ShaderModelTranslated; // minimum shader model required with 7681ad6265SDimitry Andric // translation by linker 7781ad6265SDimitry Andric SmallVector<StringRef, 4> counters; // counters for this inst. 7881ad6265SDimitry Andric DXILOperationData(const Record *R) { 7981ad6265SDimitry Andric Name = R->getValueAsString("name"); 8081ad6265SDimitry Andric DXILOp = R->getValueAsString("dxil_op"); 8181ad6265SDimitry Andric DXILOpID = R->getValueAsInt("dxil_opid"); 8281ad6265SDimitry Andric DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); 8381ad6265SDimitry Andric Category = R->getValueAsDef("category")->getValueAsString("name"); 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric if (R->getValue("llvm_intrinsic")) { 8681ad6265SDimitry Andric auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); 8781ad6265SDimitry Andric auto DefName = IntrinsicDef->getName(); 8881ad6265SDimitry Andric assert(DefName.startswith("int_") && "invalid intrinsic name"); 8981ad6265SDimitry Andric // Remove the int_ from intrinsic name. 9081ad6265SDimitry Andric Intrinsic = DefName.substr(4); 9181ad6265SDimitry Andric } 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric Doc = R->getValueAsString("doc"); 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric ListInit *ParamList = R->getValueAsListInit("ops"); 9681ad6265SDimitry Andric for (unsigned i = 0; i < ParamList->size(); ++i) { 9781ad6265SDimitry Andric Record *Param = ParamList->getElementAsRecord(i); 9881ad6265SDimitry Andric Params.emplace_back(DXILParam(Param)); 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 10681ad6265SDimitry Andric static void emitDXILOpEnum(DXILOperationData &DXILOp, raw_ostream &OS) { 10781ad6265SDimitry Andric // Name = ID, // Doc 10881ad6265SDimitry Andric OS << DXILOp.Name << " = " << DXILOp.DXILOpID << ", // " << DXILOp.Doc 10981ad6265SDimitry Andric << "\n"; 11081ad6265SDimitry Andric } 11181ad6265SDimitry Andric 11281ad6265SDimitry Andric static std::string buildCategoryStr(StringSet<> &Cetegorys) { 11381ad6265SDimitry Andric std::string Str; 11481ad6265SDimitry Andric raw_string_ostream OS(Str); 11581ad6265SDimitry Andric for (auto &It : Cetegorys) { 11681ad6265SDimitry Andric OS << " " << It.getKey(); 11781ad6265SDimitry Andric } 11881ad6265SDimitry Andric return OS.str(); 11981ad6265SDimitry Andric } 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric // Emit enum declaration for DXIL. 12281ad6265SDimitry Andric static void emitDXILEnums(std::vector<DXILOperationData> &DXILOps, 12381ad6265SDimitry Andric raw_ostream &OS) { 12481ad6265SDimitry Andric // Sort by Category + OpName. 125*fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 12681ad6265SDimitry Andric // Group by Category first. 12781ad6265SDimitry Andric if (A.Category == B.Category) 12881ad6265SDimitry Andric // Inside same Category, order by OpName. 12981ad6265SDimitry Andric return A.DXILOp < B.DXILOp; 13081ad6265SDimitry Andric else 13181ad6265SDimitry Andric return A.Category < B.Category; 13281ad6265SDimitry Andric }); 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric OS << "// Enumeration for operations specified by DXIL\n"; 13581ad6265SDimitry Andric OS << "enum class OpCode : unsigned {\n"; 13681ad6265SDimitry Andric 13781ad6265SDimitry Andric StringMap<StringSet<>> ClassMap; 13881ad6265SDimitry Andric StringRef PrevCategory = ""; 13981ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 14081ad6265SDimitry Andric StringRef Category = DXILOp.Category; 14181ad6265SDimitry Andric if (Category != PrevCategory) { 14281ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 14381ad6265SDimitry Andric PrevCategory = Category; 14481ad6265SDimitry Andric } 14581ad6265SDimitry Andric emitDXILOpEnum(DXILOp, OS); 14681ad6265SDimitry Andric auto It = ClassMap.find(DXILOp.DXILClass); 14781ad6265SDimitry Andric if (It != ClassMap.end()) { 14881ad6265SDimitry Andric It->second.insert(DXILOp.Category); 14981ad6265SDimitry Andric } else { 15081ad6265SDimitry Andric ClassMap[DXILOp.DXILClass].insert(DXILOp.Category); 15181ad6265SDimitry Andric } 15281ad6265SDimitry Andric } 15381ad6265SDimitry Andric 15481ad6265SDimitry Andric OS << "\n};\n\n"; 15581ad6265SDimitry Andric 15681ad6265SDimitry Andric std::vector<std::pair<std::string, std::string>> ClassVec; 15781ad6265SDimitry Andric for (auto &It : ClassMap) { 15881ad6265SDimitry Andric ClassVec.emplace_back( 15981ad6265SDimitry Andric std::make_pair(It.getKey().str(), buildCategoryStr(It.second))); 16081ad6265SDimitry Andric } 16181ad6265SDimitry Andric // Sort by Category + ClassName. 162*fcaf7f86SDimitry Andric llvm::sort(ClassVec, [](std::pair<std::string, std::string> &A, 16381ad6265SDimitry Andric std::pair<std::string, std::string> &B) { 16481ad6265SDimitry Andric StringRef ClassA = A.first; 16581ad6265SDimitry Andric StringRef CategoryA = A.second; 16681ad6265SDimitry Andric StringRef ClassB = B.first; 16781ad6265SDimitry Andric StringRef CategoryB = B.second; 16881ad6265SDimitry Andric // Group by Category first. 16981ad6265SDimitry Andric if (CategoryA == CategoryB) 17081ad6265SDimitry Andric // Inside same Category, order by ClassName. 17181ad6265SDimitry Andric return ClassA < ClassB; 17281ad6265SDimitry Andric else 17381ad6265SDimitry Andric return CategoryA < CategoryB; 17481ad6265SDimitry Andric }); 17581ad6265SDimitry Andric 17681ad6265SDimitry Andric OS << "// Groups for DXIL operations with equivalent function templates\n"; 17781ad6265SDimitry Andric OS << "enum class OpCodeClass : unsigned {\n"; 17881ad6265SDimitry Andric PrevCategory = ""; 17981ad6265SDimitry Andric for (auto &It : ClassVec) { 18081ad6265SDimitry Andric 18181ad6265SDimitry Andric StringRef Category = It.second; 18281ad6265SDimitry Andric if (Category != PrevCategory) { 18381ad6265SDimitry Andric OS << "\n// " << Category << "\n"; 18481ad6265SDimitry Andric PrevCategory = Category; 18581ad6265SDimitry Andric } 18681ad6265SDimitry Andric StringRef Name = It.first; 18781ad6265SDimitry Andric OS << Name << ",\n"; 18881ad6265SDimitry Andric } 18981ad6265SDimitry Andric OS << "\n};\n\n"; 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric 19281ad6265SDimitry Andric // Emit map from llvm intrinsic to DXIL operation. 19381ad6265SDimitry Andric static void emitDXILIntrinsicMap(std::vector<DXILOperationData> &DXILOps, 19481ad6265SDimitry Andric raw_ostream &OS) { 19581ad6265SDimitry Andric OS << "\n"; 19681ad6265SDimitry Andric // FIXME: use array instead of SmallDenseMap. 19781ad6265SDimitry Andric OS << "static const SmallDenseMap<Intrinsic::ID, DXIL::OpCode> LowerMap = " 19881ad6265SDimitry Andric "{\n"; 19981ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 20081ad6265SDimitry Andric if (DXILOp.Intrinsic.empty()) 20181ad6265SDimitry Andric continue; 20281ad6265SDimitry Andric // {Intrinsic::sin, DXIL::OpCode::Sin}, 20381ad6265SDimitry Andric OS << " { Intrinsic::" << DXILOp.Intrinsic 20481ad6265SDimitry Andric << ", DXIL::OpCode::" << DXILOp.DXILOp << "},\n"; 20581ad6265SDimitry Andric } 20681ad6265SDimitry Andric OS << "};\n"; 20781ad6265SDimitry Andric OS << "\n"; 20881ad6265SDimitry Andric } 20981ad6265SDimitry Andric 21081ad6265SDimitry Andric static std::string emitDXILOperationFnAttr(StringRef FnAttr) { 21181ad6265SDimitry Andric return StringSwitch<std::string>(FnAttr) 21281ad6265SDimitry Andric .Case("rn", "Attribute::ReadNone") 21381ad6265SDimitry Andric .Case("ro", "Attribute::ReadOnly") 21481ad6265SDimitry Andric .Default("Attribute::None"); 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric 21781ad6265SDimitry Andric static std::string getOverloadKind(StringRef Overload) { 21881ad6265SDimitry Andric return StringSwitch<std::string>(Overload) 21981ad6265SDimitry Andric .Case("half", "OverloadKind::HALF") 22081ad6265SDimitry Andric .Case("float", "OverloadKind::FLOAT") 22181ad6265SDimitry Andric .Case("double", "OverloadKind::DOUBLE") 22281ad6265SDimitry Andric .Case("i1", "OverloadKind::I1") 22381ad6265SDimitry Andric .Case("i16", "OverloadKind::I16") 22481ad6265SDimitry Andric .Case("i32", "OverloadKind::I32") 22581ad6265SDimitry Andric .Case("i64", "OverloadKind::I64") 22681ad6265SDimitry Andric .Case("udt", "OverloadKind::UserDefineType") 22781ad6265SDimitry Andric .Case("obj", "OverloadKind::ObjectType") 22881ad6265SDimitry Andric .Default("OverloadKind::VOID"); 22981ad6265SDimitry Andric } 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric static std::string getDXILOperationOverload(StringRef Overloads) { 23281ad6265SDimitry Andric SmallVector<StringRef> OverloadStrs; 23381ad6265SDimitry Andric Overloads.split(OverloadStrs, ';', /*MaxSplit*/ -1, /*KeepEmpty*/ false); 23481ad6265SDimitry Andric // Format is: OverloadKind::FLOAT | OverloadKind::HALF 23581ad6265SDimitry Andric assert(!OverloadStrs.empty() && "Invalid overloads"); 23681ad6265SDimitry Andric auto It = OverloadStrs.begin(); 23781ad6265SDimitry Andric std::string Result; 23881ad6265SDimitry Andric raw_string_ostream OS(Result); 23981ad6265SDimitry Andric OS << getOverloadKind(*It); 24081ad6265SDimitry Andric for (++It; It != OverloadStrs.end(); ++It) { 24181ad6265SDimitry Andric OS << " | " << getOverloadKind(*It); 24281ad6265SDimitry Andric } 24381ad6265SDimitry Andric return OS.str(); 24481ad6265SDimitry Andric } 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric static std::string lowerFirstLetter(StringRef Name) { 24781ad6265SDimitry Andric if (Name.empty()) 24881ad6265SDimitry Andric return ""; 24981ad6265SDimitry Andric 25081ad6265SDimitry Andric std::string LowerName = Name.str(); 25181ad6265SDimitry Andric LowerName[0] = llvm::toLower(Name[0]); 25281ad6265SDimitry Andric return LowerName; 25381ad6265SDimitry Andric } 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric static std::string getDXILOpClassName(StringRef DXILOpClass) { 25681ad6265SDimitry Andric // Lower first letter expect for special case. 25781ad6265SDimitry Andric return StringSwitch<std::string>(DXILOpClass) 25881ad6265SDimitry Andric .Case("CBufferLoad", "cbufferLoad") 25981ad6265SDimitry Andric .Case("CBufferLoadLegacy", "cbufferLoadLegacy") 26081ad6265SDimitry Andric .Case("GSInstanceID", "gsInstanceID") 26181ad6265SDimitry Andric .Default(lowerFirstLetter(DXILOpClass)); 26281ad6265SDimitry Andric } 26381ad6265SDimitry Andric 26481ad6265SDimitry Andric static void emitDXILOperationTable(std::vector<DXILOperationData> &DXILOps, 26581ad6265SDimitry Andric raw_ostream &OS) { 26681ad6265SDimitry Andric // Sort by DXILOpID. 267*fcaf7f86SDimitry Andric llvm::sort(DXILOps, [](DXILOperationData &A, DXILOperationData &B) { 26881ad6265SDimitry Andric return A.DXILOpID < B.DXILOpID; 26981ad6265SDimitry Andric }); 27081ad6265SDimitry Andric 27181ad6265SDimitry Andric // Collect Names. 27281ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpClassStrings; 27381ad6265SDimitry Andric SequenceToOffsetTable<std::string> OpStrings; 27481ad6265SDimitry Andric 27581ad6265SDimitry Andric StringSet<> ClassSet; 27681ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 27781ad6265SDimitry Andric OpStrings.add(DXILOp.DXILOp.str()); 27881ad6265SDimitry Andric 27981ad6265SDimitry Andric if (ClassSet.find(DXILOp.DXILClass) != ClassSet.end()) 28081ad6265SDimitry Andric continue; 28181ad6265SDimitry Andric ClassSet.insert(DXILOp.DXILClass); 28281ad6265SDimitry Andric OpClassStrings.add(getDXILOpClassName(DXILOp.DXILClass)); 28381ad6265SDimitry Andric } 28481ad6265SDimitry Andric 28581ad6265SDimitry Andric // Layout names. 28681ad6265SDimitry Andric OpStrings.layout(); 28781ad6265SDimitry Andric OpClassStrings.layout(); 28881ad6265SDimitry Andric 28981ad6265SDimitry Andric // Emit the DXIL operation table. 29081ad6265SDimitry Andric //{DXIL::OpCode::Sin, OpCodeNameIndex, OpCodeClass::Unary, 29181ad6265SDimitry Andric // OpCodeClassNameIndex, 29281ad6265SDimitry Andric // OverloadKind::FLOAT | OverloadKind::HALF, Attribute::AttrKind::ReadNone}, 29381ad6265SDimitry Andric OS << "static const OpCodeProperty *getOpCodeProperty(DXIL::OpCode DXILOp) " 29481ad6265SDimitry Andric "{\n"; 29581ad6265SDimitry Andric 29681ad6265SDimitry Andric OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 29781ad6265SDimitry Andric for (auto &DXILOp : DXILOps) { 29881ad6265SDimitry Andric OS << " { DXIL::OpCode::" << DXILOp.DXILOp << ", " 29981ad6265SDimitry Andric << OpStrings.get(DXILOp.DXILOp.str()) 30081ad6265SDimitry Andric << ", OpCodeClass::" << DXILOp.DXILClass << ", " 30181ad6265SDimitry Andric << OpClassStrings.get(getDXILOpClassName(DXILOp.DXILClass)) << ", " 30281ad6265SDimitry Andric << getDXILOperationOverload(DXILOp.OverloadTypes) << ", " 30381ad6265SDimitry Andric << emitDXILOperationFnAttr(DXILOp.FnAttr) << " },\n"; 30481ad6265SDimitry Andric } 30581ad6265SDimitry Andric OS << " };\n"; 30681ad6265SDimitry Andric 30781ad6265SDimitry Andric OS << " // FIXME: change search to indexing with\n"; 30881ad6265SDimitry Andric OS << " // DXILOp once all DXIL op is added.\n"; 30981ad6265SDimitry Andric OS << " OpCodeProperty TmpProp;\n"; 31081ad6265SDimitry Andric OS << " TmpProp.OpCode = DXILOp;\n"; 31181ad6265SDimitry Andric OS << " const OpCodeProperty *Prop =\n"; 31281ad6265SDimitry Andric OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 31381ad6265SDimitry Andric OS << " [](const OpCodeProperty &A, const " 31481ad6265SDimitry Andric "OpCodeProperty &B) {\n"; 31581ad6265SDimitry Andric OS << " return A.OpCode < B.OpCode;\n"; 31681ad6265SDimitry Andric OS << " });\n"; 31781ad6265SDimitry Andric OS << " assert(Prop && \"fail to find OpCodeProperty\");\n"; 31881ad6265SDimitry Andric OS << " return Prop;\n"; 31981ad6265SDimitry Andric OS << "}\n\n"; 32081ad6265SDimitry Andric 32181ad6265SDimitry Andric // Emit the string tables. 32281ad6265SDimitry Andric OS << "static const char *getOpCodeName(DXIL::OpCode DXILOp) {\n\n"; 32381ad6265SDimitry Andric 32481ad6265SDimitry Andric OpStrings.emitStringLiteralDef(OS, 32581ad6265SDimitry Andric " static const char DXILOpCodeNameTable[]"); 32681ad6265SDimitry Andric 32781ad6265SDimitry Andric OS << " auto *Prop = getOpCodeProperty(DXILOp);\n"; 32881ad6265SDimitry Andric OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 32981ad6265SDimitry Andric OS << " return DXILOpCodeNameTable + Index;\n"; 33081ad6265SDimitry Andric OS << "}\n\n"; 33181ad6265SDimitry Andric 33281ad6265SDimitry Andric OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 33381ad6265SDimitry Andric "{\n\n"; 33481ad6265SDimitry Andric 33581ad6265SDimitry Andric OpClassStrings.emitStringLiteralDef( 33681ad6265SDimitry Andric OS, " static const char DXILOpCodeClassNameTable[]"); 33781ad6265SDimitry Andric 33881ad6265SDimitry Andric OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 33981ad6265SDimitry Andric OS << " return DXILOpCodeClassNameTable + Index;\n"; 34081ad6265SDimitry Andric OS << "}\n "; 34181ad6265SDimitry Andric } 34281ad6265SDimitry Andric 34381ad6265SDimitry Andric namespace llvm { 34481ad6265SDimitry Andric 34581ad6265SDimitry Andric void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { 34681ad6265SDimitry Andric std::vector<Record *> Ops = Records.getAllDerivedDefinitions("dxil_op"); 34781ad6265SDimitry Andric OS << "// Generated code, do not edit.\n"; 34881ad6265SDimitry Andric OS << "\n"; 34981ad6265SDimitry Andric 35081ad6265SDimitry Andric std::vector<DXILOperationData> DXILOps; 35181ad6265SDimitry Andric DXILOps.reserve(Ops.size()); 35281ad6265SDimitry Andric for (auto *Record : Ops) { 35381ad6265SDimitry Andric DXILOps.emplace_back(DXILOperationData(Record)); 35481ad6265SDimitry Andric } 35581ad6265SDimitry Andric 35681ad6265SDimitry Andric OS << "#ifdef DXIL_OP_ENUM\n"; 35781ad6265SDimitry Andric emitDXILEnums(DXILOps, OS); 35881ad6265SDimitry Andric OS << "#endif\n\n"; 35981ad6265SDimitry Andric 36081ad6265SDimitry Andric OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; 36181ad6265SDimitry Andric emitDXILIntrinsicMap(DXILOps, OS); 36281ad6265SDimitry Andric OS << "#endif\n\n"; 36381ad6265SDimitry Andric 36481ad6265SDimitry Andric OS << "#ifdef DXIL_OP_OPERATION_TABLE\n"; 36581ad6265SDimitry Andric emitDXILOperationTable(DXILOps, OS); 36681ad6265SDimitry Andric OS << "#endif\n\n"; 36781ad6265SDimitry Andric 36881ad6265SDimitry Andric OS << "\n"; 36981ad6265SDimitry Andric } 37081ad6265SDimitry Andric 37181ad6265SDimitry Andric } // namespace llvm 372