[llvm] b649b35 - [HLSL] Adding support for Root Constants in LLVM Metadata (#135085)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 24 13:56:38 PDT 2025
Author: joaosaffran
Date: 2025-04-24T13:56:34-07:00
New Revision: b649b3557e7b0a95612be64c1fe2334f6ecb2132
URL: https://github.com/llvm/llvm-project/commit/b649b3557e7b0a95612be64c1fe2334f6ecb2132
DIFF: https://github.com/llvm/llvm-project/commit/b649b3557e7b0a95612be64c1fe2334f6ecb2132.diff
LOG: [HLSL] Adding support for Root Constants in LLVM Metadata (#135085)
- Closes [#126637](https://github.com/llvm/llvm-project/issues/126637)
---------
Co-authored-by: joaosaffran <joao.saffran at microsoft.com>
Added:
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters-Validation-Error.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-Num32BitValues.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-RegisterSpace.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-ShaderRegister.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootFlags-VisibilityValidationError.ll
Modified:
llvm/lib/Target/DirectX/DXILRootSignature.cpp
llvm/lib/Target/DirectX/DXILRootSignature.h
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
Removed:
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags-Validation-Error.ll
################################################################################
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 3ba0535e0114b..ef299c17baf76 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -40,14 +40,66 @@ static bool reportError(LLVMContext *Ctx, Twine Message,
return true;
}
+static bool reportValueError(LLVMContext *Ctx, Twine ParamName,
+ uint32_t Value) {
+ Ctx->diagnose(DiagnosticInfoGeneric(
+ "Invalid value for " + ParamName + ": " + Twine(Value), DS_Error));
+ return true;
+}
+
+static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
+ unsigned int OpId) {
+ if (auto *CI =
+ mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
+ return CI->getZExtValue();
+ return std::nullopt;
+}
+
static bool parseRootFlags(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
MDNode *RootFlagNode) {
if (RootFlagNode->getNumOperands() != 2)
return reportError(Ctx, "Invalid format for RootFlag Element");
- auto *Flag = mdconst::extract<ConstantInt>(RootFlagNode->getOperand(1));
- RSD.Flags = Flag->getZExtValue();
+ if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
+ RSD.Flags = *Val;
+ else
+ return reportError(Ctx, "Invalid value for RootFlag");
+
+ return false;
+}
+
+static bool parseRootConstants(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
+ MDNode *RootConstantNode) {
+
+ if (RootConstantNode->getNumOperands() != 5)
+ return reportError(Ctx, "Invalid format for RootConstants Element");
+
+ mcdxbc::RootParameter NewParameter;
+ NewParameter.Header.ParameterType =
+ llvm::to_underlying(dxbc::RootParameterType::Constants32Bit);
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 1))
+ NewParameter.Header.ShaderVisibility = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderVisibility");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
+ NewParameter.Constants.ShaderRegister = *Val;
+ else
+ return reportError(Ctx, "Invalid value for ShaderRegister");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
+ NewParameter.Constants.RegisterSpace = *Val;
+ else
+ return reportError(Ctx, "Invalid value for RegisterSpace");
+
+ if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
+ NewParameter.Constants.Num32BitValues = *Val;
+ else
+ return reportError(Ctx, "Invalid value for Num32BitValues");
+
+ RSD.Parameters.push_back(NewParameter);
return false;
}
@@ -62,12 +114,16 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
RootSignatureElementKind ElementKind =
StringSwitch<RootSignatureElementKind>(ElementText->getString())
.Case("RootFlags", RootSignatureElementKind::RootFlags)
+ .Case("RootConstants", RootSignatureElementKind::RootConstants)
.Default(RootSignatureElementKind::Error);
switch (ElementKind) {
case RootSignatureElementKind::RootFlags:
return parseRootFlags(Ctx, RSD, Element);
+ case RootSignatureElementKind::RootConstants:
+ return parseRootConstants(Ctx, RSD, Element);
+ break;
case RootSignatureElementKind::Error:
return reportError(Ctx, "Invalid Root Signature Element: " +
ElementText->getString());
@@ -94,10 +150,29 @@ static bool parse(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
static bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
+static bool verifyVersion(uint32_t Version) {
+ return (Version == 1 || Version == 2);
+}
+
static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
+
+ if (!verifyVersion(RSD.Version)) {
+ return reportValueError(Ctx, "Version", RSD.Version);
+ }
+
if (!verifyRootFlag(RSD.Flags)) {
- return reportError(Ctx, "Invalid Root Signature flag value");
+ return reportValueError(Ctx, "RootFlags", RSD.Flags);
+ }
+
+ for (const mcdxbc::RootParameter &P : RSD.Parameters) {
+ if (!dxbc::isValidShaderVisibility(P.Header.ShaderVisibility))
+ return reportValueError(Ctx, "ShaderVisibility",
+ P.Header.ShaderVisibility);
+
+ assert(dxbc::isValidParameterType(P.Header.ParameterType) &&
+ "Invalid value for ParameterType");
}
+
return false;
}
@@ -166,6 +241,10 @@ analyzeModule(Module &M) {
}
mcdxbc::RootSignatureDesc RSD;
+ // Clang emits the root signature data in dxcontainer following a specific
+ // sequence. First the header, then the root parameters. So the header
+ // offset will always equal to the header size.
+ RSD.RootParameterOffset = sizeof(dxbc::RootSignatureHeader);
if (parse(Ctx, RSD, RootElementListNode) || validate(Ctx, RSD)) {
return RSDMap;
@@ -192,7 +271,6 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
AM.getResult<RootSignatureAnalysis>(M);
- const size_t RSHSize = sizeof(dxbc::RootSignatureHeader);
OS << "Root Signature Definitions"
<< "\n";
uint8_t Space = 0;
@@ -205,14 +283,33 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
// start root signature header
Space++;
- OS << indent(Space) << "Flags: " << format_hex(RS.Flags, 8) << ":\n";
- OS << indent(Space) << "Version: " << RS.Version << ":\n";
- OS << indent(Space) << "NumParameters: " << RS.Parameters.size() << ":\n";
- OS << indent(Space) << "RootParametersOffset: " << RSHSize << ":\n";
- OS << indent(Space) << "NumStaticSamplers: " << 0 << ":\n";
- OS << indent(Space)
- << "StaticSamplersOffset: " << RSHSize + RS.Parameters.size_in_bytes()
- << ":\n";
+ OS << indent(Space) << "Flags: " << format_hex(RS.Flags, 8) << "\n";
+ OS << indent(Space) << "Version: " << RS.Version << "\n";
+ OS << indent(Space) << "RootParametersOffset: " << RS.RootParameterOffset
+ << "\n";
+ OS << indent(Space) << "NumParameters: " << RS.Parameters.size() << "\n";
+ Space++;
+ for (auto const &P : RS.Parameters) {
+ OS << indent(Space) << "- Parameter Type: " << P.Header.ParameterType
+ << "\n";
+ OS << indent(Space + 2)
+ << "Shader Visibility: " << P.Header.ShaderVisibility << "\n";
+ switch (P.Header.ParameterType) {
+ case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+ OS << indent(Space + 2)
+ << "Register Space: " << P.Constants.RegisterSpace << "\n";
+ OS << indent(Space + 2)
+ << "Shader Register: " << P.Constants.ShaderRegister << "\n";
+ OS << indent(Space + 2)
+ << "Num 32 Bit Values: " << P.Constants.Num32BitValues << "\n";
+ break;
+ }
+ }
+ Space--;
+ OS << indent(Space) << "NumStaticSamplers: " << 0 << "\n";
+ OS << indent(Space) << "StaticSamplersOffset: " << RS.StaticSamplersOffset
+ << "\n";
+
Space--;
// end root signature header
}
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 8c25b2eb3fadf..93ec614f1ab85 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -24,7 +24,11 @@
namespace llvm {
namespace dxil {
-enum class RootSignatureElementKind { Error = 0, RootFlags = 1 };
+enum class RootSignatureElementKind {
+ Error = 0,
+ RootFlags = 1,
+ RootConstants = 2
+};
class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
friend AnalysisInfoMixin<RootSignatureAnalysis>;
static AnalysisKey Key;
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
index ef2b97860bfae..e81679732a5d8 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
@@ -23,7 +23,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
; DXC-NEXT: RootSignature:
; DXC-NEXT: Version: 2
; DXC-NEXT: NumRootParameters: 0
-; DXC-NEXT: RootParametersOffset: 0
+; DXC-NEXT: RootParametersOffset: 24
; DXC-NEXT: NumStaticSamplers: 0
; DXC-NEXT: StaticSamplersOffset: 0
; DXC-NEXT: Parameters: []
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
index 581ac9aaec110..d23e1c71d2fc0 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
@@ -26,15 +26,15 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
; CHECK-LABEL: Definition for 'main':
; CHECK-NEXT: Flags: 0x000001
; CHECK-NEXT: Version: 2
-; CHECK-NEXT: NumParameters: 0
; CHECK-NEXT: RootParametersOffset: 24
+; CHECK-NEXT: NumParameters: 0
; CHECK-NEXT: NumStaticSamplers: 0
-; CHECK-NEXT: StaticSamplersOffset: 24
+; CHECK-NEXT: StaticSamplersOffset: 0
; CHECK-LABEL: Definition for 'anotherMain':
; CHECK-NEXT: Flags: 0x000002
; CHECK-NEXT: Version: 2
-; CHECK-NEXT: NumParameters: 0
; CHECK-NEXT: RootParametersOffset: 24
+; CHECK-NEXT: NumParameters: 0
; CHECK-NEXT: NumStaticSamplers: 0
-; CHECK-NEXT: StaticSamplersOffset: 24
+; CHECK-NEXT: StaticSamplersOffset: 0
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters-Validation-Error.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters-Validation-Error.ll
new file mode 100644
index 0000000000000..2b4a075281f80
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters-Validation-Error.ll
@@ -0,0 +1,20 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+; CHECK: error: Invalid value for ShaderVisibility: 255
+; CHECK-NOT: Root Signature Definitions
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+
+define void @main() #0 {
+entry:
+ ret void
+}
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootConstants", i32 255, i32 1, i32 2, i32 3 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll
new file mode 100644
index 0000000000000..b55d1283df0c9
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Parameters.ll
@@ -0,0 +1,30 @@
+; RUN: opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+
+define void @main() #0 {
+entry:
+ ret void
+}
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !4, !5 } ; list of root signature elements
+!4 = !{ !"RootFlags", i32 1 } ; 1 = allow_input_assembler_input_layout
+!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
+
+;CHECK-LABEL: Definition for 'main':
+;CHECK-NEXT: Flags: 0x000001
+;CHECK-NEXT: Version: 2
+;CHECK-NEXT: RootParametersOffset: 24
+;CHECK-NEXT: NumParameters: 1
+;CHECK-NEXT: - Parameter Type: 1
+;CHECK-NEXT: Shader Visibility: 0
+;CHECK-NEXT: Register Space: 2
+;CHECK-NEXT: Shader Register: 1
+;CHECK-NEXT: Num 32 Bit Values: 3
+;CHECK-NEXT: NumStaticSamplers: 0
+;CHECK-NEXT: StaticSamplersOffset: 0
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-Num32BitValues.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-Num32BitValues.ll
new file mode 100644
index 0000000000000..552c128e5ab57
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-Num32BitValues.ll
@@ -0,0 +1,16 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for Num32BitValues
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() {
+entry:
+ ret void
+}
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, !"Invalid" }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-RegisterSpace.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-RegisterSpace.ll
new file mode 100644
index 0000000000000..1087b414942e2
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-RegisterSpace.ll
@@ -0,0 +1,18 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for RegisterSpace
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootConstants", i32 0, i32 1, !"Invalid", i32 3 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-ShaderRegister.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-ShaderRegister.ll
new file mode 100644
index 0000000000000..53fd924e8f46e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants-Invalid-ShaderRegister.ll
@@ -0,0 +1,18 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for ShaderRegister
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootConstants", i32 0, !"Invalid", i32 2, i32 3 }
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants.ll
new file mode 100644
index 0000000000000..71511ff523340
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootConstants.ll
@@ -0,0 +1,34 @@
+; 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-shadermodel6.0-compute"
+
+; CHECK: @dx.rts0 = private constant [48 x i8] c"{{.*}}", section "RTS0", align 4
+
+define void @main() #0 {
+entry:
+ ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
+
+; DXC: - Name: RTS0
+; DXC-NEXT: Size: 48
+; DXC-NEXT: RootSignature:
+; DXC-NEXT: Version: 2
+; DXC-NEXT: NumRootParameters: 1
+; DXC-NEXT: RootParametersOffset: 24
+; DXC-NEXT: NumStaticSamplers: 0
+; DXC-NEXT: StaticSamplersOffset: 0
+; DXC-NEXT: Parameters:
+; DXC-NEXT: - ParameterType: 1
+; DXC-NEXT: ShaderVisibility: 0
+; DXC-NEXT: Constants:
+; DXC-NEXT: Num32BitValues: 3
+; DXC-NEXT: RegisterSpace: 2
+; DXC-NEXT: ShaderRegister: 1
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags-Validation-Error.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootFlags-VisibilityValidationError.ll
similarity index 90%
rename from llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags-Validation-Error.ll
rename to llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootFlags-VisibilityValidationError.ll
index fe93c9993c1c3..4b8e6abacd7ad 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags-Validation-Error.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootFlags-VisibilityValidationError.ll
@@ -1,6 +1,6 @@
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
-; CHECK: error: Invalid Root Signature flag value
+; CHECK: error: Invalid value for RootFlags: 2147487744
; CHECK-NOT: Root Signature Definitions
target triple = "dxil-unknown-shadermodel6.0-compute"
More information about the llvm-commits
mailing list