Author: Nathan Gauër
Date: 2025-11-19T14:51:46+01:00
New Revision: 2fc42c7163142d74e2e8ce5549f5d0142fccd89f

URL: 
https://github.com/llvm/llvm-project/commit/2fc42c7163142d74e2e8ce5549f5d0142fccd89f
DIFF: 
https://github.com/llvm/llvm-project/commit/2fc42c7163142d74e2e8ce5549f5d0142fccd89f.diff

LOG: [HLSL] Add initial support for output semantics (#168095)

This commits adds the first part of the output semantics. It only
considers return values (and sret), but does not handle `inout` or `out`
parameters yet.
Those missing bits will reuse the same code, but will require additional
testing & some fixups, so planning on adding them separately.

Added: 
    clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
    clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
    clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl
    clang/test/SemaHLSL/Semantics/missing-vs.hlsl

Modified: 
    clang/lib/CodeGen/CGHLSLRuntime.cpp
    clang/lib/CodeGen/CGHLSLRuntime.h
    clang/lib/Sema/SemaHLSL.cpp
    clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
    clang/test/CodeGenHLSL/sret_output.hlsl
    clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
    clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
    clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl
    clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl
    clang/test/SemaHLSL/Semantics/position.ps.hlsl
    clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
    clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
    clang/test/SemaHLSL/Semantics/position.vs.hlsl
    clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
    clang/test/SemaHLSL/num_threads.hlsl
    clang/test/SemaHLSL/shader_type_attr.hlsl
    llvm/include/llvm/IR/IntrinsicsDirectX.td

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp 
b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 208afff24d498..0371af417bdab 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -599,6 +599,36 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> 
&B, llvm::Type *Type,
                                  VariableName.str());
 }
 
+static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
+                                     llvm::Value *Source, unsigned Location,
+                                     StringRef Name) {
+  auto *GV = new llvm::GlobalVariable(
+      M, Source->getType(), /* isConstant= */ false,
+      llvm::GlobalValue::ExternalLinkage,
+      /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ 
nullptr,
+      llvm::GlobalVariable::GeneralDynamicTLSModel,
+      /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+  GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+  addLocationDecoration(GV, Location);
+  B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSPIRVUserSemanticStore(
+    llvm::IRBuilder<> &B, llvm::Value *Source,
+    HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
+  Twine BaseName = Twine(Semantic->getAttrName()->getName());
+  Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
+  unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
+
+  // DXC completely ignores the semantic/index pair. Location are assigned from
+  // the first semantic to the last.
+  llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
+  unsigned ElementCount = AT ? AT->getNumElements() : 1;
+  SPIRVLastAssignedOutputSemanticLocation += ElementCount;
+  createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
+                           VariableName.str());
+}
+
 llvm::Value *
 CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
                                         HLSLAppliedSemanticAttr *Semantic,
@@ -619,6 +649,23 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> 
&B, llvm::Type *Type,
   return Value;
 }
 
+void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
+                                              llvm::Value *Source,
+                                              HLSLAppliedSemanticAttr 
*Semantic,
+                                              std::optional<unsigned> Index) {
+  // DXIL packing rules etc shall be handled here.
+  // FIXME: generate proper sigpoint, index, col, row values.
+  SmallVector<Value *> Args{B.getInt32(4),
+                            B.getInt32(0),
+                            B.getInt32(0),
+                            B.getInt8(0),
+                            llvm::PoisonValue::get(B.getInt32Ty()),
+                            Source};
+
+  llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
+  B.CreateIntrinsic(/*ReturnType=*/CGM.VoidTy, IntrinsicID, Args, nullptr);
+}
+
 llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
     IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
     HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -631,6 +678,19 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
   llvm_unreachable("Unsupported target for user-semantic load.");
 }
 
+void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
+                                          const clang::DeclaratorDecl *Decl,
+                                          HLSLAppliedSemanticAttr *Semantic,
+                                          std::optional<unsigned> Index) {
+  if (CGM.getTarget().getTriple().isSPIRV())
+    return emitSPIRVUserSemanticStore(B, Source, Semantic, Index);
+
+  if (CGM.getTarget().getTriple().isDXIL())
+    return emitDXILUserSemanticStore(B, Source, Semantic, Index);
+
+  llvm_unreachable("Unsupported target for user-semantic load.");
+}
+
 llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
     IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
     HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -679,6 +739,34 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
   llvm_unreachable("non-handled system semantic. FIXME.");
 }
 
