Skip to content

Conversation

Keenuts
Copy link
Contributor

@Keenuts Keenuts commented Aug 7, 2025

This is the first PR to implement the semantics proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0031-semantics.md

This PR focuses on the changes required to handle user semantics, but tried to be almost NFC.
What changes is the error messages as the semantics case is not kept when reporting error messages.

You might notice the SV_GroupIndex semantic is not properly validated as are others. This is an existing behavior that we'll need to fix, but wanted to keep this separated from this rewrite to stay as-close as an NFC as possible.

The next PR will add support on the different kinds of I/O we can have using semantics (input, inout param, structs).

@Keenuts Keenuts requested review from farzonl and llvm-beanz August 7, 2025 15:52
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. HLSL HLSL Language Support labels Aug 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 7, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-hlsl

Author: Nathan Gauër (Keenuts)

Changes

This is the first PR to implement the semantics proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0031-semantics.md

This PR focuses on the changes required to handle user semantics, but tried to be almost NFC.
What changes is the error messages as the semantics case is not kept when reporting error messages.

You might notice the SV_GroupIndex semantic is not properly validated as are others. This is an existing behavior that we'll need to fix, but wanted to keep this separated from this rewrite to stay as-close as an NFC as possible.

The next PR will add support on the different kinds of I/O we can have using semantics (input, inout param, structs).


Patch is 46.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152537.diff

23 Files Affected:

  • (modified) clang/include/clang/AST/Attr.h (+35)
  • (modified) clang/include/clang/Basic/Attr.td (+36-32)
  • (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (+8)
  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+2-3)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5)
  • (modified) clang/include/clang/Parse/Parser.h (+8)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+21-4)
  • (modified) clang/lib/Basic/Attributes.cpp (+6-1)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+60-20)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+26-2)
  • (modified) clang/lib/Parse/ParseHLSL.cpp (+59-10)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+3-15)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+81-35)
  • (added) clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl (+8)
  • (added) clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl (+9)
  • (added) clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl (+8)
  • (modified) clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl (+2-2)
  • (modified) clang/test/ParserHLSL/semantic_parsing.hlsl (+1-1)
  • (modified) clang/test/SemaHLSL/Semantics/groupindex.hlsl (+6-6)
  • (modified) clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl (+16-16)
  • (modified) clang/test/SemaHLSL/Semantics/position.ps.size.hlsl (+2-2)
  • (modified) clang/test/SemaHLSL/Semantics/position.vs.hlsl (+1-1)
  • (modified) clang/utils/TableGen/ClangAttrEmitter.cpp (+8-1)
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index 994f236337b99..c313b5406f387 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -232,6 +232,41 @@ class HLSLAnnotationAttr : public InheritableAttr {
   }
 };
 
+class HLSLSemanticAttr : public HLSLAnnotationAttr {
+  unsigned SemanticIndex : 30;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned SemanticIndexable : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned SemanticExplicitIndex : 1;
+
+protected:
+  HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+                   attr::Kind AK, bool IsLateParsed,
+                   bool InheritEvenIfAlreadyPresent, bool SemanticIndexable)
+      : HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed,
+                           InheritEvenIfAlreadyPresent) {
+    this->SemanticIndexable = SemanticIndexable;
+    this->SemanticIndex = 0;
+    this->SemanticExplicitIndex = 0;
+  }
+
+public:
+  bool isSemanticIndexable() const { return SemanticIndexable; }
+
+  void setSemanticIndex(unsigned SemanticIndex) {
+    this->SemanticIndex = SemanticIndex;
+    this->SemanticExplicitIndex = true;
+  }
+
+  unsigned getSemanticIndex() const { return SemanticIndex; }
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Attr *A) {
+    return A->getKind() >= attr::FirstHLSLSemanticAttr &&
+           A->getKind() <= attr::LastHLSLSemanticAttr;
+  }
+};
+
 /// A parameter attribute which changes the argument-passing ABI rule
 /// for the parameter.
 class ParameterABIAttr : public InheritableParamAttr {
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..bbedc020767a0 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -396,7 +396,7 @@ class ClangGCC<string name, bit allowInC = 1, int version = 1>
 }
 
 // HLSL Annotation spellings
-class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">;
+class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation"> {}
 
 class Accessor<string name, list<Spelling> spellings> {
   string Name = name;
@@ -779,6 +779,16 @@ class DeclOrStmtAttr : InheritableAttr;
 /// An attribute class for HLSL Annotations.
 class HLSLAnnotationAttr : InheritableAttr;
 
+class HLSLSemanticAttr<bit Indexable> : HLSLAnnotationAttr {
+  bit SemanticIndexable = Indexable;
+  int SemanticIndex = 0;
+  bit SemanticExplicitIndex = 0;
+
+  let Spellings = [];
+  let Subjects = SubjectList<[ParmVar, Field, Function]>;
+  let LangOpts = [HLSL];
+}
+
 /// A target-specific attribute.  This class is meant to be used as a mixin
 /// with InheritableAttr or Attr depending on the attribute's needs.
 class TargetSpecificAttr<TargetSpec target> {
@@ -4873,27 +4883,6 @@ def HLSLNumThreads: InheritableAttr {
   let Documentation = [NumThreadsDocs];
 }
 
-def HLSLSV_GroupThreadID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupthreadid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupThreadIDDocs];
-}
-
-def HLSLSV_GroupID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupIDDocs];
-}
-
-def HLSLSV_GroupIndex: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupindex">];
-  let Subjects = SubjectList<[ParmVar, GlobalVar]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupIndexDocs];
-}
-
 def HLSLResourceBinding: InheritableAttr {
   let Spellings = [HLSLAnnotation<"register">];
   let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>;
@@ -4943,13 +4932,35 @@ def HLSLResourceBinding: InheritableAttr {
   }];
 }
 
-def HLSLSV_Position : HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_position">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
+def HLSLUnparsedSemantic : HLSLAnnotationAttr {
+  let Spellings = [];
+  let Args = [DefaultIntArgument<"Index", 0>,
+              DefaultBoolArgument<"ExplicitIndex", 0>];
+  let Subjects = SubjectList<[ParmVar, Field, Function]>;
   let LangOpts = [HLSL];
+  let Documentation = [InternalOnly];
+}
+
+def HLSLSV_Position : HLSLSemanticAttr</* Indexable= */ 1> {
   let Documentation = [HLSLSV_PositionDocs];
 }
 
