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
1718 o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)1718 o(0x93407c00 | r | r << 5); // sxtw x(r),w(r)
1719}1719}
1720 1720
1721/* char/short to int conversion */
1722ST_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
1721ST_FUNC void gen_cvt_itof(int t)1731ST_FUNC void gen_cvt_itof(int t)
1722{1732{
1723 if (t == VT_LDOUBLE) {1733 if (t == VT_LDOUBLE) {
i386-gen.c+13−0
@@ -1048,6 +1048,19 @@ ST_FUNC void gen_cvt_ftof(int t) · 1047 unmodified lines
1048 gv(RC_FLOAT);1048 gv(RC_FLOAT);
1049}1049}
1050 1050
1051/* char/short to int conversion */
1052ST_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
1051/* computed goto support */1064/* computed goto support */
1052ST_FUNC void ggoto(void)1065ST_FUNC void ggoto(void)
1053{1066{
libtcc.c+2−1
@@ -1965,7 +1965,8 @@ reparse: · 1964 unmodified lines
1965 }1965 }
1966 break;1966 break;
1967 case TCC_OPTION_W:1967 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)
1969 goto unsupported_option;1970 goto unsupported_option;
1970 break;1971 break;
1971 case TCC_OPTION_w:1972 case TCC_OPTION_w:
tcc.h+15−5
@@ -926,9 +926,9 @@ struct filespec { · 925 unmodified lines
926#define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */926#define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */
927#define VT_LVAL 0x0100 /* var is an lvalue */927#define VT_LVAL 0x0100 /* var is an lvalue */
928#define VT_SYM 0x0200 /* a symbol value is added */928#define VT_SYM 0x0200 /* a symbol value is added */
929#define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for929#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
930 char/short stored in integer registers) */930 char/short stored in integer registers) */
931#define VT_MUSTBOUND 0x0800 /* bound checking must be done before931#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
932 dereferencing value */932 dereferencing value */
933#define VT_BOUNDED 0x8000 /* value is bounded. The address of the933#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
934 bounding function call point is in vc */934 bounding function call point is in vc */
@@ -986,6 +986,11 @@ struct filespec { · 51 unmodified lines
986#define VT_ASM (VT_VOID | VT_UNSIGNED)986#define VT_ASM (VT_VOID | VT_UNSIGNED)
987#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)987#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
988 988
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
989/* token values */994/* token values */
990 995
991/* warning: the following compare tokens depend on i386 asm code */996/* warning: the following compare tokens depend on i386 asm code */
@@ -1359,7 +1364,7 @@ ST_DATA Sym *local_stack; · 367 unmodified lines
1359ST_DATA Sym *local_label_stack;1364ST_DATA Sym *local_label_stack;
1360ST_DATA Sym *global_label_stack;1365ST_DATA Sym *global_label_stack;
1361ST_DATA Sym *define_stack;1366ST_DATA Sym *define_stack;
1362ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;1367ST_DATA CType int_type, func_old_type, char_pointer_type;
1363ST_DATA SValue *vtop;1368ST_DATA SValue *vtop;
1364ST_DATA int rsym, anon_sym, ind, loc;1369ST_DATA int rsym, anon_sym, ind, loc;
1365 1370
@@ -1598,6 +1603,7 @@ ST_FUNC void gen_le16(int c); · 232 unmodified lines
1598ST_FUNC void gen_le32(int c);1603ST_FUNC void gen_le32(int c);
1599ST_FUNC void gen_addr32(int r, Sym *sym, int c);1604ST_FUNC void gen_addr32(int r, Sym *sym, int c);
1600ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);1605ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
1606ST_FUNC void gen_cvt_csti(int t);
1601#endif1607#endif
1602 1608
1603#ifdef CONFIG_TCC_BCHECK1609#ifdef CONFIG_TCC_BCHECK
@@ -1612,6 +1618,8 @@ ST_FUNC void gen_opl(int op); · 8 unmodified lines
1612#ifdef TCC_TARGET_PE1618#ifdef TCC_TARGET_PE
1613ST_FUNC void gen_vla_result(int addr);1619ST_FUNC void gen_vla_result(int addr);
1614#endif1620#endif
1621ST_FUNC void gen_cvt_sxtw(void);
1622ST_FUNC void gen_cvt_csti(int t);
1615#endif1623#endif
1616 1624
1617/* ------------ arm-gen.c ------------ */1625/* ------------ arm-gen.c ------------ */
@@ -1624,22 +1632,24 @@ ST_FUNC void arm_init(struct TCCState *s); · 6 unmodified lines
1624 1632
1625/* ------------ arm64-gen.c ------------ */1633/* ------------ arm64-gen.c ------------ */
1626#ifdef TCC_TARGET_ARM641634#ifdef TCC_TARGET_ARM64
1627ST_FUNC void gen_cvt_sxtw(void);
1628ST_FUNC void gen_opl(int op);1635ST_FUNC void gen_opl(int op);
1629ST_FUNC void gfunc_return(CType *func_type);1636ST_FUNC void gfunc_return(CType *func_type);
1630ST_FUNC void gen_va_start(void);1637ST_FUNC void gen_va_start(void);
1631ST_FUNC void gen_va_arg(CType *t);1638ST_FUNC void gen_va_arg(CType *t);
1632ST_FUNC void gen_clear_cache(void);1639ST_FUNC void gen_clear_cache(void);
1640ST_FUNC void gen_cvt_sxtw(void);
1641ST_FUNC void gen_cvt_csti(int t);
1633#endif1642#endif
1634 1643
1635/* ------------ riscv64-gen.c ------------ */1644/* ------------ riscv64-gen.c ------------ */
1636#ifdef TCC_TARGET_RISCV641645#ifdef TCC_TARGET_RISCV64
1637ST_FUNC void gen_cvt_sxtw(void);
1638ST_FUNC void gen_opl(int op);1646ST_FUNC void gen_opl(int op);
1639//ST_FUNC void gfunc_return(CType *func_type);1647//ST_FUNC void gfunc_return(CType *func_type);
1640ST_FUNC void gen_va_start(void);1648ST_FUNC void gen_va_start(void);
1641ST_FUNC void arch_transfer_ret_regs(int);1649ST_FUNC void arch_transfer_ret_regs(int);
1650ST_FUNC void gen_cvt_sxtw(void);
1642#endif1651#endif
1652
1643/* ------------ c67-gen.c ------------ */1653/* ------------ c67-gen.c ------------ */
1644#ifdef TCC_TARGET_C671654#ifdef TCC_TARGET_C67
1645#endif1655#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
79ST_DATA int func_vc;79ST_DATA int func_vc;
80static int last_line_num, new_file, func_ind; /* debug info control */80static int last_line_num, new_file, func_ind; /* debug info control */
81ST_DATA const char *funcname;81ST_DATA const char *funcname;
82ST_DATA CType int_type, func_old_type, char_pointer_type;
82 83
83ST_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
84 94
85ST_DATA struct switch_t {95ST_DATA struct switch_t {
86 struct case_t {96 struct case_t {
@@ -149,6 +159,7 @@ static void skip_or_save_block(TokenString **str); · 62 unmodified lines
149static void gv_dup(void);159static void gv_dup(void);
150static int get_temp_local_var(int size,int align);160static int get_temp_local_var(int size,int align);
151static void clear_temp_local_var_list();161static void clear_temp_local_var_list();
162static void cast_error(CType *st, CType *dt);
152 163
153ST_INLN int is_float(int t)164ST_INLN int is_float(int t)
154{165{
@@ -162,6 +173,7 @@ ST_INLN int is_float(int t) · 7 unmodified lines
162static inline int is_integer_btype(int bt)173static inline int is_integer_btype(int bt)
163{174{
164 return bt == VT_BYTE175 return bt == VT_BYTE
176 || bt == VT_BOOL
165 || bt == VT_SHORT177 || bt == VT_SHORT
166 || bt == VT_INT178 || bt == VT_INT
167 || bt == VT_LLONG;179 || bt == VT_LLONG;
@@ -439,16 +451,6 @@ ST_FUNC void tccgen_init(TCCState *s1) · 271 unmodified lines
439 int_type.t = VT_INT;451 int_type.t = VT_INT;
440 char_pointer_type.t = VT_BYTE;452 char_pointer_type.t = VT_BYTE;
441 mk_pointer(&char_pointer_type);453 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
452 func_old_type.t = VT_FUNC;454 func_old_type.t = VT_FUNC;
453 func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);455 func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
454 func_old_type.ref->f.func_call = FUNC_CDECL;456 func_old_type.ref->f.func_call = FUNC_CDECL;
@@ -922,36 +924,32 @@ ST_FUNC void vpop(void) · 467 unmodified lines
922}924}
923 925
924/* push constant of type "type" with useless value */926/* push constant of type "type" with useless value */
925ST_FUNC void vpush(CType *type)927static void vpush(CType *type)
926{928{
927 vset(type, VT_CONST, 0);929 vset(type, VT_CONST, 0);
928}930}
929 931
930/* push integer constant */932/* push arbitrary 64bit constant */
931ST_FUNC void vpushi(int v)933static void vpush64(int ty, unsigned long long v)
932{934{
933 CValue cval;935 CValue cval;
936 CType ctype;
937 ctype.t = ty;
938 ctype.ref = NULL;
934 cval.i = v;939 cval.i = v;
935 vsetc(&int_type, VT_CONST, &cval);940 vsetc(&ctype, VT_CONST, &cval);
936}941}
937 942
938/* push a pointer sized constant */943/* push integer constant */
939static void vpushs(addr_t v)944ST_FUNC void vpushi(int v)
940{945{
941 CValue cval;946 vpush64(VT_INT, v);
942 cval.i = v;
943 vsetc(&size_type, VT_CONST, &cval);
944}947}
945 948
946/* push arbitrary 64bit constant */949/* push a pointer sized constant */
947ST_FUNC void vpush64(int ty, unsigned long long v)950static void vpushs(addr_t v)
948{951{
949 CValue cval;952 vpush64(VT_SIZE_T, v);
950 CType ctype;
951 ctype.t = ty;
952 ctype.ref = NULL;
953 cval.i = v;
954 vsetc(&ctype, VT_CONST, &cval);
955}953}
956 954
957/* push long long constant */955/* push long long constant */
@@ -963,7 +961,6 @@ static inline void vpushll(long long v) · 5 unmodified lines
963ST_FUNC void vset(CType *type, int r, int v)961ST_FUNC void vset(CType *type, int r, int v)
964{962{
965 CValue cval;963 CValue cval;
966
967 cval.i = v;964 cval.i = v;
968 vsetc(type, r, &cval);965 vsetc(type, r, &cval);
969}966}
@@ -1099,6 +1096,23 @@ static int gvtst(int inv, int t) · 129 unmodified lines
1099 return t;1096 return t;
1100}1097}
1101 1098
1099/* generate a zero or nozero test */
1100static 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
1102/* ------------------------------------------------------------------------- */1116/* ------------------------------------------------------------------------- */
1103/* push a symbol value of TYPE */1117/* push a symbol value of TYPE */
1104static inline void vpushsym(CType *type, Sym *sym)1118static inline void vpushsym(CType *type, Sym *sym)
@@ -1350,44 +1364,34 @@ ST_FUNC void save_reg(int r) · 245 unmodified lines
1350 if seen up to (vtop - n) stack entry */1364 if seen up to (vtop - n) stack entry */
1351ST_FUNC void save_reg_upstack(int r, int n)1365ST_FUNC void save_reg_upstack(int r, int n)
1352{1366{
1353 int l, saved, size, align;1367 int l, size, align, bt;
1354 SValue *p, *p1, sv;1368 SValue *p, *p1, sv;
1355 CType *type;
1356 1369
1357 if ((r &= VT_VALMASK) >= VT_CONST)1370 if ((r &= VT_VALMASK) >= VT_CONST)
1358 return;1371 return;
1359 if (nocode_wanted)1372 if (nocode_wanted)
1360 return;1373 return;
1361
1362 /* modify all stack values */
1363 saved = 0;
1364 l = 0;1374 l = 0;
1365 for(p = vstack, p1 = vtop - n; p <= p1; p++) {1375 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) {
1367 /* must save value on stack if not already done */1377 /* must save value on stack if not already done */
1368 if (!saved) {1378 if (!l) {
1369 /* NOTE: must reload 'r' because r might be equal to r2 */1379 bt = p->type.t & VT_BTYPE;
1370 r = p->r & VT_VALMASK;1380 if (bt == VT_VOID)
1371 /* store register in the stack */1381 continue;
1372 type = &p->type;1382 if ((p->r & VT_LVAL) || bt == VT_FUNC)
1373 if ((p->r & VT_LVAL) ||1383 bt = VT_PTR;
1374 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))1384 sv.type.t = bt;
1375#if PTR_SIZE == 81385 size = type_size(&sv.type, &align);
1376 type = &char_pointer_type;
1377#else
1378 type = &int_type;
1379#endif
1380 size = type_size(type, &align);
1381#ifdef CONFIG_TCC_BCHECK1386#ifdef CONFIG_TCC_BCHECK
1382 if (tcc_state->do_bounds_check)1387 if (tcc_state->do_bounds_check)
1383 l = loc = (loc - size) & -align;1388 l = loc = (loc - size) & -align;
1384 else1389 else
1385#endif1390#endif
1386 l=get_temp_local_var(size,align);1391 l = get_temp_local_var(size,align);
1387 sv.type.t = type->t;
1388 sv.r = VT_LOCAL | VT_LVAL;1392 sv.r = VT_LOCAL | VT_LVAL;
1389 sv.c.i = l;1393 sv.c.i = l;
1390 store(r, &sv);1394 store(p->r & VT_VALMASK, &sv);
1391#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)1395#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1392 /* x86 specific: need to pop fp register ST0 if saved */1396 /* x86 specific: need to pop fp register ST0 if saved */
1393 if (r == TREG_ST0) {1397 if (r == TREG_ST0) {
@@ -1395,11 +1399,10 @@ ST_FUNC void save_reg_upstack(int r, int n) · 1 unmodified line
1395 }1399 }
1396#endif1400#endif
1397 /* special long long case */1401 /* 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)) {
1399 sv.c.i += PTR_SIZE;1403 sv.c.i += PTR_SIZE;
1400 store(p->r2, &sv);1404 store(p->r2, &sv);
1401 }1405 }
1402 saved = 1;
1403 }1406 }
1404 /* mark that stack entry as being saved on the stack */1407 /* mark that stack entry as being saved on the stack */
1405 if (p->r & VT_LVAL) {1408 if (p->r & VT_LVAL) {
@@ -1771,7 +1774,7 @@ ST_FUNC int gv(int rc) · 365 unmodified lines
1771 if (!r_ok)1774 if (!r_ok)
1772 r = get_reg(rc);1775 r = get_reg(rc);
1773 if (rc2) {1776 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;
1775 int original_type = vtop->type.t;1778 int original_type = vtop->type.t;
1776 1779
1777 /* two register type load :1780 /* two register type load :
@@ -1793,9 +1796,9 @@ ST_FUNC int gv(int rc) · 15 unmodified lines
1793 vdup();1796 vdup();
1794 vtop[-1].r = r; /* save register value */1797 vtop[-1].r = r; /* save register value */
1795 /* increment pointer to get second word */1798 /* increment pointer to get second word */
1796 vtop->type.t = ptrdiff_type.t;1799 vtop->type.t = VT_PTRDIFF_T;
1797 gaddrof();1800 gaddrof();
1798 vpushi(PTR_SIZE);1801 vpushs(PTR_SIZE);
1799 gen_op('+');1802 gen_op('+');
1800 vtop->r |= VT_LVAL;1803 vtop->r |= VT_LVAL;
1801 vtop->type.t = load_type;1804 vtop->type.t = load_type;
@@ -2521,7 +2524,7 @@ redo: · 719 unmodified lines
2521 }2524 }
2522 vrott(3);2525 vrott(3);
2523 gen_opic(op);2526 gen_opic(op);
2524 vtop->type.t = ptrdiff_type.t;2527 vtop->type.t = VT_PTRDIFF_T;
2525 vswap();2528 vswap();
2526 gen_op(TOK_PDIV);2529 gen_op(TOK_PDIV);
2527 } else {2530 } else {
@@ -2712,41 +2715,17 @@ static void gen_cvt_ftoi1(int t) · 184 unmodified lines
2712}2715}
2713#endif2716#endif
2714 2717
2715/* force char or short cast */2718/* special delayed cast for char/short */
2716static void force_charshort_cast(int t)2719static void force_charshort_cast(void)
2717{2720{
2718 int bits, dbt;2721 int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT;
2719 2722 int dbt = vtop->type.t;
2720 /* cannot cast static initializers */2723 vtop->r &= ~VT_MUSTCAST;
2721 if (STATIC_DATA_WANTED)2724 vtop->type.t = sbt;
2722 return;2725 gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt);
2723 2726 vtop->type.t = dbt;
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 }
2747}2727}
2748 2728
2749/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
2750static void gen_cast_s(int t)2729static void gen_cast_s(int t)
2751{2730{
2752 CType type;2731 CType type;
@@ -2755,31 +2734,33 @@ static void gen_cast_s(int t) · 2 unmodified lines
2755 gen_cast(&type);2734 gen_cast(&type);
2756}2735}
2757 2736
2737/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
2758static void gen_cast(CType *type)2738static void gen_cast(CType *type)
2759{2739{
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;
2761 2742
2762 /* special delayed cast for char/short */2743 /* special delayed cast for char/short */
2763 /* XXX: in some cases (multiple cascaded casts), it may still2744 if (vtop->r & VT_MUSTCAST)
2764 be incorrect */2745 force_charshort_cast();
2765 if (vtop->r & VT_MUSTCAST) {
2766 vtop->r &= ~VT_MUSTCAST;
2767 force_charshort_cast(vtop->type.t);
2768 }
2769 2746
2770 /* bitfields first get cast to ints */2747 /* bitfields first get cast to ints */
2771 if (vtop->type.t & VT_BITFIELD) {2748 if (vtop->type.t & VT_BITFIELD)
2772 gv(RC_INT);2749 gv(RC_INT);
2773 }
2774 2750
2775 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);2751 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
2776 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);2752 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
2753 if (sbt == VT_FUNC)
2754 sbt = VT_PTR;
2777 2755
2756again:
2778 if (sbt != dbt) {2757 if (sbt != dbt) {
2779 sf = is_float(sbt);2758 sf = is_float(sbt);
2780 df = is_float(dbt);2759 df = is_float(dbt);
2760 dbt_bt = dbt & VT_BTYPE;
2761 sbt_bt = sbt & VT_BTYPE;
2762
2781 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;2763 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);
2783#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_3872764#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387
2784 c &= (dbt != VT_LDOUBLE) | !!nocode_wanted;2765 c &= (dbt != VT_LDOUBLE) | !!nocode_wanted;
2785#endif2766#endif
@@ -2792,7 +2773,7 @@ static void gen_cast(CType *type) · 6 unmodified lines
2792 vtop->c.ld = vtop->c.d;2773 vtop->c.ld = vtop->c.d;
2793 2774
2794 if (df) {2775 if (df) {
2795 if ((sbt & VT_BTYPE) == VT_LLONG) {2776 if (sbt_bt == VT_LLONG) {
2796 if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63))2777 if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63))
2797 vtop->c.ld = vtop->c.i;2778 vtop->c.ld = vtop->c.i;
2798 else2779 else
@@ -2808,164 +2789,173 @@ static void gen_cast(CType *type) · 9 unmodified lines
2808 vtop->c.f = (float)vtop->c.ld;2789 vtop->c.f = (float)vtop->c.ld;
2809 else if (dbt == VT_DOUBLE)2790 else if (dbt == VT_DOUBLE)
2810 vtop->c.d = (double)vtop->c.ld;2791 vtop->c.d = (double)vtop->c.ld;
2811 } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
2812 vtop->c.i = vtop->c.ld;
2813 } else if (sf && dbt == VT_BOOL) {2792 } else if (sf && dbt == VT_BOOL) {
2814 vtop->c.i = (vtop->c.ld != 0);2793 vtop->c.i = (vtop->c.ld != 0);
2815 } else {2794 } else {
2816 if(sf)2795 if(sf)
2817 vtop->c.i = vtop->c.ld;2796 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))
2819 ;2798 ;
2820 else if (sbt & VT_UNSIGNED)2799 else if (sbt & VT_UNSIGNED)
2821 vtop->c.i = (uint32_t)vtop->c.i;2800 vtop->c.i = (uint32_t)vtop->c.i;
2822#if PTR_SIZE == 82801 else
2823 else if (sbt == VT_PTR)2802 vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000));
2824 ;
2825#endif
2826 else if (sbt != VT_LLONG)
2827 vtop->c.i = ((uint32_t)vtop->c.i |
2828 -(vtop->c.i & 0x80000000));
2829 2803
2830 if (dbt == (VT_LLONG|VT_UNSIGNED))2804 if (dbt_bt == VT_LLONG || (PTR_SIZE == 8 && dbt == VT_PTR))
2831 ;2805 ;
2832 else if (dbt == VT_BOOL)2806 else if (dbt == VT_BOOL)
2833 vtop->c.i = (vtop->c.i != 0);2807 vtop->c.i = (vtop->c.i != 0);
2834#if PTR_SIZE == 82808 else {
2835 else if (dbt == VT_PTR)2809 uint32_t m = dbt_bt == VT_BYTE ? 0xff :
2836 ;2810 dbt_bt == VT_SHORT ? 0xffff :
2837#endif2811 0xffffffff;
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);
2842 vtop->c.i &= m;2812 vtop->c.i &= m;
2843 if (!(dbt & VT_UNSIGNED))2813 if (!(dbt & VT_UNSIGNED))
2844 vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1));2814 vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1));
2845 }2815 }
2846 }2816 }
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) */
2848 vtop->r = VT_CONST;2823 vtop->r = VT_CONST;
2849 vtop->c.i = 1;2824 vtop->c.i = 1;
2850 } else {2825 goto done;
2851 /* non constant case: generate code */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) {
2852 if (sf && df) {2839 if (sf && df) {
2853 /* convert from fp to fp */2840 /* convert from fp to fp */
2854 gen_cvt_ftof(dbt);2841 gen_cvt_ftof(dbt);
2855 } else if (df) {2842 } else if (df) {
2856 /* convert int to fp */2843 /* convert int to fp */
2857 gen_cvt_itof1(dbt);2844 gen_cvt_itof1(dbt);
2858 } else if (sf) {2845 } else {
2859 /* convert fp to int */2846 /* convert fp to int */
2860 if (dbt == VT_BOOL) {2847 sbt = dbt;
2861 vpushi(0);2848 if (dbt_bt != VT_LLONG && dbt_bt != VT_INT)
2862 gen_op(TOK_NE);2849 sbt = VT_INT;
2863 } else {2850 gen_cvt_ftoi1(sbt);
2864 /* we handle char/short/etc... with generic code */2851 goto again; /* may need char/short cast */
2865 if (dbt != (VT_INT | VT_UNSIGNED) &&2852 }
2866 dbt != (VT_LLONG | VT_UNSIGNED) &&2853 goto done;
2867 dbt != VT_LLONG)2854 }
2868 dbt = VT_INT;2855
2869 gen_cvt_ftoi1(dbt);2856 ds = btype_size(dbt_bt);
2870 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {2857 ss = btype_size(sbt_bt);
2871 /* additional cast for char/short... */2858 if (ds == 0 || ss == 0) {
2872 vtop->type.t = dbt;2859 if (dbt_bt == VT_VOID)
2873 gen_cast(type);2860 goto done;
2874 }2861 cast_error(&vtop->type, type);
2875 }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;
2876#if PTR_SIZE == 42895#if PTR_SIZE == 4
2877 } else if ((dbt & VT_BTYPE) == VT_LLONG) {2896 if (ds == 8) {
2878 if ((sbt & VT_BTYPE) != VT_LLONG) {2897 /* generate high word */
2879 /* scalar to long long */2898 if (sbt & VT_UNSIGNED) {
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 */
2935 vpushi(0);2899 vpushi(0);
2936 gen_op(TOK_NE);2900 gv(RC_INT);
2937 } else if ((dbt & VT_BTYPE) == VT_BYTE || 2901 } else {
2938 (dbt & VT_BTYPE) == VT_SHORT) {2902 gv_dup();
2939 if (sbt == VT_PTR) {2903 vpushi(31);
2940 vtop->type.t = VT_INT;2904 gen_op(TOK_SAR);
2941 tcc_warning("nonportable conversion from pointer to char/short");2905 }
2942 }2906 lbuild(dbt);
2943 force_charshort_cast(dbt);2907 } else if (ss == 8) {
2944 } else if ((dbt & VT_BTYPE) == VT_INT) {2908 /* from long long: just take low order word */
2945 /* scalar to int */2909 lexpand();
2946 if ((sbt & VT_BTYPE) == VT_LLONG) {2910 vpop();
2947#if PTR_SIZE == 42911 }
2948 /* from long long: just take low order word */2912 ss = 4;
2949 lexpand();2913
2950 vpop();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;
2951#else2922#else
2952 if (dbt & VT_UNSIGNED) {2923 goto done;
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 }
2961#endif2924#endif
2962 }2925 } else {
2926 gen_cvt_sxtw();
2927 goto done;
2963 }2928 }
2964 if ((vtop->r & VT_LVAL)2929 ss = ds, ds = 4, dbt = sbt;
2965 && (dbt & VT_BTYPE) != (sbt & VT_BTYPE))2930 } else if (ss == 8) {
2966 gv(RC_INT);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;
2967 }2937 }
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);
2968 }2957 }
2958done:
2969 vtop->type = *type;2959 vtop->type = *type;
2970 vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY );2960 vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY );
2971}2961}
@@ -3293,25 +3283,30 @@ static void type_to_str(char *buf, int buf_size, · 321 unmodified lines
3293 no_var: ;3283 no_var: ;
3294}3284}
3295 3285
3286static 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
3296/* verify type compatibility to store vtop in 'dt' type */3294/* verify type compatibility to store vtop in 'dt' type */
3297static void verify_assign_cast(CType *dt)3295static void verify_assign_cast(CType *dt)
3298{3296{
3299 CType *st, *type1, *type2;3297 CType *st, *type1, *type2;
3300 char buf1[256], buf2[256];
3301 int dbt, sbt, qualwarn, lvl;3298 int dbt, sbt, qualwarn, lvl;
3302 3299
3303 st = &vtop->type; /* source type */3300 st = &vtop->type; /* source type */
3304 dbt = dt->t & VT_BTYPE;3301 dbt = dt->t & VT_BTYPE;
3305 sbt = st->t & VT_BTYPE;3302 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 }
3312 if (dt->t & VT_CONSTANT)3303 if (dt->t & VT_CONSTANT)
3313 tcc_warning("assignment of read-only location");3304 tcc_warning("assignment of read-only location");
3314 switch(dbt) {3305 switch(dbt) {
3306 case VT_VOID:
3307 if (sbt != dbt)
3308 tcc_error("assignment to void expression");
3309 break;
3315 case VT_PTR:3310 case VT_PTR:
3316 /* special cases for pointers */3311 /* special cases for pointers */
3317 /* '0' can also be a pointer */3312 /* '0' can also be a pointer */
@@ -3375,10 +3370,8 @@ static void verify_assign_cast(CType *dt) · 57 unmodified lines
3375 case VT_STRUCT:3370 case VT_STRUCT:
3376 case_VT_STRUCT:3371 case_VT_STRUCT:
3377 if (!is_compatible_unqualified_types(dt, st)) {3372 if (!is_compatible_unqualified_types(dt, st)) {
3378 error:3373 error:
3379 type_to_str(buf1, sizeof(buf1), st, NULL);3374 cast_error(st, dt);
3380 type_to_str(buf2, sizeof(buf2), dt, NULL);
3381 tcc_error("cannot cast '%s' to '%s'", buf1, buf2);
3382 }3375 }
3383 break;3376 break;
3384 }3377 }
@@ -3495,7 +3488,7 @@ ST_FUNC void vstore(void) · 110 unmodified lines
3495 if ((vtop->r & VT_MUSTCAST)3488 if ((vtop->r & VT_MUSTCAST)
3496 && btype_size(dbt) > btype_size(sbt)3489 && btype_size(dbt) > btype_size(sbt)
3497 )3490 )
3498 force_charshort_cast(dbt);3491 force_charshort_cast();
3499 delayed_cast = 1;3492 delayed_cast = 1;
3500 } else {3493 } else {
3501 gen_cast(&vtop[-1].type);3494 gen_cast(&vtop[-1].type);
@@ -3512,7 +3505,7 @@ ST_FUNC void vstore(void) · 10 unmodified lines
3512 gv(RC_TYPE(dbt)); /* generate value */3505 gv(RC_TYPE(dbt)); /* generate value */
3513 3506
3514 if (delayed_cast) {3507 if (delayed_cast) {
3515 vtop->r |= VT_MUSTCAST;3508 vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1);
3516 //tcc_warning("deley cast %x -> %x", sbt, dbt);3509 //tcc_warning("deley cast %x -> %x", sbt, dbt);
3517 vtop->type.t = ft & VT_TYPE;3510 vtop->type.t = ft & VT_TYPE;
3518 }3511 }
@@ -3521,7 +3514,7 @@ ST_FUNC void vstore(void) · 2 unmodified lines
3521 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {3514 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
3522 SValue sv;3515 SValue sv;
3523 r = get_reg(RC_INT);3516 r = get_reg(RC_INT);
3524 sv.type.t = ptrdiff_type.t;3517 sv.type.t = VT_PTRDIFF_T;
3525 sv.r = VT_LOCAL | VT_LVAL;3518 sv.r = VT_LOCAL | VT_LVAL;
3526 sv.c.i = vtop[-1].c.i;3519 sv.c.i = vtop[-1].c.i;
3527 load(r, &sv);3520 load(r, &sv);
@@ -3532,12 +3525,12 @@ ST_FUNC void vstore(void) · 4 unmodified lines
3532 /* two word case handling :3525 /* two word case handling :
3533 store second register at word + 4 (or +8 for x86-64) */3526 store second register at word + 4 (or +8 for x86-64) */
3534 if (USING_TWO_WORDS(dbt)) {3527 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;
3536 vtop[-1].type.t = load_type;3529 vtop[-1].type.t = load_type;
3537 store(r, vtop - 1);3530 store(r, vtop - 1);
3538 vswap();3531 vswap();
3539 /* convert to int to increment easily */3532 /* convert to int to increment easily */
3540 vtop->type.t = ptrdiff_type.t;3533 vtop->type.t = VT_PTRDIFF_T;
3541 gaddrof();3534 gaddrof();
3542 vpushs(PTR_SIZE);3535 vpushs(PTR_SIZE);
3543 gen_op('+');3536 gen_op('+');
@@ -4861,6 +4854,8 @@ static void gfunc_param_typed(Sym *func, Sym *arg) · 1317 unmodified lines
4861 type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);4854 type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
4862 type.ref = vtop->type.ref;4855 type.ref = vtop->type.ref;
4863 gen_cast(&type);4856 gen_cast(&type);
4857 } else if (vtop->r & VT_MUSTCAST) {
4858 force_charshort_cast();
4864 }4859 }
4865 } else if (arg == NULL) {4860 } else if (arg == NULL) {
4866 tcc_error("too many arguments to function");4861 tcc_error("too many arguments to function");
@@ -5094,16 +5089,7 @@ ST_FUNC void unary(void) · 227 unmodified lines
5094 case '!':5089 case '!':
5095 next();5090 next();
5096 unary();5091 unary();
5097 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {5092 gen_test_zero(TOK_EQ);
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 }
5107 break;5093 break;
5108 case '~':5094 case '~':
5109 next();5095 next();
@@ -6491,17 +6477,23 @@ again: · 1381 unmodified lines
6491 next();6477 next();
6492 6478
6493 } else if (t == TOK_RETURN) {6479 } else if (t == TOK_RETURN) {
6494 a = tok != ';';
6495 b = (func_vt.t & VT_BTYPE) != VT_VOID;6480 b = (func_vt.t & VT_BTYPE) != VT_VOID;
6496 if (a)6481 if (tok != ';') {
6497 gexpr(), gen_assign_cast(&func_vt);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 }
6498 leave_scope(root_scope);6494 leave_scope(root_scope);
6499 if (a && b)6495 if (b)
6500 gfunc_return(&func_vt);6496 gfunc_return(&func_vt);
6501 else if (a)
6502 vtop--;
6503 else if (b)
6504 tcc_warning("'return' with no value.");
6505 skip(';');6497 skip(';');
6506 /* jump unless last stmt in top-level block */6498 /* jump unless last stmt in top-level block */
6507 if (tok != '}' || local_scope != 1)6499 if (tok != '}' || local_scope != 1)
tests/Makefile+1−0
@@ -269,6 +269,7 @@ cross-test : · 268 unmodified lines
269 $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"269 $(TOP)/arm-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
270 $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"270 $(TOP)/arm-wince-tcc$(EXESUF) $(TCCFLAGS-win) -c $(TOPSRC)/examples/ex3.c && echo "ok"
271 $(TOP)/arm64-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"271 $(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"
272 $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"273 $(TOP)/c67-tcc$(EXESUF) $(TCCFLAGS-unx) -c $(TOPSRC)/examples/ex3.c && echo "ok"
273 $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"274 $(TOP)/i386-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"
274 $(TOP)/x86_64-win32-tcc$(EXESUF) $(TCCFLAGS-win) $(TOPSRC)/win32/examples/hello_win.c && echo "ok"275 $(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
16 16
17#endif17#endif
18 18
19#ifndef __TINYC__
20typedef __SIZE_TYPE__ uintptr_t;
21#endif
22
19#if defined(_WIN32)23#if defined(_WIN32)
20#define LONG_LONG_FORMAT "%lld"24#define LONG_LONG_FORMAT "%lld"
21#define ULONG_LONG_FORMAT "%llu"25#define ULONG_LONG_FORMAT "%llu"
@@ -1163,7 +1167,7 @@ void struct_test() · 1141 unmodified lines
1163 s->f3 = 1;1167 s->f3 = 1;
1164 printf("st2: %d %d %d\n",1168 printf("st2: %d %d %d\n",
1165 s->f1, s->f2, s->f3);1169 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);
1167 1171
1168 /* align / size tests */1172 /* align / size tests */
1169 printf("aligntest1 sizeof=%d alignof=%d\n",1173 printf("aligntest1 sizeof=%d alignof=%d\n",
@@ -1203,10 +1207,17 @@ void struct_test() · 33 unmodified lines
1203 printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls));1207 printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls));
1204}1208}
1205 1209
1210/* simulate char/short return value with undefined upper bits */
1211static int __csf(int x) { return x; }
1212static void *_csf = __csf;
1213#define csf(t,n) ((t(*)(int))_csf)(n)
1214
1206/* XXX: depend on endianness */1215/* XXX: depend on endianness */
1207void char_short_test()1216void char_short_test()
1208{1217{
1209 int var1, var2;1218 int var1, var2;
1219 char var3;
1220 long long var4;
1210 1221
1211 printf("char_short:\n");1222 printf("char_short:\n");
1212 1223
@@ -1230,6 +1241,34 @@ void char_short_test() · 17 unmodified lines
1230 printf("var1=%x\n", var1);1241 printf("var1=%x\n", var1);
1231 *(int *)&var1 = 0x08090a0b;1242 *(int *)&var1 = 0x08090a0b;
1232 printf("var1=%x\n", var1);1243 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);
1233}1272}
1234 1273
1235/******************/1274/******************/
@@ -1679,6 +1718,10 @@ void cast_test() · 443 unmodified lines
1679 printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));1718 printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));
1680 printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));1719 printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));
1681 1720
1721#ifdef __TINYC__
1722# pragma comment(option, "-w")
1723#endif
1724
1682 /* from pointer to integer types */1725 /* from pointer to integer types */
1683 printf("%d %d %ld %ld %lld %lld\n",1726 printf("%d %d %ld %ld %lld %lld\n",
1684 (int)p, (unsigned int)p,1727 (int)p, (unsigned int)p,
@@ -1689,6 +1732,10 @@ void cast_test() · 4 unmodified lines
1689 printf("%p %p %p %p\n",1732 printf("%p %p %p %p\n",
1690 (void *)a, (void *)b, (void *)c, (void *)d);1733 (void *)a, (void *)b, (void *)c, (void *)d);
1691 1734
1735#ifdef __TINYC__
1736# pragma comment(option, "-W")
1737#endif
1738
1692 /* int to int with sign set */1739 /* int to int with sign set */
1693 printf("0x%lx\n", (unsigned long)(int)ul);1740 printf("0x%lx\n", (unsigned long)(int)ul);
1694}1741}
@@ -2347,7 +2394,7 @@ void funcptr_test() · 652 unmodified lines
2347 2394
2348 /* Check that we can align functions */2395 /* Check that we can align functions */
2349 func = aligned_function;2396 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);
2351}2398}
2352 2399
2353void lloptest(long long a, long long b)2400void lloptest(long long a, long long b)
@@ -2549,6 +2596,9 @@ void longlong_test(void) · 195 unmodified lines
2549 unsigned long long u = 0x8000000000000001ULL;2596 unsigned long long u = 0x8000000000000001ULL;
2550 u = (unsigned)(u + 1);2597 u = (unsigned)(u + 1);
2551 printf("long long u=" ULONG_LONG_FORMAT "\n", u);2598 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);
2552 2602
2553 /* was a problem with missing save_regs in gen_opl on 32-bit platforms */2603 /* was a problem with missing save_regs in gen_opl on 32-bit platforms */
2554 char cc = 78;2604 char cc = 78;
@@ -2897,10 +2947,6 @@ void c99_vla_test(int size1, int size2) · 342 unmodified lines
2897#endif2947#endif
2898}2948}
2899 2949
2900#ifndef __TINYC__
2901typedef __SIZE_TYPE__ uintptr_t;
2902#endif
2903
2904void sizeof_test(void)2950void sizeof_test(void)
2905{2951{
2906 int a;2952 int a;
tests/tests2/88_codeopt.c+1−1
@@ -1,7 +1,7 @@
1/* Check some way in where code suppression caused various1/* Check some way in where code suppression caused various
2 miscompilations. */2 miscompilations. */
3extern int printf (const char *, ...);3extern int printf (const char *, ...);
4typedef unsigned long size_t;4typedef __SIZE_TYPE__ size_t;
5 5
6size_t _brk_start, _brk_end;6size_t _brk_start, _brk_end;
7void * extend_brk(size_t size, size_t align)7void * extend_brk(size_t size, size_t align)
tests/tests2/96_nodata_wanted.expect+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 9
10[test_local_data_noerror]10[test_local_data_noerror]
1196_nodata_wanted.c:25: warning: assignment makes integer from pointer without a cast1196_nodata_wanted.c:25: warning: assignment makes integer from pointer without a cast
1296_nodata_wanted.c:25: warning: nonportable conversion from pointer to char/short1296_nodata_wanted.c:25: warning: cast between pointer and integer of different size
13 13
14[test_data_suppression_off]14[test_data_suppression_off]
15data:15data:
x86_64-gen.c+25−5
@@ -524,7 +524,7 @@ void load(int r, SValue *sv) · 523 unmodified lines
524 o(0xf024);524 o(0xf024);
525 o(0xf02444dd); /* fldl -0x10(%rsp) */525 o(0xf02444dd); /* fldl -0x10(%rsp) */
526 } else {526 } else {
527 orex(1,r,v, 0x89);527 orex(is64_type(ft), r, v, 0x89);
528 o(0xc0 + REG_VALUE(r) + REG_VALUE(v) * 8); /* mov v, r */528 o(0xc0 + REG_VALUE(r) + REG_VALUE(v) * 8); /* mov v, r */
529 }529 }
530 }530 }
@@ -598,16 +598,13 @@ void store(int r, SValue *v) · 67 unmodified lines
598 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {598 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
599 gen_modrm64(op64, r, v->r, v->sym, fc);599 gen_modrm64(op64, r, v->r, v->sym, fc);
600 } else if (fr != r) {600 } else if (fr != r) {
601 /* XXX: don't we really come here? */601 orex(1, fr, r, op64);
602 abort();
603 o(0xc0 + fr + r * 8); /* mov r, fr */602 o(0xc0 + fr + r * 8); /* mov r, fr */
604 }603 }
605 } else {604 } else {
606 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {605 if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
607 gen_modrm(r, v->r, v->sym, fc);606 gen_modrm(r, v->r, v->sym, fc);
608 } else if (fr != r) {607 } else if (fr != r) {
609 /* XXX: don't we really come here? */
610 abort();
611 o(0xc0 + fr + r * 8); /* mov r, fr */608 o(0xc0 + fr + r * 8); /* mov r, fr */
612 }609 }
613 }610 }
@@ -2248,6 +2245,29 @@ void gen_cvt_ftoi(int t) · 1634 unmodified lines
2248 vtop->r = r;2245 vtop->r = r;
2249}2246}
2250 2247
2248// Generate sign extension from 32 to 64 bits:
2249ST_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 */
2258ST_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
2251/* computed goto support */2271/* computed goto support */
2252void ggoto(void)2272void ggoto(void)
2253{2273{

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