From af1abf1f45d45b34f0b02437f559f4dfdba7d23c Mon Sep 17 00:00:00 2001 From: grischka Date: Fri, 15 Jul 2022 22:31:24 +0200 Subject: [PATCH] Revert "Fix wrong handling of strings..." (almost) See commit e588b65390bcfadabfb00c32ae0bfee12a8a8002. Was not "wrong" really, just different. But appears to be outdated. Now disabled by default (top of tccpp.c: ACCEPT_LF_IN_STRINGS) Also, in skipped code, just warn. Also: cleanup "Optimize small structure copying on x86_64" (commit 3715f1d7ee302c220d36f545107bbf808fd979d9) - remove some copy&paste coding (tccgen.c) - RSI/RDI need to be preserved on windows - simply don't use under bcheck (this is tinycc) --- lib/bcheck.c | 13 ------- tcc.h | 3 -- tccgen.c | 84 +++++++++++++++---------------------------- tccpp.c | 18 ++++++++-- tcctok.h | 1 - tests/tcctest.c | 39 ++++++++++++-------- tests/tests2/Makefile | 3 +- x86_64-gen.c | 70 +++++++++++++++--------------------- 8 files changed, 100 insertions(+), 131 deletions(-) diff --git a/lib/bcheck.c b/lib/bcheck.c index d64159b3..729f0b5d 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -294,7 +294,6 @@ DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); DLL_EXPORT char *__bound_strcat(char *dest, const char *src); DLL_EXPORT char *__bound_strchr(const char *string, int ch); DLL_EXPORT char *__bound_strdup(const char *s); -DLL_EXPORT void __bound_struct_copy(void *dst,void *src,size_t size); #if defined(__arm__) && defined(__ARM_EABI__) DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); @@ -427,7 +426,6 @@ static unsigned long long bound_strncmp_count; static unsigned long long bound_strcat_count; static unsigned long long bound_strchr_count; static unsigned long long bound_strdup_count; -static unsigned long long bound_struct_copy_count; static unsigned long long bound_not_found; #define INCR_COUNT(x) ++x #else @@ -1262,7 +1260,6 @@ void __attribute__((destructor)) __bound_exit(void) fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); - fprintf (stderr, "bound_struct_copy_count %llu\n", bound_struct_copy_count); fprintf (stderr, "bound_not_found %llu\n", bound_not_found); #endif #if BOUND_STATISTIC_SPLAY @@ -1786,16 +1783,6 @@ void *__bound_memset(void *s, int c, size_t n) return memset(s, c, n); } -void __bound_struct_copy(void *dst,void *src,size_t size) -{ - dprintf(stderr, "Copy struct from %p to %p,size %lx\n", - src,dst,size); - INCR_COUNT(bound_struct_copy_count); - __bound_check(dst,size,"struct copy destination"); - __bound_check(src,size,"struct copy source"); - return; -} - #if defined(__arm__) && defined(__ARM_EABI__) void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) { diff --git a/tcc.h b/tcc.h index 34db3728..d4708bbd 100644 --- a/tcc.h +++ b/tcc.h @@ -1644,8 +1644,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv); /* ------------ x86_64-gen.c ------------ */ #ifdef TCC_TARGET_X86_64 -#define TCC_TARGET_NATIVE_STRUCT_COPY -ST_FUNC void gen_struct_copy(int size); ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); ST_FUNC void gen_opl(int op); #ifdef TCC_TARGET_PE @@ -1691,7 +1689,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv); #endif /* ------------ tcccoff.c ------------ */ - #ifdef TCC_TARGET_COFF ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f); ST_FUNC int tcc_load_coff(TCCState * s1, int fd); diff --git a/tccgen.c b/tccgen.c index 6bfdf4b0..184ba54a 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3468,54 +3468,42 @@ ST_FUNC void vstore(void) ft = vtop[-1].type.t; sbt = vtop->type.t & VT_BTYPE; dbt = ft & VT_BTYPE; - verify_assign_cast(&vtop[-1].type); if (sbt == VT_STRUCT) { /* if structure, only generate pointer */ /* structure assignment : generate memcpy */ - size = type_size(&vtop->type, &align); + size = type_size(&vtop->type, &align); + /* destination, keep on stack() as result */ + vpushv(vtop - 1); +#ifdef CONFIG_TCC_BCHECK + if (vtop->r & VT_MUSTBOUND) + gbound(); /* check would be wrong after gaddrof() */ +#endif + vtop->type.t = VT_PTR; + gaddrof(); + /* source */ + vswap(); +#ifdef CONFIG_TCC_BCHECK + if (vtop->r & VT_MUSTBOUND) + gbound(); +#endif + vtop->type.t = VT_PTR; + gaddrof(); #ifdef TCC_TARGET_NATIVE_STRUCT_COPY - if (size <= (PTR_SIZE << 4)) { - vswap(); + if (1 #ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); + && !tcc_state->do_bounds_check #endif - vtop->type.t = VT_PTR; - gaddrof(); - - vpushv(vtop - 1); -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); + ) { + gen_struct_copy(size); + } else #endif - vtop->type.t = VT_PTR; - gaddrof(); /* src dest src */ -#ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check) { - vpush_helper_func(TOK___bound_struct_copy); - vpushv(vtop - 2); - vpushv(vtop - 2); - vpushi(size); - gfunc_call(3); - } -#endif - - gen_struct_copy(size); - } else { -#endif - /* destination */ - vswap(); -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); /* check would be wrong after gaddrof() */ -#endif - vtop->type.t = VT_PTR; - gaddrof(); - - /* address of memcpy() */ + { + /* type size */ + vpushi(size); + /* Use memmove, rather than memcpy, as dest and src may be same: */ #ifdef TCC_ARM_EABI if(!(align & 7)) vpush_helper_func(TOK_memmove8); @@ -3523,25 +3511,11 @@ ST_FUNC void vstore(void) vpush_helper_func(TOK_memmove4); else #endif - /* Use memmove, rather than memcpy, as dest and src may be same: */ vpush_helper_func(TOK_memmove); - - vswap(); - /* source */ - vpushv(vtop - 2); -#ifdef CONFIG_TCC_BCHECK - if (vtop->r & VT_MUSTBOUND) - gbound(); -#endif - vtop->type.t = VT_PTR; - gaddrof(); - /* type size */ - vpushi(size); + vrott(4); gfunc_call(3); - /* leave source on stack */ -#ifdef TCC_TARGET_NATIVE_STRUCT_COPY - } -#endif + } + } else if (ft & VT_BITFIELD) { /* bitfield store handling */ diff --git a/tccpp.c b/tccpp.c index f070640c..6a86f097 100644 --- a/tccpp.c +++ b/tccpp.c @@ -21,6 +21,9 @@ #define USING_GLOBALS #include "tcc.h" +/* #define to 1 to enable (see parse_pp_string()) */ +#define ACCEPT_LF_IN_STRINGS 0 + /********************************************************/ /* global variables */ @@ -944,16 +947,26 @@ static uint8_t *parse_pp_string(uint8_t *p, } } } else if (c == '\n') { - tcc_error("missing terminating %c character",sep); + add_lf: + if (ACCEPT_LF_IN_STRINGS) { + file->line_num++; + goto add_char; + } else if (str) { /* not skipping */ + goto unterminated_string; + } else { + tcc_warning("missing terminating %c character", sep); + return p; + } } else if (c == '\r') { PEEKC_EOB(c, p); if (c != '\n') { if (str) cstr_ccat(str, '\r'); } else { - tcc_error("missing terminating %c character",sep); + goto add_lf; } } else { + add_char: if (str) cstr_ccat(str, c); p++; @@ -1006,6 +1019,7 @@ redo_start: case '\'': if (in_warn_or_error) goto _default; + tok_flags &= ~TOK_FLAG_BOL; p = parse_pp_string(p, c, NULL); break; /* skip comments */ diff --git a/tcctok.h b/tcctok.h index ca09063b..d4c1ef5c 100644 --- a/tcctok.h +++ b/tcctok.h @@ -330,7 +330,6 @@ DEF(TOK___bound_setjmp, "__bound_setjmp") DEF(TOK___bound_longjmp, "__bound_longjmp") DEF(TOK___bound_new_region, "__bound_new_region") - DEF(TOK___bound_struct_copy,"__bound_struct_copy") # ifdef TCC_TARGET_PE # ifdef TCC_TARGET_X86_64 DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") diff --git a/tests/tcctest.c b/tests/tcctest.c index f7fbd656..5848ab80 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1519,8 +1519,6 @@ struct structa1 { char f2; }; -struct structa1 ssta1; - void struct_assign_test1(struct structa1 s1, int t, float f) { printf("%d %d %d %f\n", s1.f1, s1.f2, t, f); @@ -1538,22 +1536,12 @@ void struct_assign_test(void) struct S { struct structa1 lsta1, lsta2; int i; - } s, *ps; + } s = {{1,2}, {3,4}}, *ps; ps = &s; ps->i = 4; -#if 0 - s.lsta1.f1 = 1; - s.lsta1.f2 = 2; - printf("%d %d\n", s.lsta1.f1, s.lsta1.f2); - s.lsta2 = s.lsta1; - printf("%d %d\n", s.lsta2.f1, s.lsta2.f2); -#else - s.lsta2.f1 = 1; - s.lsta2.f2 = 2; -#endif + struct_assign_test1(ps->lsta2, 3, 4.5); - printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2); ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i); printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2); @@ -1565,6 +1553,9 @@ void struct_assign_test(void) { struct_assign_test } }; printf("%d\n", struct_assign_test == t[0].elem); + + s.lsta1 = s.lsta2 = struct_assign_test2(s.lsta1, 1); + printf("%d %d\n", s.lsta1.f1, s.lsta1.f2); } /* casts to short/char */ @@ -4253,6 +4244,12 @@ void func_arg_test(void) /* gcc 2.95.3 does not handle correctly CR in strings or after strays */ #define CORRECT_CR_HANDLING +/* deprecated and no longer supported in gcc 3.3 */ +/* no longer supported by default in TinyCC */ +#ifdef __TINYC__ +/* # define ACCEPT_LF_IN_STRINGS */ +#endif + /* keep this as the last test because GCC messes up line-numbers with the ^L^K^M characters below */ void whitespace_test(void) @@ -4274,6 +4271,20 @@ ntf("aaa=%d\n", 3); \ ntf("min=%d\n", 4); +#ifdef ACCEPT_LF_IN_STRINGS + printf("len1=%d\n", strlen(" +")); +#ifdef CORRECT_CR_HANDLING + str = " +"; + printf("len1=%d str[0]=%d\n", strlen(str), str[0]); +#endif + printf("len1=%d\n", strlen(" a +")); +#else + printf("len1=1\nlen1=1 str[0]=10\nlen1=3\n"); +#endif /* ACCEPT_LF_IN_STRINGS */ + #ifdef __LINE__ printf("__LINE__ defined\n"); #endif diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 23482e8c..776c7276 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -105,8 +105,7 @@ GEN-ALWAYS = 112_backtrace.test: FLAGS += -dt -b 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ - -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' \ - -e 's;struct copy destination;memmove dest;g' \ + -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' # this test creates two DLLs and an EXE 113_btdll.test: T1 = \ diff --git a/x86_64-gen.c b/x86_64-gen.c index cad4da16..26435fa9 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -35,6 +35,8 @@ #define RC_RAX 0x0004 #define RC_RCX 0x0008 #define RC_RDX 0x0010 +#define RC_RSI 0x0020 +#define RC_RDI 0x0040 #define RC_ST0 0x0080 /* only for long double */ #define RC_R8 0x0100 #define RC_R9 0x0200 @@ -105,6 +107,10 @@ enum { /* define if return values need to be extended explicitely at caller side (for interfacing with non-TCC compilers) */ #define PROMOTE_RET + +#define TCC_TARGET_NATIVE_STRUCT_COPY +ST_FUNC void gen_struct_copy(int size); + /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ @@ -124,8 +130,8 @@ ST_DATA const int reg_classes[NB_REGS] = { 0, 0, 0, - 0, - 0, + RC_RSI, + RC_RDI, RC_R8, RC_R9, RC_R10, @@ -2228,7 +2234,7 @@ ST_FUNC void gen_increment_tcov (SValue *sv) } /* computed goto support */ -void ggoto(void) +ST_FUNC void ggoto(void) { gcall_or_jmp(1); vtop--; @@ -2286,53 +2292,35 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { * Assmuing the top part of the stack looks like below, * src dest src */ -void gen_struct_copy(int size) +ST_FUNC void gen_struct_copy(int size) { - save_reg(TREG_RSI); - load(TREG_RSI,vtop); - vtop->r = TREG_RSI; - vswap(); /* dest src src */ - save_reg(TREG_RDI); - load(TREG_RDI,vtop); - vtop->r = TREG_RDI; - /* Not aligned by 8bytes */ - if (size & 0x04) { - o(0xa5); - } - if (size & 0x02) { - o(0xa566); - } - if (size & 0x01) { - o(0xa4); - } - - size >>= 3; - if (!size) - goto done; - /* Although this function is only called when the struct is smaller */ - /* than 32 bytes(4 * PTR_SIZE),a common implementation is included */ - if (size <= 4 && size) { - switch (size) { - case 4: o(0xa548); - case 3: o(0xa548); - case 2: o(0xa548); - case 1: o(0xa548); - } + int n = size / PTR_SIZE; +#ifdef TCC_TARGET_PE + o(0x5756); /* push rsi, rdi */ +#endif + gv2(RC_RDI, RC_RSI); + if (n <= 4) { + while (n) + o(0xa548), --n; } else { - save_reg(TREG_RCX); - vpushi(size); - load(TREG_RCX,vtop); - vtop->r = TREG_RCX; + vpushi(n); + gv(RC_RCX); o(0xa548f3); vpop(); } -done: + if (size & 0x04) + o(0xa5); + if (size & 0x02) + o(0xa566); + if (size & 0x01) + o(0xa4); +#ifdef TCC_TARGET_PE + o(0x5e5f); /* pop rdi, rsi */ +#endif vpop(); vpop(); - return; } - /* end of x86-64 code generator */ /*************************************************************/ #endif /* ! TARGET_DEFS_ONLY */