diff --git a/arm64-gen.c b/arm64-gen.c index 5ea47db4..35538d1a 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -40,6 +40,9 @@ #define CHAR_IS_UNSIGNED +/* define if return values need to be extended explicitely + at caller side (for interfacing with non-TCC compilers) */ +#define PROMOTE_RET /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ diff --git a/i386-gen.c b/i386-gen.c index 8b81c66f..7e1e0f49 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -71,6 +71,10 @@ enum { /* maximum alignment (for aligned attribute support) */ #define MAX_ALIGN 8 +/* define if return values need to be extended explicitely + at caller side (for interfacing with non-TCC compilers) */ +#define PROMOTE_RET + /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ diff --git a/tccgen.c b/tccgen.c index 0475b3c5..0f3d96ec 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5631,10 +5631,18 @@ special_math_val: } /* Promote char/short return values. This is matters only - for calling function that were not compiled by TCC */ + for calling function that were not compiled by TCC and + only on some architectures. For those where it doesn't + matter we expect things to be already promoted to int, + but not larger. */ t = s->type.t & VT_BTYPE; - if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) + if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) { +#ifdef PROMOTE_RET vtop->r |= BFVAL(VT_MUSTCAST, 1); +#else + vtop->type.t = VT_INT; +#endif + } } if (s->f.func_noreturn) CODE_OFF(); diff --git a/tests/tcctest.c b/tests/tcctest.c index 15d849ca..373eb952 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1210,13 +1210,7 @@ void struct_test() /* simulate char/short return value with undefined upper bits */ static int __csf(int x) { return x; } static void *_csf = __csf; -#ifdef __TINYC__ #define csf(t,n) ((t(*)(int))_csf)(n) -#define csfb csf -#else /* arm gcc maybe doesn't promote function return values */ -#define csf(t,n) (t) n -#define csfb(t,n) (t) (n & 255) -#endif /* XXX: depend on endianness */ void char_short_test() @@ -1257,14 +1251,18 @@ void char_short_test() var4 = 0x11223344aa998877ULL; printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1); printf("promote char/short cast VA %d %d\n", (char)(var1 + 1), (char)(var4 + 1)); +#if !defined(__arm__) + /* We can't really express GCC behaviour of return type promotion in + the presence of undefined behaviour (like __csf is). */ var1 = csf(unsigned char,0x89898989); var4 = csf(signed char,0xabababab); printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4); printf("promote char/short fumcret VA %d %d %d %d\n", csf(unsigned short,0xcdcdcdcd), csf(short,0xefefefef), - csfb(_Bool,0x33221100), - csfb(_Bool,0x33221101)); + csf(_Bool,0x33221100), + csf(_Bool,0x33221101)); +#endif var3 = -10; var1 = (char)(unsigned char)(var3 + 1); var4 = (char)(unsigned char)(var3 + 1); diff --git a/x86_64-gen.c b/x86_64-gen.c index fd2d6936..439fd988 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -102,6 +102,9 @@ enum { /* maximum alignment (for aligned attribute support) */ #define MAX_ALIGN 16 +/* define if return values need to be extended explicitely + at caller side (for interfacing with non-TCC compilers) */ +#define PROMOTE_RET /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/