mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
riscv64: add PROMOTE_RET for narrow return ABI compliance
Other mature backends (i386, x86_64, arm64) all define PROMOTE_RET, which forces explicit sign/zero extension of narrow return types at the caller side. Without it, riscv64 relied on the assumption that RV64 registers are always sign-extended, which may not hold when interfacing with non-TCC compilers. Verified on Spacemit X100 (riscv64): self-compilation is self-consistent across 3 layers. test3 reference mismatch is expected — the test intentionally invokes UB via type-punned function pointers (csf macro).
This commit is contained in:
parent
30afb50e64
commit
69c8e92566
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
#define CHAR_IS_UNSIGNED
|
#define CHAR_IS_UNSIGNED
|
||||||
|
|
||||||
|
/* define if return values need to be extended explicitely
|
||||||
|
at caller side (for interfacing with non-TCC compilers) */
|
||||||
|
#define PROMOTE_RET
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|||||||
52
tests/tests2/138_narrow_return_promotion.c
Normal file
52
tests/tests2/138_narrow_return_promotion.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* PROMOTE_RET test: verify char/short return values are properly
|
||||||
|
zero/sign-extended to 64-bit per the RISC-V integer calling convention.
|
||||||
|
Without PROMOTE_RET, upper bits of the return register may contain
|
||||||
|
garbage, causing incorrect results when assigned to a wider type. */
|
||||||
|
|
||||||
|
unsigned char get_uc(void) { return 0x80; }
|
||||||
|
signed char get_sc(void) { return 0x80; }
|
||||||
|
unsigned short get_us(void) { return 0x8000; }
|
||||||
|
signed short get_ss(void) { return 0x8000; }
|
||||||
|
|
||||||
|
/* Prevent inlining to force ABI-compliant calling. */
|
||||||
|
unsigned char (* volatile fp_uc)(void) = get_uc;
|
||||||
|
signed char (* volatile fp_sc)(void) = get_sc;
|
||||||
|
unsigned short (* volatile fp_us)(void) = get_us;
|
||||||
|
signed short (* volatile fp_ss)(void) = get_ss;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int ok = 1;
|
||||||
|
unsigned long long uc = fp_uc();
|
||||||
|
signed long long sc = fp_sc();
|
||||||
|
unsigned long long us = fp_us();
|
||||||
|
signed long long ss = fp_ss();
|
||||||
|
|
||||||
|
printf("uc=%llx sc=%llx us=%llx ss=%llx\n",
|
||||||
|
(unsigned long long)uc,
|
||||||
|
(unsigned long long)sc,
|
||||||
|
(unsigned long long)us,
|
||||||
|
(unsigned long long)ss);
|
||||||
|
|
||||||
|
if (uc != 0x80) {
|
||||||
|
printf("FAIL: uc not zero-extended\n");
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
if (sc != 0xffffffffffffff80LL) {
|
||||||
|
printf("FAIL: sc not sign-extended\n");
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
if (us != 0x8000) {
|
||||||
|
printf("FAIL: us not zero-extended\n");
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
if (ss != 0xffffffffffff8000LL) {
|
||||||
|
printf("FAIL: ss not sign-extended\n");
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n", ok ? "PASS" : "FAIL");
|
||||||
|
return ok ? 0 : 1;
|
||||||
|
}
|
||||||
2
tests/tests2/138_narrow_return_promotion.expect
Normal file
2
tests/tests2/138_narrow_return_promotion.expect
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
uc=80 sc=ffffffffffffff80 us=8000 ss=ffffffffffff8000
|
||||||
|
PASS
|
||||||
Loading…
Reference in New Issue
Block a user