summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorDavid Chisnall <csdavec@swan.ac.uk>2018-08-09 08:02:42 +0000
committerDavid Chisnall <csdavec@swan.ac.uk>2018-08-09 08:02:42 +0000
commitc5a458cc53bc0cba359abc49f2b1fcf8f940669c (patch)
treea636059057ded3d6262aae1300001ff5b1d8a2e0 /clang/lib/CodeGen
parent20526bf48310b6a8ff5b655582545d4b79a06c2d (diff)
downloadbcm5719-llvm-c5a458cc53bc0cba359abc49f2b1fcf8f940669c.tar.gz
bcm5719-llvm-c5a458cc53bc0cba359abc49f2b1fcf8f940669c.zip
Correctly initialise global blocks on Windows.
Summary: Windows does not allow globals to be initialised to point to globals in another DLL. Exported globals may be referenced only from code. Work around this by creating an initialiser that runs in early library initialisation and sets the isa pointer. Reviewers: rjmccall Reviewed By: rjmccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D50436 llvm-svn: 339317
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp28
1 files changed, 26 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 16436830b11..f8a7901dbf1 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1213,9 +1213,13 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
auto fields = builder.beginStruct();
bool IsOpenCL = CGM.getLangOpts().OpenCL;
+ bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
if (!IsOpenCL) {
// isa
- fields.add(CGM.getNSConcreteGlobalBlock());
+ if (IsWindows)
+ fields.addNullPointer(CGM.Int8PtrPtrTy);
+ else
+ fields.add(CGM.getNSConcreteGlobalBlock());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
@@ -1250,7 +1254,27 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
llvm::Constant *literal = fields.finishAndCreateGlobal(
"__block_literal_global", blockInfo.BlockAlign,
- /*constant*/ true, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+ /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
+
+ // Windows does not allow globals to be initialised to point to globals in
+ // different DLLs. Any such variables must run code to initialise them.
+ if (IsWindows) {
+ auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
+ {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",
+ &CGM.getModule());
+ llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
+ Init));
+ b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
+ b.CreateStructGEP(literal, 0), CGM.getPointerAlign().getQuantity());
+ b.CreateRetVoid();
+ // We can't use the normal LLVM global initialisation array, because we
+ // need to specify that this runs early in library initialisation.
+ auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
+ Init, ".block_isa_init_ptr");
+ InitVar->setSection(".CRT$XCLa");
+ CGM.addUsedGlobal(InitVar);
+ }
// Return a constant of the appropriately-casted type.
llvm::Type *RequiredType =
OpenPOWER on IntegriCloud