[clang] e504194 - [Driver][HLSL] Improve diagnostics for invalid shader model and stage

Justin Bogner via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 13 11:14:09 PDT 2023


Author: Justin Bogner
Date: 2023-09-13T10:45:39-07:00
New Revision: e504194d51e1f0f7ca5b684b4aa99db4940856c2

URL: https://github.com/llvm/llvm-project/commit/e504194d51e1f0f7ca5b684b4aa99db4940856c2
DIFF: https://github.com/llvm/llvm-project/commit/e504194d51e1f0f7ca5b684b4aa99db4940856c2.diff

LOG: [Driver][HLSL] Improve diagnostics for invalid shader model and stage

This adds more validation that a dxil triple is actually useable when
compiling HLSL.

The OS field of the triple needs to be a versioned shader model.
Later, we should set a default if this is empty and check that the
version is a shader model we can actually handle.

The Environment field of the triple needs to be specified and be a
valid shader stage. I'd like to allow this to be empty and treat it
like library, but allowing that currently crashes in DXIL metadata
handling.

Differential Revision: https://reviews.llvm.org/D159103

Added: 
    clang/test/Driver/hlsl-lang-targets-spirv.hlsl

Modified: 
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/test/Driver/hlsl-lang-targets.hlsl
    llvm/include/llvm/TargetParser/Triple.h

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 73264181ca1c5c4..86567267cfb437a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -706,6 +706,11 @@ def err_drv_dxc_missing_target_profile : Error<
   "target profile option (-T) is missing">;
 def err_drv_hlsl_unsupported_target : Error<
   "HLSL code generation is unsupported for target '%0'">;
+def err_drv_hlsl_bad_shader_required_in_target : Error<
+  "shader %select{model|stage}0 is required in target '%1' for HLSL code generation">;
+
+def err_drv_hlsl_bad_shader_unsupported : Error<
+  "shader %select{model|stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
 def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
     "Resulting DXIL will not be validated or signed for use in release environments.">,
     InGroup<DXILValidation>;

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 73a3d3160370f0c..730db8e394f66f1 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4143,10 +4143,24 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
 
   // Validate options for HLSL
   if (Opts.HLSL) {
-    bool SupportedTarget = (T.getArch() == llvm::Triple::dxil ||
-                            T.getArch() == llvm::Triple::spirv) &&
-                           T.getOS() == llvm::Triple::ShaderModel;
-    if (!SupportedTarget)
+    // TODO: Revisit restricting SPIR-V to logical once we've figured out how to
+    // handle PhysicalStorageBuffer64 memory model
+    if (T.isDXIL() || T.isSPIRVLogical()) {
+      enum { ShaderModel, ShaderStage };
+      if (T.getOSName().empty()) {
+        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
+            << ShaderModel << T.str();
+      } else if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
+        Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
+            << ShaderModel << T.getOSName() << T.str();
+      } else if (T.getEnvironmentName().empty()) {
+        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
+            << ShaderStage << T.str();
+      } else if (!T.isShaderStageEnvironment()) {
+        Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
+            << ShaderStage << T.getEnvironmentName() << T.str();
+      }
+    } else
       Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
   }
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7fdef9ab5514757..7d92e93188610c0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12394,10 +12394,7 @@ void Sema::ActOnHLSLTopLevelFunction(FunctionDecl *FD) {
     case llvm::Triple::Library:
       break;
     default:
-      // TODO: This should probably just be llvm_unreachable and we should
-      // reject triples with random ABIs and such when we build the target.
-      // For now, crash.
-      llvm::report_fatal_error("Unhandled environment in triple");
+      llvm_unreachable("Unhandled environment in triple");
     }
   }
 }

diff  --git a/clang/test/Driver/hlsl-lang-targets-spirv.hlsl b/clang/test/Driver/hlsl-lang-targets-spirv.hlsl
new file mode 100644
index 000000000000000..ff29f143ba1dc8e
--- /dev/null
+++ b/clang/test/Driver/hlsl-lang-targets-spirv.hlsl
@@ -0,0 +1,31 @@
+// REQUIRES: spirv-registered-target
+
+// Supported targets
+//
+// RUN: %clang -target dxil-unknown-shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
+// RUN: %clang -target spirv-unknown-shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
+
+// Empty shader model
+//
+// RUN: not %clang -target spirv %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s
+
+// Invalid shader models
+//
+// RUN: not %clang -target spirv--unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+
+// Empty shader stage
+//
+// RUN: not %clang -target spirv--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
+
+// Invalid shader stages
+//
+// RUN: not %clang -target spirv--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
+
+// CHECK-VALID-NOT: error:
+// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
+// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
+// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
+// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
+
+[shader("pixel")]
+void main() {}

