r354147 - Variable auto-init of blocks capturing self after init bugfix

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 18 01:33:00 PST 2019


Merged to release_80 in r354248.

On Fri, Feb 15, 2019 at 6:25 PM JF Bastien via cfe-commits
<cfe-commits at 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 at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list