为什么 "long long" 参数在 RISC-V 中需要 "aligned even-odd register pair"
Why "long long" arguments need to "aligned even-odd register pair" in RISC-V
正如RISC-V calling convention documentation所说:
When primitive arguments twice the size of a pointer-word are passed on the stack, they are
naturally aligned. When they are passed in the integer registers, they reside in an aligned even-odd
register pair, with the even register holding the least-significant bits. In RV32, for example, the
function void foo(int, long long) is passed its first argument in a0 and its second in a2 and
a3. Nothing is passed in a1.
为什么不直接使用 a1
和 a2
而不是 a2
和 a3
?所以我们可以通过寄存器传递更多的参数。
通常,这样做是为了让简单的代码可以将所有寄存器刷新到内存中,并获得您期望的结果,就好像首先使用内存来传递对齐良好的参数一样——这是通常对可变参数函数很重要。
但是,我们应该注意,对于非可变参数函数,clang 和 gcc 都不会直接遵循这一点。他们都使用 a0
作为 int
和 a1
,a2
作为 long long
(其中 a1
是低阶, a2
long long
).
的高阶
long long square(int num, long long foo) {
return foo + 100;
}
结果
square:
addi a0, a1, 100
sltu a1, a0, a1
add a1, a1, a2
ret
叮当声:https://godbolt.org/z/9Pez4r
gcc: https://godbolt.org/z/b4dMsr
只有当我们使用可变参数时,我们才会看到编译器跳过 a1
:
long long square(int num, ...);
int test () {
square ( 100, (long long) 200 );
}
结果
test:
addi a0, zero, 100
addi a2, zero, 200
mv a3, zero
tail square
正如RISC-V calling convention documentation所说:
When primitive arguments twice the size of a pointer-word are passed on the stack, they are naturally aligned. When they are passed in the integer registers, they reside in an aligned even-odd register pair, with the even register holding the least-significant bits. In RV32, for example, the function void foo(int, long long) is passed its first argument in a0 and its second in a2 and a3. Nothing is passed in a1.
为什么不直接使用 a1
和 a2
而不是 a2
和 a3
?所以我们可以通过寄存器传递更多的参数。
通常,这样做是为了让简单的代码可以将所有寄存器刷新到内存中,并获得您期望的结果,就好像首先使用内存来传递对齐良好的参数一样——这是通常对可变参数函数很重要。
但是,我们应该注意,对于非可变参数函数,clang 和 gcc 都不会直接遵循这一点。他们都使用 a0
作为 int
和 a1
,a2
作为 long long
(其中 a1
是低阶, a2
long long
).
long long square(int num, long long foo) {
return foo + 100;
}
结果
square:
addi a0, a1, 100
sltu a1, a0, a1
add a1, a1, a2
ret
叮当声:https://godbolt.org/z/9Pez4r
gcc: https://godbolt.org/z/b4dMsr
只有当我们使用可变参数时,我们才会看到编译器跳过 a1
:
long long square(int num, ...);
int test () {
square ( 100, (long long) 200 );
}
结果
test:
addi a0, zero, 100
addi a2, zero, 200
mv a3, zero
tail square