@@ -3691,6 +3691,45 @@ void SPIRVToLLVM::transGlobalCtorDtors(SPIRVVariable *BV) {
3691
3691
cast<GlobalValue>(V)->setLinkage (GlobalValue::AppendingLinkage);
3692
3692
}
3693
3693
3694
+ void SPIRVToLLVM::createCXXStructor (const char *ListName,
3695
+ SmallVectorImpl<Function *> &Funcs) {
3696
+ if (Funcs.empty ())
3697
+ return ;
3698
+
3699
+ // If the SPIR-V input contained a variable for the structor list and it
3700
+ // has already been translated, then don't interfere.
3701
+ if (M->getGlobalVariable (ListName))
3702
+ return ;
3703
+
3704
+ // Type of a structor entry: { i32, void ()*, i8* }
3705
+ Type *PriorityTy = Type::getInt32Ty (*Context);
3706
+ PointerType *CtorTy = PointerType::getUnqual (
3707
+ FunctionType::get (Type::getVoidTy (*Context), false ));
3708
+ PointerType *ComdatTy = Type::getInt8PtrTy (*Context);
3709
+ StructType *StructorTy = StructType::get (PriorityTy, CtorTy, ComdatTy);
3710
+
3711
+ ArrayType *ArrTy = ArrayType::get (StructorTy, Funcs.size ());
3712
+
3713
+ GlobalVariable *GV =
3714
+ cast<GlobalVariable>(M->getOrInsertGlobal (ListName, ArrTy));
3715
+ GV->setLinkage (GlobalValue::AppendingLinkage);
3716
+
3717
+ // Build the initializer.
3718
+ SmallVector<Constant *, 2 > ArrayElts;
3719
+ for (auto *F : Funcs) {
3720
+ SmallVector<Constant *, 3 > Elts;
3721
+ // SPIR-V does not specify an order between Initializers, so set default
3722
+ // priority.
3723
+ Elts.push_back (ConstantInt::get (PriorityTy, 65535 ));
3724
+ Elts.push_back (ConstantExpr::getBitCast (F, CtorTy));
3725
+ Elts.push_back (ConstantPointerNull::get (ComdatTy));
3726
+ ArrayElts.push_back (ConstantStruct::get (StructorTy, Elts));
3727
+ }
3728
+
3729
+ Constant *NewArray = ConstantArray::get (ArrTy, ArrayElts);
3730
+ GV->setInitializer (NewArray);
3731
+ }
3732
+
3694
3733
bool SPIRVToLLVM::transFPContractMetadata () {
3695
3734
bool ContractOff = false ;
3696
3735
for (unsigned I = 0 , E = BM->getNumFunctions (); I != E; ++I) {
@@ -3767,6 +3806,7 @@ static bool transKernelArgTypeMedataFromString(LLVMContext *Ctx,
3767
3806
}
3768
3807
3769
3808
bool SPIRVToLLVM::transMetadata () {
3809
+ SmallVector<Function *, 2 > CtorKernels;
3770
3810
for (unsigned I = 0 , E = BM->getNumFunctions (); I != E; ++I) {
3771
3811
SPIRVFunction *BF = BM->getFunction (I);
3772
3812
Function *F = static_cast <Function *>(getTranslatedValue (BF));
@@ -3798,6 +3838,10 @@ bool SPIRVToLLVM::transMetadata() {
3798
3838
ConstantInt::get (Type::getInt32Ty (*Context), 1 )));
3799
3839
F->setMetadata (kSPIR2MD ::VecTyHint, MDNode::get (*Context, MetadataVec));
3800
3840
}
3841
+ // Generate metadata for Initializer.
3842
+ if (BF->getExecutionMode (ExecutionModeInitializer)) {
3843
+ CtorKernels.push_back (F);
3844
+ }
3801
3845
// Generate metadata for intel_reqd_sub_group_size
3802
3846
if (auto *EM = BF->getExecutionMode (ExecutionModeSubgroupSize)) {
3803
3847
auto SizeMD = ConstantAsMetadata::get (getUInt32 (M, EM->getLiterals ()[0 ]));
@@ -3828,6 +3872,7 @@ bool SPIRVToLLVM::transMetadata() {
3828
3872
MemoryModelMD->addOperand (
3829
3873
getMDTwoInt (Context, static_cast <unsigned >(BM->getAddressingModel ()),
3830
3874
static_cast <unsigned >(BM->getMemoryModel ())));
3875
+ createCXXStructor (" llvm.global_ctors" , CtorKernels);
3831
3876
return true ;
3832
3877
}
3833
3878
0 commit comments