llvm / llvm/llvm-project

[CIR] Avoid illegal copies of return values

Open
#198,602 8 comments 0 reactions 0 assignees View on GitHub
ClangIR
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Because ABI calling convention lowering is deferred in CIR, we do not use `sret` parameters for functions that return a structure that can't be trivially copied. This might be OK except that we currently also generate a store to the `__retval` alloca and a reload from there to return the value. The following example shows this behavior:

```c++
struct S {
S();
S(const S&) = delete;
~S();
};

S foo();
S bar() {
return foo();
}
```
That compiles to the following CIR:

```
cir.func private @_Z3foov() -> !rec_S
cir.func dso_local @_Z3barb() -> !rec_S {
%0 = cir.alloca !rec_S, !cir.ptr, ["__retval"] {alignment = 1 : i64}
%1 = cir.call @_Z3foov() : () -> !rec_S
cir.store align(1) %1, %0 : !rec_S, !cir.ptr
%2 = cir.load %0 : !cir.ptr, !rec_S
cir.return %2 : !rec_S
}
```

We need to clean up the CIR generation to avoid such copies.

Note that this issue also concerns classes with non-trivial, but non deleted copy constructors.

While the store and reload shown in the example above will almost certainly be eliminated later in the compilation pipeline, the intent of this issue is to avoid having this semantically incorrect representation in any intermediate state.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.