Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 53 additions & 9 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3286,10 +3286,11 @@ bool SPIRVToLLVM::translate() {

for (unsigned I = 0, E = BM->getNumVariables(); I != E; ++I) {
auto *BV = BM->getVariable(I);
if (BV->getStorageClass() != StorageClassFunction)
transValue(BV, nullptr, nullptr);
else
if (BV->getName() == "llvm.global_ctors" ||
BV->getName() == "llvm.global_dtors")
transGlobalCtorDtors(BV);
else if (BV->getStorageClass() != StorageClassFunction)
transValue(BV, nullptr, nullptr);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

// Then translate all debug instructions.
Expand Down Expand Up @@ -3768,13 +3769,56 @@ bool SPIRVToLLVM::transDecoration(SPIRVValue *BV, Value *V) {
return true;
}

void SPIRVToLLVM::transGlobalCtorDtors(SPIRVVariable *BV) {
if (BV->getName() != "llvm.global_ctors" &&
BV->getName() != "llvm.global_dtors")
return;
/// When spirv is generated from LLVM IR with opaque pointer enabled and then
/// the spirv is translated to LLVM IR with typed pointer, function pointer is
/// casted to i8* type in GlobalVariable \p GV, which causes error in LLVM IR
/// verifier. E.g.
/// [1 x %0][%0 { i32 1, i8* bitcast (void ()* @ctor to i8*), i8* null }]
/// This function removes the cast so that LLVM IR is valid.
static GlobalVariable *mutateGlobalCtorDtors(GlobalVariable *GV) {
if (!GV->hasInitializer())
return GV;
auto *InitArr = cast<ConstantArray>(GV->getInitializer());
unsigned NumEltsInArr = InitArr->getType()->getNumElements();
if (NumEltsInArr == 0)
return GV;
auto *CS = cast<ConstantStruct>(InitArr->getAggregateElement(0u));
auto *Elt1 = CS->getAggregateElement(1);
if (!isa<ConstantExpr>(Elt1))
return GV;

auto *STy = CS->getType();
assert(STy->getNumElements() == 3 &&
"expect 3 fields in global variable element struct type");
auto *NewSTy = StructType::create(GV->getContext(),
{STy->getElementType(0),
Elt1->stripPointerCasts()->getType(),
STy->getElementType(2)},
STy->getName(), STy->isPacked());
auto *NewTy = ArrayType::get(NewSTy, NumEltsInArr);
SmallVector<Constant *, 4> ArrElts;
for (unsigned I = 0; I < NumEltsInArr; ++I) {
auto *CS = cast<ConstantStruct>(InitArr->getAggregateElement(I));
ArrElts.push_back(ConstantStruct::get(
NewSTy, {CS->getAggregateElement(0u),
CS->getAggregateElement(1)->stripPointerCasts(),
CS->getAggregateElement(2)}));
}
auto *NewInitializer = ConstantArray::get(NewTy, ArrElts);
auto *NewGV = new GlobalVariable(
*GV->getParent(), NewTy, GV->isConstant(), GV->getLinkage(),
NewInitializer, "", 0, GV->getThreadLocalMode(), GV->getAddressSpace(),
GV->isExternallyInitialized());
NewGV->copyAttributesFrom(GV);
NewGV->takeName(GV);
GV->eraseFromParent();
return NewGV;
}

Value *V = transValue(BV, nullptr, nullptr);
cast<GlobalValue>(V)->setLinkage(GlobalValue::AppendingLinkage);
void SPIRVToLLVM::transGlobalCtorDtors(SPIRVVariable *BV) {
GlobalVariable *V = cast<GlobalVariable>(transValue(BV, nullptr, nullptr));
V = mutateGlobalCtorDtors(V);
V->setLinkage(GlobalVariable::AppendingLinkage);
}

void SPIRVToLLVM::createCXXStructor(const char *ListName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
119734787 65792 393230 22 0
2 Capability Addresses
2 Capability Linkage
2 Capability Kernel
2 Capability Int64
2 Capability Int8
2 Capability FunctionPointersINTEL
8 Extension "SPV_INTEL_function_pointers"
5 ExtInstImport 1 "OpenCL.std"
3 MemoryModel 2 2
3 Source 0 0
7 Name 14 "asan.module_ctor"
7 Name 15 "asan.module_ctor"
7 Name 20 "llvm.global_ctors"

9 Decorate 20 LinkageAttributes "llvm.global_ctors" Export
4 TypeInt 3 32 0
4 TypeInt 4 8 0
4 TypeInt 6 64 0
5 Constant 6 7 1 0
4 Constant 3 10 1
4 TypePointer 5 7 4
5 TypeStruct 2 3 5 5

4 TypeArray 8 2 7
4 TypePointer 9 7 8
2 TypeVoid 11
3 TypeFunction 12 11
4 TypePointer 13 7 12
4 ConstantFunctionPointerINTEL 13 15 14
5 SpecConstantOp 5 16 124 15
3 ConstantNull 5 17
6 ConstantComposite 2 18 10 16 17

4 ConstantComposite 8 19 18

5 Variable 9 20 7 19



5 Function 11 14 0 12

2 Label 21
1 Return

1 FunctionEnd

; RUN: llvm-spirv %s --to-binary -o %t.spv
; RUN: llvm-spirv -r %t.spv -o %t.bc
; RUN: llvm-dis %t.bc -o %t.ll
; RUN: FileCheck --input-file=%t.ll %s --check-prefix=CHECK-LLVM

; CHECK-LLVM: [[TY:%.*]] = type { i32, void ()*, i8* }
; CHECK-LLVM: @llvm.global_ctors = appending global [1 x [[TY]]] [[[TY]] { i32 1, void ()* @asan.module_ctor, i8* null }]