@@ -204,6 +204,7 @@ void CGHLSLRuntime::finishCodeGen() {
204204 addBufferResourceAnnotation (GV, RC, RK, /* IsROV=*/ false ,
205205 llvm::hlsl::ElementType::Invalid, Buf.Binding );
206206 }
207+ generateInitResBindingsFuncBody ();
207208}
208209
209210CGHLSLRuntime::Buffer::Buffer (const HLSLBufferDecl *D)
@@ -510,6 +511,10 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() {
510511 for (auto *Fn : CtorFns)
511512 B.CreateCall (FunctionCallee (Fn), {}, OB);
512513
514+ // Insert a call to initialize resource handles from bindings
515+ Function *ResInitFn = getOrCreateResourceBindingInitFn ();
516+ B.CreateCall (ResInitFn);
517+
513518 // Insert global dtors before the terminator of the last instruction
514519 B.SetInsertPoint (F.back ().getTerminator ());
515520 for (auto *Fn : DtorFns)
@@ -545,46 +550,80 @@ void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
545550 ResourcesToBind.emplace_back (VD, GV);
546551}
547552
548- bool CGHLSLRuntime::needsResourceBindingInitFn () {
549- return !ResourcesToBind.empty ();
553+ // Creates a declaration of _init_resource_bindings function. It will later be
554+ // populated with calls to initialize resource handles from bindings.
555+ llvm::Function *CGHLSLRuntime::getOrCreateResourceBindingInitFn () {
556+ if (InitResBindingsFunc == nullptr ) {
557+ InitResBindingsFunc =
558+ llvm::Function::Create (llvm::FunctionType::get (CGM.VoidTy , false ),
559+ llvm::GlobalValue::InternalLinkage,
560+ " _init_resource_bindings" , CGM.getModule ());
561+ }
562+ return InitResBindingsFunc;
563+ }
564+
565+ void CGHLSLRuntime::removeInitResBindingsFunc () {
566+ if (!InitResBindingsFunc)
567+ return ;
568+ while (InitResBindingsFunc->user_begin () != InitResBindingsFunc->user_end ()) {
569+ User *U = *InitResBindingsFunc->user_begin ();
570+ assert (isa<llvm::CallInst>(U));
571+ llvm::CallInst *CI = cast<llvm::CallInst>(U);
572+ CI->eraseFromParent ();
573+ }
574+ InitResBindingsFunc->eraseFromParent ();
575+ InitResBindingsFunc = nullptr ;
550576}
551577
552- llvm::Function *CGHLSLRuntime::createResourceBindingInitFn () {
553- // No resources to bind
554- assert (needsResourceBindingInitFn () && " no resources to bind" );
578+ // Populates the body of _init_resource_bindings function with calls to
579+ // initialize resource handles from bindings. If there are no resources to bind
580+ // it will remove the function and all of its calls.
581+ void CGHLSLRuntime::generateInitResBindingsFuncBody () {
582+ if (ResourcesToBind.empty ()) {
583+ removeInitResBindingsFunc ();
584+ return ;
585+ }
586+
587+ if (InitResBindingsFunc == nullptr ) {
588+ // FIXME: resource init function did not get created in shader entry point.
589+ // Is this a library or just a shader without an entry function?
590+ // llvm-project/llvm#119260
591+ return ;
592+ }
555593
556594 LLVMContext &Ctx = CGM.getLLVMContext ();
557595 llvm::Type *Int1Ty = llvm::Type::getInt1Ty (Ctx);
558596
559- llvm::Function *InitResBindingsFunc =
560- llvm::Function::Create (llvm::FunctionType::get (CGM.VoidTy , false ),
561- llvm::GlobalValue::InternalLinkage,
562- " _init_resource_bindings" , CGM.getModule ());
563-
564597 llvm::BasicBlock *EntryBB =
565598 llvm::BasicBlock::Create (Ctx, " entry" , InitResBindingsFunc);
566599 CGBuilderTy Builder (CGM, Ctx);
567600 const DataLayout &DL = CGM.getModule ().getDataLayout ();
568601 Builder.SetInsertPoint (EntryBB);
569602
570- for (const auto &[VD , GV] : ResourcesToBind) {
571- for (Attr *A : VD ->getAttrs ()) {
603+ for (const auto &[Decl , GV] : ResourcesToBind) {
604+ for (Attr *A : Decl ->getAttrs ()) {
572605 HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
573606 if (!RBA)
574607 continue ;
575608
576- const HLSLAttributedResourceType *AttrResType =
577- HLSLAttributedResourceType::findHandleTypeOnResource (
578- VD->getType ().getTypePtr ());
579-
580- // FIXME: Only simple declarations of resources are supported for now.
581- // Arrays of resources or resources in user defined classes are
582- // not implemented yet.
583- assert (AttrResType != nullptr &&
584- " Resource class must have a handle of HLSLAttributedResourceType" );
585-
586- llvm::Type *TargetTy =
587- CGM.getTargetCodeGenInfo ().getHLSLType (CGM, AttrResType);
609+ llvm::Type *TargetTy = nullptr ;
610+ if (const VarDecl *VD = dyn_cast<VarDecl>(Decl)) {
611+ const HLSLAttributedResourceType *AttrResType =
612+ HLSLAttributedResourceType::findHandleTypeOnResource (
613+ VD->getType ().getTypePtr ());
614+
615+ // FIXME: Only simple declarations of resources are supported for now.
616+ // Arrays of resources or resources in user defined classes are
617+ // not implemented yet.
618+ assert (
619+ AttrResType != nullptr &&
620+ " Resource class must have a handle of HLSLAttributedResourceType" );
621+
622+ TargetTy = CGM.getTargetCodeGenInfo ().getHLSLType (CGM, AttrResType);
623+ } else {
624+ assert (isa<HLSLBufferDecl>(Decl));
625+ llvm_unreachable (" CBuffer codegen is not supported yet" );
626+ }
588627 assert (TargetTy != nullptr &&
589628 " Failed to convert resource handle to target type" );
590629
@@ -599,7 +638,7 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() {
599638
600639 llvm::Value *CreateHandle = Builder.CreateIntrinsic (
601640 /* ReturnType=*/ TargetTy, getCreateHandleFromBindingIntrinsic (), Args,
602- nullptr , Twine (VD ->getName ()).concat (" _h" ));
641+ nullptr , Twine (Decl ->getName ()).concat (" _h" ));
603642
604643 llvm::Value *HandleRef =
605644 Builder.CreateStructGEP (GV->getValueType (), GV, 0 );
@@ -609,7 +648,6 @@ llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() {
609648 }
610649
611650 Builder.CreateRetVoid ();
612- return InitResBindingsFunc;
613651}
614652
615653llvm::Instruction *CGHLSLRuntime::getConvergenceToken (BasicBlock &BB) {
0 commit comments