[PATCH] D50436: Correctly initialise global blocks on Windows.

David Chisnall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 8 04:19:41 PDT 2018


theraven created this revision.
theraven added a reviewer: rjmccall.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rC Clang

https://reviews.llvm.org/D50436

Files:
  lib/CodeGen/CGBlocks.cpp
  test/CodeGen/global-blocks-win32.c


Index: test/CodeGen/global-blocks-win32.c
===================================================================
--- /dev/null
+++ 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: lib/CodeGen/CGBlocks.cpp
===================================================================
--- lib/CodeGen/CGBlocks.cpp
+++ 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.159683.patch
Type: text/x-patch
Size: 3230 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180808/276fb6e5/attachment.bin>


More information about the cfe-commits mailing list