+static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
+                                    llvm::Value *Source, const Twine &Name,
+                                    unsigned BuiltInID) {
+  auto *GV = new llvm::GlobalVariable(
+      M, Source->getType(), /* isConstant= */ false,
+      llvm::GlobalValue::ExternalLinkage,
+      /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
+      llvm::GlobalVariable::GeneralDynamicTLSModel,
+      /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+  addSPIRVBuiltinDecoration(GV, BuiltInID);
+  GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+  B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value 
*Source,
+                                            const clang::DeclaratorDecl *Decl,
+                                            HLSLAppliedSemanticAttr *Semantic,
+                                            std::optional<unsigned> Index) {
+
+  std::string SemanticName = Semantic->getAttrName()->getName().upper();
+  if (SemanticName == "SV_POSITION")
+    createSPIRVBuiltinStore(B, CGM.getModule(), Source,
+                            Semantic->getAttrName()->getName(),
+                            /* BuiltIn::Position */ 0);
+  else
+    llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
 llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
     IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
     const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
@@ -689,6 +777,16 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
   return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
 }
 
+void CGHLSLRuntime::handleScalarSemanticStore(
+    IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+    const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
+  std::optional<unsigned> Index = Semantic->getSemanticIndex();
+  if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
+    emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
+  else
+    emitUserSemanticStore(B, Source, Decl, Semantic, Index);
+}
+
 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
 CGHLSLRuntime::handleStructSemanticLoad(
     IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -715,6 +813,35 @@ CGHLSLRuntime::handleStructSemanticLoad(
   return std::make_pair(Aggregate, AttrBegin);
 }
 
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleStructSemanticStore(
+    IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+    const clang::DeclaratorDecl *Decl,
+    specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+    specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+
+  const llvm::StructType *ST = cast<StructType>(Source->getType());
+
+  const clang::RecordDecl *RD = nullptr;
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+    RD = FD->getDeclaredReturnType()->getAsRecordDecl();
+  else
+    RD = Decl->getType()->getAsRecordDecl();
+  assert(RD);
+
+  assert(std::distance(RD->field_begin(), RD->field_end()) ==
+         ST->getNumElements());
+
+  auto FieldDecl = RD->field_begin();
+  for (unsigned I = 0; I < ST->getNumElements(); ++I) {
+    llvm::Value *Extract = B.CreateExtractValue(Source, I);
+    AttrBegin =
+        handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
+  }
+
+  return AttrBegin;
+}
+
 std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
 CGHLSLRuntime::handleSemanticLoad(
     IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -731,6 +858,22 @@ CGHLSLRuntime::handleSemanticLoad(
                         AttrBegin);
 }
 
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleSemanticStore(
+    IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+    const clang::DeclaratorDecl *Decl,
+    specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+    specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+  assert(AttrBegin != AttrEnd);
+  if (Source->getType()->isStructTy())
+    return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
+
+  HLSLAppliedSemanticAttr *Attr = *AttrBegin;
+  ++AttrBegin;
+  handleScalarSemanticStore(B, FD, Source, Decl, Attr);
+  return AttrBegin;
+}
+
 void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
                                       llvm::Function *Fn) {
   llvm::Module &M = CGM.getModule();
@@ -762,20 +905,22 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl 
*FD,
     OB.emplace_back("convergencectrl", bundleArgs);
   }
 
-  // FIXME: support struct parameters where semantics are on members.
-  // See: https://github.com/llvm/llvm-project/issues/57874
+  std::unordered_map<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
+
   unsigned SRetOffset = 0;
   for (const auto &Param : Fn->args()) {
     if (Param.hasStructRetAttr()) {
-      // FIXME: support output.
-      // See: https://github.com/llvm/llvm-project/issues/57874
       SRetOffset = 1;
-      Args.emplace_back(PoisonValue::get(Param.getType()));
+      llvm::Type *VarType = Param.getParamStructRetType();
+      llvm::Value *Var = B.CreateAlloca(VarType);
+      OutputSemantic.emplace(FD, Var);
+      Args.push_back(Var);
       continue;
     }
 
     const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
     llvm::Value *SemanticValue = nullptr;
+    // FIXME: support inout/out parameters for semantics.
     if ([[maybe_unused]] HLSLParamModifierAttr *MA =
             PD->getAttr<HLSLParamModifierAttr>()) {
       llvm_unreachable("Not handled yet");
@@ -802,8 +947,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl 
*FD,
 
   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
+
+  if (Fn->getReturnType() != CGM.VoidTy)
+    OutputSemantic.emplace(FD, CI);
+
+  for (auto &[Decl, Source] : OutputSemantic) {
+    AllocaInst *AI = dyn_cast<AllocaInst>(Source);
+    llvm::Value *SourceValue =
+        AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
+
+    auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
+    auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
+    handleSemanticStore(B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
+  }
+
   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 e6f3cc09819bd..c883282a8d9c8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -184,12 +184,22 @@ class CGHLSLRuntime {
                                       HLSLAppliedSemanticAttr *Semantic,
                                       std::optional<unsigned> Index);
 
+  void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+                               const clang::DeclaratorDecl *Decl,
+                               HLSLAppliedSemanticAttr *Semantic,
+                               std::optional<unsigned> Index);
+
   llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,
                                         const FunctionDecl *FD,
                                         llvm::Type *Type,
                                         const clang::DeclaratorDecl *Decl,
                                         HLSLAppliedSemanticAttr *Semantic);
 
+  void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+                                 llvm::Value *Source,
+                                 const clang::DeclaratorDecl *Decl,
+                                 HLSLAppliedSemanticAttr *Semantic);
+
   std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
   handleStructSemanticLoad(
       llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -197,12 +207,24 @@ class CGHLSLRuntime {
       specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
       specific_attr_iterator<HLSLAppliedSemanticAttr> end);
 
+  specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore(
+      llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+      const clang::DeclaratorDecl *Decl,
+      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
   std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
   handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,
                      llvm::Type *Type, const clang::DeclaratorDecl *Decl,
                      specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
                      specific_attr_iterator<HLSLAppliedSemanticAttr> end);
 
+  specific_attr_iterator<HLSLAppliedSemanticAttr>
+  handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+                      llvm::Value *Source, const clang::DeclaratorDecl *Decl,
+                      specific_attr_iterator<HLSLAppliedSemanticAttr> 
AttrBegin,
+                      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
 public:
   CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
   virtual ~CGHLSLRuntime() {}
@@ -266,10 +288,22 @@ class CGHLSLRuntime {
                                     HLSLAppliedSemanticAttr *Semantic,
                                     std::optional<unsigned> Index);
 
+  void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+                                  HLSLAppliedSemanticAttr *Semantic,
+                                  std::optional<unsigned> Index);
+  void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+                                 HLSLAppliedSemanticAttr *Semantic,
+                                 std::optional<unsigned> Index);
+  void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+                             const clang::DeclaratorDecl *Decl,
+                             HLSLAppliedSemanticAttr *Semantic,
+                             std::optional<unsigned> Index);
+
   llvm::Triple::ArchType getArch();
 
   llvm::DenseMap<const clang::RecordType *, llvm::StructType *> LayoutTypes;
   unsigned SPIRVLastAssignedInputSemanticLocation = 0;
+  unsigned SPIRVLastAssignedOutputSemanticLocation = 0;
 };
 
 } // namespace CodeGen

diff  --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5555916c2536f..e7ee3b1adf941 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -773,7 +773,7 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) {
 
 bool SemaHLSL::determineActiveSemanticOnScalar(
     FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D,
-    SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) {
+    SemanticInfo &ActiveSemantic, llvm::StringSet<> &UsedSemantics) {
   if (ActiveSemantic.Semantic == nullptr) {
     ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
     if (ActiveSemantic.Semantic)
@@ -805,7 +805,7 @@ bool SemaHLSL::determineActiveSemanticOnScalar(
   for (unsigned I = 0; I < ElementCount; ++I) {
     Twine VariableName = BaseName.concat(Twine(Location + I));
 
-    auto [_, Inserted] = ActiveInputSemantics.insert(VariableName.str());
+    auto [_, Inserted] = UsedSemantics.insert(VariableName.str());
     if (!Inserted) {
       Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)
           << VariableName.str();
@@ -816,26 +816,29 @@ bool SemaHLSL::determineActiveSemanticOnScalar(
   return true;
 }
 
-bool SemaHLSL::determineActiveSemantic(
-    FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D,
-    SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) {
+bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,
+                                       DeclaratorDecl *OutputDecl,
+                                       DeclaratorDecl *D,
+                                       SemanticInfo &ActiveSemantic,
+                                       llvm::StringSet<> &UsedSemantics) {
   if (ActiveSemantic.Semantic == nullptr) {
     ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();
     if (ActiveSemantic.Semantic)
       ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
   }
 
-  const Type *T = D->getType()->getUnqualifiedDesugaredType();
+  const Type *T = D == FD ? &*FD->getReturnType() : &*D->getType();
+  T = T->getUnqualifiedDesugaredType();
+
   const RecordType *RT = dyn_cast<RecordType>(T);
   if (!RT)
     return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
-                                           ActiveInputSemantics);
+                                           UsedSemantics);
 
   const RecordDecl *RD = RT->getDecl();
   for (FieldDecl *Field : RD->fields()) {
     SemanticInfo Info = ActiveSemantic;
-    if (!determineActiveSemantic(FD, OutputDecl, Field, Info,
-                                 ActiveInputSemantics)) {
+    if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics)) {
       Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;
       return false;
     }
@@ -915,13 +918,21 @@ 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,
                                  ActiveInputSemantics)) {
       Diag(Param->getLocation(), diag::note_previous_decl) << Param;
       FD->setInvalidDecl();
     }
   }
-  // FIXME: Verify return type semantic annotation.
+
+  SemanticInfo ActiveSemantic;
+  llvm::StringSet<> ActiveOutputSemantics;
+  ActiveSemantic.Semantic = FD->getAttr<HLSLParsedSemanticAttr>();
+  if (ActiveSemantic.Semantic)
+    ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+  if (!FD->getReturnType()->isVoidType())
+    determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics);
 }
 
 void SemaHLSL::checkSemanticAnnotation(

diff  --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl 
b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index 1bba87ea07141..be30e79438831 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -3,8 +3,9 @@
 // CHECK: @SV_Position = external hidden thread_local addrspace(7) 
externally_initialized constant <4 x float>, !spirv.Decorations !0
 
 // CHECK: define void @main() {{.*}} {
-float4 main(float4 p : SV_Position) {
+float4 main(float4 p : SV_Position) : A {
   // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 
16
   // CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> 
%[[#P]])
+  // CHECK:            store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 
16
   return p;
 }

diff  --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl 
b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
new file mode 100644
index 0000000000000..2f8dc97ef762e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK-VK,CHECK
+
+
+struct Input {
+  float Idx : SV_Position0;
+  float Gid : SV_Position1;
+};
+
+struct Output {
+  float a : A;
+  float b : B;
+};
+
+// Make sure SV_DispatchThreadID translated into dx.thread.id.
+
+// CHECK-DX: define hidden void @_Z3foo5Input(ptr dead_on_unwind noalias 
writable sret(%struct.Output) align 1 %agg.result, ptr noundef 
byval(%struct.Input) align 1 %input)
+// CHECK-VK: define hidden spir_func void @_Z3foo5Input(ptr dead_on_unwind 
noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef 
byval(%struct.Input) align 1 %input)
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, 
i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 
0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+// CHECK: %Gid = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, 
i32 1
+// CHECK: %[[#tmp:]] = load float, ptr %Gid, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 
0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output foo(Input input) {
+  Output o;
+  o.a = input.Idx;
+  o.b = input.Gid;
+  return o;
+}
+

diff  --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl 
b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
new file mode 100644
index 0000000000000..d75f4e0ca8338
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx
+
+struct S0 {
+  float4 position[2];
+  float4 color;
+};
+
+// CHECK-SPIRV-DAG:    @A0 = external hidden thread_local addrspace(7) 
externally_initialized constant <4 x float>, !spirv.Decorations 
![[#METADATA_0:]]
+
+[shader("pixel")]
+S0 main1(float4 input : A) : B {
+// CHECK:         %[[#ARG:]] = alloca %struct.S0, align 16
+// CHECK-SPIRV: %[[#INPUT:]] = load <4 x float>, ptr addrspace(7) @A0, align 16
+// CHECK-DXIL:           %A0 = call <4 x float> @llvm.dx.load.input.v4f32(i32 
4, i32 0, i32 0, i8 0, i32 poison)
+// CHECK-DXIL:                 call void @{{.*}}main1{{.*}}(ptr %[[#ARG]], <4 
x float> %A0)
+// CHECK-SPIRV:                call spir_func void @{{.*}}main1{{.*}}(ptr 
%[[#ARG]], <4 x float> %[[#INPUT]])
+
+  // CHECK:        %[[#ST:]] = load %struct.S0, ptr %[[#ARG]], align 16
+  // CHECK:       %[[#TMP:]] = extractvalue %struct.S0 %[[#ST]], 0
+  // CHECK-SPIRV:              store [2 x <4 x float>] %[[#TMP]], ptr 
addrspace(8) @B0, align 16
+  // CHECK-DXIL:               call void @llvm.dx.store.output.a2v4f32(i32 4, 
i32 0, i32 0, i8 0, i32 poison, [2 x <4 x float>] %[[#TMP]])
+  // CHECK:       %[[#TMP:]] = extractvalue %struct.S0 %[[#ST]], 1
+  // CHECK-SPIRV:              store <4 x float> %[[#TMP]], ptr addrspace(8) 
@B2, align 16
+  // CHECK-DXIL:               call void @llvm.dx.store.output.v4f32(i32 4, 
i32 0, i32 0, i8 0, i32 poison, <4 x float> %[[#TMP]])
+
+  S0 output;
+  output.position[0] = input;
+  output.position[1] = input;
+  output.color = input;
+  return output;
+}
+
+// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0}
+//                                            |      `- Location index
+//                                            `-> Decoration "Location"

diff  --git a/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl 
b/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl
new file mode 100644
index 0000000000000..0f2444d21724a
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.struct.output.hlsl
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK-DXIL,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-vertex -x hlsl -emit-llvm 
-finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK-SPIRV,CHECK
+
+
+struct Input {
+  // FIXME: change this once we have a valid system semantic as input for VS.
+  float Idx : B2;
+};
+
+struct Output {
+  float a : A4;
+  float b : A2;
+};
+
+// CHECK-SPIRV-DAG:    @B2 = external hidden thread_local addrspace(7) 
externally_initialized constant float, !spirv.Decorations ![[#METADATA_0:]]
+// CHECK-SPIRV-DAG:    @A4 = external hidden thread_local addrspace(8) global 
float, !spirv.Decorations ![[#METADATA_0:]]
+// CHECK-SPIRV-DAG:    @A2 = external hidden thread_local addrspace(8) global 
float, !spirv.Decorations ![[#METADATA_2:]]
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, 
i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 
0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+
+// CHECK: %Idx1 = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, 
i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx1, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 
0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output main(Input input) {
+  Output o;
+  o.a = input.Idx;
+  o.b = input.Idx;
+  return o;
+}
+
+// Code generated in the entrypoint wrapper:
+
+// CHECK: %[[#OUTPUT:]] = alloca %struct.Output, align 8
+
+// CHECK-SPIRV: call spir_func void @_Z4main5Input(ptr %[[#OUTPUT]], ptr 
%[[#]])
+// CHECK-DXIL:  call void @_Z4main5Input(ptr %[[#OUTPUT]], ptr %[[#]])
+
+// CHECK: %[[#TMP:]] = load %struct.Output, ptr %[[#OUTPUT]], align 4
+// CHECK: %[[#VAL:]] = extractvalue %struct.Output %[[#TMP]], 0
+// CHECK-SPIRV:        store float %[[#VAL]], ptr addrspace(8) @A4, align 4
+// CHECK-DXIL:         call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 
0, i8 0, i32 poison, float %[[#VAL]])
+// CHECK: %[[#VAL:]] = extractvalue %struct.Output %[[#TMP]], 1
+// CHECK-SPIRV:        store float %[[#VAL]], ptr addrspace(8) @A2, align 4
+// CHECK-DXIL:         call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 
0, i8 0, i32 poison, float %[[#VAL]])
+
+// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_2]] = !{![[#METADATA_3:]]}
+// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0}
+// CHECK-SPIRV-DAG: ![[#METADATA_3]] = !{i32 30, i32 1}
+//                                            |      `- Location index
+//                                            `-> Decoration "Location"

diff  --git a/clang/test/CodeGenHLSL/sret_output.hlsl 
b/clang/test/CodeGenHLSL/sret_output.hlsl
index eefc9dabab517..e1aa0973fe5db 100644
--- a/clang/test/CodeGenHLSL/sret_output.hlsl
+++ b/clang/test/CodeGenHLSL/sret_output.hlsl
@@ -1,21 +1,33 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple 
dxil-pc-shadermodel6.3-library %s  \
-// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s 
--check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple 
spirv-pc-vulkan-library %s  \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s 
--check-prefixes=CHECK-VK,CHECK
 
-// FIXME: add semantic to a.
-// See https://github.com/llvm/llvm-project/issues/57874
 struct S {
-  float a;
+  float a : A4;
 };
 
+// CHECK-VK: @A4 = external hidden thread_local addrspace(8) global float, 
!spirv.Decorations ![[#ATTR0:]]
 
 // Make sure sret parameter is generated.
-// CHECK:define internal void @_Z7ps_mainv(ptr dead_on_unwind noalias writable 
sret(%struct.S) align 1 %agg.result)
-// FIXME: change it to real value instead of poison value once semantic is add 
to a.
-// Make sure the function with sret is called.
-// CHECK:call void @_Z7ps_mainv(ptr poison)
-[shader("pixel")]
-S ps_main() {
+// CHECK-DX: define internal void @_Z7vs_mainv(ptr dead_on_unwind noalias 
writable sret(%struct.S) align 1 %agg.result)
+// CHECK-VK: define internal spir_func void @_Z7vs_mainv(ptr dead_on_unwind 
noalias writable sret(%struct.S) align 1 %agg.result)
+
+[shader("vertex")]
+S vs_main() {
   S s;
   s.a = 0;
   return s;
 };
+
+// CHECK: %[[#alloca:]] = alloca %struct.S, align 8
+// CHECK-DX:              call void @_Z7vs_mainv(ptr %[[#alloca]])
+// CHECK-VK:              call spir_func void @_Z7vs_mainv(ptr %[[#alloca]])
+// CHECK: %[[#a:]] = load %struct.S, ptr %[[#alloca]], align 4
+// CHECK: %[[#b:]] = extractvalue %struct.S %[[#a]], 0
+// CHECK-DX:         call void @llvm.dx.store.output.f32(i32 4, i32 0, i32 0, 
i8 0, i32 poison, float %[[#b]])
+// CHECK-VK:         store float %3, ptr addrspace(8) @A4, align 4
+// CHECK:            ret void
+
+// CHECK-VK: ![[#ATTR0]] = !{![[#ATTR1:]]}
+// CHECK-VK: ![[#ATTR1]] = !{i32 30, i32 0}

diff  --git a/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl 
b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
index 2f488a8d7c357..e5e399cf490ba 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl
@@ -37,7 +37,7 @@ __attribute__((availability(shadermodel, introduced = 6.0, 
environment = mesh)))
 unsigned f8();
 
 [numthreads(4,1,1)]
-int main() {
+void main() {
     // 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
@@ -63,6 +63,4 @@ int main() {
     unsigned G = f7(); // #f7_call
 
     unsigned H = f8();
-
-    return 0;
 }

diff  --git a/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl 
b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
index 07da116d403ce..eddba54d5ca9e 100644
--- a/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
+++ b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl
@@ -37,7 +37,7 @@ __attribute__((availability(shadermodel, introduced = 6.0, 
environment = mesh)))
 unsigned f8(); // #f8
 
 [numthreads(4,1,1)]
-int main() {
+void main() {
     // 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
@@ -63,6 +63,4 @@ int main() {
     // expected-error@#f8_call {{'f8' is only available in mesh environment on 
Shader Model 6.0 or newer}}
     // expected-note@#f8 {{'f8' has been marked as being introduced in Shader 
Model 6.0 in mesh environment here, but the deployment target is Shader Model 
5.0 mesh environment}}
     unsigned H = f8(); // #f8_call
-
-    return 0;
 }

diff  --git a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl 
b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl
index 7cd13e653ed5a..83c49738f8810 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() {
+int main() : A {
     // 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/Availability/avail-diag-default-compute.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
index b60fba62bdb00..1424fe63242ae 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl
@@ -107,7 +107,7 @@ class MyClass
 };
 
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);
@@ -115,5 +115,4 @@ float main() {
   float c = C.makeF();
   float d = test((float)1.0);
   float e = test((half)1.0);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
index 35b7c384f26cd..0c997d28ecdfc 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl
@@ -162,12 +162,12 @@ namespace A {
 // Shader entry point without body
 [shader("compute")]
 [numthreads(4,1,1)]
-float main();
+void main();
 
 // Shader entry point with body
 [shader("compute")]
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);
@@ -176,5 +176,4 @@ float main() {
   float d = test((float)1.0);
   float e = test((half)1.0);
   exportedFunctionUsed(1.0f);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
index 4068798383930..2474a8ae2e02a 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl
@@ -107,7 +107,7 @@ class MyClass
 };
 
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);
@@ -115,5 +115,4 @@ float main() {
   float c = C.makeF();
   float d = test((float)1.0);
   float e = test((half)1.0);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
index a23e91a546b16..e598bc99a4e6a 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl
@@ -144,12 +144,12 @@ export void exportedFunctionUsed(float f) {
 // Shader entry point without body
 [shader("compute")]
 [numthreads(4,1,1)]
-float main();
+void main();
 
 // Shader entry point with body
 [shader("compute")]
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);
@@ -158,5 +158,4 @@ float main() {
   float d = test((float)1.0);
   float e = test((half)1.0);
   exportedFunctionUsed(1.0f);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl
index c5d14c024d540..9cb9a32e11c73 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl
@@ -117,7 +117,7 @@ class MyClass
 };
 
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);
@@ -125,5 +125,4 @@ float main() {
   float c = C.makeF();
   float d = test((float)1.0);
   float e = test((half)1.0);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl 
b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl
index 0fffbc96dac19..3a7efc3af80a0 100644
--- a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl
+++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl
@@ -180,7 +180,7 @@ namespace A {
 
 [shader("compute")]
 [numthreads(4,1,1)]
-float main() {
+void main() {
   float f = 3;
   MyClass C = { 1.0f };
   float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
@@ -188,5 +188,4 @@ float main() {
   float d = test((float)1.0);
   float e = test((half)1.0);
   exportedFunctionUsed(1.0f);
-  return a * b * c;
 }

diff  --git a/clang/test/SemaHLSL/Semantics/missing-vs.hlsl 
b/clang/test/SemaHLSL/Semantics/missing-vs.hlsl
new file mode 100644
index 0000000000000..41be9c0ab730c
--- /dev/null
+++ b/clang/test/SemaHLSL/Semantics/missing-vs.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -emit-llvm 
-disable-llvm-passes -o - -hlsl-entry main %s -verify 
-verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-vertex -x hlsl -emit-llvm 
-disable-llvm-passes -o - -hlsl-entry main %s -verify 
-verify-ignore-unexpected=note
+
+float main(unsigned GI : A) {
+  // expected-error@-1 {{semantic annotations must be present for all 
parameters of an entry function or patch constant function}}
+}

diff  --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl 
b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
index 7adf2a51f01c8..2d02384821d90 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl
@@ -1,9 +1,13 @@
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl 
-finclude-default-header -o - %s -ast-dump | FileCheck %s
 
-// FIXME(Keenuts): add mandatory output semantic once those are implemented.
-float4 main(float4 a : SV_Position2) {
+// FIXME(Keenuts): change output semantic to something valid for pixels shaders
+float4 main(float4 a : SV_Position2) : A {
 // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 
'float4 (float4)'
-// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 
'float4':'vector<float, 4>'
+// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 used a 
'float4':'vector<float, 4>'
 // CHECK-NEXT:  HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:24> "SV_Position" 2
 // CHECK-NEXT:  HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:24> "SV_Position" 
2
+
+// CHECK:       HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <line:4:40> "A" 0
+// CHECK:       HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} <col:40> "A" 0
+  return a;
 }

diff  --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl 
b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
index 3186aadf19946..213a53e30155b 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl
@@ -5,14 +5,17 @@ struct S {
 // CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f0 
'float4':'vector<float, 4>'
 // CHECK-NEXT:  HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:15> "SV_Position" 0
   float4 f1 : SV_Position3;
-// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f1 
'float4':'vector<float, 4>'
+// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 referenced f1 
'float4':'vector<float, 4>'
 // 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) {
+float4 main(S s) : B {
 // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 
'float4 (S)'
-// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:15 s '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
+  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 f12ac4df0c450..d10c817d53af2 100644
--- a/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl
@@ -2,13 +2,13 @@
 
 struct A {
   float4 x : A;
-// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 x 
'float4':'vector<float, 4>'
+// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 referenced x 
'float4':'vector<float, 4>'
 // CHECK-NEXT:  HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:14> "A" 0
 };
 
 struct Top {
   A f0 : B;
-// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:5 f0 'A'
+// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:5 referenced f0 'A'
 // CHECK-NEXT:  HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} <col:10> "B" 0
   A f1 : C;
 // CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:5 f1 'A'
@@ -17,10 +17,13 @@ struct Top {
 
 
 // FIXME(Keenuts): add mandatory output semantic once those are implemented.
-float4 main(Top s : D) {
+float4 main(Top s : D) : F4 {
 // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 
'float4 (Top)'
-// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 s '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
+  return s.f0.x;
 }

diff  --git a/clang/test/SemaHLSL/Semantics/position.vs.hlsl 
b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
index 19f781fa3757c..9d0ff285ce055 100644
--- a/clang/test/SemaHLSL/Semantics/position.vs.hlsl
+++ b/clang/test/SemaHLSL/Semantics/position.vs.hlsl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl 
-finclude-default-header -o - %s -verify
 
 // expected-error@+1 {{attribute 'SV_Position' is unsupported in 'vertex' 
shaders, requires pixel}}
-float4 main(float4 a : SV_Position) {
+float4 main(float4 a : SV_Position) : A {
   return a;
 }

diff  --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl 
b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
index a5645d1400da7..e7cb59bea8cf5 100644
--- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
+++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl
@@ -3,8 +3,8 @@
 
 [shader("compute")]
 [numthreads(8,8,1)]
-unsigned foo() {
+void foo() {
     // expected-error@#site {{'WaveActiveCountBits' is only available on 
Shader Model 6.0 or newer}}
     // expected-note@hlsl/hlsl_alias_intrinsics.h:* {{'WaveActiveCountBits' 
has been marked as being introduced in Shader Model 6.0 here, but the 
deployment target is Shader Model 5.0}}
-    return hlsl::WaveActiveCountBits(1); // #site
+    unsigned tmp = hlsl::WaveActiveCountBits(1); // #site
 }

diff  --git a/clang/test/SemaHLSL/num_threads.hlsl 
b/clang/test/SemaHLSL/num_threads.hlsl
index 96200312bbf69..073f9bcfbe2ae 100644
--- a/clang/test/SemaHLSL/num_threads.hlsl
+++ b/clang/test/SemaHLSL/num_threads.hlsl
@@ -117,7 +117,7 @@ int largeZ();
 #else // Vertex and Pixel only beyond here
 // expected-error-re@+1 {{attribute 'numthreads' is unsupported in 
'{{[A-Za-z]+}}' shaders, requires one of the following: compute, amplification, 
mesh}}
 [numthreads(1,1,1)]
-int main() {
+int main() : A {
  return 1;
 }
 

diff  --git a/clang/test/SemaHLSL/shader_type_attr.hlsl 
b/clang/test/SemaHLSL/shader_type_attr.hlsl
index 52d3b1c9d012f..5f30a520b7255 100644
--- a/clang/test/SemaHLSL/shader_type_attr.hlsl
+++ b/clang/test/SemaHLSL/shader_type_attr.hlsl
@@ -31,18 +31,17 @@ static void oops() {}
 [shader("pixel")]
 // expected-note@+1 {{conflicting attribute is here}}
 [shader("vertex")]
-int doubledUp() {
+int doubledUp() : A {
   return 1;
 }
 
 // expected-note@+1 {{conflicting attribute is here}}
 [shader("vertex")]
-int forwardDecl();
+void forwardDecl();
 
 // expected-error@+1 {{'shader' attribute parameters do not match the previous 
declaration}}
 [shader("compute")][numthreads(8,1,1)]
-int forwardDecl() {
-  return 1;
+void forwardDecl() {
 }
 
 // expected-error@+1 {{'shader' attribute takes one argument}}
@@ -57,22 +56,20 @@ int forwardDecl() {
 [shader("library")]
 #endif // END of FAIL
 
-// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:62:2, col:18> Compute
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:61:2, col:18> Compute
 // CHECK:HLSLNumThreadsAttr 0x{{[0-9a-fA-F]+}} <col:21, col:37> 8 1 1
 [shader("compute")][numthreads(8,1,1)]
-int entry() {
-  return 1;
+void entry() {
 }
 
 // Because these two attributes match, they should both appear in the AST
 [shader("compute")][numthreads(8,1,1)]
-// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:68:2, col:18> Compute
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:66:2, col:18> Compute
 // CHECK:HLSLNumThreadsAttr 0x{{[0-9a-fA-F]+}} <col:21, col:37> 8 1 1
-int secondFn();
+void secondFn();
 
 [shader("compute")][numthreads(8,1,1)]
-// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:73:2, col:18> Compute
+// CHECK:HLSLShaderAttr 0x{{[0-9a-fA-F]+}} <line:71:2, col:18> Compute
 // CHECK:HLSLNumThreadsAttr 0x{{[0-9a-fA-F]+}} <col:21, col:37> 8 1 1
-int secondFn() {
-  return 1;
+void secondFn() {
 }

diff  --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td 
b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 5a4cc776b26a5..485a49b16e2d2 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -184,4 +184,10 @@ def int_dx_load_input
                             [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i8_ty,
                              llvm_i32_ty],
                             [IntrConvergent]>;
+
+def int_dx_store_output
+    : DefaultAttrsIntrinsic<[],
+                            [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i8_ty,
+                             llvm_i32_ty, llvm_any_ty],
+                            [IntrConvergent]>;
 }


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to