+def HLSLSV_GroupThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupThreadIDDocs];
+}
+
+def HLSLSV_GroupID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupIDDocs];
+}
+
+def HLSLSV_GroupIndex : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupIndexDocs];
+}
+
+def HLSLSV_DispatchThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_DispatchThreadIDDocs];
+}
+
 def HLSLPackOffset: HLSLAnnotationAttr {
   let Spellings = [HLSLAnnotation<"packoffset">];
   let LangOpts = [HLSL];
@@ -4962,13 +4973,6 @@ def HLSLPackOffset: HLSLAnnotationAttr {
   }];
 }
 
-def HLSLSV_DispatchThreadID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_dispatchthreadid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_DispatchThreadIDDocs];
-}
-
 def HLSLShader : InheritableAttr {
   let Spellings = [Microsoft<"shader">];
   let Subjects = SubjectList<[HLSLEntry]>;
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 8a8db27490f06..6206e559b4729 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -393,6 +393,14 @@ def warn_hlsl_langstd_minimal :
           "recommend using %1 instead">,
   InGroup<HLSLDXCCompat>;
 
+def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
+
+def err_hlsl_semantic_missing : Error<"semantic annotations must be present "
+                                      "for all input and outputs of an entry "
+                                      "function or patch constant function">;
+
+def note_hlsl_semantic_used_here : Note<"%0 used here">;
+
 // ClangIR frontend errors
 def err_cir_to_cir_transform_failed : Error<
     "CIR-to-CIR transformation failed">, DefaultFatal;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 165f01514e2b1..e8999d4bd7858 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1851,9 +1851,8 @@ def note_max_tokens_total_override : Note<"total token limit set here">;
 
 def err_expected_semantic_identifier : Error<
   "expected HLSL Semantic identifier">;
-def err_invalid_declaration_in_hlsl_buffer : Error<
-  "invalid declaration inside %select{tbuffer|cbuffer}0">;
-def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">;
+def err_invalid_declaration_in_hlsl_buffer
+    : Error<"invalid declaration inside %select{tbuffer|cbuffer}0">;
 def err_hlsl_separate_attr_arg_and_number : Error<"wrong argument format for hlsl attribute, use %0 instead">;
 def ext_hlsl_access_specifiers : ExtWarn<
   "access specifiers are a clang HLSL extension">,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 94b174c758a5c..914ec11ba4554 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13058,6 +13058,11 @@ def err_hlsl_duplicate_parameter_modifier : Error<"duplicate parameter modifier
 def err_hlsl_missing_semantic_annotation : Error<
   "semantic annotations must be present for all parameters of an entry "
   "function or patch constant function">;
+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<
   "initializer priorities are not supported in HLSL">;
 
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 683934321a449..f07b4ebe567e5 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5188,6 +5188,14 @@ class Parser : public CodeCompletionHandler {
       ParseHLSLAnnotations(Attrs, EndLoc);
   }
 
+  struct ParsedSemantic {
+    StringRef Name;
+    unsigned Index;
+    bool Explicit;
+  };
+
+  ParsedSemantic ParseHLSLSemantic();
+
   void ParseHLSLAnnotations(ParsedAttributes &Attrs,
                             SourceLocation *EndLoc = nullptr,
                             bool CouldBeBitField = false);
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index c0da80a70bb82..a6bcca7a258f6 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -17,6 +17,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/SmallVector.h"
@@ -129,6 +130,7 @@ class SemaHLSL : public SemaBase {
   bool ActOnUninitializedVarDecl(VarDecl *D);
   void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
   void CheckEntryPoint(FunctionDecl *FD);
+  bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D);
   void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
                                const HLSLAnnotationAttr *AnnotationAttr);
   void DiagnoseAttrStageMismatch(
@@ -161,16 +163,31 @@ class SemaHLSL : public SemaBase {
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
   void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
   void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
   void handleShaderAttr(Decl *D, const ParsedAttr &AL);
   void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
   void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
   bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL);
 
+  template <typename T>
+  T *createSemanticAttr(const ParsedAttr &AL,
+                        std::optional<unsigned> Location) {
+    T *Attr = ::new (getASTContext()) T(getASTContext(), AL);
+    if (Attr->isSemanticIndexable())
+      Attr->setSemanticIndex(Location ? *Location : 0);
+    else if (Location.has_value()) {
+      Diag(Attr->getLocation(), diag::err_hlsl_semantic_indexing_not_supported)
+          << Attr->getAttrName()->getName();
+      return nullptr;
+    }
+
+    return Attr;
+  }
+
+  void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
+                                  std::optional<unsigned> Index);
+  void handleSemanticAttr(Decl *D, const ParsedAttr &AL);
+
   void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL);
 
   bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 81b186f844b8a..5878a4e3f83a4 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -189,7 +189,12 @@ AttributeCommonInfo::Kind
 AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
                                    const IdentifierInfo *ScopeName,
                                    Syntax SyntaxUsed) {
-  return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
+  AttributeCommonInfo::Kind Kind =
+      ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
+  if (SyntaxUsed == AS_HLSLAnnotation &&
+      Kind == AttributeCommonInfo::Kind::UnknownAttribute)
+    return AttributeCommonInfo::Kind::AT_HLSLUnparsedSemantic;
+  return Kind;
 }
 
 AttributeCommonInfo::AttrArgsInfo
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index a47d1cc22980d..346c867e5a0fe 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
 #include "llvm/IR/Constants.h"
@@ -383,47 +384,82 @@ static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
   return B.CreateLoad(Ty, GV);
 }
 
-llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
-                                              const ParmVarDecl &D,
-                                              llvm::Type *Ty) {
-  assert(D.hasAttrs() && "Entry parameter missing annotation attribute!");
-  if (D.hasAttr<HLSLSV_GroupIndexAttr>()) {
+llvm::Value *
+CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                      const clang::DeclaratorDecl *Decl,
+                                      SemanticInfo &ActiveSemantic) {
+  if (HLSLSV_GroupIndexAttr *S =
+          dyn_cast<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) {
     llvm::Function *GroupIndex =
         CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
     return B.CreateCall(FunctionCallee(GroupIndex));
   }
-  if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
+
+  if (HLSLSV_DispatchThreadIDAttr *S =
+          dyn_cast<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
     llvm::Function *ThreadIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, ThreadIDIntrinsic, Ty);
+    return buildVectorInput(B, ThreadIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_GroupThreadIDAttr>()) {
+
+  if (HLSLSV_GroupThreadIDAttr *S =
+          dyn_cast<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
     llvm::Function *GroupThreadIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, GroupThreadIDIntrinsic, Ty);
+    return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_GroupIDAttr>()) {
+
+  if (HLSLSV_GroupIDAttr *S =
+          dyn_cast<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
     llvm::Function *GroupIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, GroupIDIntrinsic, Ty);
+    return buildVectorInput(B, GroupIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_PositionAttr>()) {
-    if (getArch() == llvm::Triple::spirv)
-      return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
-                                    /* BuiltIn::Position */ 0);
-    llvm_unreachable("SV_Position semantic not implemented for this target.");
+
+  if (HLSLSV_PositionAttr *S =
+          dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) {
+    if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
+      return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+                                    S->getAttrName()->getName(),
+                                    /* BuiltIn::FragCoord */ 15);
   }
-  assert(false && "Unhandled parameter attribute");
-  return nullptr;
+
+  llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
+llvm::Value *
+CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                        const clang::DeclaratorDecl *Decl,
+                                        SemanticInfo &ActiveSemantic) {
+
+  if (!ActiveSemantic.Semantic) {
+    ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>();
+    if (!ActiveSemantic.Semantic) {
+      CGM.getDiags().Report(Decl->getInnerLocStart(),
+                            diag::err_hlsl_semantic_missing);
+      return nullptr;
+    }
+    ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+  }
+
+  return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic);
+}
+
+llvm::Value *
+CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                  const clang::DeclaratorDecl *Decl,
+                                  SemanticInfo &ActiveSemantic) {
+  assert(!Type->isStructTy());
+  return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic);
 }
 
 void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
@@ -440,13 +476,13 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
                                               Fn->getAttributes().getFnAttrs());
   EntryFn->setAttributes(NewAttrs);
   setHLSLEntryAttributes(FD, EntryFn);
+  llvm::SmallVector<Value *> Args;
 
   // Set the called function as internal linkage.
   Fn->setLinkage(GlobalValue::InternalLinkage);
 
   BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
   IRBuilder<> B(BB);
-  llvm::SmallVector<Value *> Args;
 
   SmallVector<OperandBundleDef, 1> OB;
   if (CGM.shouldEmitConvergenceTokens()) {
@@ -459,6 +495,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
 
   // FIXME: support struct parameters where semantics are on members.
   // See: https://github.com/llvm/llvm-project/issues/57874
+
   unsigned SRetOffset = 0;
   for (const auto &Param : Fn->args()) {
     if (Param.hasStructRetAttr()) {
@@ -468,14 +505,17 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
       Args.emplace_back(PoisonValue::get(Param.getType()));
       continue;
     }
+
     const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
-    Args.push_back(emitInputSemantic(B, *PD, Param.getType()));
+    SemanticInfo ActiveSemantic = {nullptr, 0};
+    Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic));
   }
 
   CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
   CI->setCallingConv(Fn->getCallingConv());
   // FIXME: Handle codegen for return type semantics.
   // See: https://github.com/llvm/llvm-project/issues/57875
+
   B.CreateRetVoid();
 
   // Add and identify root signature to function, if applicable
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 89d2aff85d913..1c78e8bbba7b7 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -21,6 +21,8 @@
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/IntrinsicsSPIRV.h"
 
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/HLSLRuntime.h"
 
@@ -29,6 +31,7 @@
 #include "llvm/Frontend/HLSL/HLSLResource.h"
 
 #include <optional>
+#include <unordered_set>
 #include <vector>
 
 // A function generator macro for picking the right intrinsic
@@ -133,8 +136,26 @@ class CGHLSLRuntime {
 protected:
   CodeGenModule &CGM;
 
-  llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
-                                 llvm::Type *Ty);
+  void collectInputSemantic(llvm::IRBuilder<> &B, const DeclaratorDecl *D,
+                            llvm::Type *Type,
+                            SmallVectorImpl<llvm::Value *> &Inputs);
+
+  struct SemanticInfo {
+    clang::HLSLSemanticAttr *Semantic;
+    uint32_t Index;
+  };
+
+  llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
+                                      const clang::DeclaratorDecl *Decl,
+                                      SemanticInfo &ActiveSemantic);
+
+  llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
+                                        const clang::DeclaratorDecl *Decl,
+                                        Sem...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Aug 7, 2025

@llvm/pr-subscribers-clang

Author: Nathan Gauër (Keenuts)

Changes

This is the first PR to implement the semantics proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0031-semantics.md

This PR focuses on the changes required to handle user semantics, but tried to be almost NFC.
What changes is the error messages as the semantics case is not kept when reporting error messages.

You might notice the SV_GroupIndex semantic is not properly validated as are others. This is an existing behavior that we'll need to fix, but wanted to keep this separated from this rewrite to stay as-close as an NFC as possible.

The next PR will add support on the different kinds of I/O we can have using semantics (input, inout param, structs).


Patch is 46.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152537.diff

23 Files Affected:

  • (modified) clang/include/clang/AST/Attr.h (+35)
  • (modified) clang/include/clang/Basic/Attr.td (+36-32)
  • (modified) clang/include/clang/Basic/DiagnosticFrontendKinds.td (+8)
  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+2-3)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5)
  • (modified) clang/include/clang/Parse/Parser.h (+8)
  • (modified) clang/include/clang/Sema/SemaHLSL.h (+21-4)
  • (modified) clang/lib/Basic/Attributes.cpp (+6-1)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+60-20)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+26-2)
  • (modified) clang/lib/Parse/ParseHLSL.cpp (+59-10)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+3-15)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+81-35)
  • (added) clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl (+8)
  • (added) clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl (+9)
  • (added) clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl (+8)
  • (modified) clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl (+2-2)
  • (modified) clang/test/ParserHLSL/semantic_parsing.hlsl (+1-1)
  • (modified) clang/test/SemaHLSL/Semantics/groupindex.hlsl (+6-6)
  • (modified) clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl (+16-16)
  • (modified) clang/test/SemaHLSL/Semantics/position.ps.size.hlsl (+2-2)
  • (modified) clang/test/SemaHLSL/Semantics/position.vs.hlsl (+1-1)
  • (modified) clang/utils/TableGen/ClangAttrEmitter.cpp (+8-1)
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index 994f236337b99..c313b5406f387 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -232,6 +232,41 @@ class HLSLAnnotationAttr : public InheritableAttr {
   }
 };
 
