From 71f420e2273678afc5b3f50bebc043913fbca916 Mon Sep 17 00:00:00 2001 From: gitoleg Date: Thu, 4 Jan 2024 18:46:18 +0300 Subject: [PATCH] [CIR][CIRGen] supports struct copy from function call result (#369) This PR fixes the next case ``` typedef struct { } A; A create() { A a; return a; } void foo() { A a; a = create(); } ``` i.e. when a struct is assigned to a function call result --- clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp | 27 ++++++++++++++++++------- clang/test/CIR/CodeGen/agg-copy.c | 13 ++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index 23fa5569eea2..755d16004a55 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -138,6 +138,9 @@ class AggExprEmitter : public StmtVisitor { enum ExprValueKind { EVK_RValue, EVK_NonRValue }; + /// Perform the final copy to DestPtr, if desired. + void buildFinalDestCopy(QualType type, RValue src); + /// Perform the final copy to DestPtr, if desired. SrcIsRValue is true if /// source comes from an RValue. void buildFinalDestCopy(QualType type, const LValue &src, @@ -331,6 +334,13 @@ void AggExprEmitter::buildAggLoadOfLValue(const Expr *E) { buildFinalDestCopy(E->getType(), LV); } +/// Perform the final copy to DestPtr, if desired. +void AggExprEmitter::buildFinalDestCopy(QualType type, RValue src) { + assert(src.isAggregate() && "value must be aggregate value!"); + LValue srcLV = CGF.makeAddrLValue(src.getAggregateAddress(), type); + buildFinalDestCopy(type, srcLV, EVK_RValue); +} + /// Perform the final copy to DestPtr, if desired. void AggExprEmitter::buildFinalDestCopy(QualType type, const LValue &src, ExprValueKind SrcValueKind) { @@ -342,11 +352,13 @@ void AggExprEmitter::buildFinalDestCopy(QualType type, const LValue &src, return; // Copy non-trivial C structs here. - if (Dest.isVolatile() || UnimplementedFeature::volatileTypes()) - llvm_unreachable("volatile is NYI"); + if (Dest.isVolatile()) + assert(!UnimplementedFeature::volatileTypes()); if (SrcValueKind == EVK_RValue) { - llvm_unreachable("rvalue is NYI"); + if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) { + llvm_unreachable("move assignment/move ctor for rvalue is NYI"); + } } else { if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) llvm_unreachable("non-trivial primitive copy is NYI"); @@ -808,7 +820,9 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) { RetAddr = Dest.getAddress(); } else { - llvm_unreachable("NYI"); + RetAddr = CGF.CreateMemTemp(RetTy, CGF.getLoc(E->getSourceRange()), + "tmp", &RetAddr); + assert(!UnimplementedFeature::shouldEmitLifetimeMarkers() && "NYI"); } RValue Src = @@ -819,14 +833,13 @@ void AggExprEmitter::withReturnValueSlot( return; assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); - llvm_unreachable("NYI"); - // TODO(cir): EmitFinalDestCopy(E->getType(), Src); + buildFinalDestCopy(E->getType(), Src); if (!RequiresDestruction) { // If there's no dtor to run, the copy was the last use of our temporary. // Since we're not guaranteed to be in an ExprWithCleanups, clean up // eagerly. - llvm_unreachable("NYI"); + assert(!UnimplementedFeature::shouldEmitLifetimeMarkers() && "NYI"); } } diff --git a/clang/test/CIR/CodeGen/agg-copy.c b/clang/test/CIR/CodeGen/agg-copy.c index e0846ee4b858..cbc1565dd7f2 100644 --- a/clang/test/CIR/CodeGen/agg-copy.c +++ b/clang/test/CIR/CodeGen/agg-copy.c @@ -59,4 +59,17 @@ A foo3(void) { // CHECK: cir.copy [[TMP2]] to [[TMP1]] : !cir.ptr void foo4(A* a1) { A a2 = *a1; +} + +A create() { A a; return a; } + +// CHECK: cir.func {{.*@foo5}} +// CHECK: [[TMP0]] = cir.alloca !ty_22A22, cir.ptr , +// CHECK: [[TMP1]] = cir.alloca !ty_22A22, cir.ptr , ["tmp"] {alignment = 4 : i64} +// CHECK: [[TMP2]] = cir.call @create() : () -> !ty_22A22 +// CHECK: cir.store [[TMP2]], [[TMP1]] : !ty_22A22, cir.ptr +// CHECK: cir.copy [[TMP1]] to [[TMP0]] : !cir.ptr +void foo5() { + A a; + a = create(); } \ No newline at end of file