History

update gen_cast

grischka committed 6 years ago

Commit 89372dc1 parent 35475b510 files · +371 −278Browse files

Unified · Split

10 files
  1. arm64-gen.c +10 −0
  2. i386-gen.c +13 −0
  3. libtcc.c +2 −1
  4. tcc.h +15 −5
  5. tccgen.c +251 −259
  6. tests/Makefile +1 −0
  7. tests/tcctest.c +52 −6
  8. tests/tests2/88_codeopt.c +1 −1
  9. tests/tests2/96_nodata_wanted.expect +1 −1
  10. x86_64-gen.c +25 −5
arm64-gen.c+10−0
@@ -1718,6 +1718,16 @@ ST_FUNC void gen_cvt_sxtw(void) · 1717 unmodified lines
17181718 o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)
17191719 }
17201720
1721+/* char/short to int conversion */
1722+ST_FUNC void gen_cvt_csti(int t)
1723+{
1724+ int r = intr(gv(RC_INT));
1725+ o(0x13001c00
1726+ | ((t & VT_BTYPE) == VT_SHORT) << 13
1727+ | (uint32_t)!!(t & VT_UNSIGNED) << 30
1728+ | r | r << 5); // [su]xt[bh] w(r),w(r)
1729+}
1730+
17211731 ST_FUNC void gen_cvt_itof(int t)
17221732 {
17231733 if (t == VT_LDOUBLE) {
i386-gen.c+13−0
@@ -1048,6 +1048,19 @@ ST_FUNC void gen_cvt_ftof(int t) · 1047 unmodified lines
10481048 gv(RC_FLOAT);
10491049 }
10501050
1051+/* char/short to int conversion */
1052+ST_FUNC void gen_cvt_csti(int t)
1053+{
1054+ int r, sz, xl;
1055+ r = gv(RC_INT);
1056+ sz = !(t & VT_UNSIGNED);
1057+ xl = (t & VT_BTYPE) == VT_SHORT;
1058+ o(0xc0b60f /* mov[sz] %a[xl], %eax */
1059+ | (sz << 3 | xl) << 8
1060+ | (r << 3 | r) << 16
1061+ );
1062+}
1063+
10511064 /* computed goto support */
10521065 ST_FUNC void ggoto(void)
10531066 {
libtcc.c+2−1
@@ -1965,7 +1965,8 @@ reparse: · 1964 unmodified lines
19651965 }
19661966 break;
19671967 case TCC_OPTION_W:
1968− if (set_flag(s, options_W, optarg) < 0)
1968+ s->warn_none = 0;
1969+ if (optarg[0] && set_flag(s, options_W, optarg) < 0)
19691970 goto unsupported_option;
19701971 break;
19711972 case TCC_OPTION_w:
tcc.h+15−5
@@ -926,9 +926,9 @@ struct filespec { · 925 unmodified lines
926926 #define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */
927927 #define VT_LVAL 0x0100 /* var is an lvalue */
928928 #define VT_SYM 0x0200 /* a symbol value is added */
929−#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
929+#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
930930 char/short stored in integer registers) */
931−#define VT_MUSTBOUND 0x0800 /* bound checking must be done before
931+#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
932932 dereferencing value */
933933 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
934934 bounding function call point is in vc */
@@ -986,6 +986,11 @@ struct filespec { · 51 unmodified lines
986986 #define VT_ASM (VT_VOID | VT_UNSIGNED)
987987 #define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
988988
989+/* general: set/get the pseudo-bitfield value for bit-mask M */
990+#define BFVAL(M,N) ((unsigned)((M) & ~((M) << 1)) * (N))
991+#define BFGET(X,M) (((X) & (M)) / BFVAL(M,1))
992+#define BFSET(X,M,N) ((X) = ((X) & ~(M)) | BFVAL(M,N))
993+
989994 /* token values */
990995
991996 /* warning: the following compare tokens depend on i386 asm code */
@@ -1359,7 +1364,7 @@ ST_DATA Sym *local_stack; · 367 unmodified lines
13591364 ST_DATA Sym *local_label_stack;
13601365 ST_DATA Sym *global_label_stack;
13611366 ST_DATA Sym *define_stack;
1362−ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
1367+ST_DATA CType int_type, func_old_type, char_pointer_type;
13631368 ST_DATA SValue *vtop;
13641369 ST_DATA int rsym, anon_sym, ind, loc;
13651370
@@ -1598,6 +1603,7 @@ ST_FUNC void gen_le16(int c); · 232 unmodified lines
15981603 ST_FUNC void gen_le32(int c);
15991604 ST_FUNC void gen_addr32(int r, Sym *sym, int c);
16001605 ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
1606+ST_FUNC void gen_cvt_csti(int t);
16011607 #endif
16021608
16031609 #ifdef CONFIG_TCC_BCHECK
@@ -1612,6 +1618,8 @@ ST_FUNC void gen_opl(int op); · 8 unmodified lines
16121618 #ifdef TCC_TARGET_PE
16131619 ST_FUNC void gen_vla_result(int addr);
16141620 #endif
1621+ST_FUNC void gen_cvt_sxtw(void);
1622+ST_FUNC void gen_cvt_csti(int t);
16151623 #endif
16161624
16171625 /* ------------ arm-gen.c ------------ */
@@ -1624,22 +1632,24 @@ ST_FUNC void arm_init(struct TCCState *s); · 6 unmodified lines
16241632
16251633 /* ------------ arm64-gen.c ------------ */
16261634 #ifdef TCC_TARGET_ARM64
1627−ST_FUNC void gen_cvt_sxtw(void);
16281635 ST_FUNC void gen_opl(int op);
16291636 ST_FUNC void gfunc_return(CType *func_type);
16301637 ST_FUNC void gen_va_start(void);
16311638 ST_FUNC void gen_va_arg(CType *t);
16321639 ST_FUNC void gen_clear_cache(void);
1640+ST_FUNC void gen_cvt_sxtw(void);
1641+ST_FUNC void gen_cvt_csti(int t);
16331642 #endif
16341643
16351644 /* ------------ riscv64-gen.c ------------ */
16361645 #ifdef TCC_TARGET_RISCV64
1637−ST_FUNC void gen_cvt_sxtw(void);
16381646 ST_FUNC void gen_opl(int op);
16391647 //ST_FUNC void gfunc_return(CType *func_type);
16401648 ST_FUNC void gen_va_start(void);
16411649 ST_FUNC void arch_transfer_ret_regs(int);
1650+ST_FUNC void gen_cvt_sxtw(void);
16421651 #endif
1652+
16431653 /* ------------ c67-gen.c ------------ */
16441654 #ifdef TCC_TARGET_C67
16451655 #endif
tccgen.c+251−259
@@ -79,8 +79,18 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in · 78 unmodified lines
7979 ST_DATA int func_vc;
8080 static int last_line_num, new_file, func_ind; /* debug info control */
8181 ST_DATA const char *funcname;
82+ST_DATA CType int_type, func_old_type, char_pointer_type;
8283
83−ST_DATA CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type;
84+#if PTR_SIZE == 4
85+#define VT_SIZE_T (VT_INT | VT_UNSIGNED)
86+#define VT_PTRDIFF_T VT_INT
87+#elif LONG_SIZE == 4
88+#define VT_SIZE_T (VT_LLONG | VT_UNSIGNED)
89+#define VT_PTRDIFF_T VT_LLONG
90+#else
91+#define VT_SIZE_T (VT_LONG | VT_LLONG | VT_UNSIGNED)
92+#define VT_PTRDIFF_T (VT_LONG | VT_LLONG)
93+#endif
8494
8595 ST_DATA struct switch_t {
8696 struct case_t {
@@ -149,6 +159,7 @@ static void skip_or_save_block(TokenString **str); · 62 unmodified lines
149159 static void gv_dup(void);
150160 static int get_temp_local_var(int size,int align);
151161 static void clear_temp_local_var_list();
162+static void cast_error(CType *st, CType *dt);
152163
153164 ST_INLN int is_float(int t)
154165 {
@@ -162,6 +173,7 @@ ST_INLN int is_float(int t) · 7 unmodified lines
162173 static inline int is_integer_btype(int bt)
163174 {
164175 return bt == VT_BYTE
176+ || bt == VT_BOOL
165177 || bt == VT_SHORT
166178 || bt == VT_INT
167179 || bt == VT_LLONG;
@@ -439,16 +451,6 @@ ST_FUNC void tccgen_init(TCCState *s1) · 271 unmodified lines
439451 int_type.t = VT_INT;
440452 char_pointer_type.t = VT_BYTE;
441453 mk_pointer(&char_pointer_type);
442−#if PTR_SIZE == 4
443− size_type.t = VT_INT | VT_UNSIGNED;
444− ptrdiff_type.t = VT_INT;
445−#elif LONG_SIZE == 4
446− size_type.t = VT_LLONG | VT_UNSIGNED;
447− ptrdiff_type.t = VT_LLONG;
448−#else
449− size_type.t = VT_LONG | VT_LLONG | VT_UNSIGNED;
450− ptrdiff_type.t = VT_LONG | VT_LLONG;
451−#endif
452454 func_old_type.t = VT_FUNC;
453455 func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
454456 func_old_type.ref->f.func_call = FUNC_CDECL;
@@ -922,36 +924,32 @@ ST_FUNC void vpop(void) · 467 unmodified lines
922924 }
923925
924926 /* push constant of type "type" with useless value */
925−ST_FUNC void vpush(CType *type)
927+static void vpush(CType *type)
926928 {
927929 vset(type, VT_CONST, 0);
928930 }
929931
930−/* push integer constant */
931−ST_FUNC void vpushi(int v)
932+/* push arbitrary 64bit constant */
933+static void vpush64(int ty, unsigned long long v)
932934 {
933935 CValue cval;
936+ CType ctype;
937+ ctype.t = ty;
938+ ctype.ref = NULL;
934939 cval.i = v;
935− vsetc(&int_type, VT_CONST, &cval);
940+ vsetc(&ctype, VT_CONST, &cval);
936941 }
937942
938−/* push a pointer sized constant */
939−static void vpushs(addr_t v)
943+/* push integer constant */
944+ST_FUNC void vpushi(int v)
940945 {
941− CValue cval;
942− cval.i = v;
943− vsetc(&size_type, VT_CONST, &cval);
946+ vpush64(VT_INT, v);
944947 }
945948
946−/* push arbitrary 64bit constant */
947−ST_FUNC void vpush64(int ty, unsigned long long v)
949+/* push a pointer sized constant */
950+static void vpushs(addr_t v)
948951 {
949− CValue cval;
950− CType ctype;
951− ctype.t = ty;
952− ctype.ref = NULL;
953− cval.i = v;
954− vsetc(&ctype, VT_CONST, &cval);
952+ vpush64(VT_SIZE_T, v);
955953 }
956954
957955 /* push long long constant */
@@ -963,7 +961,6 @@ static inline void vpushll(long long v) · 5 unmodified lines
963961 ST_FUNC void vset(CType *type, int r, int v)
964962 {
965963 CValue cval;
966−
967964 cval.i = v;
968965 vsetc(type, r, &cval);
969966 }
@@ -1099,6 +1096,23 @@ static int gvtst(int inv, int t) · 129 unmodified lines
10991096 return t;
11001097 }
11011098
1099+/* generate a zero or nozero test */
1100+static void gen_test_zero(int op)
1101+{
1102+ if (vtop->r == VT_CMP) {
1103+ int j;
1104+ if (op == TOK_EQ) {
1105+ j = vtop->jfalse;
1106+ vtop->jfalse = vtop->jtrue;
1107+ vtop->jtrue = j;
1108+ vtop->cmp_op ^= 1;
1109+ }
1110+ } else {
1111+ vpushi(0);
1112+ gen_op(op);
1113+ }
1114+}
1115+
11021116 /* ------------------------------------------------------------------------- */
11031117 /* push a symbol value of TYPE */
11041118 static inline void vpushsym(CType *type, Sym *sym)
@@ -1350,44 +1364,34 @@ ST_FUNC void save_reg(int r) · 245 unmodified lines
13501364 if seen up to (vtop - n) stack entry */
13511365 ST_FUNC void save_reg_upstack(int r, int n)
13521366 {
1353− int l, saved, size, align;
1367+ int l, size, align, bt;
13541368 SValue *p, *p1, sv;
1355− CType *type;
13561369
13571370 if ((r &= VT_VALMASK) >= VT_CONST)
13581371 return;
13591372 if (nocode_wanted)
13601373 return;
1361−
1362− /* modify all stack values */
1363− saved = 0;
13641374 l = 0;
13651375 for(p = vstack, p1 = vtop - n; p <= p1; p++) {
1366− if ((p->r & VT_VALMASK) == r || (p->r2 & VT_VALMASK) == r) {
1376+ if ((p->r & VT_VALMASK) == r || p->r2 == r) {
13671377 /* must save value on stack if not already done */
1368− if (!saved) {
1369− /* NOTE: must reload 'r' because r might be equal to r2 */
1370− r = p->r & VT_VALMASK;
1371− /* store register in the stack */
1372− type = &p->type;
1373− if ((p->r & VT_LVAL) ||
1374− (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
1375−#if PTR_SIZE == 8
1376− type = &char_pointer_type;
1377−#else
1378− type = &int_type;
1379−#endif
1380− size = type_size(type, &align);
1378+ if (!l) {
1379+ bt = p->type.t & VT_BTYPE;
1380+ if (bt == VT_VOID)
1381+ continue;
1382+ if ((p->r & VT_LVAL) || bt == VT_FUNC)
1383+ bt = VT_PTR;
1384+ sv.type.t = bt;
1385+ size = type_size(&sv.type, &align);
13811386 #ifdef CONFIG_TCC_BCHECK
13821387 if (tcc_state->do_bounds_check)
13831388 l = loc = (loc - size) & -align;
13841389 else
13851390 #endif
1386− l=get_temp_local_var(size,align);
1387− sv.type.t = type->t;
1391+ l = get_temp_local_var(size,align);
13881392 sv.r = VT_LOCAL | VT_LVAL;
13891393 sv.c.i = l;
1390− store(r, &sv);
1394+ store(p->r & VT_VALMASK, &sv);
13911395 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
13921396 /* x86 specific: need to pop fp register ST0 if saved */
13931397 if (r == TREG_ST0) {
@@ -1395,11 +1399,10 @@ ST_FUNC void save_reg_upstack(int r, int n) · 1 unmodified line
13951399 }
13961400 #endif
13971401 /* special long long case */
1398− if (p->r2 < VT_CONST && USING_TWO_WORDS(type->t)) {
1402+ if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
13991403 sv.c.i += PTR_SIZE;
14001404 store(p->r2, &sv);
14011405 }
1402− saved = 1;
14031406 }
14041407 /* mark that stack entry as being saved on the stack */
14051408 if (p->r & VT_LVAL) {
@@ -1771,7 +1774,7 @@ ST_FUNC int gv(int rc) · 365 unmodified lines
17711774 if (!r_ok)
17721775 r = get_reg(rc);
17731776 if (rc2) {
1774− int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : ptrdiff_type.t;
1777+ int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T;
17751778 int original_type = vtop->type.t;
17761779
17771780 /* two register type load :
@@ -1793,9 +1796,9 @@ ST_FUNC int gv(int rc) · 15 unmodified lines
17931796 vdup();
17941797 vtop[-1].r = r; /* save register value */
17951798 /* increment pointer to get second word */
1796− vtop->type.t = ptrdiff_type.t;
1799+ vtop->type.t = VT_PTRDIFF_T;
17971800 gaddrof();
1798− vpushi(PTR_SIZE);
1801+ vpushs(PTR_SIZE);
17991802 gen_op('+');
18001803 vtop->r |= VT_LVAL;
18011804 vtop->type.t = load_type;
@@ -2521,7 +2524,7 @@ redo: · 719 unmodified lines
25212524 }
25222525 vrott(3);
25232526 gen_opic(op);
2524− vtop->type.t = ptrdiff_type.t;
2527+ vtop->type.t = VT_PTRDIFF_T;
25252528 vswap();
25262529 gen_op(TOK_PDIV);
25272530 } else {
@@ -2712,41 +2715,17 @@ static void gen_cvt_ftoi1(int t) · 184 unmodified lines
27122715 }
27132716 #endif
27142717
2715−/* force char or short cast */
2716−static void force_charshort_cast(int t)
2718+/* special delayed cast for char/short */
2719+static void force_charshort_cast(void)
27172720 {
2718− int bits, dbt;
2719−
2720− /* cannot cast static initializers */
2721− if (STATIC_DATA_WANTED)
2722− return;
2723−
2724− dbt = t & VT_BTYPE;
2725− /* XXX: add optimization if lvalue : just change type and offset */
2726− if (dbt == VT_BYTE)
2727− bits = 8;
2728− else
2729− bits = 16;
2730− if (t & VT_UNSIGNED) {
2731− vpushi((1 << bits) - 1);
2732− gen_op('&');
2733− } else {
2734− if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
2735− bits = 64 - bits;
2736− else
2737− bits = 32 - bits;
2738− vpushi(bits);
2739− gen_op(TOK_SHL);
2740− /* result must be signed or the SAR is converted to an SHL
2741− This was not the case when "t" was a signed short
2742− and the last value on the stack was an unsigned int */
2743− vtop->type.t &= ~VT_UNSIGNED;
2744− vpushi(bits);
2745− gen_op(TOK_SAR);
2746− }
2721+ int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT;
2722+ int dbt = vtop->type.t;
2723+ vtop->r &= ~VT_MUSTCAST;
2724+ vtop->type.t = sbt;
2725+ gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt);
2726+ vtop->type.t = dbt;
27472727 }
27482728
2749−/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
27502729 static void gen_cast_s(int t)
27512730 {
27522731 CType type;
@@ -2755,31 +2734,33 @@ static void gen_cast_s(int t) · 2 unmodified lines
27552734 gen_cast(&type);
27562735 }
27572736
2737+/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
27582738 static void gen_cast(CType *type)
27592739 {
2760− int sbt, dbt, sf, df, c, p;
2740+ int sbt, dbt, sf, df, c;
2741+ int dbt_bt, sbt_bt, ds, ss, bits, trunc;
27612742
27622743 /* special delayed cast for char/short */
2763− /* XXX: in some cases (multiple cascaded casts), it may still
2764− be incorrect */
2765− if (vtop->r & VT_MUSTCAST) {
2766− vtop->r &= ~VT_MUSTCAST;
2767− force_charshort_cast(vtop->type.t);
2768− }
2744+ if (vtop->r & VT_MUSTCAST)
2745+ force_charshort_cast();
27692746
27702747 /* bitfields first get cast to ints */
2771− if (vtop->type.t & VT_BITFIELD) {
2748+ if (vtop->type.t & VT_BITFIELD)
27722749 gv(RC_INT);
2773− }
27742750
27752751 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
27762752 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
2753+ if (sbt == VT_FUNC)
2754+ sbt = VT_PTR;
27772755
2756+again:
27782757 if (sbt != dbt) {
27792758 sf = is_float(sbt);
27802759 df = is_float(dbt);
2760+ dbt_bt = dbt & VT_BTYPE;
2761+ sbt_bt = sbt & VT_BTYPE;
2762+
27812763 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
2782− p = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == (VT_CONST | VT_SYM);
27832764 #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387
27842765 c &= (dbt != VT_LDOUBLE) | !!nocode_wanted;
27852766 #endif
@@ -2792,7 +2773,7 @@ static void gen_cast(CType *type) · 6 unmodified lines
27922773 vtop->c.ld = vtop->c.d;
27932774
27942775 if (df) {
2795− if ((sbt & VT_BTYPE) == VT_LLONG) {
2776+ if (sbt_bt == VT_LLONG) {
27962777 if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63))
27972778 vtop->c.ld = vtop->c.i;
27982779 else
@@ -2808,164 +2789,173 @@ static void gen_cast(CType *type) · 9 unmodified lines
28082789 vtop->c.f = (float)vtop->c.ld;
28092790 else if (dbt == VT_DOUBLE)
28102791 vtop->c.d = (double)vtop->c.ld;
2811− } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
2812− vtop->c.i = vtop->c.ld;
28132792 } else if (sf && dbt == VT_BOOL) {
28142793 vtop->c.i = (vtop->c.ld != 0);
28152794 } else {
28162795 if(sf)
28172796 vtop->c.i = vtop->c.ld;
2818− else if (sbt == (VT_LLONG|VT_UNSIGNED))
2797+ else if (sbt_bt == VT_LLONG || (PTR_SIZE == 8 && sbt == VT_PTR))
28192798 ;
28202799 else if (sbt & VT_UNSIGNED)
28212800 vtop->c.i = (uint32_t)vtop->c.i;
2822−#if PTR_SIZE == 8
2823− else if (sbt == VT_PTR)
2824− ;
2825−#endif
2826− else if (sbt != VT_LLONG)
2827− vtop->c.i = ((uint32_t)vtop->c.i |
2828− -(vtop->c.i & 0x80000000));
2801+ else
2802+ vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000));
28292803
2830− if (dbt == (VT_LLONG|VT_UNSIGNED))
2804+ if (dbt_bt == VT_LLONG || (PTR_SIZE == 8 && dbt == VT_PTR))
28312805 ;
28322806 else if (dbt == VT_BOOL)
28332807 vtop->c.i = (vtop->c.i != 0);
2834−#if PTR_SIZE == 8
2835− else if (dbt == VT_PTR)
2836− ;
2837−#endif
2838− else if (dbt != VT_LLONG) {
2839− uint32_t m = ((dbt & VT_BTYPE) == VT_BYTE ? 0xff :
2840− (dbt & VT_BTYPE) == VT_SHORT ? 0xffff :
2841− 0xffffffff);
2808+ else {
2809+ uint32_t m = dbt_bt == VT_BYTE ? 0xff :
2810+ dbt_bt == VT_SHORT ? 0xffff :
2811+ 0xffffffff;
28422812 vtop->c.i &= m;
28432813 if (!(dbt & VT_UNSIGNED))
28442814 vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1));
28452815 }
28462816 }
2847− } else if (p && dbt == VT_BOOL) {
2817+ goto done;
2818+
2819+ } else if (dbt == VT_BOOL
2820+ && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM))
2821+ == (VT_CONST | VT_SYM)) {
2822+ /* addresses are considered non-zero (see tcctest.c:sinit23) */
28482823 vtop->r = VT_CONST;
28492824 vtop->c.i = 1;
2850− } else {
2851− /* non constant case: generate code */
2825+ goto done;
2826+ }
2827+
2828+ /* cannot generate code for global or static initializers */
2829+ if (STATIC_DATA_WANTED)
2830+ goto done;
2831+
2832+ /* non constant case: generate code */
2833+ if (dbt == VT_BOOL) {
2834+ gen_test_zero(TOK_NE);
2835+ goto done;
2836+ }
2837+
2838+ if (sf || df) {
28522839 if (sf && df) {
28532840 /* convert from fp to fp */
28542841 gen_cvt_ftof(dbt);
28552842 } else if (df) {
28562843 /* convert int to fp */
28572844 gen_cvt_itof1(dbt);
2858− } else if (sf) {
2845+ } else {
28592846 /* convert fp to int */
2860− if (dbt == VT_BOOL) {
2861− vpushi(0);
2862− gen_op(TOK_NE);
2863− } else {
2864− /* we handle char/short/etc... with generic code */
2865− if (dbt != (VT_INT | VT_UNSIGNED) &&
2866− dbt != (VT_LLONG | VT_UNSIGNED) &&
2867− dbt != VT_LLONG)
2868− dbt = VT_INT;
2869− gen_cvt_ftoi1(dbt);
2870− if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
2871− /* additional cast for char/short... */
2872− vtop->type.t = dbt;
2873− gen_cast(type);
2874− }
2875− }
2847+ sbt = dbt;
2848+ if (dbt_bt != VT_LLONG && dbt_bt != VT_INT)
2849+ sbt = VT_INT;
2850+ gen_cvt_ftoi1(sbt);
2851+ goto again; /* may need char/short cast */
2852+ }
2853+ goto done;
2854+ }
2855+
2856+ ds = btype_size(dbt_bt);
2857+ ss = btype_size(sbt_bt);
2858+ if (ds == 0 || ss == 0) {
2859+ if (dbt_bt == VT_VOID)
2860+ goto done;
2861+ cast_error(&vtop->type, type);
2862+ }
2863+ if (IS_ENUM(type->t) && type->ref->c < 0)
2864+ tcc_error("cast to incomplete type");
2865+
2866+ /* same size and no sign conversion needed */
2867+ if (ds == ss && ds >= 4)
2868+ goto done;
2869+ if (dbt_bt == VT_PTR || sbt_bt == VT_PTR) {
2870+ tcc_warning("cast between pointer and integer of different size");
2871+ if (sbt_bt == VT_PTR) {
2872+ /* put integer type to allow logical operations below */
2873+ vtop->type.t = (PTR_SIZE == 8 ? VT_LLONG : VT_INT);
2874+ }
2875+ }
2876+
2877+ /* processor allows { int a = 0, b = *(char*)&a; }
2878+ That means that if we cast to less width, we can just
2879+ change the type and read it still later. */
2880+ #define ALLOW_SUBTYPE_ACCESS 1
2881+
2882+ if (ALLOW_SUBTYPE_ACCESS && (vtop->r & VT_LVAL)) {
2883+ /* value still in memory */
2884+ if (ds <= ss)
2885+ goto done;
2886+ /* ss <= 4 here */
2887+ if (ds <= 4) {
2888+ gv(RC_INT);
2889+ goto done; /* no 64bit envolved */
2890+ }
2891+ }
2892+ gv(RC_INT);
2893+
2894+ trunc = 0;
28762895 #if PTR_SIZE == 4
2877− } else if ((dbt & VT_BTYPE) == VT_LLONG) {
2878− if ((sbt & VT_BTYPE) != VT_LLONG) {
2879− /* scalar to long long */
2880− /* machine independent conversion */
2881− gv(RC_INT);
2882− /* generate high word */
2883− if (sbt == (VT_INT | VT_UNSIGNED)) {
2884− vpushi(0);
2885− gv(RC_INT);
2886− } else {
2887− if (sbt == VT_PTR) {
2888− /* cast from pointer to int before we apply
2889− shift operation, which pointers don't support*/
2890− gen_cast_s(VT_INT);
2891− }
2892− gv_dup();
2893− vpushi(31);
2894− gen_op(TOK_SAR);
2895− }
2896− /* patch second register */
2897− vtop[-1].r2 = vtop->r;
2898− vpop();
2899− }
2900−#else
2901− } else if ((dbt & VT_BTYPE) == VT_LLONG ||
2902− (dbt & VT_BTYPE) == VT_PTR ||
2903− (dbt & VT_BTYPE) == VT_FUNC) {
2904− if ((sbt & VT_BTYPE) != VT_LLONG &&
2905− (sbt & VT_BTYPE) != VT_PTR &&
2906− (sbt & VT_BTYPE) != VT_FUNC) {
2907− /* need to convert from 32bit to 64bit */
2908− gv(RC_INT);
2909− if (sbt != (VT_INT | VT_UNSIGNED)) {
2910−#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_RISCV64)
2911− gen_cvt_sxtw();
2912−#elif defined(TCC_TARGET_X86_64)
2913− int r = gv(RC_INT);
2914− /* x86_64 specific: movslq */
2915− o(0x6348);
2916− o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
2917−#else
2918−#error
2919−#endif
2920− } else if (sbt & VT_UNSIGNED) {
2921−#if defined(TCC_TARGET_RISCV64)
2922− /* RISC-V keeps 32bit vals in registers sign-extended.
2923− So here we need a zero-extension. */
2924− vtop->type.t = VT_LLONG;
2925− vpushi(32);
2926− gen_op(TOK_SHL);
2927− vpushi(32);
2928− gen_op(TOK_SHR);
2929−#endif
2930− }
2931− }
2932−#endif
2933− } else if (dbt == VT_BOOL) {
2934− /* scalar to bool */
2896+ if (ds == 8) {
2897+ /* generate high word */
2898+ if (sbt & VT_UNSIGNED) {
29352899 vpushi(0);
2936− gen_op(TOK_NE);
2937− } else if ((dbt & VT_BTYPE) == VT_BYTE ||
2938− (dbt & VT_BTYPE) == VT_SHORT) {
2939− if (sbt == VT_PTR) {
2940− vtop->type.t = VT_INT;
2941− tcc_warning("nonportable conversion from pointer to char/short");
2942− }
2943− force_charshort_cast(dbt);
2944− } else if ((dbt & VT_BTYPE) == VT_INT) {
2945− /* scalar to int */
2946− if ((sbt & VT_BTYPE) == VT_LLONG) {
2947−#if PTR_SIZE == 4
2948− /* from long long: just take low order word */
2949− lexpand();
2950− vpop();
2900+ gv(RC_INT);
2901+ } else {
2902+ gv_dup();
2903+ vpushi(31);
2904+ gen_op(TOK_SAR);
2905+ }
2906+ lbuild(dbt);
2907+ } else if (ss == 8) {
2908+ /* from long long: just take low order word */
2909+ lexpand();
2910+ vpop();
2911+ }
2912+ ss = 4;
2913+
2914+#elif PTR_SIZE == 8
2915+ if (ds == 8) {
2916+ /* need to convert from 32bit to 64bit */
2917+ if (sbt & VT_UNSIGNED) {
2918+#if defined(TCC_TARGET_RISCV64)
2919+ /* RISC-V keeps 32bit vals in registers sign-extended.
2920+ So here we need a zero-extension. */
2921+ trunc = 32;
29512922 #else
2952− if (dbt & VT_UNSIGNED) {
2953− /* XXX some architectures (e.g. risc-v) would like it
2954− better for this merely being a 32-to-64 sign or zero-
2955− extension. */
2956− vpushi(0xffffffff);
2957− vtop->type.t |= VT_UNSIGNED;
2958− gen_op('&');
2959− } else {
2960− }
2923+ goto done;
29612924 #endif
2962− }
2925+ } else {
2926+ gen_cvt_sxtw();
2927+ goto done;
29632928 }
2964− if ((vtop->r & VT_LVAL)
2965− && (dbt & VT_BTYPE) != (sbt & VT_BTYPE))
2966− gv(RC_INT);
2929+ ss = ds, ds = 4, dbt = sbt;
2930+ } else if (ss == 8) {
2931+ /* XXX some architectures (e.g. risc-v) would like it
2932+ better for this merely being a 32-to-64 sign or zero-
2933+ extension. */
2934+ trunc = 32; /* zero upper 32 bits */
2935+ } else {
2936+ ss = 4;
29672937 }
2938+#endif
2939+
2940+ if (ds >= ss)
2941+ goto done;
2942+#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
2943+ if (ss == 4) {
2944+ gen_cvt_csti(dbt);
2945+ goto done;
2946+ }
2947+#endif
2948+ bits = (ss - ds) * 8;
2949+ /* for unsigned, gen_op will convert SAR to SHR */
2950+ vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED);
2951+ vpushi(bits);
2952+ gen_op(TOK_SHL);
2953+ vpushi(bits - trunc);
2954+ gen_op(TOK_SAR);
2955+ vpushi(trunc);
2956+ gen_op(TOK_SHR);
29682957 }
2958+done:
29692959 vtop->type = *type;
29702960 vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY );
29712961 }
@@ -3293,25 +3283,30 @@ static void type_to_str(char *buf, int buf_size, · 321 unmodified lines
32933283 no_var: ;
32943284 }
32953285
3286+static void cast_error(CType *st, CType *dt)
3287+{
3288+ char buf1[256], buf2[256];
3289+ type_to_str(buf1, sizeof(buf1), st, NULL);
3290+ type_to_str(buf2, sizeof(buf2), dt, NULL);
3291+ tcc_error("cannot convert '%s' to '%s'", buf1, buf2);
3292+}
3293+
32963294 /* verify type compatibility to store vtop in 'dt' type */
32973295 static void verify_assign_cast(CType *dt)
32983296 {
32993297 CType *st, *type1, *type2;
3300− char buf1[256], buf2[256];
33013298 int dbt, sbt, qualwarn, lvl;
33023299
33033300 st = &vtop->type; /* source type */
33043301 dbt = dt->t & VT_BTYPE;
33053302 sbt = st->t & VT_BTYPE;
3306− if (sbt == VT_VOID || dbt == VT_VOID) {
3307− if (sbt == VT_VOID && dbt == VT_VOID)
3308− ; /* It is Ok if both are void */
3309− else
3310− tcc_error("cannot cast from/to void");
3311− }
33123303 if (dt->t & VT_CONSTANT)
33133304 tcc_warning("assignment of read-only location");
33143305 switch(dbt) {
3306+ case VT_VOID:
3307+ if (sbt != dbt)
3308+ tcc_error("assignment to void expression");
3309+ break;
33153310 case VT_PTR:
33163311 /* special cases for pointers */
33173312 /* '0' can also be a pointer */
@@ -3375,10 +3370,8 @@ static void verify_assign_cast(CType *dt) · 57 unmodified lines
33753370 case VT_STRUCT:
33763371 case_VT_STRUCT:
33773372 if (!is_compatible_unqualified_types(dt, st)) {
3378− error:
3379− type_to_str(buf1, sizeof(buf1), st, NULL);
3380− type_to_str(buf2, sizeof(buf2), dt, NULL);
3381− tcc_error("cannot cast '%s' to '%s'", buf1, buf2);
3373+ error:
3374+ cast_error(st, dt);
33823375 }
33833376 break;
33843377 }
@@ -3495,7 +3488,7 @@ ST_FUNC void vstore(void) · 110 unmodified lines
34953488 if ((vtop->r & VT_MUSTCAST)
34963489 && btype_size(dbt) > btype_size(sbt)
34973490 )
3498− force_charshort_cast(dbt);
3491+ force_charshort_cast();
34993492 delayed_cast = 1;
35003493 } else {
35013494 gen_cast(&vtop[-1].type);
@@ -3512,7 +3505,7 @@ ST_FUNC void vstore(void) · 10 unmodified lines
35123505 gv(RC_TYPE(dbt)); /* generate value */
35133506
35143507 if (delayed_cast) {
3515− vtop->r |= VT_MUSTCAST;
3508+ vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1);
35163509 //tcc_warning("deley cast %x -> %x", sbt, dbt);
35173510 vtop->type.t = ft & VT_TYPE;
35183511 }
@@ -3521,7 +3514,7 @@ ST_FUNC void vstore(void) · 2 unmodified lines
35213514 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
35223515 SValue sv;
35233516 r = get_reg(RC_INT);
3524− sv.type.t = ptrdiff_type.t;
3517+ sv.type.t = VT_PTRDIFF_T;
35253518 sv.r = VT_LOCAL | VT_LVAL;
35263519 sv.c.i = vtop[-1].c.i;
35273520 load(r, &sv);
@@ -3532,12 +3525,12 @@ ST_FUNC void vstore(void) · 4 unmodified lines
35323525 /* two word case handling :
35333526 store second register at word + 4 (or +8 for x86-64) */
35343527 if (USING_TWO_WORDS(dbt)) {
3535− int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : ptrdiff_type.t;
3528+ int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T;
35363529 vtop[-1].type.t = load_type;
35373530 store(r, vtop - 1);
35383531 vswap();
35393532 /* convert to int to increment easily */
3540− vtop->type.t = ptrdiff_type.t;
3533+ vtop->type.t = VT_PTRDIFF_T;
35413534 gaddrof();
35423535 vpushs(PTR_SIZE);
35433536 gen_op('+');
@@ -4861,6 +4854,8 @@ static void gfunc_param_typed(Sym *func, Sym *arg) · 1317 unmodified lines
48614854 type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
48624855 type.ref = vtop->type.ref;
48634856 gen_cast(&type);
4857+ } else if (vtop->r & VT_MUSTCAST) {
4858+ force_charshort_cast();
48644859 }
48654860 } else if (arg == NULL) {
48664861 tcc_error("too many arguments to function");
@@ -5094,16 +5089,7 @@ ST_FUNC void unary(void) · 227 unmodified lines
50945089 case '!':
50955090 next();
50965091 unary();
5097− if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5098− gen_cast_s(VT_BOOL);
5099− vtop->c.i = !vtop->c.i;
5100− } else if (vtop->r == VT_CMP) {
5101− vtop->cmp_op ^= 1;
5102− n = vtop->jfalse, vtop->jfalse = vtop->jtrue, vtop->jtrue = n;
5103− } else {
5104− vpushi(0);
5105− gen_op(TOK_EQ);
5106− }
5092+ gen_test_zero(TOK_EQ);
51075093 break;
51085094 case '~':
51095095 next();
@@ -6491,17 +6477,23 @@ again: · 1381 unmodified lines
64916477 next();
64926478
64936479 } else if (t == TOK_RETURN) {
6494− a = tok != ';';
64956480 b = (func_vt.t & VT_BTYPE) != VT_VOID;
6496− if (a)
6497− gexpr(), gen_assign_cast(&func_vt);
6481+ if (tok != ';') {
6482+ gexpr();
6483+ if (b) {
6484+ gen_assign_cast(&func_vt);
6485+ } else {
6486+ if (vtop->type.t != VT_VOID)
6487+ tcc_warning("void function returns a value");
6488+ vtop--;
6489+ }
6490+ } else if (b) {
6491+ tcc_warning("'return' with no value");
6492+ b = 0;
6493+ }
64986494 leave_scope(root_scope);
6499− if (a && b)
6495+ if (b)
65006496 gfunc_return(&func_vt);
6501− else if (a)
6502− vtop--;
6503− else if (b)
6504− tcc_warning("'return' with no value.");
65056497 skip(';');
65066498 /* jump unless last stmt in top-level block */
65076499 if (tok != '}' || local_scope != 1)
tests/Makefile+1−0
@@ -269,6 +269,7 @@ cross-test : · 268 unmodified lines
269269 $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
270270 $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"
271271 $(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
272+ $(TOP)/riscv64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
272273 $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
273274 $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
274275 $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
tests/tcctest.c+52−6
@@ -16,6 +16,10 @@ · 15 unmodified lines
1616
1717 #endif
1818
19+#ifndef __TINYC__
20+typedef __SIZE_TYPE__ uintptr_t;
21+#endif
22+
1923 #if defined(_WIN32)
2024 #define LONG_LONG_FORMAT "%lld"
2125 #define ULONG_LONG_FORMAT "%llu"
@@ -1163,7 +1167,7 @@ void struct_test() · 1141 unmodified lines
11631167 s->f3 = 1;
11641168 printf("st2: %d %d %d\n",
11651169 s->f1, s->f2, s->f3);
1166− printf("str_addr=%x\n", (int)st1.str - (int)&st1.f1);
1170+ printf("str_addr=%x\n", (int)(uintptr_t)st1.str - (int)(uintptr_t)&st1.f1);
11671171
11681172 /* align / size tests */
11691173 printf("aligntest1 sizeof=%d alignof=%d\n",
@@ -1203,10 +1207,17 @@ void struct_test() · 33 unmodified lines
12031207 printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls));
12041208 }
12051209
1210+/* simulate char/short return value with undefined upper bits */
1211+static int __csf(int x) { return x; }
1212+static void *_csf = __csf;
1213+#define csf(t,n) ((t(*)(int))_csf)(n)
1214+
12061215 /* XXX: depend on endianness */
12071216 void char_short_test()
12081217 {
12091218 int var1, var2;
1219+ char var3;
1220+ long long var4;
12101221
12111222 printf("char_short:\n");
12121223
@@ -1230,6 +1241,34 @@ void char_short_test() · 17 unmodified lines
12301241 printf("var1=%x\n", var1);
12311242 *(int *)&var1 = 0x08090a0b;
12321243 printf("var1=%x\n", var1);
1244+
1245+ var1 = 0x778899aa;
1246+ var4 = 0x11223344aa998877ULL;
1247+ var1 = var3 = var1 + 1;
1248+ var4 = var3 = var4 + 1;
1249+ printf("promote char/short assign %d "LONG_LONG_FORMAT"\n", var1, var4);
1250+ var1 = 0x778899aa;
1251+ var4 = 0x11223344aa998877ULL;
1252+ printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);
1253+ printf("promote char/short cast VA %d %d\n", (char)(var1 + 1), (char)(var4 + 1));
1254+ var1 = csf(unsigned char,0x89898989);
1255+ var4 = csf(char,0xabababab);
1256+ printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);
1257+ printf("promote char/short fumcret VA %d %d %d %d\n",
1258+ csf(unsigned short,0xcdcdcdcd),
1259+ csf(short,0xefefefef),
1260+ csf(_Bool,0x33221100),
1261+ csf(_Bool,0x33221101));
1262+ var3 = -10;
1263+ var1 = (char)(unsigned char)(var3 + 1);
1264+ var4 = (char)(unsigned char)(var3 + 1);
1265+ printf("promote multicast (char)(unsigned char) %d "LONG_LONG_FORMAT"\n", var1, var4);
1266+ var4 = 0x11223344aa998877ULL;
1267+ var4 = (unsigned)(int)(var4 + 1);
1268+ printf("promote multicast (unsigned)(int) "LONG_LONG_FORMAT"\n", var4);
1269+ var4 = 0x11223344bbaa9988ULL;
1270+ var4 = (unsigned)(char)(var4 + 1);
1271+ printf("promote multicast (unsigned)(char) "LONG_LONG_FORMAT"\n", var4);
12331272 }
12341273
12351274 /******************/
@@ -1679,6 +1718,10 @@ void cast_test() · 443 unmodified lines
16791718 printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));
16801719 printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));
16811720
1721+#ifdef __TINYC__
1722+# pragma comment(option, "-w")
1723+#endif
1724+
16821725 /* from pointer to integer types */
16831726 printf("%d %d %ld %ld %lld %lld\n",
16841727 (int)p, (unsigned int)p,
@@ -1689,6 +1732,10 @@ void cast_test() · 4 unmodified lines
16891732 printf("%p %p %p %p\n",
16901733 (void *)a, (void *)b, (void *)c, (void *)d);
16911734
1735+#ifdef __TINYC__
1736+# pragma comment(option, "-W")
1737+#endif
1738+
16921739 /* int to int with sign set */
16931740 printf("0x%lx\n", (unsigned long)(int)ul);
16941741 }
@@ -2347,7 +2394,7 @@ void funcptr_test() · 652 unmodified lines
23472394
23482395 /* Check that we can align functions */
23492396 func = aligned_function;
2350− printf("aligned_function (should be zero): %d\n", ((int)func) & 15);
2397+ printf("aligned_function (should be zero): %d\n", ((int)(uintptr_t)func) & 15);
23512398 }
23522399
23532400 void lloptest(long long a, long long b)
@@ -2549,6 +2596,9 @@ void longlong_test(void) · 195 unmodified lines
25492596 unsigned long long u = 0x8000000000000001ULL;
25502597 u = (unsigned)(u + 1);
25512598 printf("long long u=" ULONG_LONG_FORMAT "\n", u);
2599+ u = 0x11223344aa998877ULL;
2600+ u = (unsigned)(int)(u + 1);
2601+ printf("long long u=" ULONG_LONG_FORMAT "\n", u);
25522602
25532603 /* was a problem with missing save_regs in gen_opl on 32-bit platforms */
25542604 char cc = 78;
@@ -2897,10 +2947,6 @@ void c99_vla_test(int size1, int size2) · 342 unmodified lines
28972947 #endif
28982948 }
28992949
2900−#ifndef __TINYC__
2901−typedef __SIZE_TYPE__ uintptr_t;
2902−#endif
2903−
29042950 void sizeof_test(void)
29052951 {
29062952 int a;
tests/tests2/88_codeopt.c+1−1
@@ -1,7 +1,7 @@
11 /* Check some way in where code suppression caused various
22 miscompilations. */
33 extern int printf (const char *, ...);
4−typedef unsigned long size_t;
4+typedef __SIZE_TYPE__ size_t;
55
66 size_t _brk_start, _brk_end;
77 void * extend_brk(size_t size, size_t align)
tests/tests2/96_nodata_wanted.expect+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
99
1010 [test_local_data_noerror]
1111 96_nodata_wanted.c:25: warning: assignment makes integer from pointer without a cast
12−96_nodata_wanted.c:25: warning: nonportable conversion from pointer to char/short
12+96_nodata_wanted.c:25: warning: cast between pointer and integer of different size
1313
1414 [test_data_suppression_off]
1515 data:
x86_64-gen.c+25−5
@@ -524,7 +524,7 @@ void load(int r, SValue *sv) · 523 unmodified lines
524524 o(0xf024);
525525 o(0xf02444dd); /* fldl -0x10(%rsp) */
526526 } else {
527− orex(1,r,v, 0x89);
527+ orex(is64_type(ft), r, v, 0x89);
528528 o(0xc0 + REG_VALUE(r) + REG_VALUE(v) * 8); /* mov v, r */
529529 }
530530 }
@@ -598,16 +598,13 @@ void store(int r, SValue *v) · 67 unmodified lines
598598 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
599599 gen_modrm64(op64, r, v->r, v->sym, fc);
600600 } else if (fr != r) {
601− /* XXX: don't we really come here? */
602− abort();
601+ orex(1, fr, r, op64);
603602 o(0xc0 + fr + r * 8); /* mov r, fr */
604603 }
605604 } else {
606605 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
607606 gen_modrm(r, v->r, v->sym, fc);
608607 } else if (fr != r) {
609− /* XXX: don't we really come here? */
610− abort();
611608 o(0xc0 + fr + r * 8); /* mov r, fr */
612609 }
613610 }
@@ -2248,6 +2245,29 @@ void gen_cvt_ftoi(int t) · 1634 unmodified lines
22482245 vtop->r = r;
22492246 }
22502247
2248+// Generate sign extension from 32 to 64 bits:
2249+ST_FUNC void gen_cvt_sxtw(void)
2250+{
2251+ int r = gv(RC_INT);
2252+ /* x86_64 specific: movslq */
2253+ o(0x6348);
2254+ o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
2255+}
2256+
2257+/* char/short to int conversion */
2258+ST_FUNC void gen_cvt_csti(int t)
2259+{
2260+ int r, sz, xl, ll;
2261+ r = gv(RC_INT);
2262+ sz = !(t & VT_UNSIGNED);
2263+ xl = (t & VT_BTYPE) == VT_SHORT;
2264+ ll = (vtop->type.t & VT_BTYPE) == VT_LLONG;
2265+ orex(ll, r, 0, 0xc0b60f /* mov[sz] %a[xl], %eax */
2266+ | (sz << 3 | xl) << 8
2267+ | (REG_VALUE(r) << 3 | REG_VALUE(r)) << 16
2268+ );
2269+}
2270+
22512271 /* computed goto support */
22522272 void ggoto(void)
22532273 {

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