mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50:07 +08:00
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:
parent
c60f1d953c
commit
bb80cbe0d9
2
configure
vendored
2
configure
vendored
@ -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)"
|
||||
|
43
tccgen.c
43
tccgen.c
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user