[Xtensa][clang++] Struct types of equal or lesser size than a word are always returned on the stack
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
When compiling both C and C++ for Xtensa, small (<= word/4 bytes) struct types are always returned via invisible reference. This is irrespective of the C++ notions of when an invisible reference return are required.
This can be reproduced with a very simple sample like:
```c++
struct Test {
unsigned v_;
};
Test test() {
return {.v_=1};
}
```
Which results in:
```llvm
%struct.Test = type { i32 }
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
define dso_local void @_Z4testv(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.Test) align 4 initi
alizes((0, 4)) %0) local_unnamed_addr #0 {
store i32 1, ptr %0, align 4, !tbaa !2
ret void
}
```
and the assembly:
```
00000000 <_Z4testv>:
0: 004136 entry a1, 32
3: 180c movi.n a8, 1
5: 0289 s32i.n a8, a2, 0
7: f01d retw.n
```
---
This is a deviation from the ABI defined by the Xtensa ISA which reads (in section 10.1.5 *Return Values in AR Registers*):
> Values of four words or less are returned in registers. The callee places the return value in registers beginning with AR[2] and continuing up to (and including) AR[5], depending on the size of the value. [...] Values larger than four words are returned by invisible reference. The caller passes a pointer as an invisible first argument and the callee stores the return value in the memory referenced by the pointer.
Notably, this is **not consistent** with other structure handling with clang.
A struct with size greater than a word (even by a single byte) and less than or equal to 4 words does correctly follow the ABI.
This breaks compatibility with, e.g., GCC-compiled code (which respects this ABI), and is a minor(?) pessimization.
As an (not incredibly necessary, but somewhat amusing) illustration:
```c++
#include
template
auto test() {
std::array ret;
ret.fill(0);
return ret;
}
template auto test<4>();
template auto test<5>();
```
produces quite different code:
```
00000000 <_Z4testILj4EEDav>:
0: 004136 entry a1, 32
3: 080c movi.n a8, 0
5: 034282 s8i a8, a2, 3
8: 024282 s8i a8, a2, 2
b: 014282 s8i a8, a2, 1
e: 004282 s8i a8, a2, 0
11: f01d retw.n
00000000 <_Z4testILj5EEDav>:
0: 004136 entry a1, 32
3: 020c movi.n a2, 0
5: 023d mov.n a3, a2
7: f01d retw.n
```
Contributor guide
Research direction
Start by reproducing the issue with clang++ for an Xtensa target using the small Test struct and the std::array examples, then compare the LLVM IR and assembly with the quoted Xtensa ABI rules. Done means C and C++ structs of four words or fewer are returned in AR[2]–AR[5], while larger values still use an invisible reference, preserving GCC compatibility.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100