Suppose I have this function that has many struct parameters (example from Raylib ):
void DrawTexturePro(Texture texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint) {
// do something with these
}
full test.c
:
// Texture, tex data stored in GPU memory (VRAM)
typedef struct Texture {
unsigned int id; // OpenGL texture id
int width; // Texture base width
int height; // Texture base height
int mipmaps; // Mipmap levels, 1 by default
int format; // Data format (PixelFormat type)
} Texture;
// Rectangle, 4 components
typedef struct Rectangle {
float x; // Rectangle top-left corner position x
float y; // Rectangle top-left corner position y
float width; // Rectangle width
float height; // Rectangle height
} Rectangle;
// Vector2, 2 components
typedef struct Vector2 {
float x; // Vector x component
float y; // Vector y component
} Vector2;
// Color, 4 components, R8G8B8A8 (32bit)
typedef struct Color {
unsigned char r; // Color red value
unsigned char g; // Color green value
unsigned char b; // Color blue value
unsigned char a; // Color alpha value
} Color;
void DrawTexturePro(Texture texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint) {
// do something with these
}
int main(int argc, char** argv) {
Texture tex = {0, 1, 2, 3, 4};
Rectangle rec = { 0.0f, 0.1f, 0.2f, 0.3f};
Vector2 vec = { 0.4f, 0.5f};
Color color = {'a', 'b', 'c', 'd'};
DrawTexturePro(tex, rec, rec, vec, 0.6f, color);
return 0;
}
when I try to disassemble this code, it is very interesting to see that:
_DrawTexturePro: ; @DrawTexturePro
.cfi_startproc
; %bb.0:
sub sp, sp, #64
.cfi_def_cfa_offset 64
ldr w10, [sp, #64]
ldr w9, [sp, #68]
ldr w8, [sp, #72]
str s0, [sp, #48]
str s1, [sp, #52]
str s2, [sp, #56]
str s3, [sp, #60]
str s4, [sp, #32]
str s5, [sp, #36]
str s6, [sp, #40]
str s7, [sp, #44]
str w10, [sp, #24]
str w9, [sp, #28]
str x1, [sp, #8]
ldr w9, [sp, #8]
str w9, [sp, #20]
str w8, [sp, #4]
add sp, sp, #64
ret
.cfi_endproc
full disassembly:
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 13, 0 sdk_version 13, 1
.globl _DrawTexturePro ; -- Begin function DrawTexturePro
.p2align 2
_DrawTexturePro: ; @DrawTexturePro
.cfi_startproc
; %bb.0:
sub sp, sp, #64
.cfi_def_cfa_offset 64
ldr w10, [sp, #64]
ldr w9, [sp, #68]
ldr w8, [sp, #72]
str s0, [sp, #48]
str s1, [sp, #52]
str s2, [sp, #56]
str s3, [sp, #60]
str s4, [sp, #32]
str s5, [sp, #36]
str s6, [sp, #40]
str s7, [sp, #44]
str w10, [sp, #24]
str w9, [sp, #28]
str x1, [sp, #8]
ldr w9, [sp, #8]
str w9, [sp, #20]
str w8, [sp, #4]
add sp, sp, #64
ret
.cfi_endproc
; -- End function
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #144
stp x29, x30, [sp, #128] ; 16-byte Folded Spill
add x29, sp, #128
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov w8, #0
str w8, [sp, #20] ; 4-byte Folded Spill
stur wzr, [x29, #-4]
stur w0, [x29, #-8]
stur x1, [x29, #-16]
adrp x8, l___const.main.tex@PAGE
add x8, x8, l___const.main.tex@PAGEOFF
ldr q0, [x8]
stur q0, [x29, #-48]
ldr w8, [x8, #16]
stur w8, [x29, #-32]
adrp x8, l___const.main.rec@PAGE
add x8, x8, l___const.main.rec@PAGEOFF
ldr q0, [x8]
str q0, [sp, #64]
adrp x8, l___const.main.vec@PAGE
add x8, x8, l___const.main.vec@PAGEOFF
ldr x8, [x8]
str x8, [sp, #56]
adrp x8, l___const.main.color@PAGE
add x8, x8, l___const.main.color@PAGEOFF
ldr w8, [x8]
str w8, [sp, #52]
ldur q0, [x29, #-48]
add x0, sp, #32
str q0, [sp, #32]
ldur w8, [x29, #-32]
str w8, [sp, #48]
ldr s0, [sp, #64]
ldr s1, [sp, #68]
ldr s2, [sp, #72]
ldr s3, [sp, #76]
ldr s4, [sp, #64]
ldr s5, [sp, #68]
ldr s6, [sp, #72]
ldr s7, [sp, #76]
ldr w10, [sp, #56]
ldr w9, [sp, #60]
ldr w8, [sp, #52]
str w8, [sp, #24]
ldr x1, [sp, #24]
mov x8, sp
str w10, [x8]
str w9, [x8, #4]
mov w9, #39322
movk w9, #16153, lsl #16
fmov s16, w9
str s16, [x8, #8]
bl _DrawTexturePro
ldr w0, [sp, #20] ; 4-byte Folded Reload
ldp x29, x30, [sp, #128] ; 16-byte Folded Reload
add sp, sp, #144
ret
.cfi_endproc
; -- End function
.section __TEXT,__const
.p2align 2 ; @__const.main.tex
l___const.main.tex:
.long 0 ; 0x0
.long 1 ; 0x1
.long 2 ; 0x2
.long 3 ; 0x3
.long 4 ; 0x4
.section __TEXT,__literal16,16byte_literals
.p2align 2 ; @__const.main.rec
l___const.main.rec:
.long 0x00000000 ; float 0
.long 0x3dcccccd ; float 0.100000001
.long 0x3e4ccccd ; float 0.200000003
.long 0x3e99999a ; float 0.300000012
.section __TEXT,__literal8,8byte_literals
.p2align 2 ; @__const.main.vec
l___const.main.vec:
.long 0x3ecccccd ; float 0.400000006
.long 0x3f000000 ; float 0.5
.section __TEXT,__literal4,4byte_literals
l___const.main.color: ; @__const.main.color
.byte 97 ; 0x61
.byte 98 ; 0x62
.byte 99 ; 0x63
.byte 100 ; 0x64
Looks like the params are passed so that parts of the structs are in multiple registers . According to AArch64 parameter passing rules if the Composite Type (in this case the struct?) is larger than 16 bytes, then rules B.4
dictates that it will be copied to allocated memory and passed as an address.
If the argument type is a Composite Type that is larger than 16 bytes, then the argument is copied to memory allocated by the caller and the argument is replaced by a pointer to the copy.
However , Rectangle
is a struct comprised of 4 float values, making its size at least 32 bytes.Why then is its members passed to s0-s3
and s4-s7
(line 71 to 79 of my disassembly) instead of being just a single address passed in a register (and btw if that is the case, which register set will this address be used in, the regular or the floating point registers?)
Rectangle
's size is only 16 bytes since each IEEE-754 float is 4 bytes. The compiler is correct. (thanks @Siguza)
My question is two fold:
EDIT: Question clarified following @httpdigest's pointer in the comment.
EDIT2: Question error fixed following @Siguza's comment.
Thanks to @httpdigest and @Siguza I think the answer to my question is as follow:
The parameter passing rules for aarch64 can be found here . Darwin's rules that diverge from the standard can be found here .
To determine the correct way of passing the parameter when you are looking at a function:
Rectangle
is passed as four floats on s0 to s3).Thank you very much everyone. This is making more sense to me now.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.