+class HLSLSemanticAttr : public HLSLAnnotationAttr {
+  unsigned SemanticIndex : 30;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned SemanticIndexable : 1;
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned SemanticExplicitIndex : 1;
+
+protected:
+  HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
+                   attr::Kind AK, bool IsLateParsed,
+                   bool InheritEvenIfAlreadyPresent, bool SemanticIndexable)
+      : HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed,
+                           InheritEvenIfAlreadyPresent) {
+    this->SemanticIndexable = SemanticIndexable;
+    this->SemanticIndex = 0;
+    this->SemanticExplicitIndex = 0;
+  }
+
+public:
+  bool isSemanticIndexable() const { return SemanticIndexable; }
+
+  void setSemanticIndex(unsigned SemanticIndex) {
+    this->SemanticIndex = SemanticIndex;
+    this->SemanticExplicitIndex = true;
+  }
+
+  unsigned getSemanticIndex() const { return SemanticIndex; }
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Attr *A) {
+    return A->getKind() >= attr::FirstHLSLSemanticAttr &&
+           A->getKind() <= attr::LastHLSLSemanticAttr;
+  }
+};
+
 /// A parameter attribute which changes the argument-passing ABI rule
 /// for the parameter.
 class ParameterABIAttr : public InheritableParamAttr {
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b3ff45b3e90a3..bbedc020767a0 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -396,7 +396,7 @@ class ClangGCC<string name, bit allowInC = 1, int version = 1>
 }
 
 // HLSL Annotation spellings
-class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">;
+class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation"> {}
 
 class Accessor<string name, list<Spelling> spellings> {
   string Name = name;
@@ -779,6 +779,16 @@ class DeclOrStmtAttr : InheritableAttr;
 /// An attribute class for HLSL Annotations.
 class HLSLAnnotationAttr : InheritableAttr;
 
+class HLSLSemanticAttr<bit Indexable> : HLSLAnnotationAttr {
+  bit SemanticIndexable = Indexable;
+  int SemanticIndex = 0;
+  bit SemanticExplicitIndex = 0;
+
+  let Spellings = [];
+  let Subjects = SubjectList<[ParmVar, Field, Function]>;
+  let LangOpts = [HLSL];
+}
+
 /// A target-specific attribute.  This class is meant to be used as a mixin
 /// with InheritableAttr or Attr depending on the attribute's needs.
 class TargetSpecificAttr<TargetSpec target> {
@@ -4873,27 +4883,6 @@ def HLSLNumThreads: InheritableAttr {
   let Documentation = [NumThreadsDocs];
 }
 
-def HLSLSV_GroupThreadID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupthreadid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupThreadIDDocs];
-}
-
-def HLSLSV_GroupID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupIDDocs];
-}
-
-def HLSLSV_GroupIndex: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_groupindex">];
-  let Subjects = SubjectList<[ParmVar, GlobalVar]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_GroupIndexDocs];
-}
-
 def HLSLResourceBinding: InheritableAttr {
   let Spellings = [HLSLAnnotation<"register">];
   let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>;
@@ -4943,13 +4932,35 @@ def HLSLResourceBinding: InheritableAttr {
   }];
 }
 
-def HLSLSV_Position : HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_position">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
+def HLSLUnparsedSemantic : HLSLAnnotationAttr {
+  let Spellings = [];
+  let Args = [DefaultIntArgument<"Index", 0>,
+              DefaultBoolArgument<"ExplicitIndex", 0>];
+  let Subjects = SubjectList<[ParmVar, Field, Function]>;
   let LangOpts = [HLSL];
+  let Documentation = [InternalOnly];
+}
+
+def HLSLSV_Position : HLSLSemanticAttr</* Indexable= */ 1> {
   let Documentation = [HLSLSV_PositionDocs];
 }
 
+def HLSLSV_GroupThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupThreadIDDocs];
+}
+
+def HLSLSV_GroupID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupIDDocs];
+}
+
+def HLSLSV_GroupIndex : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_GroupIndexDocs];
+}
+
+def HLSLSV_DispatchThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
+  let Documentation = [HLSLSV_DispatchThreadIDDocs];
+}
+
 def HLSLPackOffset: HLSLAnnotationAttr {
   let Spellings = [HLSLAnnotation<"packoffset">];
   let LangOpts = [HLSL];
@@ -4962,13 +4973,6 @@ def HLSLPackOffset: HLSLAnnotationAttr {
   }];
 }
 
-def HLSLSV_DispatchThreadID: HLSLAnnotationAttr {
-  let Spellings = [HLSLAnnotation<"sv_dispatchthreadid">];
-  let Subjects = SubjectList<[ParmVar, Field]>;
-  let LangOpts = [HLSL];
-  let Documentation = [HLSLSV_DispatchThreadIDDocs];
-}
-
 def HLSLShader : InheritableAttr {
   let Spellings = [Microsoft<"shader">];
   let Subjects = SubjectList<[HLSLEntry]>;
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 8a8db27490f06..6206e559b4729 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -393,6 +393,14 @@ def warn_hlsl_langstd_minimal :
           "recommend using %1 instead">,
   InGroup<HLSLDXCCompat>;
 
+def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">;
+
+def err_hlsl_semantic_missing : Error<"semantic annotations must be present "
+                                      "for all input and outputs of an entry "
+                                      "function or patch constant function">;
+
+def note_hlsl_semantic_used_here : Note<"%0 used here">;
+
 // ClangIR frontend errors
 def err_cir_to_cir_transform_failed : Error<
     "CIR-to-CIR transformation failed">, DefaultFatal;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 165f01514e2b1..e8999d4bd7858 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1851,9 +1851,8 @@ def note_max_tokens_total_override : Note<"total token limit set here">;
 
 def err_expected_semantic_identifier : Error<
   "expected HLSL Semantic identifier">;
-def err_invalid_declaration_in_hlsl_buffer : Error<
-  "invalid declaration inside %select{tbuffer|cbuffer}0">;
-def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">;
+def err_invalid_declaration_in_hlsl_buffer
+    : Error<"invalid declaration inside %select{tbuffer|cbuffer}0">;
 def err_hlsl_separate_attr_arg_and_number : Error<"wrong argument format for hlsl attribute, use %0 instead">;
 def ext_hlsl_access_specifiers : ExtWarn<
   "access specifiers are a clang HLSL extension">,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 94b174c758a5c..914ec11ba4554 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13058,6 +13058,11 @@ def err_hlsl_duplicate_parameter_modifier : Error<"duplicate parameter modifier
 def err_hlsl_missing_semantic_annotation : Error<
   "semantic annotations must be present for all parameters of an entry "
   "function or patch constant function">;
+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<
   "initializer priorities are not supported in HLSL">;
 
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 683934321a449..f07b4ebe567e5 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5188,6 +5188,14 @@ class Parser : public CodeCompletionHandler {
       ParseHLSLAnnotations(Attrs, EndLoc);
   }
 
+  struct ParsedSemantic {
+    StringRef Name;
+    unsigned Index;
+    bool Explicit;
+  };
+
+  ParsedSemantic ParseHLSLSemantic();
+
   void ParseHLSLAnnotations(ParsedAttributes &Attrs,
                             SourceLocation *EndLoc = nullptr,
                             bool CouldBeBitField = false);
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index c0da80a70bb82..a6bcca7a258f6 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -17,6 +17,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Sema/SemaBase.h"
 #include "llvm/ADT/SmallVector.h"
@@ -129,6 +130,7 @@ class SemaHLSL : public SemaBase {
   bool ActOnUninitializedVarDecl(VarDecl *D);
   void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
   void CheckEntryPoint(FunctionDecl *FD);
+  bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D);
   void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
                                const HLSLAnnotationAttr *AnnotationAttr);
   void DiagnoseAttrStageMismatch(
@@ -161,16 +163,31 @@ class SemaHLSL : public SemaBase {
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
   void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL);
-  void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL);
   void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
   void handleShaderAttr(Decl *D, const ParsedAttr &AL);
   void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
   void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
   bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL);
 
