mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
tccgen: void values, etc...
originally, this was meant to avoid 'void' values leak
to the gen-xxx.c generators which would otherwise try
to load void from/to registers. Also catch invalid types
such as 'unsigned bool' eariler.
tccgen.c:
- expr_cond()/gexpr(): ignore VT_VOID
- gen_cast(): set float reg with static initializers to make
backends happier with invalid input
- init_putv():
improve static compound literal initializers
Also:
- ignore "missing prototype" and "might return no value"
for old style K&R functions
tcc.c, libtcc.c:
- tcc_set_output_type(): return errors from loading crt1.o
tcc.h/tccpp.c:
- fix horrible longstanding mistake with sizeof SValue.tab.
Must have place for sizeof (long double) rather than the
target's LDOUBLE_SIZE.
tccdefs.h:
- add a fake __[u]int128_t for all platforms
arm-gen.c:
- gen_cvt_ftof() must load to reg always
arm64-gen.c:
- simplify arm64_pcs() a bit
i386/x86_64-gen.c:
- do not assume char is signed (for cross compilation arm->x86)
tccelf/macho linker message:
- instead of
"undefined symbol 'X'"
now say
"unresolved reference to 'X'"
which makes it more clear that it is a _linker_error_.
tccasm.c:
- .align/p2align: use 'nop's in exec sections
This commit is contained in:
parent
016087c954
commit
7e01b20362
@ -2283,8 +2283,9 @@ void gen_cvt_ftoi(int t)
|
||||
void gen_cvt_ftof(int t)
|
||||
{
|
||||
#ifdef TCC_ARM_VFP
|
||||
uint32_t r = gv(RC_FLOAT);
|
||||
if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) {
|
||||
uint32_t r = vfpr(gv(RC_FLOAT));
|
||||
r = vfpr(r);
|
||||
o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t));
|
||||
}
|
||||
#else
|
||||
|
||||
71
arm64-gen.c
71
arm64-gen.c
@ -278,7 +278,6 @@ static int arm64_type_size(int t)
|
||||
case VT_DOUBLE: return 3;
|
||||
case VT_LDOUBLE: return 4;
|
||||
case VT_BOOL: return 0;
|
||||
case VT_VOID: return 0;
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
@ -832,11 +831,10 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
int hfa = arm64_hfa(type[i], 0);
|
||||
int win_vararg_float = 0;
|
||||
int size, align;
|
||||
int size, align, bt;
|
||||
|
||||
if ((type[i]->t & VT_ARRAY) ||
|
||||
(type[i]->t & VT_BTYPE) == VT_FUNC)
|
||||
bt = type[i]->t & VT_BTYPE;
|
||||
if (bt == VT_PTR || bt == VT_FUNC)
|
||||
size = align = 8;
|
||||
else
|
||||
size = type_size(type[i], &align);
|
||||
@ -848,13 +846,10 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
}
|
||||
|
||||
#elif defined(TCC_TARGET_PE)
|
||||
if (variadic && i >= variadic && (hfa || is_float(type[i]->t))) {
|
||||
if (variadic && i >= variadic) {
|
||||
hfa = 0;
|
||||
if (is_float(type[i]->t)) {
|
||||
win_vararg_float = 1;
|
||||
size = 8;
|
||||
align = 8;
|
||||
}
|
||||
if (is_float(bt))
|
||||
bt = VT_INT, size = align = 8;
|
||||
}
|
||||
#endif
|
||||
if (hfa)
|
||||
@ -871,12 +866,12 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if ((type[i]->t & VT_BTYPE) == VT_STRUCT)
|
||||
else if (bt == VT_STRUCT)
|
||||
// B.4
|
||||
size = (size + 7) & ~7;
|
||||
|
||||
// C.1
|
||||
if (!win_vararg_float && is_float(type[i]->t) && nv < 8) {
|
||||
if (is_float(bt) && nv < 8) {
|
||||
a[i] = 16 + (nv++ << 1);
|
||||
continue;
|
||||
}
|
||||
@ -895,24 +890,24 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
}
|
||||
|
||||
// C.4
|
||||
if (hfa || (type[i]->t & VT_BTYPE) == VT_LDOUBLE) {
|
||||
if (hfa || bt == VT_LDOUBLE) {
|
||||
ns = (ns + 7) & ~7;
|
||||
ns = (ns + align - 1) & -align;
|
||||
}
|
||||
|
||||
// C.5
|
||||
if ((type[i]->t & VT_BTYPE) == VT_FLOAT)
|
||||
if (bt == VT_FLOAT)
|
||||
size = 8;
|
||||
|
||||
// C.6
|
||||
if (!win_vararg_float && (hfa || is_float(type[i]->t))) {
|
||||
if (hfa || is_float(bt)) {
|
||||
a[i] = ns;
|
||||
ns += size;
|
||||
continue;
|
||||
}
|
||||
|
||||
// C.7
|
||||
if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size <= 8 && nx < 8) {
|
||||
if (bt != VT_STRUCT && size <= 8 && nx < 8) {
|
||||
a[i] = nx++ << 1;
|
||||
continue;
|
||||
}
|
||||
@ -922,14 +917,14 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
nx = (nx + 1) & ~1;
|
||||
|
||||
// C.9
|
||||
if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size == 16 && nx < 7) {
|
||||
if (bt != VT_STRUCT && size == 16 && nx < 7) {
|
||||
a[i] = nx << 1;
|
||||
nx += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// C.10
|
||||
if ((type[i]->t & VT_BTYPE) == VT_STRUCT && size <= (8 - nx) * 8) {
|
||||
if (bt == VT_STRUCT && size <= (8 - nx) * 8) {
|
||||
a[i] = nx << 1;
|
||||
nx += (size + 7) >> 3;
|
||||
continue;
|
||||
@ -943,7 +938,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l
|
||||
ns = (ns + align - 1) & -align;
|
||||
|
||||
// C.13
|
||||
if ((type[i]->t & VT_BTYPE) == VT_STRUCT) {
|
||||
if (bt == VT_STRUCT) {
|
||||
a[i] = ns;
|
||||
ns += size;
|
||||
continue;
|
||||
@ -974,11 +969,11 @@ static unsigned long arm64_pcs(int variadic, int n, CType **type, unsigned long
|
||||
}
|
||||
|
||||
// Argument types:
|
||||
stack = arm64_pcs_aux(variadic, n, type + 1, a + 1);
|
||||
stack = arm64_pcs_aux(variadic, n - 1, type + 1, a + 1);
|
||||
|
||||
if (0) {
|
||||
int i;
|
||||
for (i = 0; i <= n; i++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!i)
|
||||
printf("arm64_pcs return: ");
|
||||
else
|
||||
@ -1076,9 +1071,9 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
|
||||
stack = arm64_pcs(
|
||||
#ifdef TCC_TARGET_PE
|
||||
old_style ? -1 :
|
||||
old_style ? /* all args like varargs in K&R style */ -1 :
|
||||
#endif
|
||||
var_nb_arg, nb_args, t, a);
|
||||
var_nb_arg, nb_args + 1, t, a);
|
||||
|
||||
// Allocate space for structs replaced by pointer:
|
||||
for (i = nb_args; i; i--)
|
||||
@ -1258,7 +1253,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
CType *func_type = &func_sym->type;
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
int pcs_n;
|
||||
Sym *sym;
|
||||
CType **t;
|
||||
unsigned long *a;
|
||||
@ -1266,35 +1260,32 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
int last_int = 0;
|
||||
int last_float = 0;
|
||||
int variadic = func_sym->type.ref->f.func_type == FUNC_ELLIPSIS;
|
||||
int var_nb_arg = n_func_args(&func_sym->type);
|
||||
int c;
|
||||
int var_nb_arg = variadic ? n_func_args(&func_sym->type) : 0;
|
||||
|
||||
func_vc = 144; // offset of where x8 is stored
|
||||
|
||||
for (sym = func_type->ref; sym; sym = sym->next)
|
||||
++n;
|
||||
|
||||
pcs_n = n - 1;
|
||||
c = n + variadic;
|
||||
t = tcc_malloc(c * sizeof(*t));
|
||||
a = tcc_malloc(c * sizeof(*a));
|
||||
#ifdef TCC_TARGET_PE
|
||||
n += variadic;
|
||||
#endif
|
||||
|
||||
t = tcc_malloc(n * sizeof(*t));
|
||||
a = tcc_malloc(n * sizeof(*a));
|
||||
for (sym = func_type->ref; sym; sym = sym->next)
|
||||
t[i++] = &sym->type;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (variadic) {
|
||||
t[i++] = &int_type;
|
||||
++pcs_n;
|
||||
}
|
||||
if (variadic)
|
||||
t[i] = &int_type;
|
||||
#endif
|
||||
|
||||
arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0,
|
||||
pcs_n, t, a);
|
||||
arm64_func_va_list_stack = arm64_pcs(var_nb_arg, n, t, a);
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (variadic)
|
||||
arm64_func_va_list_stack = arm64_pe_param_off(a[n]);
|
||||
arm64_func_va_list_stack = arm64_pe_param_off(a[n - 1]);
|
||||
#endif
|
||||
|
||||
#if !defined(TCC_TARGET_MACHO)
|
||||
@ -1304,6 +1295,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
last_float = 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (a && a[0] == 1)
|
||||
use_x8 = 1;
|
||||
for (i = 1, sym = func_type->ref->next; sym; i++, sym = sym->next) {
|
||||
@ -1563,7 +1555,8 @@ ST_FUNC void gfunc_return(CType *func_type)
|
||||
CType *t = func_type;
|
||||
unsigned long a;
|
||||
|
||||
arm64_pcs(0, 0, &t, &a);
|
||||
arm64_pcs(0, 1, &t, &a);
|
||||
|
||||
switch (a) {
|
||||
case -1:
|
||||
break;
|
||||
|
||||
10
i386-gen.c
10
i386-gen.c
@ -271,7 +271,7 @@ static void gen_modrm(int opc, int op_r2, int r, Sym *sym, int c)
|
||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
o(opc);
|
||||
/* currently, we use only ebp as base */
|
||||
if (c == (char)c) {
|
||||
if (c == (signed char)c) {
|
||||
/* short reference */
|
||||
o(0x45 | op_reg);
|
||||
g(c);
|
||||
@ -439,7 +439,7 @@ ST_FUNC void store(int r, SValue *v)
|
||||
|
||||
static void gadd_sp(int val)
|
||||
{
|
||||
if (val == (char)val) {
|
||||
if (val == (signed char)val) {
|
||||
o(0xc483);
|
||||
g(val);
|
||||
} else {
|
||||
@ -774,7 +774,7 @@ ST_FUNC void gjmp_addr(int a)
|
||||
{
|
||||
int r;
|
||||
r = a - ind - 2;
|
||||
if (r == (char)r) {
|
||||
if (r == (signed char)r) {
|
||||
g(0xeb);
|
||||
g(r);
|
||||
} else {
|
||||
@ -787,7 +787,7 @@ ST_FUNC void gjmp_addr(int a)
|
||||
ST_FUNC void gjmp_cond_addr(int a, int op)
|
||||
{
|
||||
int r = a - ind - 2;
|
||||
if (r == (char)r)
|
||||
if (r == (signed char)r)
|
||||
g(op - 32), g(r);
|
||||
else
|
||||
g(0x0f), gjmp2(op - 16, r - 4);
|
||||
@ -830,7 +830,7 @@ ST_FUNC void gen_opi(int op)
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
c = vtop->c.i;
|
||||
if (c == (char)c) {
|
||||
if (c == (signed char)c) {
|
||||
/* generate inc and dec for smaller code */
|
||||
if ((c == 1 || c == -1) && (op == '+' || op == '-')) {
|
||||
opc = (c == 1) ^ (op == '+');
|
||||
|
||||
@ -90,8 +90,6 @@
|
||||
#define __NO_TLS 1
|
||||
#define __RUNETYPE_INTERNAL 1
|
||||
# if __SIZEOF_POINTER__ == 8
|
||||
/* FIXME, __int128_t is used by setjump */
|
||||
#define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); }
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#else
|
||||
@ -142,12 +140,6 @@
|
||||
#endif
|
||||
#define __INT32_TYPE__ int
|
||||
|
||||
#if defined __aarch64__
|
||||
/* GCC's __uint128_t appears in some Linux/OSX header files. Make it a
|
||||
synonym for long double to get the size and alignment right. */
|
||||
#define __uint128_t long double
|
||||
#endif
|
||||
|
||||
#if !defined _WIN32
|
||||
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
||||
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
||||
@ -187,6 +179,12 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* GCC's __uint128_t appears in some Linux/OSX header files.
|
||||
Just make it some type with same size and alignment. */
|
||||
struct __uint128__ { char x[16]; } __attribute((__aligned__(16)));
|
||||
#define __int128_t struct __uint128__
|
||||
#define __uint128_t struct __uint128__
|
||||
|
||||
/* __builtin_va_list */
|
||||
#if defined __x86_64__
|
||||
#if !defined _WIN32
|
||||
|
||||
6
libtcc.c
6
libtcc.c
@ -252,7 +252,7 @@ static void *default_reallocator(void *ptr, unsigned long size)
|
||||
else {
|
||||
ptr1 = realloc(ptr, size);
|
||||
if (!ptr1) {
|
||||
fprintf(stderr, "memory full\n");
|
||||
fprintf(stderr, "tcc: memory full\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -1003,9 +1003,9 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
/* paths for crt objects */
|
||||
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
|
||||
tccelf_add_crtbegin(s);
|
||||
tccelf_add_crtbegin(s); /* may produce errors */
|
||||
#endif
|
||||
return 0;
|
||||
return s->nb_errors ? -1 : 0;
|
||||
}
|
||||
|
||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
|
||||
|
||||
16
tcc.c
16
tcc.c
@ -35,7 +35,7 @@ static const char help[] =
|
||||
"General options:\n"
|
||||
" -c compile only - generate an object file\n"
|
||||
" -o outfile set output filename\n"
|
||||
" -run run compiled source [with custom stdin: -rstdin FILE]\n"
|
||||
" -run run compiled source\n"
|
||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||
" -w disable all warnings\n"
|
||||
@ -105,6 +105,7 @@ static const char help2[] =
|
||||
" -static link to static libraries (not recommended)\n"
|
||||
" -dumpversion print version\n"
|
||||
" -print-search-dirs print search paths\n"
|
||||
" -rstdin file with -run: use 'file' as custom stdin\n"
|
||||
" -dt with -run/-E: auto-define 'test_...' macros\n"
|
||||
"Ignored options:\n"
|
||||
" -arch -C --param -pedantic -pipe -s -traditional\n"
|
||||
@ -354,9 +355,10 @@ redo:
|
||||
set_environment(s);
|
||||
if (s->output_type == 0)
|
||||
s->output_type = TCC_OUTPUT_EXE;
|
||||
tcc_set_output_type(s, s->output_type);
|
||||
ret = tcc_set_output_type(s, s->output_type);
|
||||
if (ppfp)
|
||||
s->ppfp = ppfp;
|
||||
|
||||
if ((s->output_type == TCC_OUTPUT_MEMORY
|
||||
|| s->output_type == TCC_OUTPUT_PREPROCESS)
|
||||
&& (s->dflag & 16)) { /* -dt option */
|
||||
@ -369,7 +371,7 @@ redo:
|
||||
|
||||
/* compile or add each files or library */
|
||||
first_file = NULL;
|
||||
do {
|
||||
while (0 == ret) {
|
||||
struct filespec *f = s->files[n];
|
||||
s->filetype = f->type;
|
||||
if (f->type & AFF_TYPE_LIB) {
|
||||
@ -381,9 +383,11 @@ redo:
|
||||
first_file = f->name;
|
||||
ret = tcc_add_file(s, f->name);
|
||||
}
|
||||
} while (++n < s->nb_files
|
||||
&& 0 == ret
|
||||
&& (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
|
||||
if (++n == s->nb_files)
|
||||
break;
|
||||
if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r)
|
||||
break;
|
||||
}
|
||||
|
||||
if (s->do_bench)
|
||||
end_time = getclock_ms();
|
||||
|
||||
9
tcc.h
9
tcc.h
@ -475,6 +475,9 @@ typedef struct CType {
|
||||
struct Sym *ref;
|
||||
} CType;
|
||||
|
||||
/* long double words on host(!) platform */
|
||||
#define LDOUBLE_WORDS ((sizeof(long double)+3)/4)
|
||||
|
||||
/* constant value */
|
||||
typedef union CValue {
|
||||
long double ld;
|
||||
@ -485,7 +488,7 @@ typedef union CValue {
|
||||
char *data;
|
||||
int size;
|
||||
} str;
|
||||
int tab[LDOUBLE_SIZE/4];
|
||||
int tab[LDOUBLE_WORDS];
|
||||
} CValue;
|
||||
|
||||
/* value on stack */
|
||||
@ -1446,8 +1449,8 @@ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expressio
|
||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
||||
ST_DATA int func_var; /* true if current function is variadic */
|
||||
ST_DATA int func_vc;
|
||||
ST_DATA int func_ind;
|
||||
ST_DATA int func_vc; /* stack address for implicit struct return storage */
|
||||
ST_DATA int func_ind; /* function start address */
|
||||
ST_DATA const char *funcname;
|
||||
|
||||
ST_FUNC void tccgen_init(TCCState *s1);
|
||||
|
||||
17
tccasm.c
17
tccasm.c
@ -510,7 +510,7 @@ static void pop_section(TCCState *s1)
|
||||
|
||||
static void asm_parse_directive(TCCState *s1, int global)
|
||||
{
|
||||
int n, offset, v, size, tok1;
|
||||
int n, offset, v, size, tok1, c;
|
||||
Section *sec;
|
||||
uint8_t *ptr;
|
||||
|
||||
@ -540,18 +540,25 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
/* the section must have a compatible alignment */
|
||||
if (sec->sh_addralign < n)
|
||||
sec->sh_addralign = n;
|
||||
c = sec->sh_flags & SHF_EXECINSTR;
|
||||
} else {
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
size = n;
|
||||
size = n, c = 0;
|
||||
}
|
||||
v = 0;
|
||||
if (tok == ',') {
|
||||
next();
|
||||
v = asm_int_expr(s1);
|
||||
v = asm_int_expr(s1), c = 0;
|
||||
}
|
||||
zero_pad:
|
||||
if ((uint64_t)ind + size >= 1<<30)
|
||||
tcc_error("too much data");
|
||||
if (sec->sh_type != SHT_NOBITS) {
|
||||
if (c) {
|
||||
gen_fill_nops(size);
|
||||
break;
|
||||
}
|
||||
sec->data_offset = ind;
|
||||
ptr = section_ptr_add(sec, size);
|
||||
memset(ptr, v, size);
|
||||
@ -706,11 +713,9 @@ static void asm_parse_directive(TCCState *s1, int global)
|
||||
expect("constant or same-section symbol");
|
||||
n += esym->st_value;
|
||||
}
|
||||
if (n < 0 || n > 0x100000)
|
||||
tcc_error(".org out of range");
|
||||
if (n < ind)
|
||||
tcc_error("attempt to .org backwards");
|
||||
v = 0;
|
||||
v = c = 0;
|
||||
size = n - ind;
|
||||
goto zero_pad;
|
||||
}
|
||||
|
||||
8
tccelf.c
8
tccelf.c
@ -1106,7 +1106,7 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||
if (sym_bind == STB_WEAK)
|
||||
sym->st_value = 0;
|
||||
else
|
||||
tcc_error_noabort("undefined symbol '%s'", name);
|
||||
tcc_error_noabort("unresolved reference to '%s'", name);
|
||||
|
||||
} else if (sh_num < SHN_LORESERVE) {
|
||||
/* add section base */
|
||||
@ -2074,7 +2074,7 @@ static void bind_exe_dynsyms(TCCState *s1, int is_PIE)
|
||||
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
|
||||
!strcmp(name, "_fp_hw")) {
|
||||
} else {
|
||||
tcc_error_noabort("undefined symbol '%s'", name);
|
||||
tcc_error_noabort("unresolved reference to '%s'", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2105,7 +2105,7 @@ static void bind_libs_dynsyms(TCCState *s1)
|
||||
if (esym->st_shndx == SHN_UNDEF) {
|
||||
/* weak symbols can stay undefined */
|
||||
if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
|
||||
tcc_warning("undefined dynamic symbol '%s'", name);
|
||||
tcc_warning("unresolved dynamic reference to '%s'", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3301,6 +3301,8 @@ invalid:
|
||||
continue;
|
||||
if (sh->sh_type != s->sh_type
|
||||
&& strcmp (s->name, ".eh_frame")
|
||||
/* some crt1.o seem to have two ".note.GNU-stack" (SHT_NOTE & SHT_PROGBITS) */
|
||||
&& strcmp (s->name, ".note.GNU-stack")
|
||||
) {
|
||||
tcc_error_noabort("section type conflict: %s %02x <> %02x", s->name, sh->sh_type, s->sh_type);
|
||||
goto the_end;
|
||||
|
||||
67
tccgen.c
67
tccgen.c
@ -70,8 +70,9 @@ ST_DATA int nocode_wanted; /* no code generation wanted */
|
||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
||||
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
|
||||
ST_DATA int func_vc;
|
||||
ST_DATA int func_ind;
|
||||
ST_DATA int func_vc; /* stack address for implicit struct return storage */
|
||||
ST_DATA int func_ind; /* function start address */
|
||||
static int func_old;
|
||||
ST_DATA const char *funcname;
|
||||
ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
|
||||
static CString initstr;
|
||||
@ -1385,7 +1386,7 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
|
||||
/* make sure that type->ref is on global stack */
|
||||
move_ref_to_global(s);
|
||||
/* put into local scope */
|
||||
s = sym_copy(s, &local_stack);
|
||||
sym_copy(s, &local_stack);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -1906,6 +1907,8 @@ ST_FUNC int gv(int rc)
|
||||
#endif
|
||||
|
||||
bt = vtop->type.t & VT_BTYPE;
|
||||
if (bt == VT_VOID || bt == VT_STRUCT) /* should not happen */
|
||||
return vtop->r;
|
||||
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
/* XXX mega hack */
|
||||
@ -2929,7 +2932,8 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
|
||||
type.ref = NULL;
|
||||
|
||||
if (bt1 == VT_VOID || bt2 == VT_VOID) {
|
||||
ret = op == '?' ? 1 : 0;
|
||||
if (op != '?')
|
||||
tcc_error("operation on void value");
|
||||
/* NOTE: as an extension, we accept void on only one side */
|
||||
type.t = VT_VOID;
|
||||
} else if (bt1 == VT_PTR || bt2 == VT_PTR) {
|
||||
@ -3176,7 +3180,7 @@ op_err:
|
||||
}
|
||||
// Make sure that we have converted to an rvalue:
|
||||
if (vtop->r & VT_LVAL)
|
||||
gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
|
||||
gv(RC_TYPE(vtop->type.t));
|
||||
}
|
||||
|
||||
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM
|
||||
@ -3281,8 +3285,10 @@ again:
|
||||
df = is_float(dbt);
|
||||
dbt_bt = dbt & VT_BTYPE;
|
||||
sbt_bt = sbt & VT_BTYPE;
|
||||
if (dbt_bt == VT_VOID)
|
||||
if (dbt_bt == VT_VOID) {
|
||||
vtop->r = vtop->r2 = VT_CONST;
|
||||
goto done;
|
||||
}
|
||||
if (sbt_bt == VT_VOID) {
|
||||
error:
|
||||
cast_error(&vtop->type, type);
|
||||
@ -3361,8 +3367,11 @@ error:
|
||||
}
|
||||
|
||||
/* cannot generate code for global or static initializers */
|
||||
if (nocode_wanted & DATA_ONLY_WANTED)
|
||||
if (nocode_wanted & DATA_ONLY_WANTED) {
|
||||
if (df)
|
||||
vtop->r = get_reg(RC_FLOAT); /* don't confuse backends */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* non constant case: generate code */
|
||||
if (dbt == VT_BOOL) {
|
||||
@ -4753,6 +4762,8 @@ static int parse_btype(CType *type, AttributeDef *ad, int ignore_label)
|
||||
} else {
|
||||
if (bt != -1 || (st != -1 && u != VT_INT))
|
||||
goto tmbt;
|
||||
if ((t & VT_DEFSIGN) && (u == VT_VOID || u > VT_LLONG))
|
||||
goto tmbt;
|
||||
bt = u;
|
||||
}
|
||||
if (u != VT_INT)
|
||||
@ -6112,6 +6123,7 @@ special_math_val:
|
||||
tcc_error("'%s' undeclared", name);
|
||||
/* for simple function calls, we tolerate undeclared
|
||||
external reference to int() function */
|
||||
if (!func_old)
|
||||
tcc_warning_c(warn_implicit_function_declaration)(
|
||||
"implicit declaration of function '%s'", name);
|
||||
s = external_global_sym(t, &func_old_type);
|
||||
@ -6660,7 +6672,7 @@ static void expr_cond(void)
|
||||
|
||||
/* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
|
||||
that `(expr ? a : b).mem` does not error with "lvalue expected" */
|
||||
islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE);
|
||||
islv = VT_STRUCT == (type.t & VT_BTYPE);
|
||||
|
||||
/* now we convert second operand */
|
||||
if (c != 1) {
|
||||
@ -6668,8 +6680,7 @@ static void expr_cond(void)
|
||||
if (islv) {
|
||||
mk_pointer(&vtop->type);
|
||||
gaddrof();
|
||||
} else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
||||
gaddrof();
|
||||
}
|
||||
}
|
||||
|
||||
rc = RC_TYPE(type.t);
|
||||
@ -6680,6 +6691,7 @@ static void expr_cond(void)
|
||||
|
||||
tt = r2 = 0;
|
||||
if (c < 0) {
|
||||
if (type.t != VT_VOID)
|
||||
r2 = gv(rc);
|
||||
tt = gjmp(0);
|
||||
}
|
||||
@ -6695,14 +6707,15 @@ static void expr_cond(void)
|
||||
if (islv) {
|
||||
mk_pointer(&vtop->type);
|
||||
gaddrof();
|
||||
} else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
|
||||
gaddrof();
|
||||
}
|
||||
}
|
||||
|
||||
if (c < 0) {
|
||||
if (type.t != VT_VOID) {
|
||||
r1 = gv(rc);
|
||||
move_reg(r2, r1, islv ? VT_PTR : type.t);
|
||||
vtop->r = r2;
|
||||
}
|
||||
gsym(tt);
|
||||
}
|
||||
|
||||
@ -6745,6 +6758,7 @@ ST_FUNC void gexpr(void)
|
||||
|
||||
/* make builtin_constant_p((1,2)) return 0 (like on gcc) */
|
||||
if ((vtop->r & VT_VALMASK) == VT_CONST && nocode_wanted && !CONST_WANTED)
|
||||
if (vtop->type.t != VT_VOID && (vtop->type.t & VT_BTYPE) != VT_STRUCT)
|
||||
gv(RC_TYPE(vtop->type.t));
|
||||
}
|
||||
}
|
||||
@ -6855,11 +6869,10 @@ static void check_func_return(void)
|
||||
{
|
||||
if ((func_vt.t & VT_BTYPE) == VT_VOID)
|
||||
return;
|
||||
if (!strcmp (funcname, "main")
|
||||
if ((!strcmp(funcname, "main") || func_old)
|
||||
&& (func_vt.t & VT_BTYPE) == VT_INT) {
|
||||
/* main returns 0 by default */
|
||||
vpushi(0);
|
||||
gen_assign_cast(&func_vt);
|
||||
gfunc_return(&func_vt);
|
||||
} else {
|
||||
tcc_warning("function might return no value: '%s'", funcname);
|
||||
@ -7242,6 +7255,8 @@ again:
|
||||
tcc_warning("void function returns a value");
|
||||
vtop--;
|
||||
}
|
||||
} else if (b && func_old && (func_vt.t & VT_BTYPE) == VT_INT) {
|
||||
vpushi(0);
|
||||
} else if (b) {
|
||||
tcc_warning("'return' with no value");
|
||||
b = 0;
|
||||
@ -7806,21 +7821,12 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
||||
ptr = sec->data + c;
|
||||
val = vtop->c.i;
|
||||
|
||||
/* XXX: make code faster ? */
|
||||
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
|
||||
vtop->sym->v >= SYM_FIRST_ANOM &&
|
||||
/* XXX This rejects compound literals like
|
||||
'(void *){ptr}'. The problem is that '&sym' is
|
||||
represented the same way, which would be ruled out
|
||||
by the SYM_FIRST_ANOM check above, but also '"string"'
|
||||
in 'char *p = "string"' is represented the same
|
||||
with the type being VT_PTR and the symbol being an
|
||||
anonymous one. That is, there's no difference in vtop
|
||||
between '(void *){x}' and '&(void *){x}'. Ignore
|
||||
pointer typed entities here. Hopefully no real code
|
||||
will ever use compound literals with scalar type. */
|
||||
(vtop->type.t & VT_BTYPE) != VT_PTR) {
|
||||
/* These come from compound literals, memcpy stuff over. */
|
||||
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST)
|
||||
&& vtop->sym->v >= SYM_FIRST_ANOM
|
||||
&& ((vtop->r & VT_LVAL) /* compound literal */
|
||||
|| bt == VT_STRUCT /* designator */
|
||||
)) {
|
||||
/* memcpy stuff over. */
|
||||
Section *ssec;
|
||||
ElfSym *esym;
|
||||
ElfW_Rel *rel;
|
||||
@ -8072,6 +8078,8 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tok == ',' && !no_oblock) /* static const char s[] = { "123", }; */
|
||||
next();
|
||||
} else {
|
||||
|
||||
do_init_array:
|
||||
@ -8528,6 +8536,7 @@ static void gen_function(Sym *sym)
|
||||
func_ind = ind;
|
||||
func_vt = sym->type.ref->type;
|
||||
func_var = sym->type.ref->f.func_type == FUNC_ELLIPSIS;
|
||||
func_old = sym->type.ref->f.func_type == FUNC_OLD;
|
||||
|
||||
/* NOTE: we patch the symbol size later */
|
||||
put_extern_sym(sym, cur_text_section, ind, 0);
|
||||
|
||||
@ -702,7 +702,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
||||
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
||||
if (sym->st_shndx == SHN_UNDEF)
|
||||
tcc_error("undefined local symbo: '%s'",
|
||||
tcc_error("unresolved local reference to '%s'",
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL;
|
||||
} else {
|
||||
@ -859,7 +859,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
||||
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
||||
if (sym->st_shndx == SHN_UNDEF)
|
||||
tcc_error("undefined local symbo: '%s'",
|
||||
tcc_error("unresolved local reference to '%s'",
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL;
|
||||
} else {
|
||||
@ -1042,7 +1042,7 @@ static int check_symbols(TCCState *s1, struct macho *mo)
|
||||
sym->st_shndx = SHN_FROMDLL;
|
||||
continue;
|
||||
}
|
||||
tcc_error_noabort("undefined symbol '%s'", name);
|
||||
tcc_error_noabort("unresolved reference to '%s'", name);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
30
tccpp.c
30
tccpp.c
@ -987,11 +987,7 @@ static inline int tok_size(const int *p)
|
||||
case TOK_CULLONG:
|
||||
return 1 + 2;
|
||||
case TOK_CLDOUBLE:
|
||||
#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
|
||||
return 1 + 8 / 4;
|
||||
#else
|
||||
return 1 + LDOUBLE_SIZE / 4;
|
||||
#endif
|
||||
return 1 + LDOUBLE_WORDS;
|
||||
default:
|
||||
return 1 + 0;
|
||||
}
|
||||
@ -1130,22 +1126,12 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
||||
str[len++] = cv->tab[1];
|
||||
break;
|
||||
case TOK_CLDOUBLE:
|
||||
#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE
|
||||
str[len++] = cv->tab[0];
|
||||
str[len++] = cv->tab[1];
|
||||
#elif LDOUBLE_SIZE == 12
|
||||
str[len++] = cv->tab[0];
|
||||
str[len++] = cv->tab[1];
|
||||
str[len++] = cv->tab[2];
|
||||
#elif LDOUBLE_SIZE == 16
|
||||
str[len++] = cv->tab[0];
|
||||
str[len++] = cv->tab[1];
|
||||
if (LDOUBLE_WORDS >= 3)
|
||||
str[len++] = cv->tab[2];
|
||||
if (LDOUBLE_WORDS >= 4)
|
||||
str[len++] = cv->tab[3];
|
||||
#else
|
||||
#error add long double size support
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1219,15 +1205,7 @@ static inline void tok_get(int *t, const int **pp, CValue *cv)
|
||||
n = 2;
|
||||
goto copy;
|
||||
case TOK_CLDOUBLE:
|
||||
#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE
|
||||
n = 2;
|
||||
#elif LDOUBLE_SIZE == 12
|
||||
n = 3;
|
||||
#elif LDOUBLE_SIZE == 16
|
||||
n = 4;
|
||||
#else
|
||||
# error add long double size support
|
||||
#endif
|
||||
n = LDOUBLE_WORDS;
|
||||
copy:
|
||||
do
|
||||
*tab++ = *p++;
|
||||
|
||||
@ -1465,17 +1465,37 @@ static int tab_reinit[10];
|
||||
static int tentative_ar[];
|
||||
static int tentative_ar[] = {1,2,3};
|
||||
|
||||
//int cinit1; /* a global variable can be defined several times without error ! */
|
||||
int cinit1;
|
||||
int cinit1; /* a global variable can be defined several times without error ! */
|
||||
int cinit1;
|
||||
int cinit1 = 0;
|
||||
int *cinit2 = (int []){3, 2, 1};
|
||||
uintptr_t cinit3 = (uintptr_t)"AA";
|
||||
char const * const cinit8[] = { [0 ... 1] = "BB", [2 ... 4] = "CC" };
|
||||
void *cinit52 = &(void*){ (void*) 52 };
|
||||
|
||||
#if __TINYC__ || __GNUC__ >= 6
|
||||
int cinit4 = (int){44};
|
||||
void *cinit51 = (void*){ (void*) 51 };
|
||||
struct _c6 { int a,b; } cinit6 = (struct _c6){61,62}, *cinit7 = &(struct _c6){71,72};
|
||||
#else
|
||||
int cinit4 = 44;
|
||||
void *cinit51 = (void*)51;
|
||||
struct _c6 { int a,b; } cinit6 = { 61,62 }, cinit70 = {71,72}, *cinit7 = &cinit70;
|
||||
#endif
|
||||
|
||||
void compound_literal_test(void)
|
||||
{
|
||||
int *p, i;
|
||||
char *q, *q3;
|
||||
|
||||
printf("cinit3 : %s\n", cinit3);
|
||||
printf("cinit4 : %d\n", cinit4);
|
||||
printf("cinit51 : %d\n", (int)cinit51);
|
||||
printf("cinit52 : %d\n", *(int*)cinit52);
|
||||
printf("cinit6 : %d %d\n", cinit6.a, cinit6.b);
|
||||
printf("cinit7 : %d %d\n", cinit7->a, cinit7->b);
|
||||
printf("cinit8 : %s %s %s %s %s\n", cinit8[0], cinit8[1], cinit8[2], cinit8[3], cinit8[4]);
|
||||
|
||||
p = (int []){1, 2, 3};
|
||||
for(i=0;i<3;i++)
|
||||
printf(" %d", p[i]);
|
||||
|
||||
@ -421,7 +421,7 @@ int f() { return v(); }
|
||||
#elif defined test_switch_W4
|
||||
#pragma comment(option, "-Wunsupported -Wno-error=implicit-function-declaration -Werror")
|
||||
#endif
|
||||
void func()
|
||||
void func(void)
|
||||
{
|
||||
char *ccp = "123";
|
||||
fink();
|
||||
|
||||
15
x86_64-gen.c
15
x86_64-gen.c
@ -314,7 +314,7 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
|
||||
}
|
||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
/* currently, we use only ebp as base */
|
||||
if (c == (char)c) {
|
||||
if (c == (signed char)c) {
|
||||
/* short reference */
|
||||
o(0x45 | op_reg);
|
||||
g(c);
|
||||
@ -436,8 +436,7 @@ void load(int r, SValue *sv)
|
||||
b = 0xdb, r = 5; /* fldt */
|
||||
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
|
||||
b = 0xbe0f; /* movsbl */
|
||||
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED) ||
|
||||
(ft & VT_TYPE) == (VT_BOOL | VT_UNSIGNED)) {
|
||||
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
|
||||
b = 0xb60f; /* movzbl */
|
||||
} else if ((ft & VT_TYPE) == VT_SHORT) {
|
||||
b = 0xbf0f; /* movswl */
|
||||
@ -532,7 +531,6 @@ void load(int r, SValue *sv)
|
||||
o(0x44 + REG_VALUE(r)*8); /* %xmmN */
|
||||
o(0xf024);
|
||||
} else {
|
||||
if (!nocode_wanted)
|
||||
assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
|
||||
if ((ft & VT_BTYPE) == VT_FLOAT) {
|
||||
o(0x100ff3);
|
||||
@ -543,7 +541,6 @@ void load(int r, SValue *sv)
|
||||
o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8);
|
||||
}
|
||||
} else if (r == TREG_ST0) {
|
||||
if (!nocode_wanted)
|
||||
assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
|
||||
/* gen_cvt_ftof(VT_LDOUBLE); */
|
||||
/* movsd %xmmN,-0x10(%rsp) */
|
||||
@ -749,7 +746,7 @@ static int arg_prepare_reg(int idx) {
|
||||
static void gen_offs_sp(int b, int r, int d)
|
||||
{
|
||||
orex(1,0,r & 0x100 ? 0 : r, b);
|
||||
if (d == (char)d) {
|
||||
if (d == (signed char)d) {
|
||||
o(0x2444 | (REG_VALUE(r) << 3));
|
||||
g(d);
|
||||
} else {
|
||||
@ -1052,7 +1049,7 @@ void gfunc_epilog(void)
|
||||
|
||||
static void gadd_sp(int val)
|
||||
{
|
||||
if (val == (char)val) {
|
||||
if (val == (signed char)val) {
|
||||
o(0xc48348);
|
||||
g(val);
|
||||
} else {
|
||||
@ -1635,7 +1632,7 @@ void gjmp_addr(int a)
|
||||
{
|
||||
int r;
|
||||
r = a - ind - 2;
|
||||
if (r == (char)r) {
|
||||
if (r == (signed char)r) {
|
||||
g(0xeb);
|
||||
g(r);
|
||||
} else {
|
||||
@ -1704,7 +1701,7 @@ void gen_opi(int op)
|
||||
r = gv(RC_INT);
|
||||
vswap();
|
||||
c = vtop->c.i;
|
||||
if (c == (char)c) {
|
||||
if (c == (signed char)c) {
|
||||
/* XXX: generate inc and dec for smaller code ? */
|
||||
orex(ll, r, 0, 0x83);
|
||||
o(0xc0 | (opc << 3) | REG_VALUE(r));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user