diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -53,6 +53,26 @@ /// members used to implement virtual inheritance. enum class MSVtorDispMode { Never, ForVBaseOverride, ForVFTable }; +/// Shader programs run in specific pipeline stages. +enum class ShaderStage { + Pixel = 0, + Vertex, + Geometry, + Hull, + Domain, + Compute, + Library, + RayGeneration, + Intersection, + AnyHit, + ClosestHit, + Miss, + Callable, + Mesh, + Amplification, + Invalid, +}; + /// Keeps track of the various options that can be /// enabled, which controls the dialect of C or C++ that is accepted. class LangOptions : public LangOptionsBase { @@ -140,6 +160,16 @@ SYCL_Default = SYCL_2020 }; + enum HLSLLangStd { + HLSL_Unset = 0, + HLSL_2015 = 2015, + HLSL_2016 = 2016, + HLSL_2017 = 2017, + HLSL_2018 = 2018, + HLSL_2021 = 2021, + HLSL_202x = 2029, + }; + /// Clang versions with different platform ABI conformance. enum class ClangABI { /// Attempt to be ABI-compatible with code generated by Clang 3.8.x diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -251,6 +251,9 @@ LANGOPT(OpenMPOffloadMandatory , 1, 0, "Assert that offloading is mandatory and do not create a host fallback.") LANGOPT(RenderScript , 1, 0, "RenderScript") +LANGOPT(HLSL, 1, 0, "HLSL") +ENUM_LANGOPT(HLSLVersion, HLSLLangStd, 16, HLSL_Unset, "HLSL Version") + LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code") LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__") diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -36,6 +36,7 @@ CUDA, RenderScript, HIP, + HLSL, ///@} }; @@ -55,7 +56,8 @@ GNUMode = (1 << 12), HexFloat = (1 << 13), ImplicitInt = (1 << 14), - OpenCL = (1 << 15) + OpenCL = (1 << 15), + HLSL = (1 << 16) }; /// LangStandard - Information about the properties of a particular language diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def --- a/clang/include/clang/Basic/LangStandards.def +++ b/clang/include/clang/Basic/LangStandards.def @@ -209,6 +209,36 @@ LANGSTANDARD(hip, "hip", HIP, "HIP", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) +// HLSL +LANGSTANDARD(hlsl, "hlsl", + HLSL, "High Level Shader Language", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl2015, "hlsl2015", + HLSL, "High Level Shader Language 2015", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl2016, "hlsl2016", + HLSL, "High Level Shader Language 2016", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl2017, "hlsl2017", + HLSL, "High Level Shader Language 2017", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl2018, "hlsl2018", + HLSL, "High Level Shader Language 2018", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl2021, "hlsl2021", + HLSL, "High Level Shader Language 2021", + LineComment | HLSL | CPlusPlus ) + +LANGSTANDARD(hlsl202x, "hlsl202x", + HLSL, "High Level Shader Language 202x", + LineComment | HLSL | CPlusPlus | CPlusPlus11) + + #undef LANGSTANDARD #undef LANGSTANDARD_ALIAS #undef LANGSTANDARD_ALIAS_DEPR diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -54,6 +54,7 @@ TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("renderscript", RenderScript, PP_C, "rs", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("hlsl", HLSL, PP_CXX, "hlsl", phases::Preprocess, phases::Compile, phases::Backend) // C family input files to precompile. TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", phases::Precompile) diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -169,6 +169,7 @@ case Language::CUDA: case Language::RenderScript: case Language::HIP: + case Language::HLSL: // Languages that the frontend cannot parse and compile case Language::Unknown: 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 @@ -2623,6 +2623,9 @@ case Language::LLVM_IR: Lang = "ir"; break; + case Language::HLSL: + Lang = "hlsl"; + break; } GenerateArg(Args, OPT_x, @@ -2809,6 +2812,7 @@ .Case("objective-c", Language::ObjC) .Case("objective-c++", Language::ObjCXX) .Case("renderscript", Language::RenderScript) + .Case("hlsl", Language::HLSL) .Default(Language::Unknown); // "objc[++]-cpp-output" is an acceptable synonym for @@ -3220,6 +3224,9 @@ case Language::HIP: LangStd = LangStandard::lang_hip; break; + case Language::HLSL: + LangStd = LangStandard::lang_hlsl2021; + break; } } @@ -3241,6 +3248,8 @@ Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); + Opts.HLSL = IK.getLanguage() == Language::HLSL; + // Set OpenCL Version. Opts.OpenCL = Std.isOpenCL(); if (LangStd == LangStandard::lang_opencl10) @@ -3257,6 +3266,18 @@ Opts.OpenCLCPlusPlusVersion = 100; else if (LangStd == LangStandard::lang_openclcpp2021) Opts.OpenCLCPlusPlusVersion = 202100; + else if (LangStd == LangStandard::lang_hlsl2015) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2015; + else if (LangStd == LangStandard::lang_hlsl2016) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2016; + else if (LangStd == LangStandard::lang_hlsl2017) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2017; + else if (LangStd == LangStandard::lang_hlsl2018) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2018; + else if (LangStd == LangStandard::lang_hlsl2021) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2021; + else if (LangStd == LangStandard::lang_hlsl202x) + Opts.HLSLVersion = (unsigned)LangOptions::HLSL_202x; // OpenCL has some additional defaults. if (Opts.OpenCL) { @@ -3341,6 +3362,9 @@ // FIXME: The -std= value is not ignored; it affects the tokenization // and preprocessing rules if we're preprocessing this asm input. return true; + + case Language::HLSL: + return S.getLanguage() == Language::HLSL; } llvm_unreachable("unexpected input language"); @@ -3373,6 +3397,9 @@ case Language::LLVM_IR: return "LLVM IR"; + case Language::HLSL: + return "HLSL"; + case Language::Unknown: break; } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -1078,6 +1078,7 @@ case Language::OpenCLCXX: case Language::CUDA: case Language::HIP: + case Language::HLSL: break; case Language::Unknown: diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -371,6 +371,52 @@ const LangOptions &LangOpts, const FrontendOptions &FEOpts, MacroBuilder &Builder) { + if (LangOpts.HLSL) { + Builder.defineMacro("__hlsl_clang"); + // HLSL Version + Builder.defineMacro("__HLSL_VERSION", + Twine((unsigned)LangOpts.getHLSLVersion())); + + // Shader target information + // "enums" for shader stages + Builder.defineMacro("__SHADER_STAGE_VERTEX", + Twine((uint32_t)ShaderStage::Vertex)); + Builder.defineMacro("__SHADER_STAGE_PIXEL", + Twine((uint32_t)ShaderStage::Pixel)); + Builder.defineMacro("__SHADER_STAGE_GEOMETRY", + Twine((uint32_t)ShaderStage::Geometry)); + Builder.defineMacro("__SHADER_STAGE_HULL", + Twine((uint32_t)ShaderStage::Hull)); + Builder.defineMacro("__SHADER_STAGE_DOMAIN", + Twine((uint32_t)ShaderStage::Domain)); + Builder.defineMacro("__SHADER_STAGE_COMPUTE", + Twine((uint32_t)ShaderStage::Compute)); + Builder.defineMacro("__SHADER_STAGE_AMPLIFICATION", + Twine((uint32_t)ShaderStage::Amplification)); + Builder.defineMacro("__SHADER_STAGE_MESH", + Twine((uint32_t)ShaderStage::Mesh)); + Builder.defineMacro("__SHADER_STAGE_LIBRARY", + Twine((uint32_t)ShaderStage::Library)); + // The current shader stage itself + uint32_t StageInteger = StageInteger = + (uint32_t)TI.getTriple().getEnvironment() - + (uint32_t)llvm::Triple::Pixel; + // TODO: When we add raytracing support we can clean this up + if (TI.getTriple().getEnvironment() == llvm::Triple::Mesh) + StageInteger = (uint32_t)ShaderStage::Mesh; + else if (TI.getTriple().getEnvironment() == llvm::Triple::Amplification) + StageInteger = (uint32_t)ShaderStage::Amplification; + + Builder.defineMacro("__SHADER_TARGET_STAGE", Twine(StageInteger)); + // Add target versions + if (TI.getTriple().getOS() == llvm::Triple::ShaderModel) { + VersionTuple Version = TI.getTriple().getOSVersion(); + Builder.defineMacro("__SHADER_TARGET_MAJOR", Twine(Version.getMajor())); + unsigned Minor = Version.getMinor() ? *Version.getMinor() : 0; + Builder.defineMacro("__SHADER_TARGET_MINOR", Twine(Minor)); + } + return; + } // C++ [cpp.predefined]p1: // The following macro names shall be defined by the implementation: diff --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg --- a/clang/test/Driver/lit.local.cfg +++ b/clang/test/Driver/lit.local.cfg @@ -1,5 +1,5 @@ config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95', - '.cu', '.rs', '.cl', '.clcpp', '.hip'] + '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hlsl'] config.substitutions = list(config.substitutions) config.substitutions.insert(0, ('%clang_cc1', diff --git a/clang/test/Preprocessor/predefined-macros-hlsl.c b/clang/test/Preprocessor/predefined-macros-hlsl.c new file mode 100644 --- /dev/null +++ b/clang/test/Preprocessor/predefined-macros-hlsl.c @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-amplification | FileCheck -match-full-lines %s --check-prefixes=CHECK,AMPLIFICATION +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-compute | FileCheck -match-full-lines %s --check-prefixes=CHECK,COMPUTE +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-domain | FileCheck -match-full-lines %s --check-prefixes=CHECK,DOMAIN +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-geometry | FileCheck -match-full-lines %s --check-prefixes=CHECK,GEOMETRY +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-hull | FileCheck -match-full-lines %s --check-prefixes=CHECK,HULL +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-library | FileCheck -match-full-lines %s --check-prefixes=CHECK,LIBRARY +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-mesh | FileCheck -match-full-lines %s --check-prefixes=CHECK,MESH +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-pixel | FileCheck -match-full-lines %s --check-prefixes=CHECK,PIXEL +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -triple dxil-pc-shadermodel6.0-vertex | FileCheck -match-full-lines %s --check-prefixes=CHECK,VERTEX + +// CHECK: #define __HLSL_VERSION 2021 +// CHECK: #define __SHADER_STAGE_AMPLIFICATION 14 +// CHECK: #define __SHADER_STAGE_COMPUTE 5 +// CHECK: #define __SHADER_STAGE_DOMAIN 4 +// CHECK: #define __SHADER_STAGE_GEOMETRY 2 +// CHECK: #define __SHADER_STAGE_HULL 3 +// CHECK: #define __SHADER_STAGE_LIBRARY 6 +// CHECK: #define __SHADER_STAGE_MESH 13 +// CHECK: #define __SHADER_STAGE_PIXEL 0 +// CHECK: #define __SHADER_STAGE_VERTEX 1 + +// AMPLIFICATION: #define __SHADER_TARGET_STAGE 14 +// COMPUTE: #define __SHADER_TARGET_STAGE 5 +// DOMAIN: #define __SHADER_TARGET_STAGE 4 +// GEOMETRY: #define __SHADER_TARGET_STAGE 2 +// HULL: #define __SHADER_TARGET_STAGE 3 +// LIBRARY: #define __SHADER_TARGET_STAGE 6 +// MESH: #define __SHADER_TARGET_STAGE 13 +// PIXEL: #define __SHADER_TARGET_STAGE 0 +// VERTEX: #define __SHADER_TARGET_STAGE 1 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl2015 | FileCheck -match-full-lines %s --check-prefixes=STD2015 +// STD2015: #define __HLSL_VERSION 2015 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl2016 | FileCheck -match-full-lines %s --check-prefixes=STD2016 +// STD2016: #define __HLSL_VERSION 2016 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl2017 | FileCheck -match-full-lines %s --check-prefixes=STD2017 +// STD2017: #define __HLSL_VERSION 2017 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl2018 | FileCheck -match-full-lines %s --check-prefixes=STD2018 +// STD2018: #define __HLSL_VERSION 2018 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl2021 | FileCheck -match-full-lines %s --check-prefixes=STD2021 +// STD2021: #define __HLSL_VERSION 2021 + +// RUN: %clang_cc1 %s -E -dM -o - -x hlsl -std=hlsl202x | FileCheck -match-full-lines %s --check-prefixes=STD202x +// STD202x: #define __HLSL_VERSION 2029 diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -25,7 +25,7 @@ config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.c', '.cpp', '.i', '.cppm', '.m', '.mm', '.cu', '.hip', +config.suffixes = ['.c', '.cpp', '.i', '.cppm', '.m', '.mm', '.cu', '.hip', '.hlsl', '.ll', '.cl', '.clcpp', '.s', '.S', '.modulemap', '.test', '.rs', '.ifs', '.rc'] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -1888,3 +1888,17 @@ return Version; } } + +// HLSL triple environment orders are relied on in the front end +static_assert(Triple::Vertex - Triple::Pixel == 1, + "incorrect HLSL stage order"); +static_assert(Triple::Geometry - Triple::Pixel == 2, + "incorrect HLSL stage order"); +static_assert(Triple::Hull - Triple::Pixel == 3, + "incorrect HLSL stage order"); +static_assert(Triple::Domain - Triple::Pixel == 4, + "incorrect HLSL stage order"); +static_assert(Triple::Compute - Triple::Pixel == 5, + "incorrect HLSL stage order"); +static_assert(Triple::Library - Triple::Pixel == 6, + "incorrect HLSL stage order");