xref: /llvm-project/llvm/utils/TableGen/DXILEmitter.cpp (revision 011b618644113996e2c0a8e57db40f89d20878e3)
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