From 19ef024aa9c11a75bc441ed687e60974254c204b Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 25 Apr 2023 08:59:42 +0200 Subject: [PATCH] lib/armeabi.c: fix zero from/to double conversion tccgen.c: - allow cross-compiling 0.0L (cross-compile tcc with tcc) tccelf.c: - use alignment of TLS section for PT_TLS tccpp.c: - support long double constants on systems that do not support long doubles (i.e. mark them (VT_DOUBLE | VT_LONG)) tccdefs.h: #define __has_feature() for android remove _unaligned (why define a msvc extension under !_WIN32) --- include/tccdefs.h | 9 ++------- lib/armeabi.c | 9 ++++++++- tccelf.c | 3 ++- tccgen.c | 15 +++++++++++---- tccpp.c | 29 +++++++++++++++-------------- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/include/tccdefs.h b/include/tccdefs.h index e2e1b264..b995d5b9 100644 --- a/include/tccdefs.h +++ b/include/tccdefs.h @@ -18,7 +18,7 @@ #if __SIZEOF_POINTER__ == 4 /* 32bit systems. */ -#if defined TARGETOS_OpenBSD +#if defined __OpenBSD__ #define __SIZE_TYPE__ unsigned long #define __PTRDIFF_TYPE__ long #else @@ -68,12 +68,6 @@ #define __WINT_TYPE__ int #endif -#if !defined _WIN32 - /* extension to generate different code on old cpu's (>20y ago) */ - #define _unaligned - #define __unaligned -#endif - #if __STDC_VERSION__ >= 201112L # define __STDC_NO_ATOMICS__ 1 # define __STDC_NO_COMPLEX__ 1 @@ -135,6 +129,7 @@ #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD #define __PRETTY_FUNCTION__ __FUNCTION__ #define __has_builtin(x) 0 + #define __has_feature(x) 0 #define _Nonnull #define _Nullable diff --git a/lib/armeabi.c b/lib/armeabi.c index 1bccbd3b..6ade65ef 100644 --- a/lib/armeabi.c +++ b/lib/armeabi.c @@ -137,6 +137,11 @@ void __aeabi_ ## name(double_unsigned_struct val) \ int exp, high_shift, sign; \ double_unsigned_struct ret; \ \ + if ((val.high & ~0x80000000) == 0 && val.low == 0) { \ + ret.low = ret.high = 0; \ + goto _ret_; \ + } \ + \ /* compute sign */ \ sign = val.high >> 31; \ \ @@ -190,6 +195,7 @@ void __aeabi_ ## name(double_unsigned_struct val) \ ret.low++; \ } \ \ +_ret_: \ double_unsigned_struct_return(ret); \ } @@ -313,7 +319,7 @@ void __aeabi_ ## name(unsigned long long v) \ } \ } else { \ ret.high = ret.low = 0; \ - double_unsigned_struct_return(ret); \ + goto _ret_; \ } \ } \ \ @@ -323,6 +329,7 @@ void __aeabi_ ## name(unsigned long long v) \ /* fill sign bit */ \ ret.high |= sign << 31; \ \ +_ret_: \ double_unsigned_struct_return(ret); \ } diff --git a/tccelf.c b/tccelf.c index 15ed168c..ec317b31 100644 --- a/tccelf.c +++ b/tccelf.c @@ -2277,8 +2277,9 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) ph->p_flags |= PF_X; if (f & SHF_TLS) { ph->p_type = PT_TLS; - ph->p_align = 4; + ph->p_align = align + 1; } + ph->p_offset = file_offset; ph->p_vaddr = addr; if (n == 0) { diff --git a/tccgen.c b/tccgen.c index e4f46f39..b45a172b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3147,7 +3147,10 @@ error: c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; #if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387 - c &= (dbt != VT_LDOUBLE) | !!nocode_wanted; + /* don't try to convert to ldouble when cross-compiling + (except when it's '0' which is needed for arm:gen_negf()) */ + if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0)) + c = 0; #endif if (c) { /* constant case: we can do it now */ @@ -5449,7 +5452,11 @@ ST_FUNC void unary(void) t = VT_DOUBLE; goto push_tokc; case TOK_CLDOUBLE: +#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE + t = VT_DOUBLE | VT_LONG; +#else t = VT_LDOUBLE; +#endif goto push_tokc; case TOK_CLONG: t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG; @@ -7662,8 +7669,6 @@ static void init_putv(init_params *p, CType *type, unsigned long c) else if (sizeof (long double) == sizeof (double)) __asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld)); #endif - else if (vtop->c.ld == 0.0) - ; else #endif /* For other platforms it should work natively, but may not work @@ -7671,7 +7676,9 @@ static void init_putv(init_params *p, CType *type, unsigned long c) if (sizeof(long double) == LDOUBLE_SIZE) memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE); else if (sizeof(double) == LDOUBLE_SIZE) - memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE); + *(double*)ptr = (double)vtop->c.ld; + else if (0 == memcmp(ptr, &vtop->c.ld, LDOUBLE_SIZE)) + ; /* nothing to do for 0.0 */ #ifndef TCC_CROSS_TEST else tcc_error("can't cross compile long double constants"); diff --git a/tccpp.c b/tccpp.c index cef93826..5192e028 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1002,7 +1002,11 @@ static inline int tok_size(const int *p) case TOK_CULLONG: return 1 + 2; case TOK_CLDOUBLE: +#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE + return 1 + 8 / 4; +#else return 1 + LDOUBLE_SIZE / 4; +#endif default: return 1 + 0; } @@ -1143,25 +1147,24 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) #if LONG_SIZE == 8 case TOK_CLONG: case TOK_CULONG: -#endif -#if LDOUBLE_SIZE == 8 - case TOK_CLDOUBLE: #endif str[len++] = cv->tab[0]; str[len++] = cv->tab[1]; break; -#if LDOUBLE_SIZE == 12 case TOK_CLDOUBLE: +#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE + str[len++] = cv->tab[0]; + str[len++] = cv->tab[1]; +#elif LDOUBLE_SIZE == 12 str[len++] = cv->tab[0]; str[len++] = cv->tab[1]; str[len++] = cv->tab[2]; #elif LDOUBLE_SIZE == 16 - case TOK_CLDOUBLE: str[len++] = cv->tab[0]; str[len++] = cv->tab[1]; str[len++] = cv->tab[2]; str[len++] = cv->tab[3]; -#elif LDOUBLE_SIZE != 8 +#else #error add long double size support #endif break; @@ -1229,12 +1232,12 @@ static inline void tok_get(int *t, const int **pp, CValue *cv) n = 2; goto copy; case TOK_CLDOUBLE: -#if LDOUBLE_SIZE == 16 - n = 4; +#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE + n = 2; #elif LDOUBLE_SIZE == 12 n = 3; -#elif LDOUBLE_SIZE == 8 - n = 2; +#elif LDOUBLE_SIZE == 16 + n = 4; #else # error add long double size support #endif @@ -2334,11 +2337,10 @@ static void parse_number(const char *p) tokc.f = (float)d; } else if (t == 'L') { ch = *p++; + tok = TOK_CLDOUBLE; #ifdef TCC_USING_DOUBLE_FOR_LDOUBLE - tok = TOK_CDOUBLE; tokc.d = d; #else - tok = TOK_CLDOUBLE; /* XXX: not large enough */ tokc.ld = (long double)d; #endif @@ -2390,11 +2392,10 @@ static void parse_number(const char *p) tokc.f = strtof(token_buf, NULL); } else if (t == 'L') { ch = *p++; + tok = TOK_CLDOUBLE; #ifdef TCC_USING_DOUBLE_FOR_LDOUBLE - tok = TOK_CDOUBLE; tokc.d = strtod(token_buf, NULL); #else - tok = TOK_CLDOUBLE; tokc.ld = strtold(token_buf, NULL); #endif } else {