History

riscv64: implement gen_cvt_csti for narrow int promotion

Add sign/zero extension for char/short to int casts using slli+srai (signed) or slli+srli/andi (unsigned) sequences. Also adds RISCV64 to the gen_cvt_csti fast-path conditional in tccgen.c:3466, matching arm64/i386/x86_64. Verified on Spacemit X100: all tests2 pass, no regressions.

Meng Zhuo committed 6 months ago

Commit 9f0915a1 parent 69c8e925 files · +71 −6Browse files

Unified · Split

5 files
  1. riscv64-gen.c +21 −0
  2. tcc.h +1 −1
  3. tccgen.c +5 −5
  4. tests/tests2/139_narrow_type_conversion.c +42 −0
  5. tests/tests2/139_narrow_type_conversion.expect +2 −0
riscv64-gen.c+21−0
@@ -1245,6 +1245,27 @@ ST_FUNC void gen_opf(int op) · 1244 unmodified lines
1245 }1245 }
1246}1246}
1247 1247
1248ST_FUNC void gen_cvt_csti(int t)
1249{
1250 int r = ireg(gv(RC_INT));
1251 if ((t & VT_BTYPE) == VT_SHORT) {
1252 if (t & VT_UNSIGNED) {
1253 EI(0x13, 1, r, r, 48); // slli r, r, 48
1254 EI(0x13, 5, r, r, 48); // srli r, r, 48
1255 } else {
1256 EI(0x13, 1, r, r, 48); // slli r, r, 48
1257 EIu(0x13, 5, r, r, 0x400 | 48); // srai r, r, 48
1258 }
1259 } else {
1260 if (t & VT_UNSIGNED) {
1261 EI(0x13, 7, r, r, 0xff); // andi r, r, 0xff
1262 } else {
1263 EI(0x13, 1, r, r, 56); // slli r, r, 56
1264 EIu(0x13, 5, r, r, 0x400 | 56); // srai r, r, 56
1265 }
1266 }
1267}
1268
1248ST_FUNC void gen_cvt_sxtw(void)1269ST_FUNC void gen_cvt_sxtw(void)
1249{1270{
1250 /* XXX on risc-v the registers are usually sign-extended already.1271 /* XXX on risc-v the registers are usually sign-extended already.
tcc.h+1−1
@@ -1725,10 +1725,10 @@ ST_FUNC void gen_increment_tcov (SValue *sv); · 1724 unmodified lines
1725/* ------------ riscv64-gen.c ------------ */1725/* ------------ riscv64-gen.c ------------ */
1726#ifdef TCC_TARGET_RISCV641726#ifdef TCC_TARGET_RISCV64
1727ST_FUNC void gen_opl(int op);1727ST_FUNC void gen_opl(int op);
1728//ST_FUNC void gfunc_return(CType *func_type);
1729ST_FUNC void gen_va_start(void);1728ST_FUNC void gen_va_start(void);
1730ST_FUNC void arch_transfer_ret_regs(int);1729ST_FUNC void arch_transfer_ret_regs(int);
1731ST_FUNC void gen_cvt_sxtw(void);1730ST_FUNC void gen_cvt_sxtw(void);
1731ST_FUNC void gen_cvt_csti(int t);
1732ST_FUNC void gen_increment_tcov (SValue *sv);1732ST_FUNC void gen_increment_tcov (SValue *sv);
1733#endif1733#endif
1734 1734
tccgen.c+5−5
@@ -3471,11 +3471,11 @@ error: · 3470 unmodified lines
3471 3471
3472 if (ds >= ss)3472 if (ds >= ss)
3473 goto done;3473 goto done;
3474#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM643474#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
3475 if (ss == 4) {3475 if (ss == 4) {
3476 gen_cvt_csti(dbt);3476 gen_cvt_csti(dbt);
3477 goto done;3477 goto done;
3478 }3478 }
3479#endif3479#endif
3480 bits = (ss - ds) * 8;3480 bits = (ss - ds) * 8;
3481 /* for unsigned, gen_op will convert SAR to SHR */3481 /* for unsigned, gen_op will convert SAR to SHR */
tests/tests2/139_narrow_type_conversion.c+42−0
@@ -0,0 +1,42 @@
1#include <stdio.h>
2
3/* gen_cvt_csti test: verify narrow-type conversions in expressions.
4 Without the fix, TCC's riscv64 backend could miss the conversion
5 step when promoting a narrow result back to int, producing wrong
6 values (e.g., treating a char as still 32-bit). */
7
8int main(void)
9{
10 int ok = 1;
11 int x = 0x12345678;
12
13 /* Cast to char then add 1 — result must be 8-bit. */
14 char c = (char)x + 1;
15 unsigned char uc = (unsigned char)x + 1;
16 short s = (short)x + 1;
17 unsigned short us = (unsigned short)x + 1;
18
19 printf("c=%x uc=%x s=%x us=%x\n",
20 (unsigned char)c, (unsigned)uc,
21 (unsigned short)s, (unsigned)us);
22
23 if (c != (char)0x78 + 1) {
24 printf("FAIL: char conversion\n");
25 ok = 0;
26 }
27 if (uc != (unsigned char)0x78 + 1) {
28 printf("FAIL: unsigned char conversion\n");
29 ok = 0;
30 }
31 if (s != (short)0x5678 + 1) {
32 printf("FAIL: short conversion\n");
33 ok = 0;
34 }
35 if (us != (unsigned short)0x5678 + 1) {
36 printf("FAIL: unsigned short conversion\n");
37 ok = 0;
38 }
39
40 printf("%s\n", ok ? "PASS" : "FAIL");
41 return ok ? 0 : 1;
42}
tests/tests2/139_narrow_type_conversion.expect+2−0
@@ -0,0 +1,2 @@
1c=79 uc=79 s=5679 us=5679
2PASS

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t