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
164#define VT_TYPEDEF 0x00000100 /* typedef definition */164#define VT_TYPEDEF 0x00000100 /* typedef definition */
165 165
166/* types */166/* 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) */
168 168
169#define VT_BTYPE_SHIFT 9169#define VT_BTYPE_SHIFT 9
170#define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */170#define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
@@ -178,6 +178,7 @@ int gnu_ext = 1; · 7 unmodified lines
178#define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */178#define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
179#define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */179#define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
180#define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */180#define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
181#define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
181 182
182#define VT_TYPE 0xfffffe00 /* type mask */183#define VT_TYPE 0xfffffe00 /* type mask */
183 184
@@ -313,6 +314,7 @@ int get_reg(void); · 129 unmodified lines
313void macro_subst(int **tok_str, int *tok_len, 314void macro_subst(int **tok_str, int *tok_len,
314 Sym **nested_list, int *macro_str);315 Sym **nested_list, int *macro_str);
315int save_reg_forced(int r);316int save_reg_forced(int r);
317void gen_op(int op);
316void vstore(void);318void vstore(void);
317int type_size(int t, int *a);319int type_size(int t, int *a);
318int pointed_type(int t);320int pointed_type(int t);
@@ -1635,7 +1637,7 @@ void gen_addr32(int c, int t) · 1316 unmodified lines
1635 1637
1636/* XXX: generate correct pointer for forward references to functions */1638/* XXX: generate correct pointer for forward references to functions */
1637/* r = (ft, fc) */1639/* r = (ft, fc) */
1638void load(r, ft, fc)1640void load(int r, int ft, int fc)
1639{1641{
1640 int v, t;1642 int v, t;
1641 1643
@@ -1975,18 +1977,35 @@ void move_reg(r, s) · 333 unmodified lines
1975 }1977 }
1976}1978}
1977 1979
1978/* convert a stack entry in register. lvalues are converted as1980/* convert a (vt, vc) in register. lvalues are converted as
1979 values. Cannot be used if cannot be converted to register value1981 values. Cannot be used if cannot be converted to register value
1980 (such as structures). */1982 (such as structures). */
1981int gvp(int *p)1983int gvp(void)
1982{1984{
1983 int r;1985 int r, bit_pos, bit_size;
1984 r = p[0] & VT_VALMASK;1986
1985 if (r >= VT_CONST || (p[0] & VT_LVAL))1987 /* NOTE: get_reg can modify vstack[] */
1986 r = get_reg();1988 if (vt & VT_BITFIELD) {
1987 /* NOTE: get_reg can modify p[] */1989 bit_pos = (vt >> VT_STRUCT_SHIFT) & 0x3f;
1988 load(r, p[0], p[1]);1990 bit_size = (vt >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
1989 p[0] = (p[0] & VT_TYPE) | r;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 }
1990 return r;2009 return r;
1991}2010}
1992 2011
@@ -1994,12 +2013,12 @@ void vpush(void) · 1 unmodified line
1994{2013{
1995 if (vstack_ptr >= vstack + VSTACK_SIZE)2014 if (vstack_ptr >= vstack + VSTACK_SIZE)
1996 error("memory full");2015 error("memory full");
1997 *vstack_ptr++ = vt;
1998 *vstack_ptr++ = vc;
1999 /* cannot let cpu flags if other instruction are generated */2016 /* cannot let cpu flags if other instruction are generated */
2000 /* XXX: VT_JMP test too ? */2017 /* XXX: VT_JMP test too ? */
2001 if ((vt & VT_VALMASK) == VT_CMP)2018 if ((vt & VT_VALMASK) == VT_CMP)
2002 gvp(vstack_ptr - 2);2019 gvp();
2020 *vstack_ptr++ = vt;
2021 *vstack_ptr++ = vc;
2003}2022}
2004 2023
2005void vpop(int *ft, int *fc)2024void vpop(int *ft, int *fc)
@@ -2008,18 +2027,25 @@ void vpop(int *ft, int *fc) · 2 unmodified lines
2008 *ft = *--vstack_ptr;2027 *ft = *--vstack_ptr;
2009}2028}
2010 2029
2030void vswap(void)
2031{
2032 swap(vstack_ptr - 4, vstack_ptr - 2);
2033 swap(vstack_ptr - 3, vstack_ptr - 1);
2034}
2035
2011/* generate a value in a register from vt and vc */2036/* generate a value in a register from vt and vc */
2012int gv(void)2037int gv(void)
2013{2038{
2014 int r;2039 int r;
2015 vpush();2040 vpush(); /* need so that gvp does not allocate the register we
2016 r = gvp(vstack_ptr - 2);2041 currently use */
2017 vpop(&vt, &vc);2042 r = gvp();
2043 vstack_ptr -= 2;
2018 return r;2044 return r;
2019}2045}
2020 2046
2021/* handle constant optimizations and various machine independant opt */2047/* handle constant optimizations and various machine independant opt */
2022void gen_opc(op)2048void gen_opc(int op)
2023{2049{
2024 int fr, ft, fc, r, c1, c2, n;2050 int fr, ft, fc, r, c1, c2, n;
2025 2051
@@ -2098,11 +2124,15 @@ void gen_opc(op) · 72 unmodified lines
2098 vpush();2124 vpush();
2099 vt = ft;2125 vt = ft;
2100 vc = fc;2126 vc = fc;
2127
2128 fr = gv(); /* second operand */
2129 vpop(&ft, &fc);
2101 vpush();2130 vpush();
2102 r = gvp(vstack_ptr - 4);2131 vt = ft;
2103 fr = gvp(vstack_ptr - 2);2132 vc = fc;
2133 r = gv(); /* first operand */
2104 vpop(&ft, &fc);2134 vpop(&ft, &fc);
2105 vpop(&vt, &vc);2135
2106 /* call low level op generator */2136 /* call low level op generator */
2107 gen_op1(op, r, fr);2137 gen_op1(op, r, fr);
2108 }2138 }
@@ -2217,12 +2247,15 @@ int type_size(int t, int *a) · 108 unmodified lines
2217 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);2247 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT);
2218 *a = 4; /* XXX: cannot store it yet. Doing that is safe */2248 *a = 4; /* XXX: cannot store it yet. Doing that is safe */
2219 return s->c;2249 return s->c;
2220 } else if (t & VT_ARRAY) {2250 } else if (bt == VT_PTR) {
2221 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));2251 if (t & VT_ARRAY) {
2222 return type_size(s->t, a) * s->c;2252 s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
2223 } else if (bt == VT_PTR ||2253 return type_size(s->t, a) * s->c;
2224 bt == VT_INT ||2254 } else {
2225 bt == VT_ENUM) {2255 *a = 4;
2256 return 4;
2257 }
2258 } else if (bt == VT_INT || bt == VT_ENUM) {
2226 *a = 4;2259 *a = 4;
2227 return 4;2260 return 4;
2228 } else if (bt == VT_SHORT) {2261 } else if (bt == VT_SHORT) {
@@ -2254,7 +2287,7 @@ int mk_pointer(int t) · 25 unmodified lines
2254/* store value in lvalue pushed on stack */2287/* store value in lvalue pushed on stack */
2255void vstore(void)2288void vstore(void)
2256{2289{
2257 int ft, fc, r, t, size, align;2290 int ft, fc, r, t, size, align, bit_size, bit_pos;
2258 GFuncContext gf;2291 GFuncContext gf;
2259 2292
2260 if ((vt & VT_BTYPE) == VT_STRUCT) {2293 if ((vt & VT_BTYPE) == VT_STRUCT) {
@@ -2285,6 +2318,31 @@ void vstore(void) · 24 unmodified lines
2285 /* generate again current type */2318 /* generate again current type */
2286 vt = ft;2319 vt = ft;
2287 vc = fc;2320 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();
2288 } else {2346 } else {
2289 r = gv(); /* generate value */2347 r = gv(); /* generate value */
2290 vpush();2348 vpush();
@@ -2302,7 +2360,7 @@ void vstore(void) · 11 unmodified lines
2302}2360}
2303 2361
2304/* post defines POST/PRE add. c is the token ++ or -- */2362/* post defines POST/PRE add. c is the token ++ or -- */
2305void inc(post, c)2363void inc(int post, int c)
2306{2364{
2307 int r, r1;2365 int r, r1;
2308 test_lvalue();2366 test_lvalue();
@@ -2329,7 +2387,8 @@ void inc(post, c) · 20 unmodified lines
2329/* enum/struct/union declaration */2387/* enum/struct/union declaration */
2330int struct_decl(int u)2388int struct_decl(int u)
2331{2389{
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;
2333 Sym *s, *ss, **ps;2392 Sym *s, *ss, **ps;
2334 2393
2335 a = tok; /* save decl type */2394 a = tok; /* save decl type */
@@ -2360,6 +2419,8 @@ int struct_decl(int u) · 24 unmodified lines
2360 c = 0;2419 c = 0;
2361 maxalign = 0;2420 maxalign = 0;
2362 ps = &s->next;2421 ps = &s->next;
2422 bit_pos = 0;
2423 offset = 0;
2363 while (1) {2424 while (1) {
2364 if (a == TOK_ENUM) {2425 if (a == TOK_ENUM) {
2365 v = tok;2426 v = tok;
@@ -2376,26 +2437,92 @@ int struct_decl(int u) · 10 unmodified lines
2376 } else {2437 } else {
2377 b = ist();2438 b = ist();
2378 while (1) {2439 while (1) {
2379 t = type_decl(&v, b, TYPE_DIRECT);2440 bit_size = -1;
2380 if ((t & VT_BTYPE) == VT_FUNC ||2441 v = 0;
2381 (t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN)))2442 if (tok != ':') {
2382 error("invalid type");2443 t = type_decl(&v, b, TYPE_DIRECT);
2383 /* XXX: align & correct type size */2444 if ((t & VT_BTYPE) == VT_FUNC ||
2384 v |= SYM_FIELD;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 }
2385 size = type_size(t, &align);2461 size = type_size(t, &align);
2386 if (a == TOK_STRUCT) {2462 lbit_pos = 0;
2387 c = (c + align - 1) & -align;2463 if (bit_size >= 0) {
2388 ss = sym_push(v, t, c);2464 bt = t & VT_BTYPE;
2389 c += size;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 }
2390 } else {2493 } else {
2391 ss = sym_push(v, t, 0);2494 bit_pos = 0;
2392 if (size > c)2495 }
2393 c = size;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;
2394 }2525 }
2395 if (align > maxalign)
2396 maxalign = align;
2397 *ps = ss;
2398 ps = &ss->next;
2399 if (tok == ';' || tok == -1)2526 if (tok == ';' || tok == -1)
2400 break;2527 break;
2401 skip(',');2528 skip(',');
@@ -3003,15 +3130,15 @@ int check_assign_types(int t1, int t2) · 601 unmodified lines
3003}3130}
3004 3131
3005 3132
3006void uneq()3133void uneq(void)
3007{3134{
3008 int t;3135 int t;
3009 3136
3010 unary();3137 unary();
3011 if (tok == '=' | 3138 if (tok == '=' ||
3012 (tok >= TOK_A_MOD & tok <= TOK_A_DIV) |3139 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
3013 tok == TOK_A_XOR | tok == TOK_A_OR | 3140 tok == TOK_A_XOR || tok == TOK_A_OR ||
3014 tok == TOK_A_SHL | tok == TOK_A_SAR) {3141 tok == TOK_A_SHL || tok == TOK_A_SAR) {
3015 test_lvalue();3142 test_lvalue();
3016 vpush();3143 vpush();
3017 t = tok;3144 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