Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect handling of pointer to return value in ARM64EC entry thunks #90229

Closed
julliard opened this issue Apr 26, 2024 · 2 comments · Fixed by #92326
Closed

Incorrect handling of pointer to return value in ARM64EC entry thunks #90229

julliard opened this issue Apr 26, 2024 · 2 comments · Fixed by #92326
Labels
ABI Application Binary Interface backend:AArch64

Comments

@julliard
Copy link

When a function returns a structure that doesn't fit in a register, a pointer to the storage for the return value is passed as hidden parameter. On x86-64 this takes the place of the first parameter (%rcx) but on aarch64 this uses the x8 register.

This means that ARM64EC entry thunks need to shuffle registers to move x0 -> x8, x1 -> x0, etc. Here's a test case:

#include <stdint.h>

struct s { intptr_t a, b, c; };

struct s func( struct s a )
{
    struct s ret = { a.a + 1, a.b + 2, a.c + 3 };
    return ret;
}

The corresponding entry thunk generated by LLVM doesn't convert anything:

0000000000000000 <.wowthk$aa>:
       0: adba9fe6     	stp	q6, q7, [sp, #-0xb0]!
       4: ad0127e8     	stp	q8, q9, [sp, #0x20]
       8: ad022fea     	stp	q10, q11, [sp, #0x40]
       c: ad0337ec     	stp	q12, q13, [sp, #0x60]
      10: ad043fee     	stp	q14, q15, [sp, #0x80]
      14: a90a7bfd     	stp	x29, x30, [sp, #0xa0]
      18: 910283fd     	add	x29, sp, #0xa0
      1c: d63f0120     	blr	x9
      20: 90000008     	adrp	x8, 0x0 <.wowthk$aa>
      24: f9400100     	ldr	x0, [x8]
      28: a94a7bfd     	ldp	x29, x30, [sp, #0xa0]
      2c: ad443fee     	ldp	q14, q15, [sp, #0x80]
      30: ad4337ec     	ldp	q12, q13, [sp, #0x60]
      34: ad422fea     	ldp	q10, q11, [sp, #0x40]
      38: ad4127e8     	ldp	q8, q9, [sp, #0x20]
      3c: acc59fe6     	ldp	q6, q7, [sp], #0xb0
      40: d61f0000     	br	x0

While MSVC generates code to shuffle registers:

0000000000000000 <.wowthk$aa>:
       0: d503237f     	pacibsp
       4: f8150ff3     	str	x19, [sp, #-0xb0]!
       8: ad009fe6     	stp	q6, q7, [sp, #0x10]
       c: ad01a7e8     	stp	q8, q9, [sp, #0x30]
      10: ad02afea     	stp	q10, q11, [sp, #0x50]
      14: ad03b7ec     	stp	q12, q13, [sp, #0x70]
      18: ad04bfee     	stp	q14, q15, [sp, #0x90]
      1c: a9bf7bfd     	stp	x29, x30, [sp, #-0x10]!
      20: 910003fd     	mov	x29, sp
      24: aa0003f3     	mov	x19, x0
      28: aa0103e0     	mov	x0, x1
      2c: aa1303e8     	mov	x8, x19
      30: d63f0120     	blr	x9
      34: aa1303e8     	mov	x8, x19
      38: a8c17bfd     	ldp	x29, x30, [sp], #0x10
      3c: ad44bfee     	ldp	q14, q15, [sp, #0x90]
      40: ad43b7ec     	ldp	q12, q13, [sp, #0x70]
      44: ad42afea     	ldp	q10, q11, [sp, #0x50]
      48: ad41a7e8     	ldp	q8, q9, [sp, #0x30]
      4c: ad409fe6     	ldp	q6, q7, [sp, #0x10]
      50: f84b07f3     	ldr	x19, [sp], #0xb0
      54: d50323ff     	autibsp
      58: 90000010     	adrp	x16, 0x0 <.wowthk$aa>
      5c: f9400210     	ldr	x16, [x16]
      60: d61f0200     	br	x16
@EugeneZelenko EugeneZelenko added backend:AArch64 ABI Application Binary Interface and removed new issue labels Apr 26, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 26, 2024

@llvm/issue-subscribers-backend-aarch64

Author: Alexandre Julliard (julliard)

When a function returns a structure that doesn't fit in a register, a pointer to the storage for the return value is passed as hidden parameter. On x86-64 this takes the place of the first parameter (%rcx) but on aarch64 this uses the x8 register.

This means that ARM64EC entry thunks need to shuffle registers to move x0 -> x8, x1 -> x0, etc. Here's a test case:

#include &lt;stdint.h&gt;

struct s { intptr_t a, b, c; };

struct s func( struct s a )
{
    struct s ret = { a.a + 1, a.b + 2, a.c + 3 };
    return ret;
}

The corresponding entry thunk generated by LLVM doesn't convert anything:

0000000000000000 &lt;.wowthk$aa&gt;:
       0: adba9fe6     	stp	q6, q7, [sp, #-0xb0]!
       4: ad0127e8     	stp	q8, q9, [sp, #<!-- -->0x20]
       8: ad022fea     	stp	q10, q11, [sp, #<!-- -->0x40]
       c: ad0337ec     	stp	q12, q13, [sp, #<!-- -->0x60]
      10: ad043fee     	stp	q14, q15, [sp, #<!-- -->0x80]
      14: a90a7bfd     	stp	x29, x30, [sp, #<!-- -->0xa0]
      18: 910283fd     	add	x29, sp, #<!-- -->0xa0
      1c: d63f0120     	blr	x9
      20: 90000008     	adrp	x8, 0x0 &lt;.wowthk$aa&gt;
      24: f9400100     	ldr	x0, [x8]
      28: a94a7bfd     	ldp	x29, x30, [sp, #<!-- -->0xa0]
      2c: ad443fee     	ldp	q14, q15, [sp, #<!-- -->0x80]
      30: ad4337ec     	ldp	q12, q13, [sp, #<!-- -->0x60]
      34: ad422fea     	ldp	q10, q11, [sp, #<!-- -->0x40]
      38: ad4127e8     	ldp	q8, q9, [sp, #<!-- -->0x20]
      3c: acc59fe6     	ldp	q6, q7, [sp], #<!-- -->0xb0
      40: d61f0000     	br	x0

While MSVC generates code to shuffle registers:

0000000000000000 &lt;.wowthk$aa&gt;:
       0: d503237f     	pacibsp
       4: f8150ff3     	str	x19, [sp, #-0xb0]!
       8: ad009fe6     	stp	q6, q7, [sp, #<!-- -->0x10]
       c: ad01a7e8     	stp	q8, q9, [sp, #<!-- -->0x30]
      10: ad02afea     	stp	q10, q11, [sp, #<!-- -->0x50]
      14: ad03b7ec     	stp	q12, q13, [sp, #<!-- -->0x70]
      18: ad04bfee     	stp	q14, q15, [sp, #<!-- -->0x90]
      1c: a9bf7bfd     	stp	x29, x30, [sp, #-0x10]!
      20: 910003fd     	mov	x29, sp
      24: aa0003f3     	mov	x19, x0
      28: aa0103e0     	mov	x0, x1
      2c: aa1303e8     	mov	x8, x19
      30: d63f0120     	blr	x9
      34: aa1303e8     	mov	x8, x19
      38: a8c17bfd     	ldp	x29, x30, [sp], #<!-- -->0x10
      3c: ad44bfee     	ldp	q14, q15, [sp, #<!-- -->0x90]
      40: ad43b7ec     	ldp	q12, q13, [sp, #<!-- -->0x70]
      44: ad42afea     	ldp	q10, q11, [sp, #<!-- -->0x50]
      48: ad41a7e8     	ldp	q8, q9, [sp, #<!-- -->0x30]
      4c: ad409fe6     	ldp	q6, q7, [sp, #<!-- -->0x10]
      50: f84b07f3     	ldr	x19, [sp], #<!-- -->0xb0
      54: d50323ff     	autibsp
      58: 90000010     	adrp	x16, 0x0 &lt;.wowthk$aa&gt;
      5c: f9400210     	ldr	x16, [x16]
      60: d61f0200     	br	x16

efriedma-quic added a commit to efriedma-quic/llvm-project that referenced this issue May 15, 2024
I accidentally left out the code to transfer sret attributes to entry
thunks, so values weren't being passed in the right registers, and the
sret pointer wasn't returned in the correct register.

Fixes llvm#90229
efriedma-quic added a commit that referenced this issue May 16, 2024
I accidentally left out the code to transfer sret attributes to entry
thunks, so values weren't being passed in the right registers, and the
sret pointer wasn't returned in the correct register.

Fixes #90229
@julliard
Copy link
Author

I can confirm that this fixed the problem I was seeing. Thanks!

dpaoliello pushed a commit to dpaoliello/llvm-project that referenced this issue May 17, 2024
I accidentally left out the code to transfer sret attributes to entry
thunks, so values weren't being passed in the right registers, and the
sret pointer wasn't returned in the correct register.

Fixes llvm#90229
tstellar pushed a commit to dpaoliello/llvm-project that referenced this issue May 17, 2024
I accidentally left out the code to transfer sret attributes to entry
thunks, so values weren't being passed in the right registers, and the
sret pointer wasn't returned in the correct register.

Fixes llvm#90229
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ABI Application Binary Interface backend:AArch64
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants