arm-gen.c: - is_hgen_float_aggr/gfunc_sret: Fix for zero sized structs arm64-gen.c: - arm64_ldrs: Fix for zero sized structs - arm64_sym: Use R_AARCH64_ABS64 instead of R_AARCH64_MOVW_UABS_G* This has same speed. See 117_gcc_test.c(tst_adr) - load: Fix for zero sized structs and add VT_CONST | VT_LVAL support - store: add VT_CONST | VT_LVAL support - arm64_gen_bl_or_b: Allow branch. See 117_gcc_test.c(tst_branch) - gen_bounds_prolog: Use R_AARCH64_ABS64 for bound checking - gen_bounds_epilog: Use R_AARCH64_ABS64 for bound checking - gfunc_call: Allow large stack - arm64_gen_opic: Do not crash on large shift riscv64-gen.c: - load: Move type_size call. (move_reg set sv.type.ref NULL for VT_STRUCT) - gfunc_call: Allow large stack - gen_opil: Fix word mode calls x86_64-gen.c: - load: Fix for zero sized structs libtcc.c: - Add some defines for gcc testsuite (only most common) tccgen.c: - parse_builtin_params: Add types for builtins - unary: Add builtins: __builtin_abort __builtin_memcpy __builtin_memcmp __builtin_memmove __builtin_memset __builtin_strlen __builtin_strcpy __builtin_strncpy __builtin_strcmp __builtin_strncmp __builtin_strcat __builtin_strchr __builtin_strdup __builtin_malloc __builtin_realloc __builtin_calloc __builtin_free __builtin_alloca - decl_initializer: Fix crash. See 60_errors_and_warnings(test_var_array) tccmacho.c: - Remove 'ret = 0' tcctok.h: - Add builtin/bound checking tokens tests/gcctestsuite.sh: - Add more counters and run execute tests tests/bug.c - Some remaining bugs in tcc (not complete) tests/tests2/60_errors_and_warnings: - Add test_var_array test tests/tests2/117_gcc_test: - New test Results of gcctestsuite.sh for all targets: linux: x86_64: 3036 test(s) ok. 328 test(s) failed. 24 test(s) exe failed. i386: 3037 test(s) ok. 327 test(s) failed. 24 test(s) exe failed. arm: 2986 test(s) ok. 362 test(s) failed. 40 test(s) exe failed. arm64: 2996 test(s) ok. 367 test(s) failed. 25 test(s) exe failed. macos: 3031 test(s) ok. 332 test(s) failed. 25 test(s) exe failed. riscv: 2948 test(s) ok. 401 test(s) failed. 39 test(s) exe failed. windows: x86_64: 3027 test(s) ok. 333 test(s) failed. 28 test(s) exe failed. i386: 3029 test(s) ok. 331 test(s) failed. 28 test(s) exe failed. linux with bounds checking: x86_64: 3030 test(s) ok. 328 test(s) failed. 30 test(s) exe failed. i386: 3028 test(s) ok. 327 test(s) failed. 33 test(s) exe failed. arm: 2997 test(s) ok. 362 test(s) failed. 29 test(s) exe failed. arm64: 2986 test(s) ok. 367 test(s) failed. 35 test(s) exe failed. macos: 3026 test(s) ok. 332 test(s) failed. 30 test(s) exe failed. riscv: 2936 test(s) ok. 409 test(s) failed. 43 test(s) exe failed. windows with bounds checking: x86_64: 3029 test(s) ok. 332 test(s) failed. 27 test(s) exe failed. i386: 3027 test(s) ok. 331 test(s) failed. 30 test(s) exe failed.
Unified · Split
| @@ -925,10 +925,12 @@ static int is_hgen_float_aggr(CType *type) · 924 unmodified lines | ||
| 925 | 925 | int btype, nb_fields = 0; |
| 926 | 926 | |
| 927 | 927 | ref = type->ref->next; |
| 928 | − btype = unalias_ldbl(ref->type.t & VT_BTYPE); | |
| 929 | − if (btype == VT_FLOAT || btype == VT_DOUBLE) { | |
| 930 | − for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); | |
| 931 | − return !ref && nb_fields <= 4; | |
| 928 | + if (ref) { | |
| 929 | + btype = unalias_ldbl(ref->type.t & VT_BTYPE); | |
| 930 | + if (btype == VT_FLOAT || btype == VT_DOUBLE) { | |
| 931 | + for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); | |
| 932 | + return !ref && nb_fields <= 4; | |
| 933 | + } | |
| 932 | 934 | } |
| 933 | 935 | } |
| 934 | 936 | return 0; |
| @@ -1017,7 +1019,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int · 82 unmodified lines | ||
| 1017 | 1019 | ret->ref = NULL; |
| 1018 | 1020 | ret->t = VT_DOUBLE; |
| 1019 | 1021 | return (size + 7) >> 3; |
| 1020 | − } else if (size <= 4) { | |
| 1022 | + } else if (size > 0 && size <= 4) { | |
| 1021 | 1023 | *ret_align = 4; |
| 1022 | 1024 | *regsize = 4; |
| 1023 | 1025 | ret->ref = NULL; |
| @@ -323,6 +323,9 @@ static void arm64_ldrs(int reg_, int size) · 322 unmodified lines | ||
| 323 | 323 | // Use x30 for intermediate value in some cases. |
| 324 | 324 | switch (size) { |
| 325 | 325 | default: assert(0); break; |
| 326 | + case 0: | |
| 327 | + /* Can happen with zero size structs */ | |
| 328 | + break; | |
| 326 | 329 | case 1: |
| 327 | 330 | arm64_ldrx(0, 0, reg, reg, 0); |
| 328 | 331 | break; |
| @@ -429,30 +432,12 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off) · 100 unmodified lines | ||
| 429 | 432 | |
| 430 | 433 | static void arm64_sym(int r, Sym *sym, unsigned long addend) |
| 431 | 434 | { |
| 432 | − // Currently TCC's linker does not generate COPY relocations for | |
| 433 | − // STT_OBJECTs when tcc is invoked with "-run". This typically | |
| 434 | − // results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when | |
| 435 | − // a program refers to stdin. A workaround is to avoid that | |
| 436 | − // relocation and use only relocations with unlimited range. | |
| 437 | − int avoid_adrp = 1; | |
| 438 | − | |
| 439 | − if (avoid_adrp || sym->a.weak) { | |
| 440 | − // (GCC uses a R_AARCH64_ABS64 in this case.) | |
| 441 | − greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend); | |
| 442 | − o(0xd2800000 | r); // mov x(rt),#0,lsl #0 | |
| 443 | − greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G1_NC, addend); | |
| 444 | − o(0xf2a00000 | r); // movk x(rt),#0,lsl #16 | |
| 445 | − greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G2_NC, addend); | |
| 446 | − o(0xf2c00000 | r); // movk x(rt),#0,lsl #32 | |
| 447 | − greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G3, addend); | |
| 448 | − o(0xf2e00000 | r); // movk x(rt),#0,lsl #48 | |
| 449 | − } | |
| 450 | − else { | |
| 451 | − greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, addend); | |
| 452 | − o(0x90000000 | r); | |
| 453 | − greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, addend); | |
| 454 | − o(0x91000000 | r | r << 5); | |
| 455 | − } | |
| 435 | + o(0x10000060 | r); // adr xr,pc+12 | |
| 436 | + o(0xf9400000 | r | (r << 5)); // ldr xr,[xr] | |
| 437 | + o(0x14000003); // b + 8 | |
| 438 | + greloca(cur_text_section, sym, ind, R_AARCH64_ABS64, addend); | |
| 439 | + o(0); | |
| 440 | + o(0); | |
| 456 | 441 | } |
| 457 | 442 | |
| 458 | 443 | static void arm64_load_cmp(int r, SValue *sv); |
| @@ -474,12 +459,24 @@ ST_FUNC void load(int r, SValue *sv) · 15 unmodified lines | ||
| 474 | 459 | return; |
| 475 | 460 | } |
| 476 | 461 | |
| 477 | − if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { | |
| 462 | + if (svr == (VT_CONST | VT_LVAL)) { | |
| 463 | + arm64_sym(30, sv->sym, sv->c.i); // use x30 for address | |
| 478 | 464 | if (IS_FREG(r)) |
| 479 | − arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); | |
| 465 | + arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, 0); | |
| 480 | 466 | else |
| 481 | 467 | arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), |
| 482 | − intr(r), intr(svrv), 0); | |
| 468 | + intr(r), 30, 0); | |
| 469 | + return; | |
| 470 | + } | |
| 471 | + | |
| 472 | + if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { | |
| 473 | + if ((svtt & VT_BTYPE) != VT_VOID) { | |
| 474 | + if (IS_FREG(r)) | |
| 475 | + arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); | |
| 476 | + else | |
| 477 | + arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), | |
| 478 | + intr(r), intr(svrv), 0); | |
| 479 | + } | |
| 483 | 480 | return; |
| 484 | 481 | } |
| 485 | 482 | |
| @@ -573,6 +570,15 @@ ST_FUNC void store(int r, SValue *sv) · 87 unmodified lines | ||
| 573 | 570 | return; |
| 574 | 571 | } |
| 575 | 572 | |
| 573 | + if (svr == (VT_CONST | VT_LVAL)) { | |
| 574 | + arm64_sym(30, sv->sym, sv->c.i); // use x30 for address | |
| 575 | + if (IS_FREG(r)) | |
| 576 | + arm64_strv(arm64_type_size(svtt), fltr(r), 30, 0); | |
| 577 | + else | |
| 578 | + arm64_strx(arm64_type_size(svtt), intr(r), 30, 0); | |
| 579 | + return; | |
| 580 | + } | |
| 581 | + | |
| 576 | 582 | if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { |
| 577 | 583 | if (IS_FREG(r)) |
| 578 | 584 | arm64_strv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); |
| @@ -597,9 +603,9 @@ ST_FUNC void store(int r, SValue *sv) · 18 unmodified lines | ||
| 597 | 603 | static void arm64_gen_bl_or_b(int b) |
| 598 | 604 | { |
| 599 | 605 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { |
| 600 | − assert(!b); | |
| 601 | − greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); | |
| 602 | − o(0x94000000); // bl . | |
| 606 | + greloca(cur_text_section, vtop->sym, ind, | |
| 607 | + b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0); | |
| 608 | + o(0x14000000 | (uint32_t)!b << 31); // b/bl . | |
| 603 | 609 | #ifdef CONFIG_TCC_BCHECK |
| 604 | 610 | if (tcc_state->do_bounds_check && |
| 605 | 611 | (vtop->sym->v == TOK_setjmp || |
| @@ -684,7 +690,8 @@ static void gen_bounds_prolog(void) · 78 unmodified lines | ||
| 684 | 690 | func_bound_offset = lbounds_section->data_offset; |
| 685 | 691 | func_bound_ind = ind; |
| 686 | 692 | func_bound_add_epilog = 0; |
| 687 | − o(0xd503201f); /* nop -> mov x0,#0,lsl #0, lbound section pointer */ | |
| 693 | + o(0xd503201f); /* nop -> mov x0, lbound section pointer */ | |
| 694 | + o(0xd503201f); | |
| 688 | 695 | o(0xd503201f); |
| 689 | 696 | o(0xd503201f); |
| 690 | 697 | o(0xd503201f); |
| @@ -712,14 +719,12 @@ static void gen_bounds_epilog(void) · 21 unmodified lines | ||
| 712 | 719 | if (offset_modified) { |
| 713 | 720 | saved_ind = ind; |
| 714 | 721 | ind = func_bound_ind; |
| 715 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); | |
| 716 | − o(0xd2800000); /* mov x0,#0,lsl #0, lbound section pointer */ | |
| 717 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); | |
| 718 | − o(0xf2a00000); /* movk x0,#0,lsl #16 */ | |
| 719 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); | |
| 720 | − o(0xf2c00000); /* movk x0,#0,lsl #32 */ | |
| 721 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0); | |
| 722 | − o(0xf2e00000); /* movk x0,#0,lsl #48 */ | |
| 722 | + o(0x10000060 | 0); // adr x0,pc+12 | |
| 723 | + o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0] | |
| 724 | + o(0x14000003); // b + 8 | |
| 725 | + greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0); | |
| 726 | + o(0); | |
| 727 | + o(0); | |
| 723 | 728 | gen_bounds_call(TOK___bound_local_new); |
| 724 | 729 | ind = saved_ind; |
| 725 | 730 | } |
| @@ -727,14 +732,12 @@ static void gen_bounds_epilog(void) · 1 unmodified line | ||
| 727 | 732 | /* generate bound check local freeing */ |
| 728 | 733 | o(0xf81f0fe0); /* str x0, [sp, #-16]! */ |
| 729 | 734 | o(0x3c9f0fe0); /* str q0, [sp, #-16]! */ |
| 730 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); | |
| 731 | − o(0xd2800000); // mov x0,#0,lsl #0 | |
| 732 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); | |
| 733 | − o(0xf2a00000); // movk x0,#0,lsl #16 | |
| 734 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); | |
| 735 | − o(0xf2c00000); // movk x0,#0,lsl #32 | |
| 736 | − greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0); | |
| 737 | − o(0xf2e00000); // movk x0,#0,lsl #48 | |
| 735 | + o(0x10000060 | 0); // adr x0,pc+12 | |
| 736 | + o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0] | |
| 737 | + o(0x14000003); // b + 8 | |
| 738 | + greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0); | |
| 739 | + o(0); | |
| 740 | + o(0); | |
| 738 | 741 | gen_bounds_call(TOK___bound_local_delete); |
| 739 | 742 | o(0x3cc107e0); /* ldr q0, [sp], #16 */ |
| 740 | 743 | o(0xf84107e0); /* ldr x0, [sp], #16 */ |
| @@ -1014,9 +1017,12 @@ ST_FUNC void gfunc_call(int nb_args) · 273 unmodified lines | ||
| 1014 | 1017 | |
| 1015 | 1018 | stack = (stack + 15) >> 4 << 4; |
| 1016 | 1019 | |
| 1017 | − assert(stack < 0x1000); | |
| 1018 | − if (stack) | |
| 1019 | − o(0xd10003ff | stack << 10); // sub sp,sp,#(n) | |
| 1020 | + if (stack >= 0x1000000) // 16Mb | |
| 1021 | + tcc_error("stack size too big %lu", stack); | |
| 1022 | + if (stack & 0xfff) | |
| 1023 | + o(0xd10003ff | (stack & 0xfff) << 10); // sub sp,sp,#(n) | |
| 1024 | + if (stack >> 12) | |
| 1025 | + o(0xd14003ff | (stack >> 12) << 10); | |
| 1020 | 1026 | |
| 1021 | 1027 | // First pass: set all values on stack |
| 1022 | 1028 | for (i = nb_args; i; i--) { |
| @@ -1109,8 +1115,10 @@ ST_FUNC void gfunc_call(int nb_args) · 86 unmodified lines | ||
| 1109 | 1115 | save_regs(0); |
| 1110 | 1116 | arm64_gen_bl_or_b(0); |
| 1111 | 1117 | --vtop; |
| 1112 | − if (stack) | |
| 1113 | − o(0x910003ff | stack << 10); // add sp,sp,#(n) | |
| 1118 | + if (stack & 0xfff) | |
| 1119 | + o(0x910003ff | (stack & 0xfff) << 10); // add sp,sp,#(n) | |
| 1120 | + if (stack >> 12) | |
| 1121 | + o(0x914003ff | (stack >> 12) << 10); | |
| 1114 | 1122 | |
| 1115 | 1123 | { |
| 1116 | 1124 | int rt = return_type->t; |
| @@ -1611,8 +1619,11 @@ static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val, · 494 unmodified lines | ||
| 1611 | 1619 | val = val & (n - 1); |
| 1612 | 1620 | if (rev) |
| 1613 | 1621 | return 0; |
| 1614 | − if (!val) | |
| 1615 | − assert(0); | |
| 1622 | + if (!val) { | |
| 1623 | + // tcc_warning("shift count >= width of type"); | |
| 1624 | + o(0x2a0003e0 | l << 31 | a << 16); | |
| 1625 | + return 1; | |
| 1626 | + } | |
| 1616 | 1627 | else if (op == TOK_SHL) |
| 1617 | 1628 | o(0x53000000 | l << 31 | l << 22 | x | a << 5 | |
| 1618 | 1629 | (n - val) << 16 | (n - 1 - val) << 10); // lsl |
| @@ -963,6 +963,24 @@ LIBTCCAPI TCCState *tcc_new(void) · 962 unmodified lines | ||
| 963 | 963 | tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1"); |
| 964 | 964 | tcc_define_symbol(s, "_FORTIFY_SOURCE", "0"); |
| 965 | 965 | #endif /* ndef TCC_TARGET_MACHO */ |
| 966 | + | |
| 967 | + if (PTR_SIZE == 4) { | |
| 968 | + tcc_define_symbol(s, "__SIZEOF_LONG__", "4"); | |
| 969 | + tcc_define_symbol(s, "__LONG_MAX__", "0x7fffffffL"); | |
| 970 | + } | |
| 971 | + else { | |
| 972 | + tcc_define_symbol(s, "__SIZEOF_LONG__", "8"); | |
| 973 | + tcc_define_symbol(s, "__LONG_MAX__", "0x7fffffffffffffffL"); | |
| 974 | + } | |
| 975 | + tcc_define_symbol(s, "__SIZEOF_INT__", "4"); | |
| 976 | + tcc_define_symbol(s, "__SIZEOF_LONG_LONG__", "8"); | |
| 977 | + tcc_define_symbol(s, "__CHAR_BIT__", "8"); | |
| 978 | + tcc_define_symbol(s, "__ORDER_LITTLE_ENDIAN__", "1234"); | |
| 979 | + tcc_define_symbol(s, "__ORDER_BIG_ENDIAN__", "4321"); | |
| 980 | + tcc_define_symbol(s, "__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__"); | |
| 981 | + tcc_define_symbol(s, "__INT_MAX__", "0x7fffffff"); | |
| 982 | + tcc_define_symbol(s, "__LONG_LONG_MAX__", "0x7fffffffffffffffLL"); | |
| 983 | + tcc_define_symbol(s, "__builtin_offsetof(type,field)", "((unsigned long) &((type *)0)->field)"); | |
| 966 | 984 | return s; |
| 967 | 985 | } |
| 968 | 986 | |
| @@ -207,9 +207,10 @@ ST_FUNC void load(int r, SValue *sv) · 206 unmodified lines | ||
| 207 | 207 | int rr = is_ireg(r) ? ireg(r) : freg(r); |
| 208 | 208 | int fc = sv->c.i; |
| 209 | 209 | int bt = sv->type.t & VT_BTYPE; |
| 210 | − int align, size = type_size(&sv->type, &align); | |
| 210 | + int align, size; | |
| 211 | 211 | if (fr & VT_LVAL) { |
| 212 | 212 | int func3, opcode = is_freg(r) ? 0x07 : 0x03, br; |
| 213 | + size = type_size(&sv->type, &align); | |
| 213 | 214 | assert (!is_freg(r) || bt == VT_FLOAT || bt == VT_DOUBLE); |
| 214 | 215 | if (bt == VT_FUNC) /* XXX should be done in generic code */ |
| 215 | 216 | size = PTR_SIZE; |
| @@ -290,6 +291,7 @@ ST_FUNC void load(int r, SValue *sv) · 74 unmodified lines | ||
| 290 | 291 | EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V |
| 291 | 292 | else { |
| 292 | 293 | int func7 = is_ireg(r) ? 0x70 : 0x78; |
| 294 | + size = type_size(&sv->type, &align); | |
| 293 | 295 | if (size == 8) |
| 294 | 296 | func7 |= 1; |
| 295 | 297 | assert(size == 4 || size == 8); |
| @@ -577,7 +579,7 @@ ST_FUNC void gfunc_call(int nb_args) · 281 unmodified lines | ||
| 577 | 579 | { |
| 578 | 580 | int i, align, size, areg[2]; |
| 579 | 581 | int info[nb_args ? nb_args : 1]; |
| 580 | − int stack_adj = 0, tempspace = 0, ofs, splitofs = 0; | |
| 582 | + int stack_adj = 0, tempspace = 0, stack_add, ofs, splitofs = 0; | |
| 581 | 583 | SValue *sv; |
| 582 | 584 | Sym *sa; |
| 583 | 585 | |
| @@ -644,8 +646,15 @@ ST_FUNC void gfunc_call(int nb_args) · 60 unmodified lines | ||
| 644 | 646 | } |
| 645 | 647 | stack_adj = (stack_adj + 15) & -16; |
| 646 | 648 | tempspace = (tempspace + 15) & -16; |
| 647 | − if (stack_adj + tempspace) { | |
| 648 | − EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj | |
| 649 | + stack_add = stack_adj + tempspace; | |
| 650 | + if (stack_add) { | |
| 651 | + if (stack_add >= 0x1000) { | |
| 652 | + o(0x37 | (5 << 7) | (-stack_add & 0xfffff000)); //lui t0, upper(v) | |
| 653 | + EI(0x13, 0, 5, 5, -stack_add << 20 >> 20); // addi t0, t0, lo(v) | |
| 654 | + ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 | |
| 655 | + } | |
| 656 | + else | |
| 657 | + EI(0x13, 0, 2, 2, -stack_add); // addi sp, sp, -adj | |
| 649 | 658 | for (i = ofs = 0; i < nb_args; i++) { |
| 650 | 659 | if (info[i] & (64 | 32)) { |
| 651 | 660 | vrotb(nb_args - i); |
| @@ -757,8 +766,15 @@ ST_FUNC void gfunc_call(int nb_args) · 105 unmodified lines | ||
| 757 | 766 | save_regs(nb_args + 1); |
| 758 | 767 | gcall_or_jmp(1); |
| 759 | 768 | vtop -= nb_args + 1; |
| 760 | − if (stack_adj + tempspace) | |
| 761 | − EI(0x13, 0, 2, 2, stack_adj + tempspace); // addi sp, sp, adj | |
| 769 | + if (stack_add) { | |
| 770 | + if (stack_add >= 0x1000) { | |
| 771 | + o(0x37 | (5 << 7) | (stack_add & 0xfffff000)); //lui t0, upper(v) | |
| 772 | + EI(0x13, 0, 5, 5, stack_add << 20 >> 20); // addi t0, t0, lo(v) | |
| 773 | + ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 | |
| 774 | + } | |
| 775 | + else | |
| 776 | + EI(0x13, 0, 2, 2, stack_add); // addi sp, sp, adj | |
| 777 | + } | |
| 762 | 778 | } |
| 763 | 779 | |
| 764 | 780 | static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; |
| @@ -1009,6 +1025,7 @@ static void gen_opil(int op, int ll) · 244 unmodified lines | ||
| 1009 | 1025 | int fc = vtop->c.i; |
| 1010 | 1026 | if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) { |
| 1011 | 1027 | int cll = 0; |
| 1028 | + int m = ll ? 31 : 63; | |
| 1012 | 1029 | vswap(); |
| 1013 | 1030 | gv(RC_INT); |
| 1014 | 1031 | a = ireg(vtop[0].r); |
| @@ -1023,6 +1040,7 @@ static void gen_opil(int op, int ll) · 8 unmodified lines | ||
| 1023 | 1040 | fc = -fc; |
| 1024 | 1041 | case '+': |
| 1025 | 1042 | func3 = 0; // addi d, a, fc |
| 1043 | + cll = ll; | |
| 1026 | 1044 | do_cop: |
| 1027 | 1045 | EI(0x13 | cll, func3, ireg(d), a, fc); |
| 1028 | 1046 | --vtop; |
| @@ -1045,22 +1063,22 @@ static void gen_opil(int op, int ll) · 16 unmodified lines | ||
| 1045 | 1063 | case '^': func3 = 4; goto do_cop; // xori d, a, fc |
| 1046 | 1064 | case '|': func3 = 6; goto do_cop; // ori d, a, fc |
| 1047 | 1065 | case '&': func3 = 7; goto do_cop; // andi d, a, fc |
| 1048 | − case TOK_SHL: func3 = 1; fc &= 63; goto do_cop; // slli d, a, fc | |
| 1049 | − case TOK_SHR: func3 = 5; cll = ll; fc &= 63; goto do_cop; // srli d, a, fc | |
| 1050 | − case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & 63); goto do_cop; | |
| 1051 | − | |
| 1052 | − case TOK_UGE: | |
| 1053 | − case TOK_UGT: | |
| 1054 | − case TOK_GE: | |
| 1055 | − case TOK_GT: | |
| 1056 | − gen_opil(op - 1, ll); | |
| 1066 | + case TOK_SHL: func3 = 1; cll = ll; fc &= m; goto do_cop; // slli d, a, fc | |
| 1067 | + case TOK_SHR: func3 = 5; cll = ll; fc &= m; goto do_cop; // srli d, a, fc | |
| 1068 | + case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & m); goto do_cop; | |
| 1069 | + | |
| 1070 | + case TOK_UGE: /* -> TOK_ULT */ | |
| 1071 | + case TOK_UGT: /* -> TOK_ULE */ | |
| 1072 | + case TOK_GE: /* -> TOK_LT */ | |
| 1073 | + case TOK_GT: /* -> TOK_LE */ | |
| 1074 | + gen_opil(op - 1, !ll); | |
| 1057 | 1075 | vtop->cmp_op ^= 1; |
| 1058 | 1076 | return; |
| 1059 | 1077 | |
| 1060 | 1078 | case TOK_NE: |
| 1061 | 1079 | case TOK_EQ: |
| 1062 | 1080 | if (fc) |
| 1063 | − gen_opil('-', ll), a = ireg(vtop++->r); | |
| 1081 | + gen_opil('-', !ll), a = ireg(vtop++->r); | |
| 1064 | 1082 | --vtop; |
| 1065 | 1083 | vset_VT_CMP(op); |
| 1066 | 1084 | vtop->cmp_r = a | 0 << 8; |
| @@ -1087,25 +1105,25 @@ static void gen_opil(int op, int ll) · 20 unmodified lines | ||
| 1087 | 1105 | break; |
| 1088 | 1106 | |
| 1089 | 1107 | case '+': |
| 1090 | − ER(0x33, 0, d, a, b, 0); // add d, a, b | |
| 1108 | + ER(0x33 | ll, 0, d, a, b, 0); // add d, a, b | |
| 1091 | 1109 | break; |
| 1092 | 1110 | case '-': |
| 1093 | − ER(0x33, 0, d, a, b, 0x20); // sub d, a, b | |
| 1111 | + ER(0x33 | ll, 0, d, a, b, 0x20); // sub d, a, b | |
| 1094 | 1112 | break; |
| 1095 | 1113 | case TOK_SAR: |
| 1096 | − ER(0x33 | ll, 5, d, a, b, 0x20); // sra d, a, b | |
| 1114 | + ER(0x33 | ll | ll, 5, d, a, b, 0x20); // sra d, a, b | |
| 1097 | 1115 | break; |
| 1098 | 1116 | case TOK_SHR: |
| 1099 | − ER(0x33 | ll, 5, d, a, b, 0); // srl d, a, b | |
| 1117 | + ER(0x33 | ll | ll, 5, d, a, b, 0); // srl d, a, b | |
| 1100 | 1118 | break; |
| 1101 | 1119 | case TOK_SHL: |
| 1102 | − ER(0x33, 1, d, a, b, 0); // sll d, a, b | |
| 1120 | + ER(0x33 | ll, 1, d, a, b, 0); // sll d, a, b | |
| 1103 | 1121 | break; |
| 1104 | 1122 | case '*': |
| 1105 | − ER(0x33, 0, d, a, b, 1); // mul d, a, b | |
| 1123 | + ER(0x33 | ll, 0, d, a, b, 1); // mul d, a, b | |
| 1106 | 1124 | break; |
| 1107 | 1125 | case '/': |
| 1108 | − ER(0x33, 4, d, a, b, 1); // div d, a, b | |
| 1126 | + ER(0x33 | ll, 4, d, a, b, 1); // div d, a, b | |
| 1109 | 1127 | break; |
| 1110 | 1128 | case '&': |
| 1111 | 1129 | ER(0x33, 7, d, a, b, 0); // and d, a, b |
| @@ -1117,14 +1135,14 @@ static void gen_opil(int op, int ll) · 5 unmodified lines | ||
| 1117 | 1135 | ER(0x33, 6, d, a, b, 0); // or d, a, b |
| 1118 | 1136 | break; |
| 1119 | 1137 | case '%': |
| 1120 | − ER(0x33, 6, d, a, b, 1); // rem d, a, b | |
| 1138 | + ER(ll ? 0x3b: 0x33, 6, d, a, b, 1); // rem d, a, b | |
| 1121 | 1139 | break; |
| 1122 | 1140 | case TOK_UMOD: |
| 1123 | − ER(0x33, 7, d, a, b, 1); // remu d, a, b | |
| 1141 | + ER(0x33 | ll, 7, d, a, b, 1); // remu d, a, b | |
| 1124 | 1142 | break; |
| 1125 | 1143 | case TOK_PDIV: |
| 1126 | 1144 | case TOK_UDIV: |
| 1127 | − ER(0x33, 5, d, a, b, 1); // divu d, a, b | |
| 1145 | + ER(0x33 | ll, 5, d, a, b, 1); // divu d, a, b | |
| 1128 | 1146 | break; |
| 1129 | 1147 | } |
| 1130 | 1148 | } |
| @@ -5356,17 +5356,51 @@ static void parse_type(CType *type) · 5355 unmodified lines | ||
| 5356 | 5356 | static void parse_builtin_params(int nc, const char *args) |
| 5357 | 5357 | { |
| 5358 | 5358 | char c, sep = '('; |
| 5359 | − CType t; | |
| 5359 | + CType type; | |
| 5360 | 5360 | if (nc) |
| 5361 | 5361 | nocode_wanted++; |
| 5362 | 5362 | next(); |
| 5363 | + if (*args == 0) | |
| 5364 | + skip(sep); | |
| 5363 | 5365 | while ((c = *args++)) { |
| 5364 | 5366 | skip(sep); |
| 5365 | 5367 | sep = ','; |
| 5366 | 5368 | switch (c) { |
| 5367 | − case 'e': expr_eq(); continue; | |
| 5368 | − case 't': parse_type(&t); vpush(&t); continue; | |
| 5369 | − default: tcc_error("internal error"); break; | |
| 5369 | + case 'e': expr_eq(); | |
| 5370 | + continue; | |
| 5371 | + case 't': parse_type(&type); | |
| 5372 | + vpush(&type); | |
| 5373 | + continue; | |
| 5374 | + case 'v': | |
| 5375 | + case 'V': expr_eq(); | |
| 5376 | + type.t = VT_VOID; | |
| 5377 | + if (c == 'V') type.t |= VT_CONSTANT; | |
| 5378 | + type.ref = NULL; | |
| 5379 | + mk_pointer (&type); | |
| 5380 | + gen_assign_cast(&type); | |
| 5381 | + continue; | |
| 5382 | + case 's': | |
| 5383 | + case 'S': expr_eq(); | |
| 5384 | + type.t = VT_BYTE; | |
| 5385 | + if (tcc_state->char_is_unsigned) | |
| 5386 | + type.t |= VT_UNSIGNED; | |
| 5387 | + if (c == 'S') type.t |= VT_CONSTANT; | |
| 5388 | + type.ref = NULL; | |
| 5389 | + mk_pointer (&type); | |
| 5390 | + gen_assign_cast(&type); | |
| 5391 | + continue; | |
| 5392 | + case 'i': expr_eq(); | |
| 5393 | + type.t = VT_INT; | |
| 5394 | + type.ref = NULL; | |
| 5395 | + gen_assign_cast(&type); | |
| 5396 | + continue; | |
| 5397 | + case 'l': expr_eq(); | |
| 5398 | + type.t = VT_SIZE_T; | |
| 5399 | + type.ref = NULL; | |
| 5400 | + gen_assign_cast(&type); | |
| 5401 | + continue; | |
| 5402 | + default: tcc_error("internal error"); | |
| 5403 | + break; | |
| 5370 | 5404 | } |
| 5371 | 5405 | } |
| 5372 | 5406 | skip(')'); |
| @@ -5746,6 +5780,197 @@ ST_FUNC void unary(void) · 373 unmodified lines | ||
| 5746 | 5780 | break; |
| 5747 | 5781 | } |
| 5748 | 5782 | #endif |
| 5783 | + case TOK___builtin_abort: | |
| 5784 | + vpush_global_sym(&func_old_type, TOK_abort); | |
| 5785 | + parse_builtin_params(0, ""); | |
| 5786 | + gfunc_call(0); | |
| 5787 | +builtin_void_return: | |
| 5788 | + vpushi(0); | |
| 5789 | + type.t = VT_VOID; | |
| 5790 | + type.ref = NULL; | |
| 5791 | + vtop->type = type; | |
| 5792 | + vtop->r = R_RET(type.t); | |
| 5793 | + break; | |
| 5794 | + case TOK___builtin_memcpy: | |
| 5795 | + t = TOK_memcpy; | |
| 5796 | +#ifdef CONFIG_TCC_BCHECK | |
| 5797 | + if (tcc_state->do_bounds_check) t = TOK___bound_memcpy; | |
| 5798 | +#endif | |
| 5799 | + vpush_global_sym(&func_old_type, t); | |
| 5800 | + parse_builtin_params(0, "vVl"); | |
| 5801 | + gfunc_call(3); | |
| 5802 | +builtin_void_ptr_return: | |
| 5803 | + vpushi(0); | |
| 5804 | + type.t = VT_VOID; | |
| 5805 | + type.ref = NULL; | |
| 5806 | + mk_pointer (&type); | |
| 5807 | + vtop->type = type; | |
| 5808 | + vtop->r = R_RET(type.t); | |
| 5809 | + break; | |
| 5810 | + case TOK___builtin_memcmp: | |
| 5811 | + t = TOK_memcmp; | |
| 5812 | +#ifdef CONFIG_TCC_BCHECK | |
| 5813 | + if (tcc_state->do_bounds_check) t = TOK___bound_memcmp; | |
| 5814 | +#endif | |
| 5815 | + vpush_global_sym(&func_old_type, t); | |
| 5816 | + parse_builtin_params(0, "VVl"); | |
| 5817 | + gfunc_call(3); | |
| 5818 | +builtin_int_return: | |
| 5819 | + vpushi(0); | |
| 5820 | + type.t = VT_INT; | |
| 5821 | + type.ref = NULL; | |
| 5822 | + vtop->type = type; | |
| 5823 | + vtop->r = R_RET(type.t); | |
| 5824 | + break; | |
| 5825 | + case TOK___builtin_memmove: | |
| 5826 | + t = TOK_memmove; | |
| 5827 | +#ifdef CONFIG_TCC_BCHECK | |
| 5828 | + if (tcc_state->do_bounds_check) t = TOK___bound_memmove; | |
| 5829 | +#endif | |
| 5830 | + vpush_global_sym(&func_old_type, t); | |
| 5831 | + parse_builtin_params(0, "vVl"); | |
| 5832 | + gfunc_call(3); | |
| 5833 | + goto builtin_void_ptr_return; | |
| 5834 | + case TOK___builtin_memset: | |
| 5835 | + t = TOK_memset; | |
| 5836 | +#ifdef CONFIG_TCC_BCHECK | |
| 5837 | + if (tcc_state->do_bounds_check) t = TOK___bound_memset; | |
| 5838 | +#endif | |
| 5839 | + vpush_global_sym(&func_old_type, t); | |
| 5840 | + parse_builtin_params(0, "vil"); | |
| 5841 | + gfunc_call(3); | |
| 5842 | + goto builtin_void_ptr_return; | |
| 5843 | + case TOK___builtin_strlen: | |
| 5844 | + t = TOK_strlen; | |
| 5845 | +#ifdef CONFIG_TCC_BCHECK | |
| 5846 | + if (tcc_state->do_bounds_check) t = TOK___bound_strlen; | |
| 5847 | +#endif | |
| 5848 | + vpush_global_sym(&func_old_type, t); | |
| 5849 | + parse_builtin_params(0, "S"); | |
| 5850 | + gfunc_call(1); | |
| 5851 | + vpushi(0); | |
| 5852 | + type.t = VT_SIZE_T; | |
| 5853 | + type.ref = NULL; | |
| 5854 | + vtop->type = type; | |
| 5855 | + vtop->r = R_RET(type.t); | |
| 5856 | + break; | |
| 5857 | + case TOK___builtin_strcpy: | |
| 5858 | + t = TOK_strcpy; | |
| 5859 | +#ifdef CONFIG_TCC_BCHECK | |
| 5860 | + if (tcc_state->do_bounds_check) t = TOK___bound_strcpy; | |
| 5861 | +#endif | |
| 5862 | + vpush_global_sym(&func_old_type, t); | |
| 5863 | + parse_builtin_params(0, "sS"); | |
| 5864 | + gfunc_call(2); | |
| 5865 | +builtin_string_ptr_return: | |
| 5866 | + vpushi(0); | |
| 5867 | + type.t = VT_BYTE; | |
| 5868 | + if (tcc_state->char_is_unsigned) | |
| 5869 | + type.t |= VT_UNSIGNED; | |
| 5870 | + type.ref = NULL; | |
| 5871 | + mk_pointer (&type); | |
| 5872 | + vtop->type = type; | |
| 5873 | + vtop->r = R_RET(type.t); | |
| 5874 | + break; | |
| 5875 | + case TOK___builtin_strncpy: | |
| 5876 | + t = TOK_strncpy; | |
| 5877 | +#ifdef CONFIG_TCC_BCHECK | |
| 5878 | + if (tcc_state->do_bounds_check) t = TOK___bound_strncpy; | |
| 5879 | +#endif | |
| 5880 | + vpush_global_sym(&func_old_type, t); | |
| 5881 | + parse_builtin_params(0, "sSl"); | |
| 5882 | + gfunc_call(3); | |
| 5883 | + goto builtin_string_ptr_return; | |
| 5884 | + case TOK___builtin_strcmp: | |
| 5885 | + t = TOK_strcmp; | |
| 5886 | +#ifdef CONFIG_TCC_BCHECK | |
| 5887 | + if (tcc_state->do_bounds_check) t = TOK___bound_strcmp; | |
| 5888 | +#endif | |
| 5889 | + vpush_global_sym(&func_old_type, t); | |
| 5890 | + parse_builtin_params(0, "SS"); | |
| 5891 | + gfunc_call(2); | |
| 5892 | + goto builtin_int_return; | |
| 5893 | + case TOK___builtin_strncmp: | |
| 5894 | + t = TOK_strncmp; | |
| 5895 | +#ifdef CONFIG_TCC_BCHECK | |
| 5896 | + if (tcc_state->do_bounds_check) t = TOK___bound_strncmp; | |
| 5897 | +#endif | |
| 5898 | + vpush_global_sym(&func_old_type, t); | |
| 5899 | + parse_builtin_params(0, "SSl"); | |
| 5900 | + gfunc_call(3); | |
| 5901 | + goto builtin_int_return; | |
| 5902 | + case TOK___builtin_strcat: | |
| 5903 | + t = TOK_strcat; | |
| 5904 | +#ifdef CONFIG_TCC_BCHECK | |
| 5905 | + if (tcc_state->do_bounds_check) t = TOK___bound_strcat; | |
| 5906 | +#endif | |
| 5907 | + vpush_global_sym(&func_old_type, t); | |
| 5908 | + parse_builtin_params(0, "sS"); | |
| 5909 | + gfunc_call(2); | |
| 5910 | + goto builtin_string_ptr_return; | |
| 5911 | + case TOK___builtin_strchr: | |
| 5912 | + t = TOK_strchr; | |
| 5913 | +#ifdef CONFIG_TCC_BCHECK | |
| 5914 | + if (tcc_state->do_bounds_check) t = TOK___bound_strchr; | |
| 5915 | +#endif | |
| 5916 | + vpush_global_sym(&func_old_type, t); | |
| 5917 | + parse_builtin_params(0, "Si"); | |
| 5918 | + gfunc_call(2); | |
| 5919 | + goto builtin_string_ptr_return; | |
| 5920 | + case TOK___builtin_strdup: | |
| 5921 | + t = TOK_strdup; | |
| 5922 | +#ifdef CONFIG_TCC_BCHECK | |
| 5923 | + if (tcc_state->do_bounds_check) t = TOK___bound_strdup; | |
| 5924 | +#endif | |
| 5925 | + vpush_global_sym(&func_old_type, t); | |
| 5926 | + parse_builtin_params(0, "S"); | |
| 5927 | + gfunc_call(1); | |
| 5928 | + goto builtin_string_ptr_return; | |
| 5929 | + case TOK___builtin_malloc: | |
| 5930 | + t = TOK_malloc; | |
| 5931 | +#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE) | |
| 5932 | + if (tcc_state->do_bounds_check) t = TOK___bound_malloc; | |
| 5933 | +#endif | |
| 5934 | + vpush_global_sym(&func_old_type, t); | |
| 5935 | + parse_builtin_params(0, "l"); | |
| 5936 | + gfunc_call(1); | |
| 5937 | + goto builtin_void_ptr_return; | |
| 5938 | + case TOK___builtin_realloc: | |
| 5939 | + t = TOK_realloc; | |
| 5940 | +#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE) | |
| 5941 | + if (tcc_state->do_bounds_check) t = TOK___bound_realloc; | |
| 5942 | +#endif | |
| 5943 | + vpush_global_sym(&func_old_type, t); | |
| 5944 | + parse_builtin_params(0, "vl"); | |
| 5945 | + gfunc_call(2); | |
| 5946 | + goto builtin_void_ptr_return; | |
| 5947 | + case TOK___builtin_calloc: | |
| 5948 | + t = TOK_calloc; | |
| 5949 | +#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE) | |
| 5950 | + if (tcc_state->do_bounds_check) t = TOK___bound_calloc; | |
| 5951 | +#endif | |
| 5952 | + vpush_global_sym(&func_old_type, t); | |
| 5953 | + parse_builtin_params(0, "ll"); | |
| 5954 | + gfunc_call(2); | |
| 5955 | + goto builtin_void_ptr_return; | |
| 5956 | + case TOK___builtin_free: | |
| 5957 | + t = TOK_free; | |
| 5958 | +#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE) | |
| 5959 | + if (tcc_state->do_bounds_check) t = TOK___bound_free; | |
| 5960 | +#endif | |
| 5961 | + vpush_global_sym(&func_old_type, t); | |
| 5962 | + parse_builtin_params(0, "v"); | |
| 5963 | + gfunc_call(1); | |
| 5964 | + goto builtin_void_return; | |
| 5965 | +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | |
| 5966 | + case TOK_alloca: | |
| 5967 | + case TOK___builtin_alloca: | |
| 5968 | + vpush_global_sym(&func_old_type, TOK_alloca); | |
| 5969 | + parse_builtin_params(0, "l"); | |
| 5970 | + gfunc_call(1); | |
| 5971 | + goto builtin_void_ptr_return; | |
| 5972 | +#endif | |
| 5973 | + | |
| 5749 | 5974 | /* pre operations */ |
| 5750 | 5975 | case TOK_INC: |
| 5751 | 5976 | case TOK_DEC: |
| @@ -7678,6 +7903,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1926 unmodified lines | ||
| 7678 | 7903 | if (n >= 0 && len > n) |
| 7679 | 7904 | nb = n; |
| 7680 | 7905 | if (!(flags & DIF_SIZE_ONLY)) { |
| 7906 | + if (sec && !NODATA_WANTED && | |
| 7907 | + (c + nb > sec->data_allocated)) | |
| 7908 | + nb = sec->data_allocated - c; | |
| 7681 | 7909 | if (len > nb) |
| 7682 | 7910 | tcc_warning("initializer-string for array is too long"); |
| 7683 | 7911 | /* in order to go faster for common case (char |
| @@ -820,7 +820,6 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 819 unmodified lines | ||
| 820 | 820 | |
| 821 | 821 | macho_write(s1, &mo, fp); |
| 822 | 822 | } |
| 823 | − ret = 0; | |
| 824 | 823 | |
| 825 | 824 | do_ret: |
| 826 | 825 | for (i = 0; i < mo.nlc; i++) |
| @@ -314,11 +314,7 @@ · 313 unmodified lines | ||
| 314 | 314 | # ifdef TCC_TARGET_X86_64 |
| 315 | 315 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") |
| 316 | 316 | # endif |
| 317 | − DEF(TOK_malloc, "malloc") | |
| 318 | − DEF(TOK_free, "free") | |
| 319 | − DEF(TOK_realloc, "realloc") | |
| 320 | 317 | DEF(TOK_memalign, "memalign") |
| 321 | − DEF(TOK_calloc, "calloc") | |
| 322 | 318 | # else |
| 323 | 319 | DEF(TOK_sigsetjmp, "sigsetjmp") |
| 324 | 320 | DEF(TOK___sigsetjmp, "__sigsetjmp") |
| @@ -326,6 +322,27 @@ · 1 unmodified line | ||
| 326 | 322 | # endif |
| 327 | 323 | DEF(TOK_mmap, "mmap") |
| 328 | 324 | DEF(TOK_munmap, "munmap") |
| 325 | + DEF(TOK_setjmp, "setjmp") | |
| 326 | + DEF(TOK__setjmp, "_setjmp") | |
| 327 | + DEF(TOK_longjmp, "longjmp") | |
| 328 | + DEF(TOK___bound_memcpy, "__bound_memcpy") | |
| 329 | + DEF(TOK___bound_memcmp, "__bound_memcmp") | |
| 330 | + DEF(TOK___bound_memmove, "__bound_memmove") | |
| 331 | + DEF(TOK___bound_memset, "__bound_memset") | |
| 332 | + DEF(TOK___bound_strlen, "__bound_strlen") | |
| 333 | + DEF(TOK___bound_strcpy, "__bound_strcpy") | |
| 334 | + DEF(TOK___bound_strncpy, "__bound_strncpy") | |
| 335 | + DEF(TOK___bound_strcmp, "__bound_strcmp") | |
| 336 | + DEF(TOK___bound_strncmp, "__bound_strncmp") | |
| 337 | + DEF(TOK___bound_strcat, "__bound_strcat") | |
| 338 | + DEF(TOK___bound_strchr, "__bound_strchr") | |
| 339 | + DEF(TOK___bound_strdup, "__bound_strdup") | |
| 340 | + DEF(TOK___bound_malloc, "__bound_malloc") | |
| 341 | + DEF(TOK___bound_free, "__bound_free") | |
| 342 | + DEF(TOK___bound_realloc, "__bound_realloc") | |
| 343 | + DEF(TOK___bound_calloc, "__bound_calloc") | |
| 344 | +#endif | |
| 345 | + DEF(TOK_abort, "abort") | |
| 329 | 346 | DEF(TOK_memcmp, "memcmp") |
| 330 | 347 | DEF(TOK_strlen, "strlen") |
| 331 | 348 | DEF(TOK_strcpy, "strcpy") |
| @@ -335,9 +352,30 @@ · 3 unmodified lines | ||
| 335 | 352 | DEF(TOK_strcat, "strcat") |
| 336 | 353 | DEF(TOK_strchr, "strchr") |
| 337 | 354 | DEF(TOK_strdup, "strdup") |
| 338 | − DEF(TOK_setjmp, "setjmp") | |
| 339 | − DEF(TOK__setjmp, "_setjmp") | |
| 340 | − DEF(TOK_longjmp, "longjmp") | |
| 355 | + DEF(TOK_malloc, "malloc") | |
| 356 | + DEF(TOK_free, "free") | |
| 357 | + DEF(TOK_realloc, "realloc") | |
| 358 | + DEF(TOK_calloc, "calloc") | |
| 359 | + | |
| 360 | + DEF(TOK___builtin_abort, "__builtin_abort") | |
| 361 | + DEF(TOK___builtin_memcpy, "__builtin_memcpy") | |
| 362 | + DEF(TOK___builtin_memcmp, "__builtin_memcmp") | |
| 363 | + DEF(TOK___builtin_memmove, "__builtin_memmove") | |
| 364 | + DEF(TOK___builtin_memset, "__builtin_memset") | |
| 365 | + DEF(TOK___builtin_strlen, "__builtin_strlen") | |
| 366 | + DEF(TOK___builtin_strcpy, "__builtin_strcpy") | |
| 367 | + DEF(TOK___builtin_strncpy, "__builtin_strncpy") | |
| 368 | + DEF(TOK___builtin_strcmp, "__builtin_strcmp") | |
| 369 | + DEF(TOK___builtin_strncmp, "__builtin_strncmp") | |
| 370 | + DEF(TOK___builtin_strcat, "__builtin_strcat") | |
| 371 | + DEF(TOK___builtin_strchr, "__builtin_strchr") | |
| 372 | + DEF(TOK___builtin_strdup, "__builtin_strdup") | |
| 373 | + DEF(TOK___builtin_malloc, "__builtin_malloc") | |
| 374 | + DEF(TOK___builtin_free, "__builtin_free") | |
| 375 | + DEF(TOK___builtin_realloc, "__builtin_realloc") | |
| 376 | + DEF(TOK___builtin_calloc, "__builtin_calloc") | |
| 377 | +#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 | |
| 378 | + DEF(TOK___builtin_alloca, "__builtin_alloca") | |
| 341 | 379 | #endif |
| 342 | 380 | |
| 343 | 381 | /* Tiny Assembler */ |
| @@ -0,0 +1,75 @@ | ||
| 1 | +#include <stdio.h> | |
| 2 | +#include <stdarg.h> | |
| 3 | + | |
| 4 | +void tst1(void) | |
| 5 | +{ | |
| 6 | + /* problem in gen_cast. Should mask unsigned types */ | |
| 7 | + signed char c = (signed char) 0xffffffff; | |
| 8 | + int r = (unsigned short) c ^ (signed char) 0x99999999; | |
| 9 | + if (r != 0xffff0066) printf ("%x\n", r); | |
| 10 | +} | |
| 11 | + | |
| 12 | +typedef struct{double x,y;}p; | |
| 13 | + | |
| 14 | +void tst2(int n,...) | |
| 15 | +{ | |
| 16 | + /* va_arg for struct double does not work on some targets */ | |
| 17 | + int i; | |
| 18 | + va_list args; | |
| 19 | + va_start(args,n); | |
| 20 | + for (i = 0; i < n; i++) { | |
| 21 | + p v = va_arg(args,p); | |
| 22 | + if (v.x != 1 || v.y != 2) printf("%g %g\n", v.x, v.y); | |
| 23 | + } | |
| 24 | + va_end(args); | |
| 25 | +} | |
| 26 | + | |
| 27 | +void tst3(void) | |
| 28 | +{ | |
| 29 | + /* Should VT_SYM be checked for TOK_builtin_constant_p */ | |
| 30 | + int r = __builtin_constant_p("c"); | |
| 31 | + if (r == 0) printf("%d\n",r); | |
| 32 | +} | |
| 33 | + | |
| 34 | +int compile_errors(void) | |
| 35 | +{ | |
| 36 | +#if TEST == 1 | |
| 37 | + { | |
| 38 | + /* Not constant */ | |
| 39 | + static int i = (&"Foobar"[1] - &"Foobar"[0]); | |
| 40 | + } | |
| 41 | +#endif | |
| 42 | +#if TEST == 2 | |
| 43 | + { | |
| 44 | + /* Not constant */ | |
| 45 | + struct{int c;}v; | |
| 46 | + static long i=((char*)&(v.c)-(char*)&v); | |
| 47 | + } | |
| 48 | +#endif | |
| 49 | +#if TEST == 3 | |
| 50 | + { | |
| 51 | + /* Not constant */ | |
| 52 | + static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 }; | |
| 53 | + void *p = &&l1 + ar[0]; | |
| 54 | + goto *p; | |
| 55 | + l1: return 1; | |
| 56 | + l2: return 2; | |
| 57 | + } | |
| 58 | +#endif | |
| 59 | +#if TEST == 4 | |
| 60 | + { | |
| 61 | + /* Only integer allowed */ | |
| 62 | + __builtin_return_address(0 + 1) != NULL; | |
| 63 | + } | |
| 64 | +#endif | |
| 65 | + return 0; | |
| 66 | +} | |
| 67 | + | |
| 68 | +int | |
| 69 | +main(void) | |
| 70 | +{ | |
| 71 | + p v = { 1, 2}; | |
| 72 | + tst1(); | |
| 73 | + tst2(1, v); | |
| 74 | + tst3(); | |
| 75 | +} | |
| @@ -1,33 +1,48 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | |
| 3 | 3 | TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture |
| 4 | −TCC="./tcc -B. -I. -DNO_TRAMPOLINES" | |
| 5 | −rm -f tcc.sum tcc.log | |
| 4 | +TCC="./tcc -B. -I. -DNO_TRAMPOLINES" | |
| 5 | +rm -f tcc.sum tcc.fail | |
| 6 | +nb_ok="0" | |
| 6 | 7 | nb_failed="0" |
| 8 | +nb_exe_failed="0" | |
| 7 | 9 | |
| 8 | 10 | for src in $TESTSUITE_PATH/compile/*.c ; do |
| 9 | − echo $TCC -o /tmp/test.o -c $src | |
| 10 | − $TCC -o /tmp/test.o -c $src >> tcc.log 2>&1 | |
| 11 | + echo $TCC -o /tmp/tst.o -c $src | |
| 12 | + $TCC -o /tmp/tst.o -c $src >> tcc.fail 2>&1 | |
| 11 | 13 | if [ "$?" = "0" ] ; then |
| 12 | − result="PASS" | |
| 14 | + result="PASS" | |
| 15 | + nb_ok=$(( $nb_ok + 1 )) | |
| 13 | 16 | else |
| 14 | − result="FAIL" | |
| 15 | − nb_failed=$(( $nb_failed + 1 )) | |
| 17 | + result="FAIL" | |
| 18 | + nb_failed=$(( $nb_failed + 1 )) | |
| 16 | 19 | fi |
| 17 | 20 | echo "$result: $src" >> tcc.sum |
| 18 | 21 | done |
| 19 | 22 | |
| 20 | 23 | for src in $TESTSUITE_PATH/execute/*.c ; do |
| 21 | − echo $TCC $src | |
| 22 | − $TCC $src >> tcc.log 2>&1 | |
| 24 | + echo $TCC $src -o /tmp/tst -lm | |
| 25 | + $TCC $src -o /tmp/tst -lm >> tcc.fail 2>&1 | |
| 23 | 26 | if [ "$?" = "0" ] ; then |
| 24 | − result="PASS" | |
| 27 | + result="PASS" | |
| 28 | + if /tmp/tst >> tcc.fail 2>&1 | |
| 29 | + then | |
| 30 | + result="PASS" | |
| 31 | + nb_ok=$(( $nb_ok + 1 )) | |
| 32 | + else | |
| 33 | + result="FAILEXE" | |
| 34 | + nb_exe_failed=$(( $nb_exe_failed + 1 )) | |
| 35 | + fi | |
| 25 | 36 | else |
| 26 | − result="FAIL" | |
| 27 | − nb_failed=$(( $nb_failed + 1 )) | |
| 37 | + result="FAIL" | |
| 38 | + nb_failed=$(( $nb_failed + 1 )) | |
| 28 | 39 | fi |
| 29 | 40 | echo "$result: $src" >> tcc.sum |
| 30 | 41 | done |
| 31 | 42 | |
| 43 | +echo "$nb_ok test(s) ok." >> tcc.sum | |
| 44 | +echo "$nb_ok test(s) ok." | |
| 32 | 45 | echo "$nb_failed test(s) failed." >> tcc.sum |
| 33 | 46 | echo "$nb_failed test(s) failed." |
| 47 | +echo "$nb_exe_failed test(s) exe failed." >> tcc.sum | |
| 48 | +echo "$nb_exe_failed test(s) exe failed." | |
| @@ -0,0 +1,134 @@ | ||
| 1 | +#include <stdio.h> | |
| 2 | + | |
| 3 | +void tst_branch(void) | |
| 4 | +{ | |
| 5 | + goto *&&a; | |
| 6 | + printf ("dummy"); | |
| 7 | +a: ; | |
| 8 | +} | |
| 9 | + | |
| 10 | +void tst_void_ptr(void *pv, int i) | |
| 11 | +{ | |
| 12 | + i ? *pv : *pv; // dr106 | |
| 13 | +} | |
| 14 | + | |
| 15 | +void tst_shift(void) | |
| 16 | +{ | |
| 17 | + int i = 1; | |
| 18 | + long l = 1; | |
| 19 | + | |
| 20 | + i = i << 32; // illegal. just test | |
| 21 | + l = l << 64; // illegal. just test | |
| 22 | +} | |
| 23 | + | |
| 24 | +#if !defined(_WIN32) | |
| 25 | +#include <sys/mman.h> | |
| 26 | + | |
| 27 | +void tst_const_addr(void) | |
| 28 | +{ | |
| 29 | + void *addr = mmap ((void *)0x20000000, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS, -1, 0); | |
| 30 | + if (addr != (void *) -1) { | |
| 31 | +#if !defined(__riscv) | |
| 32 | + *(int *)0x20000000 += 42; | |
| 33 | +#endif | |
| 34 | + munmap (addr, 4096); | |
| 35 | + } | |
| 36 | +} | |
| 37 | +#endif | |
| 38 | + | |
| 39 | +struct zero_struct {}; | |
| 40 | + | |
| 41 | +struct zero_struct tst_zero_struct(void) | |
| 42 | +{ | |
| 43 | + struct zero_struct ret; | |
| 44 | + | |
| 45 | + return ret; | |
| 46 | +} | |
| 47 | + | |
| 48 | +struct big_struct { char a[262144]; }; | |
| 49 | + | |
| 50 | +struct big_struct tst_big(struct big_struct tst) | |
| 51 | +{ | |
| 52 | + return tst; | |
| 53 | +} | |
| 54 | + | |
| 55 | +void tst_adr (int (*fp)(char *, const char *, ...)) | |
| 56 | +{ | |
| 57 | + char buf[10]; | |
| 58 | + | |
| 59 | + (*fp)(buf, "%.0f", 5.0); | |
| 60 | +} | |
| 61 | + | |
| 62 | +static const char str[] = "abcdefghijklmnopqrstuvwxyz"; | |
| 63 | + | |
| 64 | +void tst_builtin(void) | |
| 65 | +{ | |
| 66 | + char *p; | |
| 67 | + char tmp[100]; | |
| 68 | + | |
| 69 | + if (__builtin_offsetof(struct big_struct, a) != 0) __builtin_abort(); | |
| 70 | + | |
| 71 | + p = __builtin_memcpy (tmp, str, sizeof(str)); | |
| 72 | + if (p != tmp) __builtin_abort(); | |
| 73 | + | |
| 74 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 75 | + | |
| 76 | + p = __builtin_memmove(tmp, str, sizeof(str)); | |
| 77 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 78 | + | |
| 79 | + p = __builtin_memset(tmp, 0, sizeof (tmp)); | |
| 80 | + if (p != tmp || tmp[0] != 0 || tmp[99] != 0) __builtin_abort(); | |
| 81 | + | |
| 82 | + if (__builtin_strlen(str) != sizeof(str) - 1) __builtin_abort(); | |
| 83 | + | |
| 84 | + p = __builtin_strcpy(tmp, str); | |
| 85 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 86 | + | |
| 87 | + p = __builtin_strncpy(tmp, str, sizeof(str)); | |
| 88 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 89 | + | |
| 90 | + if (__builtin_strcmp (p, str)) __builtin_abort(); | |
| 91 | + | |
| 92 | + if (__builtin_strncmp (p, str, sizeof(str))) __builtin_abort(); | |
| 93 | + | |
| 94 | + tmp[0] = '\0'; | |
| 95 | + p = __builtin_strcat(tmp, str); | |
| 96 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 97 | + | |
| 98 | + if (__builtin_strchr(p, 'z') != &p[25]) __builtin_abort(); | |
| 99 | + | |
| 100 | + p = __builtin_strdup (str); | |
| 101 | + if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort(); | |
| 102 | + __builtin_free(p); | |
| 103 | + | |
| 104 | + p = __builtin_malloc (100); | |
| 105 | + __builtin_memset(p, 0, 100); | |
| 106 | + p = __builtin_realloc (p, 1000); | |
| 107 | + __builtin_memset(p, 0, 1000); | |
| 108 | + __builtin_free(p); | |
| 109 | + | |
| 110 | + p = __builtin_calloc(10, 10); | |
| 111 | + __builtin_memset(p, 0, 100); | |
| 112 | + __builtin_free(p); | |
| 113 | + | |
| 114 | +#if defined(__i386__) || defined(__x86_64__) | |
| 115 | + p = __builtin_alloca(100); | |
| 116 | + __builtin_memset(p, 0, 100); | |
| 117 | +#endif | |
| 118 | +} | |
| 119 | + | |
| 120 | +int | |
| 121 | +main (void) | |
| 122 | +{ | |
| 123 | + struct big_struct big; | |
| 124 | + | |
| 125 | + tst_shift(); | |
| 126 | + tst_void_ptr(&big.a[0], 0); | |
| 127 | +#if !defined(_WIN32) | |
| 128 | + tst_const_addr(); | |
| 129 | +#endif | |
| 130 | + tst_zero_struct(); | |
| 131 | + tst_big(big); | |
| 132 | + tst_adr(&sprintf); | |
| 133 | + tst_builtin(); | |
| 134 | +} | |
Empty file added.
| @@ -339,4 +339,11 @@ int main() · 338 unmodified lines | ||
| 339 | 339 | } |
| 340 | 340 | |
| 341 | 341 | /******************************************************************/ |
| 342 | +#elif defined test_var_array | |
| 343 | + | |
| 344 | +static struct var_len { int i; const char str[]; } var_array[] = | |
| 345 | +{ { 1, "abcdefghijklmnopqrstuvwxyz" }, | |
| 346 | + { 2, "longlonglonglonglong" }, | |
| 347 | + { 3, "tst3" } }; | |
| 348 | + | |
| 342 | 349 | #endif |
| @@ -159,3 +159,6 @@ bar : 3 ; 3 · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | [test_stray_backslash2] |
| 161 | 161 | \n |
| 162 | + | |
| 163 | +[test_var_array] | |
| 164 | +60_errors_and_warnings.c:345: warning: initializer-string for array is too long | |
| @@ -441,6 +441,9 @@ void load(int r, SValue *sv) · 440 unmodified lines | ||
| 441 | 441 | b = 0xbf0f; /* movswl */ |
| 442 | 442 | } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { |
| 443 | 443 | b = 0xb70f; /* movzwl */ |
| 444 | + } else if ((ft & VT_TYPE) == (VT_VOID)) { | |
| 445 | + /* Can happen with zero size structs */ | |
| 446 | + return; | |
| 444 | 447 | } else { |
| 445 | 448 | assert(((ft & VT_BTYPE) == VT_INT) |
| 446 | 449 | || ((ft & VT_BTYPE) == VT_LLONG) |