mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-25 06:00:11 +08:00
__builtin_/__bound_: A 'stay tiny' approach to the matter
tccgen.c: - cleanup __builtin_... stuff - merge __attribute((alias("sym"))) with __asm__("sym") Now one cannot have both, however for alias underscores are added if enabled. For __asm__ they aren't. tccpp.c: - extend tcc_predefs accordingly. Was generated with 'cd tests/misc && tcc -run c2str.c tcc_predef.h tcc_predefs' xxx-gen.c: - move bcheck setjmp test to tccgen.c:gbound_args() i386-gen.c: - create win32 compatible stack space for big structures tcctest.c: - some cleanup + nicer output
This commit is contained in:
parent
6a4f3cf127
commit
2a0167adfe
10
arm-gen.c
10
arm-gen.c
@ -161,7 +161,7 @@ static int leaffunc;
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
static int func_bound_add_epilog;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
#endif
|
||||
|
||||
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
|
||||
@ -763,14 +763,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);
|
||||
o(vtop->c.i);
|
||||
}
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(vtop->sym->v == TOK_setjmp ||
|
||||
vtop->sym->v == TOK__setjmp ||
|
||||
vtop->sym->v == TOK_sigsetjmp ||
|
||||
vtop->sym->v == TOK___sigsetjmp))
|
||||
func_bound_add_epilog = 1;
|
||||
#endif
|
||||
}else{
|
||||
if(!is_jmp)
|
||||
o(0xE28FE004); // add lr,pc,#4
|
||||
|
10
arm64-gen.c
10
arm64-gen.c
@ -84,7 +84,7 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
static int func_bound_add_epilog;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
#endif
|
||||
|
||||
#define IS_FREG(x) ((x) >= TREG_F(0))
|
||||
@ -606,14 +606,6 @@ static void arm64_gen_bl_or_b(int b)
|
||||
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 ||
|
||||
vtop->sym->v == TOK__setjmp ||
|
||||
vtop->sym->v == TOK_sigsetjmp ||
|
||||
vtop->sym->v == TOK___sigsetjmp))
|
||||
func_bound_add_epilog = 1;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
|
@ -1202,7 +1202,7 @@ ST_FUNC int asm_parse_regvar (int t)
|
||||
{
|
||||
const char *s;
|
||||
Operand op;
|
||||
if (t < TOK_IDENT)
|
||||
if (t < TOK_IDENT || (t & SYM_FIELD))
|
||||
return -1;
|
||||
s = table_ident[t - TOK_IDENT]->str;
|
||||
if (s[0] != '%')
|
||||
|
24
i386-gen.c
24
i386-gen.c
@ -97,7 +97,7 @@ static int func_ret_sub;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
static int func_bound_add_epilog;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
static void gen_bounds_prolog(void);
|
||||
static void gen_bounds_epilog(void);
|
||||
#endif
|
||||
@ -359,18 +359,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
/* constant and relocation case */
|
||||
greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
|
||||
oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(vtop->sym->v == TOK_alloca ||
|
||||
vtop->sym->v == TOK_setjmp ||
|
||||
vtop->sym->v == TOK__setjmp
|
||||
#ifndef TCC_TARGET_PE
|
||||
|| vtop->sym->v == TOK_sigsetjmp
|
||||
|| vtop->sym->v == TOK___sigsetjmp
|
||||
#endif
|
||||
))
|
||||
func_bound_add_epilog = 1;
|
||||
#endif
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
r = gv(RC_INT);
|
||||
@ -429,6 +417,16 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
/* align to stack align size */
|
||||
size = (size + 3) & ~3;
|
||||
/* allocate the necessary size on stack */
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (size >= 0x4096) {
|
||||
o(0x5250);
|
||||
oad(0x68, size);
|
||||
vpush_global_sym(&func_old_type, TOK_alloca);
|
||||
gcall_or_jmp(0);
|
||||
vtop--;
|
||||
o(0x58585a);
|
||||
} else
|
||||
#endif
|
||||
oad(0xec81, size); /* sub $xxx, %esp */
|
||||
/* generate structure store */
|
||||
r = get_reg(RC_INT);
|
||||
|
15
libtcc.c
15
libtcc.c
@ -967,14 +967,13 @@ LIBTCCAPI TCCState *tcc_new(void)
|
||||
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");
|
||||
}
|
||||
#if LONG_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");
|
||||
#endif
|
||||
tcc_define_symbol(s, "__SIZEOF_INT__", "4");
|
||||
tcc_define_symbol(s, "__SIZEOF_LONG_LONG__", "8");
|
||||
tcc_define_symbol(s, "__CHAR_BIT__", "8");
|
||||
|
@ -66,7 +66,7 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
static int func_bound_add_epilog;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
#endif
|
||||
|
||||
static int ireg(int r)
|
||||
@ -387,14 +387,6 @@ static void gcall_or_jmp(int docall)
|
||||
R_RISCV_CALL_PLT, (int)vtop->c.i);
|
||||
o(0x17 | (tr << 7)); // auipc TR, 0 %call(func)
|
||||
EI(0x67, 0, tr, tr, 0);// jalr TR, r(TR)
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(vtop->sym->v == TOK_setjmp ||
|
||||
vtop->sym->v == TOK__setjmp ||
|
||||
vtop->sym->v == TOK_sigsetjmp ||
|
||||
vtop->sym->v == TOK___sigsetjmp))
|
||||
func_bound_add_epilog = 1;
|
||||
#endif
|
||||
} else if (vtop->r < VT_CONST) {
|
||||
int r = ireg(vtop->r);
|
||||
EI(0x67, 0, tr, r, 0); // jalr TR, 0(R)
|
||||
|
2
tcc.h
2
tcc.h
@ -643,7 +643,6 @@ typedef struct AttributeDef {
|
||||
struct FuncAttr f;
|
||||
struct Section *section;
|
||||
Sym *cleanup_func;
|
||||
int alias_target; /* token */
|
||||
int asm_label; /* associated asm label */
|
||||
char attr_mode; /* __attribute__((__mode__(...))) */
|
||||
} AttributeDef;
|
||||
@ -1475,6 +1474,7 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
ST_FUNC void gbound_args(int nb_args);
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
#endif
|
||||
|
||||
/* ------------ tccelf.c ------------ */
|
||||
|
388
tccgen.c
388
tccgen.c
@ -80,7 +80,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
|
||||
ST_DATA int func_vc;
|
||||
static int last_line_num, new_file, func_ind; /* debug info control */
|
||||
ST_DATA const char *funcname;
|
||||
ST_DATA CType int_type, func_old_type, char_pointer_type;
|
||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
|
||||
static CString initstr;
|
||||
|
||||
#if PTR_SIZE == 4
|
||||
@ -771,8 +771,13 @@ ST_FUNC void tccgen_init(TCCState *s1)
|
||||
|
||||
/* define some often used types */
|
||||
int_type.t = VT_INT;
|
||||
char_pointer_type.t = VT_BYTE;
|
||||
|
||||
char_type.t = VT_BYTE;
|
||||
if (s1->char_is_unsigned)
|
||||
char_type.t |= VT_UNSIGNED;
|
||||
char_pointer_type = char_type;
|
||||
mk_pointer(&char_pointer_type);
|
||||
|
||||
func_old_type.t = VT_FUNC;
|
||||
func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
|
||||
func_old_type.ref->f.func_call = FUNC_CDECL;
|
||||
@ -886,66 +891,9 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||
ElfSym *esym;
|
||||
const char *name;
|
||||
char buf1[256];
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
char buf[32];
|
||||
#endif
|
||||
|
||||
if (!sym->c) {
|
||||
name = get_tok_str(sym->v, NULL);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check) {
|
||||
/* XXX: avoid doing that for statics ? */
|
||||
/* if bound checking is activated, we change some function
|
||||
names by adding the "__bound" prefix */
|
||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
|
||||
if (strcmp (name, "memcpy") == 0 ||
|
||||
strcmp (name, "memmove") == 0 ||
|
||||
strcmp (name, "memset") == 0)
|
||||
goto add_bound;
|
||||
#endif
|
||||
switch(sym->v) {
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* XXX: we rely only on malloc hooks */
|
||||
case TOK_malloc:
|
||||
case TOK_free:
|
||||
case TOK_realloc:
|
||||
case TOK_memalign:
|
||||
case TOK_calloc:
|
||||
#endif
|
||||
case TOK_memcpy:
|
||||
case TOK_memmove:
|
||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
|
||||
case TOK_memmove4:
|
||||
case TOK_memmove8:
|
||||
#endif
|
||||
case TOK_memset:
|
||||
case TOK_memcmp:
|
||||
case TOK_strlen:
|
||||
case TOK_strcpy:
|
||||
case TOK_strncpy:
|
||||
case TOK_strcmp:
|
||||
case TOK_strncmp:
|
||||
case TOK_strcat:
|
||||
case TOK_strchr:
|
||||
case TOK_strdup:
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
case TOK_alloca:
|
||||
#endif
|
||||
case TOK_mmap:
|
||||
case TOK_munmap:
|
||||
case TOK_longjmp:
|
||||
#ifndef TCC_TARGET_PE
|
||||
case TOK_siglongjmp:
|
||||
#endif
|
||||
#if defined(TCC_TARGET_ARM) && defined(TCC_ARM_EABI)
|
||||
add_bound:
|
||||
#endif
|
||||
strcpy(buf, "__bound_");
|
||||
strcat(buf, name);
|
||||
name = buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
t = sym->type.t;
|
||||
if ((t & VT_BTYPE) == VT_FUNC) {
|
||||
sym_type = STT_FUNC;
|
||||
@ -959,6 +907,7 @@ add_bound:
|
||||
else
|
||||
sym_bind = STB_GLOBAL;
|
||||
other = 0;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (sym_type == STT_FUNC && sym->type.ref) {
|
||||
Sym *ref = sym->type.ref;
|
||||
@ -973,13 +922,20 @@ add_bound:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sym->asm_label) {
|
||||
name = get_tok_str(sym->asm_label & ~SYM_FIELD, NULL);
|
||||
/* with SYM_FIELD it was __attribute__((alias("..."))) actually */
|
||||
if (!(sym->asm_label & SYM_FIELD))
|
||||
can_add_underscore = 0;
|
||||
}
|
||||
|
||||
if (tcc_state->leading_underscore && can_add_underscore) {
|
||||
buf1[0] = '_';
|
||||
pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
|
||||
name = buf1;
|
||||
}
|
||||
if (sym->asm_label)
|
||||
name = get_tok_str(sym->asm_label, NULL);
|
||||
|
||||
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
||||
|
||||
@ -1553,8 +1509,6 @@ static void merge_attr(AttributeDef *ad, AttributeDef *ad1)
|
||||
|
||||
if (ad1->section)
|
||||
ad->section = ad1->section;
|
||||
if (ad1->alias_target)
|
||||
ad->alias_target = ad1->alias_target;
|
||||
if (ad1->asm_label)
|
||||
ad->asm_label = ad1->asm_label;
|
||||
if (ad1->attr_mode)
|
||||
@ -1940,13 +1894,34 @@ static void gbound(void)
|
||||
args into registers */
|
||||
ST_FUNC void gbound_args(int nb_args)
|
||||
{
|
||||
int i;
|
||||
int i, v;
|
||||
SValue *sv;
|
||||
|
||||
for (i = 1; i <= nb_args; ++i)
|
||||
if (vtop[1 - i].r & VT_MUSTBOUND) {
|
||||
vrotb(i);
|
||||
gbound();
|
||||
vrott(i);
|
||||
}
|
||||
|
||||
sv = vtop - nb_args;
|
||||
if (sv->r & VT_SYM) {
|
||||
v = sv->sym->v;
|
||||
if (v == TOK_setjmp
|
||||
|| v == TOK__setjmp
|
||||
#ifndef TCC_TARGET_PE
|
||||
|| v == TOK_sigsetjmp
|
||||
|| v == TOK___sigsetjmp
|
||||
#endif
|
||||
) {
|
||||
vpush_global_sym(&func_old_type, TOK___bound_setjmp);
|
||||
vpushv(sv + 1);
|
||||
gfunc_call(1);
|
||||
func_bound_add_epilog = 1;
|
||||
}
|
||||
if (v == TOK_alloca)
|
||||
func_bound_add_epilog = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add bounds for local symbols from S to E (via ->prev) */
|
||||
@ -4099,8 +4074,8 @@ redo:
|
||||
case TOK_ALIAS2:
|
||||
skip('(');
|
||||
parse_mult_str(&astr, "alias(\"target\")");
|
||||
ad->alias_target = /* save string as token, for later */
|
||||
tok_alloc((char*)astr.data, astr.size-1)->tok;
|
||||
ad->asm_label = /* save string as token, for later */
|
||||
tok_alloc((char*)astr.data, astr.size-1)->tok | SYM_FIELD;
|
||||
skip(')');
|
||||
cstr_free(&astr);
|
||||
break;
|
||||
@ -5365,43 +5340,39 @@ static void parse_builtin_params(int nc, const char *args)
|
||||
while ((c = *args++)) {
|
||||
skip(sep);
|
||||
sep = ',';
|
||||
if (c == 't') {
|
||||
parse_type(&type);
|
||||
vpush(&type);
|
||||
continue;
|
||||
}
|
||||
expr_eq();
|
||||
type.ref = NULL;
|
||||
type.t = 0;
|
||||
switch (c) {
|
||||
case 'e': expr_eq();
|
||||
continue;
|
||||
case 't': parse_type(&type);
|
||||
vpush(&type);
|
||||
continue;
|
||||
case 'e':
|
||||
continue;
|
||||
case 'V':
|
||||
type.t = VT_CONSTANT;
|
||||
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;
|
||||
type.t |= VT_VOID;
|
||||
mk_pointer (&type);
|
||||
break;
|
||||
case 'S':
|
||||
type.t = VT_CONSTANT;
|
||||
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;
|
||||
type.t |= char_type.t;
|
||||
mk_pointer (&type);
|
||||
break;
|
||||
case 'i':
|
||||
type.t = VT_INT;
|
||||
break;
|
||||
case 'l':
|
||||
type.t = VT_SIZE_T;
|
||||
break;
|
||||
default:
|
||||
tcc_error("internal error");
|
||||
}
|
||||
gen_assign_cast(&type);
|
||||
}
|
||||
skip(')');
|
||||
if (nc)
|
||||
@ -5780,196 +5751,6 @@ 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:
|
||||
@ -6276,24 +6057,6 @@ special_math_val:
|
||||
if (sa)
|
||||
tcc_error("too few arguments to function");
|
||||
skip(')');
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(nb_args == 1 || nb_args == 2) &&
|
||||
(vtop[-nb_args].r & VT_SYM) &&
|
||||
(vtop[-nb_args].sym->v == TOK_setjmp ||
|
||||
vtop[-nb_args].sym->v == TOK__setjmp
|
||||
#ifndef TCC_TARGET_PE
|
||||
|| vtop[-nb_args].sym->v == TOK_sigsetjmp
|
||||
|| vtop[-nb_args].sym->v == TOK___sigsetjmp
|
||||
#endif
|
||||
)) {
|
||||
vpush_global_sym(&func_old_type, TOK___bound_setjmp);
|
||||
vpushv(vtop - nb_args);
|
||||
if (nb_args == 2)
|
||||
vpushv(vtop - nb_args);
|
||||
gfunc_call(nb_args);
|
||||
}
|
||||
#endif
|
||||
gfunc_call(nb_args);
|
||||
|
||||
if (ret_nregs < 0) {
|
||||
@ -8602,15 +8365,6 @@ found:
|
||||
/* external variable or function */
|
||||
type.t |= VT_EXTERN;
|
||||
sym = external_sym(v, &type, r, &ad);
|
||||
if (ad.alias_target) {
|
||||
ElfSym *esym;
|
||||
Sym *alias_target;
|
||||
alias_target = sym_find(ad.alias_target);
|
||||
esym = elfsym(alias_target);
|
||||
if (!esym)
|
||||
tcc_error("unsupported forward __alias__ attribute");
|
||||
put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0);
|
||||
}
|
||||
} else {
|
||||
if (type.t & VT_STATIC)
|
||||
r |= VT_CONST;
|
||||
|
59
tccpp.c
59
tccpp.c
@ -3625,10 +3625,13 @@ ST_INLN void unget_tok(int last_tok)
|
||||
static void tcc_predefs(CString *cstr)
|
||||
{
|
||||
cstr_cat(cstr,
|
||||
|
||||
//"#include <tcc_predefs.h>\n"
|
||||
|
||||
#if defined TCC_TARGET_X86_64
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* GCC compatible definition of va_list. This should be in sync
|
||||
with the declaration in our lib/libtcc1.c */
|
||||
/* GCC compatible definition of va_list. */
|
||||
/* This should be in sync with the declaration in our lib/libtcc1.c */
|
||||
"typedef struct{\n"
|
||||
"unsigned gp_offset,fp_offset;\n"
|
||||
"union{\n"
|
||||
@ -3644,7 +3647,6 @@ static void tcc_predefs(CString *cstr)
|
||||
#else /* TCC_TARGET_PE */
|
||||
"typedef char*__builtin_va_list;\n"
|
||||
"#define __builtin_va_arg(ap,t) ((sizeof(t)>8||(sizeof(t)&(sizeof(t)-1)))?**(t**)((ap+=8)-8):*(t*)((ap+=8)-8))\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
#endif
|
||||
#elif defined TCC_TARGET_ARM
|
||||
"typedef char*__builtin_va_list;\n"
|
||||
@ -3652,26 +3654,69 @@ static void tcc_predefs(CString *cstr)
|
||||
"#define _tcc_align(addr,type) (((unsigned)addr+_tcc_alignof(type)-1)&~(_tcc_alignof(type)-1))\n"
|
||||
"#define __builtin_va_start(ap,last) (ap=((char*)&(last))+((sizeof(last)+3)&~3))\n"
|
||||
"#define __builtin_va_arg(ap,type) (ap=(void*)((_tcc_align(ap,type)+sizeof(type)+3)&~3),*(type*)(ap-((sizeof(type)+3)&~3)))\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
#elif defined TCC_TARGET_ARM64
|
||||
"typedef struct{\n"
|
||||
"void*__stack,*__gr_top,*__vr_top;\n"
|
||||
"int __gr_offs,__vr_offs;\n"
|
||||
"}__builtin_va_list;\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
#elif defined TCC_TARGET_RISCV64
|
||||
"typedef char*__builtin_va_list;\n"
|
||||
"#define __va_reg_size (__riscv_xlen>>3)\n"
|
||||
"#define _tcc_align(addr,type) (((unsigned long)addr+__alignof__(type)-1)&-(__alignof__(type)))\n"
|
||||
"#define __builtin_va_arg(ap,type) (*(sizeof(type)>(2*__va_reg_size)?*(type**)((ap+=__va_reg_size)-__va_reg_size):(ap=(va_list)(_tcc_align(ap,type)+(sizeof(type)+__va_reg_size-1)&-__va_reg_size),(type*)(ap-((sizeof(type)+__va_reg_size-1)&-__va_reg_size)))))\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
#else /* TCC_TARGET_I386 */
|
||||
"typedef char*__builtin_va_list;\n"
|
||||
"#define __builtin_va_start(ap,last) (ap=((char*)&(last))+((sizeof(last)+3)&~3))\n"
|
||||
"#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
#endif
|
||||
"#define __builtin_va_end(ap) (void)(ap)\n"
|
||||
"#ifndef __builtin_va_copy\n"
|
||||
"#define __builtin_va_copy(dest,src) (dest)=(src)\n"
|
||||
"#endif\n"
|
||||
/* TCC BBUILTIN AND BOUNDS ALIASES */
|
||||
"#ifdef __BOUNDS_CHECKING_ON\n"
|
||||
"#define __BUILTIN(ret,name,params) ret __builtin_##name params __attribute__((alias(\"__bound_\"#name)));\n"
|
||||
"#define __BOUND(ret,name,params) ret name params __attribute__((alias(\"__bound_\"#name)));\n"
|
||||
"#else\n"
|
||||
"#define __BUILTIN(ret,name,params) ret __builtin_##name params __attribute__((alias(#name)));\n"
|
||||
"#define __BOUND(ret,name,params)\n"
|
||||
"#endif\n"
|
||||
"#define __BOTH(ret,name,params) __BUILTIN(ret,name,params)__BOUND(ret,name,params)\n"
|
||||
"__BOTH(void*,memcpy,(void*,const void*,__SIZE_TYPE__))\n"
|
||||
"__BOTH(void*,memmove,(void*,const void*,__SIZE_TYPE__))\n"
|
||||
"__BOTH(void*,memset,(void*,int,__SIZE_TYPE__))\n"
|
||||
"__BOTH(int,memcmp,(const void*,const void*,__SIZE_TYPE__))\n"
|
||||
"__BOTH(__SIZE_TYPE__,strlen,(const char*))\n"
|
||||
"__BOTH(char*,strcpy,(char*,const char*))\n"
|
||||
"__BOTH(char*,strncpy,(char*,const char*,__SIZE_TYPE__))\n"
|
||||
"__BOTH(int,strcmp,(const char*,const char*))\n"
|
||||
"__BOTH(int,strncmp,(const char*,const char*,__SIZE_TYPE__))\n"
|
||||
"__BOTH(char*,strcat,(char*,const char*))\n"
|
||||
"__BOTH(char*,strchr,(const char*,int))\n"
|
||||
"__BOTH(char*,strdup,(const char*))\n"
|
||||
#ifdef TCC_TARGET_PE
|
||||
"#define __MAYBE_REDIR __BOTH\n"
|
||||
#else // HAVE MALLOC_REDIR
|
||||
"#define __MAYBE_REDIR __BUILTIN\n"
|
||||
#endif
|
||||
"__MAYBE_REDIR(void*,malloc,(__SIZE_TYPE__))\n"
|
||||
"__MAYBE_REDIR(void*,realloc,(void*,__SIZE_TYPE__))\n"
|
||||
"__MAYBE_REDIR(void*,calloc,(__SIZE_TYPE__,__SIZE_TYPE__))\n"
|
||||
"__MAYBE_REDIR(void*,memalign,(__SIZE_TYPE__,__SIZE_TYPE__))\n"
|
||||
"__MAYBE_REDIR(void,free,(void*))\n"
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
"__BOTH(void*,alloca,(__SIZE_TYPE__))\n"
|
||||
#endif
|
||||
"__BUILTIN(void,abort,(void))\n"
|
||||
"__BOUND(int,longjmp,())\n"
|
||||
#ifndef TCC_TARGET_PE
|
||||
"__BOUND(void*,mmap,())\n"
|
||||
"__BOUND(void*,munmap,())\n"
|
||||
#endif
|
||||
"#undef __BUILTIN\n"
|
||||
"#undef __BOUND\n"
|
||||
"#undef __BOTH\n"
|
||||
"#undef __MAYBE_REDIR\n"
|
||||
, -1);
|
||||
}
|
||||
|
||||
|
55
tcctok.h
55
tcctok.h
@ -314,68 +314,13 @@
|
||||
# ifdef TCC_TARGET_X86_64
|
||||
DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
|
||||
# endif
|
||||
DEF(TOK_memalign, "memalign")
|
||||
# else
|
||||
DEF(TOK_sigsetjmp, "sigsetjmp")
|
||||
DEF(TOK___sigsetjmp, "__sigsetjmp")
|
||||
DEF(TOK_siglongjmp, "siglongjmp")
|
||||
# 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")
|
||||
DEF(TOK_strncpy, "strncpy")
|
||||
DEF(TOK_strcmp, "strcmp")
|
||||
DEF(TOK_strncmp, "strncmp")
|
||||
DEF(TOK_strcat, "strcat")
|
||||
DEF(TOK_strchr, "strchr")
|
||||
DEF(TOK_strdup, "strdup")
|
||||
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 */
|
||||
|
112
tests/misc/c2str.c
Normal file
112
tests/misc/c2str.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int isid(int c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z')
|
||||
|| (c >= 'A' && c <= 'Z')
|
||||
|| (c >= '0' && c <= '9')
|
||||
|| c == '_';
|
||||
}
|
||||
|
||||
int isspc(int c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char l[1000], *p, l2[1000], *q;
|
||||
FILE *fp, *op;
|
||||
int c, e, f;
|
||||
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
|
||||
fp = fopen(argv[1], "rb");
|
||||
op = fopen(argv[2], "wb");
|
||||
if (!fp || !op) {
|
||||
fprintf(stderr, "c2str: file error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
p = l;
|
||||
append:
|
||||
if (fgets(p, sizeof l - (p - l), fp)) {
|
||||
p = strchr(p, 0);
|
||||
while (p > l && p[-1] == '\n')
|
||||
--p;
|
||||
*p = 0;
|
||||
} else if (p == l)
|
||||
break;
|
||||
if (p > l && p[-1] == '\\') {
|
||||
--p;
|
||||
goto append;
|
||||
}
|
||||
|
||||
if (l[0] == 0)
|
||||
continue;
|
||||
p = l, q = l2, f = e = 0;
|
||||
while (*p && isspc(*p))
|
||||
++p, ++f;
|
||||
|
||||
if (f < 4) {
|
||||
do {
|
||||
static const char *sr[] = {
|
||||
"__x86_64__", "TCC_TARGET_X86_64",
|
||||
"_WIN64", "TCC_TARGET_PE",
|
||||
"_WIN32", "TCC_TARGET_PE",
|
||||
"__arm__", "TCC_TARGET_ARM",
|
||||
"__aarch64__", "TCC_TARGET_ARM64",
|
||||
"__riscv", "TCC_TARGET_RISCV64",
|
||||
"__i386__", "TCC_TARGET_I386", 0 };
|
||||
for (f = 0; sr[f]; f += 2) {
|
||||
c = strlen(sr[f]);
|
||||
if (0 == memcmp(p, sr[f], c)) {
|
||||
p += c, ++f;
|
||||
q = strchr(strcpy(q, sr[f]), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (sr[f])
|
||||
continue;
|
||||
} while (!!(*q++ = *p++));
|
||||
|
||||
fprintf(op, "%s\n", l2);
|
||||
|
||||
} else if (*p == '/') {
|
||||
strcpy(q, p);
|
||||
fprintf(op, " %s\n", l2);
|
||||
|
||||
} else {
|
||||
f = 0;
|
||||
for (;;) {
|
||||
c = *p++;
|
||||
if (isspc(c)) {
|
||||
if (q == l2 || isspc(q[-1]))
|
||||
continue;
|
||||
if ((f > 2 || e) || (q[-1] != ')' && *p != '(')) {
|
||||
if (!isid(q[-1]) || !isid(*p))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (c == '(')
|
||||
++e, ++f;
|
||||
if (c == ')')
|
||||
--e, ++f;
|
||||
if (c == '\\' || c == '\"')
|
||||
*q++ = '\\';
|
||||
*q++ = c;
|
||||
if (c == 0)
|
||||
break;
|
||||
}
|
||||
fprintf(op, " \"%s\\n\"\n", l2);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(op);
|
||||
return 0;
|
||||
}
|
111
tests/misc/tcc_predefs.h
Normal file
111
tests/misc/tcc_predefs.h
Normal file
@ -0,0 +1,111 @@
|
||||
#if defined __x86_64__
|
||||
#ifndef _WIN64
|
||||
/* GCC compatible definition of va_list. */
|
||||
/* This should be in sync with the declaration in our lib/libtcc1.c */
|
||||
typedef struct {
|
||||
unsigned gp_offset, fp_offset;
|
||||
union {
|
||||
unsigned overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __builtin_va_list[1];
|
||||
|
||||
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
|
||||
#define __builtin_va_start(ap, last) \
|
||||
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
|
||||
#define __builtin_va_arg(ap, t) \
|
||||
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
|
||||
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
||||
#endif
|
||||
|
||||
#elif defined __arm__
|
||||
typedef char *__builtin_va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
|
||||
#elif defined __aarch64__
|
||||
typedef struct {
|
||||
void *__stack, *__gr_top, *__vr_top;
|
||||
int __gr_offs, __vr_offs;
|
||||
} __builtin_va_list;
|
||||
|
||||
#elif defined __riscv
|
||||
typedef char *__builtin_va_list;
|
||||
#define __va_reg_size (__riscv_xlen >> 3)
|
||||
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
||||
& -(__alignof__(type)))
|
||||
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
|
||||
|
||||
#endif
|
||||
#define __builtin_va_end(ap) (void)(ap)
|
||||
#ifndef __builtin_va_copy
|
||||
# define __builtin_va_copy(dest, src) (dest) = (src)
|
||||
#endif
|
||||
|
||||
|
||||
/* TCC BBUILTIN AND BOUNDS ALIASES */
|
||||
#ifdef __BOUNDS_CHECKING_ON
|
||||
# define __BUILTIN(ret,name,params) \
|
||||
ret __builtin_##name params __attribute__((alias("__bound_" #name)));
|
||||
# define __BOUND(ret,name,params) \
|
||||
ret name params __attribute__((alias("__bound_" #name)));
|
||||
#else
|
||||
# define __BUILTIN(ret,name,params) \
|
||||
ret __builtin_##name params __attribute__((alias(#name)));
|
||||
# define __BOUND(ret,name,params)
|
||||
#endif
|
||||
# define __BOTH(ret,name,params) \
|
||||
__BUILTIN(ret,name,params) __BOUND(ret,name,params)
|
||||
|
||||
__BOTH(void*, memcpy, (void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(void*, memmove, (void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(void*, memset, (void *, int, __SIZE_TYPE__))
|
||||
__BOTH(int, memcmp, (const void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(__SIZE_TYPE__, strlen, (const char *))
|
||||
__BOTH(char*, strcpy, (char *, const char *))
|
||||
__BOTH(char*, strncpy, (char *, const char*, __SIZE_TYPE__))
|
||||
__BOTH(int, strcmp, (const char*, const char*))
|
||||
__BOTH(int, strncmp, (const char*, const char*, __SIZE_TYPE__))
|
||||
__BOTH(char*, strcat, (char*, const char*))
|
||||
__BOTH(char*, strchr, (const char*, int))
|
||||
__BOTH(char*, strdup, (const char*))
|
||||
|
||||
#ifdef _WIN32
|
||||
#define __MAYBE_REDIR __BOTH
|
||||
#else // HAVE MALLOC_REDIR
|
||||
#define __MAYBE_REDIR __BUILTIN
|
||||
#endif
|
||||
__MAYBE_REDIR(void*, malloc, (__SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, realloc, (void *, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void, free, (void*))
|
||||
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
__BOTH(void*, alloca, (__SIZE_TYPE__))
|
||||
#endif
|
||||
__BUILTIN(void, abort, (void))
|
||||
__BOUND(int, longjmp, ())
|
||||
#ifndef _WIN32
|
||||
__BOUND(void*, mmap, ())
|
||||
__BOUND(void*, munmap, ())
|
||||
#endif
|
||||
#undef __BUILTIN
|
||||
#undef __BOUND
|
||||
#undef __BOTH
|
||||
#undef __MAYBE_REDIR
|
422
tests/tcctest.c
422
tests/tcctest.c
@ -2,10 +2,11 @@
|
||||
* TCC auto test program
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
/* identify the configured reference compiler in use */
|
||||
#define CC_gcc 1
|
||||
#define CC_clang 2
|
||||
#define CC_tcc 3
|
||||
#define CC_msvc 4 /* cannot compile this file */
|
||||
|
||||
/* Unfortunately, gcc version < 3 does not handle that! */
|
||||
#define ALL_ISOC99
|
||||
@ -13,15 +14,9 @@
|
||||
/* only gcc 3 handles _Bool correctly */
|
||||
#define BOOL_ISOC99
|
||||
|
||||
/* gcc 2.95.3 does not handle correctly CR in strings or after strays */
|
||||
#define CORRECT_CR_HANDLING
|
||||
|
||||
/* __VA_ARGS__ and __func__ support */
|
||||
#define C99_MACROS
|
||||
|
||||
/* deprecated and no longer supported in gcc 3.3 */
|
||||
//#define ACCEPT_CR_IN_STRINGS
|
||||
|
||||
#ifndef __TINYC__
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
#endif
|
||||
@ -81,61 +76,6 @@ typedef __SIZE_TYPE__ uintptr_t;
|
||||
#include incname
|
||||
#include stringify(funnyname)
|
||||
|
||||
void intdiv_test();
|
||||
void string_test();
|
||||
void expr_test();
|
||||
void macro_test();
|
||||
void recursive_macro_test();
|
||||
void scope_test();
|
||||
void scope_test2();
|
||||
void forward_test();
|
||||
void funcptr_test();
|
||||
void if_test();
|
||||
void loop_test();
|
||||
void switch_test();
|
||||
void goto_test();
|
||||
void enum_test();
|
||||
void typedef_test();
|
||||
void struct_test();
|
||||
void array_test();
|
||||
void expr_ptr_test();
|
||||
void bool_test();
|
||||
void optimize_out();
|
||||
void expr2_test();
|
||||
void constant_expr_test();
|
||||
void expr_cmp_test();
|
||||
void char_short_test();
|
||||
void init_test(void);
|
||||
void compound_literal_test(void);
|
||||
int kr_test();
|
||||
void struct_assign_test(void);
|
||||
void cast_test(void);
|
||||
void bitfield_test(void);
|
||||
void c99_bool_test(void);
|
||||
void float_test(void);
|
||||
void longlong_test(void);
|
||||
void manyarg_test(void);
|
||||
void stdarg_test(void);
|
||||
void whitespace_test(void);
|
||||
void relocation_test(void);
|
||||
void old_style_function(void);
|
||||
void alloca_test(void);
|
||||
void c99_vla_test(int size1, int size2);
|
||||
void sizeof_test(void);
|
||||
void typeof_test(void);
|
||||
void local_label_test(void);
|
||||
void statement_expr_test(void);
|
||||
void asm_test(void);
|
||||
void builtin_test(void);
|
||||
void weak_test(void);
|
||||
void global_data_test(void);
|
||||
void cmp_comparison_test(void);
|
||||
void math_cmp_test(void);
|
||||
void callsave_test(void);
|
||||
void builtin_frame_address_test(void);
|
||||
void attrib_test(void);
|
||||
void bounds_check1_test(void);
|
||||
|
||||
int fib(int n);
|
||||
void num(int n);
|
||||
void forward_ref(void);
|
||||
@ -146,8 +86,6 @@ int isid(int c);
|
||||
void funny_line_continuation (int, ..\
|
||||
. );
|
||||
|
||||
char via_volatile (char);
|
||||
|
||||
#define A 2
|
||||
#define N 1234 + A
|
||||
#define pf printf
|
||||
@ -207,74 +145,8 @@ int qq(int x)
|
||||
#define wq_spin_lock spin_lock
|
||||
#define TEST2() wq_spin_lock(a)
|
||||
|
||||
#define UINT_MAX ((unsigned) -1)
|
||||
|
||||
void intdiv_test(void)
|
||||
{
|
||||
printf("18/21=%u\n", 18/21);
|
||||
printf("18%%21=%u\n", 18%21);
|
||||
printf("41/21=%u\n", 41/21);
|
||||
printf("41%%21=%u\n", 41%21);
|
||||
printf("42/21=%u\n", 42/21);
|
||||
printf("42%%21=%u\n", 42%21);
|
||||
printf("43/21=%u\n", 43/21);
|
||||
printf("43%%21=%u\n", 43%21);
|
||||
printf("126/21=%u\n", 126/21);
|
||||
printf("126%%21=%u\n", 126%21);
|
||||
printf("131/21=%u\n", 131/21);
|
||||
printf("131%%21=%u\n", 131%21);
|
||||
printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
|
||||
printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2);
|
||||
|
||||
printf("18/-21=%u\n", 18/-21);
|
||||
printf("18%%-21=%u\n", 18%-21);
|
||||
printf("41/-21=%u\n", 41/-21);
|
||||
printf("41%%-21=%u\n", 41%-21);
|
||||
printf("42/-21=%u\n", 42/-21);
|
||||
printf("42%%-21=%u\n", 42%-21);
|
||||
printf("43/-21=%u\n", 43/-21);
|
||||
printf("43%%-21=%u\n", 43%-21);
|
||||
printf("126/-21=%u\n", 126/-21);
|
||||
printf("126%%-21=%u\n", 126%-21);
|
||||
printf("131/-21=%u\n", 131/-21);
|
||||
printf("131%%-21=%u\n", 131%-21);
|
||||
printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
|
||||
printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2);
|
||||
|
||||
printf("-18/21=%u\n", -18/21);
|
||||
printf("-18%%21=%u\n", -18%21);
|
||||
printf("-41/21=%u\n", -41/21);
|
||||
printf("-41%%21=%u\n", -41%21);
|
||||
printf("-42/21=%u\n", -42/21);
|
||||
printf("-42%%21=%u\n", -42%21);
|
||||
printf("-43/21=%u\n", -43/21);
|
||||
printf("-43%%21=%u\n", -43%21);
|
||||
printf("-126/21=%u\n", -126/21);
|
||||
printf("-126%%21=%u\n", -126%21);
|
||||
printf("-131/21=%u\n", -131/21);
|
||||
printf("-131%%21=%u\n", -131%21);
|
||||
printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
|
||||
printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2);
|
||||
|
||||
printf("-18/-21=%u\n", -18/-21);
|
||||
printf("-18%%-21=%u\n", -18%-21);
|
||||
printf("-41/-21=%u\n", -41/-21);
|
||||
printf("-41%%-21=%u\n", -41%-21);
|
||||
printf("-42/-21=%u\n", -42/-21);
|
||||
printf("-42%%-21=%u\n", -42%-21);
|
||||
printf("-43/-21=%u\n", -43/-21);
|
||||
printf("-43%%-21=%u\n", -43%-21);
|
||||
printf("-126/-21=%u\n", -126/-21);
|
||||
printf("-126%%-21=%u\n", -126%-21);
|
||||
printf("-131/-21=%u\n", -131/-21);
|
||||
printf("-131%%-21=%u\n", -131%-21);
|
||||
printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
|
||||
printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
|
||||
}
|
||||
|
||||
void macro_test(void)
|
||||
{
|
||||
printf("macro:\n");
|
||||
pf("N=%d\n", N);
|
||||
printf("aaa=%d\n", AAA);
|
||||
|
||||
@ -349,22 +221,6 @@ void macro_test(void)
|
||||
|
||||
MACRO_NOARGS();
|
||||
|
||||
#ifdef __LINE__
|
||||
printf("__LINE__ defined\n");
|
||||
#endif
|
||||
|
||||
printf("__LINE__=%d __FILE__=%s\n",
|
||||
__LINE__, __FILE__);
|
||||
#if 0
|
||||
#line 200
|
||||
printf("__LINE__=%d __FILE__=%s\n",
|
||||
__LINE__, __FILE__);
|
||||
#line 203 "test"
|
||||
printf("__LINE__=%d __FILE__=%s\n",
|
||||
__LINE__, __FILE__);
|
||||
#line 227 "tcctest.c"
|
||||
#endif
|
||||
|
||||
/* not strictly preprocessor, but we test it there */
|
||||
#ifdef C99_MACROS
|
||||
printf("__func__ = %s\n", __func__);
|
||||
@ -677,7 +533,7 @@ void goto_test()
|
||||
int i;
|
||||
static void *label_table[3] = { &&label1, &&label2, &&label3 };
|
||||
|
||||
printf("goto:\n");
|
||||
printf("\ngoto:\n");
|
||||
i = 0;
|
||||
/* This needs to parse as label, not as start of decl. */
|
||||
typedef_and_label x;
|
||||
@ -745,8 +601,7 @@ void enum_test()
|
||||
/* The following should give no warning */
|
||||
unsigned *p = &b1;
|
||||
struct S_enum s = {E7};
|
||||
printf("enum: %d\n", s.e);
|
||||
printf("enum:\n%d %d %d %d %d %d\n",
|
||||
printf("%d %d %d %d %d %d %d\n", s.e,
|
||||
E0, E1, E2, E3, E4, E5);
|
||||
b1 = 1;
|
||||
printf("b1=%d\n", b1);
|
||||
@ -775,7 +630,6 @@ void typedef_test()
|
||||
|
||||
a = &b;
|
||||
*a = 1234;
|
||||
printf("typedef:\n");
|
||||
printf("a=%d\n", *a);
|
||||
mytype2 = 2;
|
||||
printf("mytype2=%d\n", mytype2);
|
||||
@ -783,7 +637,6 @@ void typedef_test()
|
||||
|
||||
void forward_test()
|
||||
{
|
||||
printf("forward:\n");
|
||||
forward_ref();
|
||||
forward_ref();
|
||||
}
|
||||
@ -821,69 +674,6 @@ struct empty_mem {
|
||||
int x;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
string_test();
|
||||
expr_test();
|
||||
macro_test();
|
||||
recursive_macro_test();
|
||||
scope_test();
|
||||
scope_test2();
|
||||
forward_test();
|
||||
funcptr_test();
|
||||
if_test();
|
||||
loop_test();
|
||||
switch_test();
|
||||
goto_test();
|
||||
enum_test();
|
||||
typedef_test();
|
||||
struct_test();
|
||||
array_test();
|
||||
expr_ptr_test();
|
||||
bool_test();
|
||||
optimize_out();
|
||||
expr2_test();
|
||||
constant_expr_test();
|
||||
expr_cmp_test();
|
||||
char_short_test();
|
||||
init_test();
|
||||
compound_literal_test();
|
||||
kr_test();
|
||||
struct_assign_test();
|
||||
cast_test();
|
||||
bitfield_test();
|
||||
c99_bool_test();
|
||||
float_test();
|
||||
longlong_test();
|
||||
manyarg_test();
|
||||
stdarg_test();
|
||||
whitespace_test();
|
||||
relocation_test();
|
||||
old_style_function();
|
||||
alloca_test();
|
||||
c99_vla_test(5, 2);
|
||||
sizeof_test();
|
||||
typeof_test();
|
||||
statement_expr_test();
|
||||
local_label_test();
|
||||
asm_test();
|
||||
builtin_test();
|
||||
#ifndef _WIN32
|
||||
weak_test();
|
||||
#endif
|
||||
global_data_test();
|
||||
cmp_comparison_test();
|
||||
math_cmp_test();
|
||||
callsave_test();
|
||||
builtin_frame_address_test();
|
||||
intdiv_test();
|
||||
if (via_volatile (42) != 42)
|
||||
printf ("via_volatile broken\n");
|
||||
attrib_test();
|
||||
bounds_check1_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tab[3];
|
||||
int tab2[3][2];
|
||||
|
||||
@ -896,7 +686,6 @@ void f1(g)
|
||||
|
||||
void scope_test()
|
||||
{
|
||||
printf("scope:\n");
|
||||
g = 2;
|
||||
f1(1);
|
||||
printf("g2=%d\n", g);
|
||||
@ -915,7 +704,7 @@ void scope_test()
|
||||
|
||||
int st2_i;
|
||||
int *st2_p = &st2_i;
|
||||
void scope_test2()
|
||||
void scope2_test()
|
||||
{
|
||||
char a[50];
|
||||
st2_i = 42;
|
||||
@ -941,7 +730,6 @@ void array_test()
|
||||
{
|
||||
int i, j, a[4];
|
||||
|
||||
printf("array:\n");
|
||||
printf("sizeof(a) = %d\n", sizeof(a));
|
||||
printf("sizeof(\"a\") = %d\n", sizeof("a"));
|
||||
#ifdef C99_MACROS
|
||||
@ -1046,7 +834,6 @@ void expr2_test()
|
||||
{
|
||||
int a, b;
|
||||
|
||||
printf("expr2:\n");
|
||||
vstack_ptr = vstack;
|
||||
vpush(1432432, 2);
|
||||
vstack_ptr[-2] &= ~0xffffff80;
|
||||
@ -1059,7 +846,6 @@ int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */
|
||||
void constant_expr_test()
|
||||
{
|
||||
int a;
|
||||
printf("constant_expr:\n");
|
||||
a = 3;
|
||||
printf("%d\n", a * 16);
|
||||
printf("%d\n", a * 1);
|
||||
@ -1074,7 +860,6 @@ void expr_ptr_test()
|
||||
int *p, *q;
|
||||
int i = -1;
|
||||
|
||||
printf("expr_ptr:\n");
|
||||
p = tab4;
|
||||
q = tab4 + 10;
|
||||
printf("diff=%d\n", q - p);
|
||||
@ -1130,7 +915,6 @@ void expr_ptr_test()
|
||||
void expr_cmp_test()
|
||||
{
|
||||
int a, b;
|
||||
printf("constant_expr:\n");
|
||||
a = -1;
|
||||
b = 1;
|
||||
printf("%d\n", a == a);
|
||||
@ -1250,7 +1034,6 @@ void struct_test()
|
||||
union union2 u;
|
||||
struct Large ls;
|
||||
|
||||
printf("struct:\n");
|
||||
printf("sizes: %d %d %d %d\n",
|
||||
sizeof(struct struct1),
|
||||
sizeof(struct struct2),
|
||||
@ -1326,8 +1109,6 @@ void char_short_test()
|
||||
signed char var3;
|
||||
long long var4;
|
||||
|
||||
printf("char_short:\n");
|
||||
|
||||
var1 = 0x01020304;
|
||||
var2 = 0xfffefdfc;
|
||||
printf("s8=%d %d\n",
|
||||
@ -1495,7 +1276,7 @@ static inline void refer_to_undefined(void)
|
||||
undefined_function();
|
||||
}
|
||||
|
||||
void optimize_out(void)
|
||||
void optimize_out_test(void)
|
||||
{
|
||||
int i = 0 ? undefined_function() : defined_function();
|
||||
printf ("oo:%d\n", i);
|
||||
@ -1636,8 +1417,6 @@ void compound_literal_test(void)
|
||||
int *p, i;
|
||||
char *q, *q3;
|
||||
|
||||
printf("compound_test:\n");
|
||||
|
||||
p = (int []){1, 2, 3};
|
||||
for(i=0;i<3;i++)
|
||||
printf(" %d", p[i]);
|
||||
@ -1689,7 +1468,6 @@ int kr_func2(a, b)
|
||||
|
||||
kr_test()
|
||||
{
|
||||
printf("kr_test:\n");
|
||||
printf("func1=%d\n", kr_func1(3, 4));
|
||||
printf("func2=%d\n", kr_func2(3, 4));
|
||||
return 0;
|
||||
@ -1745,8 +1523,6 @@ void struct_assign_test(void)
|
||||
ps = &s;
|
||||
ps->i = 4;
|
||||
#if 0
|
||||
printf("struct_assign_test:\n");
|
||||
|
||||
s.lsta1.f1 = 1;
|
||||
s.lsta1.f2 = 2;
|
||||
printf("%d %d\n", s.lsta1.f1, s.lsta1.f2);
|
||||
@ -1792,7 +1568,6 @@ void cast_test()
|
||||
unsigned long ul = 0x80000000UL;
|
||||
p -= 0x700000000042;
|
||||
|
||||
printf("cast_test:\n");
|
||||
a = 0xfffff;
|
||||
cast1(a, a, a, a);
|
||||
a = 0xffffe;
|
||||
@ -1833,7 +1608,7 @@ void cast_test()
|
||||
printf("sizeof(-(char)'a') = %d\n", sizeof(-(char)'a'));
|
||||
printf("sizeof(~(char)'a') = %d\n", sizeof(-(char)'a'));
|
||||
|
||||
#if CC_NAME != CC_clang /* doesn't like non-portable conversions */
|
||||
#if CC_NAME != CC_clang /* clang doesn't support non-portable conversions */
|
||||
/* from pointer to integer types */
|
||||
printf("%d %d %ld %ld %lld %lld\n",
|
||||
(int)p, (unsigned int)p,
|
||||
@ -1972,8 +1747,6 @@ void init_test(void)
|
||||
/* Addresses on non-weak symbols are non-zero, but not the access itself */
|
||||
int linit18[2] = {&zero ? 1 : -1, zero ? -1 : 1 };
|
||||
|
||||
printf("init_test:\n");
|
||||
|
||||
printf("sinit1=%d\n", sinit1);
|
||||
printf("sinit2=%d\n", sinit2);
|
||||
printf("sinit3=%d %d %d %d\n",
|
||||
@ -2194,7 +1967,6 @@ void c99_bool_test(void)
|
||||
int a;
|
||||
_Bool b, b2;
|
||||
|
||||
printf("bool_test:\n");
|
||||
printf("sizeof(_Bool) = %d\n", sizeof(_Bool));
|
||||
a = 3;
|
||||
printf("cast: %d %d %d\n", (_Bool)10, (_Bool)0, (_Bool)a);
|
||||
@ -2222,7 +1994,6 @@ void bitfield_test(void)
|
||||
int f4 : 7;
|
||||
unsigned int f5 : 7;
|
||||
} st1;
|
||||
printf("bitfield_test:");
|
||||
printf("sizeof(st1) = %d\n", sizeof(st1));
|
||||
|
||||
st1.f1 = 3;
|
||||
@ -2442,7 +2213,6 @@ void float_test(void)
|
||||
static double inf1 = 1.0/0.0;
|
||||
static double inf2 = 1e5000;
|
||||
|
||||
printf("float_test:\n");
|
||||
printf("sizeof(float) = %d\n", sizeof(float));
|
||||
printf("sizeof(double) = %d\n", sizeof(double));
|
||||
printf("sizeof(long double) = %d\n", sizeof(LONG_DOUBLE));
|
||||
@ -2490,7 +2260,6 @@ void funcptr_test()
|
||||
} st1;
|
||||
long diff;
|
||||
|
||||
printf("funcptr:\n");
|
||||
func = #
|
||||
(*func)(12345);
|
||||
func = num;
|
||||
@ -2648,7 +2417,6 @@ void longlong_test(void)
|
||||
long long a, b, c;
|
||||
int ia;
|
||||
unsigned int ua;
|
||||
printf("longlong_test:\n");
|
||||
printf("sizeof(long long) = %d\n", sizeof(long long));
|
||||
ia = -1;
|
||||
ua = -2;
|
||||
@ -2728,7 +2496,6 @@ void longlong_test(void)
|
||||
void manyarg_test(void)
|
||||
{
|
||||
LONG_DOUBLE ld = 1234567891234LL;
|
||||
printf("manyarg_test:\n");
|
||||
printf("%d %d %d %d %d %d %d %d %f %f %f %f %f %f %f %f %f %f\n",
|
||||
1, 2, 3, 4, 5, 6, 7, 8,
|
||||
0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0);
|
||||
@ -2912,38 +2679,6 @@ void stdarg_test(void)
|
||||
stdarg_syntax(1, 17);
|
||||
}
|
||||
|
||||
void whitespace_test(void)
|
||||
{
|
||||
char *str;
|
||||
|
||||
#if 1
|
||||
pri\
|
||||
ntf("whitspace:\n");
|
||||
#endif
|
||||
pf("N=%d\n", 2);
|
||||
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
pri\
|
||||
ntf("aaa=%d\n", 3);
|
||||
#endif
|
||||
|
||||
pri\
|
||||
\
|
||||
ntf("min=%d\n", 4);
|
||||
|
||||
#ifdef ACCEPT_CR_IN_STRINGS
|
||||
printf("len1=%d\n", strlen("
|
||||
"));
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
str = "
|
||||
";
|
||||
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
||||
#endif
|
||||
printf("len1=%d\n", strlen("
a
|
||||
"));
|
||||
#endif /* ACCEPT_CR_IN_STRINGS */
|
||||
}
|
||||
|
||||
int reltab[3] = { 1, 2, 3 };
|
||||
|
||||
int *rel1 = &reltab[1];
|
||||
@ -3000,7 +2735,7 @@ int cmpfn();
|
||||
printf("cmpfn=%lx\n", (long)cmpfn);
|
||||
}
|
||||
|
||||
void old_style_function(void)
|
||||
void old_style_function_test(void)
|
||||
{
|
||||
old_style_f((void *)1, 2, 3.0);
|
||||
decl_func1(NULL);
|
||||
@ -3027,7 +2762,7 @@ void *bounds_checking_is_enabled()
|
||||
|
||||
typedef int constant_negative_array_size_as_compile_time_assertion_idiom[(1 ? 2 : 0) - 1];
|
||||
|
||||
void c99_vla_test(int size1, int size2)
|
||||
void c99_vla_test_1(int size1, int size2)
|
||||
{
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
int size = size1 * size2;
|
||||
@ -3078,6 +2813,12 @@ void c99_vla_test(int size1, int size2)
|
||||
#endif
|
||||
}
|
||||
|
||||
void c99_vla_test(void)
|
||||
{
|
||||
c99_vla_test_1(5, 2);
|
||||
}
|
||||
|
||||
|
||||
void sizeof_test(void)
|
||||
{
|
||||
int a;
|
||||
@ -3750,8 +3491,6 @@ void asm_test(void)
|
||||
#endif
|
||||
register int regvar asm("%esi");
|
||||
|
||||
printf("inline asm:\n");
|
||||
|
||||
// parse 0x1E-1 as 3 tokens in asm mode
|
||||
asm volatile ("mov $0x1E-1,%eax");
|
||||
|
||||
@ -3902,7 +3641,9 @@ void builtin_test(void)
|
||||
//printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
void weak_test(void) {}
|
||||
#else
|
||||
extern int __attribute__((weak)) weak_f1(void);
|
||||
extern int __attribute__((weak)) weak_f2(void);
|
||||
extern int weak_f3(void);
|
||||
@ -4170,6 +3911,14 @@ char via_volatile (char i)
|
||||
return vi;
|
||||
}
|
||||
|
||||
void volatile_test(void)
|
||||
{
|
||||
if (via_volatile (42) != 42)
|
||||
printf (" broken\n");
|
||||
else
|
||||
printf (" ok\n");
|
||||
}
|
||||
|
||||
struct __attribute__((__packed__)) Spacked {
|
||||
char a;
|
||||
short b;
|
||||
@ -4250,3 +3999,122 @@ void bounds_check1_test (void)
|
||||
pv(x);
|
||||
pv(y);
|
||||
}
|
||||
|
||||
/* gcc 2.95.3 does not handle correctly CR in strings or after strays */
|
||||
#define CORRECT_CR_HANDLING
|
||||
|
||||
/* deprecated and no longer supported in gcc 3.3 */
|
||||
#ifdef __TINYC__
|
||||
# define ACCEPT_CR_IN_STRINGS
|
||||
#endif
|
||||
|
||||
/* keep this as the last test because GCC messes up line-numbers
|
||||
with the ^L^K^M characters below */
|
||||
void whitespace_test(void)
|
||||
{
|
||||
char *str;
|
||||
|
||||
#if 1
|
||||
pri\
|
||||
ntf("whitspace:\n");
|
||||
#endif
|
||||
pf("N=%d\n", 2);
|
||||
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
pri\
|
||||
ntf("aaa=%d\n", 3);
|
||||
#endif
|
||||
|
||||
pri\
|
||||
\
|
||||
ntf("min=%d\n", 4);
|
||||
|
||||
#ifdef ACCEPT_CR_IN_STRINGS
|
||||
printf("len1=%d\n", strlen("
|
||||
"));
|
||||
#ifdef CORRECT_CR_HANDLING
|
||||
str = "
|
||||
";
|
||||
printf("len1=%d str[0]=%d\n", strlen(str), str[0]);
|
||||
#endif
|
||||
printf("len1=%d\n", strlen("
a
|
||||
"));
|
||||
#else
|
||||
printf("len1=1\nlen1=1 str[0]=10\nlen1=3\n");
|
||||
#endif /* ACCEPT_CR_IN_STRINGS */
|
||||
|
||||
#ifdef __LINE__
|
||||
printf("__LINE__ defined\n");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* wrong with GCC */
|
||||
printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
|
||||
#line 1111
|
||||
printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
|
||||
#line 2222 "test"
|
||||
printf("__LINE__=%d __FILE__=%s\n", __LINE__, __FILE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define RUN(test) puts("---- " #test " ----"), test(), puts("")
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
RUN(whitespace_test);
|
||||
RUN(macro_test);
|
||||
RUN(recursive_macro_test);
|
||||
RUN(string_test);
|
||||
RUN(expr_test);
|
||||
RUN(scope_test);
|
||||
RUN(scope2_test);
|
||||
RUN(forward_test);
|
||||
RUN(funcptr_test);
|
||||
RUN(if_test);
|
||||
RUN(loop_test);
|
||||
RUN(switch_test);
|
||||
RUN(goto_test);
|
||||
RUN(enum_test);
|
||||
RUN(typedef_test);
|
||||
RUN(struct_test);
|
||||
RUN(array_test);
|
||||
RUN(expr_ptr_test);
|
||||
RUN(bool_test);
|
||||
RUN(optimize_out_test);
|
||||
RUN(expr2_test);
|
||||
RUN(constant_expr_test);
|
||||
RUN(expr_cmp_test);
|
||||
RUN(char_short_test);
|
||||
RUN(init_test);
|
||||
RUN(compound_literal_test);
|
||||
RUN(kr_test);
|
||||
RUN(struct_assign_test);
|
||||
RUN(cast_test);
|
||||
RUN(bitfield_test);
|
||||
RUN(c99_bool_test);
|
||||
RUN(float_test);
|
||||
RUN(longlong_test);
|
||||
RUN(manyarg_test);
|
||||
RUN(stdarg_test);
|
||||
RUN(relocation_test);
|
||||
RUN(old_style_function_test);
|
||||
RUN(alloca_test);
|
||||
RUN(c99_vla_test);
|
||||
RUN(sizeof_test);
|
||||
RUN(typeof_test);
|
||||
RUN(statement_expr_test);
|
||||
RUN(local_label_test);
|
||||
RUN(asm_test);
|
||||
RUN(builtin_test);
|
||||
RUN(weak_test);
|
||||
RUN(global_data_test);
|
||||
RUN(cmp_comparison_test);
|
||||
RUN(math_cmp_test);
|
||||
RUN(callsave_test);
|
||||
RUN(builtin_frame_address_test);
|
||||
RUN(volatile_test);
|
||||
RUN(attrib_test);
|
||||
RUN(bounds_check1_test);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
70
tests/tests2/61_integers.c
Normal file
70
tests/tests2/61_integers.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* This was first introduced to test the ARM port */
|
||||
|
||||
#define UINT_MAX ((unsigned) -1)
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("18/21=%u\n", 18/21);
|
||||
printf("18%%21=%u\n", 18%21);
|
||||
printf("41/21=%u\n", 41/21);
|
||||
printf("41%%21=%u\n", 41%21);
|
||||
printf("42/21=%u\n", 42/21);
|
||||
printf("42%%21=%u\n", 42%21);
|
||||
printf("43/21=%u\n", 43/21);
|
||||
printf("43%%21=%u\n", 43%21);
|
||||
printf("126/21=%u\n", 126/21);
|
||||
printf("126%%21=%u\n", 126%21);
|
||||
printf("131/21=%u\n", 131/21);
|
||||
printf("131%%21=%u\n", 131%21);
|
||||
printf("(UINT_MAX/2+3)/2=%u\n", (UINT_MAX/2+3)/2);
|
||||
printf("(UINT_MAX/2+3)%%2=%u\n", (UINT_MAX/2+3)%2);
|
||||
|
||||
printf("18/-21=%u\n", 18/-21);
|
||||
printf("18%%-21=%u\n", 18%-21);
|
||||
printf("41/-21=%u\n", 41/-21);
|
||||
printf("41%%-21=%u\n", 41%-21);
|
||||
printf("42/-21=%u\n", 42/-21);
|
||||
printf("42%%-21=%u\n", 42%-21);
|
||||
printf("43/-21=%u\n", 43/-21);
|
||||
printf("43%%-21=%u\n", 43%-21);
|
||||
printf("126/-21=%u\n", 126/-21);
|
||||
printf("126%%-21=%u\n", 126%-21);
|
||||
printf("131/-21=%u\n", 131/-21);
|
||||
printf("131%%-21=%u\n", 131%-21);
|
||||
printf("(UINT_MAX/2+3)/-2=%u\n", (UINT_MAX/2+3)/-2);
|
||||
printf("(UINT_MAX/2+3)%%-2=%u\n", (UINT_MAX/2+3)%-2);
|
||||
|
||||
printf("-18/21=%u\n", -18/21);
|
||||
printf("-18%%21=%u\n", -18%21);
|
||||
printf("-41/21=%u\n", -41/21);
|
||||
printf("-41%%21=%u\n", -41%21);
|
||||
printf("-42/21=%u\n", -42/21);
|
||||
printf("-42%%21=%u\n", -42%21);
|
||||
printf("-43/21=%u\n", -43/21);
|
||||
printf("-43%%21=%u\n", -43%21);
|
||||
printf("-126/21=%u\n", -126/21);
|
||||
printf("-126%%21=%u\n", -126%21);
|
||||
printf("-131/21=%u\n", -131/21);
|
||||
printf("-131%%21=%u\n", -131%21);
|
||||
printf("-(UINT_MAX/2+3)/2=%u\n", (0-(UINT_MAX/2+3))/2);
|
||||
printf("-(UINT_MAX/2+3)%%2=%u\n", (0-(UINT_MAX/2+3))%2);
|
||||
|
||||
printf("-18/-21=%u\n", -18/-21);
|
||||
printf("-18%%-21=%u\n", -18%-21);
|
||||
printf("-41/-21=%u\n", -41/-21);
|
||||
printf("-41%%-21=%u\n", -41%-21);
|
||||
printf("-42/-21=%u\n", -42/-21);
|
||||
printf("-42%%-21=%u\n", -42%-21);
|
||||
printf("-43/-21=%u\n", -43/-21);
|
||||
printf("-43%%-21=%u\n", -43%-21);
|
||||
printf("-126/-21=%u\n", -126/-21);
|
||||
printf("-126%%-21=%u\n", -126%-21);
|
||||
printf("-131/-21=%u\n", -131/-21);
|
||||
printf("-131%%-21=%u\n", -131%-21);
|
||||
printf("-(UINT_MAX/2+3)/-2=%u\n", (0-(UINT_MAX/2+3))/-2);
|
||||
printf("-(UINT_MAX/2+3)%%-2=%u\n", (0-(UINT_MAX/2+3))%-2);
|
||||
|
||||
return 0;
|
||||
}
|
56
tests/tests2/61_integers.expect
Normal file
56
tests/tests2/61_integers.expect
Normal file
@ -0,0 +1,56 @@
|
||||
18/21=0
|
||||
18%21=18
|
||||
41/21=1
|
||||
41%21=20
|
||||
42/21=2
|
||||
42%21=0
|
||||
43/21=2
|
||||
43%21=1
|
||||
126/21=6
|
||||
126%21=0
|
||||
131/21=6
|
||||
131%21=5
|
||||
(UINT_MAX/2+3)/2=1073741825
|
||||
(UINT_MAX/2+3)%2=0
|
||||
18/-21=0
|
||||
18%-21=18
|
||||
41/-21=4294967295
|
||||
41%-21=20
|
||||
42/-21=4294967294
|
||||
42%-21=0
|
||||
43/-21=4294967294
|
||||
43%-21=1
|
||||
126/-21=4294967290
|
||||
126%-21=0
|
||||
131/-21=4294967290
|
||||
131%-21=5
|
||||
(UINT_MAX/2+3)/-2=0
|
||||
(UINT_MAX/2+3)%-2=2147483650
|
||||
-18/21=0
|
||||
-18%21=4294967278
|
||||
-41/21=4294967295
|
||||
-41%21=4294967276
|
||||
-42/21=4294967294
|
||||
-42%21=0
|
||||
-43/21=4294967294
|
||||
-43%21=4294967295
|
||||
-126/21=4294967290
|
||||
-126%21=0
|
||||
-131/21=4294967290
|
||||
-131%21=4294967291
|
||||
-(UINT_MAX/2+3)/2=1073741823
|
||||
-(UINT_MAX/2+3)%2=0
|
||||
-18/-21=0
|
||||
-18%-21=4294967278
|
||||
-41/-21=1
|
||||
-41%-21=4294967276
|
||||
-42/-21=2
|
||||
-42%-21=0
|
||||
-43/-21=2
|
||||
-43%-21=4294967295
|
||||
-126/-21=6
|
||||
-126%-21=0
|
||||
-131/-21=6
|
||||
-131%-21=4294967291
|
||||
-(UINT_MAX/2+3)/-2=0
|
||||
-(UINT_MAX/2+3)%-2=2147483646
|
14
x86_64-gen.c
14
x86_64-gen.c
@ -149,7 +149,7 @@ static int func_ret_sub;
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
static int func_bound_add_epilog;
|
||||
ST_DATA int func_bound_add_epilog;
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
@ -639,18 +639,6 @@ static void gcall_or_jmp(int is_jmp)
|
||||
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
|
||||
#endif
|
||||
oad(0xe8 + is_jmp, 0); /* call/jmp im */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check &&
|
||||
(vtop->sym->v == TOK_alloca ||
|
||||
vtop->sym->v == TOK_setjmp ||
|
||||
vtop->sym->v == TOK__setjmp
|
||||
#ifndef TCC_TARGET_PE
|
||||
|| vtop->sym->v == TOK_sigsetjmp
|
||||
|| vtop->sym->v == TOK___sigsetjmp
|
||||
#endif
|
||||
))
|
||||
func_bound_add_epilog = 1;
|
||||
#endif
|
||||
} else {
|
||||
/* otherwise, indirect call */
|
||||
r = TREG_R11;
|
||||
|
Loading…
Reference in New Issue
Block a user