diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 29db13706437..a7e79f713b68 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -551,6 +551,17 @@ static cir::CIRCallOpInterface emitCallLikeOp( extraFnAttrs); } +static RValue getRValueThroughMemory(mlir::Location loc, + CIRGenBuilderTy &builder, mlir::Value val, + Address addr) { + auto ip = builder.saveInsertionPoint(); + builder.setInsertionPointAfterValue(val); + builder.createStore(loc, val, addr); + builder.restoreInsertionPoint(ip); + auto load = builder.createLoad(loc, addr); + return RValue::get(load); +} + RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &CallInfo, const CIRGenCallee &Callee, ReturnValueSlot ReturnValue, @@ -889,6 +900,18 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &CallInfo, auto Results = theCall->getOpResults(); assert(Results.size() <= 1 && "multiple returns NYI"); assert(Results[0].getType() == RetCIRTy && "Bitcast support NYI"); + + mlir::Region *region = builder.getBlock()->getParent(); + if (region != theCall->getParentRegion()) { + Address DestPtr = ReturnValue.getValue(); + + if (!DestPtr.isValid()) + DestPtr = CreateMemTemp(RetTy, callLoc, "tmp.try.call.res"); + + return getRValueThroughMemory(callLoc, builder, Results[0], + DestPtr); + } + return RValue::get(Results[0]); } default: diff --git a/clang/test/CIR/CodeGen/try-catch-dtors.cpp b/clang/test/CIR/CodeGen/try-catch-dtors.cpp index 40c35434e17c..5cf0bf0a1a0b 100644 --- a/clang/test/CIR/CodeGen/try-catch-dtors.cpp +++ b/clang/test/CIR/CodeGen/try-catch-dtors.cpp @@ -308,3 +308,34 @@ void yo2(bool x) { // CIR: } catch [type #cir.all { // CIR: cir.catch_param -> !cir.ptr // CIR: }] + + +int foo() { return 42; } + +struct A { + ~A() {} +}; + +void bar() { + A a; + int b = foo(); +} + +// CIR-LABEL: @_Z3barv +// CIR: %[[V0:.*]] = cir.alloca !ty_A, !cir.ptr, ["a"] {alignment = 1 : i64} +// CIR: %[[V1:.*]] = cir.alloca !s32i, !cir.ptr, ["b", init] {alignment = 4 : i64} +// CIR: %[[V2:.*]] = cir.alloca !s32i, !cir.ptr, ["tmp.try.call.res"] {alignment = 4 : i64} +// CIR: cir.try synthetic cleanup { +// CIR: %[[V4:.*]] = cir.call exception @_Z3foov() : () -> !s32i cleanup { +// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR: cir.yield +// CIR: } +// CIR: cir.store %[[V4]], %[[V2]] : !s32i, !cir.ptr +// CIR: cir.yield +// CIR: } catch [#cir.unwind { +// CIR: cir.resume +// CIR: }] +// CIR: %[[V3:.*]] = cir.load %[[V2]] : !cir.ptr, !s32i +// CIR: cir.store %[[V3]], %[[V1]] : !s32i, !cir.ptr +// CIR: cir.call @_ZN1AD2Ev(%[[V0]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR: cir.return