tcctest.c: sizeof (long) != 8

Bad assumption make bad things happen:

    long d3;
    asm(..."1:\tdec %3\n\t" : ... "=&c" (d3)

Which wants 'dec RDI' but did 'dec EDI' on _WIN64.

Also:
- tcctest.c: enable more asm tests for win64
- configure: show errors if any with 'gcc conftest.c'
- tccgen.c: remove decl0(x, y, z)
This commit is contained in:
grischka 2022-10-14 20:10:38 +02:00
parent c60f1d953c
commit bb80cbe0d9
3 changed files with 46 additions and 47 deletions

2
configure vendored
View File

@ -357,7 +357,7 @@ fi
if test -z "$cross_prefix" ; then
CONFTEST=./conftest$EXESUF
if ! $cc -o $CONFTEST $source_path/conftest.c 2>/dev/null ; then
if ! $cc -o $CONFTEST $source_path/conftest.c ; then
echo "configure: error: '$cc' failed to compile conftest.c."
else
cc_name="$($CONFTEST compiler)"

View File

@ -130,8 +130,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c);
static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
static void block(int is_expr);
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
static void decl(int l);
static int decl0(int l, int is_for_loop_init, Sym *);
static int decl(int l);
static void expr_eq(void);
static void vpush_type_size(CType *type, int *a);
static int is_compatible_unqualified_types(CType *type1, CType *type2);
@ -6881,7 +6880,7 @@ again:
skip('(');
if (tok != ';') {
/* c99 for-loop init decl? */
if (!decl0(VT_LOCAL, 1, NULL)) {
if (!decl(VT_JMP)) {
/* no, regular for-loop init expr */
gexpr();
vpop();
@ -7795,7 +7794,7 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
is put in the value stack. If 'has_init' is 2, a special parsing
is done to handle string constants. */
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
int has_init, int v, int scope)
int has_init, int v, int global)
{
int size, align, addr;
TokenString *init_str = NULL;
@ -7932,7 +7931,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
}
} else {
sym = NULL;
if (v && scope == VT_CONST) {
if (v && global) {
/* see if the symbol was already defined */
sym = sym_find(v);
if (sym) {
@ -8198,9 +8197,10 @@ static void free_inline_functions(TCCState *s)
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
}
/* 'l' is VT_LOCAL or VT_CONST to define default storage type, or VT_CMP
if parsing old style parameter decl list (and FUNC_SYM is set then) */
static int decl0(int l, int is_for_loop_init, Sym *func_sym)
/* 'l' is VT_LOCAL or VT_CONST to define default storage type
or VT_CMP if parsing old style parameter list
or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
static int decl(int l)
{
int v, has_init, r, oldint;
CType type, btype;
@ -8236,7 +8236,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
oldint = 0;
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
if (is_for_loop_init)
if (l == VT_JMP)
return 0;
/* skip redundant ';' if not in old parameter decl scope */
if (tok == ';' && l != VT_CMP) {
@ -8288,13 +8288,15 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
}
#endif
if ((type.t & VT_BTYPE) == VT_FUNC) {
if ((type.t & VT_STATIC) && (l == VT_LOCAL))
if ((type.t & VT_STATIC) && (l != VT_CONST))
tcc_error("function without file scope cannot be static");
/* if old style function prototype, we accept a
declaration list */
sym = type.ref;
if (sym->f.func_type == FUNC_OLD && l == VT_CONST)
decl0(VT_CMP, 0, sym);
if (sym->f.func_type == FUNC_OLD && l == VT_CONST) {
func_vt = type;
decl(VT_CMP);
}
#if defined TCC_TARGET_MACHO || defined TARGETOS_ANDROID
if (sym->f.func_alwinl
&& ((type.t & (VT_EXTERN | VT_INLINE))
@ -8388,12 +8390,12 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
} else {
if (l == VT_CMP) {
/* find parameter in function parameter list */
for (sym = func_sym->next; sym; sym = sym->next)
for (sym = func_vt.ref->next; sym; sym = sym->next)
if ((sym->v & ~SYM_FIELD) == v)
goto found;
tcc_error("declaration for parameter '%s' but no such parameter",
get_tok_str(v, NULL));
found:
found:
if (type.t & VT_STORAGE) /* 'register' is okay */
tcc_error("storage class specified for '%s'",
get_tok_str(v, NULL));
@ -8460,20 +8462,20 @@ found:
esym->st_value, esym->st_size, 1);
}
} else {
if (type.t & VT_STATIC)
if (l == VT_CONST || (type.t & VT_STATIC))
r |= VT_CONST;
else
r |= l;
r |= VT_LOCAL;
if (has_init)
next();
else if (l == VT_CONST)
/* uninitialized global variables may be overridden */
type.t |= VT_EXTERN;
decl_initializer_alloc(&type, &ad, r, has_init, v, l);
decl_initializer_alloc(&type, &ad, r, has_init, v, l == VT_CONST);
}
}
if (tok != ',') {
if (is_for_loop_init)
if (l == VT_JMP)
return 1;
skip(';');
break;
@ -8485,11 +8487,6 @@ found:
return 0;
}
static void decl(int l)
{
decl0(l, 0, NULL);
}
/* ------------------------------------------------------------------------- */
#undef gjmp_addr
#undef gjmp

View File

@ -3251,10 +3251,12 @@ void local_label_test(void)
/* inline assembler test */
#if defined(__i386__) || defined(__x86_64__)
typedef __SIZE_TYPE__ word;
/* from linux kernel */
static char * strncat1(char * dest,const char * src,size_t count)
{
long d0, d1, d2, d3;
word d0, d1, d2, d3;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
@ -3276,7 +3278,7 @@ return dest;
static char * strncat2(char * dest,const char * src,size_t count)
{
long d0, d1, d2, d3;
word d0, d1, d2, d3;
__asm__ __volatile__(
"repne scasb\n\t" /* one-line repne prefix + string op */
"dec %1\n\t"
@ -3297,7 +3299,7 @@ return dest;
static inline void * memcpy1(void * to, const void * from, size_t n)
{
size_t d0, d1, d2;
word d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"testb $2,%b4\n\t"
@ -3308,14 +3310,14 @@ __asm__ __volatile__(
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((size_t) to),"2" ((size_t) from)
:"0" (n/4), "q" (n),"1" ((word) to),"2" ((word) from)
: "memory");
return (to);
}
static inline void * memcpy2(void * to, const void * from, size_t n)
{
size_t d0, d1, d2;
word d0, d1, d2;
__asm__ __volatile__(
"rep movsl\n\t" /* one-line rep prefix + string op */
"testb $2,%b4\n\t"
@ -3326,7 +3328,7 @@ __asm__ __volatile__(
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0" (n/4), "q" (n),"1" ((size_t) to),"2" ((size_t) from)
:"0" (n/4), "q" (n),"1" ((word) to),"2" ((word) from)
: "memory");
return (to);
}
@ -3395,12 +3397,12 @@ struct struct123 {
int b;
};
struct struct1231 {
unsigned long addr;
word addr;
};
unsigned long mconstraint_test(struct struct1231 *r)
word mconstraint_test(struct struct1231 *r)
{
unsigned long ret;
word ret;
unsigned int a[2];
a[0] = 0;
__asm__ volatile ("lea %2,%0; movl 4(%0),%k0; addl %2,%k0; movl $51,%2; movl $52,4%2; movl $63,%1"
@ -3422,11 +3424,11 @@ int fls64(unsigned long long x)
void other_constraints_test(void)
{
unsigned long ret;
word ret;
int var;
#if !defined(_WIN64) && CC_NAME != CC_clang
#if CC_NAME != CC_clang
__asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var));
printf ("oc1: %d\n", ret == (unsigned long)&var);
printf ("oc1: %d\n", ret == (word)&var);
#endif
}
@ -3510,6 +3512,7 @@ void asm_local_label_diff (void)
printf ("asm_local_label_diff: %d %d\n", alld_stuff[0], alld_stuff[1]);
}
#endif
#endif
/* This checks that static local variables are available from assembler. */
void asm_local_statics (void)
@ -3518,7 +3521,6 @@ void asm_local_statics (void)
asm("incl %0" : "+m" (localint));
printf ("asm_local_statics: %d\n", localint);
}
#endif
static
unsigned int set;
@ -3533,7 +3535,7 @@ void fancy_copy2 (unsigned *in, unsigned *out)
asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory");
}
#if defined __x86_64__ && !defined _WIN64
#if defined __x86_64__
void clobber_r12(void)
{
asm volatile("mov $1, %%r12" ::: "r12");
@ -3542,9 +3544,9 @@ void clobber_r12(void)
void test_high_clobbers_really(void)
{
#if defined __x86_64__ && !defined _WIN64
register long val asm("r12");
long val2;
#if defined __x86_64__
register word val asm("r12");
word val2;
/* This tests if asm clobbers correctly save/restore callee saved
registers if they are clobbered and if it's the high 8 x86-64
registers. This is fragile for GCC as the constraints do not
@ -3558,8 +3560,8 @@ void test_high_clobbers_really(void)
void test_high_clobbers(void)
{
#if defined __x86_64__ && !defined _WIN64
long x1, x2;
#if defined __x86_64__
word x1, x2;
asm volatile("mov %%r12,%0" :: "m" (x1)); /* save r12 */
test_high_clobbers_really();
asm volatile("mov %%r12,%0" :: "m" (x2)); /* new r12 */
@ -3625,7 +3627,7 @@ void trace_console(long len, long len2)
void test_asm_dead_code(void)
{
long rdi;
word rdi;
/* Try to make sure that xdi contains a zero, and hence will
lead to a segfault if the next asm is evaluated without
arguments being set up. */
@ -3727,12 +3729,12 @@ void asm_test(void)
char buf[128];
unsigned int val, val2;
struct struct123 s1;
struct struct1231 s2 = { (unsigned long)&s1 };
struct struct1231 s2 = { (word)&s1 };
/* Hide the outer base_func, but check later that the inline
asm block gets the outer one. */
int base_func = 42;
void override_func3 (void);
unsigned long asmret;
word asmret;
#ifdef BOOL_ISOC99
_Bool somebool;
#endif
@ -3783,8 +3785,8 @@ void asm_test(void)
printf("asmstr: %s\n", get_asm_string());
asm_local_label_diff();
#endif
asm_local_statics();
#endif
asm_local_statics();
#ifndef __clang__
/* clang can't deal with the type change */
/* Check that we can also load structs of appropriate layout