diff  --git a/clang/test/Driver/hlsl-lang-targets.hlsl b/clang/test/Driver/hlsl-lang-targets.hlsl
index a757e2a3cdf74de..816e84cdc6dcbfd 100644
--- a/clang/test/Driver/hlsl-lang-targets.hlsl
+++ b/clang/test/Driver/hlsl-lang-targets.hlsl
@@ -1,14 +1,53 @@
-// RUN: not %clang -target x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=X86
-// RUN: not %clang -target dxil-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=DXIL
-// RUN: not %clang -target x86_64-unknown-shadermodel %s 2>&1 | FileCheck %s --check-prefix=SM
-// RUN: not %clang -target spirv64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=SPIRV
+// REQUIRES: dxil-registered-target
 
+// Supported targets
+//
+// RUN: %clang -target dxil--shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
+// RUN: %clang -target dxil-unknown-shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
+// RUN: %clang -target dxil--shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
+// RUN: %clang -target dxil-unknown-shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
 
-// A completely unsupported target...
-// X86: error: HLSL code generation is unsupported for target 'x86_64-unknown-unknown'
+// Empty shader model
+//
+// RUN: not %clang -target dxil %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s
 
-// Poorly specified targets
-// DXIL: error: HLSL code generation is unsupported for target 'dxil-unknown-unknown'
-// SM: error: HLSL code generation is unsupported for target 'x86_64-unknown-shadermodel'
+// Invalid shader models
+//
+// RUN: not %clang -target dxil--linux %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+// RUN: not %clang -target dxil--win32 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+// RUN: not %clang -target dxil--unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+// RUN: not %clang -target dxil--invalidos %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
 
-// FIXME// SPIRV: error: HLSL code generation is unsupported for target 'spirv64-unknown-unknown'
+// Bad shader model versions. Currently we just check for any version at all.
+//
+// RUN: not %clang -target dxil--shadermodel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+// RUN: not %clang -target dxil--shadermodel0.0 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
+
+// Empty shader stage
+//
+// RUN: not %clang -target dxil-shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
+// RUN: not %clang -target dxil--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
+// RUN: not %clang -target dxil--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
+
+// Invalid shader stages
+//
+// RUN: not %clang -target dxil--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
+// RUN: not %clang -target dxil--shadermodel6.2-invalidenvironment %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
+// RUN: not %clang -target dxil--shadermodel6.2-eabi %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
+// RUN: not %clang -target dxil--shadermodel6.2-msvc %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
+
+// Non-dxil targets
+//
+// RUN: not %clang -target x86_64-unknown-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
+// RUN: not %clang -target x86_64-linux %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
+// RUN: not %clang -target amdgcn %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
+
+// CHECK-VALID-NOT: error:
+// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
+// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
+// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
+// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
+// CHECK-BAD-TARGET: error: HLSL code generation is unsupported for target '{{.*}}'
+
+[shader("pixel")]
+void main() {}

diff  --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index b3fc6a9dee0447d..53cef0abbe0e139 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -271,7 +271,9 @@ class Triple {
     Callable,
     Mesh,
     Amplification,
+
     OpenHOS,
+
     LastEnvironmentType = OpenHOS
   };
   enum ObjectFormatType {
@@ -756,6 +758,22 @@ class Triple {
     return getArch() == Triple::dxil;
   }
 
+  bool isShaderModelOS() const {
+    return getOS() == Triple::ShaderModel;
+  }
+
+  bool isShaderStageEnvironment() const {
+    EnvironmentType Env = getEnvironment();
+    return Env == Triple::Pixel || Env == Triple::Vertex ||
+           Env == Triple::Geometry || Env == Triple::Hull ||
+           Env == Triple::Domain || Env == Triple::Compute ||
+           Env == Triple::Library || Env == Triple::RayGeneration ||
+           Env == Triple::Intersection || Env == Triple::AnyHit ||
+           Env == Triple::ClosestHit || Env == Triple::Miss ||
+           Env == Triple::Callable || Env == Triple::Mesh ||
+           Env == Triple::Amplification;
+  }
+
   /// Tests whether the target is SPIR (32- or 64-bit).
   bool isSPIR() const {
     return getArch() == Triple::spir || getArch() == Triple::spir64;
@@ -767,6 +785,11 @@ class Triple {
            getArch() == Triple::spirv;
   }
 
+  /// Tests whether the target is SPIR-V Logical
+  bool isSPIRVLogical() const {
+    return getArch() == Triple::spirv;
+  }
+
   /// Tests whether the target is NVPTX (32- or 64-bit).
   bool isNVPTX() const {
     return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;


        


More information about the cfe-commits mailing list