Fix gcc testsuite problems

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.

all: fail for complex and vector types, nested functions
     and a lot of gcc defines/buitins.
arm/arm64/riscv: fail for asm and alloca.
riscv: fail with 'error: unimp: store(struct)'
This commit is contained in:
herman ten brugge 2020-07-05 14:01:50 +02:00
parent 6a15f15093
commit 9712aff9c0
14 changed files with 659 additions and 108 deletions

View File

@ -925,10 +925,12 @@ static int is_hgen_float_aggr(CType *type)
int btype, nb_fields = 0; int btype, nb_fields = 0;
ref = type->ref->next; ref = type->ref->next;
btype = unalias_ldbl(ref->type.t & VT_BTYPE); if (ref) {
if (btype == VT_FLOAT || btype == VT_DOUBLE) { btype = unalias_ldbl(ref->type.t & VT_BTYPE);
for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); if (btype == VT_FLOAT || btype == VT_DOUBLE) {
return !ref && nb_fields <= 4; for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
return !ref && nb_fields <= 4;
}
} }
} }
return 0; return 0;
@ -1017,7 +1019,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
ret->ref = NULL; ret->ref = NULL;
ret->t = VT_DOUBLE; ret->t = VT_DOUBLE;
return (size + 7) >> 3; return (size + 7) >> 3;
} else if (size <= 4) { } else if (size > 0 && size <= 4) {
*ret_align = 4; *ret_align = 4;
*regsize = 4; *regsize = 4;
ret->ref = NULL; ret->ref = NULL;

View File

@ -323,6 +323,9 @@ static void arm64_ldrs(int reg_, int size)
// Use x30 for intermediate value in some cases. // Use x30 for intermediate value in some cases.
switch (size) { switch (size) {
default: assert(0); break; default: assert(0); break;
case 0:
/* Can happen with zero size structs */
break;
case 1: case 1:
arm64_ldrx(0, 0, reg, reg, 0); arm64_ldrx(0, 0, reg, reg, 0);
break; break;
@ -429,30 +432,12 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off)
static void arm64_sym(int r, Sym *sym, unsigned long addend) static void arm64_sym(int r, Sym *sym, unsigned long addend)
{ {
// Currently TCC's linker does not generate COPY relocations for o(0x10000060 | r); // adr xr,pc+12
// STT_OBJECTs when tcc is invoked with "-run". This typically o(0xf9400000 | r | (r << 5)); // ldr xr,[xr]
// results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when o(0x14000003); // b + 8
// a program refers to stdin. A workaround is to avoid that greloca(cur_text_section, sym, ind, R_AARCH64_ABS64, addend);
// relocation and use only relocations with unlimited range. o(0);
int avoid_adrp = 1; o(0);
if (avoid_adrp || sym->a.weak) {
// (GCC uses a R_AARCH64_ABS64 in this case.)
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend);
o(0xd2800000 | r); // mov x(rt),#0,lsl #0
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G1_NC, addend);
o(0xf2a00000 | r); // movk x(rt),#0,lsl #16
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G2_NC, addend);
o(0xf2c00000 | r); // movk x(rt),#0,lsl #32
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G3, addend);
o(0xf2e00000 | r); // movk x(rt),#0,lsl #48
}
else {
greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, addend);
o(0x90000000 | r);
greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, addend);
o(0x91000000 | r | r << 5);
}
} }
static void arm64_load_cmp(int r, SValue *sv); static void arm64_load_cmp(int r, SValue *sv);
@ -474,12 +459,24 @@ ST_FUNC void load(int r, SValue *sv)
return; return;
} }
if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { if (svr == (VT_CONST | VT_LVAL)) {
arm64_sym(30, sv->sym, sv->c.i); // use x30 for address
if (IS_FREG(r)) if (IS_FREG(r))
arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, 0);
else else
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt), arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt),
intr(r), intr(svrv), 0); intr(r), 30, 0);
return;
}
if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) {
if ((svtt & VT_BTYPE) != VT_VOID) {
if (IS_FREG(r))
arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0);
else
arm64_ldrx(!(svtt & VT_UNSIGNED), arm64_type_size(svtt),
intr(r), intr(svrv), 0);
}
return; return;
} }
@ -573,6 +570,15 @@ ST_FUNC void store(int r, SValue *sv)
return; return;
} }
if (svr == (VT_CONST | VT_LVAL)) {
arm64_sym(30, sv->sym, sv->c.i); // use x30 for address
if (IS_FREG(r))
arm64_strv(arm64_type_size(svtt), fltr(r), 30, 0);
else
arm64_strx(arm64_type_size(svtt), intr(r), 30, 0);
return;
}
if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) { if ((svr & ~VT_VALMASK) == VT_LVAL && svrv < VT_CONST) {
if (IS_FREG(r)) if (IS_FREG(r))
arm64_strv(arm64_type_size(svtt), fltr(r), intr(svrv), 0); arm64_strv(arm64_type_size(svtt), fltr(r), intr(svrv), 0);
@ -597,9 +603,9 @@ ST_FUNC void store(int r, SValue *sv)
static void arm64_gen_bl_or_b(int b) static void arm64_gen_bl_or_b(int b)
{ {
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) { if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
assert(!b); greloca(cur_text_section, vtop->sym, ind,
greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0); b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0);
o(0x94000000); // bl . o(0x14000000 | (uint32_t)!b << 31); // b/bl .
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && if (tcc_state->do_bounds_check &&
(vtop->sym->v == TOK_setjmp || (vtop->sym->v == TOK_setjmp ||
@ -684,7 +690,8 @@ static void gen_bounds_prolog(void)
func_bound_offset = lbounds_section->data_offset; func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind; func_bound_ind = ind;
func_bound_add_epilog = 0; func_bound_add_epilog = 0;
o(0xd503201f); /* nop -> mov x0,#0,lsl #0, lbound section pointer */ o(0xd503201f); /* nop -> mov x0, lbound section pointer */
o(0xd503201f);
o(0xd503201f); o(0xd503201f);
o(0xd503201f); o(0xd503201f);
o(0xd503201f); o(0xd503201f);
@ -712,14 +719,12 @@ static void gen_bounds_epilog(void)
if (offset_modified) { if (offset_modified) {
saved_ind = ind; saved_ind = ind;
ind = func_bound_ind; ind = func_bound_ind;
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); o(0x10000060 | 0); // adr x0,pc+12
o(0xd2800000); /* mov x0,#0,lsl #0, lbound section pointer */ o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0]
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); o(0x14000003); // b + 8
o(0xf2a00000); /* movk x0,#0,lsl #16 */ greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0);
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); o(0);
o(0xf2c00000); /* movk x0,#0,lsl #32 */ o(0);
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
o(0xf2e00000); /* movk x0,#0,lsl #48 */
gen_bounds_call(TOK___bound_local_new); gen_bounds_call(TOK___bound_local_new);
ind = saved_ind; ind = saved_ind;
} }
@ -727,14 +732,12 @@ static void gen_bounds_epilog(void)
/* generate bound check local freeing */ /* generate bound check local freeing */
o(0xf81f0fe0); /* str x0, [sp, #-16]! */ o(0xf81f0fe0); /* str x0, [sp, #-16]! */
o(0x3c9f0fe0); /* str q0, [sp, #-16]! */ o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0); o(0x10000060 | 0); // adr x0,pc+12
o(0xd2800000); // mov x0,#0,lsl #0 o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0]
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0); o(0x14000003); // b + 8
o(0xf2a00000); // movk x0,#0,lsl #16 greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0);
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0); o(0);
o(0xf2c00000); // movk x0,#0,lsl #32 o(0);
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
o(0xf2e00000); // movk x0,#0,lsl #48
gen_bounds_call(TOK___bound_local_delete); gen_bounds_call(TOK___bound_local_delete);
o(0x3cc107e0); /* ldr q0, [sp], #16 */ o(0x3cc107e0); /* ldr q0, [sp], #16 */
o(0xf84107e0); /* ldr x0, [sp], #16 */ o(0xf84107e0); /* ldr x0, [sp], #16 */
@ -1014,9 +1017,12 @@ ST_FUNC void gfunc_call(int nb_args)
stack = (stack + 15) >> 4 << 4; stack = (stack + 15) >> 4 << 4;
assert(stack < 0x1000); if (stack >= 0x1000000) // 16Mb
if (stack) tcc_error("stack size too big %lu", stack);
o(0xd10003ff | stack << 10); // sub sp,sp,#(n) if (stack & 0xfff)
o(0xd10003ff | (stack & 0xfff) << 10); // sub sp,sp,#(n)
if (stack >> 12)
o(0xd14003ff | (stack >> 12) << 10);
// First pass: set all values on stack // First pass: set all values on stack
for (i = nb_args; i; i--) { for (i = nb_args; i; i--) {
@ -1109,8 +1115,10 @@ ST_FUNC void gfunc_call(int nb_args)
save_regs(0); save_regs(0);
arm64_gen_bl_or_b(0); arm64_gen_bl_or_b(0);
--vtop; --vtop;
if (stack) if (stack & 0xfff)
o(0x910003ff | stack << 10); // add sp,sp,#(n) o(0x910003ff | (stack & 0xfff) << 10); // add sp,sp,#(n)
if (stack >> 12)
o(0x914003ff | (stack >> 12) << 10);
{ {
int rt = return_type->t; int rt = return_type->t;
@ -1611,8 +1619,11 @@ static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val,
val = val & (n - 1); val = val & (n - 1);
if (rev) if (rev)
return 0; return 0;
if (!val) if (!val) {
assert(0); // tcc_warning("shift count >= width of type");
o(0x2a0003e0 | l << 31 | a << 16);
return 1;
}
else if (op == TOK_SHL) else if (op == TOK_SHL)
o(0x53000000 | l << 31 | l << 22 | x | a << 5 | o(0x53000000 | l << 31 | l << 22 | x | a << 5 |
(n - val) << 16 | (n - 1 - val) << 10); // lsl (n - val) << 16 | (n - 1 - val) << 10); // lsl

View File

@ -963,6 +963,24 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1"); tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1");
tcc_define_symbol(s, "_FORTIFY_SOURCE", "0"); tcc_define_symbol(s, "_FORTIFY_SOURCE", "0");
#endif /* ndef TCC_TARGET_MACHO */ #endif /* ndef TCC_TARGET_MACHO */
if (PTR_SIZE == 4) {
tcc_define_symbol(s, "__SIZEOF_LONG__", "4");
tcc_define_symbol(s, "__LONG_MAX__", "0x7fffffffL");
}
else {
tcc_define_symbol(s, "__SIZEOF_LONG__", "8");
tcc_define_symbol(s, "__LONG_MAX__", "0x7fffffffffffffffL");
}
tcc_define_symbol(s, "__SIZEOF_INT__", "4");
tcc_define_symbol(s, "__SIZEOF_LONG_LONG__", "8");
tcc_define_symbol(s, "__CHAR_BIT__", "8");
tcc_define_symbol(s, "__ORDER_LITTLE_ENDIAN__", "1234");
tcc_define_symbol(s, "__ORDER_BIG_ENDIAN__", "4321");
tcc_define_symbol(s, "__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__");
tcc_define_symbol(s, "__INT_MAX__", "0x7fffffff");
tcc_define_symbol(s, "__LONG_LONG_MAX__", "0x7fffffffffffffffLL");
tcc_define_symbol(s, "__builtin_offsetof(type,field)", "((unsigned long) &((type *)0)->field)");
return s; return s;
} }

View File

@ -207,9 +207,10 @@ ST_FUNC void load(int r, SValue *sv)
int rr = is_ireg(r) ? ireg(r) : freg(r); int rr = is_ireg(r) ? ireg(r) : freg(r);
int fc = sv->c.i; int fc = sv->c.i;
int bt = sv->type.t & VT_BTYPE; int bt = sv->type.t & VT_BTYPE;
int align, size = type_size(&sv->type, &align); int align, size;
if (fr & VT_LVAL) { if (fr & VT_LVAL) {
int func3, opcode = is_freg(r) ? 0x07 : 0x03, br; int func3, opcode = is_freg(r) ? 0x07 : 0x03, br;
size = type_size(&sv->type, &align);
assert (!is_freg(r) || bt == VT_FLOAT || bt == VT_DOUBLE); assert (!is_freg(r) || bt == VT_FLOAT || bt == VT_DOUBLE);
if (bt == VT_FUNC) /* XXX should be done in generic code */ if (bt == VT_FUNC) /* XXX should be done in generic code */
size = PTR_SIZE; size = PTR_SIZE;
@ -290,6 +291,7 @@ ST_FUNC void load(int r, SValue *sv)
EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V EI(0x13, 0, rr, ireg(v), 0); // addi RR, V, 0 == mv RR, V
else { else {
int func7 = is_ireg(r) ? 0x70 : 0x78; int func7 = is_ireg(r) ? 0x70 : 0x78;
size = type_size(&sv->type, &align);
if (size == 8) if (size == 8)
func7 |= 1; func7 |= 1;
assert(size == 4 || size == 8); assert(size == 4 || size == 8);
@ -577,7 +579,7 @@ ST_FUNC void gfunc_call(int nb_args)
{ {
int i, align, size, areg[2]; int i, align, size, areg[2];
int info[nb_args ? nb_args : 1]; int info[nb_args ? nb_args : 1];
int stack_adj = 0, tempspace = 0, ofs, splitofs = 0; int stack_adj = 0, tempspace = 0, stack_add, ofs, splitofs = 0;
SValue *sv; SValue *sv;
Sym *sa; Sym *sa;
@ -644,8 +646,15 @@ ST_FUNC void gfunc_call(int nb_args)
} }
stack_adj = (stack_adj + 15) & -16; stack_adj = (stack_adj + 15) & -16;
tempspace = (tempspace + 15) & -16; tempspace = (tempspace + 15) & -16;
if (stack_adj + tempspace) { stack_add = stack_adj + tempspace;
EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj if (stack_add) {
if (stack_add >= 0x1000) {
o(0x37 | (5 << 7) | (-stack_add & 0xfffff000)); //lui t0, upper(v)
EI(0x13, 0, 5, 5, -stack_add << 20 >> 20); // addi t0, t0, lo(v)
ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0
}
else
EI(0x13, 0, 2, 2, -stack_add); // addi sp, sp, -adj
for (i = ofs = 0; i < nb_args; i++) { for (i = ofs = 0; i < nb_args; i++) {
if (info[i] & (64 | 32)) { if (info[i] & (64 | 32)) {
vrotb(nb_args - i); vrotb(nb_args - i);
@ -757,8 +766,15 @@ ST_FUNC void gfunc_call(int nb_args)
save_regs(nb_args + 1); save_regs(nb_args + 1);
gcall_or_jmp(1); gcall_or_jmp(1);
vtop -= nb_args + 1; vtop -= nb_args + 1;
if (stack_adj + tempspace) if (stack_add) {
EI(0x13, 0, 2, 2, stack_adj + tempspace); // addi sp, sp, adj if (stack_add >= 0x1000) {
o(0x37 | (5 << 7) | (stack_add & 0xfffff000)); //lui t0, upper(v)
EI(0x13, 0, 5, 5, stack_add << 20 >> 20); // addi t0, t0, lo(v)
ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0
}
else
EI(0x13, 0, 2, 2, stack_add); // addi sp, sp, adj
}
} }
static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; 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)
int fc = vtop->c.i; int fc = vtop->c.i;
if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) { if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) {
int cll = 0; int cll = 0;
int m = ll ? 31 : 63;
vswap(); vswap();
gv(RC_INT); gv(RC_INT);
a = ireg(vtop[0].r); a = ireg(vtop[0].r);
@ -1023,6 +1040,7 @@ static void gen_opil(int op, int ll)
fc = -fc; fc = -fc;
case '+': case '+':
func3 = 0; // addi d, a, fc func3 = 0; // addi d, a, fc
cll = ll;
do_cop: do_cop:
EI(0x13 | cll, func3, ireg(d), a, fc); EI(0x13 | cll, func3, ireg(d), a, fc);
--vtop; --vtop;
@ -1045,22 +1063,22 @@ static void gen_opil(int op, int ll)
case '^': func3 = 4; goto do_cop; // xori d, a, fc case '^': func3 = 4; goto do_cop; // xori d, a, fc
case '|': func3 = 6; goto do_cop; // ori d, a, fc case '|': func3 = 6; goto do_cop; // ori d, a, fc
case '&': func3 = 7; goto do_cop; // andi d, a, fc case '&': func3 = 7; goto do_cop; // andi d, a, fc
case TOK_SHL: func3 = 1; fc &= 63; goto do_cop; // slli d, a, fc case TOK_SHL: func3 = 1; cll = ll; fc &= m; goto do_cop; // slli d, a, fc
case TOK_SHR: func3 = 5; cll = ll; fc &= 63; goto do_cop; // srli d, a, fc case TOK_SHR: func3 = 5; cll = ll; fc &= m; goto do_cop; // srli d, a, fc
case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & 63); goto do_cop; case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & m); goto do_cop;
case TOK_UGE: case TOK_UGE: /* -> TOK_ULT */
case TOK_UGT: case TOK_UGT: /* -> TOK_ULE */
case TOK_GE: case TOK_GE: /* -> TOK_LT */
case TOK_GT: case TOK_GT: /* -> TOK_LE */
gen_opil(op - 1, ll); gen_opil(op - 1, !ll);
vtop->cmp_op ^= 1; vtop->cmp_op ^= 1;
return; return;
case TOK_NE: case TOK_NE:
case TOK_EQ: case TOK_EQ:
if (fc) if (fc)
gen_opil('-', ll), a = ireg(vtop++->r); gen_opil('-', !ll), a = ireg(vtop++->r);
--vtop; --vtop;
vset_VT_CMP(op); vset_VT_CMP(op);
vtop->cmp_r = a | 0 << 8; vtop->cmp_r = a | 0 << 8;
@ -1087,25 +1105,25 @@ static void gen_opil(int op, int ll)
break; break;
case '+': case '+':
ER(0x33, 0, d, a, b, 0); // add d, a, b ER(0x33 | ll, 0, d, a, b, 0); // add d, a, b
break; break;
case '-': case '-':
ER(0x33, 0, d, a, b, 0x20); // sub d, a, b ER(0x33 | ll, 0, d, a, b, 0x20); // sub d, a, b
break; break;
case TOK_SAR: case TOK_SAR:
ER(0x33 | ll, 5, d, a, b, 0x20); // sra d, a, b ER(0x33 | ll | ll, 5, d, a, b, 0x20); // sra d, a, b
break; break;
case TOK_SHR: case TOK_SHR:
ER(0x33 | ll, 5, d, a, b, 0); // srl d, a, b ER(0x33 | ll | ll, 5, d, a, b, 0); // srl d, a, b
break; break;
case TOK_SHL: case TOK_SHL:
ER(0x33, 1, d, a, b, 0); // sll d, a, b ER(0x33 | ll, 1, d, a, b, 0); // sll d, a, b
break; break;
case '*': case '*':
ER(0x33, 0, d, a, b, 1); // mul d, a, b ER(0x33 | ll, 0, d, a, b, 1); // mul d, a, b
break; break;
case '/': case '/':
ER(0x33, 4, d, a, b, 1); // div d, a, b ER(0x33 | ll, 4, d, a, b, 1); // div d, a, b
break; break;
case '&': case '&':
ER(0x33, 7, d, a, b, 0); // and d, a, b ER(0x33, 7, d, a, b, 0); // and d, a, b
@ -1117,14 +1135,14 @@ static void gen_opil(int op, int ll)
ER(0x33, 6, d, a, b, 0); // or d, a, b ER(0x33, 6, d, a, b, 0); // or d, a, b
break; break;
case '%': case '%':
ER(0x33, 6, d, a, b, 1); // rem d, a, b ER(ll ? 0x3b: 0x33, 6, d, a, b, 1); // rem d, a, b
break; break;
case TOK_UMOD: case TOK_UMOD:
ER(0x33, 7, d, a, b, 1); // remu d, a, b ER(0x33 | ll, 7, d, a, b, 1); // remu d, a, b
break; break;
case TOK_PDIV: case TOK_PDIV:
case TOK_UDIV: case TOK_UDIV:
ER(0x33, 5, d, a, b, 1); // divu d, a, b ER(0x33 | ll, 5, d, a, b, 1); // divu d, a, b
break; break;
} }
} }

236
tccgen.c
View File

@ -5356,17 +5356,51 @@ static void parse_type(CType *type)
static void parse_builtin_params(int nc, const char *args) static void parse_builtin_params(int nc, const char *args)
{ {
char c, sep = '('; char c, sep = '(';
CType t; CType type;
if (nc) if (nc)
nocode_wanted++; nocode_wanted++;
next(); next();
if (*args == 0)
skip(sep);
while ((c = *args++)) { while ((c = *args++)) {
skip(sep); skip(sep);
sep = ','; sep = ',';
switch (c) { switch (c) {
case 'e': expr_eq(); continue; case 'e': expr_eq();
case 't': parse_type(&t); vpush(&t); continue; continue;
default: tcc_error("internal error"); break; case 't': parse_type(&type);
vpush(&type);
continue;
case 'v':
case 'V': expr_eq();
type.t = VT_VOID;
if (c == 'V') type.t |= VT_CONSTANT;
type.ref = NULL;
mk_pointer (&type);
gen_assign_cast(&type);
continue;
case 's':
case 'S': expr_eq();
type.t = VT_BYTE;
if (tcc_state->char_is_unsigned)
type.t |= VT_UNSIGNED;
if (c == 'S') type.t |= VT_CONSTANT;
type.ref = NULL;
mk_pointer (&type);
gen_assign_cast(&type);
continue;
case 'i': expr_eq();
type.t = VT_INT;
type.ref = NULL;
gen_assign_cast(&type);
continue;
case 'l': expr_eq();
type.t = VT_SIZE_T;
type.ref = NULL;
gen_assign_cast(&type);
continue;
default: tcc_error("internal error");
break;
} }
} }
skip(')'); skip(')');
@ -5746,6 +5780,197 @@ ST_FUNC void unary(void)
break; break;
} }
#endif #endif
case TOK___builtin_abort:
vpush_global_sym(&func_old_type, TOK_abort);
parse_builtin_params(0, "");
gfunc_call(0);
builtin_void_return:
vpushi(0);
type.t = VT_VOID;
type.ref = NULL;
vtop->type = type;
vtop->r = R_RET(type.t);
break;
case TOK___builtin_memcpy:
t = TOK_memcpy;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_memcpy;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "vVl");
gfunc_call(3);
builtin_void_ptr_return:
vpushi(0);
type.t = VT_VOID;
type.ref = NULL;
mk_pointer (&type);
vtop->type = type;
vtop->r = R_RET(type.t);
break;
case TOK___builtin_memcmp:
t = TOK_memcmp;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_memcmp;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "VVl");
gfunc_call(3);
builtin_int_return:
vpushi(0);
type.t = VT_INT;
type.ref = NULL;
vtop->type = type;
vtop->r = R_RET(type.t);
break;
case TOK___builtin_memmove:
t = TOK_memmove;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_memmove;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "vVl");
gfunc_call(3);
goto builtin_void_ptr_return;
case TOK___builtin_memset:
t = TOK_memset;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_memset;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "vil");
gfunc_call(3);
goto builtin_void_ptr_return;
case TOK___builtin_strlen:
t = TOK_strlen;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strlen;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "S");
gfunc_call(1);
vpushi(0);
type.t = VT_SIZE_T;
type.ref = NULL;
vtop->type = type;
vtop->r = R_RET(type.t);
break;
case TOK___builtin_strcpy:
t = TOK_strcpy;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strcpy;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "sS");
gfunc_call(2);
builtin_string_ptr_return:
vpushi(0);
type.t = VT_BYTE;
if (tcc_state->char_is_unsigned)
type.t |= VT_UNSIGNED;
type.ref = NULL;
mk_pointer (&type);
vtop->type = type;
vtop->r = R_RET(type.t);
break;
case TOK___builtin_strncpy:
t = TOK_strncpy;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strncpy;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "sSl");
gfunc_call(3);
goto builtin_string_ptr_return;
case TOK___builtin_strcmp:
t = TOK_strcmp;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strcmp;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "SS");
gfunc_call(2);
goto builtin_int_return;
case TOK___builtin_strncmp:
t = TOK_strncmp;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strncmp;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "SSl");
gfunc_call(3);
goto builtin_int_return;
case TOK___builtin_strcat:
t = TOK_strcat;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strcat;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "sS");
gfunc_call(2);
goto builtin_string_ptr_return;
case TOK___builtin_strchr:
t = TOK_strchr;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strchr;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "Si");
gfunc_call(2);
goto builtin_string_ptr_return;
case TOK___builtin_strdup:
t = TOK_strdup;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check) t = TOK___bound_strdup;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "S");
gfunc_call(1);
goto builtin_string_ptr_return;
case TOK___builtin_malloc:
t = TOK_malloc;
#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE)
if (tcc_state->do_bounds_check) t = TOK___bound_malloc;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "l");
gfunc_call(1);
goto builtin_void_ptr_return;
case TOK___builtin_realloc:
t = TOK_realloc;
#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE)
if (tcc_state->do_bounds_check) t = TOK___bound_realloc;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "vl");
gfunc_call(2);
goto builtin_void_ptr_return;
case TOK___builtin_calloc:
t = TOK_calloc;
#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE)
if (tcc_state->do_bounds_check) t = TOK___bound_calloc;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "ll");
gfunc_call(2);
goto builtin_void_ptr_return;
case TOK___builtin_free:
t = TOK_free;
#if defined(CONFIG_TCC_BCHECK) && defined(TCC_TARGET_PE)
if (tcc_state->do_bounds_check) t = TOK___bound_free;
#endif
vpush_global_sym(&func_old_type, t);
parse_builtin_params(0, "v");
gfunc_call(1);
goto builtin_void_return;
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
case TOK_alloca:
case TOK___builtin_alloca:
vpush_global_sym(&func_old_type, TOK_alloca);
parse_builtin_params(0, "l");
gfunc_call(1);
goto builtin_void_ptr_return;
#endif
/* pre operations */ /* pre operations */
case TOK_INC: case TOK_INC:
case TOK_DEC: case TOK_DEC:
@ -7678,6 +7903,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
if (n >= 0 && len > n) if (n >= 0 && len > n)
nb = n; nb = n;
if (!(flags & DIF_SIZE_ONLY)) { if (!(flags & DIF_SIZE_ONLY)) {
if (sec && !NODATA_WANTED &&
(c + nb > sec->data_allocated))
nb = sec->data_allocated - c;
if (len > nb) if (len > nb)
tcc_warning("initializer-string for array is too long"); tcc_warning("initializer-string for array is too long");
/* in order to go faster for common case (char /* in order to go faster for common case (char

View File

@ -820,7 +820,6 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
macho_write(s1, &mo, fp); macho_write(s1, &mo, fp);
} }
ret = 0;
do_ret: do_ret:
for (i = 0; i < mo.nlc; i++) for (i = 0; i < mo.nlc; i++)

View File

@ -314,11 +314,7 @@
# ifdef TCC_TARGET_X86_64 # ifdef TCC_TARGET_X86_64
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr") DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
# endif # endif
DEF(TOK_malloc, "malloc")
DEF(TOK_free, "free")
DEF(TOK_realloc, "realloc")
DEF(TOK_memalign, "memalign") DEF(TOK_memalign, "memalign")
DEF(TOK_calloc, "calloc")
# else # else
DEF(TOK_sigsetjmp, "sigsetjmp") DEF(TOK_sigsetjmp, "sigsetjmp")
DEF(TOK___sigsetjmp, "__sigsetjmp") DEF(TOK___sigsetjmp, "__sigsetjmp")
@ -326,6 +322,27 @@
# endif # endif
DEF(TOK_mmap, "mmap") DEF(TOK_mmap, "mmap")
DEF(TOK_munmap, "munmap") DEF(TOK_munmap, "munmap")
DEF(TOK_setjmp, "setjmp")
DEF(TOK__setjmp, "_setjmp")
DEF(TOK_longjmp, "longjmp")
DEF(TOK___bound_memcpy, "__bound_memcpy")
DEF(TOK___bound_memcmp, "__bound_memcmp")
DEF(TOK___bound_memmove, "__bound_memmove")
DEF(TOK___bound_memset, "__bound_memset")
DEF(TOK___bound_strlen, "__bound_strlen")
DEF(TOK___bound_strcpy, "__bound_strcpy")
DEF(TOK___bound_strncpy, "__bound_strncpy")
DEF(TOK___bound_strcmp, "__bound_strcmp")
DEF(TOK___bound_strncmp, "__bound_strncmp")
DEF(TOK___bound_strcat, "__bound_strcat")
DEF(TOK___bound_strchr, "__bound_strchr")
DEF(TOK___bound_strdup, "__bound_strdup")
DEF(TOK___bound_malloc, "__bound_malloc")
DEF(TOK___bound_free, "__bound_free")
DEF(TOK___bound_realloc, "__bound_realloc")
DEF(TOK___bound_calloc, "__bound_calloc")
#endif
DEF(TOK_abort, "abort")
DEF(TOK_memcmp, "memcmp") DEF(TOK_memcmp, "memcmp")
DEF(TOK_strlen, "strlen") DEF(TOK_strlen, "strlen")
DEF(TOK_strcpy, "strcpy") DEF(TOK_strcpy, "strcpy")
@ -335,9 +352,30 @@
DEF(TOK_strcat, "strcat") DEF(TOK_strcat, "strcat")
DEF(TOK_strchr, "strchr") DEF(TOK_strchr, "strchr")
DEF(TOK_strdup, "strdup") DEF(TOK_strdup, "strdup")
DEF(TOK_setjmp, "setjmp") DEF(TOK_malloc, "malloc")
DEF(TOK__setjmp, "_setjmp") DEF(TOK_free, "free")
DEF(TOK_longjmp, "longjmp") DEF(TOK_realloc, "realloc")
DEF(TOK_calloc, "calloc")
DEF(TOK___builtin_abort, "__builtin_abort")
DEF(TOK___builtin_memcpy, "__builtin_memcpy")
DEF(TOK___builtin_memcmp, "__builtin_memcmp")
DEF(TOK___builtin_memmove, "__builtin_memmove")
DEF(TOK___builtin_memset, "__builtin_memset")
DEF(TOK___builtin_strlen, "__builtin_strlen")
DEF(TOK___builtin_strcpy, "__builtin_strcpy")
DEF(TOK___builtin_strncpy, "__builtin_strncpy")
DEF(TOK___builtin_strcmp, "__builtin_strcmp")
DEF(TOK___builtin_strncmp, "__builtin_strncmp")
DEF(TOK___builtin_strcat, "__builtin_strcat")
DEF(TOK___builtin_strchr, "__builtin_strchr")
DEF(TOK___builtin_strdup, "__builtin_strdup")
DEF(TOK___builtin_malloc, "__builtin_malloc")
DEF(TOK___builtin_free, "__builtin_free")
DEF(TOK___builtin_realloc, "__builtin_realloc")
DEF(TOK___builtin_calloc, "__builtin_calloc")
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
DEF(TOK___builtin_alloca, "__builtin_alloca")
#endif #endif
/* Tiny Assembler */ /* Tiny Assembler */

75
tests/bug.c Normal file
View File

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdarg.h>
void tst1(void)
{
/* problem in gen_cast. Should mask unsigned types */
signed char c = (signed char) 0xffffffff;
int r = (unsigned short) c ^ (signed char) 0x99999999;
if (r != 0xffff0066) printf ("%x\n", r);
}
typedef struct{double x,y;}p;
void tst2(int n,...)
{
/* va_arg for struct double does not work on some targets */
int i;
va_list args;
va_start(args,n);
for (i = 0; i < n; i++) {
p v = va_arg(args,p);
if (v.x != 1 || v.y != 2) printf("%g %g\n", v.x, v.y);
}
va_end(args);
}
void tst3(void)
{
/* Should VT_SYM be checked for TOK_builtin_constant_p */
int r = __builtin_constant_p("c");
if (r == 0) printf("%d\n",r);
}
int compile_errors(void)
{
#if TEST == 1
{
/* Not constant */
static int i = (&"Foobar"[1] - &"Foobar"[0]);
}
#endif
#if TEST == 2
{
/* Not constant */
struct{int c;}v;
static long i=((char*)&(v.c)-(char*)&v);
}
#endif
#if TEST == 3
{
/* Not constant */
static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 };
void *p = &&l1 + ar[0];
goto *p;
l1: return 1;
l2: return 2;
}
#endif
#if TEST == 4
{
/* Only integer allowed */
__builtin_return_address(0 + 1) != NULL;
}
#endif
return 0;
}
int
main(void)
{
p v = { 1, 2};
tst1();
tst2(1, v);
tst3();
}

View File

@ -1,33 +1,48 @@
#!/bin/sh #!/bin/sh
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
TCC="./tcc -B. -I. -DNO_TRAMPOLINES" TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
rm -f tcc.sum tcc.log rm -f tcc.sum tcc.fail
nb_ok="0"
nb_failed="0" nb_failed="0"
nb_exe_failed="0"
for src in $TESTSUITE_PATH/compile/*.c ; do for src in $TESTSUITE_PATH/compile/*.c ; do
echo $TCC -o /tmp/test.o -c $src echo $TCC -o /tmp/tst.o -c $src
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1 $TCC -o /tmp/tst.o -c $src >> tcc.fail 2>&1
if [ "$?" = "0" ] ; then if [ "$?" = "0" ] ; then
result="PASS" result="PASS"
nb_ok=$(( $nb_ok + 1 ))
else else
result="FAIL" result="FAIL"
nb_failed=$(( $nb_failed + 1 )) nb_failed=$(( $nb_failed + 1 ))
fi fi
echo "$result: $src" >> tcc.sum echo "$result: $src" >> tcc.sum
done done
for src in $TESTSUITE_PATH/execute/*.c ; do for src in $TESTSUITE_PATH/execute/*.c ; do
echo $TCC $src echo $TCC $src -o /tmp/tst -lm
$TCC $src >> tcc.log 2>&1 $TCC $src -o /tmp/tst -lm >> tcc.fail 2>&1
if [ "$?" = "0" ] ; then if [ "$?" = "0" ] ; then
result="PASS" result="PASS"
if /tmp/tst >> tcc.fail 2>&1
then
result="PASS"
nb_ok=$(( $nb_ok + 1 ))
else
result="FAILEXE"
nb_exe_failed=$(( $nb_exe_failed + 1 ))
fi
else else
result="FAIL" result="FAIL"
nb_failed=$(( $nb_failed + 1 )) nb_failed=$(( $nb_failed + 1 ))
fi fi
echo "$result: $src" >> tcc.sum echo "$result: $src" >> tcc.sum
done done
echo "$nb_ok test(s) ok." >> tcc.sum
echo "$nb_ok test(s) ok."
echo "$nb_failed test(s) failed." >> tcc.sum echo "$nb_failed test(s) failed." >> tcc.sum
echo "$nb_failed test(s) failed." echo "$nb_failed test(s) failed."
echo "$nb_exe_failed test(s) exe failed." >> tcc.sum
echo "$nb_exe_failed test(s) exe failed."

134
tests/tests2/117_gcc_test.c Normal file
View File

@ -0,0 +1,134 @@
#include <stdio.h>
void tst_branch(void)
{
goto *&&a;
printf ("dummy");
a: ;
}
void tst_void_ptr(void *pv, int i)
{
i ? *pv : *pv; // dr106
}
void tst_shift(void)
{
int i = 1;
long l = 1;
i = i << 32; // illegal. just test
l = l << 64; // illegal. just test
}
#if !defined(_WIN32)
#include <sys/mman.h>
void tst_const_addr(void)
{
void *addr = mmap ((void *)0x20000000, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS, -1, 0);
if (addr != (void *) -1) {
#if !defined(__riscv)
*(int *)0x20000000 += 42;
#endif
munmap (addr, 4096);
}
}
#endif
struct zero_struct {};
struct zero_struct tst_zero_struct(void)
{
struct zero_struct ret;
return ret;
}
struct big_struct { char a[262144]; };
struct big_struct tst_big(struct big_struct tst)
{
return tst;
}
void tst_adr (int (*fp)(char *, const char *, ...))
{
char buf[10];
(*fp)(buf, "%.0f", 5.0);
}
static const char str[] = "abcdefghijklmnopqrstuvwxyz";
void tst_builtin(void)
{
char *p;
char tmp[100];
if (__builtin_offsetof(struct big_struct, a) != 0) __builtin_abort();
p = __builtin_memcpy (tmp, str, sizeof(str));
if (p != tmp) __builtin_abort();
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
p = __builtin_memmove(tmp, str, sizeof(str));
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
p = __builtin_memset(tmp, 0, sizeof (tmp));
if (p != tmp || tmp[0] != 0 || tmp[99] != 0) __builtin_abort();
if (__builtin_strlen(str) != sizeof(str) - 1) __builtin_abort();
p = __builtin_strcpy(tmp, str);
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
p = __builtin_strncpy(tmp, str, sizeof(str));
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
if (__builtin_strcmp (p, str)) __builtin_abort();
if (__builtin_strncmp (p, str, sizeof(str))) __builtin_abort();
tmp[0] = '\0';
p = __builtin_strcat(tmp, str);
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
if (__builtin_strchr(p, 'z') != &p[25]) __builtin_abort();
p = __builtin_strdup (str);
if (__builtin_memcmp (p, str, sizeof(str))) __builtin_abort();
__builtin_free(p);
p = __builtin_malloc (100);
__builtin_memset(p, 0, 100);
p = __builtin_realloc (p, 1000);
__builtin_memset(p, 0, 1000);
__builtin_free(p);
p = __builtin_calloc(10, 10);
__builtin_memset(p, 0, 100);
__builtin_free(p);
#if defined(__i386__) || defined(__x86_64__)
p = __builtin_alloca(100);
__builtin_memset(p, 0, 100);
#endif
}
int
main (void)
{
struct big_struct big;
tst_shift();
tst_void_ptr(&big.a[0], 0);
#if !defined(_WIN32)
tst_const_addr();
#endif
tst_zero_struct();
tst_big(big);
tst_adr(&sprintf);
tst_builtin();
}

View File

View File

@ -339,4 +339,11 @@ int main()
} }
/******************************************************************/ /******************************************************************/
#elif defined test_var_array
static struct var_len { int i; const char str[]; } var_array[] =
{ { 1, "abcdefghijklmnopqrstuvwxyz" },
{ 2, "longlonglonglonglong" },
{ 3, "tst3" } };
#endif #endif

View File

@ -159,3 +159,6 @@ bar : 3 ; 3
[test_stray_backslash2] [test_stray_backslash2]
\n \n
[test_var_array]
60_errors_and_warnings.c:345: warning: initializer-string for array is too long

View File

@ -441,6 +441,9 @@ void load(int r, SValue *sv)
b = 0xbf0f; /* movswl */ b = 0xbf0f; /* movswl */
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
b = 0xb70f; /* movzwl */ b = 0xb70f; /* movzwl */
} else if ((ft & VT_TYPE) == (VT_VOID)) {
/* Can happen with zero size structs */
return;
} else { } else {
assert(((ft & VT_BTYPE) == VT_INT) assert(((ft & VT_BTYPE) == VT_INT)
|| ((ft & VT_BTYPE) == VT_LLONG) || ((ft & VT_BTYPE) == VT_LLONG)