[PATCH] D50436: Correctly initialise global blocks on Windows.
David Chisnall via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 9 01:03:27 PDT 2018
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339317: Correctly initialise global blocks on Windows. (authored by theraven, committed by ).
Herald added a subscriber: llvm-commits.
Repository:
rL LLVM
https://reviews.llvm.org/D50436
Files:
cfe/trunk/lib/CodeGen/CGBlocks.cpp
cfe/trunk/test/CodeGen/global-blocks-win32.c
Index: cfe/trunk/test/CodeGen/global-blocks-win32.c
===================================================================
--- cfe/trunk/test/CodeGen/global-blocks-win32.c
+++ cfe/trunk/test/CodeGen/global-blocks-win32.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fblocks -triple i386-pc-windows-msvc %s -emit-llvm -o - -fblocks | FileCheck %s
+
+
+int (^x)(void) = ^() { return 21; };
+
+
+// Check that the block literal is emitted with a null isa pointer
+// CHECK: @__block_literal_global = internal global { i8**, i32, i32, i8*, %struct.__block_descriptor* } { i8** null,
+
+// Check that _NSConcreteGlobalBlock has the correct dllimport specifier.
+// CHECK: @_NSConcreteGlobalBlock = external dllimport global i8*
+// Check that we create an initialiser pointer in the correct section (early library initialisation).
+// CHECK: @.block_isa_init_ptr = internal constant void ()* @.block_isa_init, section ".CRT$XCLa"
+
+// Check that we emit an initialiser for it.
+// CHECK: define internal void @.block_isa_init() {
+// CHECK: store i8** @_NSConcreteGlobalBlock, i8*** getelementptr inbounds ({ i8**, i32, i32, i8*, %struct.__block_descriptor* }, { i8**, i32, i32, i8*, %struct.__block_descriptor* }* @__block_literal_global, i32 0, i32 0), align 4
+
Index: cfe/trunk/lib/CodeGen/CGBlocks.cpp
===================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp
@@ -1213,9 +1213,13 @@
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 @@
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 =
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50436.159867.patch
Type: text/x-patch
Size: 3315 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180809/22a73963/attachment.bin>
More information about the llvm-commits
mailing list