Unified · Split
| @@ -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 9 | 169 | #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 | |||
| 313 | void macro_subst(int **tok_str, int *tok_len, | 314 | void macro_subst(int **tok_str, int *tok_len, |
| 314 | Sym **nested_list, int *macro_str); | 315 | Sym **nested_list, int *macro_str); |
| 315 | int save_reg_forced(int r); | 316 | int save_reg_forced(int r); |
| 317 | void gen_op(int op); | ||
| 316 | void vstore(void); | 318 | void vstore(void); |
| 317 | int type_size(int t, int *a); | 319 | int type_size(int t, int *a); |
| 318 | int pointed_type(int t); | 320 | int 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) */ |
| 1638 | void load(r, ft, fc) | 1640 | void 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 as | 1980 | /* convert a (vt, vc) in register. lvalues are converted as |
| 1979 | values. Cannot be used if cannot be converted to register value | 1981 | values. Cannot be used if cannot be converted to register value |
| 1980 | (such as structures). */ | 1982 | (such as structures). */ |
| 1981 | int gvp(int *p) | 1983 | int 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 | ||
| 2005 | void vpop(int *ft, int *fc) | 2024 | void 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 | ||
| 2030 | void 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 */ |
| 2012 | int gv(void) | 2037 | int 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 */ |
| 2022 | void gen_opc(op) | 2048 | void 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 */ |
| 2255 | void vstore(void) | 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 | 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 -- */ |
| 2305 | void inc(post, c) | 2363 | void 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 */ |
| 2330 | int struct_decl(int u) | 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 | 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 | ||
| 3006 | void uneq() | 3133 | void 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; |