Author: Akira Hatanaka Date: 2020-07-10T17:24:13-07:00 New Revision: e9bf0a710c993b932fa69c95ef6d0130fd721115
URL: https://github.com/llvm/llvm-project/commit/e9bf0a710c993b932fa69c95ef6d0130fd721115 DIFF: https://github.com/llvm/llvm-project/commit/e9bf0a710c993b932fa69c95ef6d0130fd721115.diff LOG: [CodeGen] Store the return value of the target function call to the thunk's return value slot directly when the return type is an aggregate instead of doing so via a temporary This fixes PR45997 (https://bugs.llvm.org/show_bug.cgi?id=45997), which is caused by a bug that has existed since we started passing and returning C++ structs with ObjC strong pointer members (see https://reviews.llvm.org/D44908) or structs annotated with trivial_abi directly. rdar://problem/63740936 Differential Revision: https://reviews.llvm.org/D82513 Added: Modified: clang/lib/CodeGen/CGCXXABI.cpp clang/lib/CodeGen/CGVTables.cpp clang/test/CodeGenCXX/trivial_abi.cpp clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 928fbaea8278..3d65c0ea805e 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -156,6 +156,7 @@ void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResultType) { + assert(!hasAggregateEvaluationKind(ResultType) && "cannot handle aggregates"); CGF.EmitReturnOfRValue(RV, ResultType); } diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 276993581117..65b3b0c5f53d 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -363,7 +363,8 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee, : FPT->getReturnType(); ReturnValueSlot Slot; if (!ResultType->isVoidType() && - CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) + (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect || + hasAggregateEvaluationKind(ResultType))) Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified(), /*IsUnused=*/false, /*IsExternallyDestructed=*/true); diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp index e7e7f840944d..cb9b9dfeb4bd 100644 --- a/clang/test/CodeGenCXX/trivial_abi.cpp +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -43,6 +43,31 @@ struct HasNonTrivial { NonTrivial m; }; +struct B0 { + virtual Small m0(); +}; + +struct B1 { + virtual Small m0(); +}; + +struct D0 : B0, B1 { + Small m0() override; +}; + +// CHECK-LABEL: define i64 @_ZThn8_N2D02m0Ev( +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[CALL:.*]] = tail call i64 @_ZN2D02m0Ev( +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* +// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[V3:.*]] = load i32*, i32** %[[COERCE_DIVE2]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V3]] to i64 +// CHECK: ret i64 %[[COERCE_VAL_PI]] + +Small D0::m0() { return {}; } + // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 diff --git a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm index 7a7781f68891..d19534f6922d 100644 --- a/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm +++ b/clang/test/CodeGenObjCXX/objc-struct-cxx-abi.mm @@ -178,3 +178,32 @@ void testParamContainsNonTrivial(ContainsNonTrivial a) { void testCallContainsNonTrivial(ContainsNonTrivial *a) { testParamContainsNonTrivial(*a); } + +namespace testThunk { + +// CHECK-LABEL: define i64 @_ZThn8_N9testThunk2D02m0Ev( +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8 +// CHECK: %[[CALL:.*]] = tail call i64 @_ZN9testThunk2D02m0Ev( +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i8* +// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[V3:.*]] = load i8*, i8** %[[COERCE_DIVE2]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V3]] to i64 +// CHECK: ret i64 %[[COERCE_VAL_PI]] + +struct B0 { + virtual Strong m0(); +}; + +struct B1 { + virtual Strong m0(); +}; + +struct D0 : B0, B1 { + Strong m0() override; +}; + +Strong D0::m0() { return {}; } + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits