libtcc.c: -m option cleanup

handle mms-bitfields as sub-options of -m. (-mfloat-abi
is still special because it requires arguments)

tcc.c: help():
- list -mms-bitfields under 'Target specific options'

libtcc.c/MEM_DEBUG
- add check for past buffer writes
master
grischka 2016-12-18 22:57:03 +01:00
parent a1c12b9fb9
commit d2332396e4
4 changed files with 152 additions and 201 deletions

309
libtcc.c
View File

@ -245,7 +245,14 @@ PUB_FUNC void tcc_memstats(int bench)
#define MEM_DEBUG_MAGIC1 0xFEEDDEB1 #define MEM_DEBUG_MAGIC1 0xFEEDDEB1
#define MEM_DEBUG_MAGIC2 0xFEEDDEB2 #define MEM_DEBUG_MAGIC2 0xFEEDDEB2
#define MEM_DEBUG_FILE_LEN 15 #define MEM_DEBUG_MAGIC3 0xFEEDDEB3
#define MEM_DEBUG_FILE_LEN 40
#define MEM_DEBUG_CHECK3(header) \
((mem_debug_header_t*)((char*)header + header->size))->magic3
#define MEM_USER_PTR(header) \
((char *)header + offsetof(mem_debug_header_t, magic3))
#define MEM_HEADER_PTR(ptr) \
(mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3))
struct mem_debug_header { struct mem_debug_header {
unsigned magic1; unsigned magic1;
@ -255,6 +262,7 @@ struct mem_debug_header {
int line_num; int line_num;
char file_name[MEM_DEBUG_FILE_LEN + 1]; char file_name[MEM_DEBUG_FILE_LEN + 1];
unsigned magic2; unsigned magic2;
unsigned magic3;
}; };
typedef struct mem_debug_header mem_debug_header_t; typedef struct mem_debug_header mem_debug_header_t;
@ -263,76 +271,70 @@ static mem_debug_header_t *mem_debug_chain;
static unsigned mem_cur_size; static unsigned mem_cur_size;
static unsigned mem_max_size; static unsigned mem_max_size;
static mem_debug_header_t *malloc_check(void *ptr, const char *msg)
{
mem_debug_header_t * header = MEM_HEADER_PTR(ptr);
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
header->magic2 != MEM_DEBUG_MAGIC2 ||
MEM_DEBUG_CHECK3(header) != MEM_DEBUG_MAGIC3 ||
header->size == (unsigned)-1) {
fprintf(stderr, "%s check failed\n", msg);
if (header->magic1 == MEM_DEBUG_MAGIC1)
fprintf(stderr, "%s:%u: block allocated here.\n",
header->file_name, header->line_num);
exit(1);
}
return header;
}
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
{ {
void *ptr;
int ofs; int ofs;
mem_debug_header_t *header; mem_debug_header_t *header;
ptr = malloc(sizeof(mem_debug_header_t) + size); header = malloc(sizeof(mem_debug_header_t) + size);
if (!ptr) if (!header)
tcc_error("memory full (malloc)"); tcc_error("memory full (malloc)");
mem_cur_size += size;
if (mem_cur_size > mem_max_size)
mem_max_size = mem_cur_size;
header = (mem_debug_header_t *)ptr;
header->magic1 = MEM_DEBUG_MAGIC1; header->magic1 = MEM_DEBUG_MAGIC1;
header->magic2 = MEM_DEBUG_MAGIC2; header->magic2 = MEM_DEBUG_MAGIC2;
header->size = size; header->size = size;
MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3;
header->line_num = line; header->line_num = line;
ofs = strlen(file) - MEM_DEBUG_FILE_LEN; ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN); strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
header->file_name[MEM_DEBUG_FILE_LEN] = 0; header->file_name[MEM_DEBUG_FILE_LEN] = 0;
header->next = mem_debug_chain; header->next = mem_debug_chain;
header->prev = NULL; header->prev = NULL;
if (header->next) if (header->next)
header->next->prev = header; header->next->prev = header;
mem_debug_chain = header; mem_debug_chain = header;
ptr = (char *)ptr + sizeof(mem_debug_header_t); mem_cur_size += size;
return ptr; if (mem_cur_size > mem_max_size)
mem_max_size = mem_cur_size;
return MEM_USER_PTR(header);
} }
PUB_FUNC void tcc_free_debug(void *ptr) PUB_FUNC void tcc_free_debug(void *ptr)
{ {
mem_debug_header_t *header; mem_debug_header_t *header;
if (!ptr) if (!ptr)
return; return;
header = malloc_check(ptr, "tcc_free");
ptr = (char *)ptr - sizeof(mem_debug_header_t);
header = (mem_debug_header_t *)ptr;
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
header->magic2 != MEM_DEBUG_MAGIC2 ||
header->size == (unsigned)-1 )
{
tcc_error("tcc_free check failed");
}
mem_cur_size -= header->size; mem_cur_size -= header->size;
header->size = (unsigned)-1; header->size = (unsigned)-1;
if (header->next) if (header->next)
header->next->prev = header->prev; header->next->prev = header->prev;
if (header->prev) if (header->prev)
header->prev->next = header->next; header->prev->next = header->next;
if (header == mem_debug_chain) if (header == mem_debug_chain)
mem_debug_chain = header->next; mem_debug_chain = header->next;
free(header);
free(ptr);
} }
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line)
{ {
void *ptr; void *ptr;
@ -345,52 +347,26 @@ PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file
{ {
mem_debug_header_t *header; mem_debug_header_t *header;
int mem_debug_chain_update = 0; int mem_debug_chain_update = 0;
if (!ptr) {
ptr = tcc_malloc_debug(size, file, line);
return ptr;
}
ptr = (char *)ptr - sizeof(mem_debug_header_t);
header = (mem_debug_header_t *)ptr;
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
header->magic2 != MEM_DEBUG_MAGIC2 ||
header->size == (unsigned)-1 )
{
check_error:
tcc_error("tcc_realloc check failed");
}
mem_debug_chain_update = (header == mem_debug_chain);
mem_cur_size -= header->size;
ptr = realloc(ptr, sizeof(mem_debug_header_t) + size);
if (!ptr) if (!ptr)
return tcc_malloc_debug(size, file, line);
header = malloc_check(ptr, "tcc_realloc");
mem_cur_size -= header->size;
mem_debug_chain_update = (header == mem_debug_chain);
header = realloc(header, sizeof(mem_debug_header_t) + size);
if (!header)
tcc_error("memory full (realloc)"); tcc_error("memory full (realloc)");
header->size = size;
header = (mem_debug_header_t *)ptr; MEM_DEBUG_CHECK3(header) = MEM_DEBUG_MAGIC3;
if (header->magic1 != MEM_DEBUG_MAGIC1 || if (header->next)
header->magic2 != MEM_DEBUG_MAGIC2) header->next->prev = header;
{ if (header->prev)
goto check_error; header->prev->next = header;
} if (mem_debug_chain_update)
mem_debug_chain = header;
mem_cur_size += size; mem_cur_size += size;
if (mem_cur_size > mem_max_size) if (mem_cur_size > mem_max_size)
mem_max_size = mem_cur_size; mem_max_size = mem_cur_size;
return MEM_USER_PTR(header);
header->size = size;
if (header->next)
header->next->prev = header;
if (header->prev)
header->prev->next = header;
if (mem_debug_chain_update)
mem_debug_chain = header;
ptr = (char *)ptr + sizeof(mem_debug_header_t);
return ptr;
} }
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
@ -405,10 +381,8 @@ PUB_FUNC void tcc_memstats(int bench)
{ {
if (mem_cur_size) { if (mem_cur_size) {
mem_debug_header_t *header = mem_debug_chain; mem_debug_header_t *header = mem_debug_chain;
fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
mem_cur_size, mem_max_size); mem_cur_size, mem_max_size);
while (header) { while (header) {
fprintf(stderr, "%s:%u: error: %u bytes leaked\n", fprintf(stderr, "%s:%u: error: %u bytes leaked\n",
header->file_name, header->line_num, header->size); header->file_name, header->line_num, header->size);
@ -417,16 +391,10 @@ PUB_FUNC void tcc_memstats(int bench)
#if MEM_DEBUG-0 == 2 #if MEM_DEBUG-0 == 2
exit(2); exit(2);
#endif #endif
} } else if (bench)
else if (bench)
fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size); fprintf(stderr, "mem_max_size= %d bytes\n", mem_max_size);
} }
#endif /* MEM_DEBUG */
#undef MEM_DEBUG_MAGIC1
#undef MEM_DEBUG_MAGIC2
#undef MEM_DEBUG_FILE_LEN
#endif
#define free(p) use_tcc_free(p) #define free(p) use_tcc_free(p)
#define malloc(s) use_tcc_malloc(s) #define malloc(s) use_tcc_malloc(s)
@ -760,7 +728,6 @@ LIBTCCAPI TCCState *tcc_new(void)
s->alacarte_link = 1; s->alacarte_link = 1;
s->nocommon = 1; s->nocommon = 1;
s->warn_implicit_function_declaration = 1; s->warn_implicit_function_declaration = 1;
s->ms_bitfields = 0;
#ifdef CHAR_IS_UNSIGNED #ifdef CHAR_IS_UNSIGNED
s->char_is_unsigned = 1; s->char_is_unsigned = 1;
@ -1231,14 +1198,6 @@ typedef struct FlagDef {
const char *name; const char *name;
} FlagDef; } FlagDef;
static const FlagDef warning_defs[] = {
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" },
{ offsetof(TCCState, warn_write_strings), 0, "write-strings" },
{ offsetof(TCCState, warn_error), 0, "error" },
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
"implicit-function-declaration" },
};
static int no_flag(const char **pp) static int no_flag(const char **pp)
{ {
const char *p = *pp; const char *p = *pp;
@ -1248,73 +1207,35 @@ static int no_flag(const char **pp)
return 1; return 1;
} }
ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, int nb_flags, ST_FUNC int set_flag(TCCState *s, const FlagDef *flags, const char *name)
const char *name, int value)
{ {
int i; int value, ret;
const FlagDef *p; const FlagDef *p;
const char *r; const char *r;
value = 1;
r = name; r = name;
if (no_flag(&r)) if (no_flag(&r))
value = !value; value = 0;
for(i = 0, p = flags; i < nb_flags; i++, p++) { for (ret = -1, p = flags; p->name; ++p) {
if (!strcmp(r, p->name)) if (ret) {
goto found; if (strcmp(r, p->name))
} continue;
return -1; } else {
found: if (0 == (p->flags & WD_ALL))
if (p->flags & FD_INVERT) continue;
value = !value; }
*(int *)((uint8_t *)s + p->offset) = value; if (p->offset) {
return 0; *(int*)((char *)s + p->offset) =
} p->flags & FD_INVERT ? !value : value;
if (ret)
/* set/reset a warning */ return 0;
static int tcc_set_warning(TCCState *s, const char *warning_name, int value) } else {
{ ret = 0;
int i;
const FlagDef *p;
if (!strcmp(warning_name, "all")) {
for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
if (p->flags & WD_ALL)
*(int *)((uint8_t *)s + p->offset) = 1;
} }
return 0;
} else {
return set_flag(s, warning_defs, countof(warning_defs),
warning_name, value);
} }
} return ret;
static const FlagDef flag_defs[] = {
{ offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
{ offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
{ offsetof(TCCState, nocommon), FD_INVERT, "common" },
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
{ offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" },
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
};
/* set/reset a flag */
static int tcc_set_flag(TCCState *s, const char *flag_name, int value)
{
return set_flag(s, flag_defs, countof(flag_defs),
flag_name, value);
}
static const FlagDef m_defs[] = {
#ifdef TCC_TARGET_X86_64
{ offsetof(TCCState, nosse), FD_INVERT, "sse" },
#endif
{ 0, 0, " no flag" },
};
static int tcc_set_m_flag(TCCState *s, const char *flag_name, int value)
{
return set_flag(s, m_defs, countof(m_defs), flag_name, value);
} }
static int strstart(const char *val, const char **str) static int strstart(const char *val, const char **str)
@ -1517,7 +1438,6 @@ enum {
TCC_OPTION_c, TCC_OPTION_c,
TCC_OPTION_dumpversion, TCC_OPTION_dumpversion,
TCC_OPTION_d, TCC_OPTION_d,
TCC_OPTION_float_abi,
TCC_OPTION_static, TCC_OPTION_static,
TCC_OPTION_std, TCC_OPTION_std,
TCC_OPTION_shared, TCC_OPTION_shared,
@ -1530,7 +1450,7 @@ enum {
TCC_OPTION_Wp, TCC_OPTION_Wp,
TCC_OPTION_W, TCC_OPTION_W,
TCC_OPTION_O, TCC_OPTION_O,
TCC_OPTION_mms_bitfields, TCC_OPTION_mfloat_abi,
TCC_OPTION_m, TCC_OPTION_m,
TCC_OPTION_f, TCC_OPTION_f,
TCC_OPTION_isystem, TCC_OPTION_isystem,
@ -1578,9 +1498,6 @@ static const TCCOption tcc_options[] = {
{ "c", TCC_OPTION_c, 0 }, { "c", TCC_OPTION_c, 0 },
{ "dumpversion", TCC_OPTION_dumpversion, 0}, { "dumpversion", TCC_OPTION_dumpversion, 0},
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
#ifdef TCC_TARGET_ARM
{ "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG },
#endif
{ "static", TCC_OPTION_static, 0 }, { "static", TCC_OPTION_static, 0 },
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "shared", TCC_OPTION_shared, 0 }, { "shared", TCC_OPTION_shared, 0 },
@ -1598,8 +1515,10 @@ static const TCCOption tcc_options[] = {
{ "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "mms-bitfields", TCC_OPTION_mms_bitfields, 0}, /* must go before option 'm' */ #ifdef TCC_TARGET_ARM
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG }, { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG },
#endif
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG }, { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
{ "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG }, { "iwithprefix", TCC_OPTION_iwithprefix, TCC_OPTION_HAS_ARG },
@ -1617,6 +1536,35 @@ static const TCCOption tcc_options[] = {
{ NULL, 0, 0 }, { NULL, 0, 0 },
}; };
static const FlagDef options_W[] = {
{ 0, 0, "all" },
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" },
{ offsetof(TCCState, warn_write_strings), 0, "write-strings" },
{ offsetof(TCCState, warn_error), 0, "error" },
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
"implicit-function-declaration" },
{ 0, 0, NULL }
};
static const FlagDef options_f[] = {
{ offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
{ offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
{ offsetof(TCCState, nocommon), FD_INVERT, "common" },
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
{ offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" },
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
{ 0, 0, NULL }
};
static const FlagDef options_m[] = {
{ offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" },
#ifdef TCC_TARGET_X86_64
{ offsetof(TCCState, nosse), FD_INVERT, "sse" },
#endif
{ 0, 0, NULL }
};
static void parse_option_D(TCCState *s1, const char *optarg) static void parse_option_D(TCCState *s1, const char *optarg)
{ {
char *sym = tcc_strdup(optarg); char *sym = tcc_strdup(optarg);
@ -1766,18 +1714,6 @@ reparse:
else else
goto unsupported_option; goto unsupported_option;
break; break;
#ifdef TCC_TARGET_ARM
case TCC_OPTION_float_abi:
/* tcc doesn't support soft float yet */
if (!strcmp(optarg, "softfp")) {
s->float_abi = ARM_SOFTFP_FLOAT;
tcc_undefine_symbol(s, "__ARM_PCS_VFP");
} else if (!strcmp(optarg, "hard"))
s->float_abi = ARM_HARD_FLOAT;
else
tcc_error("unsupported float abi '%s'", optarg);
break;
#endif
case TCC_OPTION_static: case TCC_OPTION_static:
s->static_link = 1; s->static_link = 1;
break; break;
@ -1791,12 +1727,6 @@ reparse:
case TCC_OPTION_soname: case TCC_OPTION_soname:
s->soname = tcc_strdup(optarg); s->soname = tcc_strdup(optarg);
break; break;
case TCC_OPTION_m:
if (!strcmp(optarg, "32") || !strcmp(optarg, "64"))
s->option_m = tcc_strdup(optarg);
else if (tcc_set_m_flag(s, optarg, 1) < 0)
goto unsupported_option;
break;
case TCC_OPTION_o: case TCC_OPTION_o:
if (s->outfile) { if (s->outfile) {
tcc_warning("multiple -o option"); tcc_warning("multiple -o option");
@ -1841,11 +1771,31 @@ reparse:
do ++s->verbose; while (*optarg++ == 'v'); do ++s->verbose; while (*optarg++ == 'v');
break; break;
case TCC_OPTION_f: case TCC_OPTION_f:
if (tcc_set_flag(s, optarg, 1) < 0) if (set_flag(s, options_f, optarg) < 0)
goto unsupported_option;
break;
#ifdef TCC_TARGET_ARM
case TCC_OPTION_mfloat_abi:
/* tcc doesn't support soft float yet */
if (!strcmp(optarg, "softfp")) {
s->float_abi = ARM_SOFTFP_FLOAT;
tcc_undefine_symbol(s, "__ARM_PCS_VFP");
} else if (!strcmp(optarg, "hard"))
s->float_abi = ARM_HARD_FLOAT;
else
tcc_error("unsupported float abi '%s'", optarg);
break;
#endif
case TCC_OPTION_m:
if (set_flag(s, options_m, optarg) == 0)
break;
else if (x = atoi(optarg), x == 32 || x == 64)
s->cross_target = x;
else
goto unsupported_option; goto unsupported_option;
break; break;
case TCC_OPTION_W: case TCC_OPTION_W:
if (tcc_set_warning(s, optarg, 1) < 0) if (set_flag(s, options_W, optarg) < 0)
goto unsupported_option; goto unsupported_option;
break; break;
case TCC_OPTION_w: case TCC_OPTION_w:
@ -1893,9 +1843,6 @@ reparse:
case TCC_OPTION_O: case TCC_OPTION_O:
last_o = atoi(optarg); last_o = atoi(optarg);
break; break;
case TCC_OPTION_mms_bitfields:
s->ms_bitfields = 1;
break;
case TCC_OPTION_traditional: case TCC_OPTION_traditional:
case TCC_OPTION_pedantic: case TCC_OPTION_pedantic:
case TCC_OPTION_pipe: case TCC_OPTION_pipe:

38
tcc.c
View File

@ -97,16 +97,11 @@ static void help(void)
" -o outfile set output filename\n" " -o outfile set output filename\n"
" -run run compiled source\n" " -run run compiled source\n"
" -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n" " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
" -mms-bitfields use bitfield alignment consistent with MSVC\n"
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n" " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
" -w disable all warnings\n" " -w disable all warnings\n"
" -v show version\n" " -v show version\n"
" -vv show included files (as sole argument: show search paths)\n" " -vv show included files (as sole argument: show search paths)\n"
" -dumpversion\n"
" -bench show compilation statistics\n" " -bench show compilation statistics\n"
" -xc -xa specify type of the next infile\n"
" - use stdin pipe as infile\n"
" @listfile read arguments from listfile\n"
"Preprocessor options:\n" "Preprocessor options:\n"
" -Idir add include path 'dir'\n" " -Idir add include path 'dir'\n"
" -Dsym[=val] define 'sym' with value 'val'\n" " -Dsym[=val] define 'sym' with value 'val'\n"
@ -117,12 +112,12 @@ static void help(void)
"Linker options:\n" "Linker options:\n"
" -Ldir add library path 'dir'\n" " -Ldir add library path 'dir'\n"
" -llib link with dynamic or static library 'lib'\n" " -llib link with dynamic or static library 'lib'\n"
" -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
" -r generate (relocatable) object file\n" " -r generate (relocatable) object file\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -shared generate a shared library\n" " -shared generate a shared library\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -soname set name for shared library to be used at runtime\n" " -soname set name for shared library to be used at runtime\n"
" -static static linking\n" " -static static linking\n"
" -pthread link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
" -Wl,-opt[=val] set linker option (see manual)\n" " -Wl,-opt[=val] set linker option (see manual)\n"
"Debugger options:\n" "Debugger options:\n"
" -g generate runtime debug info\n" " -g generate runtime debug info\n"
@ -133,11 +128,24 @@ static void help(void)
" -bt N show N callers in stack traces\n" " -bt N show N callers in stack traces\n"
#endif #endif
"Misc options:\n" "Misc options:\n"
" -x[c|a|n] specify type of the next infile\n"
" -nostdinc do not use standard system include paths\n" " -nostdinc do not use standard system include paths\n"
" -nostdlib do not link with standard crt and libraries\n" " -nostdlib do not link with standard crt and libraries\n"
" -Bdir use 'dir' as tcc internal library and include path\n" " -Bdir use 'dir' as tcc's private library/include path\n"
" -MD generate target dependencies for make\n" " -MD generate target dependencies for make\n"
" -MF depfile put generated dependencies here\n" " -MF depfile put generated dependencies here\n"
" -dumpversion print version\n"
" - use stdin pipe as infile\n"
" @listfile read arguments from listfile\n"
"Target specific options:\n"
" -m32/64 execute i386/x86-64 cross compiler\n"
" -mms-bitfields use MSVC bitfield layout\n"
#ifdef TCC_TARGET_ARM
" -mfloat-abi hard/softfp on arm\n"
#endif
#ifdef TCC_TARGET_X86_64
" -mno-sse disable floats on x86-64\n"
#endif
); );
} }
@ -155,10 +163,10 @@ static int execvp_win32(const char *prog, char **argv)
} }
#define execvp execvp_win32 #define execvp execvp_win32
#endif #endif
static void exec_other_tcc(TCCState *s, char **argv, const char *optarg) static void exec_other_tcc(TCCState *s, char **argv, int option)
{ {
char child_path[4096], *child_name; const char *target; char child_path[4096], *child_name; const char *target;
switch (atoi(optarg)) { switch (option) {
#ifdef TCC_TARGET_I386 #ifdef TCC_TARGET_I386
case 32: break; case 32: break;
case 64: target = "x86_64"; case 64: target = "x86_64";
@ -179,14 +187,10 @@ static void exec_other_tcc(TCCState *s, char **argv, const char *optarg)
execvp(argv[0] = child_path, argv); execvp(argv[0] = child_path, argv);
} }
tcc_error("'%s' not found", child_name); tcc_error("'%s' not found", child_name);
case 0: /* ignore -march etc. */
break;
default:
tcc_warning("unsupported option \"-m%s\"", optarg);
} }
} }
#else #else
#define exec_other_tcc(s, argv, optarg) #define exec_other_tcc(s, argv, option)
#endif #endif
static void gen_makedeps(TCCState *s, const char *target, const char *filename) static void gen_makedeps(TCCState *s, const char *target, const char *filename)
@ -274,8 +278,8 @@ int main(int argc, char **argv)
return 1; return 1;
} }
if (s->option_m) if (s->cross_target)
exec_other_tcc(s, argv, s->option_m); exec_other_tcc(s, argv, s->cross_target);
if (s->verbose) if (s->verbose)
display_info(s, 0); display_info(s, 0);

2
tcc.h
View File

@ -762,7 +762,7 @@ struct TCCState {
int nb_libraries; /* number of libs thereof */ int nb_libraries; /* number of libs thereof */
int filetype; int filetype;
char *outfile; /* output filename */ char *outfile; /* output filename */
char *option_m; /* only -m32/-m64 handled */ int cross_target; /* -m32/-m64 */
int print_search_dirs; /* option */ int print_search_dirs; /* option */
int option_r; /* option -r */ int option_r; /* option -r */
int do_bench; /* option -bench */ int do_bench; /* option -bench */

View File

@ -186,13 +186,13 @@ tail_call:
#ifdef TAL_DEBUG #ifdef TAL_DEBUG
if (al->nb_allocs > 0) { if (al->nb_allocs > 0) {
uint8_t *p; uint8_t *p;
fprintf(stderr, "TAL_DEBUG: mem leak %d chunks (limit= %d)\n", fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n",
al->nb_allocs, al->limit); al->nb_allocs, al->limit);
p = al->buffer; p = al->buffer;
while (p < al->p) { while (p < al->p) {
tal_header_t *header = (tal_header_t *)p; tal_header_t *header = (tal_header_t *)p;
if (header->line_num > 0) { if (header->line_num > 0) {
fprintf(stderr, "%s:%d: chunk of %d bytes\n", fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n",
header->file_name, header->line_num, header->size); header->file_name, header->line_num, header->size);
} }
p += header->size + sizeof(tal_header_t); p += header->size + sizeof(tal_header_t);