__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:
grischka 2020-07-06 00:00:42 +02:00
parent 6a4f3cf127
commit 2a0167adfe
16 changed files with 641 additions and 719 deletions

View File

@ -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

View File

@ -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

View File

@ -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] != '%')

View File

@ -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);

View File

@ -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");

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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);
}

View File

@ -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
View 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
View 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

View File

@ -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 = &num;
(*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;
}

View 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;
}

View 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

View File

@ -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;