Skip to content

Commit e504194

Browse files
committed
[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
1 parent 25e8105 commit e504194

File tree

6 files changed

+127
-18
lines changed

6 files changed

+127
-18
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,11 @@ def err_drv_dxc_missing_target_profile : Error<
706706
"target profile option (-T) is missing">;
707707
def err_drv_hlsl_unsupported_target : Error<
708708
"HLSL code generation is unsupported for target '%0'">;
709+
def err_drv_hlsl_bad_shader_required_in_target : Error<
710+
"shader %select{model|stage}0 is required in target '%1' for HLSL code generation">;
711+
712+
def err_drv_hlsl_bad_shader_unsupported : Error<
713+
"shader %select{model|stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
709714
def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
710715
"Resulting DXIL will not be validated or signed for use in release environments.">,
711716
InGroup<DXILValidation>;

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4143,10 +4143,24 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
41434143

41444144
// Validate options for HLSL
41454145
if (Opts.HLSL) {
4146-
bool SupportedTarget = (T.getArch() == llvm::Triple::dxil ||
4147-
T.getArch() == llvm::Triple::spirv) &&
4148-
T.getOS() == llvm::Triple::ShaderModel;
4149-
if (!SupportedTarget)
4146+
// TODO: Revisit restricting SPIR-V to logical once we've figured out how to
4147+
// handle PhysicalStorageBuffer64 memory model
4148+
if (T.isDXIL() || T.isSPIRVLogical()) {
4149+
enum { ShaderModel, ShaderStage };
4150+
if (T.getOSName().empty()) {
4151+
Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4152+
<< ShaderModel << T.str();
4153+
} else if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
4154+
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4155+
<< ShaderModel << T.getOSName() << T.str();
4156+
} else if (T.getEnvironmentName().empty()) {
4157+
Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
4158+
<< ShaderStage << T.str();
4159+
} else if (!T.isShaderStageEnvironment()) {
4160+
Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4161+
<< ShaderStage << T.getEnvironmentName() << T.str();
4162+
}
4163+
} else
41504164
Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
41514165
}
41524166

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12394,10 +12394,7 @@ void Sema::ActOnHLSLTopLevelFunction(FunctionDecl *FD) {
1239412394
case llvm::Triple::Library:
1239512395
break;
1239612396
default:
12397-
// TODO: This should probably just be llvm_unreachable and we should
12398-
// reject triples with random ABIs and such when we build the target.
12399-
// For now, crash.
12400-
llvm::report_fatal_error("Unhandled environment in triple");
12397+
llvm_unreachable("Unhandled environment in triple");
1240112398
}
1240212399
}
1240312400
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// REQUIRES: spirv-registered-target
2+
3+
// Supported targets
4+
//
5+
// RUN: %clang -target dxil-unknown-shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
6+
// RUN: %clang -target spirv-unknown-shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
7+
8+
// Empty shader model
9+
//
10+
// RUN: not %clang -target spirv %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s
11+
12+
// Invalid shader models
13+
//
14+
// RUN: not %clang -target spirv--unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
15+
16+
// Empty shader stage
17+
//
18+
// RUN: not %clang -target spirv--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
19+
20+
// Invalid shader stages
21+
//
22+
// RUN: not %clang -target spirv--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
23+
24+
// CHECK-VALID-NOT: error:
25+
// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
26+
// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
27+
// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
28+
// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
29+
30+
[shader("pixel")]
31+
void main() {}
Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,53 @@
1-
// RUN: not %clang -target x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=X86
2-
// RUN: not %clang -target dxil-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=DXIL
3-
// RUN: not %clang -target x86_64-unknown-shadermodel %s 2>&1 | FileCheck %s --check-prefix=SM
4-
// RUN: not %clang -target spirv64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=SPIRV
1+
// REQUIRES: dxil-registered-target
52

3+
// Supported targets
4+
//
5+
// RUN: %clang -target dxil--shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
6+
// RUN: %clang -target dxil-unknown-shadermodel6.2-pixel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
7+
// RUN: %clang -target dxil--shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
8+
// RUN: %clang -target dxil-unknown-shadermodel6.2-library %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-VALID %s
69

