Skip to content

Commit

Permalink
[CIR][CIRGen] supports struct copy from function call result (#369)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitoleg authored Jan 4, 2024
1 parent 0562ffc commit 71f420e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
27 changes: 20 additions & 7 deletions clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {

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,
Expand Down Expand Up @@ -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) {
Expand All @@ -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");
Expand Down Expand Up @@ -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 =
Expand All @@ -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");
}
}

Expand Down
13 changes: 13 additions & 0 deletions clang/test/CIR/CodeGen/agg-copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,17 @@ A foo3(void) {
// CHECK: cir.copy [[TMP2]] to [[TMP1]] : !cir.ptr<!ty_22A22>
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 <!ty_22A22>,
// CHECK: [[TMP1]] = cir.alloca !ty_22A22, cir.ptr <!ty_22A22>, ["tmp"] {alignment = 4 : i64}
// CHECK: [[TMP2]] = cir.call @create() : () -> !ty_22A22
// CHECK: cir.store [[TMP2]], [[TMP1]] : !ty_22A22, cir.ptr <!ty_22A22>
// CHECK: cir.copy [[TMP1]] to [[TMP0]] : !cir.ptr<!ty_22A22>
void foo5() {
A a;
a = create();
}

0 comments on commit 71f420e

Please sign in to comment.