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)
Unified · Split
| @@ -294,7 +294,6 @@ DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); · 293 unmodified lines | |||
| 294 | DLL_EXPORT char *__bound_strcat(char *dest, const char *src); | 294 | DLL_EXPORT char *__bound_strcat(char *dest, const char *src); |
| 295 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); | 295 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); |
| 296 | DLL_EXPORT char *__bound_strdup(const char *s); | 296 | DLL_EXPORT char *__bound_strdup(const char *s); |
| 297 | DLL_EXPORT void __bound_struct_copy(void *dst,void *src,size_t size); | ||
| 298 | 297 | ||
| 299 | #if defined(__arm__) && defined(__ARM_EABI__) | 298 | #if defined(__arm__) && defined(__ARM_EABI__) |
| 300 | DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); | 299 | 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; · 126 unmodified lines | |||
| 427 | static unsigned long long bound_strcat_count; | 426 | static unsigned long long bound_strcat_count; |
| 428 | static unsigned long long bound_strchr_count; | 427 | static unsigned long long bound_strchr_count; |
| 429 | static unsigned long long bound_strdup_count; | 428 | static unsigned long long bound_strdup_count; |
| 430 | static unsigned long long bound_struct_copy_count; | ||
| 431 | static unsigned long long bound_not_found; | 429 | static unsigned long long bound_not_found; |
| 432 | #define INCR_COUNT(x) ++x | 430 | #define INCR_COUNT(x) ++x |
| 433 | #else | 431 | #else |
| @@ -1262,7 +1260,6 @@ void __attribute__((destructor)) __bound_exit(void) · 828 unmodified lines | |||
| 1262 | fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); | 1260 | fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count); |
| 1263 | fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); | 1261 | fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count); |
| 1264 | fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); | 1262 | fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count); |
| 1265 | fprintf (stderr, "bound_struct_copy_count %llu\n", bound_struct_copy_count); | ||
| 1266 | fprintf (stderr, "bound_not_found %llu\n", bound_not_found); | 1263 | fprintf (stderr, "bound_not_found %llu\n", bound_not_found); |
| 1267 | #endif | 1264 | #endif |
| 1268 | #if BOUND_STATISTIC_SPLAY | 1265 | #if BOUND_STATISTIC_SPLAY |
| @@ -1786,16 +1783,6 @@ void *__bound_memset(void *s, int c, size_t n) · 517 unmodified lines | |||
| 1786 | return memset(s, c, n); | 1783 | return memset(s, c, n); |
| 1787 | } | 1784 | } |
| 1788 | 1785 | ||
| 1789 | void __bound_struct_copy(void *dst,void *src,size_t size) | ||
| 1790 | { | ||
| 1791 | dprintf(stderr, "Copy struct from %p to %p,size %lx\n", | ||
| 1792 | src,dst,size); | ||
| 1793 | INCR_COUNT(bound_struct_copy_count); | ||
| 1794 | __bound_check(dst,size,"struct copy destination"); | ||
| 1795 | __bound_check(src,size,"struct copy source"); | ||
| 1796 | return; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | #if defined(__arm__) && defined(__ARM_EABI__) | 1786 | #if defined(__arm__) && defined(__ARM_EABI__) |
| 1800 | void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) | 1787 | void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) |
| 1801 | { | 1788 | { |
| @@ -1644,8 +1644,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv); · 1643 unmodified lines | |||
| 1644 | 1644 | ||
| 1645 | /* ------------ x86_64-gen.c ------------ */ | 1645 | /* ------------ x86_64-gen.c ------------ */ |
| 1646 | #ifdef TCC_TARGET_X86_64 | 1646 | #ifdef TCC_TARGET_X86_64 |
| 1647 | #define TCC_TARGET_NATIVE_STRUCT_COPY | ||
| 1648 | ST_FUNC void gen_struct_copy(int size); | ||
| 1649 | ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); | 1647 | ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); |
| 1650 | ST_FUNC void gen_opl(int op); | 1648 | ST_FUNC void gen_opl(int op); |
| 1651 | #ifdef TCC_TARGET_PE | 1649 | #ifdef TCC_TARGET_PE |
| @@ -1691,7 +1689,6 @@ ST_FUNC void gen_increment_tcov (SValue *sv); · 39 unmodified lines | |||
| 1691 | #endif | 1689 | #endif |
| 1692 | 1690 | ||
| 1693 | /* ------------ tcccoff.c ------------ */ | 1691 | /* ------------ tcccoff.c ------------ */ |
| 1694 | |||
| 1695 | #ifdef TCC_TARGET_COFF | 1692 | #ifdef TCC_TARGET_COFF |
| 1696 | ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f); | 1693 | ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f); |
| 1697 | ST_FUNC int tcc_load_coff(TCCState * s1, int fd); | 1694 | ST_FUNC int tcc_load_coff(TCCState * s1, int fd); |
| @@ -3468,54 +3468,42 @@ ST_FUNC void vstore(void) · 3467 unmodified lines | |||
| 3468 | ft = vtop[-1].type.t; | 3468 | ft = vtop[-1].type.t; |
| 3469 | sbt = vtop->type.t & VT_BTYPE; | 3469 | sbt = vtop->type.t & VT_BTYPE; |
| 3470 | dbt = ft & VT_BTYPE; | 3470 | dbt = ft & VT_BTYPE; |
| 3471 | |||
| 3472 | verify_assign_cast(&vtop[-1].type); | 3471 | verify_assign_cast(&vtop[-1].type); |
| 3473 | 3472 | ||
| 3474 | if (sbt == VT_STRUCT) { | 3473 | if (sbt == VT_STRUCT) { |
| 3475 | /* if structure, only generate pointer */ | 3474 | /* if structure, only generate pointer */ |
| 3476 | /* structure assignment : generate memcpy */ | 3475 | /* structure assignment : generate memcpy */ |
| 3477 | size = type_size(&vtop->type, &align); | 3476 | size = type_size(&vtop->type, &align); |
| 3478 | 3477 | /* destination, keep on stack() as result */ | |
| 3479 | #ifdef TCC_TARGET_NATIVE_STRUCT_COPY | 3478 | vpushv(vtop - 1); |
| 3480 | if (size <= (PTR_SIZE << 4)) { | ||
| 3481 | vswap(); | ||
| 3482 | #ifdef CONFIG_TCC_BCHECK | 3479 | #ifdef CONFIG_TCC_BCHECK |
| 3483 | if (vtop->r & VT_MUSTBOUND) | 3480 | if (vtop->r & VT_MUSTBOUND) |
| 3484 | gbound(); | 3481 | gbound(); /* check would be wrong after gaddrof() */ |
| 3485 | #endif | 3482 | #endif |
| 3486 | vtop->type.t = VT_PTR; | 3483 | vtop->type.t = VT_PTR; |
| 3487 | gaddrof(); | 3484 | gaddrof(); |
| 3488 | 3485 | /* source */ | |
| 3489 | vpushv(vtop - 1); | 3486 | vswap(); |
| 3490 | #ifdef CONFIG_TCC_BCHECK | ||
| 3491 | if (vtop->r & VT_MUSTBOUND) | ||
| 3492 | gbound(); | ||
| 3493 | #endif | ||
| 3494 | vtop->type.t = VT_PTR; | ||
| 3495 | gaddrof(); /* src dest src */ | ||
| 3496 | #ifdef CONFIG_TCC_BCHECK | 3487 | #ifdef CONFIG_TCC_BCHECK |
| 3497 | if (tcc_state->do_bounds_check) { | 3488 | if (vtop->r & VT_MUSTBOUND) |
| 3498 | vpush_helper_func(TOK___bound_struct_copy); | 3489 | gbound(); |
| 3499 | vpushv(vtop - 2); | ||
| 3500 | vpushv(vtop - 2); | ||
| 3501 | vpushi(size); | ||
| 3502 | gfunc_call(3); | ||
| 3503 | } | ||
| 3504 | #endif | 3490 | #endif |
| 3491 | vtop->type.t = VT_PTR; | ||
| 3492 | gaddrof(); | ||
| 3505 | 3493 | ||
| 3506 | gen_struct_copy(size); | 3494 | #ifdef TCC_TARGET_NATIVE_STRUCT_COPY |
| 3507 | } else { | 3495 | if (1 |
| 3508 | #endif | ||
| 3509 | /* destination */ | ||
| 3510 | vswap(); | ||
| 3511 | #ifdef CONFIG_TCC_BCHECK | 3496 | #ifdef CONFIG_TCC_BCHECK |
| 3512 | if (vtop->r & VT_MUSTBOUND) | 3497 | && !tcc_state->do_bounds_check |
| 3513 | gbound(); /* check would be wrong after gaddrof() */ | ||
| 3514 | #endif | 3498 | #endif |
| 3515 | vtop->type.t = VT_PTR; | 3499 | ) { |
| 3516 | gaddrof(); | 3500 | gen_struct_copy(size); |
| 3517 | 3501 | } else | |
| 3518 | /* address of memcpy() */ | 3502 | #endif |
| 3503 | { | ||
| 3504 | /* type size */ | ||
| 3505 | vpushi(size); | ||
| 3506 | /* Use memmove, rather than memcpy, as dest and src may be same: */ | ||
| 3519 | #ifdef TCC_ARM_EABI | 3507 | #ifdef TCC_ARM_EABI |
| 3520 | if(!(align & 7)) | 3508 | if(!(align & 7)) |
| 3521 | vpush_helper_func(TOK_memmove8); | 3509 | vpush_helper_func(TOK_memmove8); |
| @@ -3523,25 +3511,11 @@ ST_FUNC void vstore(void) · 1 unmodified line | |||
| 3523 | vpush_helper_func(TOK_memmove4); | 3511 | vpush_helper_func(TOK_memmove4); |
| 3524 | else | 3512 | else |
| 3525 | #endif | 3513 | #endif |
| 3526 | /* Use memmove, rather than memcpy, as dest and src may be same: */ | ||
| 3527 | vpush_helper_func(TOK_memmove); | 3514 | vpush_helper_func(TOK_memmove); |
| 3528 | 3515 | vrott(4); | |
| 3529 | vswap(); | ||
| 3530 | /* source */ | ||
| 3531 | vpushv(vtop - 2); | ||
| 3532 | #ifdef CONFIG_TCC_BCHECK | ||
| 3533 | if (vtop->r & VT_MUSTBOUND) | ||
| 3534 | gbound(); | ||
| 3535 | #endif | ||
| 3536 | vtop->type.t = VT_PTR; | ||
| 3537 | gaddrof(); | ||
| 3538 | /* type size */ | ||
| 3539 | vpushi(size); | ||
| 3540 | gfunc_call(3); | 3516 | gfunc_call(3); |
| 3541 | /* leave source on stack */ | 3517 | } |
| 3542 | #ifdef TCC_TARGET_NATIVE_STRUCT_COPY | 3518 | |
| 3543 | } | ||
| 3544 | #endif | ||
| 3545 | } else if (ft & VT_BITFIELD) { | 3519 | } else if (ft & VT_BITFIELD) { |
| 3546 | /* bitfield store handling */ | 3520 | /* bitfield store handling */ |
| 3547 | 3521 | ||
| @@ -21,6 +21,9 @@ · 20 unmodified lines | |||
| 21 | #define USING_GLOBALS | 21 | #define USING_GLOBALS |
| 22 | #include "tcc.h" | 22 | #include "tcc.h" |
| 23 | 23 | ||
| 24 | /* #define to 1 to enable (see parse_pp_string()) */ | ||
| 25 | #define ACCEPT_LF_IN_STRINGS 0 | ||
| 26 | |||
| 24 | /********************************************************/ | 27 | /********************************************************/ |
| 25 | /* global variables */ | 28 | /* global variables */ |
| 26 | 29 | ||
| @@ -944,16 +947,26 @@ static uint8_t *parse_pp_string(uint8_t *p, · 917 unmodified lines | |||
| 944 | } | 947 | } |
| 945 | } | 948 | } |
| 946 | } else if (c == '\n') { | 949 | } else if (c == '\n') { |
| 947 | tcc_error("missing terminating %c character",sep); | 950 | add_lf: |
| 951 | if (ACCEPT_LF_IN_STRINGS) { | ||
| 952 | file->line_num++; | ||
| 953 | goto add_char; | ||
| 954 | } else if (str) { /* not skipping */ | ||
| 955 | goto unterminated_string; | ||
| 956 | } else { | ||
| 957 | tcc_warning("missing terminating %c character", sep); | ||
| 958 | return p; | ||
| 959 | } | ||
| 948 | } else if (c == '\r') { | 960 | } else if (c == '\r') { |
| 949 | PEEKC_EOB(c, p); | 961 | PEEKC_EOB(c, p); |
| 950 | if (c != '\n') { | 962 | if (c != '\n') { |
| 951 | if (str) | 963 | if (str) |
| 952 | cstr_ccat(str, '\r'); | 964 | cstr_ccat(str, '\r'); |
| 953 | } else { | 965 | } else { |
| 954 | tcc_error("missing terminating %c character",sep); | 966 | goto add_lf; |
| 955 | } | 967 | } |
| 956 | } else { | 968 | } else { |
| 969 | add_char: | ||
| 957 | if (str) | 970 | if (str) |
| 958 | cstr_ccat(str, c); | 971 | cstr_ccat(str, c); |
| 959 | p++; | 972 | p++; |
| @@ -1006,6 +1019,7 @@ redo_start: · 46 unmodified lines | |||
| 1006 | case '\'': | 1019 | case '\'': |
| 1007 | if (in_warn_or_error) | 1020 | if (in_warn_or_error) |
| 1008 | goto _default; | 1021 | goto _default; |
| 1022 | tok_flags &= ~TOK_FLAG_BOL; | ||
| 1009 | p = parse_pp_string(p, c, NULL); | 1023 | p = parse_pp_string(p, c, NULL); |
| 1010 | break; | 1024 | break; |
| 1011 | /* skip comments */ | 1025 | /* skip comments */ |
| @@ -330,7 +330,6 @@ · 329 unmodified lines | |||
| 330 | DEF(TOK___bound_setjmp, "__bound_setjmp") | 330 | DEF(TOK___bound_setjmp, "__bound_setjmp") |
| 331 | DEF(TOK___bound_longjmp, "__bound_longjmp") | 331 | DEF(TOK___bound_longjmp, "__bound_longjmp") |
| 332 | DEF(TOK___bound_new_region, "__bound_new_region") | 332 | DEF(TOK___bound_new_region, "__bound_new_region") |
| 333 | DEF(TOK___bound_struct_copy,"__bound_struct_copy") | ||
| 334 | # ifdef TCC_TARGET_PE | 333 | # ifdef TCC_TARGET_PE |
| 335 | # ifdef TCC_TARGET_X86_64 | 334 | # ifdef TCC_TARGET_X86_64 |
| 336 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") | 335 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") |
| @@ -1519,8 +1519,6 @@ struct structa1 { · 1518 unmodified lines | |||
| 1519 | char f2; | 1519 | char f2; |
| 1520 | }; | 1520 | }; |
| 1521 | 1521 | ||
| 1522 | struct structa1 ssta1; | ||
| 1523 | |||
| 1524 | void struct_assign_test1(struct structa1 s1, int t, float f) | 1522 | void struct_assign_test1(struct structa1 s1, int t, float f) |
| 1525 | { | 1523 | { |
| 1526 | printf("%d %d %d %f\n", s1.f1, s1.f2, t, f); | 1524 | printf("%d %d %d %f\n", s1.f1, s1.f2, t, f); |
| @@ -1538,22 +1536,12 @@ void struct_assign_test(void) · 11 unmodified lines | |||
| 1538 | struct S { | 1536 | struct S { |
| 1539 | struct structa1 lsta1, lsta2; | 1537 | struct structa1 lsta1, lsta2; |
| 1540 | int i; | 1538 | int i; |
| 1541 | } s, *ps; | 1539 | } s = {{1,2}, {3,4}}, *ps; |
| 1542 | 1540 | ||
| 1543 | ps = &s; | 1541 | ps = &s; |
| 1544 | ps->i = 4; | 1542 | ps->i = 4; |
| 1545 | #if 0 | 1543 | |
| 1546 | s.lsta1.f1 = 1; | ||
| 1547 | s.lsta1.f2 = 2; | ||
| 1548 | printf("%d %d\n", s.lsta1.f1, s.lsta1.f2); | ||
| 1549 | s.lsta2 = s.lsta1; | ||
| 1550 | printf("%d %d\n", s.lsta2.f1, s.lsta2.f2); | ||
| 1551 | #else | ||
| 1552 | s.lsta2.f1 = 1; | ||
| 1553 | s.lsta2.f2 = 2; | ||
| 1554 | #endif | ||
| 1555 | struct_assign_test1(ps->lsta2, 3, 4.5); | 1544 | struct_assign_test1(ps->lsta2, 3, 4.5); |
| 1556 | |||
| 1557 | printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2); | 1545 | printf("before call: %d %d\n", s.lsta2.f1, s.lsta2.f2); |
| 1558 | ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i); | 1546 | ps->lsta2 = struct_assign_test2(ps->lsta2, ps->i); |
| 1559 | printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2); | 1547 | printf("after call: %d %d\n", ps->lsta2.f1, ps->lsta2.f2); |
| @@ -1565,6 +1553,9 @@ void struct_assign_test(void) · 5 unmodified lines | |||
| 1565 | { struct_assign_test } | 1553 | { struct_assign_test } |
| 1566 | }; | 1554 | }; |
| 1567 | printf("%d\n", struct_assign_test == t[0].elem); | 1555 | printf("%d\n", struct_assign_test == t[0].elem); |
| 1556 | |||
| 1557 | s.lsta1 = s.lsta2 = struct_assign_test2(s.lsta1, 1); | ||
| 1558 | printf("%d %d\n", s.lsta1.f1, s.lsta1.f2); | ||
| 1568 | } | 1559 | } |
| 1569 | 1560 | ||
| 1570 | /* casts to short/char */ | 1561 | /* casts to short/char */ |
| @@ -4253,6 +4244,12 @@ void func_arg_test(void) · 2682 unmodified lines | |||
| 4253 | /* gcc 2.95.3 does not handle correctly CR in strings or after strays */ | 4244 | /* gcc 2.95.3 does not handle correctly CR in strings or after strays */ |
| 4254 | #define CORRECT_CR_HANDLING | 4245 | #define CORRECT_CR_HANDLING |
| 4255 | 4246 | ||
| 4247 | /* deprecated and no longer supported in gcc 3.3 */ | ||
| 4248 | /* no longer supported by default in TinyCC */ | ||
| 4249 | #ifdef __TINYC__ | ||
| 4250 | /* # define ACCEPT_LF_IN_STRINGS */ | ||
| 4251 | #endif | ||
| 4252 | |||
| 4256 | /* keep this as the last test because GCC messes up line-numbers | 4253 | /* keep this as the last test because GCC messes up line-numbers |
| 4257 | with the ^L^K^M characters below */ | 4254 | with the ^L^K^M characters below */ |
| 4258 | void whitespace_test(void) | 4255 | void whitespace_test(void) |
| @@ -4274,6 +4271,20 @@ ntf("aaa=%d\n", 3); · 15 unmodified lines | |||
| 4274 | \ | 4271 | \ |
| 4275 | ntf("min=%d\n", 4); | 4272 | ntf("min=%d\n", 4); |
| 4276 | 4273 | ||
| 4274 | #ifdef ACCEPT_LF_IN_STRINGS | ||
| 4275 | printf("len1=%d\n", strlen(" | ||
| 4276 | ")); | ||
| 4277 | #ifdef CORRECT_CR_HANDLING | ||
| 4278 | str = " | ||
| 4279 | "; | ||
| 4280 | printf("len1=%d str[0]=%d\n", strlen(str), str[0]); | ||
| 4281 | #endif | ||
| 4282 | printf("len1=%d\n", strlen(" a | ||
| 4283 | ")); | ||
| 4284 | #else | ||
| 4285 | printf("len1=1\nlen1=1 str[0]=10\nlen1=3\n"); | ||
| 4286 | #endif /* ACCEPT_LF_IN_STRINGS */ | ||
| 4287 | |||
| 4277 | #ifdef __LINE__ | 4288 | #ifdef __LINE__ |
| 4278 | printf("__LINE__ defined\n"); | 4289 | printf("__LINE__ defined\n"); |
| 4279 | #endif | 4290 | #endif |
| @@ -105,8 +105,7 @@ GEN-ALWAYS = · 104 unmodified lines | |||
| 105 | 112_backtrace.test: FLAGS += -dt -b | 105 | 112_backtrace.test: FLAGS += -dt -b |
| 106 | 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ | 106 | 112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \ |
| 107 | -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ | 107 | -e 's;[0-9A-Fa-fx]\{5,\};........;g' \ |
| 108 | -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' \ | 108 | -e 's;0x[0-9A-Fa-f]\{1,\};0x?;g' |
| 109 | -e 's;struct copy destination;memmove dest;g' \ | ||
| 110 | 109 | ||
| 111 | # this test creates two DLLs and an EXE | 110 | # this test creates two DLLs and an EXE |
| 112 | 113_btdll.test: T1 = \ | 111 | 113_btdll.test: T1 = \ |
| @@ -35,6 +35,8 @@ · 34 unmodified lines | |||
| 35 | #define RC_RAX 0x0004 | 35 | #define RC_RAX 0x0004 |
| 36 | #define RC_RCX 0x0008 | 36 | #define RC_RCX 0x0008 |
| 37 | #define RC_RDX 0x0010 | 37 | #define RC_RDX 0x0010 |
| 38 | #define RC_RSI 0x0020 | ||
| 39 | #define RC_RDI 0x0040 | ||
| 38 | #define RC_ST0 0x0080 /* only for long double */ | 40 | #define RC_ST0 0x0080 /* only for long double */ |
| 39 | #define RC_R8 0x0100 | 41 | #define RC_R8 0x0100 |
| 40 | #define RC_R9 0x0200 | 42 | #define RC_R9 0x0200 |
| @@ -105,6 +107,10 @@ enum { · 64 unmodified lines | |||
| 105 | /* define if return values need to be extended explicitely | 107 | /* define if return values need to be extended explicitely |
| 106 | at caller side (for interfacing with non-TCC compilers) */ | 108 | at caller side (for interfacing with non-TCC compilers) */ |
| 107 | #define PROMOTE_RET | 109 | #define PROMOTE_RET |
| 110 | |||
| 111 | #define TCC_TARGET_NATIVE_STRUCT_COPY | ||
| 112 | ST_FUNC void gen_struct_copy(int size); | ||
| 113 | |||
| 108 | /******************************************************/ | 114 | /******************************************************/ |
| 109 | #else /* ! TARGET_DEFS_ONLY */ | 115 | #else /* ! TARGET_DEFS_ONLY */ |
| 110 | /******************************************************/ | 116 | /******************************************************/ |
| @@ -124,8 +130,8 @@ ST_DATA const int reg_classes[NB_REGS] = { · 13 unmodified lines | |||
| 124 | 0, | 130 | 0, |
| 125 | 0, | 131 | 0, |
| 126 | 0, | 132 | 0, |
| 127 | 0, | 133 | RC_RSI, |
| 128 | 0, | 134 | RC_RDI, |
| 129 | RC_R8, | 135 | RC_R8, |
| 130 | RC_R9, | 136 | RC_R9, |
| 131 | RC_R10, | 137 | RC_R10, |
| @@ -2228,7 +2234,7 @@ ST_FUNC void gen_increment_tcov (SValue *sv) · 2096 unmodified lines | |||
| 2228 | } | 2234 | } |
| 2229 | 2235 | ||
| 2230 | /* computed goto support */ | 2236 | /* computed goto support */ |
| 2231 | void ggoto(void) | 2237 | ST_FUNC void ggoto(void) |
| 2232 | { | 2238 | { |
| 2233 | gcall_or_jmp(1); | 2239 | gcall_or_jmp(1); |
| 2234 | vtop--; | 2240 | vtop--; |
| @@ -2286,53 +2292,35 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { · 51 unmodified lines | |||
| 2286 | * Assmuing the top part of the stack looks like below, | 2292 | * Assmuing the top part of the stack looks like below, |
| 2287 | * src dest src | 2293 | * src dest src |
| 2288 | */ | 2294 | */ |
| 2289 | void gen_struct_copy(int size) | 2295 | ST_FUNC void gen_struct_copy(int size) |
| 2290 | { | 2296 | { |
| 2291 | save_reg(TREG_RSI); | 2297 | int n = size / PTR_SIZE; |
| 2292 | load(TREG_RSI,vtop); | 2298 | #ifdef TCC_TARGET_PE |
| 2293 | vtop->r = TREG_RSI; | 2299 | o(0x5756); /* push rsi, rdi */ |
| 2294 | vswap(); /* dest src src */ | 2300 | #endif |
| 2295 | save_reg(TREG_RDI); | 2301 | gv2(RC_RDI, RC_RSI); |
| 2296 | load(TREG_RDI,vtop); | 2302 | if (n <= 4) { |
| 2297 | vtop->r = TREG_RDI; | 2303 | while (n) |
| 2298 | /* Not aligned by 8bytes */ | 2304 | o(0xa548), --n; |
| 2299 | if (size & 0x04) { | ||
| 2300 | o(0xa5); | ||
| 2301 | } | ||
| 2302 | if (size & 0x02) { | ||
| 2303 | o(0xa566); | ||
| 2304 | } | ||
| 2305 | if (size & 0x01) { | ||
| 2306 | o(0xa4); | ||
| 2307 | } | ||
| 2308 | |||
| 2309 | size >>= 3; | ||
| 2310 | if (!size) | ||
| 2311 | goto done; | ||
| 2312 | /* Although this function is only called when the struct is smaller */ | ||
| 2313 | /* than 32 bytes(4 * PTR_SIZE),a common implementation is included */ | ||
| 2314 | if (size <= 4 && size) { | ||
| 2315 | switch (size) { | ||
| 2316 | case 4: o(0xa548); | ||
| 2317 | case 3: o(0xa548); | ||
| 2318 | case 2: o(0xa548); | ||
| 2319 | case 1: o(0xa548); | ||
| 2320 | } | ||
| 2321 | } else { | 2305 | } else { |
| 2322 | save_reg(TREG_RCX); | 2306 | vpushi(n); |
| 2323 | vpushi(size); | 2307 | gv(RC_RCX); |
| 2324 | load(TREG_RCX,vtop); | ||
| 2325 | vtop->r = TREG_RCX; | ||
| 2326 | o(0xa548f3); | 2308 | o(0xa548f3); |
| 2327 | vpop(); | 2309 | vpop(); |
| 2328 | } | 2310 | } |
| 2329 | done: | 2311 | if (size & 0x04) |
| 2312 | o(0xa5); | ||
| 2313 | if (size & 0x02) | ||
| 2314 | o(0xa566); | ||
| 2315 | if (size & 0x01) | ||
| 2316 | o(0xa4); | ||
| 2317 | #ifdef TCC_TARGET_PE | ||
| 2318 | o(0x5e5f); /* pop rdi, rsi */ | ||
| 2319 | #endif | ||
| 2330 | vpop(); | 2320 | vpop(); |
| 2331 | vpop(); | 2321 | vpop(); |
| 2332 | return; | ||
| 2333 | } | 2322 | } |
| 2334 | 2323 | ||
| 2335 | |||
| 2336 | /* end of x86-64 code generator */ | 2324 | /* end of x86-64 code generator */ |
| 2337 | /*************************************************************/ | 2325 | /*************************************************************/ |
| 2338 | #endif /* ! TARGET_DEFS_ONLY */ | 2326 | #endif /* ! TARGET_DEFS_ONLY */ |