+  template <typename T>
+  T *createSemanticAttr(const ParsedAttr &AL,
+                        std::optional<unsigned> Location) {
+    T *Attr = ::new (getASTContext()) T(getASTContext(), AL);
+    if (Attr->isSemanticIndexable())
+      Attr->setSemanticIndex(Location ? *Location : 0);
+    else if (Location.has_value()) {
+      Diag(Attr->getLocation(), diag::err_hlsl_semantic_indexing_not_supported)
+          << Attr->getAttrName()->getName();
+      return nullptr;
+    }
+
+    return Attr;
+  }
+
+  void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
+                                  std::optional<unsigned> Index);
+  void handleSemanticAttr(Decl *D, const ParsedAttr &AL);
+
   void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL);
 
   bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 81b186f844b8a..5878a4e3f83a4 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -189,7 +189,12 @@ AttributeCommonInfo::Kind
 AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
                                    const IdentifierInfo *ScopeName,
                                    Syntax SyntaxUsed) {
-  return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
+  AttributeCommonInfo::Kind Kind =
+      ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
+  if (SyntaxUsed == AS_HLSLAnnotation &&
+      Kind == AttributeCommonInfo::Kind::UnknownAttribute)
+    return AttributeCommonInfo::Kind::AT_HLSLUnparsedSemantic;
+  return Kind;
 }
 
 AttributeCommonInfo::AttrArgsInfo
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index a47d1cc22980d..346c867e5a0fe 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
 #include "llvm/IR/Constants.h"
@@ -383,47 +384,82 @@ static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
   return B.CreateLoad(Ty, GV);
 }
 
-llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
-                                              const ParmVarDecl &D,
-                                              llvm::Type *Ty) {
-  assert(D.hasAttrs() && "Entry parameter missing annotation attribute!");
-  if (D.hasAttr<HLSLSV_GroupIndexAttr>()) {
+llvm::Value *
+CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                      const clang::DeclaratorDecl *Decl,
+                                      SemanticInfo &ActiveSemantic) {
+  if (HLSLSV_GroupIndexAttr *S =
+          dyn_cast<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) {
     llvm::Function *GroupIndex =
         CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
     return B.CreateCall(FunctionCallee(GroupIndex));
   }
-  if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
+
+  if (HLSLSV_DispatchThreadIDAttr *S =
+          dyn_cast<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
     llvm::Function *ThreadIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, ThreadIDIntrinsic, Ty);
+    return buildVectorInput(B, ThreadIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_GroupThreadIDAttr>()) {
+
+  if (HLSLSV_GroupThreadIDAttr *S =
+          dyn_cast<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
     llvm::Function *GroupThreadIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, GroupThreadIDIntrinsic, Ty);
+    return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_GroupIDAttr>()) {
+
+  if (HLSLSV_GroupIDAttr *S =
+          dyn_cast<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) {
     llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
     llvm::Function *GroupIDIntrinsic =
         llvm::Intrinsic::isOverloaded(IntrinID)
             ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
             : CGM.getIntrinsic(IntrinID);
-    return buildVectorInput(B, GroupIDIntrinsic, Ty);
+    return buildVectorInput(B, GroupIDIntrinsic, Type);
   }
-  if (D.hasAttr<HLSLSV_PositionAttr>()) {
-    if (getArch() == llvm::Triple::spirv)
-      return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
-                                    /* BuiltIn::Position */ 0);
-    llvm_unreachable("SV_Position semantic not implemented for this target.");
+
+  if (HLSLSV_PositionAttr *S =
+          dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) {
+    if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
+      return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+                                    S->getAttrName()->getName(),
+                                    /* BuiltIn::FragCoord */ 15);
   }
-  assert(false && "Unhandled parameter attribute");
-  return nullptr;
+
+  llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
+llvm::Value *
+CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                        const clang::DeclaratorDecl *Decl,
+                                        SemanticInfo &ActiveSemantic) {
+
+  if (!ActiveSemantic.Semantic) {
+    ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>();
+    if (!ActiveSemantic.Semantic) {
+      CGM.getDiags().Report(Decl->getInnerLocStart(),
+                            diag::err_hlsl_semantic_missing);
+      return nullptr;
+    }
+    ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+  }
+
+  return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic);
+}
+
+llvm::Value *
+CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+                                  const clang::DeclaratorDecl *Decl,
+                                  SemanticInfo &ActiveSemantic) {
+  assert(!Type->isStructTy());
+  return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic);
 }
 
 void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
@@ -440,13 +476,13 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
                                               Fn->getAttributes().getFnAttrs());
   EntryFn->setAttributes(NewAttrs);
   setHLSLEntryAttributes(FD, EntryFn);
+  llvm::SmallVector<Value *> Args;
 
   // Set the called function as internal linkage.
   Fn->setLinkage(GlobalValue::InternalLinkage);
 
   BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
   IRBuilder<> B(BB);
-  llvm::SmallVector<Value *> Args;
 
   SmallVector<OperandBundleDef, 1> OB;
   if (CGM.shouldEmitConvergenceTokens()) {
@@ -459,6 +495,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
 
   // FIXME: support struct parameters where semantics are on members.
   // See: https://github.com/llvm/llvm-project/issues/57874
+
   unsigned SRetOffset = 0;
   for (const auto &Param : Fn->args()) {
     if (Param.hasStructRetAttr()) {
@@ -468,14 +505,17 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
       Args.emplace_back(PoisonValue::get(Param.getType()));
       continue;
     }
+
     const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
-    Args.push_back(emitInputSemantic(B, *PD, Param.getType()));
+    SemanticInfo ActiveSemantic = {nullptr, 0};
+    Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic));
   }
 
   CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
   CI->setCallingConv(Fn->getCallingConv());
   // FIXME: Handle codegen for return type semantics.
   // See: https://github.com/llvm/llvm-project/issues/57875
+
   B.CreateRetVoid();
 
   // Add and identify root signature to function, if applicable
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 89d2aff85d913..1c78e8bbba7b7 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -21,6 +21,8 @@
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/IntrinsicsSPIRV.h"
 
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/HLSLRuntime.h"
 
@@ -29,6 +31,7 @@
 #include "llvm/Frontend/HLSL/HLSLResource.h"
 
 #include <optional>
+#include <unordered_set>
 #include <vector>
 
 // A function generator macro for picking the right intrinsic
@@ -133,8 +136,26 @@ class CGHLSLRuntime {
 protected:
   CodeGenModule &CGM;
 
-  llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D,
-                                 llvm::Type *Ty);
+  void collectInputSemantic(llvm::IRBuilder<> &B, const DeclaratorDecl *D,
+                            llvm::Type *Type,
+                            SmallVectorImpl<llvm::Value *> &Inputs);
+
+  struct SemanticInfo {
+    clang::HLSLSemanticAttr *Semantic;
+    uint32_t Index;
+  };
+
+  llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
+                                      const clang::DeclaratorDecl *Decl,
+                                      SemanticInfo &ActiveSemantic);
+
+  llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
+                                        const clang::DeclaratorDecl *Decl,
+                                        Sem...
[truncated]

@Keenuts
Copy link
Contributor Author

Keenuts commented Aug 13, 2025

@llvm-beanz anything blocking this review?

Copy link
Contributor

@s-perron s-perron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern is that the parser does not allow digits in the middle of the semantic name. I believe that is possible for user semantics. It works for DXC. Otherwise LGTM.

Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may come back to this.

@Keenuts
Copy link
Contributor Author

Keenuts commented Aug 25, 2025

My only concern is that the parser does not allow digits in the middle of the semantic name. I believe that is possible for user semantics. It works for DXC. Otherwise LGTM.

Thank you all!
reworked the semantic parsing to allow digits in the middle of the identifier. This simplified a bit the parsing. Extended testing to cover those.
Also addressed all other PR comments.

@Keenuts
Copy link
Contributor Author

Keenuts commented Aug 25, 2025

Will rebase after the approvals if possible so you keep a working "review changes since last review"

@Keenuts Keenuts requested a review from s-perron August 25, 2025 13:56
@Keenuts Keenuts requested review from farzonl and shafik August 26, 2025 15:43
@Keenuts
Copy link
Contributor Author

Keenuts commented Aug 29, 2025

@farzonl anything blocking?

@farzonl
Copy link
Member

farzonl commented Aug 29, 2025

@farzonl anything blocking?

I would prefer if @llvm-beanz or @tex3d did the sign off for this pr from our side.

@Keenuts Keenuts requested a review from llvm-beanz August 29, 2025 13:45
@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 3, 2025

@llvm-beanz anything blocking this review?

@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 8, 2025

@llvm-beanz friendly ping

Copy link
Collaborator

@llvm-beanz llvm-beanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only big concern is around the forced capitalization of semantics in the diagnostics.

I also left some notes about follow-up changes we should consider.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this thought... I kinda want emoji in my user defined semantic names now.

@Keenuts Keenuts enabled auto-merge (squash) September 9, 2025 12:30
@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 9, 2025

Thanks for the reviews! Applied the last small bits

@Keenuts Keenuts requested a review from s-perron September 9, 2025 12:31
The new system doesn't require the casted value, so we had a unused
variable warning.
@Keenuts Keenuts merged commit 57e1846 into llvm:main Sep 9, 2025
10 checks passed
Keenuts added a commit to Keenuts/llvm-project that referenced this pull request Sep 9, 2025
This commit adds the support for semantics annotations on structs, but
only for inputs. Due to the current semantics implemented, we cannot
test much more than nesting/shadowing.

Once user semantics are implemented, we'll be able to test arrays in
structs and more complex cases.

As-is, this commit has one weakness vs DXC: semantics type validation is
not looking at the inner-most type, but the outermost type:

```hlsl
struct Inner {
  uint tid;
};

Inner inner : SV_GroupID
```

This sample would fail today because `SV_GroupID` require the type to be
an integer. This works in DXC as the inner type is a integer.
Because GroupIndex is not correctly validated, I uses this semantic to
test the inheritance/shadowing. But this will need to be fixed in a
later commit.

Requires llvm#152537
@mgorny
Copy link
Member

mgorny commented Sep 9, 2025

I'm guessing this change broke the build for me:

FAILED: [code=1] docs/AttributeReference.rst /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs/AttributeReference.rst 
cd /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs && /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/bin/clang-tblgen -gen-attr-docs -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/include -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/include -I/usr/lib/llvm/22/include -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic/Attr.td --write-if-changed -o AttributeReference.rst -d AttributeReference.rst.d && /usr/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64 /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs/AttributeReference.rst.d /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/CMakeFiles/d/63214aa3df9ce54c496015feb0fb3942e9cf73781c78cb807e54fac358a06d47.d
/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic/Attr.td:4986:5: error: Attribute has no supported spellings; cannot be documented
def HLSLSV_DispatchThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
    ^

@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 9, 2025

I'm guessing this change broke the build for me:

