diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -706,6 +706,11 @@ "target profile option (-T) is missing">; def err_drv_hlsl_unsupported_target : Error< "HLSL code generation is unsupported for target '%0'">; +def err_drv_dxil_bad_shader_required_in_target : Error< + "shader %select{model|stage}0 is required in target '%1' for DXIL generation">; + +def err_drv_dxil_bad_shader_unsupported : Error< + "shader %select{model|stage}0 '%1' in target '%2' is invalid for DXIL 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; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4143,10 +4143,22 @@ // 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) + if (T.isDXIL() || T.isSPIRV) { + enum { ShaderModel, ShaderStage }; + if (T.getOSName().empty()) { + Diags.Report(diag::err_drv_dxil_bad_shader_required_in_target) + << ShaderModel << T.str(); + } else if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) { + Diags.Report(diag::err_drv_dxil_bad_shader_unsupported) + << ShaderModel << T.getOSName() << T.str(); + } else if (T.getEnvironmentName().empty()) { + Diags.Report(diag::err_drv_dxil_bad_shader_required_in_target) + << ShaderStage << T.str(); + } else if (!T.isShaderStageEnvironment()) { + Diags.Report(diag::err_drv_dxil_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 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12394,10 +12394,7 @@ 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.hlsl b/clang/test/Driver/hlsl-lang-targets.hlsl --- a/clang/test/Driver/hlsl-lang-targets.hlsl +++ b/clang/test/Driver/hlsl-lang-targets.hlsl @@ -1,14 +1,52 @@ -// 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 +// 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 +// Empty shader model +// +// RUN: not %clang -target dxil %s -S -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK-NO-OS %s -// A completely unsupported target... -// X86: error: HLSL code generation is unsupported for target 'x86_64-unknown-unknown' +// 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 -// 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' +// 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 -// FIXME// SPIRV: error: HLSL code generation is unsupported for target 'spirv64-unknown-unknown' +// 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 +// RUN: not %clang -target spirv64-unknown-unknown %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 DXIL generation +// CHECK-BAD-OS: error: shader model '{{.*}}' in target '{{.*}}' is invalid for DXIL generation +// CHECK-NO-ENV: error: shader stage is required in target '{{.*}}' for DXIL generation +// CHECK-BAD-ENV: error: shader stage '{{.*}}' in target '{{.*}}' is invalid for DXIL 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 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -271,7 +271,9 @@ Callable, Mesh, Amplification, + OpenHOS, + LastEnvironmentType = OpenHOS }; enum ObjectFormatType { @@ -756,6 +758,22 @@ 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;