#pragma comment(option,"-..."), bitfields test, etc...

tccpp.c:
* #pragma comment(option,"-some-option")
  to set commandline option from C code.  May work only
  for some options.
libtcc.c:
* option "-d1..9": sets a 'g_debug' global variable.
  (for development)
tests2/Makefile:
* new make targets: tests2.37 / tests2.37+
  run single test from tests2,  optionally update .expect
* new variable GEN-ALWAYS to always generate certain .expects
* bitfields test
tccgen.c:
* bitfields: fix a bug and improve slightly more
* _Generic: ignore "type match twice"
This commit is contained in:
grischka 2017-07-14 19:26:01 +02:00
parent 04418c7add
commit 69a137ff88
10 changed files with 476 additions and 55 deletions

View File

@ -345,9 +345,12 @@ tar: tcc-doc.html
config.mak:
$(if $(wildcard $@),,@echo "Please run ./configure." && exit 1)
# in tests subdir
# run all tests
test:
$(MAKE) -C tests
# run test(s) from tests2 subdir (see make help)
tests2.%:
$(MAKE) -C tests/tests2 $@
clean:
rm -f $(PROGS) $(PROGS_CROSS) tcc_p$(EXESUF) tcc.pod
@ -389,8 +392,14 @@ help:
@echo " INC-i386 = {B}/lib/include:{B}/i386-linux/usr/include"
@echo " DEF-i386 += -D__linux__"
@echo ""
@echo "make test"
@echo " run all tests"
@echo ""
@echo "make tests2.all / make tests2.37 / make tests2.37+"
@echo " run all/single test(s) from tests2, optionally update .expect"
@echo ""
@echo "Other supported make targets:"
@echo " install install-strip test tags ETAGS tar clean distclean help"
@echo " install install-strip tags ETAGS tar clean distclean help"
@echo ""
# --------------------------------------------------------------------------

View File

@ -1801,6 +1801,8 @@ reparse:
s->dflag = 3;
else if (*optarg == 'M')
s->dflag = 7;
else if (isnum(*optarg))
g_debug = atoi(optarg);
else
goto unsupported_option;
break;

1
tcc.h
View File

@ -1289,6 +1289,7 @@ ST_DATA int func_var; /* true if current function is variadic */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA const char *funcname;
ST_DATA int g_debug;
ST_FUNC void tcc_debug_start(TCCState *s1);
ST_FUNC void tcc_debug_end(TCCState *s1);

View File

@ -57,6 +57,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA const char *funcname;
ST_DATA int g_debug;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
@ -1083,8 +1084,7 @@ static void load_packed_bf(CType *type, int bit_pos, int bit_size)
{
int n, o, bits;
save_reg_upstack(vtop->r, 1);
vpushi(0); // B X
vtop->type.t |= type->t;
vpush64(type->t & VT_BTYPE, 0); // B X
bits = 0, o = bit_pos >> 3, bit_pos &= 7;
do {
vswap(); // X B
@ -1113,7 +1113,7 @@ static void load_packed_bf(CType *type, int bit_pos, int bit_size)
}
/* single-byte store mode for packed or otherwise unaligned bitfields */
void store_packed_bf(int bit_pos, int bit_size)
static void store_packed_bf(int bit_pos, int bit_size)
{
int bits, n, o, m, c;
@ -1148,7 +1148,7 @@ void store_packed_bf(int bit_pos, int bit_size)
vpop(), vpop();
}
int adjust_bf(SValue *sv, int bit_pos, int bit_size)
static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
{
int t;
if (0 == sv->type.ref)
@ -2781,7 +2781,7 @@ static void type_to_str(char *buf, int buf_size,
pstrcat(buf, buf_size, "inline ");
buf_size -= strlen(buf);
buf += strlen(buf);
if (IS_ENUM(type->t)) {
if (IS_ENUM(t)) {
tstr = "enum ";
goto tstruct;
}
@ -3405,9 +3405,12 @@ 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);
else
/* 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
bit_size = -1;
size = type_size(&f->type, &align);
a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
@ -3476,16 +3479,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;
}
if (bit_pos >= size * 8) {
c += size;
bit_pos -= size * 8;
}
while (bit_pos >= align * 8)
c += align, bit_pos -= align * 8;
offset = c;
/* In PCC layout named bit-fields influence the alignment
of the containing struct using the base types alignment,
except for packed fields (which here have correct align). */
@ -3576,14 +3573,20 @@ static void struct_layout(CType *type, AttributeDef *ad)
if (pcc)
c += (bit_pos + 7) >> 3;
a = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 0;
/* store size and alignment */
a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1;
if (a < maxalign)
a = maxalign;
c = (c + a - 1) & -a;
/* store size and alignment */
type->ref->c = c;
type->ref->r = a;
if (pragma_pack && pragma_pack < maxalign) {
/* can happen if individual align for some member was given. In
this case MSVC ignores maxalign when aligning the size */
a = pragma_pack;
if (a < bt)
a = bt;
}
c = (c + a - 1) & -a;
type->ref->c = c;
#ifdef BF_DEBUG
printf("struct size %-2d align %-2d\n\n", c, a), fflush(stdout);
@ -3603,7 +3606,6 @@ static void struct_layout(CType *type, AttributeDef *ad)
continue;
bit_pos = BIT_POS(f->type.t);
size = type_size(&f->type, &align);
if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
continue;
@ -3637,20 +3639,21 @@ static void struct_layout(CType *type, AttributeDef *ad)
| (bit_pos << VT_STRUCT_SHIFT);
if (s != size)
f->auxtype = t.t;
#ifdef BF_DEBUG
printf("FIX field %s offset %-2d size %-2d align %-2d "
"pos %-2d bits %-2d\n",
get_tok_str(f->v & ~SYM_FIELD, NULL),
cx, s, align, px, bit_size);
#endif
} else {
/* fall back to load/store single-byte wise */
f->auxtype = VT_STRUCT;
}
#ifdef BF_DEBUG
printf("FIX field %s offset %-2d size %-2d align %-2d "
"pos %-2d bits %-2d %s\n",
get_tok_str(f->v & ~SYM_FIELD, NULL),
cx, s, align, px, bit_size,
f->auxtype == VT_PTR ? " byte-wise" : ""
);
printf("FIX field %s : load byte-wise\n",
get_tok_str(f->v & ~SYM_FIELD, NULL));
#endif
}
}
}
/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
@ -4915,9 +4918,9 @@ ST_FUNC void unary(void)
type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT);
if (compare_types(&controlling_type, &cur_type, 0)) {
if (has_match) {
tcc_error("type march twice");
// tcc_error("type march twice");
}
if (has_default)
if (str)
tok_str_free(str);
has_match = 1;
learn = 1;

18
tccpp.c
View File

@ -1658,23 +1658,27 @@ static void pragma_parse(TCCState *s1)
goto pragma_err;
} else if (tok == TOK_comment) {
char *file;
char *p; int t;
next();
skip('(');
if (tok != TOK_lib)
goto pragma_warn;
t = tok;
next();
skip(',');
if (tok != TOK_STR)
goto pragma_err;
file = tcc_strdup((char *)tokc.str.data);
dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, file);
p = tcc_strdup((char *)tokc.str.data);
next();
if (tok != ')')
goto pragma_err;
if (t == TOK_lib) {
dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, p);
} else {
pragma_warn:
if (s1->warn_unsupported)
if (t == TOK_option)
tcc_set_options(s1, p);
tcc_free(p);
}
} else if (s1->warn_unsupported) {
tcc_warning("#pragma %s is ignored", get_tok_str(tok, &tokc));
}
return;

View File

@ -167,6 +167,7 @@
DEF(TOK_push_macro, "push_macro")
DEF(TOK_pop_macro, "pop_macro")
DEF(TOK_once, "once")
DEF(TOK_option, "option")
/* builtin functions or variables */
#ifndef TCC_ARM_EABI

215
tests/tests2/95_bitfields.c Normal file
View File

@ -0,0 +1,215 @@
/* ----------------------------------------------------------------------- */
#if TEST == 1
{
struct M P A __s
{
unsigned x : 12;
unsigned char y : 7;
unsigned z : 28;
unsigned a: 4;
unsigned b: 5;
};
TEST_STRUCT(0x333,0x44,0x555555,6,7);
}
/* ----------------------------------------------------------------------- */
#elif TEST == 2
{
struct M P __s
{
int x: 12;
char y: 6;
long long z:63;
A char a:4;
long long b:2;
};
TEST_STRUCT(3,30,0x123456789abcdef0LL,5,2);
}
/* ----------------------------------------------------------------------- */
#elif TEST == 3
{
struct M P __s
{
unsigned x:5, y:5, :0, z:5; char a:5; A short b:5;
};
TEST_STRUCT(21,23,25,6,14);
}
/* ----------------------------------------------------------------------- */
#elif TEST == 4
{
struct M P __s {
int x : 3;
int : 2;
int y : 1;
int : 0;
int z : 5;
int a : 7;
unsigned int b : 7;
};
TEST_STRUCT(3,1,15,120,120);
}
/* ----------------------------------------------------------------------- */
#elif TEST == 5
{
struct M P __s {
long long x : 45;
long long : 2;
long long y : 35;
unsigned long long z : 38;
char a; short b;
};
TEST_STRUCT(0x123456789ULL, 120<<25, 120, 0x44, 0x77);
}
/* ----------------------------------------------------------------------- */
#elif TEST == 6
{
struct M P __s {
int a;
char b;
int x : 12, y : 4, : 0, : 4, z : 3;
char d;
};
TEST_STRUCT(1,2,3,4,-3);
}
/* ----------------------------------------------------------------------- */
#elif defined PACK
#if PACK
# pragma pack(push,1)
# define P //_P
#else
# define P
#endif
#define TEST 1
#include SELF
#define TEST 2
#include SELF
#define TEST 3
#include SELF
#define TEST 4
#include SELF
#define TEST 5
#include SELF
#define TEST 6
#include SELF
printf("\n\n");
#if PACK
# pragma pack(pop)
#endif
#undef P
#undef PACK
/* ----------------------------------------------------------------------- */
#elif defined ALIGN
#if ALIGN
# define A _A(16)
#else
# define A
#endif
#define PACK 0
#include SELF
#define PACK 1
#include SELF
#undef A
#undef ALIGN
/* ----------------------------------------------------------------------- */
#elif defined MS_BF
#if MS_BF
# ifdef __TINYC__
# pragma comment(option, "-mms-bitfields")
# elif defined __GNUC__
# define M __attribute__((ms_struct))
# endif
#else
# ifdef __TINYC__
# pragma comment(option, "-mno-ms-bitfields")
# elif defined __GNUC__
# define M __attribute__((gcc_struct))
# endif
#endif
#ifndef M
# define M
#endif
#define ALIGN 0
#include SELF
#define ALIGN 1
#include SELF
#undef M
#undef MS_BF
/* ----------------------------------------------------------------------- */
#else
#include <stdio.h>
#include <string.h>
/* some gcc headers #define __attribute__ to empty if it's not gcc */
#undef __attribute__
void dump(void *p, int s)
{
int i;
for (i = s; --i >= 0;)
printf("%02X", ((unsigned char*)p)[i]);
printf("\n");
}
#define pv(m) \
printf(sizeof (s->m + 0) == 8 ? " %016llx" : " %02x", s->m)
#define TEST_STRUCT(v1,v2,v3,v4,v5) { \
struct __s _s, *s = & _s; \
printf("---- TEST %d%s%s%s ----\n", \
TEST, MS_BF?" - MS-BITFIELDS":"", \
PACK?" - PACKED":"", \
ALIGN?" - WITH ALIGN":""); \
memset(s, 0, sizeof *s); \
s->x = -1, s->y = -1, s->z = -1, s->a = -1, s->b = -1; \
printf("bits in use : "), dump(s, sizeof *s); \
s->x = v1, s->y = v2, s->z = v3, s->a += v4, ++s->a, s->b = v5; \
printf("bits as set : "), dump(s, sizeof *s); \
printf("values :"), pv(x), pv(y), pv(z), pv(a), pv(b), printf("\n"); \
printf("align/size : %d %d\n\n", alignof(struct __s),sizeof(struct __s)); \
}
#ifdef _MSC_VER
# define _A(n) __declspec(align(n))
# define _P
# define alignof(x) __alignof(x)
#else
# define _A(n) __attribute__((aligned(n)))
# define _P __attribute__((packed))
# define alignof(x) __alignof__(x)
#endif
#ifndef MS_BITFIELDS
# define MS_BITFIELDS 0
#endif
#define SELF "95_bitfields.c"
int main()
{
#define MS_BF MS_BITFIELDS
#include SELF
return 0;
}
/* ----------------------------------------------------------------------- */
#endif
#undef TEST

View File

@ -0,0 +1,2 @@
#define MS_BITFIELDS 1
#include "95_bitfields.c"

View File

@ -0,0 +1,152 @@
---- TEST 1 - MS-BITFIELDS ----
bits in use : 0000001FFFFFFFFF0000007F00000FFF
bits as set : 00000007605555550000004400000333
values : 333 44 555555 06 07
align/size : 4 16
---- TEST 2 - MS-BITFIELDS ----
bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF
bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003
values : 03 1e 123456789abcdef0 05 fffffffffffffffe
align/size : 8 32
---- TEST 3 - MS-BITFIELDS ----
bits in use : 001F001F0000001F000003FF
bits as set : 000E000600000019000002F5
values : 15 17 19 06 0e
align/size : 4 12
---- TEST 4 - MS-BITFIELDS ----
bits in use : 0007FFFF00000027
bits as set : 00078F0F00000023
values : 03 ffffffff 0f fffffff8 78
align/size : 4 8
---- TEST 5 - MS-BITFIELDS ----
bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
bits as set : 0000000000770044000000000000007800000007F00000000000000123456789
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
align/size : 8 32
---- TEST 6 - MS-BITFIELDS ----
bits in use : 00000000000000700000FFFF000000FFFFFFFFFF
bits as set : 000000000000003000002001000000FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 20
---- TEST 1 - MS-BITFIELDS - PACKED ----
bits in use : 0000001FFFFFFFFF7F00000FFF
bits as set : 00000007605555554400000333
values : 333 44 555555 06 07
align/size : 1 13
---- TEST 2 - MS-BITFIELDS - PACKED ----
bits in use : 00000000000000030F7FFFFFFFFFFFFFFF3F00000FFF
bits as set : 000000000000000205123456789ABCDEF01E00000003
values : 03 1e 123456789abcdef0 05 fffffffffffffffe
align/size : 1 22
---- TEST 3 - MS-BITFIELDS - PACKED ----
bits in use : 001F1F0000001F000003FF
bits as set : 000E0600000019000002F5
values : 15 17 19 06 0e
align/size : 1 11
---- TEST 4 - MS-BITFIELDS - PACKED ----
bits in use : 0007FFFF00000027
bits as set : 00078F0F00000023
values : 03 ffffffff 0f fffffff8 78
align/size : 1 8
---- TEST 5 - MS-BITFIELDS - PACKED ----
bits in use : FFFFFF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
bits as set : 007744000000000000007800000007F00000000000000123456789
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
align/size : 1 27
---- TEST 6 - MS-BITFIELDS - PACKED ----
bits in use : 00000000700000FFFFFFFFFFFFFF
bits as set : 000000003000002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 14
---- TEST 1 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 0000001FFFFFFFFF0000007F00000FFF
bits as set : 00000007605555550000004400000333
values : 333 44 555555 06 07
align/size : 16 16
---- TEST 2 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 0000000000000003000000000000000F7FFFFFFFFFFFFFFF0000003F00000FFF
bits as set : 00000000000000020000000000000005123456789ABCDEF00000001E00000003
values : 03 1e 123456789abcdef0 05 fffffffffffffffe
align/size : 16 32
---- TEST 3 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 0000000000000000000000000000001F000000000000001F0000001F000003FF
bits as set : 0000000000000000000000000000000E000000000000000600000019000002F5
values : 15 17 19 06 0e
align/size : 16 32
---- TEST 4 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 0007FFFF00000027
bits as set : 00078F0F00000023
values : 03 ffffffff 0f fffffff8 78
align/size : 4 8
---- TEST 5 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 00000000FFFF00FF0000003FFFFFFFFF00000007FFFFFFFF00001FFFFFFFFFFF
bits as set : 0000000000770044000000000000007800000007F00000000000000123456789
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
align/size : 8 32
---- TEST 6 - MS-BITFIELDS - WITH ALIGN ----
bits in use : 00000000000000700000FFFF000000FFFFFFFFFF
bits as set : 000000000000003000002001000000FD00000004
values : 01 02 03 04 fffffffd
align/size : 4 20
---- TEST 1 - MS-BITFIELDS - PACKED - WITH ALIGN ----
bits in use : 0000000000001FFFFFFFFF7F00000FFF
bits as set : 00000000000007605555554400000333
values : 333 44 555555 06 07
align/size : 16 16
---- TEST 2 - MS-BITFIELDS - PACKED - WITH ALIGN ----
bits in use : 00000000000000030F0000007FFFFFFFFFFFFFFF3F00000FFF
bits as set : 000000000000000205000000123456789ABCDEF01E00000003
values : 03 1e 123456789abcdef0 05 fffffffffffffffe
align/size : 16 25
---- TEST 3 - MS-BITFIELDS - PACKED - WITH ALIGN ----
bits in use : 001F000000000000001F0000001F000003FF
bits as set : 000E000000000000000600000019000002F5
values : 15 17 19 06 0e
align/size : 16 18
---- TEST 4 - MS-BITFIELDS - PACKED - WITH ALIGN ----
bits in use : 0007FFFF00000027
bits as set : 00078F0F00000023
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
values : 0000000123456789 fffffffff0000000 0000000000000078 44 77
align/size : 1 27
---- TEST 6 - MS-BITFIELDS - PACKED - WITH ALIGN ----
bits in use : 00000000700000FFFFFFFFFFFFFF
bits as set : 000000003000002001FD00000004
values : 01 02 03 04 fffffffd
align/size : 1 14

View File

@ -18,6 +18,9 @@ NORUN =
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
@ -40,26 +43,55 @@ endif
ifeq (,$(filter i386 x86_64,$(ARCH)))
SKIP += 85_asm-outside-function.test
endif
ifeq (-$(findstring gcc,$(CC)-)-,--)
SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
endif
ifeq (-$(CONFIG_WIN32)-$(CONFIG_i386)$(CONFIG_arm)-,--yes-)
SKIP += 95_bitfields_ms.test # type_align is differnt on 32bit-non-windows
endif
all test: $(filter-out $(SKIP),$(TESTS))
all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
%.test: %.c %.expect
@echo Test: $*...
# test -run
@if test -z "$(NORUN)"; then \
$(TCC) $(FLAGS) -run $< $(ARGS) $(FILTER) >$*.output 2>&1 || true; \
else \
$(TCC) $(FLAGS) $< -o ./$*.exe $(FILTER) >$*.output 2>&1; \
./$*.exe $(ARGS) >>$*.output 2>&1 || true; \
fi
@diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output $*.exe
@$(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))
F1 = $(or $(filter $1_%,$(TESTS)),$1_???.test)
F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
# run single test and update .expect file, e.g. "make tests2.37+"
tests2.%+:
@$(MAKE) $(call F2,$(call F1,$*)) --no-print-directory
# run single test, e.g. "make tests2.37"
tests2.%:
@$(MAKE) $(call F1,$*) --no-print-directory
# automatically generate .expect files with gcc:
%.expect : # %.c
(gcc -w $*.c -o a.exe && ./a.exe $(ARGS)) $(FILTER) >$*.expect 2>&1; rm -f a.exe
%.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
@rm -f *.exe *.obj *.pdb
# tell make not to delete
.PRECIOUS: %.expect
$(sort $(GEN-ALWAYS) $(UPDATE)) : force
force:
clean:
rm -f fred.txt *.output a.exe
rm -f fred.txt *.output a.exe $(GEN-ALWAYS)