[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:09:14 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(
----------------
damyanp wrote:

The clang code seems to have a diagnostic td file that these messages go into.  Is it normal practice not to do that in llvm? Or is this more about the types of errors that mean they don't go into a centralized table?

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


More information about the llvm-commits mailing list