[llvm] [DXIL] Add constraint specification and backend implementation of DXIL Ops (PR #97593)

Damyan Pepper via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 14:19:19 PDT 2024


================
@@ -469,28 +561,138 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops,
   OS << "}\n ";
 }
 
+static void emitDXILOperationTableDataStructs(RecordKeeper &Records,
+                                              raw_ostream &OS) {
+  // Get Shader stage records
+  std::vector<Record *> ShaderKindRecs =
+      Records.getAllDerivedDefinitions("ShaderStage");
+  // Sort records by name
+  llvm::sort(ShaderKindRecs,
+             [](Record *A, Record *B) { return A->getName() < B->getName(); });
+
+  OS << "// Valid shader kinds\n\n";
+  // Choose the type of enum ShaderKind based on the number of stages declared
+  // plus one for allKinds
+  // This gives the flexibility to just add add new stage records in DXIL.td, if
+  // needed, with no need to change this backend code.
+  uint64_t ShaderKindCount = PowerOf2Ceil(ShaderKindRecs.size() + 1);
+  OS << "enum ShaderKind : uint" << ShaderKindCount << "_t {\n";
+  const std::string allKinds("allKinds");
+  // set unknown kind to 0
+  OS << "  Unknown = 0,\n";
+  int shiftVal = 1;
+  for (auto R : ShaderKindRecs) {
+    auto Name = R->getName();
+    if (Name.compare(allKinds)) {
+      OS << "  " << Name << " = 1 << " << std::to_string(shiftVal++) << ",\n";
+    }
+  }
+  // allkinds is set to (1 << ShaderKindCount) - 1, with all bits set denoting
+  // support for all stages
+  OS << "  " << allKinds << " =  0x"
+     << utohexstr(((1 << shiftVal) - 1), false, 0) << "\n";
+  OS << "}; // enum ShaderKind\n\n";
+
+  // Emit definitions of various data types used to define DXIL Operation table
+  // entries.
+
+  // Emit enum OverloadKind with valid overload types.
+  const SmallVector<std::string> OverloadKindList = {
+      "VOID", "HALF", "FLOAT", "DOUBLE",          "I1",        "I8",
+      "I16",  "I32",  "I64",   "UserDefinedType", "ObjectType"};
+  // Choose the type of enum OverloadKind based on the number of valid types in
+  // OverloadKindList. This gives the flexibility to just add new supported
+  // types to the list above, if needed, with no need to change this backend
+  // code.
+  unsigned OverloadKindCount = PowerOf2Ceil(OverloadKindList.size());
+  OS << "enum OverloadKind : uint" << OverloadKindCount << "_t {\n";
+  OS << "    UNDEFINED = 0,\n";
+  shiftVal = 1;
+  for (auto TyStr : OverloadKindList) {
+    OS << "    " << TyStr << " = 1 << " << shiftVal++ << ",\n";
+  }
+  OS << "  }; \n";
+
+  // Emit a convenience struct Version to encode Shader Model version specified
+  // in constraints
+  OS << "struct Version { \n \
+            unsigned Major = 0; \n \
+            unsigned Minor = 0; \n \
+          };\n\n";
+
+  // Emit struct Constraints that encapsulate overload and shader kind
+  // constraints predicated on shader model version, if any.
+  OS << "struct OpConstraints { \n \
+            Version ShaderModelVer; \n";
+  OS << "             uint" << OverloadKindCount << "_t ValidTys; \n";
+  OS << "             uint" << ShaderKindCount << "_t ValidShaderKinds; \n \
+        };\n\n";
+
+  // Emit struct OpCodeProperty record that encapsulates DXIL Op information.
+  OS << "struct OpCodeProperty { \n \
+            dxil::OpCode OpCode; \n \
+            // Offset in DXILOpCodeNameTable. \n \
+            unsigned OpCodeNameOffset; \n \
+            dxil::OpCodeClass OpCodeClass; \n \
+            // Offset in DXILOpCodeClassNameTable. \n \
+            unsigned OpCodeClassNameOffset; \n \
+            std::vector<OpConstraints> Constraints; \n \
+            llvm::Attribute::AttrKind FuncAttr; \n \
+            int OverloadParamIndex;        // parameter index which control the overload. \n \
+                                           // When < 0, should be only 1 overload type. \n \
+            unsigned NumOfParameters;      // Number of parameters include return value. \n \
+            unsigned ParameterTableOffset; // Offset in ParameterTable. \n \
+          };\n\n";
+
+  // Emit access function getOverloadTypeName()
+  OS << "static const char *getOverloadTypeName(OverloadKind Kind) { \n \
----------------
damyanp wrote:

Any reason not to use raw string literals here so there's less escaping?

https://github.com/llvm/llvm-project/pull/97593


More information about the llvm-commits mailing list