History

reverts (11/2025 - 04/2026)

Revert "Add support to debug libtcc code" - not fully developed experimental feature This reverts commit 1fe3e3bff560b3e6148933687e4a892b695f3a88. This reverts commit 4768b11737bcae47ec8b3a747e05aade5b302495. Revert "tests: add test for x86_64 xor REX prefix bug in load()" - AI generated nonsense test This reverts commit d5ecb52a71e20f0db6dcc99e30510080a87d9af3. Revert "tccpp.c: Improve integer constant overflow warning" - Too long and confusing messages and comments for feature with questionable benefit. This reverts commit 085bdf8997213df03f49258e1184cb7c32ae65bb. riscv64-link: - cleanup "pair pcrel lo relocations by hi address" From fada98b1ce9ee0c36771183177218828ccb9b9de tccgen.c: - Simplify "Cast signed pointer offset to ptrdiff_t before performing arithmetic" From 5ad52cc1ed0f1fbc9781cfac8f59d202ff58738c libtcc.c: - Revert "tcc options: document behavior and clashes (no-op)" a bit more information than one would like to have I think. (why try to understand that comments plus the extra script if one can as well just read the code itself ;) From 234e2dd2bf920e1fdb2deaa4ab549ba85e11e9d7 tccdefs.h: - Revert "Move lib/va_list.c into include/tccdefs.h" Lets not fill tccdefs.h with too much inline code Also, -nostdlib -run is no longer supported From fa6a6bfbbdbe634ec0052b1ee87f2cf3d2b143a4 arm64-gen.c: - cleanup "Implement TOK_NEG for floats natively" Also, make it "no lvalue" in tccgen.c/x86-64-gen.c From c39eaf10cfbe302342902cc7e808469ae7f7ae7c lib/lib-arm64.c: - cleanup "Remove libc dependency from lib-arm64" using unions is much faster than some made up memcpy() From 8c61b91de80ec03e623b71205a11f152fffb5125

grischka committed 6 months ago

Commit d9a6d9a1 parent a66ac6220 files · +188 −712Browse files

Unified · Split

20 files
  1. .gitignore +0 −1
  2. arm64-gen.c +9 −27
  3. include/tccdefs.h +2 −41
  4. lib/Makefile +2 −2
  5. lib/lib-arm64.c +59 −67
  6. lib/va_list.c +67 −0
  7. libtcc.c +5 −63
  8. libtcc.h +0 −12
  9. optclash +0 −38
  10. riscv64-link.c +10 −26
  11. tcc.h +1 −4
  12. tccelf.c +6 −8
  13. tccgen.c +11 −3
  14. tccpp.c +7 −28
  15. tccrun.c +8 −44
  16. tests/Makefile +0 −7
  17. tests/libtcc_debug.c +0 −58
  18. tests/libtcc_test_xor_rex.c +0 −128
  19. tests/nostdlib_test.c +0 −155
  20. x86_64-gen.c +1 −0
