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 14fa3d789dSPierre van Houtryve #include "Basic/SequenceToOffsetTable.h" 15fa3d789dSPierre van Houtryve #include "Common/CodeGenTarget.h" 16435897b4Spython3kgae #include "llvm/ADT/STLExtras.h" 17435897b4Spython3kgae #include "llvm/ADT/SmallVector.h" 18cdfd884bSS. Bharadwaj Yadavalli #include "llvm/ADT/StringExtras.h" 19435897b4Spython3kgae #include "llvm/ADT/StringSet.h" 20f357fe37SJustin Bogner #include "llvm/ADT/StringSwitch.h" 21db6bf921SJustin Bogner #include "llvm/Support/DXILABI.h" 22cdfd884bSS. Bharadwaj Yadavalli #include "llvm/Support/VersionTuple.h" 23cdfd884bSS. Bharadwaj Yadavalli #include "llvm/TableGen/Error.h" 24435897b4Spython3kgae #include "llvm/TableGen/Record.h" 259c93e728SNAKAMURA Takumi #include "llvm/TableGen/TableGenBackend.h" 26cdfd884bSS. Bharadwaj Yadavalli 2754f631d1SS. Bharadwaj Yadavalli #include <string> 28cdfd884bSS. Bharadwaj Yadavalli #include <vector> 29435897b4Spython3kgae 30435897b4Spython3kgae using namespace llvm; 31e77c40ffSChris Bieneman using namespace llvm::dxil; 32435897b4Spython3kgae 33435897b4Spython3kgae namespace { 34435897b4Spython3kgae 350a44b24dSAdam Yang struct DXILIntrinsicSelect { 360a44b24dSAdam Yang StringRef Intrinsic; 370a44b24dSAdam Yang SmallVector<const Record *> ArgSelectRecords; 380a44b24dSAdam Yang }; 390a44b24dSAdam Yang 400a44b24dSAdam Yang static StringRef StripIntrinArgSelectTypePrefix(StringRef Type) { 410a44b24dSAdam Yang StringRef Prefix = "IntrinArgSelect_"; 420a44b24dSAdam Yang if (!Type.starts_with(Prefix)) { 430a44b24dSAdam Yang PrintFatalError("IntrinArgSelectType definintion must be prefixed with " 440a44b24dSAdam Yang "'IntrinArgSelect_'"); 450a44b24dSAdam Yang } 460a44b24dSAdam Yang return Type.substr(Prefix.size()); 470a44b24dSAdam Yang } 480a44b24dSAdam Yang 49758fd59dSS. Bharadwaj Yadavalli struct DXILOperationDesc { 50b1c8b9f8SS. Bharadwaj Yadavalli std::string OpName; // name of DXIL operation 51758fd59dSS. Bharadwaj Yadavalli int OpCode; // ID of DXIL operation 52758fd59dSS. Bharadwaj Yadavalli StringRef OpClass; // name of the opcode class 53435897b4Spython3kgae StringRef Doc; // the documentation description of this instruction 54cdfd884bSS. Bharadwaj Yadavalli // Vector of operand type records - return type is at index 0 550950078bSRahul Joshi SmallVector<const Record *> OpTypes; 560950078bSRahul Joshi SmallVector<const Record *> OverloadRecs; 570950078bSRahul Joshi SmallVector<const Record *> StageRecs; 580950078bSRahul Joshi SmallVector<const Record *> AttrRecs; 59*011b6186SFinn Plummer SmallVector<const Record *> PropRecs; 600a44b24dSAdam Yang SmallVector<DXILIntrinsicSelect> IntrinsicSelects; 61435897b4Spython3kgae SmallVector<StringRef, 4> 62435897b4Spython3kgae ShaderStages; // shader stages to which this applies, empty for all. 6354f631d1SS. Bharadwaj Yadavalli int OverloadParamIndex; // Index of parameter with overload type. 6454f631d1SS. Bharadwaj Yadavalli // -1 : no overload types 65cdacc9b5SJerry Sun SmallVector<StringRef, 4> Counters; // counters for this inst. 668ba4ff39SS. Bharadwaj Yadavalli DXILOperationDesc(const Record *); 678ba4ff39SS. Bharadwaj Yadavalli }; 688ba4ff39SS. Bharadwaj Yadavalli } // end anonymous namespace 698ba4ff39SS. Bharadwaj Yadavalli 70cdfd884bSS. Bharadwaj Yadavalli /// In-place sort TableGen records of class with a field 71cdfd884bSS. Bharadwaj Yadavalli /// Version dxil_version 72cdfd884bSS. Bharadwaj Yadavalli /// in the ascending version order. 73cdacc9b5SJerry Sun static void ascendingSortByVersion(std::vector<const Record *> &Recs) { 740950078bSRahul Joshi sort(Recs, [](const Record *RecA, const Record *RecB) { 75cdfd884bSS. Bharadwaj Yadavalli unsigned RecAMaj = 76cdfd884bSS. Bharadwaj Yadavalli RecA->getValueAsDef("dxil_version")->getValueAsInt("Major"); 77cdfd884bSS. Bharadwaj Yadavalli unsigned RecAMin = 78cdfd884bSS. Bharadwaj Yadavalli RecA->getValueAsDef("dxil_version")->getValueAsInt("Minor"); 79cdfd884bSS. Bharadwaj Yadavalli unsigned RecBMaj = 80cdfd884bSS. Bharadwaj Yadavalli RecB->getValueAsDef("dxil_version")->getValueAsInt("Major"); 81cdfd884bSS. Bharadwaj Yadavalli unsigned RecBMin = 82cdfd884bSS. Bharadwaj Yadavalli RecB->getValueAsDef("dxil_version")->getValueAsInt("Minor"); 83cdfd884bSS. Bharadwaj Yadavalli 84cdfd884bSS. Bharadwaj Yadavalli return (VersionTuple(RecAMaj, RecAMin) < VersionTuple(RecBMaj, RecBMin)); 85cdfd884bSS. Bharadwaj Yadavalli }); 86cdfd884bSS. Bharadwaj Yadavalli } 87cdfd884bSS. Bharadwaj Yadavalli 880a44b24dSAdam Yang /// Take a `int_{intrinsic_name}` and return just the intrinsic_name part if 890a44b24dSAdam Yang /// available. Otherwise return the empty string. 900a44b24dSAdam Yang static StringRef GetIntrinsicName(const RecordVal *RV) { 910a44b24dSAdam Yang if (RV && RV->getValue()) { 920a44b24dSAdam Yang if (const DefInit *DI = dyn_cast<DefInit>(RV->getValue())) { 930a44b24dSAdam Yang auto *IntrinsicDef = DI->getDef(); 940a44b24dSAdam Yang auto DefName = IntrinsicDef->getName(); 950a44b24dSAdam Yang assert(DefName.starts_with("int_") && "invalid intrinsic name"); 960a44b24dSAdam Yang // Remove the int_ from intrinsic name. 970a44b24dSAdam Yang return DefName.substr(4); 980a44b24dSAdam Yang } 990a44b24dSAdam Yang } 1000a44b24dSAdam Yang return ""; 1010a44b24dSAdam Yang } 1020a44b24dSAdam Yang 103b1c8b9f8SS. Bharadwaj Yadavalli /// Construct an object using the DXIL Operation records specified 104b1c8b9f8SS. Bharadwaj Yadavalli /// in DXIL.td. This serves as the single source of reference of 105b1c8b9f8SS. Bharadwaj Yadavalli /// the information extracted from the specified Record R, for 106b1c8b9f8SS. Bharadwaj Yadavalli /// C++ code generated by this TableGen backend. 107b1c8b9f8SS. Bharadwaj Yadavalli // \param R Object representing TableGen record of a DXIL Operation 1088ba4ff39SS. Bharadwaj Yadavalli DXILOperationDesc::DXILOperationDesc(const Record *R) { 109b1c8b9f8SS. Bharadwaj Yadavalli OpName = R->getNameInitAsString(); 110758fd59dSS. Bharadwaj Yadavalli OpCode = R->getValueAsInt("OpCode"); 111435897b4Spython3kgae 112b1c8b9f8SS. Bharadwaj Yadavalli Doc = R->getValueAsString("Doc"); 1130950078bSRahul Joshi SmallVector<const Record *> ParamTypeRecs; 114b1c8b9f8SS. Bharadwaj Yadavalli 115cdfd884bSS. Bharadwaj Yadavalli ParamTypeRecs.push_back(R->getValueAsDef("result")); 116cdfd884bSS. Bharadwaj Yadavalli 1170950078bSRahul Joshi for (const Record *ArgTy : R->getValueAsListOfDefs("arguments")) { 1180950078bSRahul Joshi ParamTypeRecs.push_back(ArgTy); 119cdfd884bSS. Bharadwaj Yadavalli } 120cdfd884bSS. Bharadwaj Yadavalli size_t ParamTypeRecsSize = ParamTypeRecs.size(); 12154f631d1SS. Bharadwaj Yadavalli // Populate OpTypes with return type and parameter types 12254f631d1SS. Bharadwaj Yadavalli 12354f631d1SS. Bharadwaj Yadavalli // Parameter indices of overloaded parameters. 1243f395712SS. Bharadwaj Yadavalli // This vector contains overload parameters in the order used to 12554f631d1SS. Bharadwaj Yadavalli // resolve an LLVMMatchType in accordance with convention outlined in 12654f631d1SS. Bharadwaj Yadavalli // the comment before the definition of class LLVMMatchType in 12754f631d1SS. Bharadwaj Yadavalli // llvm/IR/Intrinsics.td 1288cf85653SJustin Bogner OverloadParamIndex = -1; // A sigil meaning none. 129cdacc9b5SJerry Sun for (unsigned I = 0; I < ParamTypeRecsSize; I++) { 130cdacc9b5SJerry Sun const Record *TR = ParamTypeRecs[I]; 13154f631d1SS. Bharadwaj Yadavalli // Track operation parameter indices of any overload types 132f357fe37SJustin Bogner if (TR->getValueAsInt("isOverload")) { 1338cf85653SJustin Bogner if (OverloadParamIndex != -1) { 1348cf85653SJustin Bogner assert(TR == ParamTypeRecs[OverloadParamIndex] && 1358cf85653SJustin Bogner "Specification of multiple differing overload parameter types " 1368cf85653SJustin Bogner "is not supported"); 13754f631d1SS. Bharadwaj Yadavalli } 1388cf85653SJustin Bogner // Keep the earliest parameter index we see, but if it was the return type 1398cf85653SJustin Bogner // overwrite it with the first overloaded argument. 1408cf85653SJustin Bogner if (OverloadParamIndex <= 0) 141cdacc9b5SJerry Sun OverloadParamIndex = I; 14254f631d1SS. Bharadwaj Yadavalli } 14354f631d1SS. Bharadwaj Yadavalli OpTypes.emplace_back(TR); 14454f631d1SS. Bharadwaj Yadavalli } 145cdfd884bSS. Bharadwaj Yadavalli 146cdfd884bSS. Bharadwaj Yadavalli // Get overload records 147a140931bSRahul Joshi std::vector<const Record *> Recs = R->getValueAsListOfDefs("overloads"); 148cdfd884bSS. Bharadwaj Yadavalli 149cdfd884bSS. Bharadwaj Yadavalli // Sort records in ascending order of DXIL version 150cdacc9b5SJerry Sun ascendingSortByVersion(Recs); 151cdfd884bSS. Bharadwaj Yadavalli 1520950078bSRahul Joshi for (const Record *CR : Recs) { 153cdfd884bSS. Bharadwaj Yadavalli OverloadRecs.push_back(CR); 154cdfd884bSS. Bharadwaj Yadavalli } 155cdfd884bSS. Bharadwaj Yadavalli 156cdfd884bSS. Bharadwaj Yadavalli // Get stage records 157a140931bSRahul Joshi Recs = R->getValueAsListOfDefs("stages"); 158cdfd884bSS. Bharadwaj Yadavalli 159cdfd884bSS. Bharadwaj Yadavalli if (Recs.empty()) { 160cdfd884bSS. Bharadwaj Yadavalli PrintFatalError(R, Twine("Atleast one specification of valid stage for ") + 161cdfd884bSS. Bharadwaj Yadavalli OpName + " is required"); 162cdfd884bSS. Bharadwaj Yadavalli } 163cdfd884bSS. Bharadwaj Yadavalli 164cdfd884bSS. Bharadwaj Yadavalli // Sort records in ascending order of DXIL version 165cdacc9b5SJerry Sun ascendingSortByVersion(Recs); 166cdfd884bSS. Bharadwaj Yadavalli 1670950078bSRahul Joshi for (const Record *CR : Recs) { 168cdfd884bSS. Bharadwaj Yadavalli StageRecs.push_back(CR); 169cdfd884bSS. Bharadwaj Yadavalli } 170cdfd884bSS. Bharadwaj Yadavalli 171cdfd884bSS. Bharadwaj Yadavalli // Get attribute records 172a140931bSRahul Joshi Recs = R->getValueAsListOfDefs("attributes"); 173cdfd884bSS. Bharadwaj Yadavalli 174cdfd884bSS. Bharadwaj Yadavalli // Sort records in ascending order of DXIL version 175cdacc9b5SJerry Sun ascendingSortByVersion(Recs); 176cdfd884bSS. Bharadwaj Yadavalli 1770950078bSRahul Joshi for (const Record *CR : Recs) { 178cdfd884bSS. Bharadwaj Yadavalli AttrRecs.push_back(CR); 179cdfd884bSS. Bharadwaj Yadavalli } 180cdfd884bSS. Bharadwaj Yadavalli 181*011b6186SFinn Plummer Recs = R->getValueAsListOfDefs("properties"); 182*011b6186SFinn Plummer 183*011b6186SFinn Plummer // Get property records 184*011b6186SFinn Plummer for (const Record *CR : Recs) 185*011b6186SFinn Plummer PropRecs.push_back(CR); 186*011b6186SFinn Plummer 18754f631d1SS. Bharadwaj Yadavalli // Get the operation class 18854f631d1SS. Bharadwaj Yadavalli OpClass = R->getValueAsDef("OpClass")->getName(); 18954f631d1SS. Bharadwaj Yadavalli 190cdfd884bSS. Bharadwaj Yadavalli if (!OpClass.str().compare("UnknownOpClass")) { 191cdfd884bSS. Bharadwaj Yadavalli PrintFatalError(R, Twine("Unspecified DXIL OpClass for DXIL operation - ") + 192cdfd884bSS. Bharadwaj Yadavalli OpName); 193cdfd884bSS. Bharadwaj Yadavalli } 194cdfd884bSS. Bharadwaj Yadavalli 1950a44b24dSAdam Yang auto IntrinsicSelectRecords = R->getValueAsListOfDefs("intrinsics"); 1960a44b24dSAdam Yang if (IntrinsicSelectRecords.size()) { 1970a44b24dSAdam Yang for (const Record *R : IntrinsicSelectRecords) { 1980a44b24dSAdam Yang DXILIntrinsicSelect IntrSelect; 1990a44b24dSAdam Yang IntrSelect.Intrinsic = GetIntrinsicName(R->getValue("intrinsic")); 2000a44b24dSAdam Yang auto Args = R->getValueAsListOfDefs("arg_selects"); 2010a44b24dSAdam Yang for (const Record *ArgSelect : Args) { 2020a44b24dSAdam Yang IntrSelect.ArgSelectRecords.emplace_back(ArgSelect); 2030a44b24dSAdam Yang } 2040a44b24dSAdam Yang IntrinsicSelects.emplace_back(std::move(IntrSelect)); 2058ba4ff39SS. Bharadwaj Yadavalli } 206b1c8b9f8SS. Bharadwaj Yadavalli } 207db6bf921SJustin Bogner } 208db6bf921SJustin Bogner 209b1c8b9f8SS. Bharadwaj Yadavalli /// Return a string representation of OverloadKind enum that maps to 21054f631d1SS. Bharadwaj Yadavalli /// input LLVMType record 21154f631d1SS. Bharadwaj Yadavalli /// \param R TableGen def record of class LLVMType 212b1c8b9f8SS. Bharadwaj Yadavalli /// \return std::string string representation of OverloadKind 213b1c8b9f8SS. Bharadwaj Yadavalli 214f357fe37SJustin Bogner static StringRef getOverloadKindStr(const Record *R) { 215f357fe37SJustin Bogner // TODO: This is a hack. We need to rework how we're handling the set of 216f357fe37SJustin Bogner // overloads to avoid this business with the separate OverloadKind enum. 217f357fe37SJustin Bogner return StringSwitch<StringRef>(R->getName()) 218f357fe37SJustin Bogner .Case("HalfTy", "OverloadKind::HALF") 219f357fe37SJustin Bogner .Case("FloatTy", "OverloadKind::FLOAT") 220f357fe37SJustin Bogner .Case("DoubleTy", "OverloadKind::DOUBLE") 221f357fe37SJustin Bogner .Case("Int1Ty", "OverloadKind::I1") 222f357fe37SJustin Bogner .Case("Int8Ty", "OverloadKind::I8") 223f357fe37SJustin Bogner .Case("Int16Ty", "OverloadKind::I16") 224f357fe37SJustin Bogner .Case("Int32Ty", "OverloadKind::I32") 2253f22756fSJustin Bogner .Case("Int64Ty", "OverloadKind::I64") 2263f22756fSJustin Bogner .Case("ResRetHalfTy", "OverloadKind::HALF") 2273f22756fSJustin Bogner .Case("ResRetFloatTy", "OverloadKind::FLOAT") 228cba9bd5cSJustin Bogner .Case("ResRetDoubleTy", "OverloadKind::DOUBLE") 2293f22756fSJustin Bogner .Case("ResRetInt16Ty", "OverloadKind::I16") 230cba9bd5cSJustin Bogner .Case("ResRetInt32Ty", "OverloadKind::I32") 231cba9bd5cSJustin Bogner .Case("ResRetInt64Ty", "OverloadKind::I64"); 232435897b4Spython3kgae } 233435897b4Spython3kgae 234cdfd884bSS. Bharadwaj Yadavalli /// Return a string representation of valid overload information denoted 235cdfd884bSS. Bharadwaj Yadavalli // by input records 236cdfd884bSS. Bharadwaj Yadavalli // 237cdfd884bSS. Bharadwaj Yadavalli /// \param Recs A vector of records of TableGen Overload records 238cdfd884bSS. Bharadwaj Yadavalli /// \return std::string string representation of overload mask string 239cdfd884bSS. Bharadwaj Yadavalli /// predicated by DXIL Version. E.g., 240cdfd884bSS. Bharadwaj Yadavalli // {{{1, 0}, Mask1}, {{1, 2}, Mask2}, ...} 2410950078bSRahul Joshi static std::string getOverloadMaskString(ArrayRef<const Record *> Recs) { 242cdfd884bSS. Bharadwaj Yadavalli std::string MaskString = ""; 243cdfd884bSS. Bharadwaj Yadavalli std::string Prefix = ""; 244cdfd884bSS. Bharadwaj Yadavalli MaskString.append("{"); 245cdfd884bSS. Bharadwaj Yadavalli // If no overload information records were specified, assume the operation 246cdfd884bSS. Bharadwaj Yadavalli // a) to be supported in DXIL Version 1.0 and later 247cdfd884bSS. Bharadwaj Yadavalli // b) has no overload types 248cdfd884bSS. Bharadwaj Yadavalli if (Recs.empty()) { 249cdfd884bSS. Bharadwaj Yadavalli MaskString.append("{{1, 0}, OverloadKind::UNDEFINED}}"); 250cdfd884bSS. Bharadwaj Yadavalli } else { 251cdacc9b5SJerry Sun for (const auto *Rec : Recs) { 252cdfd884bSS. Bharadwaj Yadavalli unsigned Major = 253cdfd884bSS. Bharadwaj Yadavalli Rec->getValueAsDef("dxil_version")->getValueAsInt("Major"); 254cdfd884bSS. Bharadwaj Yadavalli unsigned Minor = 255cdfd884bSS. Bharadwaj Yadavalli Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor"); 256cdfd884bSS. Bharadwaj Yadavalli MaskString.append(Prefix) 257cdfd884bSS. Bharadwaj Yadavalli .append("{{") 258cdfd884bSS. Bharadwaj Yadavalli .append(std::to_string(Major)) 259cdfd884bSS. Bharadwaj Yadavalli .append(", ") 260cdfd884bSS. Bharadwaj Yadavalli .append(std::to_string(Minor).append("}, ")); 261cdfd884bSS. Bharadwaj Yadavalli 262cdfd884bSS. Bharadwaj Yadavalli std::string PipePrefix = ""; 263cdfd884bSS. Bharadwaj Yadavalli auto Tys = Rec->getValueAsListOfDefs("overload_types"); 264cdfd884bSS. Bharadwaj Yadavalli if (Tys.empty()) { 265cdfd884bSS. Bharadwaj Yadavalli MaskString.append("OverloadKind::UNDEFINED"); 266cdfd884bSS. Bharadwaj Yadavalli } 267cdfd884bSS. Bharadwaj Yadavalli for (const auto *Ty : Tys) { 268cdfd884bSS. Bharadwaj Yadavalli MaskString.append(PipePrefix).append(getOverloadKindStr(Ty)); 269cdfd884bSS. Bharadwaj Yadavalli PipePrefix = " | "; 270cdfd884bSS. Bharadwaj Yadavalli } 271cdfd884bSS. Bharadwaj Yadavalli 272cdfd884bSS. Bharadwaj Yadavalli MaskString.append("}"); 273cdfd884bSS. Bharadwaj Yadavalli Prefix = ", "; 274cdfd884bSS. Bharadwaj Yadavalli } 275cdfd884bSS. Bharadwaj Yadavalli MaskString.append("}"); 276cdfd884bSS. Bharadwaj Yadavalli } 277cdfd884bSS. Bharadwaj Yadavalli return MaskString; 278cdfd884bSS. Bharadwaj Yadavalli } 279cdfd884bSS. Bharadwaj Yadavalli 280cdfd884bSS. Bharadwaj Yadavalli /// Return a string representation of valid shader stag information denoted 281cdfd884bSS. Bharadwaj Yadavalli // by input records 282cdfd884bSS. Bharadwaj Yadavalli // 283cdfd884bSS. Bharadwaj Yadavalli /// \param Recs A vector of records of TableGen Stages records 284cdfd884bSS. Bharadwaj Yadavalli /// \return std::string string representation of stages mask string 285cdfd884bSS. Bharadwaj Yadavalli /// predicated by DXIL Version. E.g., 286cdfd884bSS. Bharadwaj Yadavalli // {{{1, 0}, Mask1}, {{1, 2}, Mask2}, ...} 2870950078bSRahul Joshi static std::string getStageMaskString(ArrayRef<const Record *> Recs) { 288cdfd884bSS. Bharadwaj Yadavalli std::string MaskString = ""; 289cdfd884bSS. Bharadwaj Yadavalli std::string Prefix = ""; 290cdfd884bSS. Bharadwaj Yadavalli MaskString.append("{"); 291cdfd884bSS. Bharadwaj Yadavalli // Atleast one stage information record is expected to be specified. 292cdfd884bSS. Bharadwaj Yadavalli if (Recs.empty()) { 293cdfd884bSS. Bharadwaj Yadavalli PrintFatalError("Atleast one specification of valid stages for " 294cdfd884bSS. Bharadwaj Yadavalli "operation must be specified"); 295cdfd884bSS. Bharadwaj Yadavalli } 296cdfd884bSS. Bharadwaj Yadavalli 297cdacc9b5SJerry Sun for (const auto *Rec : Recs) { 298cdfd884bSS. Bharadwaj Yadavalli unsigned Major = Rec->getValueAsDef("dxil_version")->getValueAsInt("Major"); 299cdfd884bSS. Bharadwaj Yadavalli unsigned Minor = Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor"); 300cdfd884bSS. Bharadwaj Yadavalli MaskString.append(Prefix) 301cdfd884bSS. Bharadwaj Yadavalli .append("{{") 302cdfd884bSS. Bharadwaj Yadavalli .append(std::to_string(Major)) 303cdfd884bSS. Bharadwaj Yadavalli .append(", ") 304cdfd884bSS. Bharadwaj Yadavalli .append(std::to_string(Minor).append("}, ")); 305cdfd884bSS. Bharadwaj Yadavalli 306cdfd884bSS. Bharadwaj Yadavalli std::string PipePrefix = ""; 307cdfd884bSS. Bharadwaj Yadavalli auto Stages = Rec->getValueAsListOfDefs("shader_stages"); 308cdfd884bSS. Bharadwaj Yadavalli if (Stages.empty()) { 309cdfd884bSS. Bharadwaj Yadavalli PrintFatalError("No valid stages for operation specified"); 310cdfd884bSS. Bharadwaj Yadavalli } 311cdfd884bSS. Bharadwaj Yadavalli for (const auto *S : Stages) { 312cdfd884bSS. Bharadwaj Yadavalli MaskString.append(PipePrefix).append("ShaderKind::").append(S->getName()); 313cdfd884bSS. Bharadwaj Yadavalli PipePrefix = " | "; 314cdfd884bSS. Bharadwaj Yadavalli } 315cdfd884bSS. Bharadwaj Yadavalli 316cdfd884bSS. Bharadwaj Yadavalli MaskString.append("}"); 317cdfd884bSS. Bharadwaj Yadavalli Prefix = ", "; 318cdfd884bSS. Bharadwaj Yadavalli } 319cdfd884bSS. Bharadwaj Yadavalli MaskString.append("}"); 320cdfd884bSS. Bharadwaj Yadavalli return MaskString; 321cdfd884bSS. Bharadwaj Yadavalli } 322cdfd884bSS. Bharadwaj Yadavalli 323*011b6186SFinn Plummer /// Emit a list valid DXIL Version records 324*011b6186SFinn Plummer static void emitDXILVersions(const RecordKeeper &Records, raw_ostream &OS) { 325*011b6186SFinn Plummer OS << "#ifdef DXIL_VERSION\n"; 326*011b6186SFinn Plummer for (const Record *Version : Records.getAllDerivedDefinitions("Version")) { 327*011b6186SFinn Plummer unsigned Major = Version->getValueAsInt("Major"); 328*011b6186SFinn Plummer unsigned Minor = Version->getValueAsInt("Minor"); 329*011b6186SFinn Plummer OS << "DXIL_VERSION("; 330*011b6186SFinn Plummer OS << std::to_string(Major) << ", " << std::to_string(Minor); 331*011b6186SFinn Plummer OS << ")\n"; 332cdfd884bSS. Bharadwaj Yadavalli } 333*011b6186SFinn Plummer OS << "#undef DXIL_VERSION\n"; 334*011b6186SFinn Plummer OS << "#endif\n\n"; 335cdfd884bSS. Bharadwaj Yadavalli } 336cdfd884bSS. Bharadwaj Yadavalli 33740940980SJustin Bogner /// Emit a mapping of DXIL opcode to opname 3384fbac528SRahul Joshi static void emitDXILOpCodes(ArrayRef<DXILOperationDesc> Ops, raw_ostream &OS) { 33940940980SJustin Bogner OS << "#ifdef DXIL_OPCODE\n"; 34040940980SJustin Bogner for (const DXILOperationDesc &Op : Ops) 34140940980SJustin Bogner OS << "DXIL_OPCODE(" << Op.OpCode << ", " << Op.OpName << ")\n"; 34240940980SJustin Bogner OS << "#undef DXIL_OPCODE\n"; 34340940980SJustin Bogner OS << "\n"; 34440940980SJustin Bogner OS << "#endif\n\n"; 345435897b4Spython3kgae } 346435897b4Spython3kgae 34740940980SJustin Bogner /// Emit a list of DXIL op classes 3484fbac528SRahul Joshi static void emitDXILOpClasses(const RecordKeeper &Records, raw_ostream &OS) { 34940940980SJustin Bogner OS << "#ifdef DXIL_OPCLASS\n"; 3504fbac528SRahul Joshi for (const Record *OpClass : Records.getAllDerivedDefinitions("DXILOpClass")) 35140940980SJustin Bogner OS << "DXIL_OPCLASS(" << OpClass->getName() << ")\n"; 35240940980SJustin Bogner OS << "#undef DXIL_OPCLASS\n"; 35394da6bfbSJustin Bogner OS << "#endif\n\n"; 354435897b4Spython3kgae } 355435897b4Spython3kgae 356f357fe37SJustin Bogner /// Emit a list of DXIL op parameter types 3574fbac528SRahul Joshi static void emitDXILOpParamTypes(const RecordKeeper &Records, raw_ostream &OS) { 358f357fe37SJustin Bogner OS << "#ifdef DXIL_OP_PARAM_TYPE\n"; 3594fbac528SRahul Joshi for (const Record *OpParamType : 3604fbac528SRahul Joshi Records.getAllDerivedDefinitions("DXILOpParamType")) 3614fbac528SRahul Joshi OS << "DXIL_OP_PARAM_TYPE(" << OpParamType->getName() << ")\n"; 362f357fe37SJustin Bogner OS << "#undef DXIL_OP_PARAM_TYPE\n"; 363f357fe37SJustin Bogner OS << "#endif\n\n"; 364f357fe37SJustin Bogner } 365f357fe37SJustin Bogner 366*011b6186SFinn Plummer /// Emit a list of DXIL op function attributes 367*011b6186SFinn Plummer static void emitDXILAttributes(const RecordKeeper &Records, raw_ostream &OS) { 368*011b6186SFinn Plummer OS << "#ifdef DXIL_ATTRIBUTE\n"; 369*011b6186SFinn Plummer for (const Record *Attr : Records.getAllDerivedDefinitions("DXILAttribute")) 370*011b6186SFinn Plummer OS << "DXIL_ATTRIBUTE(" << Attr->getName() << ")\n"; 371*011b6186SFinn Plummer OS << "#undef DXIL_ATTRIBUTE\n"; 372*011b6186SFinn Plummer OS << "#endif\n\n"; 373*011b6186SFinn Plummer } 374*011b6186SFinn Plummer 375*011b6186SFinn Plummer // Helper function to determine if the given Attr is defined in the vector 376*011b6186SFinn Plummer // Attrs, by comparing the names 377*011b6186SFinn Plummer static bool attrIsDefined(std::vector<const Record *> Attrs, 378*011b6186SFinn Plummer const Record *Attr) { 379*011b6186SFinn Plummer for (auto CurAttr : Attrs) 380*011b6186SFinn Plummer if (CurAttr->getName() == Attr->getName()) 381*011b6186SFinn Plummer return true; 382*011b6186SFinn Plummer return false; 383*011b6186SFinn Plummer } 384*011b6186SFinn Plummer 385*011b6186SFinn Plummer /// Emit a table of bools denoting a DXIL op's function attributes 386*011b6186SFinn Plummer static void emitDXILOpAttributes(const RecordKeeper &Records, 387*011b6186SFinn Plummer ArrayRef<DXILOperationDesc> Ops, 388*011b6186SFinn Plummer raw_ostream &OS) { 389*011b6186SFinn Plummer // A DXIL op can have multiple function attributes that are specific to a 390*011b6186SFinn Plummer // specific DXIL version and higher. AttrRecs models this by grouping the 391*011b6186SFinn Plummer // attributes by the versions. So we will output a macro for each version 392*011b6186SFinn Plummer // number with a table of bools in the following format: 393*011b6186SFinn Plummer // 394*011b6186SFinn Plummer // OpName, VersionMajor, VersionMinor, FnAttr1, FnAttr2, ... 395*011b6186SFinn Plummer // Eg) Abs, 1, 0, true, false, ... 396*011b6186SFinn Plummer OS << "#ifdef DXIL_OP_ATTRIBUTES\n"; 397*011b6186SFinn Plummer for (const auto &Op : Ops) { 398*011b6186SFinn Plummer for (const auto *Rec : Op.AttrRecs) { 399*011b6186SFinn Plummer unsigned Major = 400*011b6186SFinn Plummer Rec->getValueAsDef("dxil_version")->getValueAsInt("Major"); 401*011b6186SFinn Plummer unsigned Minor = 402*011b6186SFinn Plummer Rec->getValueAsDef("dxil_version")->getValueAsInt("Minor"); 403*011b6186SFinn Plummer OS << "DXIL_OP_ATTRIBUTES(dxil::OpCode::" << Op.OpName << ", "; 404*011b6186SFinn Plummer OS << std::to_string(Major) << ", " << std::to_string(Minor); 405*011b6186SFinn Plummer // These Attrs are the ones set for above DXIL version 406*011b6186SFinn Plummer auto Attrs = Rec->getValueAsListOfDefs("fn_attrs"); 407*011b6186SFinn Plummer // We will then iteratre through all possible attributes and mark the 408*011b6186SFinn Plummer // present ones as 'true' and all the others as 'false' to create the 409*011b6186SFinn Plummer // boolean table, eg) true, false, false, false 410*011b6186SFinn Plummer for (const Record *Attr : 411*011b6186SFinn Plummer Records.getAllDerivedDefinitions("DXILAttribute")) { 412*011b6186SFinn Plummer std::string HasAttr = ", false"; 413*011b6186SFinn Plummer if (attrIsDefined(Attrs, Attr)) 414*011b6186SFinn Plummer HasAttr = ", true"; 415*011b6186SFinn Plummer OS << HasAttr; 416*011b6186SFinn Plummer } 417*011b6186SFinn Plummer OS << ")\n"; 418*011b6186SFinn Plummer } 419*011b6186SFinn Plummer } 420*011b6186SFinn Plummer OS << "#undef DXIL_OP_ATTRIBUTES\n"; 421*011b6186SFinn Plummer OS << "#endif\n\n"; 422*011b6186SFinn Plummer } 423*011b6186SFinn Plummer 424*011b6186SFinn Plummer /// Emit a list of DXIL op properties 425*011b6186SFinn Plummer static void emitDXILProperties(const RecordKeeper &Records, raw_ostream &OS) { 426*011b6186SFinn Plummer OS << "#ifdef DXIL_PROPERTY\n"; 427*011b6186SFinn Plummer for (const Record *Prop : Records.getAllDerivedDefinitions("DXILProperty")) 428*011b6186SFinn Plummer OS << "DXIL_PROPERTY(" << Prop->getName() << ")\n"; 429*011b6186SFinn Plummer OS << "#undef DXIL_PROPERTY\n"; 430*011b6186SFinn Plummer OS << "#endif\n\n"; 431*011b6186SFinn Plummer } 432*011b6186SFinn Plummer 433f357fe37SJustin Bogner /// Emit a list of DXIL op function types 434f357fe37SJustin Bogner static void emitDXILOpFunctionTypes(ArrayRef<DXILOperationDesc> Ops, 435f357fe37SJustin Bogner raw_ostream &OS) { 436f357fe37SJustin Bogner OS << "#ifndef DXIL_OP_FUNCTION_TYPE\n"; 437f357fe37SJustin Bogner OS << "#define DXIL_OP_FUNCTION_TYPE(OpCode, RetType, ...)\n"; 438f357fe37SJustin Bogner OS << "#endif\n"; 439f357fe37SJustin Bogner for (const DXILOperationDesc &Op : Ops) { 440f357fe37SJustin Bogner OS << "DXIL_OP_FUNCTION_TYPE(dxil::OpCode::" << Op.OpName; 441f357fe37SJustin Bogner for (const Record *Rec : Op.OpTypes) 442f357fe37SJustin Bogner OS << ", dxil::OpParamType::" << Rec->getName(); 443f357fe37SJustin Bogner // If there are no arguments, we need an empty comma for the varargs 444f357fe37SJustin Bogner if (Op.OpTypes.size() == 1) 445f357fe37SJustin Bogner OS << ", "; 446f357fe37SJustin Bogner OS << ")\n"; 447f357fe37SJustin Bogner } 448f357fe37SJustin Bogner OS << "#undef DXIL_OP_FUNCTION_TYPE\n"; 449f357fe37SJustin Bogner } 450f357fe37SJustin Bogner 451b1c8b9f8SS. Bharadwaj Yadavalli /// Emit map of DXIL operation to LLVM or DirectX intrinsic 452b1c8b9f8SS. Bharadwaj Yadavalli /// \param A vector of DXIL Ops 453b1c8b9f8SS. Bharadwaj Yadavalli /// \param Output stream 4544fbac528SRahul Joshi static void emitDXILIntrinsicMap(ArrayRef<DXILOperationDesc> Ops, 455264c09b7SXiang Li raw_ostream &OS) { 4560a44b24dSAdam Yang 45794da6bfbSJustin Bogner OS << "#ifdef DXIL_OP_INTRINSIC\n"; 45894da6bfbSJustin Bogner OS << "\n"; 45994da6bfbSJustin Bogner for (const auto &Op : Ops) { 4600a44b24dSAdam Yang if (Op.IntrinsicSelects.empty()) { 461264c09b7SXiang Li continue; 4620a44b24dSAdam Yang } 4630a44b24dSAdam Yang for (const DXILIntrinsicSelect &MappedIntr : Op.IntrinsicSelects) { 46494da6bfbSJustin Bogner OS << "DXIL_OP_INTRINSIC(dxil::OpCode::" << Op.OpName 4650a44b24dSAdam Yang << ", Intrinsic::" << MappedIntr.Intrinsic << ", "; 4660a44b24dSAdam Yang for (const Record *ArgSelect : MappedIntr.ArgSelectRecords) { 4670a44b24dSAdam Yang std::string Type = 4680a44b24dSAdam Yang ArgSelect->getValueAsDef("type")->getNameInitAsString(); 4690a44b24dSAdam Yang int Value = ArgSelect->getValueAsInt("value"); 4700a44b24dSAdam Yang OS << "(IntrinArgSelect{" 4710a44b24dSAdam Yang << "IntrinArgSelect::Type::" << StripIntrinArgSelectTypePrefix(Type) 4720a44b24dSAdam Yang << "," << Value << "}), "; 4730a44b24dSAdam Yang } 4740a44b24dSAdam Yang OS << ")\n"; 4750a44b24dSAdam Yang } 476264c09b7SXiang Li } 47794da6bfbSJustin Bogner OS << "\n"; 47894da6bfbSJustin Bogner OS << "#undef DXIL_OP_INTRINSIC\n"; 47994da6bfbSJustin Bogner OS << "#endif\n\n"; 4800d2dde20SXiang Li } 4810d2dde20SXiang Li 4820a44b24dSAdam Yang /// Emit the IntrinArgSelect type for DirectX intrinsic to DXIL Op lowering 4830a44b24dSAdam Yang static void emitDXILIntrinsicArgSelectTypes(const RecordKeeper &Records, 4840a44b24dSAdam Yang raw_ostream &OS) { 4850a44b24dSAdam Yang OS << "#ifdef DXIL_OP_INTRINSIC_ARG_SELECT_TYPE\n"; 4860a44b24dSAdam Yang for (const Record *Records : 4870a44b24dSAdam Yang Records.getAllDerivedDefinitions("IntrinArgSelectType")) { 4880a44b24dSAdam Yang StringRef StrippedName = StripIntrinArgSelectTypePrefix(Records->getName()); 4890a44b24dSAdam Yang OS << "DXIL_OP_INTRINSIC_ARG_SELECT_TYPE(" << StrippedName << ")\n"; 4900a44b24dSAdam Yang } 4910a44b24dSAdam Yang OS << "#undef DXIL_OP_INTRINSIC_ARG_SELECT_TYPE\n"; 4920a44b24dSAdam Yang OS << "#endif\n\n"; 4930a44b24dSAdam Yang } 4940a44b24dSAdam Yang 495b1c8b9f8SS. Bharadwaj Yadavalli /// Emit DXIL operation table 496b1c8b9f8SS. Bharadwaj Yadavalli /// \param A vector of DXIL Ops 497b1c8b9f8SS. Bharadwaj Yadavalli /// \param Output stream 4984fbac528SRahul Joshi static void emitDXILOperationTable(ArrayRef<DXILOperationDesc> Ops, 4990d2dde20SXiang Li raw_ostream &OS) { 5000d2dde20SXiang Li // Collect Names. 5010d2dde20SXiang Li SequenceToOffsetTable<std::string> OpClassStrings; 5020d2dde20SXiang Li SequenceToOffsetTable<std::string> OpStrings; 5030d2dde20SXiang Li 5040d2dde20SXiang Li StringSet<> ClassSet; 5054fbac528SRahul Joshi for (const auto &Op : Ops) { 506b1c8b9f8SS. Bharadwaj Yadavalli OpStrings.add(Op.OpName); 5070d2dde20SXiang Li 508a0c43be0SKazu Hirata if (ClassSet.insert(Op.OpClass).second) 509b1c8b9f8SS. Bharadwaj Yadavalli OpClassStrings.add(Op.OpClass.data()); 5100d2dde20SXiang Li } 5110d2dde20SXiang Li 5120d2dde20SXiang Li // Layout names. 5130d2dde20SXiang Li OpStrings.layout(); 5140d2dde20SXiang Li OpClassStrings.layout(); 5150d2dde20SXiang Li 516cdfd884bSS. Bharadwaj Yadavalli // Emit access function getOpcodeProperty() that embeds DXIL Operation table 517cdfd884bSS. Bharadwaj Yadavalli // with entries of type struct OpcodeProperty. 518758fd59dSS. Bharadwaj Yadavalli OS << "static const OpCodeProperty *getOpCodeProperty(dxil::OpCode Op) " 5190d2dde20SXiang Li "{\n"; 5200d2dde20SXiang Li 5210d2dde20SXiang Li OS << " static const OpCodeProperty OpCodeProps[] = {\n"; 522cdfd884bSS. Bharadwaj Yadavalli std::string Prefix = ""; 5234fbac528SRahul Joshi for (const auto &Op : Ops) { 524cdfd884bSS. Bharadwaj Yadavalli OS << Prefix << " { dxil::OpCode::" << Op.OpName << ", " 525cdfd884bSS. Bharadwaj Yadavalli << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", " 526b1c8b9f8SS. Bharadwaj Yadavalli << OpClassStrings.get(Op.OpClass.data()) << ", " 527cdfd884bSS. Bharadwaj Yadavalli << getOverloadMaskString(Op.OverloadRecs) << ", " 528*011b6186SFinn Plummer << getStageMaskString(Op.StageRecs) << ", " << Op.OverloadParamIndex 529f357fe37SJustin Bogner << " }"; 530cdfd884bSS. Bharadwaj Yadavalli Prefix = ",\n"; 5310d2dde20SXiang Li } 5320d2dde20SXiang Li OS << " };\n"; 5330d2dde20SXiang Li 5340d2dde20SXiang Li OS << " // FIXME: change search to indexing with\n"; 535758fd59dSS. Bharadwaj Yadavalli OS << " // Op once all DXIL operations are added.\n"; 5360d2dde20SXiang Li OS << " OpCodeProperty TmpProp;\n"; 537758fd59dSS. Bharadwaj Yadavalli OS << " TmpProp.OpCode = Op;\n"; 5380d2dde20SXiang Li OS << " const OpCodeProperty *Prop =\n"; 5390d2dde20SXiang Li OS << " llvm::lower_bound(OpCodeProps, TmpProp,\n"; 5400d2dde20SXiang Li OS << " [](const OpCodeProperty &A, const " 5410d2dde20SXiang Li "OpCodeProperty &B) {\n"; 5420d2dde20SXiang Li OS << " return A.OpCode < B.OpCode;\n"; 5430d2dde20SXiang Li OS << " });\n"; 544b1c8b9f8SS. Bharadwaj Yadavalli OS << " assert(Prop && \"failed to find OpCodeProperty\");\n"; 5450d2dde20SXiang Li OS << " return Prop;\n"; 5460d2dde20SXiang Li OS << "}\n\n"; 5470d2dde20SXiang Li 5480d2dde20SXiang Li // Emit the string tables. 549758fd59dSS. Bharadwaj Yadavalli OS << "static const char *getOpCodeName(dxil::OpCode Op) {\n\n"; 5500d2dde20SXiang Li 5510d2dde20SXiang Li OpStrings.emitStringLiteralDef(OS, 5520d2dde20SXiang Li " static const char DXILOpCodeNameTable[]"); 5530d2dde20SXiang Li 554758fd59dSS. Bharadwaj Yadavalli OS << " auto *Prop = getOpCodeProperty(Op);\n"; 5550d2dde20SXiang Li OS << " unsigned Index = Prop->OpCodeNameOffset;\n"; 5560d2dde20SXiang Li OS << " return DXILOpCodeNameTable + Index;\n"; 5570d2dde20SXiang Li OS << "}\n\n"; 5580d2dde20SXiang Li 5590d2dde20SXiang Li OS << "static const char *getOpCodeClassName(const OpCodeProperty &Prop) " 5600d2dde20SXiang Li "{\n\n"; 5610d2dde20SXiang Li 5620d2dde20SXiang Li OpClassStrings.emitStringLiteralDef( 5630d2dde20SXiang Li OS, " static const char DXILOpCodeClassNameTable[]"); 5640d2dde20SXiang Li 5650d2dde20SXiang Li OS << " unsigned Index = Prop.OpCodeClassNameOffset;\n"; 5660d2dde20SXiang Li OS << " return DXILOpCodeClassNameTable + Index;\n"; 56794da6bfbSJustin Bogner OS << "}\n\n"; 5680d2dde20SXiang Li } 5690d2dde20SXiang Li 5704fbac528SRahul Joshi static void emitDXILOperationTableDataStructs(const RecordKeeper &Records, 571cdfd884bSS. Bharadwaj Yadavalli raw_ostream &OS) { 572cdfd884bSS. Bharadwaj Yadavalli // Get Shader stage records 5734fbac528SRahul Joshi std::vector<const Record *> ShaderKindRecs = 574cdfd884bSS. Bharadwaj Yadavalli Records.getAllDerivedDefinitions("DXILShaderStage"); 575cdfd884bSS. Bharadwaj Yadavalli // Sort records by name 5764fbac528SRahul Joshi llvm::sort(ShaderKindRecs, [](const Record *A, const Record *B) { 5774fbac528SRahul Joshi return A->getName() < B->getName(); 5784fbac528SRahul Joshi }); 579cdfd884bSS. Bharadwaj Yadavalli 580cdfd884bSS. Bharadwaj Yadavalli OS << "// Valid shader kinds\n\n"; 581cdfd884bSS. Bharadwaj Yadavalli // Choose the type of enum ShaderKind based on the number of stages declared. 582cdfd884bSS. Bharadwaj Yadavalli // This gives the flexibility to just add add new stage records in DXIL.td, if 583cdfd884bSS. Bharadwaj Yadavalli // needed, with no need to change this backend code. 584cdfd884bSS. Bharadwaj Yadavalli size_t ShaderKindCount = ShaderKindRecs.size(); 585cdfd884bSS. Bharadwaj Yadavalli uint64_t ShaderKindTySz = PowerOf2Ceil(ShaderKindRecs.size() + 1); 586cdfd884bSS. Bharadwaj Yadavalli OS << "enum ShaderKind : uint" << ShaderKindTySz << "_t {\n"; 587cdacc9b5SJerry Sun const std::string AllStages("all_stages"); 588cdacc9b5SJerry Sun const std::string Removed("removed"); 589cdacc9b5SJerry Sun int ShiftVal = 1; 590cdacc9b5SJerry Sun for (const auto *R : ShaderKindRecs) { 591cdfd884bSS. Bharadwaj Yadavalli auto Name = R->getName(); 592cdacc9b5SJerry Sun if (Name.compare(Removed) == 0) { 593cdfd884bSS. Bharadwaj Yadavalli OS << " " << Name 594cdfd884bSS. Bharadwaj Yadavalli << " = 0, // Pseudo-stage indicating op not supported in any " 595cdfd884bSS. Bharadwaj Yadavalli "stage\n"; 596cdacc9b5SJerry Sun } else if (Name.compare(AllStages) == 0) { 597cdfd884bSS. Bharadwaj Yadavalli OS << " " << Name << " = 0x" 598cdfd884bSS. Bharadwaj Yadavalli << utohexstr(((1 << ShaderKindCount) - 1), false, 0) 599cdfd884bSS. Bharadwaj Yadavalli << ", // Pseudo-stage indicating op is supported in all stages\n"; 600cdacc9b5SJerry Sun } else if (Name.compare(AllStages)) { 601cdacc9b5SJerry Sun OS << " " << Name << " = 1 << " << std::to_string(ShiftVal++) << ",\n"; 602cdfd884bSS. Bharadwaj Yadavalli } 603cdfd884bSS. Bharadwaj Yadavalli } 604cdfd884bSS. Bharadwaj Yadavalli OS << "}; // enum ShaderKind\n\n"; 605cdfd884bSS. Bharadwaj Yadavalli } 606cdfd884bSS. Bharadwaj Yadavalli 607b1c8b9f8SS. Bharadwaj Yadavalli /// Entry function call that invokes the functionality of this TableGen backend 608b1c8b9f8SS. Bharadwaj Yadavalli /// \param Records TableGen records of DXIL Operations defined in DXIL.td 609b1c8b9f8SS. Bharadwaj Yadavalli /// \param OS output stream 610cdacc9b5SJerry Sun static void emitDxilOperation(const RecordKeeper &Records, raw_ostream &OS) { 611435897b4Spython3kgae OS << "// Generated code, do not edit.\n"; 612435897b4Spython3kgae OS << "\n"; 613cdfd884bSS. Bharadwaj Yadavalli // Get all DXIL Ops property records 614758fd59dSS. Bharadwaj Yadavalli std::vector<DXILOperationDesc> DXILOps; 6154fbac528SRahul Joshi for (const Record *R : Records.getAllDerivedDefinitions("DXILOp")) { 6164fbac528SRahul Joshi DXILOps.emplace_back(DXILOperationDesc(R)); 617435897b4Spython3kgae } 61894da6bfbSJustin Bogner // Sort by opcode. 6194fbac528SRahul Joshi llvm::sort(DXILOps, 6204fbac528SRahul Joshi [](const DXILOperationDesc &A, const DXILOperationDesc &B) { 62194da6bfbSJustin Bogner return A.OpCode < B.OpCode; 62294da6bfbSJustin Bogner }); 62394da6bfbSJustin Bogner int PrevOp = -1; 6244fbac528SRahul Joshi for (const DXILOperationDesc &Desc : DXILOps) { 62594da6bfbSJustin Bogner if (Desc.OpCode == PrevOp) 62694da6bfbSJustin Bogner PrintFatalError(Twine("Duplicate opcode: ") + Twine(Desc.OpCode)); 62794da6bfbSJustin Bogner PrevOp = Desc.OpCode; 62894da6bfbSJustin Bogner } 62994da6bfbSJustin Bogner 630*011b6186SFinn Plummer emitDXILVersions(Records, OS); 63140940980SJustin Bogner emitDXILOpCodes(DXILOps, OS); 63240940980SJustin Bogner emitDXILOpClasses(Records, OS); 633f357fe37SJustin Bogner emitDXILOpParamTypes(Records, OS); 634*011b6186SFinn Plummer emitDXILAttributes(Records, OS); 635*011b6186SFinn Plummer emitDXILOpAttributes(Records, DXILOps, OS); 636*011b6186SFinn Plummer emitDXILProperties(Records, OS); 637f357fe37SJustin Bogner emitDXILOpFunctionTypes(DXILOps, OS); 6380a44b24dSAdam Yang emitDXILIntrinsicArgSelectTypes(Records, OS); 6390d2dde20SXiang Li emitDXILIntrinsicMap(DXILOps, OS); 64094da6bfbSJustin Bogner OS << "#ifdef DXIL_OP_OPERATION_TABLE\n\n"; 641cdfd884bSS. Bharadwaj Yadavalli emitDXILOperationTableDataStructs(Records, OS); 6420d2dde20SXiang Li emitDXILOperationTable(DXILOps, OS); 64394da6bfbSJustin Bogner OS << "#undef DXIL_OP_OPERATION_TABLE\n"; 64494da6bfbSJustin Bogner OS << "#endif\n\n"; 645435897b4Spython3kgae } 646435897b4Spython3kgae 647cdacc9b5SJerry Sun static TableGen::Emitter::Opt X("gen-dxil-operation", emitDxilOperation, 6489c93e728SNAKAMURA Takumi "Generate DXIL operation information"); 649