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
12451245 }
12461246 }
12471247
1248+ST_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+
12481269 ST_FUNC void gen_cvt_sxtw(void)
12491270 {
12501271 /* 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
17251725 /* ------------ riscv64-gen.c ------------ */
17261726 #ifdef TCC_TARGET_RISCV64
17271727 ST_FUNC void gen_opl(int op);
1728−//ST_FUNC void gfunc_return(CType *func_type);
17291728 ST_FUNC void gen_va_start(void);
17301729 ST_FUNC void arch_transfer_ret_regs(int);
17311730 ST_FUNC void gen_cvt_sxtw(void);
1731+ST_FUNC void gen_cvt_csti(int t);
17321732 ST_FUNC void gen_increment_tcov (SValue *sv);
17331733 #endif
17341734
tccgen.c+5−5
@@ -3471,11 +3471,11 @@ error: · 3470 unmodified lines
34713471
34723472 if (ds >= ss)
34733473 goto done;
3474−#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
3475− if (ss == 4) {
3476− gen_cvt_csti(dbt);
3477− goto done;
3478− }
3474+#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
3475+ if (ss == 4) {
3476+ gen_cvt_csti(dbt);
3477+ goto done;
3478+ }
34793479 #endif
34803480 bits = (ss - ds) * 8;
34813481 /* 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+
8+int 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 @@
1+c=79 uc=79 s=5679 us=5679
2+PASS

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