Merged to release_80 in r354248.
On Fri, Feb 15, 2019 at 6:25 PM JF Bastien via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > Author: jfb > Date: Fri Feb 15 09:26:29 2019 > New Revision: 354147 > > URL: http://llvm.org/viewvc/llvm-project?rev=354147&view=rev > Log: > Variable auto-init of blocks capturing self after init bugfix > > Summary: > Blocks that capture themselves (and escape) after initialization currently > codegen wrong because this: > > bool capturedByInit = > Init && emission.IsEscapingByRef && isCapturedBy(D, Init); > > Address Loc = > capturedByInit ? emission.Addr : emission.getObjectAddress(*this); > > Already adjusts Loc from thr alloca to a GEP. This code: > > if (emission.IsEscapingByRef) > Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); > > Was trying to do the same adjustment, and a GEP on a GEP (returning an int) > triggers an assertion. > > <rdar://problem/47943027> > > Reviewers: ahatanak > > Subscribers: jkorous, dexonsmith, cfe-commits, rjmccall > > Tags: #clang > > Differential Revision: https://reviews.llvm.org/D58218 > > Modified: > cfe/trunk/lib/CodeGen/CGDecl.cpp > cfe/trunk/test/CodeGenCXX/trivial-auto-var-init.cpp > > Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=354147&r1=354146&r2=354147&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Feb 15 09:26:29 2019 > @@ -1620,8 +1620,9 @@ void CodeGenFunction::EmitAutoVarInit(co > bool capturedByInit = > Init && emission.IsEscapingByRef && isCapturedBy(D, Init); > > - Address Loc = > - capturedByInit ? emission.Addr : emission.getObjectAddress(*this); > + bool locIsByrefHeader = !capturedByInit; > + const Address Loc = > + locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; > > // Note: constexpr already initializes everything correctly. > LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = > @@ -1637,7 +1638,7 @@ void CodeGenFunction::EmitAutoVarInit(co > return; > > // Only initialize a __block's storage: we always initialize the header. > - if (emission.IsEscapingByRef) > + if (emission.IsEscapingByRef && !locIsByrefHeader) > Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); > > CharUnits Size = getContext().getTypeSizeInChars(type); > @@ -1744,10 +1745,9 @@ void CodeGenFunction::EmitAutoVarInit(co > } > > llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace()); > - if (Loc.getType() != BP) > - Loc = Builder.CreateBitCast(Loc, BP); > - > - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); > + emitStoresForConstant( > + CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP), > + isVolatile, Builder, constant); > } > > /// Emit an expression as an initializer for an object (variable, field, > etc.) > > Modified: cfe/trunk/test/CodeGenCXX/trivial-auto-var-init.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/trivial-auto-var-init.cpp?rev=354147&r1=354146&r2=354147&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/trivial-auto-var-init.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/trivial-auto-var-init.cpp Fri Feb 15 09:26:29 > 2019 > @@ -45,14 +45,35 @@ void test_block() { > // PATTERN: %captured1 = getelementptr inbounds > %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, > i32 0, i32 4 > // PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to > %struct.XYZ*), %struct.XYZ** %captured1, align 8 > // PATTERN: %call = call %struct.XYZ* @create( > +using Block = void (^)(); > +typedef struct XYZ { > + Block block; > +} * xyz_t; > void test_block_self_init() { > - using Block = void (^)(); > - typedef struct XYZ { > - Block block; > - } * xyz_t; > extern xyz_t create(Block block); > __block xyz_t captured = create(^() { > - (void)captured; > + used(captured); > + }); > +} > + > +// Capturing with escape after initialization is also an edge case. > +// > +// UNINIT-LABEL: test_block_captures_self_after_init( > +// ZERO-LABEL: test_block_captures_self_after_init( > +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, > %struct.__block_descriptor*, i8* }>, align 8 > +// ZERO: %captured1 = getelementptr inbounds > %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* > %captured, i32 0, i32 4 > +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 > +// ZERO: %call = call %struct.XYZ* @create( > +// PATTERN-LABEL: test_block_captures_self_after_init( > +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, > %struct.__block_descriptor*, i8* }>, align 8 > +// PATTERN: %captured1 = getelementptr inbounds > %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* > %captured, i32 0, i32 4 > +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to > %struct.XYZ*), %struct.XYZ** %captured1, align 8 > +// PATTERN: %call = call %struct.XYZ* @create( > +void test_block_captures_self_after_init() { > + extern xyz_t create(Block block); > + __block xyz_t captured; > + captured = create(^() { > + used(captured); > }); > } > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits