Unified · Split
| @@ -292,6 +292,7 @@ DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n); · 291 unmodified lines | |||
| 292 | DLL_EXPORT char *__bound_strcat(char *dest, const char *src); | 292 | DLL_EXPORT char *__bound_strcat(char *dest, const char *src); |
| 293 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); | 293 | DLL_EXPORT char *__bound_strchr(const char *string, int ch); |
| 294 | DLL_EXPORT char *__bound_strdup(const char *s); | 294 | DLL_EXPORT char *__bound_strdup(const char *s); |
| 295 | DLL_EXPORT void __bound_struct_copy(void *dst,void *src,size_t size); | ||
| 295 | 296 | ||
| 296 | #if defined(__arm__) && defined(__ARM_EABI__) | 297 | #if defined(__arm__) && defined(__ARM_EABI__) |
| 297 | DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); | 298 | DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size); |
| @@ -424,6 +425,7 @@ static unsigned long long bound_strncmp_count; · 126 unmodified lines | |||
| 424 | static unsigned long long bound_strcat_count; | 425 | static unsigned long long bound_strcat_count; |
| 425 | static unsigned long long bound_strchr_count; | 426 | static unsigned long long bound_strchr_count; |
| 426 | static unsigned long long bound_strdup_count; | 427 | static unsigned long long bound_strdup_count; |
| 428 | static unsigned long long bound_struct_copy_count; | ||
| 427 | static unsigned long long bound_not_found; | 429 | static unsigned long long bound_not_found; |
| 428 | #define INCR_COUNT(x) ++x | 430 | #define INCR_COUNT(x) ++x |
| 429 | #else | 431 | #else |
| @@ -1765,6 +1767,16 @@ void *__bound_memset(void *s, int c, size_t n) · 1335 unmodified lines | |||
| 1765 | return memset(s, c, n); | 1767 | return memset(s, c, n); |
| 1766 | } | 1768 | } |
| 1767 | 1769 | ||
| 1770 | void __bound_struct_copy(void *dst,void *src,size_t size) | ||
| 1771 | { | ||
| 1772 | dprintf(stderr, "Copy struct from %p to %p,size %lx\n", | ||
| 1773 | src,dst,size); | ||
| 1774 | INCR_COUNT(bound_struct_copy_count); | ||
| 1775 | __bound_check(dst,size,"struct copy destination"); | ||
| 1776 | __bound_check(src,size,"struct copy source"); | ||
| 1777 | return; | ||
| 1778 | } | ||
| 1779 | |||
| 1768 | #if defined(__arm__) && defined(__ARM_EABI__) | 1780 | #if defined(__arm__) && defined(__ARM_EABI__) |
| 1769 | void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) | 1781 | void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n) |
| 1770 | { | 1782 | { |
| @@ -1644,6 +1644,8 @@ 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); | ||
| 1647 | ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); | 1649 | ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c); |
| 1648 | ST_FUNC void gen_opl(int op); | 1650 | ST_FUNC void gen_opl(int op); |
| 1649 | #ifdef TCC_TARGET_PE | 1651 | #ifdef TCC_TARGET_PE |
| @@ -3474,9 +3474,38 @@ ST_FUNC void vstore(void) · 3473 unmodified lines | |||
| 3474 | if (sbt == VT_STRUCT) { | 3474 | if (sbt == VT_STRUCT) { |
| 3475 | /* if structure, only generate pointer */ | 3475 | /* if structure, only generate pointer */ |
| 3476 | /* structure assignment : generate memcpy */ | 3476 | /* structure assignment : generate memcpy */ |
| 3477 | /* XXX: optimize if small size */ | ||
| 3478 | size = type_size(&vtop->type, &align); | 3477 | size = type_size(&vtop->type, &align); |
| 3479 | 3478 | ||
| 3479 | #ifdef TCC_TARGET_NATIVE_STRUCT_COPY | ||
| 3480 | if (size <= (PTR_SIZE << 4)) { | ||
| 3481 | vswap(); | ||
| 3482 | #ifdef CONFIG_TCC_BCHECK | ||
| 3483 | if (vtop->r & VT_MUSTBOUND) | ||
| 3484 | gbound(); | ||
| 3485 | #endif | ||
| 3486 | vtop->type.t = VT_PTR; | ||
| 3487 | gaddrof(); | ||
| 3488 | |||
| 3489 | vpushv(vtop - 1); | ||
| 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 | ||
| 3497 | if (tcc_state->do_bounds_check) { | ||
| 3498 | vpush_helper_func(TOK___bound_struct_copy); | ||
| 3499 | vpushv(vtop - 2); | ||
| 3500 | vpushv(vtop - 2); | ||
| 3501 | vpushi(size); | ||
| 3502 | gfunc_call(3); | ||
| 3503 | } | ||
| 3504 | #endif | ||
| 3505 | |||
| 3506 | gen_struct_copy(size); | ||
| 3507 | } else { | ||
| 3508 | #endif | ||
| 3480 | /* destination */ | 3509 | /* destination */ |
| 3481 | vswap(); | 3510 | vswap(); |
| 3482 | #ifdef CONFIG_TCC_BCHECK | 3511 | #ifdef CONFIG_TCC_BCHECK |
| @@ -3510,7 +3539,9 @@ ST_FUNC void vstore(void) · 27 unmodified lines | |||
| 3510 | vpushi(size); | 3539 | vpushi(size); |
| 3511 | gfunc_call(3); | 3540 | gfunc_call(3); |
| 3512 | /* leave source on stack */ | 3541 | /* leave source on stack */ |
| 3513 | 3542 | #ifdef TCC_TARGET_NATIVE_STRUCT_COPY | |
| 3543 | } | ||
| 3544 | #endif | ||
| 3514 | } else if (ft & VT_BITFIELD) { | 3545 | } else if (ft & VT_BITFIELD) { |
| 3515 | /* bitfield store handling */ | 3546 | /* bitfield store handling */ |
| 3516 | 3547 | ||
| @@ -330,6 +330,7 @@ · 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") | ||
| 333 | # ifdef TCC_TARGET_PE | 334 | # ifdef TCC_TARGET_PE |
| 334 | # ifdef TCC_TARGET_X86_64 | 335 | # ifdef TCC_TARGET_X86_64 |
| 335 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") | 336 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") |
| @@ -2282,6 +2282,56 @@ ST_FUNC void gen_vla_alloc(CType *type, int align) { · 2281 unmodified lines | |||
| 2282 | } | 2282 | } |
| 2283 | } | 2283 | } |
| 2284 | 2284 | ||
| 2285 | /* | ||
| 2286 | * Assmuing the top part of the stack looks like below, | ||
| 2287 | * src dest src | ||
| 2288 | */ | ||
| 2289 | void gen_struct_copy(int size) | ||
| 2290 | { | ||
| 2291 | save_reg(TREG_RSI); | ||
| 2292 | load(TREG_RSI,vtop); | ||
| 2293 | vtop->r = TREG_RSI; | ||
| 2294 | vswap(); /* dest src src */ | ||
| 2295 | save_reg(TREG_RDI); | ||
| 2296 | load(TREG_RDI,vtop); | ||
| 2297 | vtop->r = TREG_RDI; | ||
| 2298 | /* Not aligned by 8bytes */ | ||
| 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 { | ||
| 2322 | save_reg(TREG_RCX); | ||
| 2323 | vpushi(size); | ||
| 2324 | load(TREG_RCX,vtop); | ||
| 2325 | vtop->r = TREG_RCX; | ||
| 2326 | o(0xa548f3); | ||
| 2327 | vpop(); | ||
| 2328 | } | ||
| 2329 | done: | ||
| 2330 | vpop(); | ||
| 2331 | vpop(); | ||
| 2332 | return; | ||
| 2333 | } | ||
| 2334 | |||
| 2285 | 2335 | ||
| 2286 | /* end of x86-64 code generator */ | 2336 | /* end of x86-64 code generator */ |
| 2287 | /*************************************************************/ | 2337 | /*************************************************************/ |