Unified · Split
| @@ -164,7 +164,7 @@ int gnu_ext = 1; · 163 unmodified lines | ||
| 164 | 164 | #define VT_TYPEDEF 0x00000100 /* typedef definition */ |
| 165 | 165 | |
| 166 | 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 | 169 | #define VT_BTYPE_SHIFT 9 |
| 170 | 170 | #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */ |
| @@ -178,6 +178,7 @@ int gnu_ext = 1; · 7 unmodified lines | ||
| 178 | 178 | #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */ |
| 179 | 179 | #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */ |
| 180 | 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 | 183 | #define VT_TYPE 0xfffffe00 /* type mask */ |
| 183 | 184 | |
| @@ -313,6 +314,7 @@ int get_reg(void); · 129 unmodified lines | ||
| 313 | 314 | void macro_subst(int **tok_str, int *tok_len, |
| 314 | 315 | Sym **nested_list, int *macro_str); |
| 315 | 316 | int save_reg_forced(int r); |
| 317 | +void gen_op(int op); | |
| 316 | 318 | void vstore(void); |
| 317 | 319 | int type_size(int t, int *a); |
| 318 | 320 | int pointed_type(int t); |
| @@ -1635,7 +1637,7 @@ void gen_addr32(int c, int t) · 1316 unmodified lines | ||
| 1635 | 1637 | |
| 1636 | 1638 | /* XXX: generate correct pointer for forward references to functions */ |
| 1637 | 1639 | /* r = (ft, fc) */ |
| 1638 | −void load(r, ft, fc) | |
| 1640 | +void load(int r, int ft, int fc) | |
| 1639 | 1641 | { |
| 1640 | 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 as | |
| 1980 | +/* convert a (vt, vc) in register. lvalues are converted as | |
| 1979 | 1981 | values. Cannot be used if cannot be converted to register value |
| 1980 | 1982 | (such as structures). */ |
| 1981 | −int gvp(int *p) | |
| 1983 | +int gvp(void) | |
| 1982 | 1984 | { |
| 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 | + } | |
| 1990 | 2009 | return r; |
| 1991 | 2010 | } |
| 1992 | 2011 | |
| @@ -1994,12 +2013,12 @@ void vpush(void) · 1 unmodified line | ||
| 1994 | 2013 | { |
| 1995 | 2014 | if (vstack_ptr >= vstack + VSTACK_SIZE) |
| 1996 | 2015 | error("memory full"); |
| 1997 | − *vstack_ptr++ = vt; | |
| 1998 | − *vstack_ptr++ = vc; | |
| 1999 | 2016 | /* cannot let cpu flags if other instruction are generated */ |
| 2000 | 2017 | /* XXX: VT_JMP test too ? */ |
| 2001 | 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 | |
| 2005 | 2024 | void vpop(int *ft, int *fc) |
| @@ -2008,18 +2027,25 @@ void vpop(int *ft, int *fc) · 2 unmodified lines | ||
| 2008 | 2027 | *ft = *--vstack_ptr; |
| 2009 | 2028 | } |
| 2010 | 2029 | |
| 2030 | +void vswap(void) | |
| 2031 | +{ | |
| 2032 | + swap(vstack_ptr - 4, vstack_ptr - 2); | |
| 2033 | + swap(vstack_ptr - 3, vstack_ptr - 1); | |
| 2034 | +} | |
| 2035 | + | |
| 2011 | 2036 | /* generate a value in a register from vt and vc */ |
| 2012 | 2037 | int gv(void) |
| 2013 | 2038 | { |
| 2014 | 2039 | 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; | |
| 2018 | 2044 | return r; |
| 2019 | 2045 | } |
| 2020 | 2046 | |
| 2021 | 2047 | /* handle constant optimizations and various machine independant opt */ |
| 2022 | −void gen_opc(op) | |
| 2048 | +void gen_opc(int op) | |
| 2023 | 2049 | { |
| 2024 | 2050 | int fr, ft, fc, r, c1, c2, n; |
| 2025 | 2051 | |
| @@ -2098,11 +2124,15 @@ void gen_opc(op) · 72 unmodified lines | ||
| 2098 | 2124 | vpush(); |
| 2099 | 2125 | vt = ft; |
| 2100 | 2126 | vc = fc; |
| 2127 | + | |
| 2128 | + fr = gv(); /* second operand */ | |
| 2129 | + vpop(&ft, &fc); | |
| 2101 | 2130 | vpush(); |
| 2102 | − r = gvp(vstack_ptr - 4); | |
| 2103 | − fr = gvp(vstack_ptr - 2); | |
| 2131 | + vt = ft; | |
| 2132 | + vc = fc; | |
| 2133 | + r = gv(); /* first operand */ | |
| 2104 | 2134 | vpop(&ft, &fc); |
| 2105 | − vpop(&vt, &vc); | |
| 2135 | + | |
| 2106 | 2136 | /* call low level op generator */ |
| 2107 | 2137 | gen_op1(op, r, fr); |
| 2108 | 2138 | } |
| @@ -2217,12 +2247,15 @@ int type_size(int t, int *a) · 108 unmodified lines | ||
| 2217 | 2247 | s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT) | SYM_STRUCT); |
| 2218 | 2248 | *a = 4; /* XXX: cannot store it yet. Doing that is safe */ |
| 2219 | 2249 | 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) { | |
| 2226 | 2259 | *a = 4; |
| 2227 | 2260 | return 4; |
| 2228 | 2261 | } else if (bt == VT_SHORT) { |
| @@ -2254,7 +2287,7 @@ int mk_pointer(int t) · 25 unmodified lines | ||
| 2254 | 2287 | /* store value in lvalue pushed on stack */ |
| 2255 | 2288 | void 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 | 2291 | GFuncContext gf; |
| 2259 | 2292 | |
| 2260 | 2293 | if ((vt & VT_BTYPE) == VT_STRUCT) { |
| @@ -2285,6 +2318,31 @@ void vstore(void) · 24 unmodified lines | ||
| 2285 | 2318 | /* generate again current type */ |
| 2286 | 2319 | vt = ft; |
| 2287 | 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 | 2346 | } else { |
| 2289 | 2347 | r = gv(); /* generate value */ |
| 2290 | 2348 | vpush(); |
| @@ -2302,7 +2360,7 @@ void vstore(void) · 11 unmodified lines | ||
| 2302 | 2360 | } |
| 2303 | 2361 | |
| 2304 | 2362 | /* post defines POST/PRE add. c is the token ++ or -- */ |
| 2305 | −void inc(post, c) | |
| 2363 | +void inc(int post, int c) | |
| 2306 | 2364 | { |
| 2307 | 2365 | int r, r1; |
| 2308 | 2366 | test_lvalue(); |
| @@ -2329,7 +2387,8 @@ void inc(post, c) · 20 unmodified lines | ||
| 2329 | 2387 | /* enum/struct/union declaration */ |
| 2330 | 2388 | int 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 | 2392 | Sym *s, *ss, **ps; |
| 2334 | 2393 | |
| 2335 | 2394 | a = tok; /* save decl type */ |
| @@ -2360,6 +2419,8 @@ int struct_decl(int u) · 24 unmodified lines | ||
| 2360 | 2419 | c = 0; |
| 2361 | 2420 | maxalign = 0; |
| 2362 | 2421 | ps = &s->next; |
| 2422 | + bit_pos = 0; | |
| 2423 | + offset = 0; | |
| 2363 | 2424 | while (1) { |
| 2364 | 2425 | if (a == TOK_ENUM) { |
| 2365 | 2426 | v = tok; |
| @@ -2376,26 +2437,92 @@ int struct_decl(int u) · 10 unmodified lines | ||
| 2376 | 2437 | } else { |
| 2377 | 2438 | b = ist(); |
| 2378 | 2439 | 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 | + } | |
| 2385 | 2461 | 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 | + } | |
| 2390 | 2493 | } 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; | |
| 2394 | 2525 | } |
| 2395 | − if (align > maxalign) | |
| 2396 | − maxalign = align; | |
| 2397 | − *ps = ss; | |
| 2398 | − ps = &ss->next; | |
| 2399 | 2526 | if (tok == ';' || tok == -1) |
| 2400 | 2527 | break; |
| 2401 | 2528 | skip(','); |
| @@ -3003,15 +3130,15 @@ int check_assign_types(int t1, int t2) · 601 unmodified lines | ||
| 3003 | 3130 | } |
| 3004 | 3131 | |
| 3005 | 3132 | |
| 3006 | −void uneq() | |
| 3133 | +void uneq(void) | |
| 3007 | 3134 | { |
| 3008 | 3135 | int t; |
| 3009 | 3136 | |
| 3010 | 3137 | 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) { | |
| 3015 | 3142 | test_lvalue(); |
| 3016 | 3143 | vpush(); |
| 3017 | 3144 | t = tok; |