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 | int btype, nb_fields = 0; | 925 | int btype, nb_fields = 0; |
| 926 | 926 | ||
| 927 | ref = type->ref->next; | 927 | ref = type->ref->next; |
| 928 | btype = unalias_ldbl(ref->type.t & VT_BTYPE); | 928 | if (ref) { |
| 929 | if (btype == VT_FLOAT || btype == VT_DOUBLE) { | 929 | btype = unalias_ldbl(ref->type.t & VT_BTYPE); |
| 930 | for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); | 930 | if (btype == VT_FLOAT || btype == VT_DOUBLE) { |
| 931 | return !ref && nb_fields <= 4; | 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 | return 0; | 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 | ret->ref = NULL; | 1019 | ret->ref = NULL; |
| 1018 | ret->t = VT_DOUBLE; | 1020 | ret->t = VT_DOUBLE; |
| 1019 | return (size + 7) >> 3; | 1021 | return (size + 7) >> 3; |
| 1020 | } else if (size <= 4) { | 1022 | } else if (size > 0 && size <= 4) { |
| 1021 | *ret_align = 4; | 1023 | *ret_align = 4; |
| 1022 | *regsize = 4; | 1024 | *regsize = 4; |
| 1023 | ret->ref = NULL; | 1025 | ret->ref = NULL; |
| @@ -323,6 +323,9 @@ static void arm64_ldrs(int reg_, int size) · 322 unmodified lines | |||
| 323 | // Use x30 for intermediate value in some cases. | 323 | // Use x30 for intermediate value in some cases. |
| 324 | switch (size) { | 324 | switch (size) { |
| 325 | default: assert(0); break; | 325 | default: assert(0); break; |
| 326 | case 0: | ||
| 327 | /* Can happen with zero size structs */ | ||
| 328 | break; | ||
| 326 | case 1: | 329 | case 1: |
| 327 | arm64_ldrx(0, 0, reg, reg, 0); | 330 | arm64_ldrx(0, 0, reg, reg, 0); |
| 328 | break; | 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 | static void arm64_sym(int r, Sym *sym, unsigned long addend) | 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 | 435 | o(0x10000060 | r); // adr xr,pc+12 |
| 433 | // STT_OBJECTs when tcc is invoked with "-run". This typically | 436 | o(0xf9400000 | r | (r << 5)); // ldr xr,[xr] |
| 434 | // results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when | 437 | o(0x14000003); // b + 8 |
| 435 | // a program refers to stdin. A workaround is to avoid that | 438 | greloca(cur_text_section, sym, ind, R_AARCH64_ABS64, addend); |
| 436 | // relocation and use only relocations with unlimited range. | 439 | o(0); |
| 437 | int avoid_adrp = 1; | 440 | o(0); |
| 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 | } | ||
| 456 | } | 441 | } |
| 457 | 442 | ||
| 458 | static void arm64_load_cmp(int r, SValue *sv); | 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 | return; | 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 | if (IS_FREG(r)) | 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 | else | 466 | else |
| 481 | arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), | 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 | return; | 480 | return; |
| 484 | } | 481 | } |
| 485 | 482 | ||
| @@ -573,6 +570,15 @@ ST_FUNC void store(int r, SValue *sv) · 87 unmodified lines | |||
| 573 | return; | 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 | if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { | 582 | if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { |
| 577 | if (IS_FREG(r)) | 583 | if (IS_FREG(r)) |
| 578 | arm64_strv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); | 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 | static void arm64_gen_bl_or_b(int b) | 603 | static void arm64_gen_bl_or_b(int b) |
| 598 | { | 604 | { |
| 599 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { | 605 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { |
| 600 | assert(!b); | 606 | greloca(cur_text_section, vtop->sym, ind, |
| 601 | greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); | 607 | b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0); |
| 602 | o(0x94000000); // bl . | 608 | o(0x14000000 | (uint32_t)!b << 31); // b/bl . |
| 603 | #ifdef CONFIG_TCC_BCHECK | 609 | #ifdef CONFIG_TCC_BCHECK |
| 604 | if (tcc_state->do_bounds_check && | 610 | if (tcc_state->do_bounds_check && |
| 605 | (vtop->sym->v == TOK_setjmp || | 611 | (vtop->sym->v == TOK_setjmp || |
| @@ -684,7 +690,8 @@ static void gen_bounds_prolog(void) · 78 unmodified lines | |||
| 684 | func_bound_offset = lbounds_section->data_offset; | 690 | func_bound_offset = lbounds_section->data_offset; |
| 685 | func_bound_ind = ind; | 691 | func_bound_ind = ind; |
| 686 | func_bound_add_epilog = 0; | 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 | o(0xd503201f); | 695 | o(0xd503201f); |
| 689 | o(0xd503201f); | 696 | o(0xd503201f); |
| 690 | o(0xd503201f); | 697 | o(0xd503201f); |
| @@ -712,14 +719,12 @@ static void gen_bounds_epilog(void) · 21 unmodified lines | |||
| 712 | if (offset_modified) { | 719 | if (offset_modified) { |
| 713 | saved_ind = ind; | 720 | saved_ind = ind; |
| 714 | ind = func_bound_ind; | 721 | ind = func_bound_ind; |
| 715 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); | 722 | o(0x10000060 | 0); // adr x0,pc+12 |
| 716 | o(0xd2800000); /* mov x0,#0,lsl #0, lbound section pointer */ | 723 | o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0] |
| 717 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); | 724 | o(0x14000003); // b + 8 |
| 718 | o(0xf2a00000); /* movk x0,#0,lsl #16 */ | 725 | greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0); |
| 719 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); | 726 | o(0); |
| 720 | o(0xf2c00000); /* movk x0,#0,lsl #32 */ | 727 | o(0); |
| 721 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0); | ||
| 722 | o(0xf2e00000); /* movk x0,#0,lsl #48 */ | ||
| 723 | gen_bounds_call(TOK___bound_local_new); | 728 | gen_bounds_call(TOK___bound_local_new); |
| 724 | ind = saved_ind; | 729 | ind = saved_ind; |
| 725 | } | 730 | } |
| @@ -727,14 +732,12 @@ static void gen_bounds_epilog(void) · 1 unmodified line | |||
| 727 | /* generate bound check local freeing */ | 732 | /* generate bound check local freeing */ |
| 728 | o(0xf81f0fe0); /* str x0, [sp, #-16]! */ | 733 | o(0xf81f0fe0); /* str x0, [sp, #-16]! */ |
| 729 | o(0x3c9f0fe0); /* str q0, [sp, #-16]! */ | 734 | o(0x3c9f0fe0); /* str q0, [sp, #-16]! */ |
| 730 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); | 735 | o(0x10000060 | 0); // adr x0,pc+12 |
| 731 | o(0xd2800000); // mov x0,#0,lsl #0 | 736 | o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0] |
| 732 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); | 737 | o(0x14000003); // b + 8 |
| 733 | o(0xf2a00000); // movk x0,#0,lsl #16 | 738 | greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0); |
| 734 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); | 739 | o(0); |
| 735 | o(0xf2c00000); // movk x0,#0,lsl #32 | 740 | o(0); |
| 736 | greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0); | ||
| 737 | o(0xf2e00000); // movk x0,#0,lsl #48 | ||
| 738 | gen_bounds_call(TOK___bound_local_delete); | 741 | gen_bounds_call(TOK___bound_local_delete); |
| 739 | o(0x3cc107e0); /* ldr q0, [sp], #16 */ | 742 | o(0x3cc107e0); /* ldr q0, [sp], #16 */ |
| 740 | o(0xf84107e0); /* ldr x0, [sp], #16 */ | 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 | stack = (stack + 15) >> 4 << 4; | 1018 | stack = (stack + 15) >> 4 << 4; |
| 1016 | 1019 | ||
| 1017 | assert(stack < 0x1000); | 1020 | if (stack >= 0x1000000) // 16Mb |
| 1018 | if (stack) | 1021 | tcc_error("stack size too big %lu", stack); |
| 1019 | o(0xd10003ff | stack << 10); // sub sp,sp,#(n) | 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 | // First pass: set all values on stack | 1027 | // First pass: set all values on stack |
| 1022 | for (i = nb_args; i; i--) { | 1028 | for (i = nb_args; i; i--) { |
| @@ -1109,8 +1115,10 @@ ST_FUNC void gfunc_call(int nb_args) · 86 unmodified lines | |||
| 1109 | save_regs(0); | 1115 | save_regs(0); |
| 1110 | arm64_gen_bl_or_b(0); | 1116 | arm64_gen_bl_or_b(0); |
| 1111 | --vtop; | 1117 | --vtop; |
| 1112 | if (stack) | 1118 | if (stack & 0xfff) |
| 1113 | o(0x910003ff | stack << 10); // add sp,sp,#(n) | 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 | int rt = return_type->t; | 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 | val = val & (n - 1); | 1619 | val = val & (n - 1); |
| 1612 | if (rev) | 1620 | if (rev) |
| 1613 | return 0; | 1621 | return 0; |
| 1614 | if (!val) | 1622 | if (!val) { |
| 1615 | assert(0); | 1623 | // tcc_warning("shift count >= width of type"); |
| 1624 | o(0x2a0003e0 | l << 31 | a << 16); | ||
| 1625 | return 1; | ||
| 1626 | } | ||
| 1616 | else if (op == TOK_SHL) | 1627 | else if (op == TOK_SHL) |
| 1617 | o(0x53000000 | l << 31 | l << 22 | x | a << 5 | | 1628 | o(0x53000000 | l << 31 | l << 22 | x | a << 5 | |
| 1618 | (n - val) << 16 | (n - 1 - val) << 10); // lsl | 1629 | (n - val) << 16 | (n - 1 - val) << 10); // lsl |
| @@ -963,6 +963,24 @@ LIBTCCAPI TCCState *tcc_new(void) · 962 unmodified lines | |||
| 963 | tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1"); | 963 | tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1"); |
| 964 | tcc_define_symbol(s, "_FORTIFY_SOURCE", "0"); | 964 | tcc_define_symbol(s, "_FORTIFY_SOURCE", "0"); |
| 965 | #endif /* ndef TCC_TARGET_MACHO */ | 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 | return s; | 984 | return s; |
| 967 | } | 985 | } |
| 968 | 986 | ||
| @@ -207,9 +207,10 @@ ST_FUNC void load(int r, SValue *sv) · 206 unmodified lines | |||
| 207 | int rr = is_ireg(r) ? ireg(r) : freg(r); | 207 | int rr = is_ireg(r) ? ireg(r) : freg(r); |
| 208 | int fc = sv->c.i; | 208 | int fc = sv->c.i; |
| 209 | int bt = sv->type.t & VT_BTYPE; | 209 | int bt = sv->type.t & VT_BTYPE; |
| 210 | int align, size = type_size(&sv->type, &align); | 210 | int align, size; |
| 211 | if (fr & VT_LVAL) { | 211 | if (fr & VT_LVAL) { |
| 212 | int func3, opcode = is_freg(r) ? 0x07 : 0x03, br; | 212 | int func3, opcode = is_freg(r) ? 0x07 : 0x03, br; |
| 213 | size = type_size(&sv->type, &align); | ||
| 213 | assert (!is_freg(r) || bt == VT_FLOAT || bt == VT_DOUBLE); | 214 | assert (!is_freg(r) || bt == VT_FLOAT || bt == VT_DOUBLE); |
| 214 | if (bt == VT_FUNC) /* XXX should be done in generic code */ | 215 | if (bt == VT_FUNC) /* XXX should be done in generic code */ |
| 215 | size = PTR_SIZE; | 216 | size = PTR_SIZE; |
| @@ -290,6 +291,7 @@ ST_FUNC void load(int r, SValue *sv) · 74 unmodified lines | |||
| 290 | EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V | 291 | EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V |
| 291 | else { | 292 | else { |
| 292 | int func7 = is_ireg(r) ? 0x70 : 0x78; | 293 | int func7 = is_ireg(r) ? 0x70 : 0x78; |
| 294 | size = type_size(&sv->type, &align); | ||
| 293 | if (size == 8) | 295 | if (size == 8) |
| 294 | func7 |= 1; | 296 | func7 |= 1; |
| 295 | assert(size == 4 || size == 8); | 297 | assert(size == 4 || size == 8); |
| @@ -577,7 +579,7 @@ ST_FUNC void gfunc_call(int nb_args) · 281 unmodified lines | |||
| 577 | { | 579 | { |
| 578 | int i, align, size, areg[2]; | 580 | int i, align, size, areg[2]; |
| 579 | int info[nb_args ? nb_args : 1]; | 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 | SValue *sv; | 583 | SValue *sv; |
| 582 | Sym *sa; | 584 | Sym *sa; |
| 583 | 585 | ||
| @@ -644,8 +646,15 @@ ST_FUNC void gfunc_call(int nb_args) · 60 unmodified lines | |||
| 644 | } | 646 | } |
| 645 | stack_adj = (stack_adj + 15) & -16; | 647 | stack_adj = (stack_adj + 15) & -16; |
| 646 | tempspace = (tempspace + 15) & -16; | 648 | tempspace = (tempspace + 15) & -16; |
| 647 | if (stack_adj + tempspace) { | 649 | stack_add = stack_adj + tempspace; |
| 648 | EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj | 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 | for (i = ofs = 0; i < nb_args; i++) { | 658 | for (i = ofs = 0; i < nb_args; i++) { |
| 650 | if (info[i] & (64 | 32)) { | 659 | if (info[i] & (64 | 32)) { |
| 651 | vrotb(nb_args - i); | 660 | vrotb(nb_args - i); |
| @@ -757,8 +766,15 @@ ST_FUNC void gfunc_call(int nb_args) · 105 unmodified lines | |||
| 757 | save_regs(nb_args + 1); | 766 | save_regs(nb_args + 1); |
| 758 | gcall_or_jmp(1); | 767 | gcall_or_jmp(1); |
| 759 | vtop -= nb_args + 1; | 768 | vtop -= nb_args + 1; |
| 760 | if (stack_adj + tempspace) | 769 | if (stack_add) { |
| 761 | EI(0x13, 0, 2, 2, stack_adj + tempspace); // addi sp, sp, adj | 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 | static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; | 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 | int fc = vtop->c.i; | 1025 | int fc = vtop->c.i; |
| 1010 | if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) { | 1026 | if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) { |
| 1011 | int cll = 0; | 1027 | int cll = 0; |
| 1028 | int m = ll ? 31 : 63; | ||
| 1012 | vswap(); | 1029 | vswap(); |
| 1013 | gv(RC_INT); | 1030 | gv(RC_INT); |
| 1014 | a = ireg(vtop[0].r); | 1031 | a = ireg(vtop[0].r); |
| @@ -1023,6 +1040,7 @@ static void gen_opil(int op, int ll) · 8 unmodified lines | |||
| 1023 | fc = -fc; | 1040 | fc = -fc; |
| 1024 | case '+': | 1041 | case '+': |
| 1025 | func3 = 0; // addi d, a, fc | 1042 | func3 = 0; // addi d, a, fc |
| 1043 | cll = ll; | ||
| 1026 | do_cop: | 1044 | do_cop: |
| 1027 | EI(0x13 | cll, func3, ireg(d), a, fc); | 1045 | EI(0x13 | cll, func3, ireg(d), a, fc); |
| 1028 | --vtop; | 1046 | --vtop; |
| @@ -1045,22 +1063,22 @@ static void gen_opil(int op, int ll) · 16 unmodified lines | |||
| 1045 | case '^': func3 = 4; goto do_cop; // xori d, a, fc | 1063 | case '^': func3 = 4; goto do_cop; // xori d, a, fc |
| 1046 | case '|': func3 = 6; goto do_cop; // ori d, a, fc | 1064 | case '|': func3 = 6; goto do_cop; // ori d, a, fc |
| 1047 | case '&': func3 = 7; goto do_cop; // andi d, a, fc | 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 | 1066 | case TOK_SHL: func3 = 1; cll = ll; fc &= m; goto do_cop; // slli d, a, fc |
| 1049 | case TOK_SHR: func3 = 5; cll = ll; fc &= 63; goto do_cop; // srli d, a, fc | 1067 | case TOK_SHR: func3 = 5; cll = ll; fc &= m; goto do_cop; // srli d, a, fc |
| 1050 | case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & 63); goto do_cop; | 1068 | case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & m); goto do_cop; |
| 1051 | 1069 | ||
| 1052 | case TOK_UGE: | 1070 | case TOK_UGE: /* -> TOK_ULT */ |
| 1053 | case TOK_UGT: | 1071 | case TOK_UGT: /* -> TOK_ULE */ |
| 1054 | case TOK_GE: | 1072 | case TOK_GE: /* -> TOK_LT */ |
| 1055 | case TOK_GT: | 1073 | case TOK_GT: /* -> TOK_LE */ |
| 1056 | gen_opil(op - 1, ll); | 1074 | gen_opil(op - 1, !ll); |
| 1057 | vtop->cmp_op ^= 1; | 1075 | vtop->cmp_op ^= 1; |
| 1058 | return; | 1076 | return; |
| 1059 | 1077 | ||
| 1060 | case TOK_NE: | 1078 | case TOK_NE: |
| 1061 | case TOK_EQ: | 1079 | case TOK_EQ: |
| 1062 | if (fc) | 1080 | if (fc) |
| 1063 | gen_opil('-', ll), a = ireg(vtop++->r); | 1081 | gen_opil('-', !ll), a = ireg(vtop++->r); |
| 1064 | --vtop; | 1082 | --vtop; |
| 1065 | vset_VT_CMP(op); | 1083 | vset_VT_CMP(op); |
| 1066 | vtop->cmp_r = a | 0 << 8; | 1084 | vtop->cmp_r = a | 0 << 8; |
| @@ -1087,25 +1105,25 @@ static void gen_opil(int op, int ll) · 20 unmodified lines | |||
| 1087 | break; | 1105 | break; |
| 1088 | 1106 | ||
| 1089 | case '+': | 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 | break; | 1109 | break; |
| 1092 | case '-': | 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 | break; | 1112 | break; |
| 1095 | case TOK_SAR: | 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 | break; | 1115 | break; |
| 1098 | case TOK_SHR: | 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 | break; | 1118 | break; |
| 1101 | case TOK_SHL: | 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 | break; | 1121 | break; |
| 1104 | case '*': | 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 | break; | 1124 | break; |
| 1107 | case '/': | 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 | break; | 1127 | break; |
| 1110 | case '&': | 1128 | case '&': |
| 1111 | ER(0x33, 7, d, a, b, 0); // and d, a, b | 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 | ER(0x33, 6, d, a, b, 0); // or d, a, b | 1135 | ER(0x33, 6, d, a, b, 0); // or d, a, b |
| 1118 | break; | 1136 | break; |
| 1119 | case '%': | 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 | break; | 1139 | break; |
| 1122 | case TOK_UMOD: | 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 | break; | 1142 | break; |
| 1125 | case TOK_PDIV: | 1143 | case TOK_PDIV: |
| 1126 | case TOK_UDIV: | 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 | break; | 1146 | break; |
| 1129 | } | 1147 | } |
| 1130 | } | 1148 | } |
| @@ -5356,17 +5356,51 @@ static void parse_type(CType *type) · 5355 unmodified lines | |||
| 5356 | static void parse_builtin_params(int nc, const char *args) | 5356 | static void parse_builtin_params(int nc, const char *args) |
| 5357 | { | 5357 | { |
| 5358 | char c, sep = '('; | 5358 | char c, sep = '('; |
| 5359 | CType t; | 5359 | CType type; |
| 5360 | if (nc) | 5360 | if (nc) |
| 5361 | nocode_wanted++; | 5361 | nocode_wanted++; |
| 5362 | next(); | 5362 | next(); |
| 5363 | if (*args == 0) | ||
| 5364 | skip(sep); | ||
| 5363 | while ((c = *args++)) { | 5365 | while ((c = *args++)) { |
| 5364 | skip(sep); | 5366 | skip(sep); |
| 5365 | sep = ','; | 5367 | sep = ','; |
| 5366 | switch (c) { | 5368 | switch (c) { |
| 5367 | case 'e': expr_eq(); continue; | 5369 | case 'e': expr_eq(); |
| 5368 | case 't': parse_type(&t); vpush(&t); continue; | 5370 | continue; |
| 5369 | default: tcc_error("internal error"); break; | 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 | skip(')'); | 5406 | skip(')'); |
| @@ -5746,6 +5780,197 @@ ST_FUNC void unary(void) · 373 unmodified lines | |||
| 5746 | break; | 5780 | break; |
| 5747 | } | 5781 | } |
| 5748 | #endif | 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 | /* pre operations */ | 5974 | /* pre operations */ |
| 5750 | case TOK_INC: | 5975 | case TOK_INC: |
| 5751 | case TOK_DEC: | 5976 | case TOK_DEC: |
| @@ -7678,6 +7903,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1926 unmodified lines | |||
| 7678 | if (n >= 0 && len > n) | 7903 | if (n >= 0 && len > n) |
| 7679 | nb = n; | 7904 | nb = n; |
| 7680 | if (!(flags & DIF_SIZE_ONLY)) { | 7905 | if (!(flags & DIF_SIZE_ONLY)) { |
| 7906 | if (sec && !NODATA_WANTED && | ||
| 7907 | (c + nb > sec->data_allocated)) | ||
| 7908 | nb = sec->data_allocated - c; | ||
| 7681 | if (len > nb) | 7909 | if (len > nb) |
| 7682 | tcc_warning("initializer-string for array is too long"); | 7910 | tcc_warning("initializer-string for array is too long"); |
| 7683 | /* in order to go faster for common case (char | 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 | macho_write(s1, &mo, fp); | 821 | macho_write(s1, &mo, fp); |
| 822 | } | 822 | } |
| 823 | ret = 0; | ||
| 824 | 823 | ||
| 825 | do_ret: | 824 | do_ret: |
| 826 | for (i = 0; i < mo.nlc; i++) | 825 | for (i = 0; i < mo.nlc; i++) |
| @@ -314,11 +314,7 @@ · 313 unmodified lines | |||
| 314 | # ifdef TCC_TARGET_X86_64 | 314 | # ifdef TCC_TARGET_X86_64 |
| 315 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") | 315 | DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") |
| 316 | # endif | 316 | # endif |
| 317 | DEF(TOK_malloc, "malloc") | ||
| 318 | DEF(TOK_free, "free") | ||
| 319 | DEF(TOK_realloc, "realloc") | ||
| 320 | DEF(TOK_memalign, "memalign") | 317 | DEF(TOK_memalign, "memalign") |
| 321 | DEF(TOK_calloc, "calloc") | ||
| 322 | # else | 318 | # else |
| 323 | DEF(TOK_sigsetjmp, "sigsetjmp") | 319 | DEF(TOK_sigsetjmp, "sigsetjmp") |
| 324 | DEF(TOK___sigsetjmp, "__sigsetjmp") | 320 | DEF(TOK___sigsetjmp, "__sigsetjmp") |
| @@ -326,6 +322,27 @@ · 1 unmodified line | |||
| 326 | # endif | 322 | # endif |
| 327 | DEF(TOK_mmap, "mmap") | 323 | DEF(TOK_mmap, "mmap") |
| 328 | DEF(TOK_munmap, "munmap") | 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 | DEF(TOK_memcmp, "memcmp") | 346 | DEF(TOK_memcmp, "memcmp") |
| 330 | DEF(TOK_strlen, "strlen") | 347 | DEF(TOK_strlen, "strlen") |
| 331 | DEF(TOK_strcpy, "strcpy") | 348 | DEF(TOK_strcpy, "strcpy") |
| @@ -335,9 +352,30 @@ · 3 unmodified lines | |||
| 335 | DEF(TOK_strcat, "strcat") | 352 | DEF(TOK_strcat, "strcat") |
| 336 | DEF(TOK_strchr, "strchr") | 353 | DEF(TOK_strchr, "strchr") |
| 337 | DEF(TOK_strdup, "strdup") | 354 | DEF(TOK_strdup, "strdup") |
| 338 | DEF(TOK_setjmp, "setjmp") | 355 | DEF(TOK_malloc, "malloc") |
| 339 | DEF(TOK__setjmp, "_setjmp") | 356 | DEF(TOK_free, "free") |
| 340 | DEF(TOK_longjmp, "longjmp") | 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 | #endif | 379 | #endif |
| 342 | 380 | ||
| 343 | /* Tiny Assembler */ | 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 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture | 3 | TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture |
| 4 | TCC="./tcc -B. -I. -DNO_TRAMPOLINES" | 4 | TCC="./tcc -B. -I. -DNO_TRAMPOLINES" |
| 5 | rm -f tcc.sum tcc.log | 5 | rm -f tcc.sum tcc.fail |
| 6 | nb_ok="0" | ||
| 6 | nb_failed="0" | 7 | nb_failed="0" |
| 8 | nb_exe_failed="0" | ||
| 7 | 9 | ||
| 8 | for src in $TESTSUITE_PATH/compile/*.c ; do | 10 | for src in $TESTSUITE_PATH/compile/*.c ; do |
| 9 | echo $TCC -o /tmp/test.o -c $src | 11 | echo $TCC -o /tmp/tst.o -c $src |
| 10 | $TCC -o /tmp/test.o -c $src >> tcc.log 2>&1 | 12 | $TCC -o /tmp/tst.o -c $src >> tcc.fail 2>&1 |
| 11 | if [ "$?" = "0" ] ; then | 13 | if [ "$?" = "0" ] ; then |
| 12 | result="PASS" | 14 | result="PASS" |
| 15 | nb_ok=$(( $nb_ok + 1 )) | ||
| 13 | else | 16 | else |
| 14 | result="FAIL" | 17 | result="FAIL" |
| 15 | nb_failed=$(( $nb_failed + 1 )) | 18 | nb_failed=$(( $nb_failed + 1 )) |
| 16 | fi | 19 | fi |
| 17 | echo "$result: $src" >> tcc.sum | 20 | echo "$result: $src" >> tcc.sum |
| 18 | done | 21 | done |
| 19 | 22 | ||
| 20 | for src in $TESTSUITE_PATH/execute/*.c ; do | 23 | for src in $TESTSUITE_PATH/execute/*.c ; do |
| 21 | echo $TCC $src | 24 | echo $TCC $src -o /tmp/tst -lm |
| 22 | $TCC $src >> tcc.log 2>&1 | 25 | $TCC $src -o /tmp/tst -lm >> tcc.fail 2>&1 |
| 23 | if [ "$?" = "0" ] ; then | 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 | else | 36 | else |
| 26 | result="FAIL" | 37 | result="FAIL" |
| 27 | nb_failed=$(( $nb_failed + 1 )) | 38 | nb_failed=$(( $nb_failed + 1 )) |
| 28 | fi | 39 | fi |
| 29 | echo "$result: $src" >> tcc.sum | 40 | echo "$result: $src" >> tcc.sum |
| 30 | done | 41 | done |
| 31 | 42 | ||
| 43 | echo "$nb_ok test(s) ok." >> tcc.sum | ||
| 44 | echo "$nb_ok test(s) ok." | ||
| 32 | echo "$nb_failed test(s) failed." >> tcc.sum | 45 | echo "$nb_failed test(s) failed." >> tcc.sum |
| 33 | echo "$nb_failed test(s) failed." | 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 | #endif | 349 | #endif |
| @@ -159,3 +159,6 @@ bar : 3 ; 3 · 158 unmodified lines | |||
| 159 | 159 | ||
| 160 | [test_stray_backslash2] | 160 | [test_stray_backslash2] |
| 161 | \n | 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 | b = 0xbf0f; /* movswl */ | 441 | b = 0xbf0f; /* movswl */ |
| 442 | } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { | 442 | } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { |
| 443 | b = 0xb70f; /* movzwl */ | 443 | b = 0xb70f; /* movzwl */ |
| 444 | } else if ((ft & VT_TYPE) == (VT_VOID)) { | ||
| 445 | /* Can happen with zero size structs */ | ||
| 446 | return; | ||
| 444 | } else { | 447 | } else { |
| 445 | assert(((ft & VT_BTYPE) == VT_INT) | 448 | assert(((ft & VT_BTYPE) == VT_INT) |
| 446 | || ((ft & VT_BTYPE) == VT_LLONG) | 449 | || ((ft & VT_BTYPE) == VT_LLONG) |