Author: ahatanak Date: Fri Oct 19 22:45:01 2018 New Revision: 344833 URL: http://llvm.org/viewvc/llvm-project?rev=344833&view=rev Log: [CodeGen] Use the mangle context owned by CodeGenModule to correctly mangle types of lambda objects captured by a block instead of creating a new mangle context everytime a captured field type is mangled.
This fixes a bug in IRGen's block helper merging code that was introduced in r339438 where two blocks capturing two distinct lambdas would end up sharing helper functions and the block descriptor. This happened because the ID number used to distinguish lambdas defined in the same context is reset everytime a mangled context is created. rdar://problem/45314494 Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=344833&r1=344832&r2=344833&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Oct 19 22:45:01 2018 @@ -1817,8 +1817,6 @@ static std::string getBlockCaptureStr(co CodeGenModule &CGM) { std::string Str; ASTContext &Ctx = CGM.getContext(); - std::unique_ptr<ItaniumMangleContext> MC( - ItaniumMangleContext::create(Ctx, Ctx.getDiagnostics())); const BlockDecl::Capture &CI = *E.CI; QualType CaptureTy = CI.getVariable()->getType(); @@ -1844,7 +1842,7 @@ static std::string getBlockCaptureStr(co Str += "c"; SmallString<256> TyStr; llvm::raw_svector_ostream Out(TyStr); - MC->mangleTypeName(CaptureTy, Out); + CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out); Str += llvm::to_string(TyStr.size()) + TyStr.c_str(); break; } Modified: cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm?rev=344833&r1=344832&r2=344833&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm (original) +++ cfe/trunk/test/CodeGenObjCXX/lambda-to-block.mm Fri Oct 19 22:45:01 2018 @@ -3,16 +3,74 @@ // rdar://31385153 // Shouldn't crash! +// CHECK: %[[STRUCT_COPYABLE:.*]] = type { i8 } +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } +// CHECK: %[[CLASS_ANON:.*]] = type { %[[STRUCT_COPYABLE]] } +// CHECK: %[[CLASS_ANON_0:.*]] = type { %[[STRUCT_COPYABLE]] } +// CHECK: %[[CLASS_ANON_1:.*]] = type { %[[STRUCT_COPYABLE]] } +// CHECK: %[[CLASS_ANON_2:.*]] = type { %[[STRUCT_COPYABLE]] } + +// CHECK: @[[BLOCK_DESC0:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER0:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8 +// CHECK: @[[BLOCK_DESC1:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER1:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8 +// CHECK: @[[BLOCK_DESC2:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER2:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8 +// CHECK: @[[BLOCK_DESC3:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 33, i8* bitcast (void (i8*, i8*)* @[[COPY_HELPER3:.*__copy_helper_block_.*]] to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block{{.*}} to i8*), {{.*}}}, align 8 + +// CHECK: define void @_Z9hasLambda8Copyable( +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>, align 8 +// CHECK: %[[BLOCK1:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>, align 8 +// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON]] }>* %[[BLOCK]], i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC0]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8 +// CHECK: %[[BLOCK_DESCRIPTOR6:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_0]] }>* %[[BLOCK1]], i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC1]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR6]], align 8 + void takesBlock(void (^)(void)); struct Copyable { Copyable(const Copyable &x); }; +// Check that each block has its block descriptor and helper function. + void hasLambda(Copyable x) { takesBlock([x] () { }); + takesBlock([x] () { }); } -// CHECK-LABEL: define internal void @"__copy_helper_block_ +// CHECK: define internal void @[[COPY_HELPER0]] // CHECK: call void @"_ZZ9hasLambda8CopyableEN3$_0C1ERKS0_" +// CHECK: define internal void @[[COPY_HELPER1]] + +// CHECK: define void @_Z17testHelperMerging8Copyable( +// CHECK: %[[CALL:.*]] = call void ()* @[[CONV_FUNC0:.*]](%[[CLASS_ANON_1]]* +// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL]]) +// CHECK: %[[CALL1:.*]] = call void ()* @[[CONV_FUNC0]](%[[CLASS_ANON_1]]* +// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL1]]) +// CHECK: %[[CALL2:.*]] = call void ()* @[[CONV_FUNC1:.*]](%[[CLASS_ANON_2]]* +// CHECK: call void @_Z10takesBlockU13block_pointerFvvE(void ()* %[[CALL2]]) + +// CHECK: define internal void ()* @[[CONV_FUNC0]]( +// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_1]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_1]] }>* %{{.*}}, i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC2]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8 + +// CHECK: define internal void ()* @[[CONV_FUNC1]]( +// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_2]] }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, %[[CLASS_ANON_2]] }>* %{{.*}}, i32 0, i32 4 +// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESC3]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8 + // CHECK-LABEL: define internal void @"_ZZ9hasLambda8CopyableEN3$_0C2ERKS0_" // CHECK: call void @_ZN8CopyableC1ERKS_ + +// CHECK: define internal void @[[COPY_HELPER2]] +// CHECK: define internal void @[[COPY_HELPER3]] + +void testHelperMerging(Copyable x) { + auto lambda0 = [x]{}; + auto lambda1 = [x]{}; + takesBlock(lambda0); + + // This block has the same helper functions and a descriptor as the block + // created above. + takesBlock(lambda0); + + // This block has different helper functions and a descriptor as the blocks + // created above. + takesBlock(lambda1); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits