mirror of
https://github.com/frida/tinycc
synced 2024-11-24 00:29:38 +03:00
tccgen: nodata_wanted
The existing variable 'nocode_wanted' is now used to control output of static data too. So... (nocode_wanted == 0) code and data (normal within functions) (nocode_wanted < 0) means: no code, but data (global or static data) (nocode_wanted > 0) means: no code and no data (code and data suppressed) (nocode_wanted & 0xC0000000) means: we're in declaration of static data Also: new option '-dT' to be used with -run tcc -dT -run file.c This will look in file.c for certain comment-boundaries: /*-* test-xxx: ...some description */ and then for each test below run it from memory. This way various features and error messages can be tested with one single file. See 96_nodata_wanted.c for an example. Also: tccgen.c: one more bitfield fix
This commit is contained in:
parent
69a137ff88
commit
7f1ab9b1e1
4
libtcc.c
4
libtcc.c
@ -634,11 +634,9 @@ static int tcc_compile(TCCState *s1)
|
||||
|
||||
preprocess_start(s1);
|
||||
tccgen_start(s1);
|
||||
|
||||
#ifdef INC_DEBUG
|
||||
printf("%s: **** new file\n", file->filename);
|
||||
#endif
|
||||
|
||||
ch = file->buf_ptr[0];
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR;
|
||||
@ -1801,6 +1799,8 @@ reparse:
|
||||
s->dflag = 3;
|
||||
else if (*optarg == 'M')
|
||||
s->dflag = 7;
|
||||
else if (*optarg == 'T')
|
||||
s->do_test = argc;
|
||||
else if (isnum(*optarg))
|
||||
g_debug = atoi(optarg);
|
||||
else
|
||||
|
2
tcc.c
2
tcc.c
@ -282,6 +282,8 @@ redo:
|
||||
n = s->nb_files;
|
||||
if (n == 0)
|
||||
tcc_error("no input files\n");
|
||||
if (s->do_test)
|
||||
tcc_tool_test(s, argc, argv); /* maybe never returns */
|
||||
|
||||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
if (!s->outfile) {
|
||||
|
1
tcc.h
1
tcc.h
@ -813,6 +813,7 @@ struct TCCState {
|
||||
int option_pthread; /* -pthread option */
|
||||
int argc;
|
||||
char **argv;
|
||||
int do_test;
|
||||
};
|
||||
|
||||
struct filespec {
|
||||
|
89
tccgen.c
89
tccgen.c
@ -50,7 +50,9 @@ ST_DATA int vla_sp_loc; /* Pointer to variable holding location to store stack p
|
||||
ST_DATA SValue __vstack[1+VSTACK_SIZE], *vtop, *pvtop;
|
||||
|
||||
ST_DATA int const_wanted; /* true if constant wanted */
|
||||
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
ST_DATA int nocode_wanted; /* no code generation wanted */
|
||||
#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
|
||||
#define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */
|
||||
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
|
||||
ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
|
||||
@ -230,7 +232,7 @@ ST_FUNC void tccgen_start(TCCState *s1)
|
||||
anon_sym = SYM_FIRST_ANOM;
|
||||
section_sym = 0;
|
||||
const_wanted = 0;
|
||||
nocode_wanted = 1;
|
||||
nocode_wanted = 0x80000000;
|
||||
|
||||
/* define some often used types */
|
||||
int_type.t = VT_INT;
|
||||
@ -1206,14 +1208,12 @@ ST_FUNC int gv(int rc)
|
||||
} else {
|
||||
if (is_float(vtop->type.t) &&
|
||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||
unsigned long offset;
|
||||
/* CPUs usually cannot use float constants, so we store them
|
||||
generically in data segment */
|
||||
size = type_size(&vtop->type, &align);
|
||||
offset = section_add(data_section, size, align);
|
||||
vpush_ref(&vtop->type, data_section, offset, size);
|
||||
vpush_ref(&vtop->type, data_section, data_section->data_offset, size);
|
||||
vswap();
|
||||
init_putv(&vtop->type, data_section, offset);
|
||||
init_putv(&vtop->type, data_section, data_section->data_offset);
|
||||
vtop->r |= VT_LVAL;
|
||||
}
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@ -2329,6 +2329,11 @@ static void gen_cvt_ftoi1(int t)
|
||||
static void force_charshort_cast(int t)
|
||||
{
|
||||
int bits, dbt;
|
||||
|
||||
/* cannot cast static initializers */
|
||||
if (STATIC_DATA_WANTED)
|
||||
return;
|
||||
|
||||
dbt = t & VT_BTYPE;
|
||||
/* XXX: add optimization if lvalue : just change type and offset */
|
||||
if (dbt == VT_BYTE)
|
||||
@ -3405,12 +3410,9 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
//#define BF_DEBUG
|
||||
|
||||
for (f = type->ref->next; f; f = f->next) {
|
||||
if (f->type.t & VT_BITFIELD) {
|
||||
if (f->type.t & VT_BITFIELD)
|
||||
bit_size = BIT_SIZE(f->type.t);
|
||||
/* in pcc mode, long long bitfields have type int if they fit */
|
||||
if (pcc && (f->type.t & VT_BTYPE) == VT_LLONG && bit_size <= 32)
|
||||
f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT;
|
||||
} else
|
||||
else
|
||||
bit_size = -1;
|
||||
size = type_size(&f->type, &align);
|
||||
a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
|
||||
@ -3479,6 +3481,10 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
goto new_field;
|
||||
}
|
||||
|
||||
/* in pcc mode, long long bitfields have type int if they fit */
|
||||
if (size == 8 && bit_size <= 32)
|
||||
f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT, size = 4;
|
||||
|
||||
while (bit_pos >= align * 8)
|
||||
c += align, bit_pos -= align * 8;
|
||||
offset = c;
|
||||
@ -4558,8 +4564,10 @@ ST_FUNC void unary(void)
|
||||
type.t |= VT_ARRAY;
|
||||
type.ref->c = len;
|
||||
vpush_ref(&type, data_section, data_section->data_offset, len);
|
||||
if (!NODATA_WANTED) {
|
||||
ptr = section_ptr_add(data_section, len);
|
||||
memcpy(ptr, funcname, len);
|
||||
}
|
||||
next();
|
||||
}
|
||||
break;
|
||||
@ -6314,7 +6322,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
|
||||
vstore();
|
||||
}
|
||||
vpop();
|
||||
} else {
|
||||
} else if (!NODATA_WANTED) {
|
||||
c_end = c + nb_elems * elem_size;
|
||||
if (c_end > sec->data_allocated)
|
||||
section_realloc(sec, c_end);
|
||||
@ -6348,9 +6356,25 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||
/* XXX: generate error if incorrect relocation */
|
||||
gen_assign_cast(&dtype);
|
||||
bt = type->t & VT_BTYPE;
|
||||
|
||||
if ((vtop->r & VT_SYM)
|
||||
&& bt != VT_PTR
|
||||
&& bt != VT_FUNC
|
||||
&& (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
|
||||
|| (type->t & VT_BITFIELD))
|
||||
&& !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM)
|
||||
)
|
||||
tcc_error("initializer element is not computable at load time");
|
||||
|
||||
if (NODATA_WANTED) {
|
||||
vtop--;
|
||||
return;
|
||||
}
|
||||
|
||||
size = type_size(type, &align);
|
||||
section_reserve(sec, c + size);
|
||||
ptr = sec->data + c;
|
||||
|
||||
/* XXX: make code faster ? */
|
||||
if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
|
||||
vtop->sym->v >= SYM_FIRST_ANOM &&
|
||||
@ -6404,20 +6428,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((vtop->r & VT_SYM) &&
|
||||
(bt == VT_BYTE ||
|
||||
bt == VT_SHORT ||
|
||||
bt == VT_DOUBLE ||
|
||||
bt == VT_LDOUBLE ||
|
||||
#if PTR_SIZE == 8
|
||||
bt == VT_INT ||
|
||||
#else
|
||||
bt == VT_LLONG ||
|
||||
#endif
|
||||
(type->t & VT_BITFIELD)
|
||||
))
|
||||
tcc_error("initializer element is not computable at load time");
|
||||
|
||||
if (type->t & VT_BITFIELD) {
|
||||
int bit_pos, bit_size, bits, n;
|
||||
unsigned char *p, v, m;
|
||||
@ -6598,6 +6608,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||
string in global variable, we handle it
|
||||
specifically */
|
||||
if (sec && tok == TOK_STR && size1 == 1) {
|
||||
if (!NODATA_WANTED)
|
||||
memcpy(sec->data + c + len, tokc.str.data, nb);
|
||||
} else {
|
||||
for(i=0;i<nb;i++) {
|
||||
@ -6714,6 +6725,13 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
Section *sec;
|
||||
Sym *flexible_array;
|
||||
Sym *sym = NULL;
|
||||
int saved_nocode_wanted = nocode_wanted;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
|
||||
#endif
|
||||
|
||||
if (type->t & VT_STATIC)
|
||||
nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000;
|
||||
|
||||
flexible_array = NULL;
|
||||
if ((type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
@ -6779,10 +6797,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
} else if (ad->a.packed) {
|
||||
align = 1;
|
||||
}
|
||||
|
||||
if (NODATA_WANTED)
|
||||
size = 0, align = 1;
|
||||
|
||||
if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
sec = NULL;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) {
|
||||
if (bcheck && (type->t & VT_ARRAY)) {
|
||||
loc--;
|
||||
}
|
||||
#endif
|
||||
@ -6792,7 +6814,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
/* handles bounds */
|
||||
/* XXX: currently, since we do only one pass, we cannot track
|
||||
'&' operators, so we add only arrays */
|
||||
if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) {
|
||||
if (bcheck && (type->t & VT_ARRAY)) {
|
||||
addr_t *bounds_ptr;
|
||||
/* add padding between regions */
|
||||
loc--;
|
||||
@ -6860,7 +6882,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
addr = section_add(sec, size, align);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* add padding if bound check */
|
||||
if (tcc_state->do_bounds_check)
|
||||
if (bcheck)
|
||||
section_add(sec, 1, 1);
|
||||
#endif
|
||||
} else {
|
||||
@ -6888,7 +6910,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* handles bounds now because the symbol must be defined
|
||||
before for the relocation */
|
||||
if (tcc_state->do_bounds_check) {
|
||||
if (bcheck) {
|
||||
addr_t *bounds_ptr;
|
||||
|
||||
greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0);
|
||||
@ -6903,6 +6925,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
if (type->t & VT_VLA) {
|
||||
int a;
|
||||
|
||||
if (NODATA_WANTED)
|
||||
goto no_alloc;
|
||||
|
||||
/* save current stack pointer */
|
||||
if (vlas_in_scope == 0) {
|
||||
if (vla_sp_root_loc == -1)
|
||||
@ -6935,6 +6960,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
end_macro();
|
||||
restore_parse_state(&saved_parse_state);
|
||||
}
|
||||
|
||||
nocode_wanted = saved_nocode_wanted;
|
||||
}
|
||||
|
||||
/* parse a function defined by symbol 'sym' and generate its code in
|
||||
@ -6978,7 +7005,7 @@ static void gen_function(Sym *sym)
|
||||
func_vt.t = VT_VOID; /* for safety */
|
||||
func_var = 0; /* for safety */
|
||||
ind = 0; /* for safety */
|
||||
nocode_wanted = 1;
|
||||
nocode_wanted = 0x80000000;
|
||||
check_vstack();
|
||||
}
|
||||
|
||||
|
105
tcctools.c
105
tcctools.c
@ -544,3 +544,108 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* run test snippets from file */
|
||||
|
||||
static char *readfile(const char *fname)
|
||||
{
|
||||
char *buf;
|
||||
int fsize;
|
||||
FILE *fi;
|
||||
fi = fopen(fname, "rb");
|
||||
if (!fi)
|
||||
return NULL;
|
||||
fseek(fi, 0, SEEK_END);
|
||||
fsize = ftell(fi);
|
||||
fseek(fi, 0, SEEK_SET);
|
||||
buf = tcc_malloc(fsize + 1);
|
||||
fread(buf, fsize, 1, fi);
|
||||
fclose(fi);
|
||||
buf[fsize] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int run_prog(const char *prog, int ac, char **av)
|
||||
{
|
||||
TCCState *s;
|
||||
int (*func)(int, char**);
|
||||
int ret = -10000;
|
||||
|
||||
s = tcc_new();
|
||||
tcc_parse_args(s, &ac, &av, 1);
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
if (tcc_compile_string(s, prog) == -1)
|
||||
goto done;
|
||||
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
|
||||
goto done;
|
||||
func = tcc_get_symbol(s, "main");
|
||||
if (!func)
|
||||
goto done;
|
||||
ret = func(ac, av);
|
||||
done:
|
||||
tcc_delete(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *trimback(char *a, char *e)
|
||||
{
|
||||
while (e > a && (unsigned char)e[-1] <= ' ')
|
||||
--e;
|
||||
*e = 0;;
|
||||
return a;
|
||||
}
|
||||
|
||||
ST_FUNC int tcc_tool_test(TCCState *s, int argc, char **argv)
|
||||
{
|
||||
const char *fname;
|
||||
char *buf, *p, *a, *b, *e, tmp[100];
|
||||
int r = 0, c, n;
|
||||
const char sep[] = "/*-* test";
|
||||
|
||||
n = s->do_test - argc;
|
||||
if (!n)
|
||||
return 0;
|
||||
fname = argv[0], argv -= n, argc += n;
|
||||
|
||||
buf = readfile(fname);
|
||||
if (NULL == buf)
|
||||
return -1;
|
||||
p = strstr(buf, sep);
|
||||
if (!p) {
|
||||
tcc_free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
a = p, p = strchr(p, '\n');
|
||||
if (NULL == p)
|
||||
break;
|
||||
*p++ = 0;
|
||||
b = p, p = strstr(p, sep);
|
||||
if (NULL == p)
|
||||
p = strchr(b, 0);
|
||||
c = *p, *p = 0;
|
||||
|
||||
trimback(a, b);
|
||||
if (r)
|
||||
printf("\n");
|
||||
printf("%s\n", a);
|
||||
fflush(stdout);
|
||||
|
||||
e = a += sizeof sep - 5;
|
||||
while (*e && *e != ':')
|
||||
++e;
|
||||
if (!*e || e - a > 32)
|
||||
e = a + 4;
|
||||
n = snprintf(tmp, sizeof tmp, "#line 1 \"%.*s\"\n", (int)(e - a), a);
|
||||
if (b - buf >= n)
|
||||
b = memcpy(b - n, tmp, n);
|
||||
n = run_prog(b, argc, argv);
|
||||
if (n != -10000)
|
||||
printf("returns %d\n", n);
|
||||
*p = c, ++r;
|
||||
}
|
||||
tcc_free(buf);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
@ -58,7 +58,7 @@
|
||||
struct M P __s {
|
||||
long long x : 45;
|
||||
long long : 2;
|
||||
long long y : 35;
|
||||
long long y : 30;
|
||||
unsigned long long z : 38;
|
||||
char a; short b;
|
||||
};
|
||||
|
@ -23,8 +23,8 @@ values : 03 ffffffff 0f fffffff8 78
|
||||
align/size : 4 8
|
||||
|
||||
---- TEST 5 - MS-BITFIELDS ----
|
||||
bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 0000000000770044000000000000007800000007F00000000000000123456789
|
||||
bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 0000000000770044000000000000007800000000300000000000000123456789
|
||||
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
|
||||
align/size : 8 32
|
||||
|
||||
@ -61,8 +61,8 @@ values : 03 ffffffff 0f fffffff8 78
|
||||
align/size : 1 8
|
||||
|
||||
---- TEST 5 - MS-BITFIELDS - PACKED ----
|
||||
bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 007744000000000000007800000007F00000000000000123456789
|
||||
bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 007744000000000000007800000000300000000000000123456789
|
||||
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
|
||||
align/size : 1 27
|
||||
|
||||
@ -99,8 +99,8 @@ values : 03 ffffffff 0f fffffff8 78
|
||||
align/size : 4 8
|
||||
|
||||
---- TEST 5 - MS-BITFIELDS - WITH ALIGN ----
|
||||
bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 0000000000770044000000000000007800000007F00000000000000123456789
|
||||
bits in use : 00000000FFFF00FF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 0000000000770044000000000000007800000000300000000000000123456789
|
||||
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
|
||||
align/size : 8 32
|
||||
|
||||
@ -137,8 +137,8 @@ values : 03 ffffffff 0f fffffff8 78
|
||||
align/size : 1 8
|
||||
|
||||
---- TEST 5 - MS-BITFIELDS - PACKED - WITH ALIGN ----
|
||||
bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 007744000000000000007800000007F00000000000000123456789
|
||||
bits in use : FFFFFF0000003FFFFFFFFF000000003FFFFFFF00001FFFFFFFFFFF
|
||||
bits as set : 007744000000000000007800000000300000000000000123456789
|
||||
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
|
||||
align/size : 1 27
|
||||
|
||||
|
74
tests/tests2/96_nodata_wanted.c
Normal file
74
tests/tests2/96_nodata_wanted.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*****************************************************************************/
|
||||
/* test 'nodata_wanted' data output suppression */
|
||||
|
||||
/*-* test 1: initializer not computable 1 */
|
||||
void foo() {
|
||||
if (1) {
|
||||
static short w = (int)&foo; /* error */
|
||||
}
|
||||
}
|
||||
|
||||
/*-* test 2: initializer not computable 2 */
|
||||
void foo() {
|
||||
if (0) {
|
||||
static short w = (int)&foo; /* error */
|
||||
}
|
||||
}
|
||||
|
||||
/*-* test 3: initializer not computable 3 */
|
||||
void foo();
|
||||
static short w = (int)&foo; /* error */
|
||||
|
||||
|
||||
/*-* test 4: 2 cast warnings */
|
||||
void foo() {
|
||||
short w = &foo; /* no error */
|
||||
}
|
||||
|
||||
/*-* test 5; nodata_wanted test */
|
||||
#include <stdio.h>
|
||||
|
||||
#define DATA_LBL(s) \
|
||||
__asm__(".global d"#s",t"#s"\n.data\nd"#s":\n.text\nt"#s":\n"); \
|
||||
extern char d##s[],t##s[];
|
||||
|
||||
#define PROG \
|
||||
static void *p = (void*)&main;\
|
||||
static char cc[] = "static string";\
|
||||
static double d = 8.0;\
|
||||
static struct __attribute__((packed)) {\
|
||||
unsigned x : 12;\
|
||||
unsigned char y : 7;\
|
||||
unsigned z : 28, a: 4, b: 5;\
|
||||
} s = { 0x333,0x44,0x555555,6,7 };\
|
||||
printf(" static data: %d - %.1f - %.1f - %s - %s\n",\
|
||||
sizeof 8.0, 8.0, d, __FUNCTION__, cc);\
|
||||
printf(" static bitfields: %x %x %x %x %x\n", s.x, s.y, s.z, s.a, s.b);
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("suppression off\n");
|
||||
DATA_LBL(s1);
|
||||
if (1) {
|
||||
PROG
|
||||
}
|
||||
DATA_LBL(e1);
|
||||
printf(" data length is %s\n", de1 - ds1 ? "not 0":"0");
|
||||
//printf(" text length is %s\n", te1 - ts1 ? "not 0":"0");
|
||||
|
||||
printf("suppression on\n");
|
||||
DATA_LBL(s2);
|
||||
if (0) {
|
||||
PROG
|
||||
}
|
||||
DATA_LBL(e2);
|
||||
printf(" data length is %x\n", de2 - ds2);
|
||||
//printf(" text length is %X\n", te2 - ts2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-* test 6: some test */
|
||||
int main()
|
||||
{
|
||||
return 34;
|
||||
}
|
24
tests/tests2/96_nodata_wanted.expect
Normal file
24
tests/tests2/96_nodata_wanted.expect
Normal file
@ -0,0 +1,24 @@
|
||||
/*-* test 1: initializer not computable 1 */
|
||||
test 1:3: error: initializer element is not computable at load time
|
||||
|
||||
/*-* test 2: initializer not computable 2 */
|
||||
test 2:3: error: initializer element is not computable at load time
|
||||
|
||||
/*-* test 3: initializer not computable 3 */
|
||||
test 3:2: error: initializer element is not computable at load time
|
||||
|
||||
/*-* test 4: 2 cast warnings */
|
||||
test 4:2: warning: assignment makes integer from pointer without a cast
|
||||
test 4:2: warning: nonportable conversion from pointer to char/short
|
||||
|
||||
/*-* test 5; nodata_wanted test */
|
||||
suppression off
|
||||
static data: 8 - 8.0 - 8.0 - main - static string
|
||||
static bitfields: 333 44 555555 6 7
|
||||
data length is not 0
|
||||
suppression on
|
||||
data length is 0
|
||||
returns 0
|
||||
|
||||
/*-* test 6: some test */
|
||||
returns 34
|
@ -5,29 +5,6 @@ VPATH = $(SRC)
|
||||
|
||||
TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c))))
|
||||
|
||||
# Some tests might need arguments
|
||||
ARGS =
|
||||
31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5
|
||||
46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c
|
||||
|
||||
# And some tests don't test the right thing with -run
|
||||
NORUN =
|
||||
42_function_pointer.test : NORUN = true
|
||||
|
||||
# Some tests might need different flags
|
||||
FLAGS =
|
||||
76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers
|
||||
|
||||
# Always generate certain .expects (don't put these in the GIT),
|
||||
GEN-ALWAYS = 95_bitfields.expect
|
||||
|
||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
|
||||
# Filter some always-warning
|
||||
ifeq (-$(findstring arm,$(ARCH))-,-arm-)
|
||||
FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported'
|
||||
endif
|
||||
|
||||
# some tests do not pass on all platforms, remove them for now
|
||||
SKIP = 34_array_assignment.test # array assignment is not in C standard
|
||||
ifeq ($(CONFIG_arm_eabi),yes) # not ARM soft-float
|
||||
@ -50,46 +27,80 @@ ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-)
|
||||
SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows
|
||||
endif
|
||||
|
||||
# Some tests might need arguments
|
||||
ARGS =
|
||||
31_args.test : ARGS = arg1 arg2 arg3 arg4 arg5
|
||||
46_grep.test : ARGS = '[^* ]*[:a:d: ]+\:\*-/: $$' $(SRC)/46_grep.c
|
||||
|
||||
# And some tests don't test the right thing with -run
|
||||
NORUN =
|
||||
42_function_pointer.test : NORUN = true
|
||||
|
||||
# Some tests might need different flags
|
||||
FLAGS =
|
||||
76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers
|
||||
|
||||
# run the source file cut into snippets
|
||||
96_nodata_wanted.test : FLAGS = -dT
|
||||
|
||||
# Always generate certain .expects (don't put these in the GIT),
|
||||
GEN-ALWAYS =
|
||||
GEN-ALWAYS += 95_bitfields.expect
|
||||
|
||||
# using the ms compiler for the really ms-compatible bitfields
|
||||
95_bitfields_ms.test : GEN = $(GEN-MSC)
|
||||
|
||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||
FILTER = 2>&1 | sed 's,$(SRC)/,,g'
|
||||
# Filter some always-warning
|
||||
ifeq (-$(findstring arm,$(ARCH))-,-arm-)
|
||||
FILTER += 2>&1 | grep -v 'warning: soft float ABI currently not supported'
|
||||
endif
|
||||
|
||||
all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
|
||||
|
||||
%.test: %.c %.expect
|
||||
@echo Test: $*...
|
||||
@$(if $(NORUN),\
|
||||
($(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)),\
|
||||
$(TCC) $(FLAGS) -run $< $(ARGS)\
|
||||
) $(FILTER) >$*.output 2>&1 || true
|
||||
@diff -Nbu $(filter %.expect,$^) $*.output \
|
||||
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
|
||||
@$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3))
|
||||
|
||||
F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test)
|
||||
F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
|
||||
T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)
|
||||
T2 = $(TCC) $(FLAGS) -run $< $(ARGS)
|
||||
T3 = $(FILTER) >$*.output 2>&1 || true \
|
||||
&& diff -Nbu $(filter %.expect,$^) $*.output \
|
||||
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
|
||||
|
||||
# run single test and update .expect file, e.g. "make tests2.37+"
|
||||
tests2.%+:
|
||||
@$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory
|
||||
|
||||
# just run tcc to see the output, e.g. "make tests2.37-"
|
||||
tests2.%-:
|
||||
@$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory
|
||||
|
||||
# run single test, e.g. "make tests2.37"
|
||||
tests2.%:
|
||||
@$(MAKE) $(call F1,$*) --no-print-directory
|
||||
|
||||
F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test)
|
||||
F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
|
||||
|
||||
# automatically generate .expect files with gcc:
|
||||
%.expect :
|
||||
@echo Generating: $@
|
||||
@$(CC) -w -std=gnu99 $(FLAGS) $(SRC)/$*.c -o a.exe
|
||||
@./a.exe $(ARGS) $(FILTER) >$@ 2>&1
|
||||
@rm -f a.exe
|
||||
|
||||
# using the ms compiler for the really ms-compatible bitfields
|
||||
MS-CC = cl
|
||||
95_bitfields_ms.expect :
|
||||
@echo Generating: $@
|
||||
@$(MS-CC) $(basename $@).c
|
||||
@./$(basename $@).exe >$@ 2>&1
|
||||
@$(call GEN,$(SRC)/$*.c) $(FILTER) >$@ 2>&1
|
||||
@rm -f *.exe *.obj *.pdb
|
||||
|
||||
# using TCC for .expect if -dT in FLAGS
|
||||
GEN = $(if $(findstring -dT,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
|
||||
GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS)
|
||||
GEN-TCC = $(TCC) $(FLAGS) -run $1 $(ARGS)
|
||||
GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe
|
||||
MS-CC = cl
|
||||
|
||||
# tell make not to delete
|
||||
.PRECIOUS: %.expect
|
||||
|
||||
# force .expect generation for these files
|
||||
$(sort $(GEN-ALWAYS) $(UPDATE)) : force
|
||||
force:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user