r339317 - Correctly initialise global blocks on Windows.

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 9 05:43:09 PDT 2018


Merged to 7.0 in r339339.

On Thu, Aug 9, 2018 at 10:02 AM, David Chisnall via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: theraven
> Date: Thu Aug  9 01:02:42 2018
> New Revision: 339317
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339317&view=rev
> Log:
> 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
>
> Added:
>     cfe/trunk/test/CodeGen/global-blocks-win32.c
> Modified:
>     cfe/trunk/lib/CodeGen/CGBlocks.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=339317&r1=339316&r2=339317&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Aug  9 01:02:42 2018
> @@ -1213,9 +1213,13 @@ static llvm::Constant *buildGlobalBlock(
>    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(
>
>    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 =
>
> Added: cfe/trunk/test/CodeGen/global-blocks-win32.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/global-blocks-win32.c?rev=339317&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGen/global-blocks-win32.c (added)
> +++ cfe/trunk/test/CodeGen/global-blocks-win32.c Thu Aug  9 01:02:42 2018
> @@ -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
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list