@@ -280,7 +280,8 @@ var_t *truncate_unchecked(block_t *block,
280
280
var_t * resize_var (block_t * block , basic_block_t * * bb , var_t * from , var_t * to )
281
281
{
282
282
bool is_from_ptr = from -> is_ptr || from -> array_size ,
283
- is_to_ptr = to -> is_ptr || to -> array_size ;
283
+ is_to_ptr = to -> is_ptr || to -> array_size ||
284
+ (to -> type && to -> type -> ptr_level > 0 );
284
285
285
286
if (is_from_ptr && is_to_ptr )
286
287
return from ;
@@ -1250,10 +1251,6 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
1250
1251
1251
1252
vd -> type = type ;
1252
1253
1253
- /* Inherit pointer level from typedef */
1254
- if (type -> ptr_level > 0 )
1255
- vd -> is_ptr = type -> ptr_level ;
1256
-
1257
1254
read_inner_var_decl (vd , anon , is_param );
1258
1255
}
1259
1256
@@ -1528,8 +1525,28 @@ void handle_single_dereference(block_t *parent, basic_block_t **bb)
1528
1525
vd = require_deref_var (parent , var -> type , var -> is_ptr );
1529
1526
if (lvalue .is_ptr > 1 )
1530
1527
sz = PTR_SIZE ;
1531
- else
1532
- sz = lvalue .type -> size ;
1528
+ else {
1529
+ /* For typedef pointers, get the size of the pointed-to type */
1530
+ if (lvalue .type && lvalue .type -> ptr_level > 0 ) {
1531
+ /* This is a typedef pointer */
1532
+ switch (lvalue .type -> base_type ) {
1533
+ case TYPE_char :
1534
+ sz = TY_char -> size ;
1535
+ break ;
1536
+ case TYPE_int :
1537
+ sz = TY_int -> size ;
1538
+ break ;
1539
+ case TYPE_void :
1540
+ sz = 1 ;
1541
+ break ;
1542
+ default :
1543
+ sz = lvalue .type -> size ;
1544
+ break ;
1545
+ }
1546
+ } else {
1547
+ sz = lvalue .type -> size ;
1548
+ }
1549
+ }
1533
1550
gen_name_to (vd -> var_name );
1534
1551
opstack_push (vd );
1535
1552
add_insn (parent , * bb , OP_read , vd , rs1 , NULL , sz , NULL );
@@ -1587,8 +1604,29 @@ void handle_multiple_dereference(block_t *parent, basic_block_t **bb)
1587
1604
lvalue .is_ptr > i ? lvalue .is_ptr - i - 1 : 0 );
1588
1605
if (lvalue .is_ptr > i + 1 )
1589
1606
sz = PTR_SIZE ;
1590
- else
1591
- sz = lvalue .type -> size ;
1607
+ else {
1608
+ /* For typedef pointers, get the size of the pointed-to type */
1609
+ if (lvalue .type && lvalue .type -> ptr_level > 0 &&
1610
+ i == deref_count - 1 ) {
1611
+ /* This is a typedef pointer on the final dereference */
1612
+ switch (lvalue .type -> base_type ) {
1613
+ case TYPE_char :
1614
+ sz = TY_char -> size ;
1615
+ break ;
1616
+ case TYPE_int :
1617
+ sz = TY_int -> size ;
1618
+ break ;
1619
+ case TYPE_void :
1620
+ sz = 1 ;
1621
+ break ;
1622
+ default :
1623
+ sz = lvalue .type -> size ;
1624
+ break ;
1625
+ }
1626
+ } else {
1627
+ sz = lvalue .type -> size ;
1628
+ }
1629
+ }
1592
1630
gen_name_to (vd -> var_name );
1593
1631
opstack_push (vd );
1594
1632
add_insn (parent , * bb , OP_read , vd , rs1 , NULL , sz , NULL );
@@ -2156,6 +2194,99 @@ void read_expr(block_t *parent, basic_block_t **bb)
2156
2194
if (get_operator_prio (top_op ) >= get_operator_prio (op )) {
2157
2195
rs2 = opstack_pop ();
2158
2196
rs1 = opstack_pop ();
2197
+
2198
+ /* Handle pointer arithmetic for addition and subtraction */
2199
+ if ((top_op == OP_add || top_op == OP_sub ) &&
2200
+ (rs1 -> is_ptr ||
2201
+ (rs1 -> type && rs1 -> type -> ptr_level > 0 ) ||
2202
+ rs2 -> is_ptr ||
2203
+ (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2204
+ var_t * ptr_var = NULL ;
2205
+ var_t * int_var = NULL ;
2206
+ int element_size = 0 ;
2207
+
2208
+ /* Determine which operand is the pointer */
2209
+ if (rs1 -> is_ptr ||
2210
+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) {
2211
+ ptr_var = rs1 ;
2212
+ int_var = rs2 ;
2213
+
2214
+ /* Calculate element size */
2215
+ if (rs1 -> is_ptr && rs1 -> type ) {
2216
+ element_size = rs1 -> type -> size ;
2217
+ } else if (rs1 -> type && rs1 -> type -> ptr_level > 0 ) {
2218
+ /* Typedef pointer */
2219
+ switch (rs1 -> type -> base_type ) {
2220
+ case TYPE_char :
2221
+ element_size = TY_char -> size ;
2222
+ break ;
2223
+ case TYPE_int :
2224
+ element_size = TY_int -> size ;
2225
+ break ;
2226
+ case TYPE_void :
2227
+ element_size = 1 ;
2228
+ break ;
2229
+ default :
2230
+ element_size =
2231
+ rs1 -> type ? rs1 -> type -> size : PTR_SIZE ;
2232
+ break ;
2233
+ }
2234
+ }
2235
+ } else if (rs2 -> is_ptr ||
2236
+ (rs2 -> type && rs2 -> type -> ptr_level > 0 )) {
2237
+ /* Only for addition (p + n == n + p) */
2238
+ if (top_op == OP_add ) {
2239
+ ptr_var = rs2 ;
2240
+ int_var = rs1 ;
2241
+
2242
+ /* Calculate element size */
2243
+ if (rs2 -> is_ptr && rs2 -> type ) {
2244
+ element_size = rs2 -> type -> size ;
2245
+ } else if (rs2 -> type &&
2246
+ rs2 -> type -> ptr_level > 0 ) {
2247
+ /* Typedef pointer */
2248
+ switch (rs2 -> type -> base_type ) {
2249
+ case TYPE_char :
2250
+ element_size = TY_char -> size ;
2251
+ break ;
2252
+ case TYPE_int :
2253
+ element_size = TY_int -> size ;
2254
+ break ;
2255
+ case TYPE_void :
2256
+ element_size = 1 ;
2257
+ break ;
2258
+ default :
2259
+ element_size = rs2 -> type
2260
+ ? rs2 -> type -> size
2261
+ : PTR_SIZE ;
2262
+ break ;
2263
+ }
2264
+ }
2265
+ /* Swap operands so pointer is rs1 */
2266
+ rs1 = ptr_var ;
2267
+ rs2 = int_var ;
2268
+ }
2269
+ }
2270
+
2271
+ /* If we need to scale the integer operand */
2272
+ if (ptr_var && element_size > 1 ) {
2273
+ /* Create multiplication by element size */
2274
+ var_t * size_const = require_var (parent );
2275
+ gen_name_to (size_const -> var_name );
2276
+ size_const -> init_val = element_size ;
2277
+ add_insn (parent , * bb , OP_load_constant , size_const ,
2278
+ NULL , NULL , 0 , NULL );
2279
+
2280
+ var_t * scaled = require_var (parent );
2281
+ gen_name_to (scaled -> var_name );
2282
+ add_insn (parent , * bb , OP_mul , scaled , int_var ,
2283
+ size_const , 0 , NULL );
2284
+
2285
+ /* Use scaled value as rs2 */
2286
+ rs2 = scaled ;
2287
+ }
2288
+ }
2289
+
2159
2290
vd = require_var (parent );
2160
2291
gen_name_to (vd -> var_name );
2161
2292
opstack_push (vd );
@@ -2271,6 +2402,91 @@ void read_expr(block_t *parent, basic_block_t **bb)
2271
2402
rs2 = opstack_pop ();
2272
2403
rs1 = opstack_pop ();
2273
2404
2405
+ /* Handle pointer arithmetic for addition and subtraction */
2406
+ if ((top_op == OP_add || top_op == OP_sub ) &&
2407
+ (rs1 -> is_ptr || (rs1 -> type && rs1 -> type -> ptr_level > 0 ) ||
2408
+ rs2 -> is_ptr || (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2409
+ var_t * ptr_var = NULL ;
2410
+ var_t * int_var = NULL ;
2411
+ int element_size = 0 ;
2412
+
2413
+ /* Determine which operand is the pointer */
2414
+ if (rs1 -> is_ptr || (rs1 -> type && rs1 -> type -> ptr_level > 0 )) {
2415
+ ptr_var = rs1 ;
2416
+ int_var = rs2 ;
2417
+
2418
+ /* Calculate element size */
2419
+ if (rs1 -> is_ptr && rs1 -> type ) {
2420
+ element_size = rs1 -> type -> size ;
2421
+ } else if (rs1 -> type && rs1 -> type -> ptr_level > 0 ) {
2422
+ /* Typedef pointer */
2423
+ switch (rs1 -> type -> base_type ) {
2424
+ case TYPE_char :
2425
+ element_size = TY_char -> size ;
2426
+ break ;
2427
+ case TYPE_int :
2428
+ element_size = TY_int -> size ;
2429
+ break ;
2430
+ case TYPE_void :
2431
+ element_size = 1 ;
2432
+ break ;
2433
+ default :
2434
+ element_size = rs1 -> type ? rs1 -> type -> size : PTR_SIZE ;
2435
+ break ;
2436
+ }
2437
+ }
2438
+ } else if (rs2 -> is_ptr || (rs2 -> type && rs2 -> type -> ptr_level > 0 )) {
2439
+ /* Only for addition (p + n == n + p) */
2440
+ if (top_op == OP_add ) {
2441
+ ptr_var = rs2 ;
2442
+ int_var = rs1 ;
2443
+
2444
+ /* Calculate element size */
2445
+ if (rs2 -> is_ptr && rs2 -> type ) {
2446
+ element_size = rs2 -> type -> size ;
2447
+ } else if (rs2 -> type && rs2 -> type -> ptr_level > 0 ) {
2448
+ /* Typedef pointer */
2449
+ switch (rs2 -> type -> base_type ) {
2450
+ case TYPE_char :
2451
+ element_size = TY_char -> size ;
2452
+ break ;
2453
+ case TYPE_int :
2454
+ element_size = TY_int -> size ;
2455
+ break ;
2456
+ case TYPE_void :
2457
+ element_size = 1 ;
2458
+ break ;
2459
+ default :
2460
+ element_size =
2461
+ rs2 -> type ? rs2 -> type -> size : PTR_SIZE ;
2462
+ break ;
2463
+ }
2464
+ }
2465
+ /* Swap operands so pointer is rs1 */
2466
+ rs1 = ptr_var ;
2467
+ rs2 = int_var ;
2468
+ }
2469
+ }
2470
+
2471
+ /* If we need to scale the integer operand */
2472
+ if (ptr_var && element_size > 1 ) {
2473
+ /* Create multiplication by element size */
2474
+ var_t * size_const = require_var (parent );
2475
+ gen_name_to (size_const -> var_name );
2476
+ size_const -> init_val = element_size ;
2477
+ add_insn (parent , * bb , OP_load_constant , size_const , NULL , NULL ,
2478
+ 0 , NULL );
2479
+
2480
+ var_t * scaled = require_var (parent );
2481
+ gen_name_to (scaled -> var_name );
2482
+ add_insn (parent , * bb , OP_mul , scaled , int_var , size_const , 0 ,
2483
+ NULL );
2484
+
2485
+ /* Use scaled value as rs2 */
2486
+ rs2 = scaled ;
2487
+ }
2488
+ }
2489
+
2274
2490
/* Constant folding for binary operations */
2275
2491
if (rs1 && rs2 && rs1 -> init_val && !rs1 -> is_ptr && !rs1 -> is_global &&
2276
2492
rs2 -> init_val && !rs2 -> is_ptr && !rs2 -> is_global ) {
@@ -2421,11 +2637,15 @@ void read_lvalue(lvalue_t *lvalue,
2421
2637
}
2422
2638
2423
2639
/* var must be either a pointer or an array of some type */
2424
- if (var -> is_ptr == 0 && var -> array_size == 0 )
2640
+ /* For typedef pointers, check the type's ptr_level */
2641
+ bool is_typedef_pointer = (var -> type && var -> type -> ptr_level > 0 );
2642
+ if (var -> is_ptr == 0 && var -> array_size == 0 && !is_typedef_pointer )
2425
2643
error ("Cannot apply square operator to non-pointer" );
2426
2644
2427
2645
/* if nested pointer, still pointer */
2428
- if (var -> is_ptr <= 1 && var -> array_size == 0 ) {
2646
+ /* Also handle typedef pointers which have is_ptr == 0 */
2647
+ if ((var -> is_ptr <= 1 || is_typedef_pointer ) &&
2648
+ var -> array_size == 0 ) {
2429
2649
/* For typedef pointers, get the size of the base type that the
2430
2650
* pointer points to
2431
2651
*/
@@ -2645,7 +2865,31 @@ void read_lvalue(lvalue_t *lvalue,
2645
2865
side_effect [se_idx ].opcode = OP_load_constant ;
2646
2866
vd = require_var (parent );
2647
2867
gen_name_to (vd -> var_name );
2648
- vd -> init_val = 1 ;
2868
+
2869
+ /* Calculate increment size based on pointer type */
2870
+ int increment_size = 1 ;
2871
+ if (lvalue -> is_ptr && !lvalue -> is_reference ) {
2872
+ increment_size = lvalue -> type -> size ;
2873
+ } else if (!lvalue -> is_reference && lvalue -> type &&
2874
+ lvalue -> type -> ptr_level > 0 ) {
2875
+ /* This is a typedef pointer */
2876
+ switch (lvalue -> type -> base_type ) {
2877
+ case TYPE_char :
2878
+ increment_size = TY_char -> size ;
2879
+ break ;
2880
+ case TYPE_int :
2881
+ increment_size = TY_int -> size ;
2882
+ break ;
2883
+ case TYPE_void :
2884
+ increment_size = 1 ;
2885
+ break ;
2886
+ default :
2887
+ increment_size = lvalue -> type -> size ;
2888
+ break ;
2889
+ }
2890
+ }
2891
+ vd -> init_val = increment_size ;
2892
+
2649
2893
side_effect [se_idx ].rd = vd ;
2650
2894
side_effect [se_idx ].rs1 = NULL ;
2651
2895
side_effect [se_idx ].rs2 = NULL ;
@@ -2960,6 +3204,27 @@ bool read_body_assignment(char *token,
2960
3204
*/
2961
3205
if (lvalue .is_ptr && !lvalue .is_reference )
2962
3206
increment_size = lvalue .type -> size ;
3207
+ /* Also check for typedef pointers which have is_ptr == 0 */
3208
+ else if (!lvalue .is_reference && lvalue .type &&
3209
+ lvalue .type -> ptr_level > 0 ) {
3210
+ /* This is a typedef pointer, get the base type size */
3211
+ switch (lvalue .type -> base_type ) {
3212
+ case TYPE_char :
3213
+ increment_size = TY_char -> size ;
3214
+ break ;
3215
+ case TYPE_int :
3216
+ increment_size = TY_int -> size ;
3217
+ break ;
3218
+ case TYPE_void :
3219
+ /* void pointers treated as byte pointers */
3220
+ increment_size = 1 ;
3221
+ break ;
3222
+ default :
3223
+ /* For struct pointers and other types */
3224
+ increment_size = lvalue .type -> size ;
3225
+ break ;
3226
+ }
3227
+ }
2963
3228
2964
3229
/* If operand is a reference, read the value and push to stack for
2965
3230
* the incoming addition/subtraction. Otherwise, use the top element
0 commit comments