mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-25 06:00:11 +08:00
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:
parent
6a15f15093
commit
9712aff9c0
12
arm-gen.c
12
arm-gen.c
@ -925,10 +925,12 @@ static int is_hgen_float_aggr(CType *type)
|
||||
int btype, nb_fields = 0;
|
||||
|
||||
ref = type->ref->next;
|
||||
btype = unalias_ldbl(ref->type.t & VT_BTYPE);
|
||||
if (btype == VT_FLOAT || btype == VT_DOUBLE) {
|
||||
for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
|
||||
return !ref && nb_fields <= 4;
|
||||
if (ref) {
|
||||
btype = unalias_ldbl(ref->type.t & VT_BTYPE);
|
||||
if (btype == VT_FLOAT || btype == VT_DOUBLE) {
|
||||
for(; ref && btype == unalias_ldbl(ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++);
|
||||
return !ref && nb_fields <= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
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->t = VT_DOUBLE;
|
||||
return (size + 7) >> 3;
|
||||
} else if (size <= 4) {
|
||||
} else if (size > 0 && size <= 4) {
|
||||
*ret_align = 4;
|
||||
*regsize = 4;
|
||||
ret->ref = NULL;
|
||||
|
119
arm64-gen.c
119
arm64-gen.c
@ -323,6 +323,9 @@ static void arm64_ldrs(int reg_, int size)
|
||||
// Use x30 for intermediate value in some cases.
|
||||
switch (size) {
|
||||
default: assert(0); break;
|
||||
case 0:
|
||||
/* Can happen with zero size structs */
|
||||
break;
|
||||
case 1:
|
||||
arm64_ldrx(0, 0, reg, reg, 0);
|
||||
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)
|
||||
{
|
||||
// Currently TCC's linker does not generate COPY relocations for
|
||||
// STT_OBJECTs when tcc is invoked with "-run". This typically
|
||||
// results in "R_AARCH64_ADR_PREL_PG_HI21 relocation failed" when
|
||||
// a program refers to stdin. A workaround is to avoid that
|
||||
// relocation and use only relocations with unlimited range.
|
||||
int avoid_adrp = 1;
|
||||
|
||||
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);
|
||||
}
|
||||
o(0x10000060 | r); // adr xr,pc+12
|
||||
o(0xf9400000 | r | (r << 5)); // ldr xr,[xr]
|
||||
o(0x14000003); // b + 8
|
||||
greloca(cur_text_section, sym, ind, R_AARCH64_ABS64, addend);
|
||||
o(0);
|
||||
o(0);
|
||||
}
|
||||
|
||||
static void arm64_load_cmp(int r, SValue *sv);
|
||||
@ -474,12 +459,24 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
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))
|
||||
arm64_ldrv(arm64_type_size(svtt), fltr(r), intr(svrv), 0);
|
||||
arm64_ldrv(arm64_type_size(svtt), fltr(r), 30, 0);
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
@ -573,6 +570,15 @@ ST_FUNC void store(int r, SValue *sv)
|
||||
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 (IS_FREG(r))
|
||||
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)
|
||||
{
|
||||
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
|
||||
assert(!b);
|
||||
greloca(cur_text_section, vtop->sym, ind, R_AARCH64_CALL26, 0);
|
||||
o(0x94000000); // bl .
|
||||
greloca(cur_text_section, vtop->sym, ind,
|
||||
b ? R_AARCH64_JUMP26 : R_AARCH64_CALL26, 0);
|
||||
o(0x14000000 | (uint32_t)!b << 31); // b/bl .
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(vtop->sym->v == TOK_setjmp ||
|
||||
@ -684,7 +690,8 @@ static void gen_bounds_prolog(void)
|
||||
func_bound_offset = lbounds_section->data_offset;
|
||||
func_bound_ind = ind;
|
||||
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);
|
||||
@ -712,14 +719,12 @@ static void gen_bounds_epilog(void)
|
||||
if (offset_modified) {
|
||||
saved_ind = ind;
|
||||
ind = func_bound_ind;
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
|
||||
o(0xd2800000); /* mov x0,#0,lsl #0, lbound section pointer */
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
|
||||
o(0xf2a00000); /* movk x0,#0,lsl #16 */
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
|
||||
o(0xf2c00000); /* movk x0,#0,lsl #32 */
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
|
||||
o(0xf2e00000); /* movk x0,#0,lsl #48 */
|
||||
o(0x10000060 | 0); // adr x0,pc+12
|
||||
o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0]
|
||||
o(0x14000003); // b + 8
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0);
|
||||
o(0);
|
||||
o(0);
|
||||
gen_bounds_call(TOK___bound_local_new);
|
||||
ind = saved_ind;
|
||||
}
|
||||
@ -727,14 +732,12 @@ static void gen_bounds_epilog(void)
|
||||
/* generate bound check local freeing */
|
||||
o(0xf81f0fe0); /* str x0, [sp, #-16]! */
|
||||
o(0x3c9f0fe0); /* str q0, [sp, #-16]! */
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G0_NC, 0);
|
||||
o(0xd2800000); // mov x0,#0,lsl #0
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G1_NC, 0);
|
||||
o(0xf2a00000); // movk x0,#0,lsl #16
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G2_NC, 0);
|
||||
o(0xf2c00000); // movk x0,#0,lsl #32
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_MOVW_UABS_G3, 0);
|
||||
o(0xf2e00000); // movk x0,#0,lsl #48
|
||||
o(0x10000060 | 0); // adr x0,pc+12
|
||||
o(0xf9400000 | 0 | (0 << 5)); // ldr x0,[x0]
|
||||
o(0x14000003); // b + 8
|
||||
greloca(cur_text_section, sym_data, ind, R_AARCH64_ABS64, 0);
|
||||
o(0);
|
||||
o(0);
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
o(0x3cc107e0); /* ldr q0, [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;
|
||||
|
||||
assert(stack < 0x1000);
|
||||
if (stack)
|
||||
o(0xd10003ff | stack << 10); // sub sp,sp,#(n)
|
||||
if (stack >= 0x1000000) // 16Mb
|
||||
tcc_error("stack size too big %lu", stack);
|
||||
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
|
||||
for (i = nb_args; i; i--) {
|
||||
@ -1109,8 +1115,10 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
save_regs(0);
|
||||
arm64_gen_bl_or_b(0);
|
||||
--vtop;
|
||||
if (stack)
|
||||
o(0x910003ff | stack << 10); // add sp,sp,#(n)
|
||||
if (stack & 0xfff)
|
||||
o(0x910003ff | (stack & 0xfff) << 10); // add sp,sp,#(n)
|
||||
if (stack >> 12)
|
||||
o(0x914003ff | (stack >> 12) << 10);
|
||||
|
||||
{
|
||||
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);
|
||||
if (rev)
|
||||
return 0;
|
||||
if (!val)
|
||||
assert(0);
|
||||
if (!val) {
|
||||
// tcc_warning("shift count >= width of type");
|
||||
o(0x2a0003e0 | l << 31 | a << 16);
|
||||
return 1;
|
||||
}
|
||||
else if (op == TOK_SHL)
|
||||
o(0x53000000 | l << 31 | l << 22 | x | a << 5 |
|
||||
(n - val) << 16 | (n - 1 - val) << 10); // lsl
|
||||
|
18
libtcc.c
18
libtcc.c
@ -963,6 +963,24 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
tcc_define_symbol(s, "__FINITE_MATH_ONLY__", "1");
|
||||
tcc_define_symbol(s, "_FORTIFY_SOURCE", "0");
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -207,9 +207,10 @@ ST_FUNC void load(int r, SValue *sv)
|
||||
int rr = is_ireg(r) ? ireg(r) : freg(r);
|
||||
int fc = sv->c.i;
|
||||
int bt = sv->type.t & VT_BTYPE;
|
||||
int align, size = type_size(&sv->type, &align);
|
||||
int align, size;
|
||||
if (fr & VT_LVAL) {
|
||||
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);
|
||||
if (bt == VT_FUNC) /* XXX should be done in generic code */
|
||||
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
|
||||
else {
|
||||
int func7 = is_ireg(r) ? 0x70 : 0x78;
|
||||
size = type_size(&sv->type, &align);
|
||||
if (size == 8)
|
||||
func7 |= 1;
|
||||
assert(size == 4 || size == 8);
|
||||
@ -577,7 +579,7 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
{
|
||||
int i, align, size, areg[2];
|
||||
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;
|
||||
Sym *sa;
|
||||
|
||||
@ -644,8 +646,15 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
}
|
||||
stack_adj = (stack_adj + 15) & -16;
|
||||
tempspace = (tempspace + 15) & -16;
|
||||
if (stack_adj + tempspace) {
|
||||
EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj
|
||||
stack_add = stack_adj + tempspace;
|
||||
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++) {
|
||||
if (info[i] & (64 | 32)) {
|
||||
vrotb(nb_args - i);
|
||||
@ -757,8 +766,15 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
save_regs(nb_args + 1);
|
||||
gcall_or_jmp(1);
|
||||
vtop -= nb_args + 1;
|
||||
if (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
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (fc == vtop->c.i && !(((unsigned)fc + (1 << 11)) >> 12)) {
|
||||
int cll = 0;
|
||||
int m = ll ? 31 : 63;
|
||||
vswap();
|
||||
gv(RC_INT);
|
||||
a = ireg(vtop[0].r);
|
||||
@ -1023,6 +1040,7 @@ static void gen_opil(int op, int ll)
|
||||
fc = -fc;
|
||||
case '+':
|
||||
func3 = 0; // addi d, a, fc
|
||||
cll = ll;
|
||||
do_cop:
|
||||
EI(0x13 | cll, func3, ireg(d), a, fc);
|
||||
--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 = 6; goto do_cop; // ori 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_SHR: func3 = 5; cll = ll; fc &= 63; goto do_cop; // srli d, a, fc
|
||||
case TOK_SAR: func3 = 5; cll = ll; fc = 1024 | (fc & 63); goto do_cop;
|
||||
case TOK_SHL: func3 = 1; cll = ll; fc &= m; goto do_cop; // slli 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 & m); goto do_cop;
|
||||
|
||||
case TOK_UGE:
|
||||
case TOK_UGT:
|
||||
case TOK_GE:
|
||||
case TOK_GT:
|
||||
gen_opil(op - 1, ll);
|
||||
case TOK_UGE: /* -> TOK_ULT */
|
||||
case TOK_UGT: /* -> TOK_ULE */
|
||||
case TOK_GE: /* -> TOK_LT */
|
||||
case TOK_GT: /* -> TOK_LE */
|
||||
gen_opil(op - 1, !ll);
|
||||
vtop->cmp_op ^= 1;
|
||||
return;
|
||||
|
||||
case TOK_NE:
|
||||
case TOK_EQ:
|
||||
if (fc)
|
||||
gen_opil('-', ll), a = ireg(vtop++->r);
|
||||
gen_opil('-', !ll), a = ireg(vtop++->r);
|
||||
--vtop;
|
||||
vset_VT_CMP(op);
|
||||
vtop->cmp_r = a | 0 << 8;
|
||||
@ -1087,25 +1105,25 @@ static void gen_opil(int op, int ll)
|
||||
break;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
case '&':
|
||||
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
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
case TOK_PDIV:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
236
tccgen.c
236
tccgen.c
@ -5356,17 +5356,51 @@ static void parse_type(CType *type)
|
||||
static void parse_builtin_params(int nc, const char *args)
|
||||
{
|
||||
char c, sep = '(';
|
||||
CType t;
|
||||
CType type;
|
||||
if (nc)
|
||||
nocode_wanted++;
|
||||
next();
|
||||
if (*args == 0)
|
||||
skip(sep);
|
||||
while ((c = *args++)) {
|
||||
skip(sep);
|
||||
sep = ',';
|
||||
switch (c) {
|
||||
case 'e': expr_eq(); continue;
|
||||
case 't': parse_type(&t); vpush(&t); continue;
|
||||
default: tcc_error("internal error"); break;
|
||||
case 'e': expr_eq();
|
||||
continue;
|
||||
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(')');
|
||||
@ -5746,6 +5780,197 @@ ST_FUNC void unary(void)
|
||||
break;
|
||||
}
|
||||
#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 */
|
||||
case TOK_INC:
|
||||
case TOK_DEC:
|
||||
@ -7678,6 +7903,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||
if (n >= 0 && len > n)
|
||||
nb = n;
|
||||
if (!(flags & DIF_SIZE_ONLY)) {
|
||||
if (sec && !NODATA_WANTED &&
|
||||
(c + nb > sec->data_allocated))
|
||||
nb = sec->data_allocated - c;
|
||||
if (len > nb)
|
||||
tcc_warning("initializer-string for array is too long");
|
||||
/* in order to go faster for common case (char
|
||||
|
@ -820,7 +820,6 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
||||
|
||||
macho_write(s1, &mo, fp);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
do_ret:
|
||||
for (i = 0; i < mo.nlc; i++)
|
||||
|
52
tcctok.h
52
tcctok.h
@ -314,11 +314,7 @@
|
||||
# ifdef TCC_TARGET_X86_64
|
||||
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
|
||||
# endif
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
DEF(TOK_realloc, "realloc")
|
||||
DEF(TOK_memalign, "memalign")
|
||||
DEF(TOK_calloc, "calloc")
|
||||
# else
|
||||
DEF(TOK_sigsetjmp, "sigsetjmp")
|
||||
DEF(TOK___sigsetjmp, "__sigsetjmp")
|
||||
@ -326,6 +322,27 @@
|
||||
# endif
|
||||
DEF(TOK_mmap, "mmap")
|
||||
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_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
@ -335,9 +352,30 @@
|
||||
DEF(TOK_strcat, "strcat")
|
||||
DEF(TOK_strchr, "strchr")
|
||||
DEF(TOK_strdup, "strdup")
|
||||
DEF(TOK_setjmp, "setjmp")
|
||||
DEF(TOK__setjmp, "_setjmp")
|
||||
DEF(TOK_longjmp, "longjmp")
|
||||
DEF(TOK_malloc, "malloc")
|
||||
DEF(TOK_free, "free")
|
||||
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
|
||||
|
||||
/* Tiny Assembler */
|
||||
|
75
tests/bug.c
Normal file
75
tests/bug.c
Normal 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();
|
||||
}
|
@ -1,33 +1,48 @@
|
||||
#!/bin/sh
|
||||
|
||||
TESTSUITE_PATH=$HOME/gcc/gcc-3.2/gcc/testsuite/gcc.c-torture
|
||||
TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
|
||||
rm -f tcc.sum tcc.log
|
||||
TCC="./tcc -B. -I. -DNO_TRAMPOLINES"
|
||||
rm -f tcc.sum tcc.fail
|
||||
nb_ok="0"
|
||||
nb_failed="0"
|
||||
nb_exe_failed="0"
|
||||
|
||||
for src in $TESTSUITE_PATH/compile/*.c ; do
|
||||
echo $TCC -o /tmp/test.o -c $src
|
||||
$TCC -o /tmp/test.o -c $src >> tcc.log 2>&1
|
||||
echo $TCC -o /tmp/tst.o -c $src
|
||||
$TCC -o /tmp/tst.o -c $src >> tcc.fail 2>&1
|
||||
if [ "$?" = "0" ] ; then
|
||||
result="PASS"
|
||||
result="PASS"
|
||||
nb_ok=$(( $nb_ok + 1 ))
|
||||
else
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
done
|
||||
|
||||
for src in $TESTSUITE_PATH/execute/*.c ; do
|
||||
echo $TCC $src
|
||||
$TCC $src >> tcc.log 2>&1
|
||||
echo $TCC $src -o /tmp/tst -lm
|
||||
$TCC $src -o /tmp/tst -lm >> tcc.fail 2>&1
|
||||
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
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
result="FAIL"
|
||||
nb_failed=$(( $nb_failed + 1 ))
|
||||
fi
|
||||
echo "$result: $src" >> tcc.sum
|
||||
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."
|
||||
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
134
tests/tests2/117_gcc_test.c
Normal 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();
|
||||
}
|
0
tests/tests2/117_gcc_test.expect
Normal file
0
tests/tests2/117_gcc_test.expect
Normal 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
|
||||
|
@ -159,3 +159,6 @@ bar : 3 ; 3
|
||||
|
||||
[test_stray_backslash2]
|
||||
\n
|
||||
|
||||
[test_var_array]
|
||||
60_errors_and_warnings.c:345: warning: initializer-string for array is too long
|
||||
|
@ -441,6 +441,9 @@ void load(int r, SValue *sv)
|
||||
b = 0xbf0f; /* movswl */
|
||||
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
|
||||
b = 0xb70f; /* movzwl */
|
||||
} else if ((ft & VT_TYPE) == (VT_VOID)) {
|
||||
/* Can happen with zero size structs */
|
||||
return;
|
||||
} else {
|
||||
assert(((ft & VT_BTYPE) == VT_INT)
|
||||
|| ((ft & VT_BTYPE) == VT_LLONG)
|
||||
|
Loading…
Reference in New Issue
Block a user