[clang] [llvm] [NFC][SemaHLSL][CGHLSL] Move semantic classification to common `HLSL/SemanticSignatures` (PR #218058)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 9 14:49:41 PDT 2026
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/218058
>From e52b84aa7ee4c878202e01826bfaa40de0128bf4 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:40:58 +0000
Subject: [PATCH 01/36] nfc: move def to semasig
---
clang/include/clang/Sema/SemaHLSL.h | 21 +++++--------------
clang/lib/Sema/SemaHLSL.cpp | 2 ++
.../llvm/Frontend/HLSL/SemanticSignatures.h | 15 +++++++++++++
3 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 8928524e49783..0f834df21c40d 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Frontend/HLSL/SemanticSignatures.h"
#include "llvm/TargetParser/Triple.h"
#include <initializer_list>
@@ -289,14 +290,6 @@ class SemaHLSL : public SemaBase {
std::optional<uint32_t> Index = std::nullopt;
};
- // Bitmask used to recall if the current semantic subtree is
- // input, output or inout.
- enum IOType {
- In = 0b01,
- Out = 0b10,
- InOut = 0b11,
- };
-
// The context shared by all semantics with the same IOType during
// flattening.
struct SemanticContext {
@@ -307,12 +300,7 @@ class SemaHLSL : public SemaBase {
// index collisions.
llvm::StringSet<> ActiveSemantics = {};
// The IOType of this semantic set.
- IOType CurrentIOType;
- };
-
- struct SemanticStageInfo {
- llvm::Triple::EnvironmentType Stage;
- IOType AllowedIOTypesMask;
+ llvm::hlsl::IOType CurrentIOType;
};
private:
@@ -343,8 +331,9 @@ class SemaHLSL : public SemaBase {
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
void diagnoseSemanticStageMismatch(
- const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
- std::initializer_list<SemanticStageInfo> AllowedStages);
+ const Attr *A, llvm::Triple::EnvironmentType Stage,
+ llvm::hlsl::IOType CurrentIOType,
+ std::initializer_list<llvm::hlsl::SemanticStageInfo> AllowedStages);
void handleGlobalStructOrArrayOfWithResources(VarDecl *VD);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 184339044e5bf..6bcd6d9182e44 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -54,6 +54,8 @@
using namespace clang;
using namespace clang::hlsl;
+using llvm::hlsl::IOType;
+using llvm::hlsl::SemanticStageInfo;
using RegisterType = HLSLResourceBindingAttr::RegisterType;
static CXXRecordDecl *createHostLayoutStruct(Sema &S,
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 0d0da50189e53..042b4afdf6faf 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -21,6 +21,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DXILABI.h"
#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/Triple.h"
#include <cstdint>
namespace llvm {
@@ -32,6 +33,20 @@ namespace hlsl {
// Definitions of the in-memory data layout structures
+// Bitmask denoting whether a semantic is an input, output, or a value that is
+// constant across a patch (hull/domain shaders) or primitive (mesh shaders).
+enum IOType {
+ In = 0b001,
+ Out = 0b010,
+ InOut = 0b011,
+ PatchConstantOrPrimitive = 0b100,
+};
+
+struct SemanticStageInfo {
+ Triple::EnvironmentType Stage;
+ IOType AllowedIOTypesMask;
+};
+
// Sentinel values denoting that an element is unallocated
static constexpr uint32_t UnallocatedRow = ~0U;
static constexpr uint8_t UnallocatedCol = 0xFF;
>From 0a79bad0fc01ced54e83f66e55fa3d289ae02229 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:42:51 +0000
Subject: [PATCH 02/36] extend to for patch constants
---
clang/lib/Sema/SemaHLSL.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6bcd6d9182e44..5ed6d4632d8ee 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1158,12 +1158,19 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
ValidType.push_back("input");
if (Case.AllowedIOTypesMask & IOType::Out)
ValidType.push_back("output");
+ if (Case.AllowedIOTypesMask & IOType::PatchConstantOrPrimitive)
+ ValidType.push_back("patch constant or primitive");
return std::string(
HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
" " + join(ValidType, "/");
});
+ StringRef CurrentIOTypeName = "patch constant or primitive";
+ if (CurrentIOType & IOType::In)
+ CurrentIOTypeName = "input";
+ else if (CurrentIOType & IOType::Out)
+ CurrentIOTypeName = "output";
Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
- << A->getAttrName() << (CurrentIOType & IOType::In ? "input" : "output")
+ << A->getAttrName() << CurrentIOTypeName
<< llvm::Triple::getEnvironmentTypeName(Case.Stage)
<< join(ValidCases, ", ");
return;
>From a65ec0ce3b98b7330cc61d0c7b47f5f51a0cc497 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:54:45 +0000
Subject: [PATCH 03/36] define common info getter
---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 3 +++
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 042b4afdf6faf..5749f0b0538a9 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -119,6 +119,9 @@ struct SemanticSignatureElement {
LLVM_ABI dxbc::PSV::SemanticKind getSemanticKind(StringRef SemanticName);
+LLVM_ABI ArrayRef<SemanticStageInfo>
+getAvailableStages(dxbc::PSV::SemanticKind SemanticKind);
+
} // namespace hlsl
} // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 48d68c68946d7..72a5366bafb70 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -17,6 +17,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Type.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
using namespace llvm::hlsl;
@@ -54,6 +55,11 @@ dxbc::PSV::SemanticKind hlsl::getSemanticKind(StringRef SemanticName) {
return dxbc::PSV::SemanticKind::Invalid;
}
+ArrayRef<SemanticStageInfo>
+hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
+ llvm_unreachable("available stages for given semantic kind are not handled");
+}
+
Expected<SemanticSignatureElement>
SemanticSignatureElement::fromMetadata(const MDNode *Node) {
// Operand positions within a signature element metadata node.
>From cf60ce9fdef9340dc1860e6bce45d521bc4d8d7b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:56:51 +0000
Subject: [PATCH 04/36] categorize compute semantics
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 72a5366bafb70..68f8e20b4ff8b 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -57,7 +57,19 @@ dxbc::PSV::SemanticKind hlsl::getSemanticKind(StringRef SemanticName) {
ArrayRef<SemanticStageInfo>
hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
- llvm_unreachable("available stages for given semantic kind are not handled");
+ switch (SemanticKind) {
+ case dxbc::PSV::SemanticKind::DispatchThreadID:
+ case dxbc::PSV::SemanticKind::GroupID:
+ case dxbc::PSV::SemanticKind::GroupIndex:
+ case dxbc::PSV::SemanticKind::GroupThreadID: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Compute, IOType::In}};
+ return Stages;
+ }
+ default:
+ llvm_unreachable(
+ "available stages for given semantic kind are not handled");
+ }
}
Expected<SemanticSignatureElement>
>From 66534f60a860bc77aafbe42cb93d3fda558eac69 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:56:57 +0000
Subject: [PATCH 05/36] categorize target
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 68f8e20b4ff8b..7b631fa22d545 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -66,6 +66,11 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
{Triple::Compute, IOType::In}};
return Stages;
}
+ case dxbc::PSV::SemanticKind::Target: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Pixel, IOType::Out}};
+ return Stages;
+ }
default:
llvm_unreachable(
"available stages for given semantic kind are not handled");
>From ab60f591d0e0b153a3c4b73e7b99f4a8c5eb980e Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:03 +0000
Subject: [PATCH 06/36] categorize vertexid
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 7b631fa22d545..4704f2859be82 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -71,6 +71,11 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
{Triple::Pixel, IOType::Out}};
return Stages;
}
+ case dxbc::PSV::SemanticKind::VertexID: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Vertex, IOType::In}};
+ return Stages;
+ }
default:
llvm_unreachable(
"available stages for given semantic kind are not handled");
>From 910bf701476377dab90ea5ee78a70b3781862a1b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:12 +0000
Subject: [PATCH 07/36] categorize position
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 4704f2859be82..1ac635e50d635 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -76,6 +76,11 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
{Triple::Vertex, IOType::In}};
return Stages;
}
+ case dxbc::PSV::SemanticKind::Position: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Vertex, IOType::InOut}, {Triple::Pixel, IOType::In}};
+ return Stages;
+ }
default:
llvm_unreachable(
"available stages for given semantic kind are not handled");
>From f7df75f0ba00cf358cb795755f2413b730b81c1c Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:26 +0000
Subject: [PATCH 08/36] categorize arbitrary
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 1ac635e50d635..480e6c0f122d4 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -58,6 +58,18 @@ dxbc::PSV::SemanticKind hlsl::getSemanticKind(StringRef SemanticName) {
ArrayRef<SemanticStageInfo>
hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
switch (SemanticKind) {
+ case dxbc::PSV::SemanticKind::Arbitrary: {
+ static constexpr IOType AllIOTypes =
+ static_cast<IOType>(IOType::InOut | IOType::PatchConstantOrPrimitive);
+ static constexpr IOType OutOrPatchConstant =
+ static_cast<IOType>(IOType::Out | IOType::PatchConstantOrPrimitive);
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Vertex, IOType::InOut}, {Triple::Geometry, IOType::InOut},
+ {Triple::Hull, AllIOTypes}, {Triple::Domain, AllIOTypes},
+ {Triple::Pixel, IOType::In}, {Triple::Mesh, OutOrPatchConstant},
+ };
+ return Stages;
+ }
case dxbc::PSV::SemanticKind::DispatchThreadID:
case dxbc::PSV::SemanticKind::GroupID:
case dxbc::PSV::SemanticKind::GroupIndex:
>From 6c2656c0136147e770aa72ed54ab99a4c8b08a95 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:38 +0000
Subject: [PATCH 09/36] categorize clip/cull
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 480e6c0f122d4..58e44fe756a75 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -93,6 +93,17 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
{Triple::Vertex, IOType::InOut}, {Triple::Pixel, IOType::In}};
return Stages;
}
+ case dxbc::PSV::SemanticKind::ClipDistance:
+ case dxbc::PSV::SemanticKind::CullDistance: {
+ static constexpr IOType AllIOTypes =
+ static_cast<IOType>(IOType::InOut | IOType::PatchConstantOrPrimitive);
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Vertex, IOType::InOut}, {Triple::Hull, AllIOTypes},
+ {Triple::Domain, AllIOTypes}, {Triple::Geometry, IOType::InOut},
+ {Triple::Pixel, IOType::In}, {Triple::Mesh, IOType::Out},
+ };
+ return Stages;
+ }
default:
llvm_unreachable(
"available stages for given semantic kind are not handled");
>From 5e5f6474d507f3110de7b9ef2e1015111b113d3f Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:46 +0000
Subject: [PATCH 10/36] categorize tess factors
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 58e44fe756a75..f28979bf702f6 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -104,6 +104,14 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
};
return Stages;
}
+ case dxbc::PSV::SemanticKind::TessFactor:
+ case dxbc::PSV::SemanticKind::InsideTessFactor: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Hull, IOType::PatchConstantOrPrimitive},
+ {Triple::Domain, IOType::PatchConstantOrPrimitive},
+ };
+ return Stages;
+ }
default:
llvm_unreachable(
"available stages for given semantic kind are not handled");
>From 0be9a96259a637132ee32e7b388a228590c969f9 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:57:53 +0000
Subject: [PATCH 11/36] categorize front-face semantics
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index f28979bf702f6..5971275fd0dde 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -88,6 +88,11 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
{Triple::Vertex, IOType::In}};
return Stages;
}
+ case dxbc::PSV::SemanticKind::IsFrontFace: {
+ static constexpr SemanticStageInfo Stages[] = {
+ {Triple::Geometry, IOType::Out}, {Triple::Pixel, IOType::In}};
+ return Stages;
+ }
case dxbc::PSV::SemanticKind::Position: {
static constexpr SemanticStageInfo Stages[] = {
{Triple::Vertex, IOType::InOut}, {Triple::Pixel, IOType::In}};
>From 03e6d10cf6c65923c5b27c556db3b931d7ada19b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:59:05 +0000
Subject: [PATCH 12/36] nfc: define all in enum
---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 1 +
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 10 +++-------
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 5749f0b0538a9..0af56b46d60b1 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -40,6 +40,7 @@ enum IOType {
Out = 0b010,
InOut = 0b011,
PatchConstantOrPrimitive = 0b100,
+ All = 0b111,
};
struct SemanticStageInfo {
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 5971275fd0dde..09fd5c4ee6744 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -59,13 +59,11 @@ ArrayRef<SemanticStageInfo>
hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
switch (SemanticKind) {
case dxbc::PSV::SemanticKind::Arbitrary: {
- static constexpr IOType AllIOTypes =
- static_cast<IOType>(IOType::InOut | IOType::PatchConstantOrPrimitive);
static constexpr IOType OutOrPatchConstant =
static_cast<IOType>(IOType::Out | IOType::PatchConstantOrPrimitive);
static constexpr SemanticStageInfo Stages[] = {
{Triple::Vertex, IOType::InOut}, {Triple::Geometry, IOType::InOut},
- {Triple::Hull, AllIOTypes}, {Triple::Domain, AllIOTypes},
+ {Triple::Hull, IOType::All}, {Triple::Domain, IOType::All},
{Triple::Pixel, IOType::In}, {Triple::Mesh, OutOrPatchConstant},
};
return Stages;
@@ -100,11 +98,9 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
}
case dxbc::PSV::SemanticKind::ClipDistance:
case dxbc::PSV::SemanticKind::CullDistance: {
- static constexpr IOType AllIOTypes =
- static_cast<IOType>(IOType::InOut | IOType::PatchConstantOrPrimitive);
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Vertex, IOType::InOut}, {Triple::Hull, AllIOTypes},
- {Triple::Domain, AllIOTypes}, {Triple::Geometry, IOType::InOut},
+ {Triple::Vertex, IOType::InOut}, {Triple::Hull, IOType::All},
+ {Triple::Domain, IOType::All}, {Triple::Geometry, IOType::InOut},
{Triple::Pixel, IOType::In}, {Triple::Mesh, IOType::Out},
};
return Stages;
>From a127af01ebc58492dbd2a9af1b7233b295e874e6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 17:59:46 +0000
Subject: [PATCH 13/36] define interpretation kinds enum
---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 0af56b46d60b1..85ddabe266c1e 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -43,6 +43,17 @@ enum IOType {
All = 0b111,
};
+enum class SemanticInterpretation {
+ Invalid,
+ NotAllocated,
+ Arbitrary,
+ SV,
+ SGV,
+ ClipCull,
+ TessFactor,
+ Target,
+};
+
struct SemanticStageInfo {
Triple::EnvironmentType Stage;
IOType AllowedIOTypesMask;
>From afd27adc4a2c4d149948c3869338ef17cc2f7f4e Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 18:02:29 +0000
Subject: [PATCH 14/36] include interpretation in semantic stage info
---
.../llvm/Frontend/HLSL/SemanticSignatures.h | 1 +
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 42 +++++++++++++------
2 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 85ddabe266c1e..30d04f0da098e 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -57,6 +57,7 @@ enum class SemanticInterpretation {
struct SemanticStageInfo {
Triple::EnvironmentType Stage;
IOType AllowedIOTypesMask;
+ SemanticInterpretation Interpretation;
};
// Sentinel values denoting that an element is unallocated
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 09fd5c4ee6744..9361f57115f5b 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -62,9 +62,12 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
static constexpr IOType OutOrPatchConstant =
static_cast<IOType>(IOType::Out | IOType::PatchConstantOrPrimitive);
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Vertex, IOType::InOut}, {Triple::Geometry, IOType::InOut},
- {Triple::Hull, IOType::All}, {Triple::Domain, IOType::All},
- {Triple::Pixel, IOType::In}, {Triple::Mesh, OutOrPatchConstant},
+ {Triple::Vertex, IOType::InOut, SemanticInterpretation::Arbitrary},
+ {Triple::Geometry, IOType::InOut, SemanticInterpretation::Arbitrary},
+ {Triple::Hull, IOType::All, SemanticInterpretation::Arbitrary},
+ {Triple::Domain, IOType::All, SemanticInterpretation::Arbitrary},
+ {Triple::Pixel, IOType::In, SemanticInterpretation::Arbitrary},
+ {Triple::Mesh, OutOrPatchConstant, SemanticInterpretation::Arbitrary},
};
return Stages;
}
@@ -73,43 +76,56 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
case dxbc::PSV::SemanticKind::GroupIndex:
case dxbc::PSV::SemanticKind::GroupThreadID: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Compute, IOType::In}};
+ {Triple::Compute, IOType::In, SemanticInterpretation::NotAllocated}};
return Stages;
}
case dxbc::PSV::SemanticKind::Target: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Pixel, IOType::Out}};
+ {Triple::Pixel, IOType::Out, SemanticInterpretation::Target}};
return Stages;
}
case dxbc::PSV::SemanticKind::VertexID: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Vertex, IOType::In}};
+ {Triple::Vertex, IOType::In, SemanticInterpretation::SV}};
return Stages;
}
case dxbc::PSV::SemanticKind::IsFrontFace: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Geometry, IOType::Out}, {Triple::Pixel, IOType::In}};
+ {Triple::Geometry, IOType::Out, SemanticInterpretation::SGV},
+ {Triple::Pixel, IOType::In, SemanticInterpretation::SGV}};
return Stages;
}
case dxbc::PSV::SemanticKind::Position: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Vertex, IOType::InOut}, {Triple::Pixel, IOType::In}};
+ {Triple::Vertex, IOType::In, SemanticInterpretation::Arbitrary},
+ {Triple::Vertex, IOType::Out, SemanticInterpretation::SV},
+ {Triple::Pixel, IOType::In, SemanticInterpretation::SV}};
return Stages;
}
case dxbc::PSV::SemanticKind::ClipDistance:
case dxbc::PSV::SemanticKind::CullDistance: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Vertex, IOType::InOut}, {Triple::Hull, IOType::All},
- {Triple::Domain, IOType::All}, {Triple::Geometry, IOType::InOut},
- {Triple::Pixel, IOType::In}, {Triple::Mesh, IOType::Out},
+ {Triple::Vertex, IOType::In, SemanticInterpretation::Arbitrary},
+ {Triple::Vertex, IOType::Out, SemanticInterpretation::ClipCull},
+ {Triple::Hull, IOType::InOut, SemanticInterpretation::ClipCull},
+ {Triple::Hull, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::Arbitrary},
+ {Triple::Domain, IOType::InOut, SemanticInterpretation::ClipCull},
+ {Triple::Domain, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::Arbitrary},
+ {Triple::Geometry, IOType::InOut, SemanticInterpretation::ClipCull},
+ {Triple::Pixel, IOType::In, SemanticInterpretation::ClipCull},
+ {Triple::Mesh, IOType::Out, SemanticInterpretation::ClipCull},
};
return Stages;
}
case dxbc::PSV::SemanticKind::TessFactor:
case dxbc::PSV::SemanticKind::InsideTessFactor: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Hull, IOType::PatchConstantOrPrimitive},
- {Triple::Domain, IOType::PatchConstantOrPrimitive},
+ {Triple::Hull, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::TessFactor},
+ {Triple::Domain, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::TessFactor},
};
return Stages;
}
>From e22de0a6a70d27808e867748a216a9b08381935f Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 18:10:44 +0000
Subject: [PATCH 15/36] add kind helper
---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 4 ++++
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 9 +++++++++
2 files changed, 13 insertions(+)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 30d04f0da098e..8e355a05cb86c 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -135,6 +135,10 @@ LLVM_ABI dxbc::PSV::SemanticKind getSemanticKind(StringRef SemanticName);
LLVM_ABI ArrayRef<SemanticStageInfo>
getAvailableStages(dxbc::PSV::SemanticKind SemanticKind);
+LLVM_ABI SemanticInterpretation
+getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind,
+ Triple::EnvironmentType ShaderStage, IOType IOTy);
+
} // namespace hlsl
} // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 9361f57115f5b..7a0e3a21564d4 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -135,6 +135,15 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
}
}
+SemanticInterpretation
+hlsl::getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind,
+ Triple::EnvironmentType ShaderStage, IOType IOTy) {
+ for (const SemanticStageInfo &Info : getAvailableStages(SemanticKind))
+ if (Info.Stage == ShaderStage && (Info.AllowedIOTypesMask & IOTy))
+ return Info.Interpretation;
+ return SemanticInterpretation::Invalid;
+}
+
Expected<SemanticSignatureElement>
SemanticSignatureElement::fromMetadata(const MDNode *Node) {
// Operand positions within a signature element metadata node.
>From 11ef54bdc4fdbb1084f4c6b043a54beab6e52122 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 18:17:04 +0000
Subject: [PATCH 16/36] nfc: refactor semahlsl to use look-up table
---
clang/include/clang/Sema/SemaHLSL.h | 3 +-
clang/lib/Sema/SemaHLSL.cpp | 73 +++++++++----------
.../CodeGenHLSL/semantics/SV_Position.ps.hlsl | 4 +-
.../semantics/semantic.array.output.hlsl | 2 +-
.../Availability/attr-availability-pixel.hlsl | 2 +-
.../Semantics/arbitrary.ps.output.hlsl | 7 ++
.../Semantics/position.ps.struct.hlsl | 5 +-
.../Semantics/position.ps.struct.reuse.hlsl | 5 +-
.../SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
clang/test/SemaHLSL/num_threads.hlsl | 7 +-
clang/test/SemaHLSL/shader_type_attr.hlsl | 2 +-
11 files changed, 59 insertions(+), 53 deletions(-)
create mode 100644 clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 0f834df21c40d..dcf165be082a2 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -20,6 +20,7 @@
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/SemaBase.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
@@ -333,7 +334,7 @@ class SemaHLSL : public SemaBase {
void diagnoseSemanticStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
llvm::hlsl::IOType CurrentIOType,
- std::initializer_list<llvm::hlsl::SemanticStageInfo> AllowedStages);
+ llvm::ArrayRef<llvm::hlsl::SemanticStageInfo> AllowedStages);
void handleGlobalStructOrArrayOfWithResources(VarDecl *VD);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5ed6d4632d8ee..a678df9e4774b 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1080,15 +1080,19 @@ void SemaHLSL::checkSemanticAnnotation(
assert(ShaderAttr && "Entry point has no shader attribute");
llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
- auto SemanticName = SemanticAttr->getSemanticName().upper();
- if (SemanticName == "SV_DISPATCHTHREADID" ||
- SemanticName == "SV_GROUPINDEX" || SemanticName == "SV_GROUPTHREADID" ||
- SemanticName == "SV_GROUPID") {
-
- if (ST != llvm::Triple::Compute)
- diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- {{llvm::Triple::Compute, IOType::In}});
+ llvm::dxbc::PSV::SemanticKind SemanticKind =
+ llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
+ llvm::hlsl::SemanticInterpretation Interpretation =
+ llvm::hlsl::getInterpretationKind(SemanticKind, ST, SC.CurrentIOType);
+ if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
+ llvm::hlsl::getAvailableStages(SemanticKind));
+ switch (SemanticKind) {
+ case llvm::dxbc::PSV::SemanticKind::DispatchThreadID:
+ case llvm::dxbc::PSV::SemanticKind::GroupID:
+ case llvm::dxbc::PSV::SemanticKind::GroupIndex:
+ case llvm::dxbc::PSV::SemanticKind::GroupThreadID:
if (SemanticAttr->getSemanticIndex() != 0) {
std::string PrettyName =
"'" + SemanticAttr->getSemanticName().str() + "'";
@@ -1096,33 +1100,10 @@ void SemaHLSL::checkSemanticAnnotation(
diag::err_hlsl_semantic_indexing_not_supported)
<< PrettyName;
}
- return;
- }
-
- if (SemanticName == "SV_POSITION") {
- // SV_Position can be an input or output in vertex shaders,
- // but only an input in pixel shaders.
- diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- {{llvm::Triple::Vertex, IOType::InOut},
- {llvm::Triple::Pixel, IOType::In}});
- return;
- }
- if (SemanticName == "SV_VERTEXID") {
- diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- {{llvm::Triple::Vertex, IOType::In}});
- return;
- }
-
- if (SemanticName == "SV_TARGET") {
- diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- {{llvm::Triple::Pixel, IOType::Out}});
- return;
+ break;
+ default:
+ break;
}
-
- // FIXME: catch-all for non-implemented system semantics reaching this
- // location.
- if (SemanticAttr->getAttrName()->getName().starts_with_insensitive("SV_"))
- llvm_unreachable("Unknown SemanticAttr");
}
void SemaHLSL::diagnoseAttrStageMismatch(
@@ -1141,9 +1122,21 @@ void SemaHLSL::diagnoseAttrStageMismatch(
void SemaHLSL::diagnoseSemanticStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
- std::initializer_list<SemanticStageInfo> Allowed) {
+ ArrayRef<SemanticStageInfo> Allowed) {
+ SmallVector<SemanticStageInfo, 8> CombinedAllowed;
+ for (const SemanticStageInfo &Case : Allowed) {
+ auto It = llvm::find_if(CombinedAllowed, [&](SemanticStageInfo Info) {
+ return Info.Stage == Case.Stage;
+ });
+ if (It == CombinedAllowed.end()) {
+ CombinedAllowed.push_back(Case);
+ continue;
+ }
+ It->AllowedIOTypesMask =
+ static_cast<IOType>(It->AllowedIOTypesMask | Case.AllowedIOTypesMask);
+ }
- for (auto &Case : Allowed) {
+ for (auto &Case : CombinedAllowed) {
if (Case.Stage != Stage)
continue;
@@ -1152,7 +1145,8 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
SmallVector<std::string, 8> ValidCases;
llvm::transform(
- Allowed, std::back_inserter(ValidCases), [](SemanticStageInfo Case) {
+ CombinedAllowed, std::back_inserter(ValidCases),
+ [](SemanticStageInfo Case) {
SmallVector<std::string, 2> ValidType;
if (Case.AllowedIOTypesMask & IOType::In)
ValidType.push_back("input");
@@ -1178,14 +1172,15 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
SmallVector<StringRef, 8> StageStrings;
llvm::transform(
- Allowed, std::back_inserter(StageStrings), [](SemanticStageInfo Case) {
+ CombinedAllowed, std::back_inserter(StageStrings),
+ [](SemanticStageInfo Case) {
return StringRef(
HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
});
Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
<< A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
- << (Allowed.size() != 1) << join(StageStrings, ", ");
+ << (CombinedAllowed.size() != 1) << join(StageStrings, ", ");
}
template <CastKind Kind>
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index 095532863ac5a..b1a0a2b16c3d1 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -4,10 +4,10 @@
// CHECK-SPIRV: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_0:]]
// CHECK: define void @main() {{.*}} {
-float4 main(float4 p : SV_Position) : A {
+float4 main(float4 p : SV_Position) : SV_Target {
// CHECK-SPIRV: %[[P:.*]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 4
// CHECK-SPIRV: %[[R:.*]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[P]])
- // CHECK-SPIRV: store <4 x float> %[[R]], ptr addrspace(8) @A0, align 4
+ // CHECK-SPIRV: store <4 x float> %[[R]], ptr addrspace(8) @SV_Target0, align 4
// CHECK-DXIL: %[[INPUT:.*]] = call <4 x float> @llvm.dx.load.input.v4f32(i32 0, i32 0, i8 0, i32 poison)
// CHECK-DXIL: %[[RESULT:.*]] = call <4 x float> @_Z4mainDv4_f(<4 x float> %[[INPUT]])
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
index 5427a569e5eee..8a8ba0f52bc1e 100644
--- a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
@@ -8,7 +8,7 @@ struct S0 {
// CHECK-SPIRV-DAG: @A0 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#METADATA_0:]]
-[shader("pixel")]
+[shader("vertex")]
S0 main1(float4 input : A) : B {
// CHECK: %[[ARG:.*]] = alloca %struct.S0
// CHECK-SPIRV: %[[INPUT:.*]] = load <4 x float>, ptr addrspace(7) @A0, align 4
diff --git a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
index 83c49738f8810..0f24f7f10f980 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
@@ -36,7 +36,7 @@ __attribute__((availability(shadermodel, introduced = 5.0, environment = compute
__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh)))
unsigned f8();
-int main() : A {
+float main() : SV_Target {
// expected-error@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}}
// expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}}
unsigned A = f1(); // #f1_call
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
new file mode 100644
index 0000000000000..308bb48b096ba
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -finclude-default-header -x hlsl -verify -o - %s
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
+
+float4 main(float4 a : A) : B {
+// expected-error at -1 {{semantic 'B' is unsupported in pixel shaders as output}}
+ return a;
+}
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
index 213a53e30155b..d8fdd58ba0855 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
@@ -9,13 +9,12 @@ struct S {
// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:15> "SV_Position" 3
};
-// FIXME(Keenuts): add mandatory output semantic once those are implemented.
-float4 main(S s) : B {
+float4 main(S s) : SV_Target {
// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (S)'
// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:15 used s 'S'
// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <line:4:15> "SV_Position" 0
// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <line:7:15> "SV_Position" 3
-// CHECK: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:20> "B" 0
+// CHECK: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:20> "SV_Target" 0
return s.f1;
}
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
index d10c817d53af2..532d73131895b 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
@@ -16,14 +16,13 @@ struct Top {
};
-// FIXME(Keenuts): add mandatory output semantic once those are implemented.
-float4 main(Top s : D) : F4 {
+float4 main(Top s : D) : SV_Target {
// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (Top)'
// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 used s 'Top'
// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:21> "D" 0
// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:21> "D" 0
// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:21> "D" 1
-// CHECK: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:26> "F" 4
+// CHECK: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:26> "SV_Target" 0
return s.f0.x;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index a77b46c0e9f1a..87972640e294a 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-pixel -finclude-default-header -x hlsl -verify -o - %s
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
-float4 main(float4 a : SV_Target) : A {
+float4 main(float4 a : SV_Target) : SV_Target {
// expected-error at -1 {{semantic 'SV_Target' is unsupported in pixel shaders as input, requires one of the following: pixel out}}
return a;
}
diff --git a/clang/test/SemaHLSL/num_threads.hlsl b/clang/test/SemaHLSL/num_threads.hlsl
index 52e71ec458161..6713af80ba9d6 100644
--- a/clang/test/SemaHLSL/num_threads.hlsl
+++ b/clang/test/SemaHLSL/num_threads.hlsl
@@ -130,7 +130,12 @@ int largeZ();
#endif
// expected-error-re at +1 {{attribute 'numthreads' is unsupported in '{{[A-Za-z]+}}' shaders, requires one of the following: compute, amplification, mesh}}
[numthreads(1,1,1)]
-int main() : A {
+#if __SHADER_TARGET_STAGE == __SHADER_STAGE_PIXEL
+float main() : SV_Target
+#else
+int main() : A
+#endif
+{
return 1;
}
diff --git a/clang/test/SemaHLSL/shader_type_attr.hlsl b/clang/test/SemaHLSL/shader_type_attr.hlsl
index 5f30a520b7255..c0c3ec4fe0e6d 100644
--- a/clang/test/SemaHLSL/shader_type_attr.hlsl
+++ b/clang/test/SemaHLSL/shader_type_attr.hlsl
@@ -31,7 +31,7 @@ static void oops() {}
[shader("pixel")]
// expected-note at +1 {{conflicting attribute is here}}
[shader("vertex")]
-int doubledUp() : A {
+float doubledUp() : SV_Target {
return 1;
}
>From 0c4a469003efa74ed82544bb96db8898b2fc75d6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 18:21:46 +0000
Subject: [PATCH 17/36] nfc: refactor cghlsl to not do logic on the names
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 132 ++++++++++++++--------------
clang/lib/CodeGen/CGHLSLRuntime.h | 12 +--
2 files changed, 74 insertions(+), 70 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 05f755edde64b..66178493a9ccc 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -1435,18 +1435,17 @@ void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
}
llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
- IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
- const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
- std::optional<unsigned> Index, SemanticSignatures &Signature) {
-
- std::string SemanticName = Semantic->getAttrName()->getName().upper();
- if (SemanticName == "SV_GROUPINDEX") {
+ IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ SemanticSignatures &Signature) {
+ switch (SemanticKind) {
+ case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
llvm::Function *GroupIndex =
CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
return B.CreateCall(FunctionCallee(GroupIndex));
}
-
- if (SemanticName == "SV_DISPATCHTHREADID") {
+ case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
llvm::Function *ThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1454,8 +1453,7 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
: CGM.getIntrinsic(IntrinID);
return buildVectorInput(B, ThreadIDIntrinsic, Type);
}
-
- if (SemanticName == "SV_GROUPTHREADID") {
+ case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
llvm::Function *GroupThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1463,8 +1461,7 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
: CGM.getIntrinsic(IntrinID);
return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
}
-
- if (SemanticName == "SV_GROUPID") {
+ case llvm::dxbc::PSV::SemanticKind::GroupID: {
llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
llvm::Function *GroupIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1472,38 +1469,26 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
: CGM.getIntrinsic(IntrinID);
return buildVectorInput(B, GroupIDIntrinsic, Type);
}
-
- const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
- assert(ShaderAttr && "Entry point has no shader attribute");
- llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
-
- if (SemanticName == "SV_POSITION") {
- if (ST == Triple::EnvironmentType::Pixel) {
- if (CGM.getTarget().getTriple().isSPIRV())
- return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::FragCoord */ 15);
- if (CGM.getTarget().getTriple().isDXIL())
- return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
- Signature);
- }
-
- if (ST == Triple::EnvironmentType::Vertex) {
- return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index,
- Signature);
- }
- }
-
- if (SemanticName == "SV_VERTEXID") {
- if (ST == Triple::EnvironmentType::Vertex) {
- if (CGM.getTarget().getTriple().isSPIRV())
- return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
- Semantic->getAttrName()->getName(),
- /* BuiltIn::VertexIndex */ 42);
- else
- return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
- Signature);
- }
+ case llvm::dxbc::PSV::SemanticKind::Position:
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::FragCoord */ 15);
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
+ Signature);
+ break;
+ case llvm::dxbc::PSV::SemanticKind::VertexID:
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::VertexIndex */ 42);
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
+ Signature);
+ break;
+ default:
+ break;
}
llvm_unreachable(
@@ -1524,30 +1509,29 @@ static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
B.CreateStore(Source, GV);
}
-void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
- const clang::DeclaratorDecl *Decl,
- HLSLAppliedSemanticAttr *Semantic,
- std::optional<unsigned> Index,
- SemanticSignatures &Signature) {
-
- std::string SemanticName = Semantic->getAttrName()->getName().upper();
- if (SemanticName == "SV_POSITION") {
+void CGHLSLRuntime::emitSystemSemanticStore(
+ IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ SemanticSignatures &Signature) {
+ switch (SemanticKind) {
+ case llvm::dxbc::PSV::SemanticKind::Position:
if (CGM.getTarget().getTriple().isDXIL()) {
emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
return;
}
-
if (CGM.getTarget().getTriple().isSPIRV()) {
createSPIRVBuiltinStore(B, CGM.getModule(), Source,
Semantic->getAttrName()->getName(),
/* BuiltIn::Position */ 0);
return;
}
- }
-
- if (SemanticName == "SV_TARGET") {
+ break;
+ case llvm::dxbc::PSV::SemanticKind::Target:
emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
return;
+ default:
+ break;
}
llvm_unreachable(
@@ -1560,10 +1544,19 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
SemanticSignatures &Signature) {
std::optional<unsigned> Index = Semantic->getSemanticIndex();
- if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
- return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index,
- Signature);
- return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature);
+ llvm::dxbc::PSV::SemanticKind SemanticKind =
+ llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
+ const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
+ assert(ShaderAttr && "Entry point has no shader attribute");
+ llvm::hlsl::SemanticInterpretation Interpretation =
+ llvm::hlsl::getInterpretationKind(SemanticKind, ShaderAttr->getType(),
+ llvm::hlsl::IOType::In);
+ if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
+ llvm_unreachable("invalid semantic should have been diagnosed by Sema");
+ if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
+ return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature);
+ return emitSystemSemanticLoad(B, Type, Decl, Semantic, SemanticKind, Index,
+ Signature);
}
void CGHLSLRuntime::handleScalarSemanticStore(IRBuilder<> &B,
@@ -1573,10 +1566,21 @@ void CGHLSLRuntime::handleScalarSemanticStore(IRBuilder<> &B,
HLSLAppliedSemanticAttr *Semantic,
SemanticSignatures &Signature) {
std::optional<unsigned> Index = Semantic->getSemanticIndex();
- if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
- emitSystemSemanticStore(B, Source, Decl, Semantic, Index, Signature);
- else
- emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
+ llvm::dxbc::PSV::SemanticKind SemanticKind =
+ llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
+ const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
+ assert(ShaderAttr && "Entry point has no shader attribute");
+
+ llvm::hlsl::SemanticInterpretation Interpretation =
+ llvm::hlsl::getInterpretationKind(SemanticKind, ShaderAttr->getType(),
+ llvm::hlsl::IOType::Out);
+ assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
+ "invalid semantic should have been diagnosed by Sema");
+
+ if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
+ return emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
+ emitSystemSemanticStore(B, Source, Decl, Semantic, SemanticKind, Index,
+ Signature);
}
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 2f251505cfa3e..29d085b2c76e0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -222,16 +222,16 @@ class CGHLSLRuntime {
CodeGenModule &CGM;
- llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B,
- const FunctionDecl *FD, llvm::Type *Type,
- const clang::DeclaratorDecl *Decl,
- HLSLAppliedSemanticAttr *Semantic,
- std::optional<unsigned> Index,
- SemanticSignatures &Signature);
+ llvm::Value *emitSystemSemanticLoad(
+ llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ SemanticSignatures &Signature);
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic,
+ llvm::dxbc::PSV::SemanticKind SemanticKind,
std::optional<unsigned> Index,
SemanticSignatures &Signature);
>From 73a666ce1a12e2d2e4a46d2430404a628b7f34a0 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 19:00:44 +0000
Subject: [PATCH 18/36] review: small typo
---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 8e355a05cb86c..3f2d2946d44eb 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -41,6 +41,8 @@ enum IOType {
InOut = 0b011,
PatchConstantOrPrimitive = 0b100,
All = 0b111,
+
+ LLVM_MARK_AS_BITMASK_ENUM(PatchConstantOrPrimitive),
};
enum class SemanticInterpretation {
>From 0ce7889dda3d439120f49528180ab44faafef134 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Fri, 21 Aug 2026 23:23:06 +0000
Subject: [PATCH 19/36] audit all uses in SemaHLSL
---
clang/include/clang/Sema/SemaHLSL.h | 1 +
clang/lib/Sema/SemaHLSL.cpp | 118 ++++++++++------------------
2 files changed, 41 insertions(+), 78 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index dcf165be082a2..9e2212a6d9eda 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -207,6 +207,7 @@ class SemaHLSL : public SemaBase {
}
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
+ llvm::dxbc::PSV::SemanticKind SemanticKind,
std::optional<unsigned> Index);
void handleSemanticAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a678df9e4774b..5e075809101fd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -56,6 +56,7 @@ using namespace clang;
using namespace clang::hlsl;
using llvm::hlsl::IOType;
using llvm::hlsl::SemanticStageInfo;
+using SemanticKind = llvm::dxbc::PSV::SemanticKind;
using RegisterType = HLSLResourceBindingAttr::RegisterType;
static CXXRecordDecl *createHostLayoutStruct(Sema &S,
@@ -873,19 +874,20 @@ static bool isVkPipelineBuiltin(const ASTContext &AstContext, FunctionDecl *FD,
const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
assert(ShaderAttr && "Entry point has no shader attribute");
llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
- auto SemanticName = Semantic->getSemanticName().upper();
+ SemanticKind Kind = llvm::hlsl::getSemanticKind(Semantic->getSemanticName());
- // The SV_Position semantic is lowered to:
- // - Position built-in for vertex output.
- // - FragCoord built-in for fragment input.
- if (SemanticName == "SV_POSITION") {
+ switch (Kind) {
+ case SemanticKind::Position:
+ // The SV_Position semantic is lowered to:
+ // - Position built-in for vertex output.
+ // - FragCoord built-in for fragment input.
return (ST == llvm::Triple::Vertex && !IsInput) ||
(ST == llvm::Triple::Pixel && IsInput);
- }
- if (SemanticName == "SV_VERTEXID")
+ case SemanticKind::VertexID:
return true;
-
- return false;
+ default:
+ return false;
+ }
}
bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,
@@ -1080,19 +1082,19 @@ void SemaHLSL::checkSemanticAnnotation(
assert(ShaderAttr && "Entry point has no shader attribute");
llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
- llvm::dxbc::PSV::SemanticKind SemanticKind =
+ SemanticKind Kind =
llvm::hlsl::getSemanticKind(SemanticAttr->getSemanticName());
llvm::hlsl::SemanticInterpretation Interpretation =
- llvm::hlsl::getInterpretationKind(SemanticKind, ST, SC.CurrentIOType);
+ llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- llvm::hlsl::getAvailableStages(SemanticKind));
+ llvm::hlsl::getAvailableStages(Kind));
- switch (SemanticKind) {
- case llvm::dxbc::PSV::SemanticKind::DispatchThreadID:
- case llvm::dxbc::PSV::SemanticKind::GroupID:
- case llvm::dxbc::PSV::SemanticKind::GroupIndex:
- case llvm::dxbc::PSV::SemanticKind::GroupThreadID:
+ switch (Kind) {
+ case SemanticKind::DispatchThreadID:
+ case SemanticKind::GroupID:
+ case SemanticKind::GroupIndex:
+ case SemanticKind::GroupThreadID:
if (SemanticAttr->getSemanticIndex() != 0) {
std::string PrettyName =
"'" + SemanticAttr->getSemanticName().str() + "'";
@@ -1927,9 +1929,8 @@ bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
}
void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
+ SemanticKind Kind,
std::optional<unsigned> Index) {
- std::string SemanticName = AL.getAttrName()->getName().upper();
-
auto *VD = cast<ValueDecl>(D);
QualType ValueType = VD->getType();
if (auto *FD = dyn_cast<FunctionDecl>(D))
@@ -1943,74 +1944,34 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
}
}
- if (SemanticName == "SV_DISPATCHTHREADID") {
- diagnoseInputIDType(ValueType, AL);
- if (IsOutput)
- Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
- if (Index.has_value())
- Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
- }
-
- if (SemanticName == "SV_GROUPINDEX") {
- if (IsOutput)
- Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
- if (Index.has_value())
- Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
- }
-
- if (SemanticName == "SV_GROUPTHREADID") {
- diagnoseInputIDType(ValueType, AL);
- if (IsOutput)
- Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
- if (Index.has_value())
- Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
- }
-
- if (SemanticName == "SV_GROUPID") {
+ switch (Kind) {
+ case SemanticKind::DispatchThreadID:
+ case SemanticKind::GroupThreadID:
+ case SemanticKind::GroupID:
diagnoseInputIDType(ValueType, AL);
+ [[fallthrough]];
+ case SemanticKind::GroupIndex:
if (IsOutput)
Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
if (Index.has_value())
Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
- }
-
- if (SemanticName == "SV_POSITION") {
- const auto *VT = ValueType->getAs<VectorType>();
- if (!ValueType->hasFloatingRepresentation() ||
- (VT && VT->getNumElements() > 4))
- Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
- << AL << "float/float1/float2/float3/float4";
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
- }
-
- if (SemanticName == "SV_VERTEXID") {
+ break;
+ case SemanticKind::Position:
+ case SemanticKind::Target:
+ diagnosePositionType(ValueType, AL);
+ break;
+ case SemanticKind::VertexID: {
uint64_t SizeInBits = SemaRef.Context.getTypeSize(ValueType);
if (!ValueType->isUnsignedIntegerType() || SizeInBits != 32)
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) << AL << "uint";
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
- return;
+ break;
}
-
- if (SemanticName == "SV_TARGET") {
- const auto *VT = ValueType->getAs<VectorType>();
- if (!ValueType->hasFloatingRepresentation() ||
- (VT && VT->getNumElements() > 4))
- Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
- << AL << "float/float1/float2/float3/float4";
- D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
+ default:
+ Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
return;
}
- Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;
+ D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
}
void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) {
@@ -2023,10 +1984,11 @@ void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) {
std::optional<unsigned> Index =
ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;
- if (AL.getAttrName()->getName().starts_with_insensitive("SV_"))
- diagnoseSystemSemanticAttr(D, AL, Index);
- else
+ SemanticKind Kind = llvm::hlsl::getSemanticKind(AL.getAttrName()->getName());
+ if (Kind == SemanticKind::Arbitrary)
D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));
+ else
+ diagnoseSystemSemanticAttr(D, AL, Kind, Index);
}
void SemaHLSL::handlePackOffsetAttr(Decl *D, const ParsedAttr &AL) {
>From 5f5aab245321be0eec55e083b92ac95f512eace0 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 16:27:18 +0000
Subject: [PATCH 20/36] review: clean up nits
---
clang/lib/Sema/SemaHLSL.cpp | 6 +++---
llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h | 5 +++--
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 2 +-
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index da958578a418e..9341c0a3c9fdd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1127,7 +1127,7 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
ArrayRef<SemanticStageInfo> Allowed) {
SmallVector<SemanticStageInfo, 8> CombinedAllowed;
for (const SemanticStageInfo &Case : Allowed) {
- auto It = llvm::find_if(CombinedAllowed, [&](SemanticStageInfo Info) {
+ auto It = llvm::find_if(CombinedAllowed, [&](SemanticStageInfo &Info) {
return Info.Stage == Case.Stage;
});
if (It == CombinedAllowed.end()) {
@@ -1148,7 +1148,7 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
SmallVector<std::string, 8> ValidCases;
llvm::transform(
CombinedAllowed, std::back_inserter(ValidCases),
- [](SemanticStageInfo Case) {
+ [](SemanticStageInfo &Case) {
SmallVector<std::string, 2> ValidType;
if (Case.AllowedIOTypesMask & IOType::In)
ValidType.push_back("input");
@@ -1175,7 +1175,7 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
SmallVector<StringRef, 8> StageStrings;
llvm::transform(
CombinedAllowed, std::back_inserter(StageStrings),
- [](SemanticStageInfo Case) {
+ [](SemanticStageInfo &Case) {
return StringRef(
HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
});
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 3f2d2946d44eb..1756f9cc978f4 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -33,8 +33,9 @@ namespace hlsl {
// Definitions of the in-memory data layout structures
-// Bitmask denoting whether a semantic is an input, output, or a value that is
-// constant across a patch (hull/domain shaders) or primitive (mesh shaders).
+// Bitmask denoting whether a semantic is an input, output, inout or a value
+// that is constant across a patch (hull/domain shaders) or primitive
+// (mesh shaders).
enum IOType {
In = 0b001,
Out = 0b010,
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 7a0e3a21564d4..753cd28563d6e 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -131,7 +131,7 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
}
default:
llvm_unreachable(
- "available stages for given semantic kind are not handled");
+ "available stages for given semantic kind are not handled yet");
}
}
>From 16f98ae114b29aae4e23126abd9b4c21a0cf6d8d Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 16:33:26 +0000
Subject: [PATCH 21/36] review: use an assert
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 66178493a9ccc..578c5fc53bc89 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -1551,8 +1551,8 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
llvm::hlsl::SemanticInterpretation Interpretation =
llvm::hlsl::getInterpretationKind(SemanticKind, ShaderAttr->getType(),
llvm::hlsl::IOType::In);
- if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
- llvm_unreachable("invalid semantic should have been diagnosed by Sema");
+ assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
+ "invalid semantic should have been diagnosed by Sema");
if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature);
return emitSystemSemanticLoad(B, Type, Decl, Semantic, SemanticKind, Index,
>From 477aed64b1e173faa748753d646d7acd00b7f23a Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 16:36:09 +0000
Subject: [PATCH 22/36] review: improve diag function names
---
clang/include/clang/Sema/SemaHLSL.h | 7 ++++---
clang/lib/Sema/SemaHLSL.cpp | 8 ++++----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 3ecb6e6c61fe7..fa05921260646 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -231,9 +231,10 @@ class SemaHLSL : public SemaBase {
QualType ActOnTemplateShorthand(TemplateDecl *Template,
SourceLocation NameLoc);
- // Diagnose whether the input ID is uint/unit2/uint3 type.
- bool diagnoseInputIDType(QualType T, const ParsedAttr &AL);
- bool diagnosePositionType(QualType T, const ParsedAttr &AL);
+ // Diagnose whether the index type is uint/unit2/uint3 type.
+ bool diagnoseIndexType(QualType T, const ParsedAttr &AL);
+ // Diagnose whether the type is float/float2/float3/float4 type.
+ bool diagnoseFloatType(QualType T, const ParsedAttr &AL);
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
bool CanPerformElementwiseCast(Expr *Src, QualType DestType);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9341c0a3c9fdd..481497b4dbf86 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1904,7 +1904,7 @@ void SemaHLSL::handleVkLocationAttr(Decl *D, const ParsedAttr &AL) {
HLSLVkLocationAttr(getASTContext(), AL, Location));
}
-bool SemaHLSL::diagnoseInputIDType(QualType T, const ParsedAttr &AL) {
+bool SemaHLSL::diagnoseIndexType(QualType T, const ParsedAttr &AL) {
const auto *VT = T->getAs<VectorType>();
if (!T->hasUnsignedIntegerRepresentation() ||
@@ -1917,7 +1917,7 @@ bool SemaHLSL::diagnoseInputIDType(QualType T, const ParsedAttr &AL) {
return true;
}
-bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {
+bool SemaHLSL::diagnoseFloatType(QualType T, const ParsedAttr &AL) {
const auto *VT = T->getAs<VectorType>();
if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {
Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)
@@ -1948,7 +1948,7 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
case SemanticKind::DispatchThreadID:
case SemanticKind::GroupThreadID:
case SemanticKind::GroupID:
- diagnoseInputIDType(ValueType, AL);
+ diagnoseIndexType(ValueType, AL);
[[fallthrough]];
case SemanticKind::GroupIndex:
if (IsOutput)
@@ -1958,7 +1958,7 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
break;
case SemanticKind::Position:
case SemanticKind::Target:
- diagnosePositionType(ValueType, AL);
+ diagnoseFloatType(ValueType, AL);
break;
case SemanticKind::VertexID: {
uint64_t SizeInBits = SemaRef.Context.getTypeSize(ValueType);
>From 2d2306a38c7a2415ec94bc41328bacfd764c6285 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 16:56:16 +0000
Subject: [PATCH 23/36] self-review: remove dead code
---
clang/lib/Sema/SemaHLSL.cpp | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 481497b4dbf86..e386d80a7e35a 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1171,18 +1171,6 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
<< join(ValidCases, ", ");
return;
}
-
- SmallVector<StringRef, 8> StageStrings;
- llvm::transform(
- CombinedAllowed, std::back_inserter(StageStrings),
- [](SemanticStageInfo &Case) {
- return StringRef(
- HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage));
- });
-
- Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
- << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
- << (CombinedAllowed.size() != 1) << join(StageStrings, ", ");
}
template <CastKind Kind>
>From dfa25e6b6e1f60452a18b954d159d052144ff474 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 18:02:08 +0000
Subject: [PATCH 24/36] review: clean-up diagnose func
---
.../clang/Basic/DiagnosticSemaKinds.td | 4 +-
clang/include/clang/Sema/SemaHLSL.h | 9 +--
clang/lib/Sema/SemaHLSL.cpp | 63 ++++++++-----------
.../Semantics/arbitrary.ps.output.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/groupindex.hlsl | 12 ++--
.../Semantics/invalid_entry_parameter.hlsl | 8 +--
.../test/SemaHLSL/Semantics/position.ps.hlsl | 2 +-
.../SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
.../SemaHLSL/Semantics/target.vs.input.hlsl | 2 +-
.../SemaHLSL/Semantics/target.vs.output.hlsl | 2 +-
.../test/SemaHLSL/Semantics/vertexid.ps.hlsl | 2 +-
11 files changed, 48 insertions(+), 60 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9bd0a526654c7..b985a23035d79 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13682,8 +13682,8 @@ def err_hlsl_init_priority_unsupported : Error<
"initializer priorities are not supported in HLSL">;
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
- : Error<"semantic %0 is unsupported in %2 shaders as %1, requires one of "
- "the following: %3">;
+ : Error<"semantic %0 is not supported %select{in %1 shaders"
+ "|as a %1 shader %3, it is available as an %4}2">;
def err_hlsl_semantic_partial_explicit_indexing
: Error<"partial explicit stage input location assignment via "
"vk::location(X) unsupported">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index fa05921260646..6c0e5b52f7cb3 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -334,10 +334,11 @@ class SemaHLSL : public SemaBase {
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
- void diagnoseSemanticStageMismatch(
- const Attr *A, llvm::Triple::EnvironmentType Stage,
- llvm::hlsl::IOType CurrentIOType,
- llvm::ArrayRef<llvm::hlsl::SemanticStageInfo> AllowedStages);
+ void
+ diagnoseSemanticStageMismatch(const Attr *A,
+ llvm::Triple::EnvironmentType Stage,
+ llvm::hlsl::IOType CurrentIOType,
+ llvm::dxbc::PSV::SemanticKind SemanticKind);
void handleGlobalStructOrArrayOfWithResources(VarDecl *VD);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e386d80a7e35a..fd200ade60379 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1087,8 +1087,7 @@ void SemaHLSL::checkSemanticAnnotation(
llvm::hlsl::SemanticInterpretation Interpretation =
llvm::hlsl::getInterpretationKind(Kind, ST, SC.CurrentIOType);
if (Interpretation == llvm::hlsl::SemanticInterpretation::Invalid)
- diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType,
- llvm::hlsl::getAvailableStages(Kind));
+ diagnoseSemanticStageMismatch(SemanticAttr, ST, SC.CurrentIOType, Kind);
switch (Kind) {
case SemanticKind::DispatchThreadID:
@@ -1124,51 +1123,39 @@ void SemaHLSL::diagnoseAttrStageMismatch(
void SemaHLSL::diagnoseSemanticStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage, IOType CurrentIOType,
- ArrayRef<SemanticStageInfo> Allowed) {
- SmallVector<SemanticStageInfo, 8> CombinedAllowed;
- for (const SemanticStageInfo &Case : Allowed) {
- auto It = llvm::find_if(CombinedAllowed, [&](SemanticStageInfo &Info) {
- return Info.Stage == Case.Stage;
- });
- if (It == CombinedAllowed.end()) {
- CombinedAllowed.push_back(Case);
- continue;
- }
- It->AllowedIOTypesMask =
- static_cast<IOType>(It->AllowedIOTypesMask | Case.AllowedIOTypesMask);
- }
+ SemanticKind Kind) {
- for (auto &Case : CombinedAllowed) {
- if (Case.Stage != Stage)
- continue;
+ ArrayRef<SemanticStageInfo> Allowed = llvm::hlsl::getAvailableStages(Kind);
+ auto It = llvm::find_if(Allowed, [&Stage](const SemanticStageInfo &Info) {
+ return Info.Stage == Stage;
+ });
- if (CurrentIOType & Case.AllowedIOTypesMask)
- return;
+ // The semantic is not available in this shader stage at all.
+ if (It == Allowed.end()) {
+ Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
+ << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
+ << /*AvailableInStage=*/false;
+ return;
+ }
- SmallVector<std::string, 8> ValidCases;
- llvm::transform(
- CombinedAllowed, std::back_inserter(ValidCases),
- [](SemanticStageInfo &Case) {
- SmallVector<std::string, 2> ValidType;
- if (Case.AllowedIOTypesMask & IOType::In)
- ValidType.push_back("input");
- if (Case.AllowedIOTypesMask & IOType::Out)
- ValidType.push_back("output");
- if (Case.AllowedIOTypesMask & IOType::PatchConstantOrPrimitive)
- ValidType.push_back("patch constant or primitive");
- return std::string(
- HLSLShaderAttr::ConvertEnvironmentTypeToStr(Case.Stage)) +
- " " + join(ValidType, "/");
- });
+ auto AllowedIOTypes = It->AllowedIOTypesMask;
+ if (!(AllowedIOTypes & CurrentIOType)) {
StringRef CurrentIOTypeName = "patch constant or primitive";
if (CurrentIOType & IOType::In)
CurrentIOTypeName = "input";
else if (CurrentIOType & IOType::Out)
CurrentIOTypeName = "output";
+ SmallVector<std::string, 3> ValidType;
+ if (AllowedIOTypes & IOType::In)
+ ValidType.push_back("input");
+ if (AllowedIOTypes & IOType::Out)
+ ValidType.push_back("output");
+ if (AllowedIOTypes & IOType::PatchConstantOrPrimitive)
+ ValidType.push_back("patch constant or primitive");
Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
- << A->getAttrName() << CurrentIOTypeName
- << llvm::Triple::getEnvironmentTypeName(Case.Stage)
- << join(ValidCases, ", ");
+ << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
+ << /*AvailableInStage=*/true << CurrentIOTypeName
+ << join(ValidType, ", ");
return;
}
}
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
index 308bb48b096ba..9306af56503ec 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : B {
-// expected-error at -1 {{semantic 'B' is unsupported in pixel shaders as output}}
+// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output, it is available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/groupindex.hlsl b/clang/test/SemaHLSL/Semantics/groupindex.hlsl
index a33e060c82906..f6ce2105f3139 100644
--- a/clang/test/SemaHLSL/Semantics/groupindex.hlsl
+++ b/clang/test/SemaHLSL/Semantics/groupindex.hlsl
@@ -4,26 +4,26 @@
[shader("compute")][numthreads(32,1,1)]
void compute(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'pixel' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in pixel shaders}}
[shader("pixel")]
void pixel(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'vertex' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in vertex shaders}}
[shader("vertex")]
void vertex(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'geometry' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in geometry shaders}}
[shader("geometry")]
void geometry(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'domain' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in domain shaders}}
[shader("domain")]
void domain(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'amplification' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in amplification shaders}}
[shader("amplification")][numthreads(32,1,1)]
void amplification(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{attribute 'SV_GroupIndex' is unsupported in 'mesh' shaders}}
+// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in mesh shaders}}
[shader("mesh")][numthreads(32,1,1)]
void mesh(int GI : SV_GroupIndex) {}
diff --git a/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
index 070075d419df1..200331869d24c 100644
--- a/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
+++ b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl
@@ -74,8 +74,8 @@ struct ST2_GThreadID {
[shader("vertex")]
-// expected-error at +4 {{attribute 'SV_GroupIndex' is unsupported in 'vertex' shaders, requires compute}}
-// expected-error at +3 {{attribute 'SV_DispatchThreadID' is unsupported in 'vertex' shaders, requires compute}}
-// expected-error at +2 {{attribute 'SV_GroupID' is unsupported in 'vertex' shaders, requires compute}}
-// expected-error at +1 {{attribute 'SV_GroupThreadID' is unsupported in 'vertex' shaders, requires compute}}
+// expected-error at +4 {{semantic 'SV_GroupIndex' is not supported in vertex shaders}}
+// expected-error at +3 {{semantic 'SV_DispatchThreadID' is not supported in vertex shaders}}
+// expected-error at +2 {{semantic 'SV_GroupID' is not supported in vertex shaders}}
+// expected-error at +1 {{semantic 'SV_GroupThreadID' is not supported in vertex shaders}}
void vs_main(int GI : SV_GroupIndex, uint ID : SV_DispatchThreadID, uint GID : SV_GroupID, uint GThreadID : SV_GroupThreadID) {}
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index d0fe19d1a5407..ac053a91d0ec6 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : SV_Position {
-// expected-error at -1 {{semantic 'SV_Position' is unsupported in pixel shaders as output, requires one of the following: vertex input/output, pixel input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output, it is available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index 87972640e294a..ace2639d37d6b 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : SV_Target {
-// expected-error at -1 {{semantic 'SV_Target' is unsupported in pixel shaders as input, requires one of the following: pixel out}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input, it is available as an output}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.vs.input.hlsl b/clang/test/SemaHLSL/Semantics/target.vs.input.hlsl
index add24732fc05a..cc4e983dcc09d 100644
--- a/clang/test/SemaHLSL/Semantics/target.vs.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.vs.input.hlsl
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-vertex -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : A {
-// expected-error at -1 {{attribute 'SV_Target' is unsupported in 'vertex' shaders, requires pixel}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported in vertex shaders}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.vs.output.hlsl b/clang/test/SemaHLSL/Semantics/target.vs.output.hlsl
index 0481bcdad0177..89f1ccf1f2eb7 100644
--- a/clang/test/SemaHLSL/Semantics/target.vs.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.vs.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-vertex -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Position) : SV_Target {
-// expected-error at -1 {{attribute 'SV_Target' is unsupported in 'vertex' shaders, requires pixel}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported in vertex shaders}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/vertexid.ps.hlsl b/clang/test/SemaHLSL/Semantics/vertexid.ps.hlsl
index d205e099149cb..1d26edfc5b8db 100644
--- a/clang/test/SemaHLSL/Semantics/vertexid.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/vertexid.ps.hlsl
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(uint id : SV_VertexID) : SV_Target {
-// expected-error at -1 {{attribute 'SV_VertexID' is unsupported in 'pixel' shaders, requires vertex}}
+// expected-error at -1 {{semantic 'SV_VertexID' is not supported in pixel shaders}}
return float4(1, 1, 1, 1);
}
>From e5b23934352ce756264acecb3400286301619440 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 18:28:43 +0000
Subject: [PATCH 25/36] review: correct iotype as a bitmask
---
clang/lib/Sema/SemaHLSL.cpp | 14 +++++++-------
.../llvm/Frontend/HLSL/SemanticSignatures.h | 5 ++++-
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 4 ++--
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index fd200ade60379..65a2e60d118cf 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -919,7 +919,7 @@ bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,
unsigned Location = ActiveSemantic.Index.value_or(0);
if (!isVkPipelineBuiltin(getASTContext(), FD, A,
- SC.CurrentIOType & IOType::In)) {
+ any(SC.CurrentIOType & IOType::In))) {
bool HasVkLocation = false;
if (auto *A = D->getAttr<HLSLVkLocationAttr>()) {
HasVkLocation = true;
@@ -1138,19 +1138,19 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
return;
}
- auto AllowedIOTypes = It->AllowedIOTypesMask;
+ IOType AllowedIOTypes = It->AllowedIOTypesMask;
if (!(AllowedIOTypes & CurrentIOType)) {
StringRef CurrentIOTypeName = "patch constant or primitive";
- if (CurrentIOType & IOType::In)
+ if (any(CurrentIOType & IOType::In))
CurrentIOTypeName = "input";
- else if (CurrentIOType & IOType::Out)
+ else if (any(CurrentIOType & IOType::Out))
CurrentIOTypeName = "output";
SmallVector<std::string, 3> ValidType;
- if (AllowedIOTypes & IOType::In)
+ if (any(AllowedIOTypes & IOType::In))
ValidType.push_back("input");
- if (AllowedIOTypes & IOType::Out)
+ if (any(AllowedIOTypes & IOType::Out))
ValidType.push_back("output");
- if (AllowedIOTypes & IOType::PatchConstantOrPrimitive)
+ if (any(AllowedIOTypes & IOType::PatchConstantOrPrimitive))
ValidType.push_back("patch constant or primitive");
Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
<< A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
diff --git a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
index 1756f9cc978f4..975fc2032d46e 100644
--- a/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
+++ b/llvm/include/llvm/Frontend/HLSL/SemanticSignatures.h
@@ -15,6 +15,7 @@
#define LLVM_FRONTEND_HLSL_SEMANTICSIGNATURES_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/DXContainer.h"
@@ -31,12 +32,14 @@ class MDNode;
namespace hlsl {
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
// Definitions of the in-memory data layout structures
// Bitmask denoting whether a semantic is an input, output, inout or a value
// that is constant across a patch (hull/domain shaders) or primitive
// (mesh shaders).
-enum IOType {
+enum class IOType {
In = 0b001,
Out = 0b010,
InOut = 0b011,
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 753cd28563d6e..9d4bb2b3ba7b7 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -60,7 +60,7 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
switch (SemanticKind) {
case dxbc::PSV::SemanticKind::Arbitrary: {
static constexpr IOType OutOrPatchConstant =
- static_cast<IOType>(IOType::Out | IOType::PatchConstantOrPrimitive);
+ IOType::Out | IOType::PatchConstantOrPrimitive;
static constexpr SemanticStageInfo Stages[] = {
{Triple::Vertex, IOType::InOut, SemanticInterpretation::Arbitrary},
{Triple::Geometry, IOType::InOut, SemanticInterpretation::Arbitrary},
@@ -139,7 +139,7 @@ SemanticInterpretation
hlsl::getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind,
Triple::EnvironmentType ShaderStage, IOType IOTy) {
for (const SemanticStageInfo &Info : getAvailableStages(SemanticKind))
- if (Info.Stage == ShaderStage && (Info.AllowedIOTypesMask & IOTy))
+ if (Info.Stage == ShaderStage && any(Info.AllowedIOTypesMask & IOTy))
return Info.Interpretation;
return SemanticInterpretation::Invalid;
}
>From 2fe71fa30c726bf02a595a473f1b44e78f5ecf22 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 18:39:22 +0000
Subject: [PATCH 26/36] review: correct stages to be completed
---
clang/test/SemaHLSL/Semantics/groupindex.hlsl | 2 --
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 17 +++++++++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/clang/test/SemaHLSL/Semantics/groupindex.hlsl b/clang/test/SemaHLSL/Semantics/groupindex.hlsl
index f6ce2105f3139..d07db9f4f57b4 100644
--- a/clang/test/SemaHLSL/Semantics/groupindex.hlsl
+++ b/clang/test/SemaHLSL/Semantics/groupindex.hlsl
@@ -20,10 +20,8 @@ void geometry(int GI : SV_GroupIndex) {}
[shader("domain")]
void domain(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in amplification shaders}}
[shader("amplification")][numthreads(32,1,1)]
void amplification(int GI : SV_GroupIndex) {}
-// expected-error at +2 {{semantic 'SV_GroupIndex' is not supported in mesh shaders}}
[shader("mesh")][numthreads(32,1,1)]
void mesh(int GI : SV_GroupIndex) {}
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 9d4bb2b3ba7b7..c1f66bd7daede 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -76,7 +76,11 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
case dxbc::PSV::SemanticKind::GroupIndex:
case dxbc::PSV::SemanticKind::GroupThreadID: {
static constexpr SemanticStageInfo Stages[] = {
- {Triple::Compute, IOType::In, SemanticInterpretation::NotAllocated}};
+ {Triple::Compute, IOType::In, SemanticInterpretation::NotAllocated},
+ {Triple::Mesh, IOType::In, SemanticInterpretation::NotAllocated},
+ {Triple::Amplification, IOType::In,
+ SemanticInterpretation::NotAllocated},
+ };
return Stages;
}
case dxbc::PSV::SemanticKind::Target: {
@@ -99,7 +103,16 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
static constexpr SemanticStageInfo Stages[] = {
{Triple::Vertex, IOType::In, SemanticInterpretation::Arbitrary},
{Triple::Vertex, IOType::Out, SemanticInterpretation::SV},
- {Triple::Pixel, IOType::In, SemanticInterpretation::SV}};
+ {Triple::Hull, IOType::InOut, SemanticInterpretation::SV},
+ {Triple::Hull, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::Arbitrary},
+ {Triple::Domain, IOType::InOut, SemanticInterpretation::SV},
+ {Triple::Domain, IOType::PatchConstantOrPrimitive,
+ SemanticInterpretation::Arbitrary},
+ {Triple::Geometry, IOType::InOut, SemanticInterpretation::SV},
+ {Triple::Pixel, IOType::In, SemanticInterpretation::SV},
+ {Triple::Mesh, IOType::Out, SemanticInterpretation::SV},
+ };
return Stages;
}
case dxbc::PSV::SemanticKind::ClipDistance:
>From dea4018fcd8598734f408532ed48b759eb35454c Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 18:45:07 +0000
Subject: [PATCH 27/36] review: assert a single iotype in getInterpretationKind
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index c1f66bd7daede..0c521342e487f 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -14,10 +14,12 @@
#include "llvm/Frontend/HLSL/SemanticSignatures.h"
#include "llvm/ADT/Enum.h"
#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/bit.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
using namespace llvm;
using namespace llvm::hlsl;
@@ -151,6 +153,8 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
SemanticInterpretation
hlsl::getInterpretationKind(dxbc::PSV::SemanticKind SemanticKind,
Triple::EnvironmentType ShaderStage, IOType IOTy) {
+ assert(llvm::has_single_bit(static_cast<unsigned>(IOTy)) &&
+ "a single IOType is expected, not a mask of IOTypes");
for (const SemanticStageInfo &Info : getAvailableStages(SemanticKind))
if (Info.Stage == ShaderStage && any(Info.AllowedIOTypesMask & IOTy))
return Info.Interpretation;
>From 69e4fff2dcc43272bf4218d069e9773d425707e5 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 19:01:32 +0000
Subject: [PATCH 28/36] review: add invariant unit tests of stage tables
---
llvm/unittests/Frontend/CMakeLists.txt | 1 +
.../Frontend/HLSLSemanticStagesTest.cpp | 102 ++++++++++++++++++
2 files changed, 103 insertions(+)
create mode 100644 llvm/unittests/Frontend/HLSLSemanticStagesTest.cpp
diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt
index 8976dd1b2f737..b8a26561069d5 100644
--- a/llvm/unittests/Frontend/CMakeLists.txt
+++ b/llvm/unittests/Frontend/CMakeLists.txt
@@ -16,6 +16,7 @@ add_llvm_unittest(LLVMFrontendTests
EnumSetTest.cpp
HLSLBindingTest.cpp
HLSLRootSignatureDumpTest.cpp
+ HLSLSemanticStagesTest.cpp
HLSLSemanticSignatureMetadataTest.cpp
OpenACCTest.cpp
OpenMPContextTest.cpp
diff --git a/llvm/unittests/Frontend/HLSLSemanticStagesTest.cpp b/llvm/unittests/Frontend/HLSLSemanticStagesTest.cpp
new file mode 100644
index 0000000000000..d6aef45c4f5bf
--- /dev/null
+++ b/llvm/unittests/Frontend/HLSLSemanticStagesTest.cpp
@@ -0,0 +1,102 @@
+//===- HLSLSemanticStagesTest.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/SemanticSignatures.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <ostream>
+
+using namespace llvm;
+using namespace llvm::hlsl;
+
+namespace llvm::hlsl {
+
+static StringRef getInterpretationName(SemanticInterpretation Interpretation) {
+ switch (Interpretation) {
+ case SemanticInterpretation::Invalid:
+ return "Invalid";
+ case SemanticInterpretation::NotAllocated:
+ return "NotAllocated";
+ case SemanticInterpretation::Arbitrary:
+ return "Arbitrary";
+ case SemanticInterpretation::SV:
+ return "SV";
+ case SemanticInterpretation::SGV:
+ return "SGV";
+ case SemanticInterpretation::ClipCull:
+ return "ClipCull";
+ case SemanticInterpretation::TessFactor:
+ return "TessFactor";
+ case SemanticInterpretation::Target:
+ return "Target";
+ }
+ llvm_unreachable("unhandled interpretation");
+}
+
+// Print the enum by name to keep the test failures readable.
+static void PrintTo(SemanticInterpretation Interpretation, std::ostream *OS) {
+ *OS << getInterpretationName(Interpretation).str();
+}
+
+} // namespace llvm::hlsl
+
+namespace {
+
+using SemanticKind = dxbc::PSV::SemanticKind;
+
+// Every shader stage a semantic could possibly be used in, plus a stage that
+// never holds a signature (Library) to make sure it is always rejected.
+constexpr Triple::EnvironmentType AllStages[] = {
+ Triple::Vertex, Triple::Hull, Triple::Domain,
+ Triple::Geometry, Triple::Pixel, Triple::Compute,
+ Triple::Amplification, Triple::Mesh, Triple::Library};
+
+// The semantic kinds getAvailableStages knows about.
+constexpr SemanticKind SupportedKinds[] = {
+ SemanticKind::Arbitrary, SemanticKind::Position,
+ SemanticKind::VertexID, SemanticKind::Target,
+ SemanticKind::IsFrontFace, SemanticKind::ClipDistance,
+ SemanticKind::CullDistance, SemanticKind::TessFactor,
+ SemanticKind::InsideTessFactor, SemanticKind::DispatchThreadID,
+ SemanticKind::GroupID, SemanticKind::GroupIndex,
+ SemanticKind::GroupThreadID};
+
+// Ensure all stages return a valid SemanticInterpretation
+TEST(HLSLSemanticStagesTest, StagesAreValid) {
+ for (SemanticKind Kind : SupportedKinds) {
+ ArrayRef<SemanticStageInfo> Stages = getAvailableStages(Kind);
+ EXPECT_FALSE(Stages.empty());
+ for (const SemanticStageInfo &Info : Stages) {
+ EXPECT_TRUE(any(Info.AllowedIOTypesMask))
+ << "stage " << Triple::getEnvironmentTypeName(Info.Stage).str()
+ << " allows no IOType";
+ EXPECT_NE(Info.Interpretation, SemanticInterpretation::Invalid);
+ EXPECT_THAT(AllStages, testing::Contains(Info.Stage));
+ }
+ }
+}
+
+// Ensure a stage is not listed twice with overlapping IOTypes
+TEST(HLSLSemanticStagesTest, StageIOTypesAreDisjoint) {
+ for (SemanticKind Kind : SupportedKinds) {
+ ArrayRef<SemanticStageInfo> Stages = getAvailableStages(Kind);
+ for (Triple::EnvironmentType Stage : AllStages) {
+ IOType Seen = static_cast<IOType>(0);
+ for (const SemanticStageInfo &Info : Stages) {
+ if (Info.Stage != Stage)
+ continue;
+ EXPECT_FALSE(any(Seen & Info.AllowedIOTypesMask))
+ << "stage " << Triple::getEnvironmentTypeName(Stage).str()
+ << " is listed twice for the same IOType";
+ Seen |= Info.AllowedIOTypesMask;
+ }
+ }
+ }
+}
+
+} // namespace
>From 78a809ed110ea95fb3b80d4947445cc169ac33fa Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 19:08:26 +0000
Subject: [PATCH 29/36] review: correct double diag
---
clang/lib/Sema/SemaHLSL.cpp | 5 +++--
.../semantics/DispatchThreadID-noindex.hlsl | 4 ++--
.../semantics/SV_GroupID-noindex.hlsl | 4 ++--
.../semantics/SV_GroupThreadID-noindex.hlsl | 4 ++--
.../SemaHLSL/Semantics/semantic-indexing.hlsl | 19 +++++++++++++++++++
5 files changed, 28 insertions(+), 8 deletions(-)
create mode 100644 clang/test/SemaHLSL/Semantics/semantic-indexing.hlsl
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 65a2e60d118cf..c28d072397b27 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1928,8 +1928,9 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
case SemanticKind::GroupIndex:
if (IsOutput)
Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
- if (Index.has_value())
- Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;
+ // Indexing is diagnosed in checkSemanticAnnotation, where the semantic
+ // index of the entry point signature is known. It can be explicit, like
+ // here, or derived when a semantic is spread over an aggregate.
break;
case SemanticKind::Position:
case SemanticKind::Target:
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
index b41bb0b0e8995..cf0c75479ddd9 100644
--- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
-// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
[shader("compute")]
[numthreads(8,8,1)]
diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
index 795e880fba0fd..31f5bca195d57 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
-// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
[shader("compute")]
[numthreads(8,8,1)]
diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
index 1fd5ae4ff488e..5f34118cdc4b0 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
-// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note
[shader("compute")]
[numthreads(8,8,1)]
diff --git a/clang/test/SemaHLSL/Semantics/semantic-indexing.hlsl b/clang/test/SemaHLSL/Semantics/semantic-indexing.hlsl
new file mode 100644
index 0000000000000..b78d165c164b1
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/semantic-indexing.hlsl
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -fsyntax-only -verify %s
+
+struct Pair {
+ uint A;
+ uint B;
+};
+
+// The semantic index can be written explicitly ...
+[shader("compute")][numthreads(1,1,1)]
+void explicit_index(uint GI : SV_GroupIndex1) {}
+// expected-error at -1 {{semantic 'SV_GroupIndex' does not allow indexing}}
+
+// ... or be derived when a semantic is spread over an aggregate.
+[shader("compute")][numthreads(1,1,1)]
+void derived_index(Pair GI : SV_GroupIndex) {}
+// expected-error at -1 {{semantic 'SV_GroupIndex' does not allow indexing}}
+
+[shader("compute")][numthreads(1,1,1)]
+void no_index(uint GI : SV_GroupIndex) {}
>From cca419a759598999ce65c0bbdd8dddd6805fa6a2 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 19:20:03 +0000
Subject: [PATCH 30/36] self-review: remove redundant error
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 --
clang/lib/Sema/SemaHLSL.cpp | 28 ++++++++-----------
.../SemaHLSL/Semantics/output-parameters.hlsl | 26 +++++++++++++++++
3 files changed, 38 insertions(+), 18 deletions(-)
create mode 100644 clang/test/SemaHLSL/Semantics/output-parameters.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b985a23035d79..719c6c62801a5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13674,8 +13674,6 @@ def err_hlsl_missing_semantic_annotation : Error<
"function or patch constant function">;
def note_hlsl_semantic_used_here : Note<"%0 used here">;
def err_hlsl_unknown_semantic : Error<"unknown HLSL semantic %0">;
-def err_hlsl_semantic_output_not_supported
- : Error<"semantic %0 does not support output">;
def err_hlsl_semantic_indexing_not_supported
: Error<"semantic %0 does not allow indexing">;
def err_hlsl_init_priority_unsupported : Error<
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c28d072397b27..c98ef25fba2a3 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1051,6 +1051,8 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
SemaHLSL::SemanticContext InputSC = {};
InputSC.CurrentIOType = IOType::In;
+ SemaHLSL::SemanticContext OutputSC = {};
+ OutputSC.CurrentIOType = IOType::Out;
for (ParmVarDecl *Param : FD->parameters()) {
SemanticInfo ActiveSemantic;
@@ -1058,16 +1060,18 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
- // FIXME: Verify output semantics in parameters.
- if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, InputSC)) {
+ // FIXME: An `inout` parameter is part of both signatures, but it is only
+ // verified against the output one here.
+ const auto *MA = Param->getAttr<HLSLParamModifierAttr>();
+ SemanticContext &SC = MA && MA->isAnyOut() ? OutputSC : InputSC;
+
+ if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, SC)) {
Diag(Param->getLocation(), diag::note_previous_decl) << Param;
FD->setInvalidDecl();
}
}
SemanticInfo ActiveSemantic;
- SemaHLSL::SemanticContext OutputSC = {};
- OutputSC.CurrentIOType = IOType::Out;
ActiveSemantic.Semantic = FD->getAttr<HLSLParsedSemanticAttr>();
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
@@ -1911,26 +1915,18 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
if (auto *FD = dyn_cast<FunctionDecl>(D))
ValueType = FD->getReturnType();
- bool IsOutput = false;
- if (HLSLParamModifierAttr *MA = D->getAttr<HLSLParamModifierAttr>()) {
- if (MA->isOut()) {
- IsOutput = true;
+ // `out` and `inout` parameters are passed by reference.
+ if (HLSLParamModifierAttr *MA = D->getAttr<HLSLParamModifierAttr>())
+ if (MA->isAnyOut())
ValueType = cast<ReferenceType>(ValueType)->getPointeeType();
- }
- }
switch (Kind) {
case SemanticKind::DispatchThreadID:
case SemanticKind::GroupThreadID:
case SemanticKind::GroupID:
diagnoseIndexType(ValueType, AL);
- [[fallthrough]];
+ break;
case SemanticKind::GroupIndex:
- if (IsOutput)
- Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;
- // Indexing is diagnosed in checkSemanticAnnotation, where the semantic
- // index of the entry point signature is known. It can be explicit, like
- // here, or derived when a semantic is spread over an aggregate.
break;
case SemanticKind::Position:
case SemanticKind::Target:
diff --git a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
new file mode 100644
index 0000000000000..fe6eb2006aeee
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -fsyntax-only -verify %s
+
+// Parameters passed by reference are written by the entry point, so they are
+// verified against the output signature of the shader stage.
+
+[shader("vertex")]
+void vs_out(out float4 Pos : SV_Position) { Pos = 0; }
+
+[shader("pixel")]
+void ps_out(out float4 Color : SV_Target) { Color = 0; }
+
+[shader("pixel")]
+void ps_position_out(out float4 Pos : SV_Position) { Pos = 0; }
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output, it is available as an input}}
+
+[shader("compute")][numthreads(1,1,1)]
+void cs_group_index_out(out uint GI : SV_GroupIndex) { GI = 0; }
+// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output, it is available as an input}}
+
+// Output parameters share the output signature with the return value.
+[shader("pixel")]
+float4 ps_overlap(out float4 Color : SV_Target) : SV_Target {
+// expected-error at -1 {{semantic index overlap SV_Target0}}
+ Color = 0;
+ return 0;
+}
>From e9c77001d8a82c772e816bc076a16bfcd7253c25 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 20:12:16 +0000
Subject: [PATCH 31/36] review: return empty instead of crash
---
llvm/lib/Frontend/HLSL/SemanticSignatures.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
index 0c521342e487f..7c4480075d6af 100644
--- a/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
+++ b/llvm/lib/Frontend/HLSL/SemanticSignatures.cpp
@@ -145,8 +145,7 @@ hlsl::getAvailableStages(dxbc::PSV::SemanticKind SemanticKind) {
return Stages;
}
default:
- llvm_unreachable(
- "available stages for given semantic kind are not handled yet");
+ return {};
}
}
>From 69b3b236a8a4d6d8735faf136a1918c2620dac7a Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 8 Sep 2026 21:19:23 +0000
Subject: [PATCH 32/36] review: fix grammar typo
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/output-parameters.hlsl | 4 ++--
clang/test/SemaHLSL/Semantics/position.ps.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 719c6c62801a5..7d499ce4e3b1a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13681,7 +13681,7 @@ def err_hlsl_init_priority_unsupported : Error<
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
: Error<"semantic %0 is not supported %select{in %1 shaders"
- "|as a %1 shader %3, it is available as an %4}2">;
+ "|as a %1 shader %3; it is available as an %4}2">;
def err_hlsl_semantic_partial_explicit_indexing
: Error<"partial explicit stage input location assignment via "
"vk::location(X) unsupported">;
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
index 9306af56503ec..b29baa9e39529 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : B {
-// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output, it is available as an input}}
+// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output; it is available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
index fe6eb2006aeee..85397e094174c 100644
--- a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
+++ b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
@@ -11,11 +11,11 @@ void ps_out(out float4 Color : SV_Target) { Color = 0; }
[shader("pixel")]
void ps_position_out(out float4 Pos : SV_Position) { Pos = 0; }
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output, it is available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is available as an input}}
[shader("compute")][numthreads(1,1,1)]
void cs_group_index_out(out uint GI : SV_GroupIndex) { GI = 0; }
-// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output, it is available as an input}}
+// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output; it is available as an input}}
// Output parameters share the output signature with the return value.
[shader("pixel")]
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index ac053a91d0ec6..ddc8841393e5c 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : SV_Position {
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output, it is available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index ace2639d37d6b..a140d94cfb7b1 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : SV_Target {
-// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input, it is available as an output}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input; it is available as an output}}
return a;
}
>From 10cc2f4a76dd3e46edf34a8569a79de139c4f692 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Wed, 9 Sep 2026 17:38:33 +0000
Subject: [PATCH 33/36] review: update a(n) in error message
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/lib/Sema/SemaHLSL.cpp | 6 +++---
clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl | 7 +++++++
clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/output-parameters.hlsl | 4 ++--
clang/test/SemaHLSL/Semantics/position.ps.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
7 files changed, 16 insertions(+), 9 deletions(-)
create mode 100644 clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7d499ce4e3b1a..b6b91eb82de27 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13681,7 +13681,7 @@ def err_hlsl_init_priority_unsupported : Error<
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
: Error<"semantic %0 is not supported %select{in %1 shaders"
- "|as a %1 shader %3; it is available as an %4}2">;
+ "|as a %1 shader %3; it is only available as %4}2">;
def err_hlsl_semantic_partial_explicit_indexing
: Error<"partial explicit stage input location assignment via "
"vk::location(X) unsupported">;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c98ef25fba2a3..a348da02d7a84 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1151,11 +1151,11 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
CurrentIOTypeName = "output";
SmallVector<std::string, 3> ValidType;
if (any(AllowedIOTypes & IOType::In))
- ValidType.push_back("input");
+ ValidType.push_back("an input");
if (any(AllowedIOTypes & IOType::Out))
- ValidType.push_back("output");
+ ValidType.push_back("an output");
if (any(AllowedIOTypes & IOType::PatchConstantOrPrimitive))
- ValidType.push_back("patch constant or primitive");
+ ValidType.push_back("a patch constant or a primitive");
Diag(A->getLoc(), diag::err_hlsl_semantic_unsupported_iotype_for_stage)
<< A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)
<< /*AvailableInStage=*/true << CurrentIOTypeName
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
new file mode 100644
index 0000000000000..e569533d596c5
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-mesh -finclude-default-header -x hlsl -verify -o - %s
+// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-mesh -finclude-default-header -x hlsl -verify -o - %s
+
+[numthreads(1,1,1)]
+void main(uint a : A) {
+// expected-error at -1 {{semantic 'A' is not supported as a mesh shader input; it is only available as an output, a patch constant or a primitive}}
+}
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
index b29baa9e39529..4e9875b8802d4 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : B {
-// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output; it is available as an input}}
+// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
index 85397e094174c..0f135e34db24d 100644
--- a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
+++ b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
@@ -11,11 +11,11 @@ void ps_out(out float4 Color : SV_Target) { Color = 0; }
[shader("pixel")]
void ps_position_out(out float4 Pos : SV_Position) { Pos = 0; }
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is only available as an input}}
[shader("compute")][numthreads(1,1,1)]
void cs_group_index_out(out uint GI : SV_GroupIndex) { GI = 0; }
-// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output; it is available as an input}}
+// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output; it is only available as an input}}
// Output parameters share the output signature with the return value.
[shader("pixel")]
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index ddc8841393e5c..8e5b3d3decaab 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : SV_Position {
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index a140d94cfb7b1..d92bc5bfdaab3 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : SV_Target {
-// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input; it is available as an output}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input; it is only available as an output}}
return a;
}
>From 7bad6984e94af77a8c5096479c03ef159d61f4d2 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Wed, 9 Sep 2026 18:04:54 +0000
Subject: [PATCH 34/36] review: add fixmes to missing semantic implementations
---
clang/lib/CodeGen/CGHLSLRuntime.cpp | 74 ++++++++++++++++++++++++++---
clang/lib/CodeGen/CGHLSLRuntime.h | 4 +-
2 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 578c5fc53bc89..beeb919748994 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -1437,15 +1437,34 @@ void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic,
- llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ llvm::dxbc::PSV::SemanticKind SemanticKind,
+ llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
SemanticSignatures &Signature) {
switch (SemanticKind) {
case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
+ assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
+ llvm::Triple::Amplification},
+ Stage) &&
+ "SV_GroupIndex is in an unavailable stage and should have been "
+ "diagnosed by Sema");
+ assert(Stage != llvm::Triple::Mesh &&
+ Stage != llvm::Triple::Amplification &&
+ "FIXME: SV_GroupIndex is not yet implemented for this shader "
+ "stage");
llvm::Function *GroupIndex =
CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
return B.CreateCall(FunctionCallee(GroupIndex));
}
case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
+ assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
+ llvm::Triple::Amplification},
+ Stage) &&
+ "SV_DispatchThreadID is in an unavailable stage and should have "
+ "been diagnosed by Sema");
+ assert(Stage != llvm::Triple::Mesh &&
+ Stage != llvm::Triple::Amplification &&
+ "FIXME: SV_DispatchThreadID is not yet implemented for this "
+ "shader stage");
llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
llvm::Function *ThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1454,6 +1473,15 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
return buildVectorInput(B, ThreadIDIntrinsic, Type);
}
case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
+ assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
+ llvm::Triple::Amplification},
+ Stage) &&
+ "SV_GroupThreadID is in an unavailable stage and should have been "
+ "diagnosed by Sema");
+ assert(Stage != llvm::Triple::Mesh &&
+ Stage != llvm::Triple::Amplification &&
+ "FIXME: SV_GroupThreadID is not yet implemented for this shader "
+ "stage");
llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
llvm::Function *GroupThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1462,6 +1490,14 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
}
case llvm::dxbc::PSV::SemanticKind::GroupID: {
+ assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
+ llvm::Triple::Amplification},
+ Stage) &&
+ "SV_GroupID is in an unavailable stage and should have been "
+ "diagnosed by Sema");
+ assert(Stage != llvm::Triple::Mesh &&
+ Stage != llvm::Triple::Amplification &&
+ "FIXME: SV_GroupID is not yet implemented for this shader stage");
llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
llvm::Function *GroupIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
@@ -1470,6 +1506,15 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
return buildVectorInput(B, GroupIDIntrinsic, Type);
}
case llvm::dxbc::PSV::SemanticKind::Position:
+ assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
+ llvm::Triple::Geometry, llvm::Triple::Pixel},
+ Stage) &&
+ "SV_Position is in an unavailable stage and should have been "
+ "diagnosed by Sema");
+ assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
+ Stage != llvm::Triple::Geometry &&
+ "FIXME: loading SV_Position is not yet implemented for this "
+ "shader stage");
if (CGM.getTarget().getTriple().isSPIRV())
return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
Semantic->getAttrName()->getName(),
@@ -1479,6 +1524,9 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
Signature);
break;
case llvm::dxbc::PSV::SemanticKind::VertexID:
+ assert(Stage == llvm::Triple::Vertex &&
+ "SV_VertexID is in an unavailable stage and should have been "
+ "diagnosed by Sema");
if (CGM.getTarget().getTriple().isSPIRV())
return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
Semantic->getAttrName()->getName(),
@@ -1512,10 +1560,21 @@ static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
void CGHLSLRuntime::emitSystemSemanticStore(
IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic,
- llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ llvm::dxbc::PSV::SemanticKind SemanticKind,
+ llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
SemanticSignatures &Signature) {
switch (SemanticKind) {
case llvm::dxbc::PSV::SemanticKind::Position:
+ assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
+ llvm::Triple::Domain, llvm::Triple::Geometry,
+ llvm::Triple::Mesh},
+ Stage) &&
+ "SV_Position is in an unavailable stage and should have been "
+ "diagnosed by Sema");
+ assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
+ Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
+ "FIXME: storing SV_Position is not yet implemented for this "
+ "shader stage");
if (CGM.getTarget().getTriple().isDXIL()) {
emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
return;
@@ -1528,6 +1587,9 @@ void CGHLSLRuntime::emitSystemSemanticStore(
}
break;
case llvm::dxbc::PSV::SemanticKind::Target:
+ assert(Stage == llvm::Triple::Pixel &&
+ "SV_Target is in an unavailable stage and should have been "
+ "diagnosed by Sema");
emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
return;
default:
@@ -1555,8 +1617,8 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
"invalid semantic should have been diagnosed by Sema");
if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature);
- return emitSystemSemanticLoad(B, Type, Decl, Semantic, SemanticKind, Index,
- Signature);
+ return emitSystemSemanticLoad(B, Type, Decl, Semantic, SemanticKind,
+ ShaderAttr->getType(), Index, Signature);
}
void CGHLSLRuntime::handleScalarSemanticStore(IRBuilder<> &B,
@@ -1579,8 +1641,8 @@ void CGHLSLRuntime::handleScalarSemanticStore(IRBuilder<> &B,
if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
return emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
- emitSystemSemanticStore(B, Source, Decl, Semantic, SemanticKind, Index,
- Signature);
+ emitSystemSemanticStore(B, Source, Decl, Semantic, SemanticKind,
+ ShaderAttr->getType(), Index, Signature);
}
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 7fb54c033d74f..f551bb006ea2c 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -225,13 +225,15 @@ class CGHLSLRuntime {
llvm::Value *emitSystemSemanticLoad(
llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic,
- llvm::dxbc::PSV::SemanticKind SemanticKind, std::optional<unsigned> Index,
+ llvm::dxbc::PSV::SemanticKind SemanticKind,
+ llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
SemanticSignatures &Signature);
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic,
llvm::dxbc::PSV::SemanticKind SemanticKind,
+ llvm::Triple::EnvironmentType Stage,
std::optional<unsigned> Index,
SemanticSignatures &Signature);
>From 22374cbc5cf0381e92cf9bd723a5ec92597fda49 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Wed, 9 Sep 2026 18:18:39 +0000
Subject: [PATCH 35/36] review: correct more grammar
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/lib/Sema/SemaHLSL.cpp | 6 +++---
clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/output-parameters.hlsl | 4 ++--
clang/test/SemaHLSL/Semantics/position.ps.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
7 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b6b91eb82de27..712b3489207cd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13681,7 +13681,7 @@ def err_hlsl_init_priority_unsupported : Error<
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
: Error<"semantic %0 is not supported %select{in %1 shaders"
- "|as a %1 shader %3; it is only available as %4}2">;
+ "|as %1 shader %3; it is only available as %4}2">;
def err_hlsl_semantic_partial_explicit_indexing
: Error<"partial explicit stage input location assignment via "
"vk::location(X) unsupported">;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a348da02d7a84..9ddd58eb363c9 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1144,11 +1144,11 @@ void SemaHLSL::diagnoseSemanticStageMismatch(
IOType AllowedIOTypes = It->AllowedIOTypesMask;
if (!(AllowedIOTypes & CurrentIOType)) {
- StringRef CurrentIOTypeName = "patch constant or primitive";
+ StringRef CurrentIOTypeName = "patch constants or primitives";
if (any(CurrentIOType & IOType::In))
- CurrentIOTypeName = "input";
+ CurrentIOTypeName = "inputs";
else if (any(CurrentIOType & IOType::Out))
- CurrentIOTypeName = "output";
+ CurrentIOTypeName = "outputs";
SmallVector<std::string, 3> ValidType;
if (any(AllowedIOTypes & IOType::In))
ValidType.push_back("an input");
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
index e569533d596c5..0fc3673afe3cb 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
@@ -3,5 +3,5 @@
[numthreads(1,1,1)]
void main(uint a : A) {
-// expected-error at -1 {{semantic 'A' is not supported as a mesh shader input; it is only available as an output, a patch constant or a primitive}}
+// expected-error at -1 {{semantic 'A' is not supported as mesh shader inputs; it is only available as an output, a patch constant or a primitive}}
}
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
index 4e9875b8802d4..ac086a29e0f4d 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : B {
-// expected-error at -1 {{semantic 'B' is not supported as a pixel shader output; it is only available as an input}}
+// expected-error at -1 {{semantic 'B' is not supported as pixel shader outputs; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
index 0f135e34db24d..ede086a68d1de 100644
--- a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
+++ b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
@@ -11,11 +11,11 @@ void ps_out(out float4 Color : SV_Target) { Color = 0; }
[shader("pixel")]
void ps_position_out(out float4 Pos : SV_Position) { Pos = 0; }
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as pixel shader outputs; it is only available as an input}}
[shader("compute")][numthreads(1,1,1)]
void cs_group_index_out(out uint GI : SV_GroupIndex) { GI = 0; }
-// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as a compute shader output; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as compute shader outputs; it is only available as an input}}
// Output parameters share the output signature with the return value.
[shader("pixel")]
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index 8e5b3d3decaab..c8d2a9db796c5 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : SV_Position {
-// expected-error at -1 {{semantic 'SV_Position' is not supported as a pixel shader output; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported as pixel shader outputs; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index d92bc5bfdaab3..fb7761cc6faf8 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : SV_Target {
-// expected-error at -1 {{semantic 'SV_Target' is not supported as a pixel shader input; it is only available as an output}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported as pixel shader inputs; it is only available as an output}}
return a;
}
>From 480514b58a5aeb71d3a37632e795594c5d2c7929 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Wed, 9 Sep 2026 21:49:05 +0000
Subject: [PATCH 36/36] self-review: one last wording touch up
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/output-parameters.hlsl | 4 ++--
clang/test/SemaHLSL/Semantics/position.ps.hlsl | 2 +-
clang/test/SemaHLSL/Semantics/target.ps.input.hlsl | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 712b3489207cd..1f49ebd98d6f1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13681,7 +13681,7 @@ def err_hlsl_init_priority_unsupported : Error<
def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
def err_hlsl_semantic_unsupported_iotype_for_stage
: Error<"semantic %0 is not supported %select{in %1 shaders"
- "|as %1 shader %3; it is only available as %4}2">;
+ "|in %1 shader %3; it is only available as %4}2">;
def err_hlsl_semantic_partial_explicit_indexing
: Error<"partial explicit stage input location assignment via "
"vk::location(X) unsupported">;
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
index 0fc3673afe3cb..279bad839ba82 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ms.input.hlsl
@@ -3,5 +3,5 @@
[numthreads(1,1,1)]
void main(uint a : A) {
-// expected-error at -1 {{semantic 'A' is not supported as mesh shader inputs; it is only available as an output, a patch constant or a primitive}}
+// expected-error at -1 {{semantic 'A' is not supported in mesh shader inputs; it is only available as an output, a patch constant or a primitive}}
}
diff --git a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
index ac086a29e0f4d..55612cf0eba8f 100644
--- a/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
+++ b/clang/test/SemaHLSL/Semantics/arbitrary.ps.output.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : B {
-// expected-error at -1 {{semantic 'B' is not supported as pixel shader outputs; it is only available as an input}}
+// expected-error at -1 {{semantic 'B' is not supported in pixel shader outputs; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
index ede086a68d1de..606e7fff35981 100644
--- a/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
+++ b/clang/test/SemaHLSL/Semantics/output-parameters.hlsl
@@ -11,11 +11,11 @@ void ps_out(out float4 Color : SV_Target) { Color = 0; }
[shader("pixel")]
void ps_position_out(out float4 Pos : SV_Position) { Pos = 0; }
-// expected-error at -1 {{semantic 'SV_Position' is not supported as pixel shader outputs; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported in pixel shader outputs; it is only available as an input}}
[shader("compute")][numthreads(1,1,1)]
void cs_group_index_out(out uint GI : SV_GroupIndex) { GI = 0; }
-// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported as compute shader outputs; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_GroupIndex' is not supported in compute shader outputs; it is only available as an input}}
// Output parameters share the output signature with the return value.
[shader("pixel")]
diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index c8d2a9db796c5..7c753ba5c1806 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : A) : SV_Position {
-// expected-error at -1 {{semantic 'SV_Position' is not supported as pixel shader outputs; it is only available as an input}}
+// expected-error at -1 {{semantic 'SV_Position' is not supported in pixel shader outputs; it is only available as an input}}
return a;
}
diff --git a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
index fb7761cc6faf8..02ec779527fd7 100644
--- a/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
+++ b/clang/test/SemaHLSL/Semantics/target.ps.input.hlsl
@@ -2,6 +2,6 @@
// RUN: %clang_cc1 -triple spirv-pc-vulkan1.3-pixel -finclude-default-header -x hlsl -verify -o - %s
float4 main(float4 a : SV_Target) : SV_Target {
-// expected-error at -1 {{semantic 'SV_Target' is not supported as pixel shader inputs; it is only available as an output}}
+// expected-error at -1 {{semantic 'SV_Target' is not supported in pixel shader inputs; it is only available as an output}}
return a;
}
More information about the cfe-commits
mailing list