7-
// A completely unsupported target...
8-
// X86: error: HLSL code generation is unsupported for target 'x86_64-unknown-unknown'
10+
// Empty shader model
11+
//
12+
// RUN: not %clang -target dxil %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s
913

10-
// Poorly specified targets
11-
// DXIL: error: HLSL code generation is unsupported for target 'dxil-unknown-unknown'
12-
// SM: error: HLSL code generation is unsupported for target 'x86_64-unknown-shadermodel'
14+
// Invalid shader models
15+
//
16+
// RUN: not %clang -target dxil--linux %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
17+
// RUN: not %clang -target dxil--win32 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
18+
// RUN: not %clang -target dxil--unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
19+
// RUN: not %clang -target dxil--invalidos %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
1320

14-
// FIXME// SPIRV: error: HLSL code generation is unsupported for target 'spirv64-unknown-unknown'
21+
// Bad shader model versions. Currently we just check for any version at all.
22+
//
23+
// RUN: not %clang -target dxil--shadermodel %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
24+
// RUN: not %clang -target dxil--shadermodel0.0 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-OS %s
25+
26+
// Empty shader stage
27+
//
28+
// RUN: not %clang -target dxil-shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
29+
// RUN: not %clang -target dxil--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
30+
// RUN: not %clang -target dxil--shadermodel6.2 %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-ENV %s
31+
32+
// Invalid shader stages
33+
//
34+
// RUN: not %clang -target dxil--shadermodel6.2-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
35+
// RUN: not %clang -target dxil--shadermodel6.2-invalidenvironment %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
36+
// RUN: not %clang -target dxil--shadermodel6.2-eabi %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
37+
// RUN: not %clang -target dxil--shadermodel6.2-msvc %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-ENV %s
38+
39+
// Non-dxil targets
40+
//
41+
// RUN: not %clang -target x86_64-unknown-unknown %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
42+
// RUN: not %clang -target x86_64-linux %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
43+
// RUN: not %clang -target amdgcn %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-BAD-TARGET %s
44+
45+
// CHECK-VALID-NOT: error:
46+
// CHECK-NO-OS: error: shader model is required in target '{{.*}}' for HLSL code generation
47+
// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
48+
// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for HLSL code generation
49+
// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for HLSL code generation
50+
// CHECK-BAD-TARGET: error: HLSL code generation is unsupported for target '{{.*}}'
51+
52+
[shader("pixel")]
53+
void main() {}

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,9 @@ class Triple {
271271
Callable,
272272
Mesh,
273273
Amplification,
274+
274275
OpenHOS,
276+
275277
LastEnvironmentType = OpenHOS
276278
};
277279
enum ObjectFormatType {
@@ -756,6 +758,22 @@ class Triple {
756758
return getArch() == Triple::dxil;
757759
}
758760

761+
bool isShaderModelOS() const {
762+
return getOS() == Triple::ShaderModel;
763+
}
764+
765+
bool isShaderStageEnvironment() const {
766+
EnvironmentType Env = getEnvironment();
767+
return Env == Triple::Pixel || Env == Triple::Vertex ||
768+
Env == Triple::Geometry || Env == Triple::Hull ||
769+
Env == Triple::Domain || Env == Triple::Compute ||
770+
Env == Triple::Library || Env == Triple::RayGeneration ||
771+
Env == Triple::Intersection || Env == Triple::AnyHit ||
772+
Env == Triple::ClosestHit || Env == Triple::Miss ||
773+
Env == Triple::Callable || Env == Triple::Mesh ||
774+
Env == Triple::Amplification;
775+
}
776+
759777
/// Tests whether the target is SPIR (32- or 64-bit).
760778
bool isSPIR() const {
761779
return getArch() == Triple::spir || getArch() == Triple::spir64;
@@ -767,6 +785,11 @@ class Triple {
767785
getArch() == Triple::spirv;
768786
}
769787

788+
/// Tests whether the target is SPIR-V Logical
789+
bool isSPIRVLogical() const {
790+
return getArch() == Triple::spirv;
791+
}
792+
770793
/// Tests whether the target is NVPTX (32- or 64-bit).
771794
bool isNVPTX() const {
772795
return getArch() == Triple::nvptx || getArch() == Triple::nvptx64;

0 commit comments

Comments
 (0)