@@ -599,6 +599,36 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
599599 VariableName.str ());
600600}
601601
602+ static void createSPIRVLocationStore (IRBuilder<> &B, llvm::Module &M,
603+ llvm::Value *Source, unsigned Location,
604+ StringRef Name) {
605+ auto *GV = new llvm::GlobalVariable (
606+ M, Source->getType (), /* isConstant= */ false ,
607+ llvm::GlobalValue::ExternalLinkage,
608+ /* Initializer= */ nullptr , /* Name= */ Name, /* insertBefore= */ nullptr ,
609+ llvm::GlobalVariable::GeneralDynamicTLSModel,
610+ /* AddressSpace */ 8 , /* isExternallyInitialized= */ false );
611+ GV->setVisibility (llvm::GlobalValue::HiddenVisibility);
612+ addLocationDecoration (GV, Location);
613+ B.CreateStore (Source, GV);
614+ }
615+
616+ void CGHLSLRuntime::emitSPIRVUserSemanticStore (
617+ llvm::IRBuilder<> &B, llvm::Value *Source,
618+ HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
619+ Twine BaseName = Twine (Semantic->getAttrName ()->getName ());
620+ Twine VariableName = BaseName.concat (Twine (Index.value_or (0 )));
621+ unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
622+
623+ // DXC completely ignores the semantic/index pair. Location are assigned from
624+ // the first semantic to the last.
625+ llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType ());
626+ unsigned ElementCount = AT ? AT->getNumElements () : 1 ;
627+ SPIRVLastAssignedOutputSemanticLocation += ElementCount;
628+ createSPIRVLocationStore (B, CGM.getModule (), Source, Location,
629+ VariableName.str ());
630+ }
631+
602632llvm::Value *
603633CGHLSLRuntime::emitDXILUserSemanticLoad (llvm::IRBuilder<> &B, llvm::Type *Type,
604634 HLSLAppliedSemanticAttr *Semantic,
@@ -619,6 +649,23 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
619649 return Value;
620650}
621651
652+ void CGHLSLRuntime::emitDXILUserSemanticStore (llvm::IRBuilder<> &B,
653+ llvm::Value *Source,
654+ HLSLAppliedSemanticAttr *Semantic,
655+ std::optional<unsigned > Index) {
656+ // DXIL packing rules etc shall be handled here.
657+ // FIXME: generate proper sigpoint, index, col, row values.
658+ SmallVector<Value *> Args{B.getInt32 (4 ),
659+ B.getInt32 (0 ),
660+ B.getInt32 (0 ),
661+ B.getInt8 (0 ),
662+ llvm::PoisonValue::get (B.getInt32Ty ()),
663+ Source};
664+
665+ llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
666+ B.CreateIntrinsic (/* ReturnType=*/ CGM.VoidTy , IntrinsicID, Args, nullptr );
667+ }
668+
622669llvm::Value *CGHLSLRuntime::emitUserSemanticLoad (
623670 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
624671 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
@@ -631,6 +678,19 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
631678 llvm_unreachable (" Unsupported target for user-semantic load." );
632679}
633680
681+ void CGHLSLRuntime::emitUserSemanticStore (IRBuilder<> &B, llvm::Value *Source,
682+ const clang::DeclaratorDecl *Decl,
683+ HLSLAppliedSemanticAttr *Semantic,
684+ std::optional<unsigned > Index) {
685+ if (CGM.getTarget ().getTriple ().isSPIRV ())
686+ return emitSPIRVUserSemanticStore (B, Source, Semantic, Index);
687+
688+ if (CGM.getTarget ().getTriple ().isDXIL ())
689+ return emitDXILUserSemanticStore (B, Source, Semantic, Index);
690+
691+ llvm_unreachable (" Unsupported target for user-semantic load." );
692+ }
693+
634694llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad (
635695 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
636696 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
@@ -679,6 +739,34 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
679739 llvm_unreachable (" non-handled system semantic. FIXME." );
680740}
681741
742+ static void createSPIRVBuiltinStore (IRBuilder<> &B, llvm::Module &M,
743+ llvm::Value *Source, const Twine &Name,
744+ unsigned BuiltInID) {
745+ auto *GV = new llvm::GlobalVariable (
746+ M, Source->getType (), /* isConstant= */ false ,
747+ llvm::GlobalValue::ExternalLinkage,
748+ /* Initializer= */ nullptr , Name, /* insertBefore= */ nullptr ,
749+ llvm::GlobalVariable::GeneralDynamicTLSModel,
750+ /* AddressSpace */ 8 , /* isExternallyInitialized= */ false );
751+ addSPIRVBuiltinDecoration (GV, BuiltInID);
752+ GV->setVisibility (llvm::GlobalValue::HiddenVisibility);
753+ B.CreateStore (Source, GV);
754+ }
755+
756+ void CGHLSLRuntime::emitSystemSemanticStore (IRBuilder<> &B, llvm::Value *Source,
757+ const clang::DeclaratorDecl *Decl,
758+ HLSLAppliedSemanticAttr *Semantic,
759+ std::optional<unsigned > Index) {
760+
761+ std::string SemanticName = Semantic->getAttrName ()->getName ().upper ();
762+ if (SemanticName == " SV_POSITION" )
763+ createSPIRVBuiltinStore (B, CGM.getModule (), Source,
764+ Semantic->getAttrName ()->getName (),
765+ /* BuiltIn::Position */ 0 );
766+ else
767+ llvm_unreachable (" non-handled system semantic. FIXME." );
768+ }
769+
682770llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad (
683771 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
684772 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
@@ -689,6 +777,16 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
689777 return emitUserSemanticLoad (B, Type, Decl, Semantic, Index);
690778}
691779
780+ void CGHLSLRuntime::handleScalarSemanticStore (
781+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
782+ const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
783+ std::optional<unsigned > Index = Semantic->getSemanticIndex ();
784+ if (Semantic->getAttrName ()->getName ().starts_with_insensitive (" SV_" ))
785+ emitSystemSemanticStore (B, Source, Decl, Semantic, Index);
786+ else
787+ emitUserSemanticStore (B, Source, Decl, Semantic, Index);
788+ }
789+
692790std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
693791CGHLSLRuntime::handleStructSemanticLoad (
694792 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -715,6 +813,35 @@ CGHLSLRuntime::handleStructSemanticLoad(
715813 return std::make_pair (Aggregate, AttrBegin);
716814}
717815
816+ specific_attr_iterator<HLSLAppliedSemanticAttr>
817+ CGHLSLRuntime::handleStructSemanticStore (
818+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
819+ const clang::DeclaratorDecl *Decl,
820+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
821+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
822+
823+ const llvm::StructType *ST = cast<StructType>(Source->getType ());
824+
825+ const clang::RecordDecl *RD = nullptr ;
826+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
827+ RD = FD->getDeclaredReturnType ()->getAsRecordDecl ();
828+ else
829+ RD = Decl->getType ()->getAsRecordDecl ();
830+ assert (RD);
831+
832+ assert (std::distance (RD->field_begin (), RD->field_end ()) ==
833+ ST->getNumElements ());
834+
835+ auto FieldDecl = RD->field_begin ();
836+ for (unsigned I = 0 ; I < ST->getNumElements (); ++I) {
837+ llvm::Value *Extract = B.CreateExtractValue (Source, I);
838+ AttrBegin =
839+ handleSemanticStore (B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
840+ }
841+
842+ return AttrBegin;
843+ }
844+
718845std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
719846CGHLSLRuntime::handleSemanticLoad (
720847 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -731,6 +858,22 @@ CGHLSLRuntime::handleSemanticLoad(
731858 AttrBegin);
732859}
733860
861+ specific_attr_iterator<HLSLAppliedSemanticAttr>
862+ CGHLSLRuntime::handleSemanticStore (
863+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
864+ const clang::DeclaratorDecl *Decl,
865+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
866+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
867+ assert (AttrBegin != AttrEnd);
868+ if (Source->getType ()->isStructTy ())
869+ return handleStructSemanticStore (B, FD, Source, Decl, AttrBegin, AttrEnd);
870+
871+ HLSLAppliedSemanticAttr *Attr = *AttrBegin;
872+ ++AttrBegin;
873+ handleScalarSemanticStore (B, FD, Source, Decl, Attr);
874+ return AttrBegin;
875+ }
876+
734877void CGHLSLRuntime::emitEntryFunction (const FunctionDecl *FD,
735878 llvm::Function *Fn) {
736879 llvm::Module &M = CGM.getModule ();
@@ -762,20 +905,22 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
762905 OB.emplace_back (" convergencectrl" , bundleArgs);
763906 }
764907
765- // FIXME: support struct parameters where semantics are on members.
766- // See: https://github.com/llvm/llvm-project/issues/57874
908+ std::unordered_map< const DeclaratorDecl *, llvm::Value *> OutputSemantic;
909+
767910 unsigned SRetOffset = 0 ;
768911 for (const auto &Param : Fn->args ()) {
769912 if (Param.hasStructRetAttr ()) {
770- // FIXME: support output.
771- // See: https://github.com/llvm/llvm-project/issues/57874
772913 SRetOffset = 1 ;
773- Args.emplace_back (PoisonValue::get (Param.getType ()));
914+ llvm::Type *VarType = Param.getParamStructRetType ();
915+ llvm::Value *Var = B.CreateAlloca (VarType);
916+ OutputSemantic.emplace (FD, Var);
917+ Args.push_back (Var);
774918 continue ;
775919 }
776920
777921 const ParmVarDecl *PD = FD->getParamDecl (Param.getArgNo () - SRetOffset);
778922 llvm::Value *SemanticValue = nullptr ;
923+ // FIXME: support inout/out parameters for semantics.
779924 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
780925 PD->getAttr <HLSLParamModifierAttr>()) {
781926 llvm_unreachable (" Not handled yet" );
@@ -802,8 +947,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
802947
803948 CallInst *CI = B.CreateCall (FunctionCallee (Fn), Args, OB);
804949 CI->setCallingConv (Fn->getCallingConv ());
805- // FIXME: Handle codegen for return type semantics.
806- // See: https://github.com/llvm/llvm-project/issues/57875
950+
951+ if (Fn->getReturnType () != CGM.VoidTy )
952+ OutputSemantic.emplace (FD, CI);
953+
954+ for (auto &[Decl, Source] : OutputSemantic) {
955+ AllocaInst *AI = dyn_cast<AllocaInst>(Source);
956+ llvm::Value *SourceValue =
957+ AI ? B.CreateLoad (AI->getAllocatedType (), Source) : Source;
958+
959+ auto AttrBegin = Decl->specific_attr_begin <HLSLAppliedSemanticAttr>();
960+ auto AttrEnd = Decl->specific_attr_end <HLSLAppliedSemanticAttr>();
961+ handleSemanticStore (B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
962+ }
963+
807964 B.CreateRetVoid ();
808965
809966 // Add and identify root signature to function, if applicable
0 commit comments