[llvm] [DXIL] Add DXIL version-specific TableGen specification and implementation of DXIL Ops (PR #97593)

Chris B via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 13:01:31 PDT 2024


================
@@ -249,17 +228,102 @@ static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop,
       ArgTys[0], ArrayRef<Type *>(&ArgTys[1], ArgTys.size() - 1), false);
 }
 
+static int getValidConstraintIndex(const OpCodeProperty *Prop,
+                                   const VersionTuple SMVer) {
+  // std::vector Prop->Constraints is in ascending order of SM Version
+  // Overloads of highest SM version that is not greater than SMVer
+  // are the ones that are valid for SMVer.
+  auto Size = Prop->Constraints.size();
+  for (int I = Size - 1; I >= 0; I--) {
+    auto OL = Prop->Constraints[I];
+    if (VersionTuple(OL.ShaderModelVer.Major, OL.ShaderModelVer.Minor) <=
+        SMVer) {
+      return I;
+    }
+  }
+  report_fatal_error(
+      StringRef(SMVer.getAsString().append(": Unknown Shader Model Version")),
+      /*gen_crash_diag*/ false);
+
+  return -1;
+}
+
 namespace llvm {
 namespace dxil {
 
 CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy,
                                           Type *OverloadTy,
                                           SmallVector<Value *> Args) {
+
+  std::string TTStr = M.getTargetTriple();
+  // No extra checks need be performed to verify that the Triple is
+  // well-formed or the target is supported since these checks would have
+  // been done at the time the module M is constructed in the earlier stages of
+  // compilation.
+  auto Major = Triple(TTStr).getOSVersion().getMajor();
+  auto MinorOrErr = Triple(TTStr).getOSVersion().getMinor();
+  uint32_t Minor = MinorOrErr.has_value() ? *MinorOrErr : 0;
+  VersionTuple SMVer(Major, Minor);
+  // Get Shader Stage Kind
+  Triple::EnvironmentType ShaderEnv = Triple(TTStr).getEnvironment();
+  auto ShaderEnvStr = Triple(TTStr).getEnvironmentName();
+
   const OpCodeProperty *Prop = getOpCodeProperty(OpCode);
+  int Index = getValidConstraintIndex(Prop, SMVer);
+  uint16_t ValidTyMask = Prop->Constraints[Index].ValidTys;
 
   OverloadKind Kind = getOverloadKind(OverloadTy);
-  if ((Prop->OverloadTys & (uint16_t)Kind) == 0) {
-    report_fatal_error("Invalid Overload Type", /* gen_crash_diag=*/false);
+
+  // Check if the operation supports overload types and OverloadTy is valid
+  // per the specified types for the operation
+  if ((ValidTyMask != OverloadKind::UNDEFINED) &&
+      (ValidTyMask & (uint16_t)Kind) == 0) {
+    report_fatal_error(
+        StringRef(std::string("Invalid Overload Type for DXIL operation - ")
+                      .append(getOpCodeName((OpCode)))),
+        /* gen_crash_diag=*/false);
+  }
+
+  // Ensure Environment type is known
+  if (ShaderEnv == Triple::UnknownEnvironment) {
+    report_fatal_error(
+        StringRef(SMVer.getAsString().append(
+            ": Unknown Compilation Target Shader Stage specified ")),
+        /*gen_crash_diag*/ false);
+  }
+
+  // Perform necessary checks to ensure Opcode is valid in the targeted shader
+  // kind
+  uint16_t ValidShaderKindMask = Prop->Constraints[Index].ValidShaderKinds;
+  enum ShaderKind ModuleStagekind = getShaderKindEnum(ShaderEnv);
+
+  // Ensure valid shader stage constraints are specified
+  if (ValidShaderKindMask == ShaderKind::Unknown) {
+    report_fatal_error(
----------------
llvm-beanz wrote:

There isn't really an equivalent to Clang's diagnostic tablegen in LLVM. Generally LLVM's errors are all fatal so they report this way (basically exiting the compiler).

We may want to consider a larger design proposal for LLVM to allow passes to propagate errors up. This has been discussed in the past, but never really worked on.

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


More information about the llvm-commits mailing list