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).
master
grischka 2014-04-04 20:18:39 +02:00
parent 2024c44541
commit 5879c854fb
3 changed files with 52 additions and 70 deletions

76
tcc.h
View File

@ -55,18 +55,27 @@
# ifndef CONFIG_TCC_STATIC
# include <dlfcn.h>
# 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 <sys/timeb.h>
# include <io.h> /* open, close etc. */
# include <direct.h> /* getcwd */
# ifdef __GNUC__
# include <stdint.h>
# else
typedef UINT_PTR uintptr_t;
# endif
# define inline __inline
# 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
# define LIBTCCAPI __declspec(dllexport)
# define PUB_FUNC LIBTCCAPI
@ -79,6 +88,30 @@
# define O_BINARY 0
#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"
#ifdef TCC_TARGET_X86_64
# define ELFCLASSW ELFCLASS64
@ -315,7 +348,7 @@ typedef union CValue {
long long ll;
unsigned long long ull;
struct CString *cstr;
void *ptr;
addr_t ptr_offset;
int tab[LDOUBLE_SIZE/4];
} CValue;
@ -938,37 +971,6 @@ enum tcc_token {
#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 */
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)
PUB_FUNC void tcc_memstats(void);
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, ...);
/* other utilities */
@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1);
ST_FUNC void preprocess_new(void);
ST_FUNC int tcc_preprocess(TCCState *s1);
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 ------------ */

View File

@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc)
void vpush(CType *type)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
vsetc(type, VT_CONST, &cval);
}
@ -337,29 +336,23 @@ void vpush(CType *type)
ST_FUNC void vpushi(int v)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
cval.i = v;
vsetc(&int_type, VT_CONST, &cval);
}
/* push a pointer sized constant */
static void vpushs(long long v)
static void vpushs(addr_t v)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
if (PTR_SIZE == 4)
cval.i = (int)v;
else
cval.ull = v;
cval.ptr_offset = v;
vsetc(&size_type, VT_CONST, &cval);
}
/* push arbitrary 64bit constant */
void vpush64(int ty, unsigned long long v)
{
CType ctype;
CValue cval;
memset(&cval, 0, sizeof(CValue));
CType ctype;
ctype.t = ty;
ctype.ref = NULL;
cval.ull = v;
@ -376,9 +369,7 @@ static inline void vpushll(long long v)
static inline void vpushsym(CType *type, Sym *sym)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
cval.ull = 0;
cval.ptr_offset = 0;
vsetc(type, VT_CONST | VT_SYM, &cval);
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)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
cval.i = v;
vsetc(type, r, &cval);
@ -737,7 +727,6 @@ ST_FUNC int gv(int rc)
unsigned long offset;
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
CValue check;
memset(&check, 0, sizeof(CValue));
#endif
/* 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);
vtop->r |= VT_LVAL | VT_SYM;
vtop->sym = sym;
vtop->c.ull = 0;
vtop->c.ptr_offset = 0;
}
#ifdef CONFIG_TCC_BCHECK
if (vtop->r & VT_MUSTBOUND)
@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p)
return 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_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)
@ -3886,8 +3875,7 @@ ST_FUNC void unary(void)
mk_pointer(&s->type);
s->type.t |= VT_STATIC;
}
vset(&s->type, VT_CONST | VT_SYM, 0);
vtop->sym = s;
vpushsym(&s->type, s);
next();
break;
@ -3939,7 +3927,7 @@ ST_FUNC void unary(void)
/* if forward reference, we must point to s */
if (vtop->r & VT_SYM) {
vtop->sym = s;
vtop->c.ull = 0;
vtop->c.ptr_offset = 0;
}
break;
}
@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
if (vtop->r & VT_SYM) {
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;
default:
if (vtop->r & VT_SYM) {

16
tccpp.c
View File

@ -974,7 +974,6 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
ST_FUNC void tok_str_add_tok(TokenString *s)
{
CValue cval;
memset(&cval, 0, sizeof(CValue));
/* save line number info */
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)
{
char buf[STRING_MAX_SIZE + 1];
int t;
CValue cv;
memset(&cv, 0, sizeof(CValue));
int t;
while (*a && *b) {
TOK_GET(&t, &a, &cv);
pstrcpy(buf, sizeof buf, get_tok_str(t, &cv));
@ -1199,7 +1197,6 @@ static void tok_print(int *str)
{
int t;
CValue cval;
memset(&cval, 0, sizeof(CValue));
printf("<");
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;
const int *st;
Sym *s;
CValue cval;
TokenString str;
CString cstr;
CValue cval;
memset(&cval, 0, sizeof(CValue));
tok_str_new(&str);
last_tok = 0;
@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str,
const int *p;
TokenString str;
char *cstrval;
CValue cval;
CString cstr;
char buf[32];
CValue cval;
memset(&cval, 0, sizeof(CValue));
/* if symbol is a macro, prepare substitution */
/* special macros */
@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str)
/* we search the first '##' */
for(ptr = macro_str;;) {
CValue cval;
memset(&cval, 0, sizeof(CValue));
TOK_GET(&t, &ptr, &cval);
if (t == TOK_TWOSHARPS)
break;
@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str)
t = *++ptr;
if (t && t != TOK_TWOSHARPS) {
CValue cval;
memset(&cval, 0, sizeof(CValue));
TOK_GET(&t, &ptr, &cval);
/* We concatenate the two tokens */
cstr_new(&cstr);
@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
int *macro_str1;
const int *ptr;
int t, ret, spc;
CValue cval;
struct macro_level ml;
int force_blank;
CValue cval;
memset(&cval, 0, sizeof(CValue));
/* first scan for '##' operator handling */
ptr = macro_str;