.gitignore+0−1
@@ -62,7 +62,6 @@ tests/*-cc* · 61 unmodified lines
62tests/*-tcc*62tests/*-tcc*
63tests/libtcc_test63tests/libtcc_test
64tests/libtcc_test_mt64tests/libtcc_test_mt
65tests/libtcc_test_xor_rex
66tests/asm-c-connect65tests/asm-c-connect
67tests/asm-c-connect-sep66tests/asm-c-connect-sep
68tests/vla_test67tests/vla_test
arm64-gen.c+9−27
@@ -1848,39 +1848,26 @@ ST_FUNC void gen_opl(int op) · 1847 unmodified lines
1848ST_FUNC void gen_opf(int op)1848ST_FUNC void gen_opf(int op)
1849{1849{
1850 uint32_t x, a, b, dbl;1850 uint32_t x, a, b, dbl;
1851 int bt = vtop[0].type.t & VT_BTYPE;
1851 1852
1852 if (op == TOK_NEG) {1853 if (op == TOK_NEG) {
1853 switch (vtop[0].type.t & VT_BTYPE) {1854 if (bt == VT_LDOUBLE) {
1854 case VT_LDOUBLE:
1855 vpush_helper_func(TOK___negtf2);1855 vpush_helper_func(TOK___negtf2);
1856 vrott(2);1856 vrott(2);
1857 gfunc_call(1);1857 gfunc_call(1);
1858 vpushi(0);1858 vpushi(0);
1859 vtop->type.t = VT_LDOUBLE;1859 vtop->type.t = bt;
1860 vtop->r = REG_FRET;1860 vtop->r = REG_FRET;
1861 break;1861 } else {
1862
1863 case VT_FLOAT:
1864 case VT_DOUBLE:
1865 gv(RC_FLOAT);1862 gv(RC_FLOAT);
1866 dbl = (vtop[0].type.t & VT_BTYPE) == VT_DOUBLE;1863 dbl = bt == VT_DOUBLE;
1867
1868 a = fltr(vtop[0].r);1864 a = fltr(vtop[0].r);
1869 vtop--;1865 o(0x1e214000 | dbl << 22 | a | a << 5);
1870 x = get_reg(RC_FLOAT);
1871 vtop++;
1872 vtop[0].r = x;
1873 x = fltr(x);
1874
1875 o(0x1e214000 | dbl << 22 | x | a << 5);
1876 break;
1877 default:
1878 assert(0);
1879 }1866 }
1880 return;1867 return;
1881 }1868 }
1882 1869
1883 if (vtop[0].type.t == VT_LDOUBLE) {1870 if (bt == VT_LDOUBLE) {
1884 CType type = vtop[0].type;1871 CType type = vtop[0].type;
1885 int func = 0;1872 int func = 0;
1886 int cond = -1;1873 int cond = -1;
@@ -1912,7 +1899,7 @@ ST_FUNC void gen_opf(int op) · 25 unmodified lines
1912 return;1899 return;
1913 }1900 }
1914 1901
1915 dbl = vtop[0].type.t != VT_FLOAT;1902 dbl = bt != VT_FLOAT;
1916 gv2(RC_FLOAT, RC_FLOAT);1903 gv2(RC_FLOAT, RC_FLOAT);
1917 assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST);1904 assert(vtop[-1].r < VT_CONST && vtop[0].r < VT_CONST);
1918 a = fltr(vtop[-1].r);1905 a = fltr(vtop[-1].r);
@@ -2075,12 +2062,7 @@ ST_FUNC void gen_cvt_ftof(int t) · 156 unmodified lines
2075 gv(RC_FLOAT);2062 gv(RC_FLOAT);
2076 assert(vtop[0].r < VT_CONST);2063 assert(vtop[0].r < VT_CONST);
2077 a = fltr(vtop[0].r);2064 a = fltr(vtop[0].r);
2078 --vtop;2065 x = a;
2079 x = get_reg(RC_FLOAT);
2080 ++vtop;
2081 vtop[0].r = x;
2082 x = fltr(x);
2083
2084 if (f == VT_FLOAT)2066 if (f == VT_FLOAT)
2085 o(0x1e22c000 | x | a << 5); // fcvt d(x),s(a)2067 o(0x1e22c000 | x | a << 5); // fcvt d(x),s(a)
2086 else2068 else
include/tccdefs.h+2−41
@@ -191,10 +191,7 @@ · 190 unmodified lines
191#if defined __x86_64__191#if defined __x86_64__
192#if !defined _WIN32192#if !defined _WIN32
193 /* GCC compatible definition of va_list. */193 /* GCC compatible definition of va_list. */
194 194 /* This should be in sync with the declaration in our lib/va_list.c */
195 enum __va_arg_type {
196 __va_gen_reg, __va_float_reg, __va_stack
197 };
198 typedef struct {195 typedef struct {
199 unsigned gp_offset, fp_offset;196 unsigned gp_offset, fp_offset;
200 union {197 union {
@@ -204,43 +201,7 @@ · 3 unmodified lines
204 char *reg_save_area;201 char *reg_save_area;
205 } __builtin_va_list[1];202 } __builtin_va_list[1];
206 203
207 static inline void *__va_arg(__builtin_va_list ap, int arg_type,204 void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
208 int size, int align)
209 {
210 size = (size + 7) & ~7;
211 align = (align + 7) & ~7;
212 switch ((enum __va_arg_type)arg_type) {
213 case __va_gen_reg:
214 if (ap->gp_offset + size <= 48) {
215 ap->gp_offset += size;
216 return ap->reg_save_area + ap->gp_offset - size;
217 }
218 goto use_overflow_area;
219 case __va_float_reg:
220 if (ap->fp_offset < 128 + 48) {
221 ap->fp_offset += 16;
222 if (size == 8)
223 return ap->reg_save_area + ap->fp_offset - 16;
224 if (ap->fp_offset < 128 + 48) {
225 double *p = (double *)(ap->reg_save_area + ap->fp_offset);
226 p[-1] = p[0];
227 ap->fp_offset += 16;
228 return ap->reg_save_area + ap->fp_offset - 32;
229 }
230 }
231 goto use_overflow_area;
232 case __va_stack:
233 use_overflow_area:
234 ap->overflow_arg_area += size;
235 ap->overflow_arg_area =
236 (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
237 return ap->overflow_arg_area - size;
238 default: /* should never happen */
239 char *a = (char *)0; *a = 0; // abort
240 return 0;
241 }
242 }
243
244 #define __builtin_va_start(ap, last) \205 #define __builtin_va_start(ap, last) \
245 (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))206 (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
246 #define __builtin_va_arg(ap, t) \207 #define __builtin_va_arg(ap, t) \
lib/Makefile+2−2
@@ -59,8 +59,8 @@ $(Cbc)COMMON_O += bcheck.o · 58 unmodified lines
59EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o59EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
60 60
61OBJ-i386 = $(I386_O) pic86.o $(LIN_O)61OBJ-i386 = $(I386_O) pic86.o $(LIN_O)
62OBJ-x86_64 = $(X86_64_O) $(LIN_O)62OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O)
63OBJ-x86_64-osx = $(X86_64_O) $(OSX_O)63OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
64OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)64OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
65OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)65OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
66OBJ-arm64 = $(ARM64_O) $(LIN_O)66OBJ-arm64 = $(ARM64_O) $(LIN_O)
lib/lib-arm64.c+59−67
@@ -18,14 +18,6 @@ typedef int int32_t; · 17 unmodified lines
18typedef unsigned uint32_t;18typedef unsigned uint32_t;
19typedef long long int64_t;19typedef long long int64_t;
20typedef unsigned long long uint64_t;20typedef unsigned long long uint64_t;
21static void *memcpy(void* d, void* s, __SIZE_TYPE__ c) {
22 char *d_, *s_;
23 d_ = d; s_ = s;
24 for (__SIZE_TYPE__ i = 0; i < c; ++i) {
25 d_[i] = s_[i];
26 }
27 return d;
28}
29#else21#else
30#include <stdint.h>22#include <stdint.h>
31#include <string.h>23#include <string.h>
@@ -38,29 +30,35 @@ void __clear_cache(void *beg, void *end) · 6 unmodified lines
38}30}
39#endif31#endif
40 32
41typedef struct {33typedef union {
42 uint64_t x0, x1;34 struct { uint64_t x0, x1; };
35 long double f;
43} u128_t;36} u128_t;
44 37
38typedef union {
39 uint64_t x;
40 double f;
41} u64_t;
42
43typedef union {
44 uint32_t x;
45 float f;
46} u32_t;
47
45static long double f3_zero(int sgn)48static long double f3_zero(int sgn)
46{49{
47 long double f;
48 u128_t x = { 0, (uint64_t)sgn << 63 };50 u128_t x = { 0, (uint64_t)sgn << 63 };
49 memcpy(&f, &x, 16);51 return x.f;
50 return f;
51}52}
52 53
53static long double f3_infinity(int sgn)54static long double f3_infinity(int sgn)
54{55{
55 long double f;
56 u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };56 u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
57 memcpy(&f, &x, 16);57 return x.f;
58 return f;
59}58}
60 59
61static long double f3_NaN(void)60static long double f3_NaN(void)
62{61{
63 long double f;
64#if 062#if 0
65 // ARM's default NaN usually has just the top fraction bit set:63 // ARM's default NaN usually has just the top fraction bit set:
66 u128_t x = { 0, 0x7fff800000000000 };64 u128_t x = { 0, 0x7fff800000000000 };
@@ -68,28 +66,31 @@ static long double f3_NaN(void) · 1 unmodified line
68 // GCC's library sets all fraction bits:66 // GCC's library sets all fraction bits:
69 u128_t x = { -1, 0x7fffffffffffffff };67 u128_t x = { -1, 0x7fffffffffffffff };
70#endif68#endif
71 memcpy(&f, &x, 16);69 return x.f;
72 return f;
73}70}
74 71
75static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)72static int fp3_convert_NaN(long double *f, int sgn, u128_t *mnt)
76{73{
77 u128_t x = { mnt.x0,74 u128_t x = { mnt->x0,
78 mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };75 mnt->x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
79 memcpy(f, &x, 16);76 *f = x.f;
80 return 1;77 return 1;
78#define fp3_convert_NaN(a,b,c) fp3_convert_NaN(a,b,&c)
81}79}
82 80
83static int fp3_detect_NaNs(long double *f,81static int fp3_detect_NaNs(long double *f,
84 int a_sgn, int a_exp, u128_t a,82 int a_sgn, int a_exp, u128_t *a,
85 int b_sgn, int b_exp, u128_t b)83 int b_sgn, int b_exp, u128_t *b)
84#define a (*a)
85#define b (*b)
86{86{
87#if 0
87 // Detect signalling NaNs:88 // Detect signalling NaNs:
88 if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))89 if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
89 return fp3_convert_NaN(f, a_sgn, a);90 return fp3_convert_NaN(f, a_sgn, a);
90 if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))91 if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
91 return fp3_convert_NaN(f, b_sgn, b);92 return fp3_convert_NaN(f, b_sgn, b);
92 93#endif
93 // Detect quiet NaNs:94 // Detect quiet NaNs:
94 if (a_exp == 32767 && (a.x0 | a.x1 << 16))95 if (a_exp == 32767 && (a.x0 | a.x1 << 16))
95 return fp3_convert_NaN(f, a_sgn, a);96 return fp3_convert_NaN(f, a_sgn, a);
@@ -97,12 +98,16 @@ static int fp3_detect_NaNs(long double *f, · 1 unmodified line
97 return fp3_convert_NaN(f, b_sgn, b);98 return fp3_convert_NaN(f, b_sgn, b);
98 99
99 return 0;100 return 0;
101#undef a
102#undef b
103#define fp3_detect_NaNs(a,b,c,d,e,f,g) fp3_detect_NaNs(a,b,c,&d,e,f,&g)
100}104}
101 105
102static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)106static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
103{107{
104 u128_t x;108 u128_t x;
105 memcpy(&x, &f, 16);109
110 x.f = f;
106 *sgn = x.x1 >> 63;111 *sgn = x.x1 >> 63;
107 *exp = x.x1 >> 48 & 32767;112 *exp = x.x1 >> 48 & 32767;
108 x.x1 = x.x1 << 16 >> 16;113 x.x1 = x.x1 << 16 >> 16;
@@ -110,7 +115,7 @@ static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f) · 1 unmodified line
110 x.x1 |= (uint64_t)1 << 48;115 x.x1 |= (uint64_t)1 << 48;
111 else116 else
112 *exp = 1;117 *exp = 1;
113 memcpy(mnt, &x, 16);118 mnt->f = x.f;
114}119}
115 120
116static void f3_normalise(int32_t *exp, u128_t *mnt)121static void f3_normalise(int32_t *exp, u128_t *mnt)
@@ -184,8 +189,7 @@ static long double f3_round(int sgn, int32_t exp, u128_t *x) · 67 unmodified lines
184 return f3_infinity(sgn);189 return f3_infinity(sgn);
185 190
186 x->x1 = x->x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;191 x->x1 = x->x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
187 memcpy(&f, x, 16);192 return x->f;
188 return f;
189}193}
190 194
191static long double f3_add(long double fa, long double fb, int neg)195static long double f3_add(long double fa, long double fb, int neg)
@@ -380,23 +384,20 @@ long double __divtf3(long double fa, long double fb) · 188 unmodified lines
380 384
381long double __negtf2(long double f)385long double __negtf2(long double f)
382{386{
383 u128_t a;387 ((u128_t*)&f)->x1 ^= 1UL << 63;
384
385 memcpy(&a, &f, 16);
386 a.x1 ^= 1UL << 63;
387 memcpy(&f, &a, 16);
388
389 return f;388 return f;
390}389}
391 390
392long double __extendsftf2(float f)391long double __extendsftf2(float f)
393{392{
394 long double fx;
395 u128_t x;393 u128_t x;
394 u32_t u;
396 uint32_t a;395 uint32_t a;
397 uint64_t aa;396 uint64_t aa;
398 memcpy(&a, &f, 4);397
398 u.f = f, a = u.x;
399 aa = a;399 aa = a;
400
400 x.x0 = 0;401 x.x0 = 0;
401 if (!(a << 1))402 if (!(a << 1))
402 x.x1 = aa << 32;403 x.x1 = aa << 32;
@@ -411,16 +412,17 @@ long double __extendsftf2(float f) · 8 unmodified lines
411 } else412 } else
412 x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |413 x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
413 aa << 41 >> 16);414 aa << 41 >> 16);
414 memcpy(&fx, &x, 16);415 return x.f;
415 return fx;
416}416}
417 417
418long double __extenddftf2(double f)418long double __extenddftf2(double f)
419{419{
420 long double fx;
421 u128_t x;420 u128_t x;
421 u64_t u;
422 uint64_t a;422 uint64_t a;
423 memcpy(&a, &f, 8);423
424 u.f = f, a = u.x;
425
424 x.x0 = a << 60;426 x.x0 = a << 60;
425 if (!(a << 1))427 if (!(a << 1))
426 x.x1 = a;428 x.x1 = a;
@@ -435,8 +437,7 @@ long double __extenddftf2(double f) · 8 unmodified lines
435 x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;437 x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;
436 } else438 } else
437 x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;439 x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
438 memcpy(&fx, &x, 16);440 return x.f;
439 return fx;
440}441}
441 442
442float __trunctfsf2(long double f)443float __trunctfsf2(long double f)
@@ -444,11 +445,10 @@ float __trunctfsf2(long double f) · 1 unmodified line
444 u128_t mnt;445 u128_t mnt;
445 int32_t exp;446 int32_t exp;
446 int sgn;447 int sgn;
447 uint32_t x;448 u32_t x;
448 float fx;449#define x x.x
449 450
450 f3_unpack(&sgn, &exp, &mnt, f);451 f3_unpack(&sgn, &exp, &mnt, f);
451
452 if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))452 if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
453 x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);453 x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
454 else if (exp > 16510)454 else if (exp > 16510)
@@ -466,8 +466,8 @@ float __trunctfsf2(long double f) · 11 unmodified lines
466 x += 4;466 x += 4;
467 x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;467 x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
468 }468 }
469 memcpy(&fx, &x, 4);469#undef x
470 return fx;470 return x.f;
471}471}
472 472
473double __trunctfdf2(long double f)473double __trunctfdf2(long double f)
@@ -475,11 +475,10 @@ double __trunctfdf2(long double f) · 1 unmodified line
475 u128_t mnt;475 u128_t mnt;
476 int32_t exp;476 int32_t exp;
477 int sgn;477 int sgn;
478 uint64_t x;478 u64_t x;
479 double fx;479#define x x.x
480 480
481 f3_unpack(&sgn, &exp, &mnt, f);481 f3_unpack(&sgn, &exp, &mnt, f);
482
483 if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))482 if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
484 x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |483 x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
485 mnt.x1 << 16 >> 12 | mnt.x0 >> 60);484 mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
@@ -498,8 +497,8 @@ double __trunctfdf2(long double f) · 12 unmodified lines
498 x += 4;497 x += 4;
499 x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;498 x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
500 }499 }
501 memcpy(&fx, &x, 8);500#undef x
502 return fx;501 return x.f;
503}502}
504 503
505int32_t __fixtfsi(long double fa)504int32_t __fixtfsi(long double fa)
@@ -564,7 +563,6 @@ long double __floatsitf(int32_t a) · 58 unmodified lines
564 int exp = 16414;563 int exp = 16414;
565 uint32_t mnt = a;564 uint32_t mnt = a;
566 u128_t x = { 0, 0 };565 u128_t x = { 0, 0 };
567 long double f;
568 int i;566 int i;
569 if (a) {567 if (a) {
570 if (a < 0) {568 if (a < 0) {
@@ -579,8 +577,7 @@ long double __floatsitf(int32_t a) · 8 unmodified lines
579 x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |577 x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
580 (uint64_t)(mnt << 1) << 16);578 (uint64_t)(mnt << 1) << 16);
581 }579 }
582 memcpy(&f, &x, 16);580 return x.f;
583 return f;
584}581}
585 582
586long double __floatditf(int64_t a)583long double __floatditf(int64_t a)
@@ -589,7 +586,6 @@ long double __floatditf(int64_t a) · 2 unmodified lines
589 int exp = 16446;586 int exp = 16446;
590 uint64_t mnt = a;587 uint64_t mnt = a;
591 u128_t x = { 0, 0 };588 u128_t x = { 0, 0 };
592 long double f;
593 int i;589 int i;
594 if (a) {590 if (a) {
595 if (a < 0) {591 if (a < 0) {
@@ -604,8 +600,7 @@ long double __floatditf(int64_t a) · 8 unmodified lines
604 x.x0 = mnt << 49;600 x.x0 = mnt << 49;
605 x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;601 x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
606 }602 }
607 memcpy(&f, &x, 16);603 return x.f;
608 return f;
609}604}
610 605
611long double __floatunsitf(uint32_t a)606long double __floatunsitf(uint32_t a)
@@ -613,7 +608,6 @@ long double __floatunsitf(uint32_t a) · 1 unmodified line
613 int exp = 16414;608 int exp = 16414;
614 uint32_t mnt = a;609 uint32_t mnt = a;
615 u128_t x = { 0, 0 };610 u128_t x = { 0, 0 };
616 long double f;
617 int i;611 int i;
618 if (a) {612 if (a) {
619 for (i = 16; i; i >>= 1)613 for (i = 16; i; i >>= 1)
@@ -623,8 +617,7 @@ long double __floatunsitf(uint32_t a) · 3 unmodified lines
623 }617 }
624 x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;618 x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
625 }619 }
626 memcpy(&f, &x, 16);620 return x.f;
627 return f;
628}621}
629 622
630long double __floatunditf(uint64_t a)623long double __floatunditf(uint64_t a)
@@ -643,15 +636,14 @@ long double __floatunditf(uint64_t a) · 12 unmodified lines
643 x.x0 = mnt << 49;636 x.x0 = mnt << 49;
644 x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;637 x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
645 }638 }
646 memcpy(&f, &x, 16);639 return x.f;
647 return f;
648}640}
649 641
650static int f3_cmp(long double fa, long double fb)642static int f3_cmp(long double fa, long double fb)
651{643{
652 u128_t a, b;644 u128_t a, b;
653 memcpy(&a, &fa, 16);645 a.f = fa;
654 memcpy(&b, &fb, 16);646 b.f = fb;
655 return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :647 return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
656 ((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||648 ((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
657 (b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :649 (b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
lib/va_list.c+67−0
@@ -0,0 +1,67 @@
1/* va_list.c - tinycc support for va_list on X86_64 */
2
3#if defined __x86_64__
4
5/* Avoid include files, they may not be available when cross compiling */
6extern void abort(void);
7
8/* This should be in sync with our include/stdarg.h */
9enum __va_arg_type {
10 __va_gen_reg, __va_float_reg, __va_stack
11};
12
13/* GCC compatible definition of va_list. */
14/*predefined by TCC (tcc_predefs.h):
15typedef struct {
16 unsigned int gp_offset;
17 unsigned int fp_offset;
18 union {
19 unsigned int overflow_offset;
20 char *overflow_arg_area;
21 };
22 char *reg_save_area;
23} __builtin_va_list[1];
24*/
25
26extern void *memcpy(void *dest, const void *src, unsigned long n);
27
28void *__va_arg(__builtin_va_list ap,
29 int arg_type,
30 int size, int align)
31{
32 size = (size + 7) & ~7;
33 align = (align + 7) & ~7;
34 switch ((enum __va_arg_type)arg_type) {
35 case __va_gen_reg:
36 if (ap->gp_offset + size <= 48) {
37 ap->gp_offset += size;
38 return ap->reg_save_area + ap->gp_offset - size;
39 }
40 goto use_overflow_area;
41
42 case __va_float_reg:
43 if (ap->fp_offset < 128 + 48) {
44 ap->fp_offset += 16;
45 if (size == 8)
46 return ap->reg_save_area + ap->fp_offset - 16;
47 if (ap->fp_offset < 128 + 48) {
48 memcpy(ap->reg_save_area + ap->fp_offset - 8,
49 ap->reg_save_area + ap->fp_offset, 8);
50 ap->fp_offset += 16;
51 return ap->reg_save_area + ap->fp_offset - 32;
52 }
53 }
54 goto use_overflow_area;
55
56 case __va_stack:
57 use_overflow_area:
58 ap->overflow_arg_area += size;
59 ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
60 return ap->overflow_arg_area - size;
61
62 default: /* should never happen */
63 abort();
64 return 0;
65 }
66}
67#endif
libtcc.c+5−63
@@ -791,7 +791,7 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename) · 790 unmodified lines
791}791}
792 792
793/* compile the file opened in 'file'. Return non zero if errors. */793/* compile the file opened in 'file'. Return non zero if errors. */
794static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd, const char *filename)794static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
795{795{
796 /* Here we enter the code section where we use the global variables for796 /* Here we enter the code section where we use the global variables for
797 parsing and code generation (tccpp.c, tccgen.c, <target>-gen.c).797 parsing and code generation (tccpp.c, tccgen.c, <target>-gen.c).
@@ -807,16 +807,8 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd, cons · 9 unmodified lines
807 807
808 if (fd == -1) {808 if (fd == -1) {
809 int len = strlen(str);809 int len = strlen(str);
810 tcc_open_bf(s1, filename ? filename : "<string>", len);810 tcc_open_bf(s1, "<string>", len);
811 memcpy(file->buffer, str, len);811 memcpy(file->buffer, str, len);
812 if (s1->do_debug && filename) {
813 FILE *fp = fopen(filename, "w");
814
815 if (fp) {
816 fputs(str, fp);
817 fclose(fp);
818 }
819 }
820 } else {812 } else {
821 tcc_open_bf(s1, str, 0);813 tcc_open_bf(s1, str, 0);
822 file->fd = fd;814 file->fd = fd;
@@ -846,12 +838,7 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd, cons · 23 unmodified lines
846 838
847LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)839LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
848{840{
849 return tcc_compile(s, s->filetype, str, -1, NULL);841 return tcc_compile(s, s->filetype, str, -1);
850}
851
852LIBTCCAPI int tcc_compile_string_file(TCCState *s, const char *str, const char *filename)
853{
854 return tcc_compile(s, s->filetype, str, -1, filename);
855}842}
856 843
857/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */844/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
@@ -1246,7 +1233,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) · 388 unmodified lines
1246 return tcc_add_binary(s1, flags, filename, fd);1233 return tcc_add_binary(s1, flags, filename, fd);
1247 1234
1248 dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename));1235 dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename));
1249 return tcc_compile(s1, flags, filename, fd, NULL);1236 return tcc_compile(s1, flags, filename, fd);
1250}1237}
1251 1238
1252LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)1239LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
@@ -1585,30 +1572,6 @@ enum { · 332 unmodified lines
1585#define TCC_OPTION_HAS_ARG 0x00011572#define TCC_OPTION_HAS_ARG 0x0001
1586#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */1573#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
1587 1574
1588/*
1589 * in tcc_options, if opt-string A is a prefix of opt-string B,
1590 * it's un-ambiguous if and only if option A is without TCC_OPTION_HAS_ARG.
1591 * otherwise (A with HAS_ARG), if, for instance, A is FOO and B is FOOBAR,
1592 * then "-FOOBAR" is either A with arg BAR, or B (-FOOBARX too, if B HAS_ARG).
1593 *
1594 * tcc_parse_args searches tcc_options in order, so if ambiguous:
1595 * - if the shorter (A) is earlier: the longer (B) is completely unreachable.
1596 * - else B wins, and A can't be used with adjacent arg if it also matches B.
1597 *
1598 * there are few clashes currently, and the longer is always earlier/reachable.
1599 * when it's ambiguous, shorter-concat-arg is not useful currently.
1600 * the sh(1) script 'optclash' can identifiy clashes (tcc root dir, try "-h").
1601 * at the time of writing, running './optclash' prints this:
1602
1603 -Wl,... (1642) overrides -W... (1644)
1604 -Wp,... (1643) overrides -W... (1644)
1605 -dumpmachine (1630) overrides -d... (1632)
1606 -dumpversion (1631) overrides -d... (1632)
1607 -dynamiclib (1623) overrides -d... (1632)
1608 -flat_namespace (1624) overrides -f... (1650)
1609 -mfloat-abi... (1647) overrides -m... (1649)
1610
1611 */
1612static const TCCOption tcc_options[] = {1575static const TCCOption tcc_options[] = {
1613 { "h", TCC_OPTION_HELP, 0 },1576 { "h", TCC_OPTION_HELP, 0 },
1614 { "-help", TCC_OPTION_HELP, 0 },1577 { "-help", TCC_OPTION_HELP, 0 },
@@ -1848,27 +1811,6 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 233 unmodified lines
1848 ++s->nb_libraries;1811 ++s->nb_libraries;
1849}1812}
1850 1813
1851/* parsing is between getopt(3) and getopt_long(3), and permuting-like:
1852 * - an option is 1 or more chars.
1853 * - at most 1 option per arg in argv.
1854 * - an option in argv is "-OPT[...]" (few are --OPT, if OPT is "-...").
1855 * - optarg is next arg, or adjacent non-empty (no '='. -std=.. is arg "=..").
1856 * - supports also adjacent-only optarg (typically optional).
1857 * - supports mixed options and operands ("--" is ignored, except with -run).
1858 * - -OPT[...] can be ambiguous, which is resolved using tcc_options's order.
1859 * (see tcc_options for details)
1860 *
1861 * specifically, per arg of argv, in order:
1862 * - if arg begins with '@' and is not exactly "@": process as @listfile.
1863 * - elif arg is exactly "-" or doesn't begin with '-': process as input file.
1864 * - if -run... is already set: also stop, arg... become argv of run_main.
1865 * - elif arg is "--":
1866 * - if -run... is already set: stop, arg... become argv of run_main.
1867 * - else ignore it.
1868 * - else ("-STRING") try to apply it as option, maybe with next (opt)arg.
1869 *
1870 * after all args, if -run... but no "stop": run_main gets our argv (tcc ...)
1871 */
1872/* using * to argc/argv to let "tcc -ar" benefit from @listfile expansion */1814/* using * to argc/argv to let "tcc -ar" benefit from @listfile expansion */
1873PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)1815PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
1874{1816{
@@ -2217,7 +2159,7 @@ unsupported_option: · 342 unmodified lines
2217 if (run) {2159 if (run) {
2218 if (*run && tcc_set_options(s, run) < 0)2160 if (*run && tcc_set_options(s, run) < 0)
2219 return -1;2161 return -1;
2220 x = 0;2162 x = 0, r = 0;
2221 goto extra_action;2163 goto extra_action;
2222 }2164 }
2223 if (!empty)2165 if (!empty)
libtcc.h+0−12
@@ -105,18 +105,6 @@ LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx, · 104 unmodified lines
105LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);105LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
106#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))106#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
107 107
108/* debugging */
109/* For debugging to work you have to enable it with tcc_set_options */
110
111/* compile a string containing a C source. Return -1 if error.
112 Write the string to file filename if debug is set. */
113LIBTCCAPI int tcc_compile_string_file(TCCState *s, const char *buf, const char *filename);
114
115/* Output object file. This must be done after tcc_relocate.
116 It only generates the file if debug is set.
117 The filename can be loaded with gdb command add-symbol-file */
118LIBTCCAPI int elf_output_obj(TCCState *s1, const char *filename);
119
120/* custom error printer for runtime exceptions. Returning 0 stops backtrace */108/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
121typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);109typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
122LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);110LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
optclash+0−38
@@ -1,38 +0,0 @@
1#!/bin/sh
2
3export LC_ALL=C
4
5defname=libtcc.c
6
7# $1 is the line number, $2... is the actual source line
8extract_opts() { awk '/tcc_options\[\]/ {x=1}; x; x && $2~/^}/ {exit}'; }
9
10case $1 in -h|--help)
11 echo "Usage: $0 [INFILE]"
12 echo "Detect tcc_options[] clashes in $defname-like INFILE."
13 echo "If INFILE is missing, use $defname at the same dir as this script."
14 echo "Clashes are reported as longer-overrides, or longer-unreachable."
15 exit
16esac
17
18f=${1-$(dirname "$0")/$defname}
19[ -r "$f" ] || { >&2 echo "$0: can't read -- $f"; exit 1; }
20
21nl -b a <"$f" | extract_opts | tr \" ' ' | awk '$2=="{"' | sort -b -k 3 |
22# "<line-num> { <unquoted-opt> <rest-of-line>" sorted-up by opt
23# unavoidable O(N^2). the sort simplifies the awk code - only test prior opts.
24awk '
25 {
26 n=$1; opt=$3; h=/HAS_ARG/
27 for (pn in prevs) { # pn: line-num
28 po = prevs[pn] # po: opt-with-has-arg
29 if (index(opt,po) == 1) {
30 clash=1
31 printf("-%s%s (%d) %s -%s... (%s)\n", opt,h?"...":"",n,
32 n>pn? "is not reachable! by":"overrides", po,pn)
33 }
34 }
35 }
36 h {prevs[n] = opt}
37 END {if (clash) exit 1; print "no clashes"}
38'
riscv64-link.c+10−26
@@ -175,37 +175,23 @@ ST_FUNC void relocate_plt(TCCState *s1) · 174 unmodified lines
175 175
176static void riscv64_record_pcrel_hi(TCCState *s1, addr_t addr, addr_t val)176static void riscv64_record_pcrel_hi(TCCState *s1, addr_t addr, addr_t val)
177{177{
178 int n = s1->nb_pcrel_hi_entries;178 struct pcrel_hi *entry = tcc_malloc(sizeof *entry);
179 if (n >= s1->alloc_pcrel_hi_entries) {179 entry->addr = addr;
180 int new_alloc = s1->alloc_pcrel_hi_entries ? s1->alloc_pcrel_hi_entries * 2 : 64;180 entry->val = val;
181 s1->pcrel_hi_entries = tcc_realloc(s1->pcrel_hi_entries,181 dynarray_add(&s1->pcrel_hi_entries, &s1->nb_pcrel_hi_entries, entry);
182 new_alloc * sizeof(*s1->pcrel_hi_entries));
183 s1->alloc_pcrel_hi_entries = new_alloc;
184 }
185 s1->pcrel_hi_entries[n].addr = addr;
186 s1->pcrel_hi_entries[n].val = val;
187 s1->nb_pcrel_hi_entries = n + 1;
188 last_hi.addr = addr;
189 last_hi.val = val;
190}182}
191 183
192static int riscv64_lookup_pcrel_hi(TCCState *s1, addr_t hi_addr, addr_t *hi_val)184static int riscv64_lookup_pcrel_hi(TCCState *s1, addr_t hi_addr, addr_t *hi_val)
193{185{
194 int i;186 int i;
195 struct pcrel_hi *entry;187 for (i = s1->nb_pcrel_hi_entries; i > 0; ) {
196 if (s1->nb_pcrel_hi_entries && hi_addr == last_hi.addr) {188 struct pcrel_hi *entry = s1->pcrel_hi_entries[--i];
197 *hi_val = last_hi.val;
198 return 1;
199 }
200 for (i = s1->nb_pcrel_hi_entries - 1; i >= 0; --i) {
201 entry = &s1->pcrel_hi_entries[i];
202 if (entry->addr == hi_addr) {189 if (entry->addr == hi_addr) {
203 last_hi = *entry;
204 *hi_val = entry->val;190 *hi_val = entry->val;
205 return 1;191 return 0;
206 }192 }
207 }193 }
208 return 0;194 return tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
209}195}
210 196
211ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,197ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
@@ -279,15 +265,13 @@ ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 67 unmodified lines
279 printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);265 printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
280#endif266#endif
281 addr = val;267 addr = val;
282 if (!riscv64_lookup_pcrel_hi(s1, addr, &val))268 riscv64_lookup_pcrel_hi(s1, addr, &val);
283 tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
284 write32le(ptr, (read32le(ptr) & 0xfffff)269 write32le(ptr, (read32le(ptr) & 0xfffff)
285 | (((val - addr) & 0xfff) << 20));270 | (((val - addr) & 0xfff) << 20));
286 return;271 return;
287 case R_RISCV_PCREL_LO12_S:272 case R_RISCV_PCREL_LO12_S:
288 addr = val;273 addr = val;
289 if (!riscv64_lookup_pcrel_hi(s1, addr, &val))274 riscv64_lookup_pcrel_hi(s1, addr, &val);
290 tcc_error_noabort("unsupported hi/lo pcrel reloc scheme");
291 off32 = val - addr;275 off32 = val - addr;
292 write32le(ptr, (read32le(ptr) & ~0xfe000f80)276 write32le(ptr, (read32le(ptr) & ~0xfe000f80)
293 | ((off32 & 0xfe0) << 20)277 | ((off32 & 0xfe0) << 20)
tcc.h+1−4
@@ -938,11 +938,8 @@ struct TCCState { · 937 unmodified lines
938 #define qrel s1->qrel938 #define qrel s1->qrel
939 939
940#ifdef TCC_TARGET_RISCV64940#ifdef TCC_TARGET_RISCV64
941 struct pcrel_hi { addr_t addr, val; } last_hi;941 struct pcrel_hi { addr_t addr, val; } **pcrel_hi_entries;
942 struct pcrel_hi *pcrel_hi_entries;
943 int nb_pcrel_hi_entries;942 int nb_pcrel_hi_entries;
944 int alloc_pcrel_hi_entries;
945 #define last_hi s1->last_hi
946#endif943#endif
947 944
948#ifdef TCC_TARGET_PE945#ifdef TCC_TARGET_PE
tccelf.c+6−8
@@ -145,9 +145,6 @@ ST_FUNC void tccelf_delete(TCCState *s1) · 144 unmodified lines
145 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);145 dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
146 146
147 tcc_free(s1->sym_attrs);147 tcc_free(s1->sym_attrs);
148#ifdef TCC_TARGET_RISCV64
149 tcc_free(s1->pcrel_hi_entries);
150#endif
151 symtab_section = NULL; /* for tccrun.c:rt_printline() */148 symtab_section = NULL; /* for tccrun.c:rt_printline() */
152}149}
153 150
@@ -1130,10 +1127,6 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) · 976 unmodified lines
1130 addr_t tgt, addr;1127 addr_t tgt, addr;
1131 int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;1128 int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
1132 1129
1133#ifdef TCC_TARGET_RISCV64
1134 s1->nb_pcrel_hi_entries = 0;
1135#endif
1136
1137 qrel = (ElfW_Rel *)sr->data;1130 qrel = (ElfW_Rel *)sr->data;
1138 for_each_elem(sr, 0, rel, ElfW_Rel) {1131 for_each_elem(sr, 0, rel, ElfW_Rel) {
1139 if (s->data == NULL) /* bss */1132 if (s->data == NULL) /* bss */
@@ -1155,6 +1148,7 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) · 15 unmodified lines
1155 addr = s->sh_addr + rel->r_offset;1148 addr = s->sh_addr + rel->r_offset;
1156 relocate(s1, rel, type, ptr, addr, tgt);1149 relocate(s1, rel, type, ptr, addr, tgt);
1157 }1150 }
1151
1158#ifndef ELF_OBJ_ONLY1152#ifndef ELF_OBJ_ONLY
1159 /* if the relocation is allocated, we change its symbol table */1153 /* if the relocation is allocated, we change its symbol table */
1160 if (sr->sh_flags & SHF_ALLOC) {1154 if (sr->sh_flags & SHF_ALLOC) {
@@ -1172,6 +1166,10 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) · 11 unmodified lines
1172 }1166 }
1173 }1167 }
1174#endif1168#endif
1169
1170#ifdef TCC_TARGET_RISCV64
1171 dynarray_reset(&s1->pcrel_hi_entries, &s1->nb_pcrel_hi_entries);
1172#endif
1175}1173}
1176 1174
1177/* relocate all sections */1175/* relocate all sections */
@@ -3103,7 +3101,7 @@ static void alloc_sec_names(TCCState *s1, int is_obj) · 1925 unmodified lines
3103}3101}
3104 3102
3105/* Output an elf .o file */3103/* Output an elf .o file */
3106LIBTCCAPI int elf_output_obj(TCCState *s1, const char *filename)3104static int elf_output_obj(TCCState *s1, const char *filename)
3107{3105{
3108 Section *s;3106 Section *s;
3109 int i, ret, file_offset;3107 int i, ret, file_offset;
tccgen.c+11−3
@@ -2526,6 +2526,14 @@ void gen_negf(int op) · 2525 unmodified lines
2526 2526
2527 size = type_size(&vtop->type, &align);2527 size = type_size(&vtop->type, &align);
2528 bt = vtop->type.t & VT_BTYPE;2528 bt = vtop->type.t & VT_BTYPE;
2529#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
2530 /* sizeof long double is 12 or 16 here, but it's really the 80bit
2531 extended float format. */
2532 if (bt == VT_LDOUBLE)
2533 size = 10;
2534#endif
2535 if (nocode_wanted) /* save_reg() wont work */
2536 goto gv2;
2529 save_reg(gv(RC_TYPE(bt)));2537 save_reg(gv(RC_TYPE(bt)));
2530 vdup();2538 vdup();
2531 incr_bf_adr(size - 1);2539 incr_bf_adr(size - 1);
@@ -2534,6 +2542,8 @@ void gen_negf(int op) · 2 unmodified lines
2534 gen_op('^');2542 gen_op('^');
2535 vstore();2543 vstore();
2536 vpop();2544 vpop();
2545gv2:
2546 gv(RC_TYPE(bt)); /* -n is not a lvalue */
2537}2547}
2538#endif2548#endif
2539 2549
@@ -3097,9 +3107,7 @@ op_err: · 557 unmodified lines
3097#endif3107#endif
3098 type1 = vtop[-1].type;3108 type1 = vtop[-1].type;
3099 vpush_type_size(pointed_type(&vtop[-1].type), &align);3109 vpush_type_size(pointed_type(&vtop[-1].type), &align);
3100 if (!(vtop[-1].type.t & VT_UNSIGNED)) {3110 vtop->type.t &= ~VT_UNSIGNED;
3101 gen_cast_s(VT_PTRDIFF_T);
3102 }
3103 gen_op('*');3111 gen_op('*');
3104#ifdef CONFIG_TCC_BCHECK3112#ifdef CONFIG_TCC_BCHECK
3105 if (tcc_state->do_bounds_check && !CONST_WANTED) {3113 if (tcc_state->do_bounds_check && !CONST_WANTED) {
tccpp.c+7−28
@@ -2475,7 +2475,7 @@ static void parse_number(const char *p) · 2474 unmodified lines
2475 }2475 }
2476 }2476 }
2477 } else {2477 } else {
2478 unsigned long long n = 0, n1 = 0;2478 unsigned long long n, n1;
2479 int lcount, ucount, ov = 0;2479 int lcount, ucount, ov = 0;
2480 const char *p1;2480 const char *p1;
2481 2481
@@ -2486,6 +2486,7 @@ static void parse_number(const char *p) · 4 unmodified lines
2486 b = 8;2486 b = 8;
2487 q++;2487 q++;
2488 }2488 }
2489 n = 0;
2489 while(1) {2490 while(1) {
2490 t = *q++;2491 t = *q++;
2491 /* no need for checks except for base 10 / 8 errors */2492 /* no need for checks except for base 10 / 8 errors */
@@ -2499,14 +2500,11 @@ static void parse_number(const char *p) · 7 unmodified lines
2499 t = t - '0';2500 t = t - '0';
2500 if (t >= b)2501 if (t >= b)
2501 tcc_error("invalid digit");2502 tcc_error("invalid digit");
2503 n1 = n;
2502 n = n * b + t;2504 n = n * b + t;
2503 if (!ov) {2505 /* detect overflow */
2504 /* detect overflow */2506 if (n1 >= 0x1000000000000000ULL && n / b != n1)
2505 if (n1 >= 0x1000000000000000ULL && n / b != n1)2507 ov = 1;
2506 ov = 1;
2507 else
2508 n1 = n;
2509 }
2510 }2508 }
2511 2509
2512 /* Determine the characteristics (unsigned and/or 64bit) the type of2510 /* Determine the characteristics (unsigned and/or 64bit) the type of
@@ -2556,26 +2554,7 @@ static void parse_number(const char *p) · 43 unmodified lines
2556 }2554 }
2557 2555
2558 if (ov)2556 if (ov)
2559 /* Give a warning with values in case of an overflow. This helps to2557 tcc_warning("integer constant overflow");
2560 spot the 0 too much in 0x8000'0000'0000'0000'0. It may even be
2561 better to use a 0x8000'0000'0000'0000 from n1 instead of a 0 from
2562 n after the overflow. This is at least undefined behavior.
2563 The C99 to C23 standards state:
2564 "Each constant shall have a type and the value of a constant
2565 shall be in the range of representable values for its type."
2566 "If an integer constant cannot be represented by any type ...,
2567 then the integer constant has no type."
2568 The C++ standards state:
2569 "A program is ill-formed if one of its translation units contains
2570 an integer-literal that cannot be represented by any of the
2571 allowed types." */
2572 tcc_warning(
2573 b == 8
2574 ? "integer constant overflow, using %#llo; did you mean %#llo?"
2575 : b == 10
2576 ? "integer constant overflow, using %llu, did you mean %llu?"
2577 : "integer constant overflow, using %#llx; did you mean %#llx?",
2578 n, n1);
2579 2558
2580 tok = TOK_CINT;2559 tok = TOK_CINT;
2581 if (lcount) {2560 if (lcount) {
tccrun.c+8−44
@@ -260,56 +260,22 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) · 259 unmodified lines
260}260}
261 261
262/* ------------------------------------------------------------- */262/* ------------------------------------------------------------- */
263/* remove all STB_LOCAL symbols. When do_debug is set, cleanup_sections()263/* remove all STB_LOCAL symbols */
264 keeps the relocation sections alive for a later elf_output_obj() call;
265 the r_info indices in those rela entries refer to the pre-cleanup
266 symbol numbering, so we must build an old->new map and rewrite them.
267 Without that, sort_syms() in elf_output_obj() allocates an
268 old_to_new_syms[] array sized for the post-cleanup (smaller) symtab
269 and indexes it with the stale (larger) sym_index values, reading off
270 the end of the array. */
271static void cleanup_symbols(TCCState *s1)264static void cleanup_symbols(TCCState *s1)
272{265{
273 Section *s = s1->symtab;266 Section *s = s1->symtab;
274 int sym_index, end_sym = s->data_offset / sizeof (ElfSym);267 int sym_index, end_sym = s->data_offset / sizeof (ElfSym);
275 int *old_to_new = s1->do_debug
276 ? tcc_mallocz(end_sym * sizeof(int))
277 : NULL;
278 /* reset symtab */268 /* reset symtab */
279 s->data_offset = s->link->data_offset = s->hash->data_offset = 0;269 s->data_offset = s->link->data_offset = s->hash->data_offset = 0;
280 init_symtab(s);270 init_symtab(s);
281 /* add global symbols again, recording the new index of each */271 /* add global symbols again */
282 for (sym_index = 1; sym_index < end_sym; ++sym_index) {272 for (sym_index = 1; sym_index < end_sym; ++sym_index) {
283 ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index];273 ElfW(Sym) *sym = &((ElfW(Sym) *)s->data)[sym_index];
284 const char *name = (char *)s->link->data + sym->st_name;274 const char *name = (char *)s->link->data + sym->st_name;
285 int new_idx;
286 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)275 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
287 continue;276 continue;
288 //printf("sym %s\n", name);277 //printf("sym %s\n", name);
289 new_idx = put_elf_sym(s, sym->st_value, sym->st_size,278 put_elf_sym(s, sym->st_value, sym->st_size, sym->st_info, sym->st_other, sym->st_shndx, name);
290 sym->st_info, sym->st_other, sym->st_shndx, name);
291 if (old_to_new)
292 old_to_new[sym_index] = new_idx;
293 }
294 if (old_to_new) {
295 int i;
296 for (i = 1; i < s1->nb_sections; i++) {
297 Section *sr = s1->sections[i];
298 ElfW_Rel *rel;
299 if (sr->sh_type != SHT_RELX || sr->link != s)
300 continue;
301 for_each_elem(sr, 0, rel, ElfW_Rel) {
302 int old = ELFW(R_SYM)(rel->r_info);
303 int type = ELFW(R_TYPE)(rel->r_info);
304 /* Locals (and the undef sym at 0) map to 0 by
305 tcc_mallocz; relocations against dropped locals now
306 refer to SHN_UNDEF, which is the best we can do
307 without preserving the locals themselves. */
308 int new_idx = (old > 0 && old < end_sym) ? old_to_new[old] : 0;
309 rel->r_info = ELFW(R_INFO)(new_idx, type);
310 }
311 }
312 tcc_free(old_to_new);
313 }279 }
314}280}
315 281
@@ -321,7 +287,7 @@ static void cleanup_sections(TCCState *s1) · 5 unmodified lines
321 do {287 do {
322 for (i = --f; i < p->nb_secs; i++) {288 for (i = --f; i < p->nb_secs; i++) {
323 Section *s = p->secs[i];289 Section *s = p->secs[i];
324 if (s1->do_debug || s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash) {290 if (s == s1->symtab || s == s1->symtab->link || s == s1->symtab->hash) {
325 s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset);291 s->data = tcc_realloc(s->data, s->data_allocated = s->data_offset);
326 } else {292 } else {
327 free_section(s), tcc_free(s), p->secs[i] = NULL;293 free_section(s), tcc_free(s), p->secs[i] = NULL;
@@ -333,11 +299,10 @@ static void cleanup_sections(TCCState *s1) · 5 unmodified lines
333/* ------------------------------------------------------------- */299/* ------------------------------------------------------------- */
334/* 0 = .text rwx other rw (memory >= 2 pages a 4096 bytes) */300/* 0 = .text rwx other rw (memory >= 2 pages a 4096 bytes) */
335/* 1 = .text rx other rw (memory >= 3 pages) */301/* 1 = .text rx other rw (memory >= 3 pages) */
336/* 2 = .debug .debug ro (optional) */302/* 2 = .text rx .rdata ro .data/.bss rw (memory >= 4 pages) */
337/* 3 = .text rx .rdata ro .data/.bss rw (memory >= 4 pages) */
338 303
339/* Some targets implement secutiry options that do not allow write in304/* Some targets implement secutiry options that do not allow write in
340 executable code. These targets need CONFIG_RUNMEM_RO=2.305 executable code. These targets need CONFIG_RUNMEM_RO=1.
341 The disadvantage of this is that it requires a little bit more memory. */306 The disadvantage of this is that it requires a little bit more memory. */
342 307
343#ifndef CONFIG_RUNMEM_RO308#ifndef CONFIG_RUNMEM_RO
@@ -378,13 +343,12 @@ redo: · 34 unmodified lines
378 if (copy == 3)343 if (copy == 3)
379 return 0;344 return 0;
380 345
381 for (k = 0; k < 4; ++k) { /* 0:rx, 1:ro, 2:ro debug , 3:rw sections */346 for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
382 n = 0; addr = 0;347 n = 0; addr = 0;
383 for(i = 1; i < s1->nb_sections; i++) {348 for(i = 1; i < s1->nb_sections; i++) {
384 static const char shf[] = {349 static const char shf[] = {
385 SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, 0, SHF_ALLOC|SHF_WRITE350 SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE
386 };351 };
387 if (k == 2 && s1->do_debug == 0) continue;
388 s = s1->sections[i];352 s = s1->sections[i];
389 if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))353 if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
390 continue;354 continue;
tests/Makefile+0−7
@@ -13,7 +13,6 @@ TESTS = \ · 12 unmodified lines
13 hello-run \13 hello-run \
14 libtest \14 libtest \
15 libtest_mt \15 libtest_mt \
16 libtest_xor_rex \
17 test3 \16 test3 \
18 abitest \17 abitest \
19 asm-c-connect-test \18 asm-c-connect-test \
@@ -41,9 +40,6 @@ endif · 21 unmodified lines
41ifeq (,$(filter i386 x86_64,$(ARCH)))40ifeq (,$(filter i386 x86_64,$(ARCH)))
42 TESTS := $(filter-out asm-c-connect-test,$(TESTS))41 TESTS := $(filter-out asm-c-connect-test,$(TESTS))
43endif42endif
44ifeq (,$(filter x86_64,$(ARCH)))
45 TESTS := $(filter-out libtest_xor_rex,$(TESTS))
46endif
47ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll43ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
48 PATH := $(CURDIR)/$(TOP)$(if $(findstring ;,$(PATH)),;,:)$(PATH)44 PATH := $(CURDIR)/$(TOP)$(if $(findstring ;,$(PATH)),;,:)$(PATH)
49endif45endif
@@ -107,9 +103,6 @@ libtcc_test$(EXESUF): libtcc_test.c · 57 unmodified lines
107libtcc_test_mt$(EXESUF): libtcc_test_mt.c103libtcc_test_mt$(EXESUF): libtcc_test_mt.c
108 $(CC) -o $@ $< $(CFLAGS) $(-LTCC) $(LIBS)104 $(CC) -o $@ $< $(CFLAGS) $(-LTCC) $(LIBS)
109 105
110libtcc_test_xor_rex$(EXESUF): libtcc_test_xor_rex.c
111 $(CC) -o $@ $< $(CFLAGS) $(-LTCC) $(LIBS)
112
113%-dir:106%-dir:
114 @echo ------------ $@ ------------107 @echo ------------ $@ ------------
115 $(MAKE) -k -C $*108 $(MAKE) -k -C $*
tests/libtcc_debug.c+0−58
@@ -1,58 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include "libtcc.h"
5
6static const char program[] =
7"#include <stdio.h>\n"
8"int fib(int n)\n"
9"{\n"
10" if (n <= 2)\n"
11" return 1;\n"
12" else\n"
13" return fib(n-1) + fib(n-2);\n"
14"}\n"
15"int tst(void)\n"
16"{\n"
17" int i;\n"
18" for (i = 2; i < 20; i++)\n"
19" printf(\"%d \", fib(i));\n"
20" printf(\"\\n\");\n"
21" return 0;\n"
22"}\n";
23
24void handle_error(void *opaque, const char *msg)
25{
26 fprintf(opaque, "%s\n", msg);
27}
28
29int
30main(void)
31{
32 int (*func)(void);
33 TCCState *s = tcc_new();
34
35 if (!s) {
36 fprintf(stderr, __FILE__ ": could not create tcc state\n");
37 return 1;
38 }
39#if 1
40 /* If -g option is not set the debugging files tst.c en tst.o will
41 not be created. */
42 tcc_set_options(s, "-g");
43#endif
44 tcc_set_error_func(s, stdout, handle_error);
45 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
46 if (tcc_compile_string_file(s, program, "tst.c") == -1)
47 return 1;
48 if (tcc_relocate(s) < 0)
49 return 1;
50 elf_output_obj(s, "tst.o");
51 /* set breakpoint on next line. and load symbol file with
52 gdb command add-symbol-file.
53 Then set breakpoint on tst and continue. */
54 if ((func = tcc_get_symbol(s, "tst")))
55 func();
56 tcc_delete(s);
57 return 0;
58}
tests/libtcc_test_xor_rex.c+0−128
@@ -1,128 +0,0 @@
1/*
2 * Test for x86_64 xor REX prefix bug in load() -- x86_64-gen.c
3 *
4 * Bug: when loading a 64-bit zero constant into registers r8-r15,
5 * load() emits:
6 *
7 * o(0xc031 + REG_VALUE(r) * 0x900); // xor r, r
8 *
9 * REG_VALUE(r) masks to (r & 7), losing bit 3, and no orex() call
10 * emits the REX prefix needed for extended registers.
11 *
12 * Result: r=TREG_R11(11) -> REG_VALUE=3 -> emits 31 db (xor ebx,ebx)
13 * Correct: should emit 45 31 db (REX.RB xor r11d,r11d)
14 *
15 * Fix:
16 * orex(0, r, r, 0x31);
17 * o(0xc0 + REG_VALUE(r) * 9);
18 *
19 * Trigger: an indirect call through a compile-time null function pointer,
20 * e.g. ((void(*)(void))0)(), causes gcall_or_jmp() to fall into the
21 * "indirect call" path which does load(TREG_R11, <constant 0>).
22 *
23 * This test compiles such code via the libtcc API, then inspects the
24 * generated machine code for the incorrect encoding.
25 */
26
27#if !defined __x86_64__
28#include <stdio.h>
29int main(void) { printf("SKIP (x86_64 only)\n"); return 0; }
30#else
31
32#include <stdio.h>
33#include "libtcc.h"
34
35static void handle_error(void *opaque, const char *msg)
36{
37 fprintf(opaque, "%s\n", msg);
38}
39
40/*
41 * Compiled via libtcc. The cast-to-null indirect call forces
42 * gcall_or_jmp() into its "else" branch (no VT_SYM, so the
43 * condition on line ~650 fails), which does:
44 *
45 * r = TREG_R11;
46 * load(r, vtop); // <-- buggy xor lands here
47 * o(0x41); o(0xff); // call/jmp *r
48 * o(0xd0 + REG_VALUE(r)); // r11 -> 0xd3
49 *
50 * We never execute the function (it would crash); we only
51 * inspect the generated bytes.
52 */
53static const char test_code[] =
54 "void test(void) {\n"
55 " ((void(*)(void))0)();\n"
56 "}\n";
57
58int main(int argc, char **argv)
59{
60 TCCState *s;
61 unsigned char *code;
62 int i;
63 int ret = 0;
64
65 s = tcc_new();
66 if (!s) {
67 fprintf(stderr, "tcc_new() failed\n");
68 return 2;
69 }
70 tcc_set_error_func(s, stderr, handle_error);
71
72 for (i = 1; i < argc; ++i) {
73 char *a = argv[i];
74 if (a[0] == '-') {
75 if (a[1] == 'B')
76 tcc_set_lib_path(s, a + 2);
77 else if (a[1] == 'I')
78 tcc_add_include_path(s, a + 2);
79 else if (a[1] == 'L')
80 tcc_add_library_path(s, a + 2);
81 }
82 }
83
84 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
85 if (tcc_compile_string(s, test_code) == -1)
86 return 2;
87 if (tcc_relocate(s) < 0)
88 return 2;
89
90 code = (unsigned char *)tcc_get_symbol(s, "test");
91 if (!code) {
92 fprintf(stderr, "symbol 'test' not found\n");
93 return 2;
94 }
95
96 /*
97 * Scan for the 'call *%r11' instruction: 41 ff d3
98 * Then inspect the bytes immediately before it.
99 *
100 * Correct: 45 31 db 41 ff d3 (xor %r11d,%r11d ; call *%r11)
101 * Buggy: 31 db 41 ff d3 (xor %ebx,%ebx ; call *%r11)
102 */
103 for (i = 3; i < 128; i++) {
104 if (code[i] == 0x41 && code[i+1] == 0xff && code[i+2] == 0xd3) {
105 if (i >= 3 && code[i-3] == 0x45
106 && code[i-2] == 0x31
107 && code[i-1] == 0xdb) {
108 printf("xor_rex: OK\n");
109 } else if (i >= 2 && code[i-2] == 0x31 && code[i-1] == 0xdb) {
110 printf("xor_rex: FAIL - xor %%ebx,%%ebx (31 db) emitted"
111 " instead of xor %%r11d,%%r11d (45 31 db)\n");
112 ret = 1;
113 } else {
114 printf("xor_rex: FAIL - unexpected bytes before"
115 " call *%%r11: %02x %02x %02x %02x\n",
116 code[i-4], code[i-3], code[i-2], code[i-1]);
117 ret = 1;
118 }
119 goto done;
120 }
121 }
122 printf("xor_rex: SKIP - call *%%r11 not found in generated code\n");
123
124done:
125 tcc_delete(s);
126 return ret;
127}
128#endif
tests/nostdlib_test.c+0−155
@@ -1,155 +0,0 @@
1#!/usr/local/bin/tcc -run -nostdlib
2
3// Not working on windows and apple because of different API.
4
5#include <unistd.h>
6#include <sys/syscall.h>
7#if defined __x86_64__
8__asm__ ("syscall:\n\t"
9 "mov %rdi,%rax\n\t"
10 "mov %rsi,%rdi\n\t"
11 "mov %rdx,%rsi\n\t"
12 "mov %rcx,%rdx\n\t"
13 "mov %r8,%r10\n\t"
14 "mov %r9,%r8\n\t"
15 "mov 0x8(%rsp),%r9\n\t"
16 "syscall\n\t"
17 "ret");
18__asm__ (".global _start\n\t"
19 "_start:\n\t"
20 "mov 0(%rsp), %rdi\n\t"
21 "lea 8(%rsp), %rsi\n\t"
22 "jmp print");
23#elif defined __i386__
24__asm__ ("syscall:\n\t"
25 "push %ebp\n\t"
26 "push %edi\n\t"
27 "push %esi\n\t"
28 "push %ebx\n\t"
29 "mov 0x2c(%esp),%ebp\n\t"
30 "mov 0x28(%esp),%edi\n\t"
31 "mov 0x24(%esp),%esi\n\t"
32 "mov 0x20(%esp),%edx\n\t"
33 "mov 0x1c(%esp),%ecx\n\t"
34 "mov 0x18(%esp),%ebx\n\t"
35 "mov 0x14(%esp),%eax\n\t"
36 // "call *%gs:0x10\n\t"
37 ".byte 0x65,0xff,0x15,0x10,0x00,0x00,0x00\n\t"
38 "pop %ebx\n\t"
39 "pop %esi\n\t"
40 "pop %edi\n\t"
41 "pop %ebp\n\t"
42 "ret");
43__asm__ (".global _start\n\t"
44 "_start:\n\t"
45 "pop %esi\n\t"
46 "mov %esp, %ecx\n\t"
47 "and $0xfffffff0,%esp\n\t"
48 "push %ecx\n\t"
49 "push %esi\n\t"
50 "call print");
51#elif defined __arm__
52__asm__ ("syscall:\n\t"
53 "mov r12, sp\n\t"
54 "push {r4, r5, r6, r7}\n\t"
55 "mov r7, r0\n\t"
56 "mov r0, r1\n\t"
57 "mov r1, r2\n\t"
58 "mov r2, r3\n\t"
59 "ldm r12, {r3, r4, r5, r6}\n\t"
60 "svc 0x00000000\n\t"
61 "pop {r4, r5, r6, r7}\n\t"
62 "mov pc, lr");
63__asm__ (".global _start\n\t"
64 "_start:\n\t"
65 "pop {r0}\n\t"
66 "mov r1, sp\n\t"
67 "bl print");
68#elif defined __aarch64__
69__asm__ ("syscall:\n\t"
70 ".int 0x2a0003e8\n\t" // mov w8, w0
71 ".int 0xaa0103e0\n\t" // x0, x1
72 ".int 0xaa0203e1\n\t" // mov x1, x2
73 ".int 0xaa0303e2\n\t" // mov x2, x3
74 ".int 0xaa0403e3\n\t" // mov x3, x4
75 ".int 0xaa0503e4\n\t" // mov x4, x5
76 ".int 0xaa0603e5\n\t" // mov x5, x6
77 ".int 0xaa0703e6\n\t" // mov x6, x7
78 ".int 0xd4000001\n\t" // svc #0x0
79 ".int 0xd65f03c0"); // ret
80__asm__ (".global _start\n\t"
81 "_start:\n\t"
82 ".int 0xf94003e0\n\t" // ldr x0, [sp]
83 ".int 0x910023e1\n\t" // add x1, sp, #08
84 ".reloc .,R_AARCH64_CALL26,print\n\t"
85 ".int 0x94000000"); // bl print
86#elif defined __riscv
87__asm__ ("syscall:\n\t"
88 "mv t1,a0\n\t"
89 "mv a0,a1\n\t"
90 "mv a1,a2\n\t"
91 "mv a2,a3\n\t"
92 "mv a3,a4\n\t"
93 "mv a4,a5\n\t"
94 "mv a5,a6\n\t"
95 "mv a6,a7\n\t"
96 "mv a7,t1\n\t"
97 "ecall\n\t"
98 "ret");
99__asm__ (".global _start\n\t"
100 "_start:\n\t"
101 "ld a0,0(sp)\n\t"
102 "addi a1,sp,8\n\t"
103 "jal print");
104#endif
105unsigned long strlen(const char *s)
106{
107 unsigned long len = 0;
108
109 while (*s++)
110 len++;
111 return len;
112}
113
114static void pr_num(int num)
115{
116 char val[20], *p = &val[20];
117
118 *--p = '\0';
119 do {
120 int a = num, b = 0;
121
122 while (a >= 10) {
123 a -= 10;
124 b++;
125 }
126 *--p = a + '0';
127 num = b;
128 } while (num);
129 syscall(SYS_write, 1, p, strlen(p));
130}
131
132static void pr_str(int n, char *s)
133{
134 pr_num(n);
135 syscall(SYS_write, 1, ": ", 2);
136 syscall(SYS_write, 1, s, strlen(s));
137 syscall(SYS_write, 1, "\n", 1);
138}
139
140void print(int argc, char **argv) {
141 int i;
142 char **envp = &argv[argc + 1];
143
144 syscall(SYS_write, 1, "argc: ", 6);
145 pr_num(argc);
146 syscall(SYS_write, 1, "\n", 1);
147 syscall(SYS_write, 1, "argv[]\n", 7);
148 for (i = 0; i < argc; i++)
149 pr_str(i, argv[i]);
150 syscall(SYS_write, 1, "envp[]\n", 7);
151 i = 0;
152 while (*envp)
153 pr_str(i++, *envp++);
154 syscall(SYS_exit, 0);
155}
x86_64-gen.c+1−0
@@ -1840,6 +1840,7 @@ void gen_opf(int op) · 1839 unmodified lines
1840 o(0x80); /* xor $0x80, $n(rbp) */1840 o(0x80); /* xor $0x80, $n(rbp) */
1841 gen_modrm(6, vtop->r, NULL, vtop->c.i + (bt == VT_DOUBLE ? 7 : 3));1841 gen_modrm(6, vtop->r, NULL, vtop->c.i + (bt == VT_DOUBLE ? 7 : 3));
1842 o(0x80);1842 o(0x80);
1843 gv(float_type); /* -n is not a lvalue */
1843 }1844 }
1844 return;1845 return;
1845 }1846 }

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