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

14
configure vendored
View File

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

View File

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

View File

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

View File

@ -264,7 +264,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;
__attribute__((aligned(16))) unsigned magic3; ALIGNED(16) unsigned magic3;
}; };
typedef struct mem_debug_header mem_debug_header_t; 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 = bf->buffer + initlen;
bf->buf_end[0] = CH_EOB; /* put eob symbol */ bf->buf_end[0] = CH_EOB; /* put eob symbol */
pstrcpy(bf->filename, sizeof(bf->filename), filename); pstrcpy(bf->filename, sizeof(bf->filename), filename);
pstrcpy(bf->filename2, sizeof(bf->filename2), filename); bf->true_filename = bf->filename;
#ifdef _WIN32
normalize_slashes(bf->filename);
#endif
bf->line_num = 1; bf->line_num = 1;
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr; bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
bf->fd = -1; bf->fd = -1;
@ -599,6 +596,8 @@ ST_FUNC void tcc_close(void)
close(bf->fd); close(bf->fd);
total_lines += bf->line_num; total_lines += bf->line_num;
} }
if (bf->true_filename != bf->filename)
tcc_free(bf->true_filename);
file = bf->prev; file = bf->prev;
tcc_free(bf); 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); (int)(s1->include_stack_ptr - s1->include_stack), "", filename);
if (fd < 0) if (fd < 0)
return -1; return -1;
tcc_open_bf(s1, filename, 0); tcc_open_bf(s1, filename, 0);
#ifdef _WIN32
normalize_slashes(file->filename);
#endif
file->fd = fd; file->fd = fd;
return fd; return fd;
} }
@ -737,6 +738,7 @@ 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_extensions = 1;
#ifdef CHAR_IS_UNSIGNED #ifdef CHAR_IS_UNSIGNED
s->char_is_unsigned = 1; s->char_is_unsigned = 1;

22
tcc.h
View File

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

View File

@ -1752,8 +1752,8 @@ static void gen_opic(int op)
vtop--; vtop--;
} else if (!const_wanted && } else if (!const_wanted &&
c2 && ((l2 == 0 && (op == '&' || op == '*')) || c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
(l2 == -1 && op == '|') || (op == '|' &&
(l2 == 0xffffffff && t2 != VT_LLONG && op == '|') || (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) ||
(l2 == 1 && (op == '%' || op == TOK_UMOD)))) { (l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
/* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */ /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */
if (l2 == 1) if (l2 == 1)
@ -1767,7 +1767,7 @@ static void gen_opic(int op)
op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
l2 == 0) || l2 == 0) ||
(op == '&' && (op == '&' &&
l2 == -1))) { (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) {
/* filter out NOP operations like x*1, x-0, x&-1... */ /* filter out NOP operations like x*1, x-0, x&-1... */
vtop--; vtop--;
} else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
@ -1817,6 +1817,10 @@ static void gen_opif(int op)
{ {
int c1, c2; int c1, c2;
SValue *v1, *v2; 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; long double f1, f2;
v1 = vtop - 1; v1 = vtop - 1;
@ -3497,7 +3501,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (v < TOK_IDENT) if (v < TOK_IDENT)
expect("struct/union/enum name"); expect("struct/union/enum name");
s = struct_find(v); s = struct_find(v);
if (s && (s->scope == local_scope || (tok != '{' && tok != ';'))) { if (s && (s->scope == local_scope || tok != '{')) {
if (s->type.t != a) if (s->type.t != a)
tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
goto do_decl; goto do_decl;
@ -4381,6 +4385,8 @@ ST_FUNC void unary(void)
case TOK_STR: case TOK_STR:
/* string parsing */ /* string parsing */
t = VT_BYTE; t = VT_BYTE;
if (tcc_state->char_is_unsigned)
t = VT_BYTE | VT_UNSIGNED;
str_init: str_init:
if (tcc_state->warn_write_strings) if (tcc_state->warn_write_strings)
t |= VT_CONSTANT; 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_DOS_HEADER dh;
IMAGE_FILE_HEADER ih; IMAGE_FILE_HEADER ih;
DWORD sig, ref, addr, ptr, namep; 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; int pef_hdroffset, opt_hdroffset, sec_hdroffset;
n = n0 = 0; n = n0 = 0;
@ -1562,7 +1558,6 @@ PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
if (fd < 0) if (fd < 0)
goto the_end_1; goto the_end_1;
ret = 1; ret = 1;
if (!read_mem(fd, 0, &dh, sizeof dh)) if (!read_mem(fd, 0, &dh, sizeof dh))
goto the_end; goto the_end;
if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig)) 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; pef_hdroffset = dh.e_lfanew + sizeof sig;
if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih)) if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
goto the_end; 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; opt_hdroffset = pef_hdroffset + sizeof ih;
sec_hdroffset = opt_hdroffset + sizeof oh; if (ih.Machine == 0x014C) {
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh)) 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; 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); //printf("addr: %08x\n", addr);
for (i = 0; i < ih.NumberOfSections; ++i) { for (i = 0; i < ih.NumberOfSections; ++i) {
if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish)) 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; break;
/* above tokens have value, the ones below don't */ /* above tokens have value, the ones below don't */
case TOK_LT: case TOK_LT:
v = '<'; v = '<';
goto addv; goto addv;
@ -544,6 +543,8 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
return strcpy(p, "<<="); return strcpy(p, "<<=");
case TOK_A_SAR: case TOK_A_SAR:
return strcpy(p, ">>="); return strcpy(p, ">>=");
case TOK_EOF:
return strcpy(p, "<eof>");
default: default:
if (v < TOK_IDENT) { if (v < TOK_IDENT) {
/* search in two bytes table */ /* search in two bytes table */
@ -1791,7 +1792,7 @@ ST_FUNC void preprocess(int is_bof)
if (c != '\"') if (c != '\"')
continue; continue;
/* https://savannah.nongnu.org/bugs/index.php?50847 */ /* https://savannah.nongnu.org/bugs/index.php?50847 */
path = file->filename2; path = file->true_filename;
pstrncpy(buf1, path, tcc_basename(path) - path); pstrncpy(buf1, path, tcc_basename(path) - path);
} else { } else {
@ -1921,9 +1922,11 @@ include_done:
_line_num: _line_num:
next(); next();
if (tok != TOK_LINEFEED) { 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); 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; break;
else else
goto _line_err; goto _line_err;

View File

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

View File

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