unsorted adjustments

- configure
  * use aarch64 instead of arm64

- Makefile
  * rename the custom include file to "config-extra.mak"
  * Also avoid "rm -r /*" if $(tccdir) is empty

- pp/Makefile
  * fix .expect generation with gcc

- tcc.h
  * cleanup #defines for _MSC_VER

- tccgen.c:
  * fix const-propagation for &,|
  * fix anonymous named struct (ms-extension) and enable
    -fms-extension by default

- i386-gen.c
  * clear VT_DEFSIGN

- x86_64-gen.c/win64:
  * fix passing structs in registers
  * fix alloca (need to keep "func_scratch" below each alloca area on stack)
    (This allows to compile a working gnu-make on win64)

- tccpp.c
  * alternative approach to 37999a4fbf
    This is to avoid some slowdown with ## token pasting.
  * get_tok_str() : return <eof> for TOK_EOF
  * -funsigned-char: apply to "string" literals as well

- tccpe/tools.c: -impdef: support both 32 and 64 bit dlls anyway
master
grischka 2017-07-09 12:07:40 +02:00
parent 6c468c10f7
commit 9f79b62ec4
11 changed files with 105 additions and 80 deletions

View File

@ -151,8 +151,8 @@ DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
endif
endif
# include custom cross-compiler configuration (see make help)
-include config-cross.mak
# include custom configuration (see make help)
-include config-extra.mak
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c tccrun.c
CORE_FILES += tcc.h config.h libtcc.h tcctok.h
@ -318,7 +318,7 @@ install-win : INSTALL = cp
# uninstall on windows
uninstall-win:
rm -r "$(tccdir)/"*
rm -r "$(tccdir)"
# --------------------------------------------------------------------------
# other stuff
@ -374,19 +374,24 @@ help:
@echo " build one specific cross compiler for 'TARGET', as in"
@echo " $(TCC_X)"
@echo ""
@echo "Cross compiler configuration:"
@echo " make will read custom configuration for cross compilers from a file"
@echo " 'config-cross.mak' if present. For example for a windows->i386-linux"
@echo " cross-compiler that expects the linux files in <tccdir>/i386-linux:"
@echo "Custom configuration:"
@echo " The makefile includes a file 'config-extra.mak' if it is present."
@echo " This file may contain some custom configuration. For example:"
@echo ""
@echo " ROOT-i386 = {B}/i386-linux"
@echo " CRT-i386 = {B}/i386-linux/usr/lib"
@echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib"
@echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include"
@echo " DEF-i386 += -D__linux__"
@echo " NATIVE_DEFINES += -D..."
@echo ""
@echo " Or for example to configure the search paths for a cross-compiler"
@echo " that expects the linux files in <tccdir>/i386-linux:"
@echo ""
@echo " ROOT-i386 = {B}/i386-linux"
@echo " CRT-i386 = {B}/i386-linux/usr/lib"
@echo " LIB-i386 = {B}/i386-linux/lib:{B}/i386-linux/usr/lib"
@echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include"
@echo " DEF-i386 += -D__linux__"
@echo ""
@echo "Other supported make targets:"
@echo " install install-strip test tags ETAGS tar clean distclean help"
@echo ""
# --------------------------------------------------------------------------
endif # ($(INCLUDED),no)

14
configure vendored
View File

@ -161,7 +161,7 @@ fi
case "$cpu" in
x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
cpu="x86"
cpu="i386"
;;
x86_64|amd64|x86-64)
cpu="x86_64"
@ -184,7 +184,7 @@ case "$cpu" in
cpu="arm"
;;
aarch64)
cpu="arm64"
cpu="aarch64"
;;
alpha)
cpu="alpha"
@ -301,7 +301,7 @@ Advanced options (experts only):
--disable-static make libtcc.so instead of libtcc.a
--enable-static make libtcc.a instead of libtcc.dll (win32)
--disable-rpath disable use of -rpath with the above
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a in dynamic link
--with-libgcc use libgcc_s.so.1 instead of libtcc1.a
--enable-mingw32 build windows version on linux with mingw32
--enable-cross build cross compilers
--with-selinux use mmap for executable memory (with tcc -run)
@ -340,7 +340,7 @@ if test -z "$cross_prefix" ; then
fi
if test -z "$triplet"; then
if test $cpu = "x86_64" -o $cpu = "arm64" ; then
if test $cpu = "x86_64" -o $cpu = "aarch64" ; then
if test -f "/usr/lib64/crti.o" ; then
tcc_lddir="lib64"
fi
@ -473,13 +473,11 @@ print_mak_int TCC_CPU_VERSION "$cpuver"
echo "#define GCC_MAJOR $gcc_major" >> $TMPH
echo "#define GCC_MINOR $gcc_minor" >> $TMPH
if test "$cpu" = "x86" ; then
echo "ARCH=i386" >> config.mak
if test "$cpu" = "aarch64" ; then
echo "ARCH=arm64" >> config.mak
else
echo "ARCH=$cpu" >> config.mak
fi
echo "TARGETOS=$targetos" >> config.mak
for v in $confvars ; do

