When compiling the following code snippet (clang x86-64 -O3
)
std::array<int, 5> test() { std::array<int, 5> values {{0, 1, 2, 3, 4}}; return values; }
It produced the typical assembly that I would expect
test(): # @test() mov rax, rdi mov ecx, dword ptr [rip + .L__const.test().values+16] mov dword ptr [rdi + 16], ecx movups xmm0, xmmword ptr [rip + .L__const.test().values] movups xmmword ptr [rdi], xmm0 ret .L__const.test().values: .long 0 # 0x0 .long 1 # 0x1 .long 2 # 0x2 .long 3 # 0x3 .long 4 # 0x4
However for small arrays, it seems to have figured out a trick?
std::array<int, 3> test() { std::array<int, 3> values {{0, 1, 2}}; return values; }
This was the corresponding assembly
test(): # @test() movabs rax, 4294967296 mov edx, 2 ret
Where did that magic number (4294967296
) come from? Is that essentially a value that can be reinterpret_cast
back into an array of int
somehow?
A std::array<int, 3>
is 96 bits wide on your implementation. As such the ABI declares that it should be returned in RAX + the low 32 bits of RDX (aka EDX).
4294967296 is 232, in hex it is $1'0000'0000
. So the movabs
stores 0 in the low order 32 bits of RAX, and 1 in the high order bits of RAX. The mov
stores 2 in EDX (which is exactly what you wanted).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With