History

added bitfields support

bellard committed 24 years ago

Commit 3d1bdcf1 parent cb693e51 file · +179 −52Browse files

Unified · Split

tcc.c+179−52
@@ -164,7 +164,7 @@ int gnu_ext = 1; · 163 unmodified lines
164164 #define VT_TYPEDEF 0x00000100 /* typedef definition */
165165
166166 /* types */
167−#define VT_STRUCT_SHIFT 15 /* structure/enum name shift (14 bits left) */
167+#define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
168168
169169 #define VT_BTYPE_SHIFT 9
170170 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
@@ -178,6 +178,7 @@ int gnu_ext = 1; · 7 unmodified lines
178178 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
179179 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
180180 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
181+#define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
181182
182183 #define VT_TYPE 0xfffffe00 /* type mask */
183184
@@ -313,6 +314,7 @@ int get_reg(void); · 129 unmodified lines
313314 void macro_subst(int **tok_str, int *tok_len,
314315 Sym **nested_list, int *macro_str);
315316 int save_reg_forced(int r);
317+void gen_op(int op);
316318 void vstore(void);
317319 int type_size(int t, int *a);
318320 int pointed_type(int t);
@@ -1635,7 +1637,7 @@ void gen_addr32(int c, int t) · 1316 unmodified lines
16351637
16361638 /* XXX: generate correct pointer for forward references to functions */
16371639 /* r = (ft, fc) */
1638−void load(r, ft, fc)
1640+void load(int r, int ft, int fc)
16391641 {
16401642 int v, t;
16411643
@@ -1975,18 +1977,35 @@ void move_reg(r, s) · 333 unmodified lines
19751977 }
19761978 }
19771979
1978−/* convert a stack entry in register. lvalues are converted as
1980+/* convert a (vt, vc) in register. lvalues are converted as
19791981 values. Cannot be used if cannot be converted to register value
19801982 (such as structures). */
1981−int gvp(int *p)
1983+int gvp(void)
19821984 {
1983− int r;
1984− r = p[0] & VT_VALMASK;
1985− if (r >= VT_CONST || (p[0] & VT_LVAL))
1986− r = get_reg();
1987− /* NOTE: get_reg can modify p[] */
1988− load(r, p[0], p[1]);
1989− p[0] = (p[0] & VT_TYPE) | r;
1985+ int r, bit_pos, bit_size;
1986+
1987+ /* NOTE: get_reg can modify vstack[] */
1988+ if (vt & VT_BITFIELD) {
1989+ bit_pos = (vt >> VT_STRUCT_SHIFT) & 0x3f;
1990+ bit_size = (vt >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
1991+ /* remove bit field info to avoid loops */
1992+ vt &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
1993+ /* generate shifts */
1994+ vpush();
1995+ vset(VT_CONST, 32 - (bit_pos + bit_size));
1996+ gen_op(TOK_SHL);
1997+ vpush();
1998+ vset(VT_CONST, 32 - bit_size);
1999+ /* NOTE: transformed to SHR if unsigned */
2000+ gen_op(TOK_SAR);
2001+ r = gv();
2002+ } else {
2003+ r = vt & VT_VALMASK;
2004+ if (r >= VT_CONST || (vt & VT_LVAL))
2005+ r = get_reg();
2006+ load(r, vt, vc);
2007+ vt = (vt & VT_TYPE) | r;
2008+ }
19902009 return r;
19912010 }
19922011
@@ -1994,12 +2013,12 @@ void vpush(void) · 1 unmodified line
19942013 {
19952014 if (vstack_ptr >= vstack + VSTACK_SIZE)
19962015 error("memory full");
1997− *vstack_ptr++ = vt;
1998− *vstack_ptr++ = vc;
19992016 /* cannot let cpu flags if other instruction are generated */
20002017 /* XXX: VT_JMP test too ? */
20012018 if ((vt & VT_VALMASK) == VT_CMP)
2002− gvp(vstack_ptr - 2);
2019+ gvp();
2020+ *vstack_ptr++ = vt;
2021+ *vstack_ptr++ = vc;
20032022 }
20042023
20052024 void vpop(int *ft, int *fc)
@@ -2008,18 +2027,25 @@ void vpop(int *ft, int *fc) · 2 unmodified lines
20082027 *ft = *--vstack_ptr;
20092028 }
20102029
2030+void vswap(void)
2031+{
2032+ swap(vstack_ptr - 4, vstack_ptr - 2);
2033+ swap(vstack_ptr - 3, vstack_ptr - 1);
2034+}
2035+
20112036 /* generate a value in a register from vt and vc */
20122037 int gv(void)
20132038 {
20142039 int r;
2015− vpush();
2016− r = gvp(vstack_ptr - 2);
2017− vpop(&vt, &vc);
2040+ vpush(); /* need so that gvp does not allocate the register we
2041+ currently use */
2042+ r = gvp();
2043+ vstack_ptr -= 2;
20182044 return r;
20192045 }
20202046
20212047 /* handle constant optimizations and various machine independant opt */
2022−void gen_opc(op)
2048+void gen_opc(int op)
20232049 {
20242050 int fr, ft, fc, r, c1, c2, n;
20252051
@@ -2098,11 +2124,15 @@ void gen_opc(op) · 72 unmodified lines
20982124 vpush();
20992125 vt = ft;
21002126 vc = fc;
2127+
2128+ fr = gv(); /* second operand */
2129+ vpop(&ft, &fc);
21012130 vpush();
2102− r = gvp(vstack_ptr - 4);
2103− fr = gvp(vstack_ptr - 2);
2131+ vt = ft;
2132+ vc = fc;
2133+ r = gv(); /* first operand */
21042134 vpop(&ft, &fc);
2105− vpop(&vt, &vc);
2135+
21062136 /* call low level op generator */
21072137 gen_op1(op, r, fr);
21082138 }
@@ -2217,12 +2247,15 @@ int type_size(int t, int *a) · 108 unmodified lines
22172247 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
22182248 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
22192249 return s->c;
2220− } else if (t & VT_ARRAY) {
2221− s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2222− return type_size(s->t, a) * s->c;
2223− } else if (bt == VT_PTR ||
2224− bt == VT_INT ||
2225− bt == VT_ENUM) {
2250+ } else if (bt == VT_PTR) {
2251+ if (t & VT_ARRAY) {
2252+ s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2253+ return type_size(s->t, a) * s->c;
2254+ } else {
2255+ *a = 4;
2256+ return 4;
2257+ }
2258+ } else if (bt == VT_INT || bt == VT_ENUM) {
22262259 *a = 4;
22272260 return 4;
22282261 } else if (bt == VT_SHORT) {
@@ -2254,7 +2287,7 @@ int mk_pointer(int t) · 25 unmodified lines
22542287 /* store value in lvalue pushed on stack */
22552288 void vstore(void)
22562289 {
2257− int ft, fc, r, t, size, align;
2290+ int ft, fc, r, t, size, align, bit_size, bit_pos;
22582291 GFuncContext gf;
22592292
22602293 if ((vt & VT_BTYPE) == VT_STRUCT) {
@@ -2285,6 +2318,31 @@ void vstore(void) · 24 unmodified lines
22852318 /* generate again current type */
22862319 vt = ft;
22872320 vc = fc;
2321+ } else if (vstack_ptr[-2] & VT_BITFIELD) {
2322+ /* bitfield store handling */
2323+ ft = vstack_ptr[-2];
2324+ bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
2325+ bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
2326+ /* remove bit field info to avoid loops */
2327+ vstack_ptr[-2] = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
2328+
2329+ /* mask and shift source */
2330+ vpush();
2331+ vset(VT_CONST, (1 << bit_size) - 1);
2332+ gen_op('&');
2333+ vpush();
2334+ vset(VT_CONST, bit_pos);
2335+ gen_op(TOK_SHL);
2336+ vpush();
2337+ /* load destination, mask and or with source */
2338+ vt = vstack_ptr[-4];
2339+ vc = vstack_ptr[-3];
2340+ vpush();
2341+ vset(VT_CONST, ~(((1 << bit_size) - 1) << bit_pos));
2342+ gen_op('&');
2343+ gen_op('|');
2344+ /* store result */
2345+ vstore();
22882346 } else {
22892347 r = gv(); /* generate value */
22902348 vpush();
@@ -2302,7 +2360,7 @@ void vstore(void) · 11 unmodified lines
23022360 }
23032361
23042362 /* post defines POST/PRE add. c is the token ++ or -- */
2305−void inc(post, c)
2363+void inc(int post, int c)
23062364 {
23072365 int r, r1;
23082366 test_lvalue();
@@ -2329,7 +2387,8 @@ void inc(post, c) · 20 unmodified lines
23292387 /* enum/struct/union declaration */
23302388 int struct_decl(int u)
23312389 {
2332− int a, t, b, v, size, align, maxalign, c;
2390+ int a, t, b, v, size, align, maxalign, c, offset;
2391+ int bit_size, bit_pos, bsize, bt, lbit_pos;
23332392 Sym *s, *ss, **ps;
23342393
23352394 a = tok; /* save decl type */
@@ -2360,6 +2419,8 @@ int struct_decl(int u) · 24 unmodified lines
23602419 c = 0;
23612420 maxalign = 0;
23622421 ps = &s->next;
2422+ bit_pos = 0;
2423+ offset = 0;
23632424 while (1) {
23642425 if (a == TOK_ENUM) {
23652426 v = tok;
@@ -2376,26 +2437,92 @@ int struct_decl(int u) · 10 unmodified lines
23762437 } else {
23772438 b = ist();
23782439 while (1) {
2379− t = type_decl(&v, b, TYPE_DIRECT);
2380− if ((t & VT_BTYPE) == VT_FUNC ||
2381− (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
2382− error("invalid type");
2383− /* XXX: align & correct type size */
2384− v |= SYM_FIELD;
2440+ bit_size = -1;
2441+ v = 0;
2442+ if (tok != ':') {
2443+ t = type_decl(&v, b, TYPE_DIRECT);
2444+ if ((t & VT_BTYPE) == VT_FUNC ||
2445+ (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))
2446+ error("invalid type for '%s'", get_tok_str(v, 0));
2447+ } else {
2448+ t = b;
2449+ }
2450+ if (tok == ':') {
2451+ next();
2452+ bit_size = expr_const();
2453+ /* XXX: handle v = 0 case for messages */
2454+ if (bit_size < 0)
2455+ error("negative width in bit-field '%s'",
2456+ get_tok_str(v, 0));
2457+ if (v && bit_size == 0)
2458+ error("zero width for bit-field '%s'",
2459+ get_tok_str(v, 0));
2460+ }
23852461 size = type_size(t, &align);
2386− if (a == TOK_STRUCT) {
2387− c = (c + align - 1) & -align;
2388− ss = sym_push(v, t, c);
2389− c += size;
2462+ lbit_pos = 0;
2463+ if (bit_size >= 0) {
2464+ bt = t & VT_BTYPE;
2465+ if (bt != VT_INT &&
2466+ bt != VT_BYTE &&
2467+ bt != VT_SHORT)
2468+ error("bitfields must have scalar type");
2469+ bsize = size * 8;
2470+ if (bit_size > bsize) {
2471+ error("width of '%s' exceeds its type",
2472+ get_tok_str(v, 0));
2473+ } else if (bit_size == bsize) {
2474+ /* no need for bit fields */
2475+ bit_pos = 0;
2476+ } else if (bit_size == 0) {
2477+ /* XXX: what to do if only padding in a
2478+ structure ? */
2479+ /* zero size: means to pad */
2480+ if (bit_pos > 0)
2481+ bit_pos = bsize;
2482+ } else {
2483+ /* we do not have enough room ? */
2484+ if ((bit_pos + bit_size) > bsize)
2485+ bit_pos = 0;
2486+ lbit_pos = bit_pos;
2487+ /* XXX: handle LSB first */
2488+ t |= VT_BITFIELD |
2489+ (bit_pos << VT_STRUCT_SHIFT) |
2490+ (bit_size << (VT_STRUCT_SHIFT + 6));
2491+ bit_pos += bit_size;
2492+ }
23902493 } else {
2391− ss = sym_push(v, t, 0);
2392− if (size > c)
2393− c = size;
2494+ bit_pos = 0;
2495+ }
2496+ if (v) {
2497+ /* add new memory data only if starting
2498+ bit field */
2499+ if (lbit_pos == 0) {
2500+ if (a == TOK_STRUCT) {
2501+ c = (c + align - 1) & -align;
2502+ offset = c;
2503+ c += size;
2504+ } else {
2505+ offset = 0;
2506+ if (size > c)
2507+ c = size;
2508+ }
2509+ if (align > maxalign)
2510+ maxalign = align;
2511+ }
2512+#if 0
2513+ printf("add field %s offset=%d",
2514+ get_tok_str(v, 0), offset);
2515+ if (t & VT_BITFIELD) {
2516+ printf(" pos=%d size=%d",
2517+ (t >> VT_STRUCT_SHIFT) & 0x3f,
2518+ (t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
2519+ }
2520+ printf("\n");
2521+#endif
2522+ ss = sym_push(v | SYM_FIELD, t, offset);
2523+ *ps = ss;
2524+ ps = &ss->next;
23942525 }
2395− if (align > maxalign)
2396− maxalign = align;
2397− *ps = ss;
2398− ps = &ss->next;
23992526 if (tok == ';' || tok == -1)
24002527 break;
24012528 skip(',');
@@ -3003,15 +3130,15 @@ int check_assign_types(int t1, int t2) · 601 unmodified lines
30033130 }
30043131
30053132
3006−void uneq()
3133+void uneq(void)
30073134 {
30083135 int t;
30093136
30103137 unary();
3011− if (tok == '=' |
3012− (tok >= TOK_A_MOD & tok <= TOK_A_DIV) |
3013− tok == TOK_A_XOR | tok == TOK_A_OR |
3014− tok == TOK_A_SHL | tok == TOK_A_SAR) {
3138+ if (tok == '=' ||
3139+ (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
3140+ tok == TOK_A_XOR || tok == TOK_A_OR ||
3141+ tok == TOK_A_SHL || tok == TOK_A_SAR) {
30153142 test_lvalue();
30163143 vpush();
30173144 t = tok;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t