View File

@ -210,7 +210,7 @@ ST_FUNC void load(int r, SValue *sv)
#endif
fr = sv->r;
ft = sv->type.t;
ft = sv->type.t & ~VT_DEFSIGN;
fc = sv->c.i;
ft &= ~(VT_VOLATILE | VT_CONSTANT);

View File

@ -27,10 +27,6 @@ p2:
sub %rax,%rsp
mov %rsp,%rax
#ifdef TCC_TARGET_PE
add $32,%rax
#endif
p3:
push %rdx
ret

View File

@ -264,7 +264,7 @@ struct mem_debug_header {
int line_num;
char file_name[MEM_DEBUG_FILE_LEN + 1];
unsigned magic2;
__attribute__((aligned(16))) unsigned magic3;
ALIGNED(16) unsigned magic3;
};
typedef struct mem_debug_header mem_debug_header_t;
@ -581,10 +581,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
bf->buf_end = bf->buffer + initlen;
bf->buf_end[0] = CH_EOB; /* put eob symbol */
pstrcpy(bf->filename, sizeof(bf->filename), filename);
pstrcpy(bf->filename2, sizeof(bf->filename2), filename);
#ifdef _WIN32
normalize_slashes(bf->filename);
#endif
bf->true_filename = bf->filename;
bf->line_num = 1;
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
bf->fd = -1;
@ -599,6 +596,8 @@ ST_FUNC void tcc_close(void)
close(bf->fd);
total_lines += bf->line_num;
}
if (bf->true_filename != bf->filename)
tcc_free(bf->true_filename);
file = bf->prev;
tcc_free(bf);
}
@ -615,8 +614,10 @@ ST_FUNC int tcc_open(TCCState *s1, const char *filename)
(int)(s1->include_stack_ptr - s1->include_stack), "", filename);
if (fd < 0)
return -1;
tcc_open_bf(s1, filename, 0);
#ifdef _WIN32
normalize_slashes(file->filename);
#endif
file->fd = fd;
return fd;
}
@ -737,6 +738,7 @@ LIBTCCAPI TCCState *tcc_new(void)
s->alacarte_link = 1;
s->nocommon = 1;
s->warn_implicit_function_declaration = 1;
s->ms_extensions = 1;
#ifdef CHAR_IS_UNSIGNED
s->char_is_unsigned = 1;

22
tcc.h
View File

@ -41,10 +41,11 @@
# include <dlfcn.h>
# endif
/* XXX: need to define this to use them in non ISOC99 context */
extern float strtof (const char *__nptr, char **__endptr);
extern long double strtold (const char *__nptr, char **__endptr);
extern float strtof (const char *__nptr, char **__endptr);
extern long double strtold (const char *__nptr, char **__endptr);
#endif
#else /* on _WIN32: */
#ifdef _WIN32
# include <windows.h>
# include <io.h> /* open, close etc. */
# include <direct.h> /* getcwd */
@ -52,7 +53,6 @@
# include <stdint.h>
# endif
# define inline __inline
# define inp next_inp /* inp is an intrinsic on msvc */
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# ifndef __GNUC__
@ -65,6 +65,7 @@
# define LIBTCCAPI __declspec(dllexport)
# define PUB_FUNC LIBTCCAPI
# endif
# define inp next_inp /* inp is an intrinsic on msvc/mingw */
# ifdef _MSC_VER
# pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data
# pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data
@ -72,9 +73,6 @@
# pragma warning (disable : 4018) // signed/unsigned mismatch
# pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
# define ssize_t intptr_t
# define __attribute__(x) __declspec x
# define aligned align
# else
# endif
# undef CONFIG_TCC_STATIC
#endif
@ -83,12 +81,12 @@
# define O_BINARY 0
#endif
#ifdef __GNUC__
# define NORETURN __attribute__ ((noreturn))
#elif defined _MSC_VER
#ifdef _MSC_VER
# define NORETURN __declspec(noreturn)
# define ALIGNED(x) __declspec(align(x))
#else
# define NORETURN
# define NORETURN __attribute__((noreturn))
# define ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifdef _WIN32
@ -540,7 +538,7 @@ typedef struct BufferedFile {
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
int include_next_index; /* next search path */
char filename[1024]; /* filename */
char filename2[1024]; /* filename not modified by # line directive */
char *true_filename; /* filename not modified by # line directive */
unsigned char unget[4];
unsigned char buffer[1]; /* extra size for CH_EOB char */
} BufferedFile;