FAILED: [code=1] docs/AttributeReference.rst /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs/AttributeReference.rst 
cd /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs && /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/bin/clang-tblgen -gen-attr-docs -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/include -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/include -I/usr/lib/llvm/22/include -I/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic/Attr.td --write-if-changed -o AttributeReference.rst -d AttributeReference.rst.d && /usr/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64 /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/docs/AttributeReference.rst.d /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/CMakeFiles/d/63214aa3df9ce54c496015feb0fb3942e9cf73781c78cb807e54fac358a06d47.d
/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang/docs/../include/clang/Basic/Attr.td:4986:5: error: Attribute has no supported spellings; cannot be documented
def HLSLSV_DispatchThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
    ^

Interesting, what cmake flags do you use? (seems like the CI doesn't build with those, so maybe I can repro on my end?)

@Keenuts Keenuts deleted the hlsl-semantics-1 branch September 9, 2025 16:53
@mgorny
Copy link
Member

mgorny commented Sep 9, 2025

LLVM with (sorry for no escaping, it's from build logs):

cmake -C /var/tmp/portage/llvm-core/llvm-22.0.0.9999/work/llvm_build-.arm64/gentoo_common_config.cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DLLVM_APPEND_VC_REV=OFF -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm/22 -DLLVM_LIBDIR_SUFFIX=64 -DBUILD_SHARED_LIBS=OFF -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DLLVM_DISTRIBUTION_COMPONENTS=LLVM;LTO;Remarks;llvm-config;cmake-exports;llvm-headers;LLVMDemangle;LLVMSupport;LLVMTableGen;LLVMCodeGenTypes;llvm_gtest;llvm_gtest_main;LLVMTestingAnnotations;LLVMTestingSupport;LLVMDebuginfod;llvm-tblgen;llvm-test-mustache-spec;FileCheck;llvm-PerfectShuffle;count;not;yaml-bench;UnicodeNameMappingGenerator;bugpoint;dsymutil;llc;lli;lli-child-target;llvm-addr2line;llvm-ar;llvm-as;llvm-bcanalyzer;llvm-bitcode-strip;llvm-c-test;llvm-cat;llvm-cfi-verify;llvm-cgdata;llvm-config;llvm-cov;llvm-ctxprof-util;llvm-cvtres;llvm-cxxdump;llvm-cxxfilt;llvm-cxxmap;llvm-debuginfo-analyzer;llvm-debuginfod-find;llvm-diff;llvm-dis;llvm-dlltool;llvm-dwarfdump;llvm-dwarfutil;llvm-dwp;llvm-exegesis;llvm-extract;llvm-gsymutil;llvm-ifs;llvm-install-name-tool;llvm-ir2vec;llvm-jitlink;llvm-jitlink-executor;llvm-lib;llvm-libtool-darwin;llvm-link;llvm-lipo;llvm-lto;llvm-lto2;llvm-mc;llvm-mca;llvm-ml;llvm-ml64;llvm-modextract;llvm-nm;llvm-objcopy;llvm-objdump;llvm-offload-wrapper;llvm-opt-report;llvm-otool;llvm-pdbutil;llvm-profdata;llvm-profgen;llvm-ranlib;llvm-rc;llvm-readelf;llvm-readobj;llvm-readtapi;llvm-reduce;llvm-remarkutil;llvm-rtdyld;llvm-sim;llvm-size;llvm-split;llvm-stress;llvm-strings;llvm-strip;llvm-symbolizer;llvm-tli-checker;llvm-undname;llvm-windres;llvm-xray;obj2yaml;opt;reduce-chunk-list;sancov;sanstats;split-file;verify-uselistorder;yaml2obj;opt-viewer;docs-dsymutil-man;docs-llvm-dwarfdump-man;docs-llvm-man;LLVMgold;llvm-mt; -DLLVM_TARGETS_TO_BUILD= -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AArch64;AMDGPU;ARC;ARM;AVR;BPF;CSKY;DirectX;Hexagon;Lanai;LoongArch;M68k;MSP430;Mips;NVPTX;PowerPC;RISCV;SPIRV;Sparc;SystemZ;VE;WebAssembly;X86;XCore;Xtensa -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_TESTS=ON -DLLVM_BUILD_TESTS=yes -DLLVM_INSTALL_GTEST=ON -DLLVM_ENABLE_FFI=yes -DLLVM_ENABLE_LIBEDIT=yes -DLLVM_ENABLE_LIBXML2=yes -DLLVM_ENABLE_ASSERTIONS=yes -DLLVM_ENABLE_LIBPFM=yes -DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_Z3_SOLVER=yes -DLLVM_ENABLE_ZLIB=FORCE_ON -DLLVM_ENABLE_ZSTD=FORCE_ON -DLLVM_ENABLE_CURL=no -DLLVM_ENABLE_HTTPLIB=no -DLLVM_HOST_TRIPLE=aarch64-unknown-linux-gnu -DPython3_EXECUTABLE=/usr/bin/python3.13 -DOCAMLFIND=NO -DLLVM_VERSION_SUFFIX=git4e30d783 -DLLVM_LIT_ARGS=-vv;-j;96 -DCMAKE_INSTALL_MANDIR=/usr/lib/llvm/22/share/man -DLLVM_INSTALL_SPHINX_HTML_DIR=/usr/share/doc/llvm-22.0.0.9999/html -DSPHINX_WARNINGS_AS_ERRORS=OFF -DLLVM_BUILD_DOCS=ON -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_SPHINX=ON -DLLVM_ENABLE_DOXYGEN=OFF -DLLVM_INSTALL_UTILS=ON -DLLVM_BINUTILS_INCDIR=/usr/include -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE=/var/tmp/portage/llvm-core/llvm-22.0.0.9999/work/llvm_build-.arm64/gentoo_toolchain.cmake /var/tmp/portage/llvm-core/llvm-22.0.0.9999/work/llvm

Clang with:

cmake -C /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/gentoo_common_config.cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DDEFAULT_SYSROOT= -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm/22 -DCMAKE_INSTALL_MANDIR=/usr/lib/llvm/22/share/man -DLLVM_ROOT=/usr/lib/llvm/22 -DCLANG_CONFIG_FILE_SYSTEM_DIR=/etc/clang/22 -DCLANG_CONFIG_FILE_USER_DIR=~/.config/clang -DCLANG_RESOURCE_DIR=../../../../lib/clang/22 -DBUILD_SHARED_LIBS=OFF -DCLANG_LINK_CLANG_DYLIB=ON -DLLVM_DISTRIBUTION_COMPONENTS=clang-cmake-exports;clang-headers;clang-resource-headers;libclang-headers;aarch64-resource-headers;arm-common-resource-headers;arm-resource-headers;core-resource-headers;cuda-resource-headers;hexagon-resource-headers;hip-resource-headers;hlsl-resource-headers;mips-resource-headers;opencl-resource-headers;openmp-resource-headers;ppc-htm-resource-headers;ppc-resource-headers;riscv-resource-headers;spirv-resource-headers;systemz-resource-headers;utility-resource-headers;ve-resource-headers;webassembly-resource-headers;windows-resource-headers;x86-resource-headers;clang-cpp;libclang;bash-autocomplete;libclang-python-bindings;c-index-test;clang;clang-format;clang-installapi;clang-linker-wrapper;clang-nvlink-wrapper;clang-offload-bundler;clang-offload-packager;clang-refactor;clang-repl;clang-scan-deps;clang-sycl-linker;diagtool;hmaptool;offload-arch;clang-tblgen;clang-apply-replacements;clang-change-namespace;clang-doc;clang-include-cleaner;clang-include-fixer;clang-move;clang-query;clang-reorder-fields;clang-tidy;clang-tidy-headers;clangd;find-all-symbols;modularize;pp-trace;docs-clang-man;docs-clang-tools-man;clang-check;clang-extdef-mapping;scan-build;scan-build-py;scan-view; -DCLANG_INCLUDE_TESTS=yes -DLLVM_TARGETS_TO_BUILD=AArch64;AMDGPU;ARC;ARM;AVR;BPF;CSKY;DirectX;Hexagon;Lanai;LoongArch;M68k;MSP430;Mips;NVPTX;PowerPC;RISCV;SPIRV;Sparc;SystemZ;VE;WebAssembly;X86;XCore;Xtensa -DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_RTTI=ON -DCLANG_DEFAULT_OPENMP_RUNTIME=libomp -DCLANG_DEFAULT_PIE_ON_LINUX=yes -DCLANG_ENABLE_LIBXML2=yes -DCLANG_ENABLE_ARCMT=yes -DCLANG_ENABLE_STATIC_ANALYZER=yes -DPython3_EXECUTABLE=/usr/bin/python3.13 -DPPC_LINUX_DEFAULT_IEEELONGDOUBLE=no -DLLVM_BUILD_TESTS=ON -DLLVM_LIT_ARGS=-vv;-j;96 -DLLVM_BUILD_DOCS=ON -DLLVM_ENABLE_SPHINX=ON -DCLANG_INSTALL_SPHINX_HTML_DIR=/usr/share/doc/clang-22.0.0.9999/html -DSPHINX_WARNINGS_AS_ERRORS=OFF -DCLANG-TOOLS_INSTALL_SPHINX_HTML_DIR=/usr/share/doc/clang-22.0.0.9999/tools-extra -DCLANG_INCLUDE_DOCS=ON -DLLVM_EXTERNAL_CLANG_TOOLS_EXTRA_SOURCE_DIR=/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang-tools-extra -DCLANG_TOOLS_EXTRA_INCLUDE_DOCS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE=/var/tmp/portage/llvm-core/clang-22.0.0.9999/work/x/y/clang-.arm64/gentoo_toolchain.cmake /var/tmp/portage/llvm-core/clang-22.0.0.9999/work/clang

Full logs:
llvm-core:llvm-22.0.0.9999:20250909-161615.log.gz
llvm-core:clang-22.0.0.9999:20250909-163351.log.gz

I'm currently verifying the commit prior to this to confirm. Then I can start trying to reproduce with a more regular build.

@Keenuts Keenuts restored the hlsl-semantics-1 branch September 9, 2025 17:11
@Keenuts Keenuts deleted the hlsl-semantics-1 branch September 9, 2025 17:11
Keenuts added a commit that referenced this pull request Sep 9, 2025
@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 9, 2025

Thanks! I'll try to repro and figure out the best solution to fix this, but in the meanting, rolling this back (#157718)

Keenuts added a commit that referenced this pull request Sep 9, 2025
Reverts #152537

Broke the build in some cases. Need to investigate more for a proper
solution.
@mgorny
Copy link
Member

mgorny commented Sep 9, 2025

Thanks!

@mgorny
Copy link
Member

mgorny commented Sep 9, 2025

And sorry, I won't be able to take a closer look at it today, as the devboxes are currently busy building new kernels.

llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Sep 9, 2025
Reverts llvm/llvm-project#152537

Broke the build in some cases. Need to investigate more for a proper
solution.
Keenuts added a commit to Keenuts/llvm-project that referenced this pull request Sep 10, 2025
HLSL semantics are split between system semantics with some
kind of spelling, and user semantics with no actual spelling.
Those have been documented as normal function attributes, but
they'd benefit from a custom section with a slightly different
handling.

This will allow llvm#152537 to land.
@Keenuts
Copy link
Contributor Author

Keenuts commented Sep 10, 2025

I was able to reproduce the build issue. Turns out we'd benefit from a different documentation generation for those. Will re-land once #157841 is merged.

Keenuts added a commit that referenced this pull request Sep 11, 2025
)

HLSL semantics are split between system semantics with some kind of
spelling, and user semantics with no actual spelling. Those have been
documented as normal function attributes, but they'd benefit from a
custom section with a slightly different handling.

This will allow #152537 to land.

Verified the resulting RST file, and only diff are around HLSL
semantics.

Rendered output: 
<img width="1064" height="1035" alt="Screenshot from 2025-09-10
14-05-08"
src="https://github.com/user-attachments/assets/554b70d6-2bf8-4131-b343-8f379babaca8"
/>
Keenuts added a commit that referenced this pull request Sep 11, 2025
Keenuts added a commit to Keenuts/llvm-project that referenced this pull request Sep 15, 2025
This commit adds the support for semantics annotations on structs, but
only for inputs. Due to the current semantics implemented, we cannot
test much more than nesting/shadowing.

Once user semantics are implemented, we'll be able to test arrays in
structs and more complex cases.

As-is, this commit has one weakness vs DXC: semantics type validation is
not looking at the inner-most type, but the outermost type:

```hlsl
struct Inner {
  uint tid;
};

Inner inner : SV_GroupID
```

This sample would fail today because `SV_GroupID` require the type to be
an integer. This works in DXC as the inner type is a integer.
Because GroupIndex is not correctly validated, I uses this semantic to
test the inheritance/shadowing. But this will need to be fixed in a
later commit.

Requires llvm#152537
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants