History

Adjust return value promotion for some archs

this is a bit complicated: for i386 and x86-64 we really need to extend return values ourself, as the common code now does. For arm64 this at least preserves old behaviour. For riscv64 we don't have to extend ourself but can expect things to be extended up to int (this matters for var-args tests, when the sign-extension to int64 needs to happen explicitely). As the extensions are useless, don't do them. And for arm32 we actually can't express GCC behaviour: the callee side expects the return value to be correctly extended to int32, but remembers the original type. In case the ultimate target type for the call result is only int, no further extension is done. But in case the target type is e.g. int64 an extension happens, but not from int32 but from the original type. We don't know the ultimate target type, so we have to choose a type to put into vtop: * original type (plus VT_MUSTCAST) - this looses when the ultimate target is int (GCC: no cast, TCC: a cast) * int (without MUSTCAST) - this looses when the ultimate target is int64 (GCC: cast from original type, TCC: cast from int) This difference can only be seen with undefined sources, like the testcases, so it doesn't seem worthwhile to try an make it work, just disable the test on arm and choose the second variant as that generates less code.

Michael Matz committed 6 years ago

Commit c8ca64d1 parent 2d17e5a5 files · +26 −10Browse files

Unified · Split

5 files
  1. arm64-gen.c +3 −0
  2. i386-gen.c +4 −0
  3. tccgen.c +10 −2
  4. tests/tcctest.c +6 −8
  5. x86_64-gen.c +3 −0
arm64-gen.c+3−0
@@ -40,6 +40,9 @@ · 39 unmodified lines
40 40
41#define CHAR_IS_UNSIGNED41#define CHAR_IS_UNSIGNED
42 42
43/* define if return values need to be extended explicitely
44 at caller side (for interfacing with non-TCC compilers) */
45#define PROMOTE_RET
43/******************************************************/46/******************************************************/
44#else /* ! TARGET_DEFS_ONLY */47#else /* ! TARGET_DEFS_ONLY */
45/******************************************************/48/******************************************************/
i386-gen.c+4−0
@@ -71,6 +71,10 @@ enum { · 70 unmodified lines
71/* maximum alignment (for aligned attribute support) */71/* maximum alignment (for aligned attribute support) */
72#define MAX_ALIGN 872#define MAX_ALIGN 8
73 73
74/* define if return values need to be extended explicitely
75 at caller side (for interfacing with non-TCC compilers) */
76#define PROMOTE_RET
77
74/******************************************************/78/******************************************************/
75#else /* ! TARGET_DEFS_ONLY */79#else /* ! TARGET_DEFS_ONLY */
76/******************************************************/80/******************************************************/
tccgen.c+10−2
@@ -5631,10 +5631,18 @@ special_math_val: · 5630 unmodified lines
5631 }5631 }
5632 5632
5633 /* Promote char/short return values. This is matters only5633 /* Promote char/short return values. This is matters only
5634 for calling function that were not compiled by TCC */5634 for calling function that were not compiled by TCC and
5635 only on some architectures. For those where it doesn't
5636 matter we expect things to be already promoted to int,
5637 but not larger. */
5635 t = s->type.t & VT_BTYPE;5638 t = s->type.t & VT_BTYPE;
5636 if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL)5639 if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) {
5640#ifdef PROMOTE_RET
5637 vtop->r |= BFVAL(VT_MUSTCAST, 1);5641 vtop->r |= BFVAL(VT_MUSTCAST, 1);
5642#else
5643 vtop->type.t = VT_INT;
5644#endif
5645 }
5638 }5646 }
5639 if (s->f.func_noreturn)5647 if (s->f.func_noreturn)
5640 CODE_OFF();5648 CODE_OFF();
tests/tcctest.c+6−8
@@ -1210,13 +1210,7 @@ void struct_test() · 1209 unmodified lines
1210/* simulate char/short return value with undefined upper bits */1210/* simulate char/short return value with undefined upper bits */
1211static int __csf(int x) { return x; }1211static int __csf(int x) { return x; }
1212static void *_csf = __csf;1212static void *_csf = __csf;
1213#ifdef __TINYC__
1214#define csf(t,n) ((t(*)(int))_csf)(n)1213#define csf(t,n) ((t(*)(int))_csf)(n)
1215#define csfb csf
1216#else /* arm gcc maybe doesn't promote function return values */
1217#define csf(t,n) (t) n
1218#define csfb(t,n) (t) (n & 255)
1219#endif
1220 1214
1221/* XXX: depend on endianness */1215/* XXX: depend on endianness */
1222void char_short_test()1216void char_short_test()
@@ -1257,14 +1251,18 @@ void char_short_test() · 34 unmodified lines
1257 var4 = 0x11223344aa998877ULL;1251 var4 = 0x11223344aa998877ULL;
1258 printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);1252 printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);
1259 printf("promote char/short cast VA %d %d\n", (char)(var1 + 1), (char)(var4 + 1));1253 printf("promote char/short cast VA %d %d\n", (char)(var1 + 1), (char)(var4 + 1));
1254#if !defined(__arm__)
1255 /* We can't really express GCC behaviour of return type promotion in
1256 the presence of undefined behaviour (like __csf is). */
1260 var1 = csf(unsigned char,0x89898989);1257 var1 = csf(unsigned char,0x89898989);
1261 var4 = csf(signed char,0xabababab);1258 var4 = csf(signed char,0xabababab);
1262 printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);1259 printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);
1263 printf("promote char/short fumcret VA %d %d %d %d\n",1260 printf("promote char/short fumcret VA %d %d %d %d\n",
1264 csf(unsigned short,0xcdcdcdcd),1261 csf(unsigned short,0xcdcdcdcd),
1265 csf(short,0xefefefef),1262 csf(short,0xefefefef),
1266 csfb(_Bool,0x33221100),1263 csf(_Bool,0x33221100),
1267 csfb(_Bool,0x33221101));1264 csf(_Bool,0x33221101));
1265#endif
1268 var3 = -10;1266 var3 = -10;
1269 var1 = (char)(unsigned char)(var3 + 1);1267 var1 = (char)(unsigned char)(var3 + 1);
1270 var4 = (char)(unsigned char)(var3 + 1);1268 var4 = (char)(unsigned char)(var3 + 1);
x86_64-gen.c+3−0
@@ -102,6 +102,9 @@ enum { · 101 unmodified lines
102/* maximum alignment (for aligned attribute support) */102/* maximum alignment (for aligned attribute support) */
103#define MAX_ALIGN 16103#define MAX_ALIGN 16
104 104
105/* define if return values need to be extended explicitely
106 at caller side (for interfacing with non-TCC compilers) */
107#define PROMOTE_RET
105/******************************************************/108/******************************************************/
106#else /* ! TARGET_DEFS_ONLY */109#else /* ! TARGET_DEFS_ONLY */
107/******************************************************/110/******************************************************/

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