Merged to 7.0 in r339339.
On Thu, Aug 9, 2018 at 10:02 AM, David Chisnall via cfe-commits <cfe-commits@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits