cleanups & stuff

libtcc.c:
- free 'elfint' string
- acceot  -O and -Os
- accept -gstabs (to override dwarf when default)
- better -Wp,...

tccpp.c:
- #line cleanup
  also warn with "extra tokens after directive"

tccgen.c & xxx_gen.c:
- force CPU flags to register earlier

tccelf.c:
- tcc_load_object: align size only for code sections
  data/bss objects are always put with their specfic type align
      (in decl_initializer_alloc())
  x86/64 doesn't need aligned code
  from c6afdff7ab

tccpe.c:
- enable dllimport for "_imp__<sym>" also from assembler

x86_64-gen.c & lib/libtcc1.c:
- simpler fneg without libtcc1 reference

tests2/134_double_to_signed.c:
- a tcc compiled by msvc won't pass this test
This commit is contained in:
grischka 2025-02-19 20:58:24 +01:00
parent f075851f9d
commit 006174449e
14 changed files with 65 additions and 96 deletions

View File

@ -1332,7 +1332,7 @@ again:
parameters and the function address. */
void gfunc_call(int nb_args)
{
int r, args_size;
int args_size;
int def_float_abi = float_abi;
int todo;
struct plan plan;
@ -1352,12 +1352,6 @@ void gfunc_call(int nb_args)
float_abi = ARM_SOFTFP_FLOAT;
}
#endif
/* cannot let cpu flags if other instruction are generated. Also avoid leaving
VT_JMP anywhere except on the top of the stack because it would complicate
the code generator. */
r = vtop->r & VT_VALMASK;
if (r == VT_CMP || (r & ~1) == VT_JMP)
gv(RC_INT);
memset(&plan, 0, sizeof plan);
if (nb_args)
@ -1716,9 +1710,6 @@ void gen_opi(int op)
opc|=2; // sub -> rsb
}
}
if ((vtop->r & VT_VALMASK) == VT_CMP ||
(vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
gv(RC_INT);
vswap();
c=intr(gv(RC_INT));
vswap();
@ -1757,9 +1748,6 @@ done:
break;
case 2:
opc=0xE1A00000|(opc<<5);
if ((vtop->r & VT_VALMASK) == VT_CMP ||
(vtop->r & (VT_VALMASK & ~1)) == VT_JMP)
gv(RC_INT);
vswap();
r=intr(gv(RC_INT));
vswap();

View File

@ -1029,10 +1029,6 @@ ST_FUNC void gfunc_call(int nb_args)
stack = (stack + 15) >> 4 << 4;
/* fetch cpu flag before generating any code */
if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(RC_INT);
if (stack >= 0x1000000) // 16Mb
tcc_error("stack size too big %lu", stack);
if (stack & 0xfff)

View File

@ -409,9 +409,6 @@ ST_FUNC void gfunc_call(int nb_args)
args_size = 0;
for(i = 0;i < nb_args; i++) {
if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
/* fetch cpu flag before generating any code */
if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(RC_INT);
size = type_size(&vtop->type, &align);
/* align to stack align size */
size = (size + 3) & ~3;

View File

@ -626,12 +626,6 @@ long long __fixxfdi (long double a1)
}
#endif /* !ARM */
#if defined __x86_64__
/* float constants used for unary minus operation */
const float __mzerosf = -0.0;
const double __mzerodf = -0.0;
#endif
#if defined _WIN64
/* MSVC x64 intrinsic */
void __faststorefence(void)

View File

@ -75,6 +75,8 @@ TCC_SEM(static tcc_compile_sem);
/* an array of pointers to memory to be free'd after errors */
ST_DATA void** stk_data;
ST_DATA int nb_stk_data;
/* option -d<num> (for general development purposes) */
ST_DATA int g_debug;
/********************************************************/
#ifdef _WIN32
@ -547,9 +549,8 @@ static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *
}
if (str.size) {
cstr_ccat(&str, '\0');
dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
dynarray_add(p_ary, p_nb_ary, str.data);
}
cstr_free(&str);
in = p+1;
} while (*p);
}
@ -848,6 +849,9 @@ LIBTCCAPI TCCState *tcc_new(void)
s->include_stack_ptr = s->include_stack;
tcc_set_lib_path(s, CONFIG_TCCDIR);
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif
return s;
}
@ -867,6 +871,7 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
tcc_free(s1->tcc_lib_path);
tcc_free(s1->soname);
tcc_free(s1->rpath);
tcc_free(s1->elfint);
tcc_free(s1->elf_entryname);
tcc_free(s1->init_symbol);
tcc_free(s1->fini_symbol);
@ -1225,17 +1230,15 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
"%s/lib%s.a",
NULL
};
const char * const *pp = s->static_link
? libs + sizeof(libs) / sizeof(*libs) - 2
: libs;
/* if libraryname begins with a colon, it means search lib paths for
exactly the following file, without lib prefix or anything */
if (*libraryname == ':')
if (*libraryname == ':') {
libraryname++;
else {
} else {
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
const char * const *pp = libs;
if (s->static_link)
pp += sizeof(libs) / sizeof(*libs) - 2; /* only "%s/lib%s.a" */
while (*pp) {
int ret = tcc_add_library_internal(s, *pp,
libraryname, flags, s->library_paths, s->nb_library_paths);
@ -1341,7 +1344,7 @@ static int link_option(const char *str, const char *val, const char **ptr)
if (*p != ',' && *p != '=')
return 0;
p++;
} else if (*p) {
} else if (*p && *p != ',') {
return 0;
}
*ptr = p;
@ -1890,7 +1893,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
++s->verbose;
continue;
}
reparse:
if (r[0] != '-' || r[1] == '\0') {
args_parser_add_file(s, r, s->filetype);
if (run) {
@ -1968,7 +1970,8 @@ dorun:
goto enable_backtrace;
enable_backtrace:
s->do_backtrace = 1;
s->do_debug = s->do_debug ? s->do_debug : 1;
if (0 == s->do_debug)
s->do_debug = 1;
s->dwarf = CONFIG_DWARF_VERSION;
break;
#ifdef CONFIG_TCC_BCHECK
@ -1982,6 +1985,8 @@ dorun:
s->dwarf = CONFIG_DWARF_VERSION;
if (strstart("dwarf", &optarg)) {
s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
} else if (0 == strcmp("stabs", optarg)) {
s->dwarf = 0;
} else if (isnum(*optarg)) {
x = *optarg - '0';
/* -g0 = no info, -g1 = lines/functions only, -g2 = full info */
@ -2007,7 +2012,7 @@ dorun:
else if (*optarg == 't')
s->dflag = 16;
else if (isnum(*optarg))
s->g_debug |= atoi(optarg);
g_debug |= atoi(optarg);
else
goto unsupported_option;
break;
@ -2106,8 +2111,15 @@ dorun:
return -1;
break;
case TCC_OPTION_Wp:
r = optarg;
goto reparse;
{
char *p = tcc_strdup(optarg), *q = p;
while (!!(q = strchr(q, ','))) *q++ = ' ';
x = tcc_set_options(s, p);
tcc_free(p);
if (x < 0)
return -1;
break;
}
case TCC_OPTION_E:
x = TCC_OUTPUT_PREPROCESS;
goto set_output_type;
@ -2156,7 +2168,7 @@ dorun:
s->filetype = x | (s->filetype & ~AFF_TYPE_MASK);
break;
case TCC_OPTION_O:
s->optimize = atoi(optarg);
s->optimize = isnum(optarg[0]) ? optarg[0]-'0' : 1 /* -O -Os */;
break;
case TCC_OPTION_print_search_dirs:
x = OPT_PRINT_DIRS;

View File

@ -628,11 +628,6 @@ ST_FUNC void gfunc_call(int nb_args)
tempspace = (tempspace + 15) & -16;
stack_add = stack_adj + tempspace;
/* fetch cpu flag before generating any code */
if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(RC_INT);
if (stack_add) {
if (stack_add >= 0x800) {
unsigned int bit11 = (((unsigned int)-stack_add) >> 11) & 1;

3
tcc.c
View File

@ -293,9 +293,6 @@ int main(int argc0, char **argv0)
redo:
argc = argc0, argv = argv0;
s = s1 = tcc_new();
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
tcc_set_options(s, CONFIG_TCC_SWITCHES);
#endif
opt = tcc_parse_args(s, &argc, &argv, 1);
if (opt < 0)
return 1;

6
tcc.h
View File

@ -803,7 +803,7 @@ struct TCCState {
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
char *soname; /* as specified on the command line (-soname) */
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
char *elfint; /* -Wl,-I on command line, LD_SO in environment, or DEFAULT_ELFINTERP(this) */
char *elfint; /* -Wl,-I... on command line */
char *elf_entryname; /* "_start" unless set */
char *init_symbol; /* symbols to call at load-time (not used currently) */
char *fini_symbol; /* symbols to call at unload-time (not used currently) */
@ -987,9 +987,6 @@ struct TCCState {
unsigned int total_bytes;
unsigned int total_output[4];
/* option -dnum (for general development purposes) */
int g_debug;
/* used by tcc_load_ldscript */
int fd, cc;
@ -1193,6 +1190,7 @@ enum tcc_token {
ST_DATA struct TCCState *tcc_state;
ST_DATA void** stk_data;
ST_DATA int nb_stk_data;
ST_DATA int g_debug;
/* public functions currently used by the tcc main function */
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);

View File

@ -3247,11 +3247,12 @@ invalid:
} else {
s->data_offset += size;
}
/* align end of section */
#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
/* align code sections to instruction lenght */
/* This is needed if we compile a c file after this */
if (s == text_section || s == data_section || s == rodata_section ||
s == bss_section || s == common_section)
s->data_offset += -s->data_offset & (s->sh_addralign - 1);
if (s->sh_flags & SHF_EXECINSTR)
section_add(s, 0, 4);
#endif
next: ;
}

View File

@ -6187,6 +6187,7 @@ special_math_val:
}
next();
vcheck_cmp(); /* the generators don't like VT_CMP on vtop */
gfunc_call(nb_args);
if (ret_nregs < 0) {
@ -8221,7 +8222,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
sec = rodata_section;
} else if (has_init) {
sec = data_section;
/*if (tcc_state->g_debug & 4)
/*if (g_debug & 4)
tcc_warning("rw data: %s", get_tok_str(v, 0));*/
} else if (tcc_state->nocommon)
sec = bss_section;

View File

@ -1262,6 +1262,8 @@ static int pe_check_symbols(struct pe_info *pe)
const char *s, *p;
n = _imp_ = 0;
if (sym->st_other & ST_PE_IMPORT)
_imp_ = 1;
do {
s = pe_export_name(s1, sym);
if (n) {
@ -1293,7 +1295,7 @@ static int pe_check_symbols(struct pe_info *pe)
if (type == STT_FUNC
/* symbols from assembler often have no type */
|| type == STT_NOTYPE) {
|| (type == STT_NOTYPE && 0 == _imp_)) {
unsigned offset = is->thk_offset;
if (offset) {
/* got aliased symbol, like stricmp and _stricmp */
@ -1336,7 +1338,7 @@ static int pe_check_symbols(struct pe_info *pe)
sym->st_other &= ~ST_PE_EXPORT; /* do not export */
} else { /* STT_OBJECT */
if (0 == _imp_ && 0 == (sym->st_other & ST_PE_IMPORT))
if (0 == _imp_)
ret = tcc_error_noabort("symbol '%s' is missing __declspec(dllimport)", name);
/* original symbol will be patched later in pe_build_imports */
sym->st_value = is->iat_index; /* chain potential alias */
@ -2015,7 +2017,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
}
pe_free_imports(&pe);
#if PE_PRINT_SECTIONS
if (s1->g_debug & 8)
if (g_debug & 8)
pe_print_sections(s1, "tcc.log");
#endif
return s1->nb_errors ? -1 : 0;

25
tccpp.c
View File

@ -1338,8 +1338,10 @@ ST_FUNC void skip_to_eol(int warn)
return;
if (warn)
tcc_warning("extra tokens after directive");
while (macro_stack)
end_macro();
file->buf_ptr = parse_line_comment(file->buf_ptr - 1);
tok = TOK_LINEFEED;
next_nomacro();
}
static CachedInclude *
@ -1931,38 +1933,37 @@ ST_FUNC void preprocess(int is_bof)
case TOK_LINE:
parse_flags &= ~PARSE_FLAG_TOK_NUM;
next();
parse_flags |= PARSE_FLAG_TOK_NUM;
if (tok != TOK_PPNUM) {
_line_err:
tcc_error("wrong #line format");
}
c = 1;
goto _line_num;
case TOK_PPNUM:
if (parse_flags & PARSE_FLAG_ASM_FILE)
goto ignore;
c = 0; /* no error with extra tokens */
_line_num:
for (n = 0, q = tokc.str.data; *q; ++q) {
if (!isnum(*q))
goto _line_err;
n = n * 10 + *q - '0';
}
parse_flags &= ~PARSE_FLAG_TOK_STR;
parse_flags &= ~PARSE_FLAG_TOK_STR; /* don't parse escape sequences */
next();
parse_flags |= PARSE_FLAG_TOK_STR;
if (tok == TOK_PPSTR && tokc.str.data[0] == '"') {
if (tok != TOK_LINEFEED) {
if (tok != TOK_PPSTR || tokc.str.data[0] != '"')
goto _line_err;
tokc.str.data[tokc.str.size - 2] = 0;
tccpp_putfile(tokc.str.data + 1);
n--;
if (macro_ptr && *macro_ptr == 0)
macro_stack->save_line_num = n;
next();
/* skip optional level number & advance to next line */
skip_to_eol(c);
}
else if (tok != TOK_LINEFEED)
goto _line_err;
if (file->fd > 0)
total_lines += file->line_num - n;
file->line_ref += file->line_num - n;
file->line_num = n;
goto ignore; /* skip optional level number */
break;
case TOK_ERROR:
case TOK_WARNING:

View File

@ -8,5 +8,10 @@ int main() {
d = -2147483648.0;
printf("%d\n", (int)d);
#ifndef _WIN32
printf("%llu\n", (unsigned long long)1e19);
#else
/* some msvc compiler won't compile tcc correctly in this ragard */
printf("10000000000000000000\n");
#endif
}

View File

@ -828,9 +828,6 @@ void gfunc_call(int nb_args)
continue; /* arguments smaller than 8 bytes passed in registers or on stack */
if (bt == VT_STRUCT) {
/* fetch cpu flag before generating any code */
if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(RC_INT);
/* align to stack align size */
size = (size + 15) & ~15;
/* generate structure store */
@ -1281,10 +1278,6 @@ void gfunc_call(int nb_args)
if (nb_sse_args && tcc_state->nosse)
tcc_error("SSE disabled but floating point arguments passed");
/* fetch cpu flag before generating any code */
if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(RC_INT);
/* for struct arguments, we need to call memcpy and the function
call breaks register passing arguments we are preparing.
So, we process arguments which will be passed by stack first. */
@ -1831,13 +1824,6 @@ void gen_opl(int op)
gen_opi(op);
}
void vpush_const(int t, int v)
{
CType ctype = { t | VT_CONSTANT, 0 };
vpushsym(&ctype, external_global_sym(v, &ctype));
vtop->r |= VT_LVAL;
}
/* generate a floating point operation 'v = t1 op t2' instruction. The
two operands are guaranteed to have the same floating point type */
/* XXX: need to use ST1 too */
@ -1852,14 +1838,10 @@ void gen_opf(int op)
if (float_type == RC_ST0) {
o(0xe0d9); /* fchs */
} else {
/* -0.0, in libtcc1.c */
vpush_const(bt, bt == VT_FLOAT ? TOK___mzerosf : TOK___mzerodf);
gv(RC_FLOAT);
if (bt == VT_DOUBLE)
o(0x66);
/* xorp[sd] %xmm1, %xmm0 */
o(0xc0570f | (REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8) << 16);
vtop--;
save_reg(vtop->r);
o(0x80); /* xor $0x80, $n(rbp) */
gen_modrm(6, vtop->r, NULL, vtop->c.i + (bt == VT_DOUBLE ? 7 : 3));
o(0x80);
}
return;
}