View File

@ -1752,8 +1752,8 @@ static void gen_opic(int op)
vtop--;
} else if (!const_wanted &&
c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
(l2 == -1 && op == '|') ||
(l2 == 0xffffffff && t2 != VT_LLONG && op == '|') ||
(op == '|' &&
(l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) ||
(l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
/* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */
if (l2 == 1)
@ -1767,7 +1767,7 @@ static void gen_opic(int op)
op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
l2 == 0) ||
(op == '&' &&
l2 == -1))) {
(l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) {
/* filter out NOP operations like x*1, x-0, x&-1... */
vtop--;
} else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
@ -1817,6 +1817,10 @@ static void gen_opif(int op)
{
int c1, c2;
SValue *v1, *v2;
#if defined _MSC_VER && defined _AMD64_
/* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */
volatile
#endif
long double f1, f2;
v1 = vtop - 1;
@ -3497,7 +3501,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (v < TOK_IDENT)
expect("struct/union/enum name");
s = struct_find(v);
if (s && (s->scope == local_scope || (tok != '{' && tok != ';'))) {
if (s && (s->scope == local_scope || tok != '{')) {
if (s->type.t != a)
tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
goto do_decl;
@ -4381,6 +4385,8 @@ ST_FUNC void unary(void)
case TOK_STR:
/* string parsing */
t = VT_BYTE;
if (tcc_state->char_is_unsigned)
t = VT_BYTE | VT_UNSIGNED;
str_init:
if (tcc_state->warn_write_strings)
t |= VT_CONSTANT;

37
tccpe.c
View File

@ -1547,11 +1547,7 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
IMAGE_DOS_HEADER dh;
IMAGE_FILE_HEADER ih;
DWORD sig, ref, addr, ptr, namep;
#ifdef TCC_TARGET_X86_64
IMAGE_OPTIONAL_HEADER64 oh;
#else
IMAGE_OPTIONAL_HEADER32 oh;
#endif
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
n = n0 = 0;
@ -1562,7 +1558,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
if (fd < 0)
goto the_end_1;
ret = 1;
if (!read_mem(fd, 0, &dh, sizeof dh))
goto the_end;
if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
@ -1572,22 +1567,26 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
pef_hdroffset = dh.e_lfanew + sizeof sig;
if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
goto the_end;
if (IMAGE_FILE_MACHINE != ih.Machine) {
if (ih.Machine == 0x014C)
ret = 32;
else if (ih.Machine == 0x8664)
ret = 64;
goto the_end;
}
opt_hdroffset = pef_hdroffset + sizeof ih;
sec_hdroffset = opt_hdroffset + sizeof oh;
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
if (ih.Machine == 0x014C) {
IMAGE_OPTIONAL_HEADER32 oh;
sec_hdroffset = opt_hdroffset + sizeof oh;
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
goto the_end;
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
goto the_end_0;
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
} else if (ih.Machine == 0x8664) {
IMAGE_OPTIONAL_HEADER64 oh;
sec_hdroffset = opt_hdroffset + sizeof oh;
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
goto the_end;
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
goto the_end_0;
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
} else
goto the_end;
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
goto the_end_0;
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
//printf("addr: %08x\n", addr);
for (i = 0; i < ih.NumberOfSections; ++i) {
if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))

11
tccpp.c
View File

@ -531,7 +531,6 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
break;
/* above tokens have value, the ones below don't */
case TOK_LT:
v = '<';
goto addv;
@ -544,6 +543,8 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
return strcpy(p, "<<=");
case TOK_A_SAR:
return strcpy(p, ">>=");
case TOK_EOF:
return strcpy(p, "<eof>");
default:
if (v < TOK_IDENT) {
/* search in two bytes table */
@ -1791,7 +1792,7 @@ ST_FUNC void preprocess(int is_bof)
if (c != '\"')
continue;
/* https://savannah.nongnu.org/bugs/index.php?50847 */
path = file->filename2;
path = file->true_filename;
pstrncpy(buf1, path, tcc_basename(path) - path);
} else {
@ -1921,9 +1922,11 @@ include_done:
_line_num:
next();
if (tok != TOK_LINEFEED) {
if (tok == TOK_STR)
if (tok == TOK_STR) {
if (file->true_filename == file->filename)
file->true_filename = tcc_strdup(file->filename);
pstrcpy(file->filename, sizeof(file->filename), (char *)tokc.str.data);
else if (parse_flags & PARSE_FLAG_ASM_FILE)
} else if (parse_flags & PARSE_FLAG_ASM_FILE)
break;
else
goto _line_err;

View File

@ -363,9 +363,8 @@ usage:
ret = tcc_get_dllexports(file, &p);
if (ret || !p) {
fprintf(stderr, "tcc: impdef: %s '%s'\n",
ret == 32 ? "can't read symbols from 32bit" :
ret == 64 ? "can't read symbols from 64bit" :
ret == -1 ? "can't find file" :
ret == 1 ? "can't read symbols" :
ret == 0 ? "no symbols found in" :
"unknown file type", file);
ret = 1;

View File

@ -728,13 +728,13 @@ static int arg_prepare_reg(int idx) {
return arg_regs[idx];
}
static int func_scratch;
static int func_scratch, func_alloca;
/* Generate function call. The function address is pushed first, then
all the parameters in call order. This functions pops all the
parameters and the function address. */
void gen_offs_sp(int b, int r, int d)
static void gen_offs_sp(int b, int r, int d)
{
orex(1,0,r & 0x100 ? 0 : r, b);
if (d == (char)d) {
@ -746,6 +746,11 @@ void gen_offs_sp(int b, int r, int d)
}
}
static int using_regs(int size)
{
return !(size > 8 || (size & (size - 1)));
}
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
@ -754,7 +759,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int
*ret_align = 1; // Never have to re-align return values for x86-64
*regsize = 8;
size = type_size(vt, &align);
if (size > 8 || (size & (size - 1)))
if (!using_regs(size))
return 0;
if (size == 8)
ret->t = VT_LLONG;
@ -774,7 +779,7 @@ static int is_sse_float(int t) {
return bt == VT_DOUBLE || bt == VT_FLOAT;
}
int gfunc_arg_size(CType *type) {
static int gfunc_arg_size(CType *type) {
int align;
if (type->t & (VT_ARRAY|VT_BITFIELD))
return 8;
@ -801,7 +806,7 @@ void gfunc_call(int nb_args)
bt = (sv->type.t & VT_BTYPE);
size = gfunc_arg_size(&sv->type);
if (size <= 8)
if (using_regs(size))
continue; /* arguments smaller than 8 bytes passed in registers or on stack */
if (bt == VT_STRUCT) {
@ -835,7 +840,7 @@ void gfunc_call(int nb_args)
bt = (vtop->type.t & VT_BTYPE);
size = gfunc_arg_size(&vtop->type);
if (size > 8) {
if (!using_regs(size)) {
/* align to stack align size */
size = (size + 15) & ~15;
if (arg >= REGN) {
@ -895,6 +900,12 @@ void gfunc_call(int nb_args)
}
gcall_or_jmp(0);
if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) {
/* need to add the "func_scratch" area after alloca */
o(0x0548), gen_le32(func_alloca), func_alloca = ind - 4;
}
/* other compilers don't clear the upper bits when returning char/short */
bt = vtop->type.ref->type.t & (VT_BTYPE | VT_UNSIGNED);
if (bt == (VT_BYTE | VT_UNSIGNED))
@ -926,6 +937,7 @@ void gfunc_prolog(CType *func_type)
func_ret_sub = 0;
func_scratch = 0;
func_alloca = 0;
loc = 0;
addr = PTR_SIZE * 2;
@ -940,7 +952,7 @@ void gfunc_prolog(CType *func_type)
func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS);
size = gfunc_arg_size(&func_vt);
if (size > 8) {
if (!using_regs(size)) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
func_vc = addr;
reg_param_index++;
@ -952,7 +964,7 @@ void gfunc_prolog(CType *func_type)
type = &sym->type;
bt = type->t & VT_BTYPE;
size = gfunc_arg_size(type);
if (size > 8) {
if (!using_regs(size)) {
if (reg_param_index < REGN) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
}
@ -1015,6 +1027,13 @@ void gfunc_epilog(void)
gen_le32(v);
}
/* add the "func_scratch" area after each alloca seen */
while (func_alloca) {
unsigned char *ptr = cur_text_section->data + func_alloca;
func_alloca = read32le(ptr);
write32le(ptr, func_scratch);
}
cur_text_section->data_offset = saved_ind;
pe_add_unwind_data(ind, saved_ind, v);
ind = cur_text_section->data_offset;