[clang] [Clang][HLSL] Fix struct semantic store (PR #181681)
Nathan Gauër via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 16 07:05:54 PST 2026
https://github.com/Keenuts created https://github.com/llvm/llvm-project/pull/181681
The store to a nested semantic had an issue we the field index was not increased when walking through it.
One of the check-in test was bad, causing this to slip by.
Fixes #181674
>From 33ed9b09a440f9c3456a79d936d0470f1923d10a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Mon, 16 Feb 2026 15:42:50 +0100
Subject: [PATCH] [Clang][HLSL] Fix struct semantic store
The store to a nested semantic had an issue we the field index
was not increased when walking through it.
One of the check-in test was bad, causing this to slip by.
Fixes #181674
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 1 +
.../semantic.explicit-mix-builtin.vs.hlsl | 6 ++-
.../semantics/semantic.nested.vs.hlsl | 52 +++++++++++++++++++
3 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGenHLSL/semantics/semantic.nested.vs.hlsl
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 7aa7ecbe211d5..00c44eeeb1670 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -880,6 +880,7 @@ CGHLSLRuntime::handleStructSemanticStore(
llvm::Value *Extract = B.CreateExtractValue(Source, I);
AttrBegin =
handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
+ ++FieldDecl;
}
return AttrBegin;
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl
index 43dc30f089d9e..29851c258db40 100644
--- a/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/semantic.explicit-mix-builtin.vs.hlsl
@@ -11,7 +11,7 @@ struct S1 {
// CHECK: @SV_Position0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
// CHECK: @SV_Position = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
-// CHECK: @A0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_0]]
+// CHECK: @A0 = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_4:]]
[shader("vertex")]
S1 main1(float4 position : SV_Position) {
@@ -29,3 +29,7 @@ S1 main1(float4 position : SV_Position) {
// CHECK: ![[#MD_3]] = !{i32 11, i32 0}
// | `-> BuiltIn 'Position'
// `-> SPIR-V decoration 'BuiltIn'
+// CHECK: ![[#MD_4]] = !{![[#MD_5:]]}
+// CHECK: ![[#MD_5]] = !{i32 30, i32 3}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.nested.vs.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.nested.vs.hlsl
new file mode 100644
index 0000000000000..1cea88e338aab
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.nested.vs.hlsl
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s
+
+struct Inner {
+ uint b : B;
+};
+
+struct VSInput {
+ float4 position : POSITION; // Not system semantic, Location 0
+};
+
+struct VSOutput {
+ float4 position : SV_POSITION; // System semantic, builtin Position
+ uint a : A; // Location 0
+ Inner inner; // Location 1
+ uint c : C; // Location 2
+};
+
+
+// CHECK: @POSITION0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @SV_POSITION = external hidden thread_local addrspace(8) global <4 x float>, !spirv.Decorations ![[#MD_2:]]
+// CHECK: @A0 = external hidden thread_local addrspace(8) global i32, !spirv.Decorations ![[#MD_0:]]
+// CHECK: @B0 = external hidden thread_local addrspace(8) global i32, !spirv.Decorations ![[#MD_4:]]
+// CHECK: @C0 = external hidden thread_local addrspace(8) global i32, !spirv.Decorations ![[#MD_6:]]
+
+VSOutput main(VSInput input) {
+ VSOutput output;
+ output.position = input.position;
+ output.a = 1;
+ output.inner.b = 2;
+ output.c = 3;
+ return output;
+}
+
+// CHECK: ![[#MD_0]] = !{![[#MD_1:]]}
+// CHECK: ![[#MD_1]] = !{i32 30, i32 0}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
+
+// CHECK: ![[#MD_2]] = !{![[#MD_3:]]}
+// CHECK: ![[#MD_3]] = !{i32 11, i32 0}
+// | `-> BuiltIn 'Position'
+// `-> SPIR-V decoration 'BuiltIn'
+
+// CHECK: ![[#MD_4]] = !{![[#MD_5:]]}
+// CHECK: ![[#MD_5]] = !{i32 30, i32 1}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
+
+// CHECK: ![[#MD_6]] = !{![[#MD_7:]]}
+// CHECK: ![[#MD_7]] = !{i32 30, i32 2}
+// | `-> Location index
+// `-> SPIR-V decoration 'Location'
More information about the cfe-commits
mailing list