https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/156373
>From 64237b0b410049018a093a4b9d35ba7346b729dc Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Fri, 29 Aug 2025 09:42:59 -0700 Subject: [PATCH 01/14] add support for rootsig as an hlsl environment --- clang/include/clang/Basic/Attr.td | 1 + clang/include/clang/Driver/Options.td | 3 ++- clang/lib/Driver/ToolChains/HLSL.cpp | 5 +++++ clang/lib/Sema/SemaHLSL.cpp | 4 ++++ llvm/include/llvm/TargetParser/Triple.h | 3 ++- llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp | 2 ++ llvm/lib/TargetParser/Triple.cpp | 3 +++ 7 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 29364c5903d31..f9a8f2f555fbe 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1185,6 +1185,7 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm .Case("callable", llvm::Triple::Callable) .Case("mesh", llvm::Triple::Mesh) .Case("amplification", llvm::Triple::Amplification) + .Case("rootsignature", llvm::Triple::RootSignature) .Case("library", llvm::Triple::Library) .Default(llvm::Triple::UnknownEnvironment); } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f507968d30670..0ca2baada1421 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9430,7 +9430,8 @@ def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">, "cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7," "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x," "ms_6_5, ms_6_6, ms_6_7," - "as_6_5, as_6_6, as_6_7">; + "as_6_5, as_6_6, as_6_7," + "rootsig_1_0, rootsig_1_1">; def emit_pristine_llvm : DXCFlag<"emit-pristine-llvm">, HelpText<"Emit pristine LLVM IR from the frontend by not running any LLVM passes at all." "Same as -S + -emit-llvm + -disable-llvm-passes.">; diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 660661945d62a..304c367cc4367 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -62,6 +62,10 @@ bool isLegalShaderModel(Triple &T) { VersionTuple MinVer(6, 5); return MinVer <= Version; } break; + case Triple::EnvironmentType::RootSignature: + VersionTuple MinVer(1, 0); + VersionTuple MaxVer(1, 1); + return MinVer <= Version && Version <= MaxVer; } return false; } @@ -84,6 +88,7 @@ std::optional<std::string> tryParseProfile(StringRef Profile) { .Case("lib", Triple::EnvironmentType::Library) .Case("ms", Triple::EnvironmentType::Mesh) .Case("as", Triple::EnvironmentType::Amplification) + .Case("rootsig", Triple::EnvironmentType::RootSignature) .Default(Triple::EnvironmentType::UnknownEnvironment); if (Kind == Triple::EnvironmentType::UnknownEnvironment) return std::nullopt; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 1e5ec952c1ecf..9e99f9a1525a9 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -765,6 +765,8 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { case llvm::Triple::UnknownEnvironment: case llvm::Triple::Library: break; + case llvm::Triple::RootSignature: + llvm_unreachable("rootsig environment has no functions"); default: llvm_unreachable("Unhandled environment in triple"); } @@ -827,6 +829,8 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { } } break; + case llvm::Triple::RootSignature: + llvm_unreachable("rootsig environment has no function entry point"); default: llvm_unreachable("Unhandled environment in triple"); } diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index ede9797ac7488..891f2de60a4d4 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -303,6 +303,7 @@ class Triple { Callable, Mesh, Amplification, + RootSignature, OpenCL, OpenHOS, Mlibc, @@ -870,7 +871,7 @@ class Triple { Env == Triple::Intersection || Env == Triple::AnyHit || Env == Triple::ClosestHit || Env == Triple::Miss || Env == Triple::Callable || Env == Triple::Mesh || - Env == Triple::Amplification; + Env == Triple::Amplification || Env == Triple::RootSignature; } /// Tests whether the target is SPIR (32- or 64-bit). diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 82bcacee7a6dd..9eebcc9b13063 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -127,6 +127,8 @@ static StringRef getShortShaderStage(Triple::EnvironmentType Env) { return "ms"; case Triple::Amplification: return "as"; + case Triple::RootSignature: + return "rootsig"; default: break; } diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 6acb0bc49ecfe..fa0d6974b3042 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -387,6 +387,8 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { case Callable: return "callable"; case Mesh: return "mesh"; case Amplification: return "amplification"; + case RootSignature: + return "rootsignature"; case OpenCL: return "opencl"; case OpenHOS: return "ohos"; @@ -780,6 +782,7 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("callable", Triple::Callable) .StartsWith("mesh", Triple::Mesh) .StartsWith("amplification", Triple::Amplification) + .StartsWith("rootsignature", Triple::RootSignature) .StartsWith("opencl", Triple::OpenCL) .StartsWith("ohos", Triple::OpenHOS) .StartsWith("pauthtest", Triple::PAuthTest) >From 9fc43d49920e4545b02df9f9ece2ee5be5435163 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 12:40:32 -0700 Subject: [PATCH 02/14] add profile test --- llvm/unittests/TargetParser/TripleTest.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp index 35927e340a257..635b9f4f1e219 100644 --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -546,6 +546,22 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(VersionTuple(1, 8), T.getDXILVersion()); EXPECT_EQ(Triple::Amplification, T.getEnvironment()); + T = Triple("dxilv1.0-unknown-shadermodel1.0-rootsignature"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_0, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 0), T.getDXILVersion()); + EXPECT_EQ(Triple::RootSignature, T.getEnvironment()); + + T = Triple("dxilv1.1-unknown-shadermodel1.1-rootsignature"); + EXPECT_EQ(Triple::dxil, T.getArch()); + EXPECT_EQ(Triple::DXILSubArch_v1_1, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(VersionTuple(1, 1), T.getDXILVersion()); + EXPECT_EQ(Triple::RootSignature, T.getEnvironment()); + T = Triple("dxilv1.8-unknown-shadermodel6.15-library"); EXPECT_EQ(Triple::dxil, T.getArch()); EXPECT_EQ(Triple::DXILSubArch_v1_8, T.getSubArch()); >From 11f61c163cc7a89e15142b37958d205ff1973e0b Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Fri, 29 Aug 2025 10:26:38 -0700 Subject: [PATCH 03/14] introduce custom handling for root signature target --- .../clang/Parse/ParseHLSLRootSignature.h | 2 ++ clang/lib/Frontend/FrontendActions.cpp | 14 ++++++++++-- clang/lib/Parse/ParseHLSLRootSignature.cpp | 22 ++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index c87e6637c7fce..2ae383c38a486 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -240,6 +240,8 @@ IdentifierInfo *ParseHLSLRootSignature(Sema &Actions, llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature); +void HandleRootSignatureTarget(Sema &S); + } // namespace hlsl } // namespace clang diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index ccda2c4ce4b6d..666923101401b 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -1296,6 +1296,9 @@ class InjectRootSignatureCallback : public PPCallbacks { void HLSLFrontendAction::ExecuteAction() { // Pre-requisites to invoke + if (getCurrentFileKind().getLanguage() != Language::HLSL) + return WrapperFrontendAction::ExecuteAction(); + CompilerInstance &CI = getCompilerInstance(); if (!CI.hasASTContext() || !CI.hasPreprocessor()) return WrapperFrontendAction::ExecuteAction(); @@ -1309,6 +1312,10 @@ void HLSLFrontendAction::ExecuteAction() { /*CodeCompleteConsumer=*/nullptr); Sema &S = CI.getSema(); + auto &TargetInfo = CI.getASTContext().getTargetInfo(); + bool IsRootSignatureTarget = + TargetInfo.getTriple().getEnvironment() == llvm::Triple::RootSignature; + // Register HLSL specific callbacks auto LangOpts = CI.getLangOpts(); auto MacroCallback = std::make_unique<InjectRootSignatureCallback>( @@ -1317,8 +1324,11 @@ void HLSLFrontendAction::ExecuteAction() { Preprocessor &PP = CI.getPreprocessor(); PP.addPPCallbacks(std::move(MacroCallback)); - // Invoke as normal - WrapperFrontendAction::ExecuteAction(); + // If we are targeting a root signature, invoke custom handling + if (IsRootSignatureTarget) + return hlsl::HandleRootSignatureTarget(S); + else // otherwise, invoke as normal + return WrapperFrontendAction::ExecuteAction(); } HLSLFrontendAction::HLSLFrontendAction( diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 1af72f8b1c934..11af62f132be8 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -7,8 +7,9 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/ParseHLSLRootSignature.h" - +#include "clang/AST/ASTConsumer.h" #include "clang/Lex/LiteralSupport.h" +#include "clang/Parse/Parser.h" #include "clang/Sema/Sema.h" using namespace llvm::hlsl::rootsig; @@ -1472,5 +1473,24 @@ IdentifierInfo *ParseHLSLRootSignature(Sema &Actions, return DeclIdent; } +void HandleRootSignatureTarget(Sema &S) { + ASTConsumer *Consumer = &S.getASTConsumer(); + + // Minimally initalize the parser. This does a couple things: + // - initializes Sema scope handling + // - invokes HLSLExternalSemaSource + // - invokes the preprocessor to lex the macros in the file + std::unique_ptr<Parser> P(new Parser(S.getPreprocessor(), S, true)); + S.getPreprocessor().EnterMainSourceFile(); + + bool HaveLexer = S.getPreprocessor().getCurrentLexer(); + if (HaveLexer) { + P->Initialize(); + S.ActOnStartOfTranslationUnit(); + } + + Consumer->HandleTranslationUnit(S.getASTContext()); +} + } // namespace hlsl } // namespace clang >From e6747824bd95cb0c048dfad4e29c0a52d6673458 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Fri, 29 Aug 2025 10:45:00 -0700 Subject: [PATCH 04/14] nfc: pull out lookup of root signature --- clang/include/clang/Sema/SemaHLSL.h | 2 ++ clang/lib/Sema/SemaHLSL.cpp | 34 ++++++++++++++++++----------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 5cbe1b658f5cd..4bad26e7a09a7 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -157,6 +157,8 @@ class SemaHLSL : public SemaBase { RootSigOverrideIdent = DeclIdent; } + HLSLRootSignatureDecl *lookupRootSignatureOverrideDecl(DeclContext *DC) const; + // Returns true if any RootSignatureElement is invalid and a diagnostic was // produced bool diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 9e99f9a1525a9..6ef43b833b759 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -729,19 +729,15 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { // If we have specified a root signature to override the entry function then // attach it now - if (RootSigOverrideIdent) { - LookupResult R(SemaRef, RootSigOverrideIdent, SourceLocation(), - Sema::LookupOrdinaryName); - if (SemaRef.LookupQualifiedName(R, FD->getDeclContext())) - if (auto *SignatureDecl = - dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) { - FD->dropAttr<RootSignatureAttr>(); - // We could look up the SourceRange of the macro here as well - AttributeCommonInfo AL(RootSigOverrideIdent, AttributeScopeInfo(), - SourceRange(), ParsedAttr::Form::Microsoft()); - FD->addAttr(::new (getASTContext()) RootSignatureAttr( - getASTContext(), AL, RootSigOverrideIdent, SignatureDecl)); - } + HLSLRootSignatureDecl *SignatureDecl = + lookupRootSignatureOverrideDecl(FD->getDeclContext()); + if (SignatureDecl) { + FD->dropAttr<RootSignatureAttr>(); + // We could look up the SourceRange of the macro here as well + AttributeCommonInfo AL(RootSigOverrideIdent, AttributeScopeInfo(), + SourceRange(), ParsedAttr::Form::Microsoft()); + FD->addAttr(::new (getASTContext()) RootSignatureAttr( + getASTContext(), AL, RootSigOverrideIdent, SignatureDecl)); } llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment(); @@ -1111,6 +1107,18 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope()); } +HLSLRootSignatureDecl * +SemaHLSL::lookupRootSignatureOverrideDecl(DeclContext *DC) const { + if (RootSigOverrideIdent) { + LookupResult R(SemaRef, RootSigOverrideIdent, SourceLocation(), + Sema::LookupOrdinaryName); + if (SemaRef.LookupQualifiedName(R, DC)) + return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl()); + } + + return nullptr; +} + namespace { struct PerVisibilityBindingChecker { >From f41c4c4aedbf010a0b8472315c30c8e452460b5d Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 11:34:15 -0700 Subject: [PATCH 05/14] construct the RootSignatureDecl node in ASTContext --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ .../clang/Parse/ParseHLSLRootSignature.h | 2 +- clang/lib/Frontend/FrontendActions.cpp | 8 ++++-- clang/lib/Parse/ParseHLSLRootSignature.cpp | 12 +++++++- .../AST/HLSL/RootSignature-Target-AST.hlsl | 28 +++++++++++++++++++ .../SemaHLSL/RootSignature-target-err.hlsl | 5 ++++ 6 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/AST/HLSL/RootSignature-Target-AST.hlsl create mode 100644 clang/test/SemaHLSL/RootSignature-target-err.hlsl diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c934fed2c7462..f1d64cdca5da4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13136,6 +13136,8 @@ def err_hlsl_attribute_needs_intangible_type: Error<"attribute %0 can be used on def err_hlsl_incorrect_num_initializers: Error< "too %select{few|many}0 initializers in list for type %1 " "(expected %2 but found %3)">; +def err_hlsl_rootsignature_entry: Error< + "rootsignature specified as target environment but entry, %0, was not defined">; def err_hlsl_operator_unsupported : Error< "the '%select{&|*|->}0' operator is unsupported in HLSL">; diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 2ae383c38a486..b06846fd83c09 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -240,7 +240,7 @@ IdentifierInfo *ParseHLSLRootSignature(Sema &Actions, llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature); -void HandleRootSignatureTarget(Sema &S); +void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig); } // namespace hlsl } // namespace clang diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 666923101401b..9e00494bcfbcf 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -1315,18 +1315,22 @@ void HLSLFrontendAction::ExecuteAction() { auto &TargetInfo = CI.getASTContext().getTargetInfo(); bool IsRootSignatureTarget = TargetInfo.getTriple().getEnvironment() == llvm::Triple::RootSignature; + StringRef HLSLEntry = TargetInfo.getTargetOpts().HLSLEntry; // Register HLSL specific callbacks auto LangOpts = CI.getLangOpts(); + StringRef RootSigName = + IsRootSignatureTarget ? HLSLEntry : LangOpts.HLSLRootSigOverride; + auto MacroCallback = std::make_unique<InjectRootSignatureCallback>( - S, LangOpts.HLSLRootSigOverride, LangOpts.HLSLRootSigVer); + S, RootSigName, LangOpts.HLSLRootSigVer); Preprocessor &PP = CI.getPreprocessor(); PP.addPPCallbacks(std::move(MacroCallback)); // If we are targeting a root signature, invoke custom handling if (IsRootSignatureTarget) - return hlsl::HandleRootSignatureTarget(S); + return hlsl::HandleRootSignatureTarget(S, HLSLEntry); else // otherwise, invoke as normal return WrapperFrontendAction::ExecuteAction(); } diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 11af62f132be8..4e5b8b83200e0 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -1473,7 +1473,7 @@ IdentifierInfo *ParseHLSLRootSignature(Sema &Actions, return DeclIdent; } -void HandleRootSignatureTarget(Sema &S) { +void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig) { ASTConsumer *Consumer = &S.getASTConsumer(); // Minimally initalize the parser. This does a couple things: @@ -1487,6 +1487,16 @@ void HandleRootSignatureTarget(Sema &S) { if (HaveLexer) { P->Initialize(); S.ActOnStartOfTranslationUnit(); + + HLSLRootSignatureDecl *SignatureDecl = + S.HLSL().lookupRootSignatureOverrideDecl( + S.getASTContext().getTranslationUnitDecl()); + + if (SignatureDecl) + Consumer->HandleTopLevelDecl(DeclGroupRef(SignatureDecl)); + else + S.getDiagnostics().Report(diag::err_hlsl_rootsignature_entry) + << EntryRootSig; } Consumer->HandleTranslationUnit(S.getASTContext()); diff --git a/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl new file mode 100644 index 0000000000000..91441e32e047d --- /dev/null +++ b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ +// RUN: -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_1 + +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ +// RUN: -fdx-rootsignature-version=rootsig_1_0 \ +// RUN: -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_0 + +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ +// RUN: -D CmdRS='"UAV(u0)"'\ +// RUN: -hlsl-entry CmdRS -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CMD + +// CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[ENTRY_RS_DECL:__hlsl_rootsig_decl_\d*]] +// CHECK-V1_0-SAME: version: 1.0, +// CHECK-V1_1-SAME: version: 1.1, +// CHECK-SAME: RootElements{ +// CHECK-SAME: RootCBV(b0, +// CHECK-SAME: space = 0, visibility = All, +// CHECK-V1_0-SAME: flags = DataVolatile +// CHECK-V1_1-SAME: flags = DataStaticWhileSetAtExecute +// CHECK-SAME: ) +// CHECK-SAME: } +#define EntryRootSig "CBV(b0)" + +// CMD: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[CMD_RS_DECL:__hlsl_rootsig_decl_\d*]] +// CMD-SAME: version: 1.1, +// CMD-SAME: RootElements{ +// CMD-SAME: RootUAV(u0, space = 0, visibility = All, flags = DataVolatile) +// CMD-SAME: } diff --git a/clang/test/SemaHLSL/RootSignature-target-err.hlsl b/clang/test/SemaHLSL/RootSignature-target-err.hlsl new file mode 100644 index 0000000000000..49aca9ed6b377 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-target-err.hlsl @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -hlsl-entry NotFoundRS -fsyntax-only %s -verify + +// expected-error@* {{rootsignature specified as target environment but entry, NotFoundRS, was not defined}} + +#define EntryRootSig "CBV(b0)" >From 0033778084f517588382fb805f156cb0af76b27c Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 11:55:24 -0700 Subject: [PATCH 06/14] add support for generating the metadata --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 28 ++++++++++++++----- clang/lib/CodeGen/CGHLSLRuntime.h | 2 ++ clang/lib/CodeGen/CodeGenModule.cpp | 2 +- .../CodeGenHLSL/RootSignature-Target.hlsl | 9 ++++++ 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 clang/test/CodeGenHLSL/RootSignature-Target.hlsl diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index f32d01ae78658..4370c0082ce7f 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -67,9 +67,9 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } -void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer, - ArrayRef<llvm::hlsl::rootsig::RootElement> Elements, - llvm::Function *Fn, llvm::Module &M) { +void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer, + ArrayRef<llvm::hlsl::rootsig::RootElement> Elements, + llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements); @@ -77,8 +77,8 @@ void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer, ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get( llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer))); - MDNode *MDVals = - MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature, Version}); + ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr; + MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version}); StringRef RootSignatureValKey = "dx.rootsignatures"; auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); @@ -381,6 +381,20 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) { } } +void CGHLSLRuntime::addRootSignature( + const HLSLRootSignatureDecl *SignatureDecl) { + llvm::Module &M = CGM.getModule(); + Triple T(M.getTargetTriple()); + + // If we are not targeting a root signature enviornment then this decl will + // be generated when the function decl it is attached is handled + if (T.getEnvironment() != Triple::EnvironmentType::RootSignature) + return; + + addRootSignatureMD(SignatureDecl->getVersion(), + SignatureDecl->getRootElements(), nullptr, M); +} + llvm::TargetExtType * CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) { const auto Entry = LayoutTypes.find(StructType); @@ -584,8 +598,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, for (const Attr *Attr : FD->getAttrs()) { if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) { auto *RSDecl = RSAttr->getSignatureDecl(); - addRootSignature(RSDecl->getVersion(), RSDecl->getRootElements(), EntryFn, - M); + addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(), + EntryFn, M); } } } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index b872f9ef0e9b6..613d0ad6bca5c 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -62,6 +62,7 @@ class VarDecl; class ParmVarDecl; class InitListExpr; class HLSLBufferDecl; +class HLSLRootSignatureDecl; class HLSLVkBindingAttr; class HLSLResourceBindingAttr; class Type; @@ -150,6 +151,7 @@ class CGHLSLRuntime { void generateGlobalCtorDtorCalls(); void addBuffer(const HLSLBufferDecl *D); + void addRootSignature(const HLSLRootSignatureDecl *D); void finishCodeGen(); void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 323823c964a79..f90a8196ecced 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7535,7 +7535,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; case Decl::HLSLRootSignature: - // Will be handled by attached function + getHLSLRuntime().addRootSignature(cast<HLSLRootSignatureDecl>(D)); break; case Decl::HLSLBuffer: getHLSLRuntime().addBuffer(cast<HLSLBufferDecl>(D)); diff --git a/clang/test/CodeGenHLSL/RootSignature-Target.hlsl b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl new file mode 100644 index 0000000000000..50e6bae6786f0 --- /dev/null +++ b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-rootsignature \ +// RUN: -hlsl-entry EntryRS -emit-llvm -o - %s | FileCheck %s + +// CHECK: !dx.rootsignatures = !{![[#ENTRY:]]} +// CHECK: ![[#ENTRY]] = !{null, ![[#ENTRY_RS:]], i32 2} +// CHECK: ![[#ENTRY_RS]] = !{![[#ROOT_CBV:]]} +// CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4} + +#define EntryRS "CBV(b0)" >From 34cce6b34ce52564344f1cab57aa9db8c83a91e4 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 11:56:42 -0700 Subject: [PATCH 07/14] nfc: pull out handling of rs node --- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 2436d3869464f..5b70e29a12073 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -72,11 +72,11 @@ analyzeModule(Module &M) { if (RootSignatureNode == nullptr) return RSDMap; - for (const auto &RSDefNode : RootSignatureNode->operands()) { + auto HandleNode = [&Ctx, &RSDMap](MDNode *RSDefNode) { if (RSDefNode->getNumOperands() != 3) { reportError(Ctx, "Invalid Root Signature metadata - expected function, " "signature, and version."); - continue; + return; } // Function was pruned during compilation. @@ -84,38 +84,38 @@ analyzeModule(Module &M) { if (FunctionPointerMdNode == nullptr) { reportError( Ctx, "Function associated with Root Signature definition is null."); - continue; + return; } ValueAsMetadata *VAM = llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get()); if (VAM == nullptr) { reportError(Ctx, "First element of root signature is not a Value"); - continue; + return; } Function *F = dyn_cast<Function>(VAM->getValue()); if (F == nullptr) { reportError(Ctx, "First element of root signature is not a Function"); - continue; + return; } Metadata *RootElementListOperand = RSDefNode->getOperand(1).get(); if (RootElementListOperand == nullptr) { reportError(Ctx, "Root Element mdnode is null."); - continue; + return; } MDNode *RootElementListNode = dyn_cast<MDNode>(RootElementListOperand); if (RootElementListNode == nullptr) { reportError(Ctx, "Root Element is not a metadata node."); - continue; + return; } std::optional<uint32_t> V = extractMdIntValue(RSDefNode, 2); if (!V.has_value()) { reportError(Ctx, "Invalid RSDefNode value, expected constant int"); - continue; + return; } llvm::hlsl::rootsig::MetadataParser MDParser(RootElementListNode); @@ -126,7 +126,7 @@ analyzeModule(Module &M) { handleAllErrors(RSDOrErr.takeError(), [&](ErrorInfoBase &EIB) { Ctx->emitError(EIB.message()); }); - continue; + return; } auto &RSD = *RSDOrErr; @@ -140,8 +140,12 @@ analyzeModule(Module &M) { RSD.StaticSamplersOffset = 0u; RSDMap.insert(std::make_pair(F, RSD)); + }; } + for (MDNode *RSDefNode : RootSignatureNode->operands()) + HandleNode(RSDefNode); + return RSDMap; } >From 229aa65013160ec062126d09c9ae168ba834fefc Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Fri, 29 Aug 2025 15:38:09 -0700 Subject: [PATCH 08/14] add support constructing dxcontainer for rootsignature without entry function --- llvm/include/llvm/BinaryFormat/DXContainer.h | 2 +- .../lib/Target/DirectX/DXContainerGlobals.cpp | 16 +++++-- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 46 +++++++++++-------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index f74c9775cb3f3..0547d96a8dec7 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -45,7 +45,7 @@ namespace dxbc { LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); inline Triple::EnvironmentType getShaderStage(uint32_t Kind) { - assert(Kind <= Triple::Amplification - Triple::Pixel && + assert(Kind <= Triple::RootSignature - Triple::Pixel && "Shader kind out of expected range."); return static_cast<Triple::EnvironmentType>(Triple::Pixel + Kind); } diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index a1ef2578f00aa..37c58e041f4df 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -158,10 +158,14 @@ void DXContainerGlobals::addRootSignature(Module &M, if (MMI.ShaderProfile == llvm::Triple::Library) return; - assert(MMI.EntryPropertyVec.size() == 1); - auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo(); - const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; + const Function *EntryFunction = nullptr; + + if (MMI.ShaderProfile != llvm::Triple::RootSignature) { + assert(MMI.EntryPropertyVec.size() == 1); + EntryFunction = MMI.EntryPropertyVec[0].Entry; + } + const mcdxbc::RootSignatureDesc *RS = RSA.getDescForFunction(EntryFunction); if (!RS) @@ -258,7 +262,8 @@ void DXContainerGlobals::addPipelineStateValidationInfo( dxil::ModuleMetadataInfo &MMI = getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata(); assert(MMI.EntryPropertyVec.size() == 1 || - MMI.ShaderProfile == Triple::Library); + MMI.ShaderProfile == Triple::Library || + MMI.ShaderProfile == Triple::RootSignature); PSV.BaseData.ShaderStage = static_cast<uint8_t>(MMI.ShaderProfile - Triple::Pixel); @@ -279,7 +284,8 @@ void DXContainerGlobals::addPipelineStateValidationInfo( break; } - if (MMI.ShaderProfile != Triple::Library) + if (MMI.ShaderProfile != Triple::Library && + MMI.ShaderProfile != Triple::RootSignature) PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName(); PSV.finalize(MMI.ShaderProfile); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5b70e29a12073..8db9436eabc57 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -72,32 +72,35 @@ analyzeModule(Module &M) { if (RootSignatureNode == nullptr) return RSDMap; - auto HandleNode = [&Ctx, &RSDMap](MDNode *RSDefNode) { + auto HandleNode = [&Ctx, &RSDMap](MDNode *RSDefNode, bool NullFunc = false) { if (RSDefNode->getNumOperands() != 3) { reportError(Ctx, "Invalid Root Signature metadata - expected function, " "signature, and version."); return; } - // Function was pruned during compilation. - const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0); - if (FunctionPointerMdNode == nullptr) { - reportError( - Ctx, "Function associated with Root Signature definition is null."); - return; - } + Function *F = nullptr; + if (!NullFunc) { + // Function was pruned during compilation. + const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0); + if (FunctionPointerMdNode == nullptr) { + reportError( + Ctx, "Function associated with Root Signature definition is null."); + return; + } - ValueAsMetadata *VAM = - llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get()); - if (VAM == nullptr) { - reportError(Ctx, "First element of root signature is not a Value"); - return; - } + ValueAsMetadata *VAM = + llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get()); + if (VAM == nullptr) { + reportError(Ctx, "First element of root signature is not a Value"); + return; + } - Function *F = dyn_cast<Function>(VAM->getValue()); - if (F == nullptr) { - reportError(Ctx, "First element of root signature is not a Function"); - return; + F = dyn_cast<Function>(VAM->getValue()); + if (F == nullptr) { + reportError(Ctx, "First element of root signature is not a Function"); + return; + } } Metadata *RootElementListOperand = RSDefNode->getOperand(1).get(); @@ -141,6 +144,13 @@ analyzeModule(Module &M) { RSDMap.insert(std::make_pair(F, RSD)); }; + + if (M.getTargetTriple().getEnvironment() == + Triple::EnvironmentType::RootSignature) { + assert(RootSignatureNode->getNumOperands() == 1); + MDNode *RSDefNode = RootSignatureNode->getOperand(0); + HandleNode(RSDefNode, true); + return RSDMap; } for (MDNode *RSDefNode : RootSignatureNode->operands()) >From 028a74a38805a8a8d4bf81046edbce155813ddfe Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 12:39:50 -0700 Subject: [PATCH 09/14] nfc: extract intermediate parse profile step --- clang/lib/Driver/ToolChains/HLSL.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 304c367cc4367..0c96935ba93b7 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -70,7 +70,7 @@ bool isLegalShaderModel(Triple &T) { return false; } -std::optional<std::string> tryParseProfile(StringRef Profile) { +std::optional<llvm::Triple> tryParseTriple(StringRef Profile) { // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] SmallVector<StringRef, 3> Parts; Profile.split(Parts, "_"); @@ -149,8 +149,14 @@ std::optional<std::string> tryParseProfile(StringRef Profile) { T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() + VersionTuple(Major, Minor).getAsString()); T.setEnvironment(Kind); - if (isLegalShaderModel(T)) - return T.getTriple(); + + return T; +} + +std::optional<std::string> tryParseProfile(StringRef Profile) { + std::optional<llvm::Triple> MaybeT = tryParseTriple(Profile); + if (MaybeT && isLegalShaderModel(*MaybeT)) + return MaybeT->getTriple(); else return std::nullopt; } >From 060eae14a68056e2ffc082608244da03137d4c5f Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 12:40:20 -0700 Subject: [PATCH 10/14] add invocation to just emit root signature of dxcontainer --- clang/lib/Driver/ToolChains/HLSL.cpp | 22 ++++++++++++++++++- .../test/Driver/dxc_rootsignature_target.hlsl | 8 +++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 clang/test/Driver/dxc_rootsignature_target.hlsl diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index 0c96935ba93b7..543ab268540da 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -266,6 +266,19 @@ bool checkExtensionArgsAreValid(ArrayRef<std::string> SpvExtensionArgs, } return AllValid; } + +bool isRootSignatureTarget(StringRef Profile) { + if (std::optional<llvm::Triple> T = tryParseTriple(Profile)) + return T->getEnvironment() == Triple::EnvironmentType::RootSignature; + return false; +} + +bool isRootSignatureTarget(DerivedArgList &Args) { + if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) + return isRootSignatureTarget(A->getValue()); + return false; +} + } // namespace void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA, @@ -325,6 +338,12 @@ void tools::hlsl::LLVMObjcopy::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Frs); } + if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) + if (isRootSignatureTarget(A->getValue())) { + const char *Fos = Args.MakeArgString("--only-section=RTS0"); + CmdArgs.push_back(Fos); + } + assert(CmdArgs.size() > 2 && "Unnecessary invocation of objcopy."); C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), @@ -501,7 +520,8 @@ bool HLSLToolChain::requiresBinaryTranslation(DerivedArgList &Args) const { bool HLSLToolChain::requiresObjcopy(DerivedArgList &Args) const { return Args.hasArg(options::OPT_dxc_Fo) && - Args.hasArg(options::OPT_dxc_strip_rootsignature); + (Args.hasArg(options::OPT_dxc_strip_rootsignature) || + isRootSignatureTarget(Args)); } bool HLSLToolChain::isLastJob(DerivedArgList &Args, diff --git a/clang/test/Driver/dxc_rootsignature_target.hlsl b/clang/test/Driver/dxc_rootsignature_target.hlsl new file mode 100644 index 0000000000000..a732c50507cdb --- /dev/null +++ b/clang/test/Driver/dxc_rootsignature_target.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_dxc -E EntryRS -T rootsig_1_1 /Fo %t.dxo -### %s 2>&1 | FileCheck %s --check-prefix=CMDS + +// CMDS: "{{.*}}clang{{.*}}" "-cc1" +// CMDS-SAME: "-triple" "dxilv1.1-unknown-shadermodel1.1-rootsignature" +// CMDS-SAME: "-hlsl-entry" "EntryRS" +// CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.dxo" "--only-section=RTS0" + +#define EntryRS "CBV(b0)" >From 50d72e692c0d45134422956fff10e779ce822b7f Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Mon, 1 Sep 2025 12:57:54 -0700 Subject: [PATCH 11/14] add clang_dxc test to demonstrate lexing bug --- clang/lib/Parse/ParseHLSLRootSignature.cpp | 4 +++ .../test/Driver/dxc_rootsignature_target.hlsl | 34 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 4e5b8b83200e0..91976489ee660 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -1488,6 +1488,10 @@ void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig) { P->Initialize(); S.ActOnStartOfTranslationUnit(); + // Skim through the file to parse to find the define + while (P->getCurToken().getKind() != tok::eof) + P->ConsumeAnyToken(); + HLSLRootSignatureDecl *SignatureDecl = S.HLSL().lookupRootSignatureOverrideDecl( S.getASTContext().getTranslationUnitDecl()); diff --git a/clang/test/Driver/dxc_rootsignature_target.hlsl b/clang/test/Driver/dxc_rootsignature_target.hlsl index a732c50507cdb..011fa4be9050d 100644 --- a/clang/test/Driver/dxc_rootsignature_target.hlsl +++ b/clang/test/Driver/dxc_rootsignature_target.hlsl @@ -1,8 +1,40 @@ // RUN: %clang_dxc -E EntryRS -T rootsig_1_1 /Fo %t.dxo -### %s 2>&1 | FileCheck %s --check-prefix=CMDS +// RUN: %clang_dxc -E EntryRS -T rootsig_1_1 /Fo %t.dxo %s +// RUN: obj2yaml %t.dxo | FileCheck %s --check-prefix=OBJ + // CMDS: "{{.*}}clang{{.*}}" "-cc1" // CMDS-SAME: "-triple" "dxilv1.1-unknown-shadermodel1.1-rootsignature" // CMDS-SAME: "-hlsl-entry" "EntryRS" // CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.dxo" "--only-section=RTS0" -#define EntryRS "CBV(b0)" +#define EntryRS "UAV(u0)" + +// OBJ: --- !dxcontainer +// FileSize = 32 (header) + 48 (RTS0 content) + 4 (1 part offset) + 8 (1 part header) +// OBJ: FileSize: 92 +// OBJ-NEXT: PartCount: 1 +// OBJ-NEXT: PartOffsets: [ 36 ] +// OBJ-NEXT: Parts: +// OBJ-NOT: DXIL +// OBJ-NOT: SFI0 +// OBJ-NOT: HASH +// OBJ-NOT: ISG0 +// OBJ-NOT: OSG0 + +// OBJ: - Name: RTS0 +// OBJ-NEXT: Size: 48 +// OBJ-NEXT: RootSignature: +// OBJ-NEXT: Version: 2 +// OBJ-NEXT: NumRootParameters: 1 +// OBJ-NEXT: RootParametersOffset: 24 + +// OBJ: Parameters: +// UAV(u0) +// OBJ: - ParameterType: 4 +// OBJ-NEXT: ShaderVisibility: 0 +// OBJ-NEXT: Descriptor: +// OBJ-NEXT: RegisterSpace: 0 +// OBJ-NEXT: ShaderRegister: 0 + +// OBJ-NOT: PSV0 >From 51b472c73d06b6cb2121aa0ab28af9082e4e1323 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Tue, 2 Sep 2025 13:32:05 -0700 Subject: [PATCH 12/14] Revert "add clang_dxc test to demonstrate lexing bug" This reverts commit 50d72e692c0d45134422956fff10e779ce822b7f. --- clang/lib/Parse/ParseHLSLRootSignature.cpp | 4 --- .../test/Driver/dxc_rootsignature_target.hlsl | 32 ------------------- 2 files changed, 36 deletions(-) diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 91976489ee660..4e5b8b83200e0 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -1488,10 +1488,6 @@ void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig) { P->Initialize(); S.ActOnStartOfTranslationUnit(); - // Skim through the file to parse to find the define - while (P->getCurToken().getKind() != tok::eof) - P->ConsumeAnyToken(); - HLSLRootSignatureDecl *SignatureDecl = S.HLSL().lookupRootSignatureOverrideDecl( S.getASTContext().getTranslationUnitDecl()); diff --git a/clang/test/Driver/dxc_rootsignature_target.hlsl b/clang/test/Driver/dxc_rootsignature_target.hlsl index 011fa4be9050d..08cd1ab00089b 100644 --- a/clang/test/Driver/dxc_rootsignature_target.hlsl +++ b/clang/test/Driver/dxc_rootsignature_target.hlsl @@ -1,40 +1,8 @@ // RUN: %clang_dxc -E EntryRS -T rootsig_1_1 /Fo %t.dxo -### %s 2>&1 | FileCheck %s --check-prefix=CMDS -// RUN: %clang_dxc -E EntryRS -T rootsig_1_1 /Fo %t.dxo %s -// RUN: obj2yaml %t.dxo | FileCheck %s --check-prefix=OBJ - // CMDS: "{{.*}}clang{{.*}}" "-cc1" // CMDS-SAME: "-triple" "dxilv1.1-unknown-shadermodel1.1-rootsignature" // CMDS-SAME: "-hlsl-entry" "EntryRS" // CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.dxo" "--only-section=RTS0" #define EntryRS "UAV(u0)" - -// OBJ: --- !dxcontainer -// FileSize = 32 (header) + 48 (RTS0 content) + 4 (1 part offset) + 8 (1 part header) -// OBJ: FileSize: 92 -// OBJ-NEXT: PartCount: 1 -// OBJ-NEXT: PartOffsets: [ 36 ] -// OBJ-NEXT: Parts: -// OBJ-NOT: DXIL -// OBJ-NOT: SFI0 -// OBJ-NOT: HASH -// OBJ-NOT: ISG0 -// OBJ-NOT: OSG0 - -// OBJ: - Name: RTS0 -// OBJ-NEXT: Size: 48 -// OBJ-NEXT: RootSignature: -// OBJ-NEXT: Version: 2 -// OBJ-NEXT: NumRootParameters: 1 -// OBJ-NEXT: RootParametersOffset: 24 - -// OBJ: Parameters: -// UAV(u0) -// OBJ: - ParameterType: 4 -// OBJ-NEXT: ShaderVisibility: 0 -// OBJ-NEXT: Descriptor: -// OBJ-NEXT: RegisterSpace: 0 -// OBJ-NEXT: ShaderRegister: 0 - -// OBJ-NOT: PSV0 >From e032523d27b2171d5979c789d1639fc173ab2811 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Tue, 2 Sep 2025 13:34:53 -0700 Subject: [PATCH 13/14] add skimming of main file to ignore invalid code - P->Initialize() will only parse until the first non-preprocessor token is found. If a user specifies any code before their entry root signature macro definition, we would not find the definition and incorrectly report that it is not defined This change ensures that we will parse through the entire source file to resolve our macro and match DXC's behaviour --- clang/lib/Parse/ParseHLSLRootSignature.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 4e5b8b83200e0..91976489ee660 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -1488,6 +1488,10 @@ void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig) { P->Initialize(); S.ActOnStartOfTranslationUnit(); + // Skim through the file to parse to find the define + while (P->getCurToken().getKind() != tok::eof) + P->ConsumeAnyToken(); + HLSLRootSignatureDecl *SignatureDecl = S.HLSL().lookupRootSignatureOverrideDecl( S.getASTContext().getTranslationUnitDecl()); >From e303da852cf7fbb32a5fba52d4fbe07d1ea5c8d0 Mon Sep 17 00:00:00 2001 From: Finn Plummer <m...@inbelic.dev> Date: Tue, 2 Sep 2025 13:47:52 -0700 Subject: [PATCH 14/14] add missing test case for dxcontainer logic --- .../ContainerData/RootSignature-Target.ll | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Target.ll diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Target.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Target.ll new file mode 100644 index 0000000000000..76212a0f66f9d --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Target.ll @@ -0,0 +1,23 @@ +; RUN: opt %s -dxil-embed -dxil-globals -S -o - | FileCheck %s +; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC + +target triple = "dxil-unknown-shadermodel1.1-rootsignature" + +; CHECK: @dx.rts0 = private constant [24 x i8] c"{{.*}}", section "RTS0", align 4 + +!dx.rootsignatures = !{!2} ; list of function/root signature pairs +!2 = !{ null, !3, i32 2 } ; function, root signature, version +!3 = !{ !4 } ; list of root signature elements +!4 = !{ !"RootFlags", i32 1 } ; 1 = allow_input_assembler_input_layout + +; DXC: - Name: RTS0 +; DXC-NEXT: Size: 24 +; DXC-NEXT: RootSignature: +; DXC-NEXT: Version: 2 +; DXC-NEXT: NumRootParameters: 0 +; DXC-NEXT: RootParametersOffset: 24 +; DXC-NEXT: NumStaticSamplers: 0 +; DXC-NEXT: StaticSamplersOffset: 24 +; DXC-NEXT: Parameters: [] +; DXC-NEXT: AllowInputAssemblerInputLayout: true + _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits