@@ -589,6 +589,36 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
589589 VariableName.str ());
590590}
591591
592+ static void createSPIRVLocationStore (IRBuilder<> &B, llvm::Module &M,
593+ llvm::Value *Source, unsigned Location,
594+ StringRef Name) {
595+ auto *GV = new llvm::GlobalVariable (
596+ M, Source->getType (), /* isConstant= */ false ,
597+ llvm::GlobalValue::ExternalLinkage,
598+ /* Initializer= */ nullptr , /* Name= */ Name, /* insertBefore= */ nullptr ,
599+ llvm::GlobalVariable::GeneralDynamicTLSModel,
600+ /* AddressSpace */ 8 , /* isExternallyInitialized= */ false );
601+ GV->setVisibility (llvm::GlobalValue::HiddenVisibility);
602+ addLocationDecoration (GV, Location);
603+ B.CreateStore (Source, GV);
604+ }
605+
606+ void CGHLSLRuntime::emitSPIRVUserSemanticStore (
607+ llvm::IRBuilder<> &B, llvm::Value *Source,
608+ HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
609+ Twine BaseName = Twine (Semantic->getAttrName ()->getName ());
610+ Twine VariableName = BaseName.concat (Twine (Index.value_or (0 )));
611+ unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
612+
613+ // DXC completely ignores the semantic/index pair. Location are assigned from
614+ // the first semantic to the last.
615+ llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType ());
616+ unsigned ElementCount = AT ? AT->getNumElements () : 1 ;
617+ SPIRVLastAssignedOutputSemanticLocation += ElementCount;
618+ createSPIRVLocationStore (B, CGM.getModule (), Source, Location,
619+ VariableName.str ());
620+ }
621+
592622llvm::Value *
593623CGHLSLRuntime::emitDXILUserSemanticLoad (llvm::IRBuilder<> &B, llvm::Type *Type,
594624 HLSLAppliedSemanticAttr *Semantic,
@@ -609,6 +639,23 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
609639 return Value;
610640}
611641
642+ void CGHLSLRuntime::emitDXILUserSemanticStore (llvm::IRBuilder<> &B,
643+ llvm::Value *Source,
644+ HLSLAppliedSemanticAttr *Semantic,
645+ std::optional<unsigned > Index) {
646+ // DXIL packing rules etc shall be handled here.
647+ // FIXME: generate proper sigpoint, index, col, row values.
648+ SmallVector<Value *> Args{B.getInt32 (4 ),
649+ B.getInt32 (0 ),
650+ B.getInt32 (0 ),
651+ B.getInt8 (0 ),
652+ llvm::PoisonValue::get (B.getInt32Ty ()),
653+ Source};
654+
655+ llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
656+ B.CreateIntrinsic (/* ReturnType=*/ CGM.VoidTy , IntrinsicID, Args, nullptr );
657+ }
658+
612659llvm::Value *CGHLSLRuntime::emitUserSemanticLoad (
613660 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
614661 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
@@ -621,6 +668,19 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
621668 llvm_unreachable (" Unsupported target for user-semantic load." );
622669}
623670
671+ void CGHLSLRuntime::emitUserSemanticStore (IRBuilder<> &B, llvm::Value *Source,
672+ const clang::DeclaratorDecl *Decl,
673+ HLSLAppliedSemanticAttr *Semantic,
674+ std::optional<unsigned > Index) {
675+ if (CGM.getTarget ().getTriple ().isSPIRV ())
676+ return emitSPIRVUserSemanticStore (B, Source, Semantic, Index);
677+
678+ if (CGM.getTarget ().getTriple ().isDXIL ())
679+ return emitDXILUserSemanticStore (B, Source, Semantic, Index);
680+
681+ llvm_unreachable (" Unsupported target for user-semantic load." );
682+ }
683+
624684llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad (
625685 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
626686 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned > Index) {
@@ -669,6 +729,34 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
669729 llvm_unreachable (" non-handled system semantic. FIXME." );
670730}
671731
732+ static void createSPIRVBuiltinStore (IRBuilder<> &B, llvm::Module &M,
733+ llvm::Value *Source, const Twine &Name,
734+ unsigned BuiltInID) {
735+ auto *GV = new llvm::GlobalVariable (
736+ M, Source->getType (), /* isConstant= */ false ,
737+ llvm::GlobalValue::ExternalLinkage,
738+ /* Initializer= */ nullptr , Name, /* insertBefore= */ nullptr ,
739+ llvm::GlobalVariable::GeneralDynamicTLSModel,
740+ /* AddressSpace */ 8 , /* isExternallyInitialized= */ false );
741+ addSPIRVBuiltinDecoration (GV, BuiltInID);
742+ GV->setVisibility (llvm::GlobalValue::HiddenVisibility);
743+ B.CreateStore (Source, GV);
744+ }
745+
746+ void CGHLSLRuntime::emitSystemSemanticStore (IRBuilder<> &B, llvm::Value *Source,
747+ const clang::DeclaratorDecl *Decl,
748+ HLSLAppliedSemanticAttr *Semantic,
749+ std::optional<unsigned > Index) {
750+
751+ std::string SemanticName = Semantic->getAttrName ()->getName ().upper ();
752+ if (SemanticName == " SV_POSITION" )
753+ createSPIRVBuiltinStore (B, CGM.getModule (), Source,
754+ Semantic->getAttrName ()->getName (),
755+ /* BuiltIn::Position */ 0 );
756+ else
757+ llvm_unreachable (" non-handled system semantic. FIXME." );
758+ }
759+
672760llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad (
673761 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
674762 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
@@ -679,6 +767,16 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
679767 return emitUserSemanticLoad (B, Type, Decl, Semantic, Index);
680768}
681769
770+ void CGHLSLRuntime::handleScalarSemanticStore (
771+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
772+ const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
773+ std::optional<unsigned > Index = Semantic->getSemanticIndex ();
774+ if (Semantic->getAttrName ()->getName ().starts_with_insensitive (" SV_" ))
775+ emitSystemSemanticStore (B, Source, Decl, Semantic, Index);
776+ else
777+ emitUserSemanticStore (B, Source, Decl, Semantic, Index);
778+ }
779+
682780std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
683781CGHLSLRuntime::handleStructSemanticLoad (
684782 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -705,6 +803,35 @@ CGHLSLRuntime::handleStructSemanticLoad(
705803 return std::make_pair (Aggregate, AttrBegin);
706804}
707805
806+ specific_attr_iterator<HLSLAppliedSemanticAttr>
807+ CGHLSLRuntime::handleStructSemanticStore (
808+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
809+ const clang::DeclaratorDecl *Decl,
810+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
811+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
812+
813+ const llvm::StructType *ST = cast<StructType>(Source->getType ());
814+
815+ const clang::RecordDecl *RD = nullptr ;
816+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
817+ RD = FD->getDeclaredReturnType ()->getAsRecordDecl ();
818+ else
819+ RD = Decl->getType ()->getAsRecordDecl ();
820+ assert (RD);
821+
822+ assert (std::distance (RD->field_begin (), RD->field_end ()) ==
823+ ST->getNumElements ());
824+
825+ auto FieldDecl = RD->field_begin ();
826+ for (unsigned I = 0 ; I < ST->getNumElements (); ++I) {
827+ llvm::Value *Extract = B.CreateExtractValue (Source, I);
828+ AttrBegin =
829+ handleSemanticStore (B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
830+ }
831+
832+ return AttrBegin;
833+ }
834+
708835std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
709836CGHLSLRuntime::handleSemanticLoad (
710837 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -721,6 +848,22 @@ CGHLSLRuntime::handleSemanticLoad(
721848 AttrBegin);
722849}
723850
851+ specific_attr_iterator<HLSLAppliedSemanticAttr>
852+ CGHLSLRuntime::handleSemanticStore (
853+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
854+ const clang::DeclaratorDecl *Decl,
855+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
856+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
857+ assert (AttrBegin != AttrEnd);
858+ if (Source->getType ()->isStructTy ())
859+ return handleStructSemanticStore (B, FD, Source, Decl, AttrBegin, AttrEnd);
860+
861+ HLSLAppliedSemanticAttr *Attr = *AttrBegin;
862+ ++AttrBegin;
863+ handleScalarSemanticStore (B, FD, Source, Decl, Attr);
864+ return AttrBegin;
865+ }
866+
724867void CGHLSLRuntime::emitEntryFunction (const FunctionDecl *FD,
725868 llvm::Function *Fn) {
726869 llvm::Module &M = CGM.getModule ();
@@ -752,20 +895,22 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
752895 OB.emplace_back (" convergencectrl" , bundleArgs);
753896 }
754897
755- // FIXME: support struct parameters where semantics are on members.
756- // See: https://github.com/llvm/llvm-project/issues/57874
898+ std::unordered_map< const DeclaratorDecl *, llvm::Value *> OutputSemantic;
899+
757900 unsigned SRetOffset = 0 ;
758901 for (const auto &Param : Fn->args ()) {
759902 if (Param.hasStructRetAttr ()) {
760- // FIXME: support output.
761- // See: https://github.com/llvm/llvm-project/issues/57874
762903 SRetOffset = 1 ;
763- Args.emplace_back (PoisonValue::get (Param.getType ()));
904+ llvm::Type *VarType = Param.getParamStructRetType ();
905+ llvm::Value *Var = B.CreateAlloca (VarType);
906+ OutputSemantic.emplace (FD, Var);
907+ Args.push_back (Var);
764908 continue ;
765909 }
766910
767911 const ParmVarDecl *PD = FD->getParamDecl (Param.getArgNo () - SRetOffset);
768912 llvm::Value *SemanticValue = nullptr ;
913+ // FIXME: support inout/out parameters for semantics.
769914 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
770915 PD->getAttr <HLSLParamModifierAttr>()) {
771916 llvm_unreachable (" Not handled yet" );
@@ -792,8 +937,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
792937
793938 CallInst *CI = B.CreateCall (FunctionCallee (Fn), Args, OB);
794939 CI->setCallingConv (Fn->getCallingConv ());
795- // FIXME: Handle codegen for return type semantics.
796- // See: https://github.com/llvm/llvm-project/issues/57875
940+
941+ if (Fn->getReturnType () != CGM.VoidTy )
942+ OutputSemantic.emplace (FD, CI);
943+
944+ for (auto &[Decl, Source] : OutputSemantic) {
945+ AllocaInst *AI = dyn_cast<AllocaInst>(Source);
946+ llvm::Value *SourceValue =
947+ AI ? B.CreateLoad (AI->getAllocatedType (), Source) : Source;
948+
949+ auto AttrBegin = Decl->specific_attr_begin <HLSLAppliedSemanticAttr>();
950+ auto AttrEnd = Decl->specific_attr_end <HLSLAppliedSemanticAttr>();
951+ handleSemanticStore (B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
952+ }
953+
797954 B.CreateRetVoid ();
798955
799956 // Add and identify root signature to function, if applicable
0 commit comments