From af1abf1f45d45b34f0b02437f559f4dfdba7d23c Mon Sep 17 00:00:00 2001
From: grischka <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 */