tccgen: x86_64: fix garbage in the SValue upper bits
This was going wrong (case TOK_LAND in unary: computed labels)
- vset(&s->type, VT_CONST | VT_SYM, 0);
- vtop->sym = s;
This does the right thing and is shorter:
+ vpushsym(&s->type, s);
Test case was:
int main(int argc, char **argv)
{
int x;
static void *label_return = &&lbl_return;
printf("label_return = %p\n", label_return);
goto *label_return; //<<<<< here segfault on linux X86_64 without the memset on vset
printf("unreachable\n");
lbl_return:
return 0;
}
Also::
- Rename "void* CValue.ptr" to more usable "addr_t ptr_offset"
and start to use it in obvious cases.
- use __attribute__ ((noreturn)) only with gnu compiler
- Revert CValue memsets ("After several days searching ...")
commit 4bc83ac393
Doesn't mean that the vsetX/vpush thingy isn't brittle and
there still might be bugs as to differences in how the CValue
union was set and is then interpreted later on.
However the big memset hammer was just too slow (-3% overall).
This commit is contained in:
76
tcc.h
76
tcc.h
@ -55,18 +55,27 @@
|
|||||||
# ifndef CONFIG_TCC_STATIC
|
# ifndef CONFIG_TCC_STATIC
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
# endif
|
# endif
|
||||||
#else
|
/* 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);
|
||||||
|
#else /* on _WIN32: */
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <sys/timeb.h>
|
# include <sys/timeb.h>
|
||||||
# include <io.h> /* open, close etc. */
|
# include <io.h> /* open, close etc. */
|
||||||
# include <direct.h> /* getcwd */
|
# include <direct.h> /* getcwd */
|
||||||
# ifdef __GNUC__
|
# ifdef __GNUC__
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# else
|
|
||||||
typedef UINT_PTR uintptr_t;
|
|
||||||
# endif
|
# endif
|
||||||
# define inline __inline
|
# define inline __inline
|
||||||
# define inp next_inp
|
# define inp next_inp
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
# ifndef __GNUC__
|
||||||
|
# define strtold (long double)strtod
|
||||||
|
# define strtof (float)strtod
|
||||||
|
# define strtoll _strtoi64
|
||||||
|
# define strtoull _strtoui64
|
||||||
|
# endif
|
||||||
# ifdef LIBTCC_AS_DLL
|
# ifdef LIBTCC_AS_DLL
|
||||||
# define LIBTCCAPI __declspec(dllexport)
|
# define LIBTCCAPI __declspec(dllexport)
|
||||||
# define PUB_FUNC LIBTCCAPI
|
# define PUB_FUNC LIBTCCAPI
|
||||||
@ -79,6 +88,30 @@
|
|||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define NORETURN __attribute__ ((noreturn))
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
# define NORETURN __declspec(noreturn)
|
||||||
|
#else
|
||||||
|
# define NORETURN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define IS_DIRSEP(c) (c == '/' || c == '\\')
|
||||||
|
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
|
||||||
|
# define PATHCMP stricmp
|
||||||
|
#else
|
||||||
|
# define IS_DIRSEP(c) (c == '/')
|
||||||
|
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
|
||||||
|
# define PATHCMP strcmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_PE
|
||||||
|
#define PATHSEP ';'
|
||||||
|
#else
|
||||||
|
#define PATHSEP ':'
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
# define ELFCLASSW ELFCLASS64
|
# define ELFCLASSW ELFCLASS64
|
||||||
@ -315,7 +348,7 @@ typedef union CValue {
|
|||||||
long long ll;
|
long long ll;
|
||||||
unsigned long long ull;
|
unsigned long long ull;
|
||||||
struct CString *cstr;
|
struct CString *cstr;
|
||||||
void *ptr;
|
addr_t ptr_offset;
|
||||||
int tab[LDOUBLE_SIZE/4];
|
int tab[LDOUBLE_SIZE/4];
|
||||||
} CValue;
|
} CValue;
|
||||||
|
|
||||||
@ -938,37 +971,6 @@ enum tcc_token {
|
|||||||
|
|
||||||
#define TOK_UIDENT TOK_DEFINE
|
#define TOK_UIDENT TOK_DEFINE
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#define vsnprintf _vsnprintf
|
|
||||||
#ifndef __GNUC__
|
|
||||||
# define strtold (long double)strtod
|
|
||||||
# define strtof (float)strtod
|
|
||||||
# define strtoll _strtoi64
|
|
||||||
# define strtoull _strtoui64
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
/* 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);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define IS_DIRSEP(c) (c == '/' || c == '\\')
|
|
||||||
#define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
|
|
||||||
#define PATHCMP stricmp
|
|
||||||
#else
|
|
||||||
#define IS_DIRSEP(c) (c == '/')
|
|
||||||
#define IS_ABSPATH(p) IS_DIRSEP(p[0])
|
|
||||||
#define PATHCMP strcmp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
#define PATHSEP ';'
|
|
||||||
#else
|
|
||||||
#define PATHSEP ':'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* space exlcuding newline */
|
/* space exlcuding newline */
|
||||||
static inline int is_space(int ch)
|
static inline int is_space(int ch)
|
||||||
{
|
{
|
||||||
@ -1045,7 +1047,7 @@ PUB_FUNC char *tcc_strdup(const char *str);
|
|||||||
#define strdup(s) use_tcc_strdup(s)
|
#define strdup(s) use_tcc_strdup(s)
|
||||||
PUB_FUNC void tcc_memstats(void);
|
PUB_FUNC void tcc_memstats(void);
|
||||||
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
PUB_FUNC void tcc_error_noabort(const char *fmt, ...);
|
||||||
PUB_FUNC void tcc_error(const char *fmt, ...) __attribute__ ((noreturn));
|
PUB_FUNC NORETURN void tcc_error(const char *fmt, ...);
|
||||||
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
PUB_FUNC void tcc_warning(const char *fmt, ...);
|
||||||
|
|
||||||
/* other utilities */
|
/* other utilities */
|
||||||
@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1);
|
|||||||
ST_FUNC void preprocess_new(void);
|
ST_FUNC void preprocess_new(void);
|
||||||
ST_FUNC int tcc_preprocess(TCCState *s1);
|
ST_FUNC int tcc_preprocess(TCCState *s1);
|
||||||
ST_FUNC void skip(int c);
|
ST_FUNC void skip(int c);
|
||||||
ST_FUNC void expect(const char *msg) __attribute__ ((noreturn));
|
ST_FUNC NORETURN void expect(const char *msg);
|
||||||
|
|
||||||
/* ------------ tccgen.c ------------ */
|
/* ------------ tccgen.c ------------ */
|
||||||
|
|
||||||
|
|||||||
30
tccgen.c
30
tccgen.c
@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc)
|
|||||||
void vpush(CType *type)
|
void vpush(CType *type)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
vsetc(type, VT_CONST, &cval);
|
vsetc(type, VT_CONST, &cval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,29 +336,23 @@ void vpush(CType *type)
|
|||||||
ST_FUNC void vpushi(int v)
|
ST_FUNC void vpushi(int v)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
cval.i = v;
|
cval.i = v;
|
||||||
vsetc(&int_type, VT_CONST, &cval);
|
vsetc(&int_type, VT_CONST, &cval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a pointer sized constant */
|
/* push a pointer sized constant */
|
||||||
static void vpushs(long long v)
|
static void vpushs(addr_t v)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
cval.ptr_offset = v;
|
||||||
if (PTR_SIZE == 4)
|
|
||||||
cval.i = (int)v;
|
|
||||||
else
|
|
||||||
cval.ull = v;
|
|
||||||
vsetc(&size_type, VT_CONST, &cval);
|
vsetc(&size_type, VT_CONST, &cval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push arbitrary 64bit constant */
|
/* push arbitrary 64bit constant */
|
||||||
void vpush64(int ty, unsigned long long v)
|
void vpush64(int ty, unsigned long long v)
|
||||||
{
|
{
|
||||||
CType ctype;
|
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
CType ctype;
|
||||||
ctype.t = ty;
|
ctype.t = ty;
|
||||||
ctype.ref = NULL;
|
ctype.ref = NULL;
|
||||||
cval.ull = v;
|
cval.ull = v;
|
||||||
@ -376,9 +369,7 @@ static inline void vpushll(long long v)
|
|||||||
static inline void vpushsym(CType *type, Sym *sym)
|
static inline void vpushsym(CType *type, Sym *sym)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
cval.ptr_offset = 0;
|
||||||
|
|
||||||
cval.ull = 0;
|
|
||||||
vsetc(type, VT_CONST | VT_SYM, &cval);
|
vsetc(type, VT_CONST | VT_SYM, &cval);
|
||||||
vtop->sym = sym;
|
vtop->sym = sym;
|
||||||
}
|
}
|
||||||
@ -451,7 +442,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v)
|
|||||||
ST_FUNC void vset(CType *type, int r, int v)
|
ST_FUNC void vset(CType *type, int r, int v)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
cval.i = v;
|
cval.i = v;
|
||||||
vsetc(type, r, &cval);
|
vsetc(type, r, &cval);
|
||||||
@ -737,7 +727,6 @@ ST_FUNC int gv(int rc)
|
|||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
|
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
|
||||||
CValue check;
|
CValue check;
|
||||||
memset(&check, 0, sizeof(CValue));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* XXX: unify with initializers handling ? */
|
/* XXX: unify with initializers handling ? */
|
||||||
@ -770,7 +759,7 @@ ST_FUNC int gv(int rc)
|
|||||||
sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
|
sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
|
||||||
vtop->r |= VT_LVAL | VT_SYM;
|
vtop->r |= VT_LVAL | VT_SYM;
|
||||||
vtop->sym = sym;
|
vtop->sym = sym;
|
||||||
vtop->c.ull = 0;
|
vtop->c.ptr_offset = 0;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
if (vtop->r & VT_MUSTBOUND)
|
||||||
@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p)
|
|||||||
return 0;
|
return 0;
|
||||||
return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
|
return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
|
||||||
((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) ||
|
((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) ||
|
||||||
((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0);
|
((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_integer_btype(int bt)
|
static inline int is_integer_btype(int bt)
|
||||||
@ -3886,8 +3875,7 @@ ST_FUNC void unary(void)
|
|||||||
mk_pointer(&s->type);
|
mk_pointer(&s->type);
|
||||||
s->type.t |= VT_STATIC;
|
s->type.t |= VT_STATIC;
|
||||||
}
|
}
|
||||||
vset(&s->type, VT_CONST | VT_SYM, 0);
|
vpushsym(&s->type, s);
|
||||||
vtop->sym = s;
|
|
||||||
next();
|
next();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3939,7 +3927,7 @@ ST_FUNC void unary(void)
|
|||||||
/* if forward reference, we must point to s */
|
/* if forward reference, we must point to s */
|
||||||
if (vtop->r & VT_SYM) {
|
if (vtop->r & VT_SYM) {
|
||||||
vtop->sym = s;
|
vtop->sym = s;
|
||||||
vtop->c.ull = 0;
|
vtop->c.ptr_offset = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
|
|||||||
if (vtop->r & VT_SYM) {
|
if (vtop->r & VT_SYM) {
|
||||||
greloc(sec, vtop->sym, c, R_DATA_PTR);
|
greloc(sec, vtop->sym, c, R_DATA_PTR);
|
||||||
}
|
}
|
||||||
*(addr_t *)ptr |= (vtop->c.ull & bit_mask) << bit_pos;
|
*(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (vtop->r & VT_SYM) {
|
if (vtop->r & VT_SYM) {
|
||||||
|
|||||||
16
tccpp.c
16
tccpp.c
@ -974,7 +974,6 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
|||||||
ST_FUNC void tok_str_add_tok(TokenString *s)
|
ST_FUNC void tok_str_add_tok(TokenString *s)
|
||||||
{
|
{
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
/* save line number info */
|
/* save line number info */
|
||||||
if (file->line_num != s->last_line_num) {
|
if (file->line_num != s->last_line_num) {
|
||||||
@ -1038,9 +1037,8 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv)
|
|||||||
static int macro_is_equal(const int *a, const int *b)
|
static int macro_is_equal(const int *a, const int *b)
|
||||||
{
|
{
|
||||||
char buf[STRING_MAX_SIZE + 1];
|
char buf[STRING_MAX_SIZE + 1];
|
||||||
int t;
|
|
||||||
CValue cv;
|
CValue cv;
|
||||||
memset(&cv, 0, sizeof(CValue));
|
int t;
|
||||||
while (*a && *b) {
|
while (*a && *b) {
|
||||||
TOK_GET(&t, &a, &cv);
|
TOK_GET(&t, &a, &cv);
|
||||||
pstrcpy(buf, sizeof buf, get_tok_str(t, &cv));
|
pstrcpy(buf, sizeof buf, get_tok_str(t, &cv));
|
||||||
@ -1199,7 +1197,6 @@ static void tok_print(int *str)
|
|||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
printf("<");
|
printf("<");
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -2566,10 +2563,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
|||||||
int last_tok, t, spc;
|
int last_tok, t, spc;
|
||||||
const int *st;
|
const int *st;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
CValue cval;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
CString cstr;
|
CString cstr;
|
||||||
CValue cval;
|
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
tok_str_new(&str);
|
tok_str_new(&str);
|
||||||
last_tok = 0;
|
last_tok = 0;
|
||||||
@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
const int *p;
|
const int *p;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
char *cstrval;
|
char *cstrval;
|
||||||
|
CValue cval;
|
||||||
CString cstr;
|
CString cstr;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
CValue cval;
|
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
/* if symbol is a macro, prepare substitution */
|
/* if symbol is a macro, prepare substitution */
|
||||||
/* special macros */
|
/* special macros */
|
||||||
@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str)
|
|||||||
/* we search the first '##' */
|
/* we search the first '##' */
|
||||||
for(ptr = macro_str;;) {
|
for(ptr = macro_str;;) {
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
TOK_GET(&t, &ptr, &cval);
|
TOK_GET(&t, &ptr, &cval);
|
||||||
if (t == TOK_TWOSHARPS)
|
if (t == TOK_TWOSHARPS)
|
||||||
break;
|
break;
|
||||||
@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str)
|
|||||||
t = *++ptr;
|
t = *++ptr;
|
||||||
if (t && t != TOK_TWOSHARPS) {
|
if (t && t != TOK_TWOSHARPS) {
|
||||||
CValue cval;
|
CValue cval;
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
TOK_GET(&t, &ptr, &cval);
|
TOK_GET(&t, &ptr, &cval);
|
||||||
/* We concatenate the two tokens */
|
/* We concatenate the two tokens */
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
|||||||
int *macro_str1;
|
int *macro_str1;
|
||||||
const int *ptr;
|
const int *ptr;
|
||||||
int t, ret, spc;
|
int t, ret, spc;
|
||||||
|
CValue cval;
|
||||||
struct macro_level ml;
|
struct macro_level ml;
|
||||||
int force_blank;
|
int force_blank;
|
||||||
CValue cval;
|
|
||||||
memset(&cval, 0, sizeof(CValue));
|
|
||||||
|
|
||||||
/* first scan for '##' operator handling */
|
/* first scan for '##' operator handling */
|
||||||
ptr = macro_str;
|
ptr = macro_str;
|
||||||
|
|||||||
Reference in New Issue
Block a user