@@ -2265,7 +2265,6 @@ void handle_pointer_difference(block_t *parent,
2265
2265
var_t * result = require_var (parent );
2266
2266
gen_name_to (result -> var_name );
2267
2267
add_insn (parent , * bb , OP_div , result , vd , size_const , 0 , NULL );
2268
-
2269
2268
/* Push the result */
2270
2269
opstack_push (result );
2271
2270
} else {
@@ -2285,16 +2284,8 @@ void handle_pointer_arithmetic(block_t *parent,
2285
2284
var_t * int_var = NULL ;
2286
2285
int element_size = 0 ;
2287
2286
2288
- /* FIXME: Integer pointer differences are not fully supported.
2289
- * The type information needed to determine element size is lost
2290
- * when pointer variables are loaded for use in expressions.
2291
- * Character pointer differences work because element size is 1.
2292
- *
2293
- * Current workaround: Cast to char* and divide by sizeof(type)
2294
- * Example: ((char*)q - (char*)p) / sizeof(int)
2295
- *
2296
- * Attempted fixes include looking up original variable declarations,
2297
- * but the fundamental issue remains in the compilation pipeline.
2287
+ /* Pointer arithmetic: differences (char*, int*, struct*, etc.),
2288
+ * addition/increment with scaling, and array indexing.
2298
2289
*/
2299
2290
2300
2291
/* Check if both operands are pointers (pointer difference) */
@@ -2321,6 +2312,16 @@ void handle_pointer_arithmetic(block_t *parent,
2321
2312
bool rs2_is_ptr = (orig_rs2 -> ptr_level > 0 ) ||
2322
2313
(orig_rs2 -> type && orig_rs2 -> type -> ptr_level > 0 );
2323
2314
2315
+ /* If variable lookup failed, check the passed variables directly */
2316
+ if (!rs1_is_ptr ) {
2317
+ rs1_is_ptr =
2318
+ (rs1 -> ptr_level > 0 ) || (rs1 -> type && rs1 -> type -> ptr_level > 0 );
2319
+ }
2320
+ if (!rs2_is_ptr ) {
2321
+ rs2_is_ptr =
2322
+ (rs2 -> ptr_level > 0 ) || (rs2 -> type && rs2 -> type -> ptr_level > 0 );
2323
+ }
2324
+
2324
2325
if (rs1_is_ptr && rs2_is_ptr ) {
2325
2326
/* Both are pointers - this is pointer difference */
2326
2327
/* Determine element size */
@@ -2427,6 +2428,11 @@ void handle_pointer_arithmetic(block_t *parent,
2427
2428
2428
2429
/* Perform the operation */
2429
2430
var_t * vd = require_var (parent );
2431
+ /* Preserve pointer type metadata on results of pointer arithmetic */
2432
+ if (ptr_var ) {
2433
+ vd -> type = ptr_var -> type ;
2434
+ vd -> ptr_level = ptr_var -> ptr_level ;
2435
+ }
2430
2436
gen_name_to (vd -> var_name );
2431
2437
opstack_push (vd );
2432
2438
add_insn (parent , * bb , op , vd , rs1 , rs2 , 0 , NULL );
@@ -2463,41 +2469,6 @@ bool is_pointer_var(var_t *v, block_t *parent)
2463
2469
return false;
2464
2470
}
2465
2471
2466
- /* Helper function to check if it's a pointer difference operation */
2467
- bool is_pointer_difference (opcode_t op , var_t * rs1 , var_t * rs2 )
2468
- {
2469
- if (op != OP_sub )
2470
- return false;
2471
-
2472
- /* Check if both operands are pointers or have pointer types */
2473
- bool rs1_is_ptr =
2474
- rs1 -> ptr_level > 0 || (rs1 -> type && rs1 -> type -> ptr_level > 0 );
2475
- bool rs2_is_ptr =
2476
- rs2 -> ptr_level > 0 || (rs2 -> type && rs2 -> type -> ptr_level > 0 );
2477
-
2478
- /* If both explicitly marked as pointers, it's pointer difference */
2479
- if (rs1_is_ptr && rs2_is_ptr )
2480
- return true;
2481
-
2482
- /* If both variables have the same type and that type has base_type set
2483
- * (indicating they're related to typed data), assume it is pointer
2484
- * subtraction.
2485
- */
2486
- if (rs1 -> type && rs2 -> type ) {
2487
- /* If they have the same type object or same base type, and the
2488
- * base type is not void, treat as pointer difference.
2489
- */
2490
- if ((rs1 -> type == rs2 -> type ||
2491
- rs1 -> type -> base_type == rs2 -> type -> base_type ) &&
2492
- rs1 -> type -> base_type != TYPE_void &&
2493
- rs1 -> type -> base_type != TYPE_struct ) {
2494
- return true;
2495
- }
2496
- }
2497
-
2498
- return false;
2499
- }
2500
-
2501
2472
void read_expr (block_t * parent , basic_block_t * * bb )
2502
2473
{
2503
2474
var_t * vd , * rs1 , * rs2 ;
@@ -2544,14 +2515,10 @@ void read_expr(block_t *parent, basic_block_t **bb)
2544
2515
2545
2516
/* Handle pointer arithmetic for addition and subtraction */
2546
2517
if (is_pointer_operation (top_op , rs1 , rs2 )) {
2547
- if (is_pointer_difference (top_op , rs1 , rs2 )) {
2548
- /* Special case: pointer - pointer difference */
2549
- handle_pointer_difference (parent , bb , rs1 , rs2 );
2550
- } else {
2551
- /* Regular pointer arithmetic with scaling */
2552
- handle_pointer_arithmetic (parent , bb , top_op , rs1 ,
2553
- rs2 );
2554
- }
2518
+ /* handle_pointer_arithmetic handles both pointer
2519
+ * differences and regular pointer arithmetic internally
2520
+ */
2521
+ handle_pointer_arithmetic (parent , bb , top_op , rs1 , rs2 );
2555
2522
oper_stack_idx -- ;
2556
2523
continue ;
2557
2524
}
@@ -2671,90 +2638,10 @@ void read_expr(block_t *parent, basic_block_t **bb)
2671
2638
rs2 = opstack_pop ();
2672
2639
rs1 = opstack_pop ();
2673
2640
2674
- /* Handle pointer arithmetic for addition and subtraction */
2675
- if ((top_op == OP_add || top_op == OP_sub ) &&
2676
- (rs1 -> ptr_level || (rs1 -> type && rs1 -> type -> ptr_level > 0 ) ||
2677
- rs2 -> ptr_level || (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2678
- var_t * ptr_var = NULL ;
2679
- var_t * int_var = NULL ;
2680
- int element_size = 0 ;
2681
-
2682
- /* Determine which operand is the pointer */
2683
- if (rs1 -> ptr_level || (rs1 -> type && rs1 -> type -> ptr_level > 0 )) {
2684
- ptr_var = rs1 ;
2685
- int_var = rs2 ;
2686
-
2687
- /* Calculate element size */
2688
- if (rs1 -> ptr_level && rs1 -> type ) {
2689
- element_size = rs1 -> type -> size ;
2690
- } else if (rs1 -> type && rs1 -> type -> ptr_level > 0 ) {
2691
- /* Typedef pointer */
2692
- switch (rs1 -> type -> base_type ) {
2693
- case TYPE_char :
2694
- element_size = TY_char -> size ;
2695
- break ;
2696
- case TYPE_int :
2697
- element_size = TY_int -> size ;
2698
- break ;
2699
- case TYPE_void :
2700
- element_size = 1 ;
2701
- break ;
2702
- default :
2703
- element_size = rs1 -> type ? rs1 -> type -> size : PTR_SIZE ;
2704
- break ;
2705
- }
2706
- }
2707
- } else if (rs2 -> ptr_level ||
2708
- (rs2 -> type && rs2 -> type -> ptr_level > 0 )) {
2709
- /* Only for addition (p + n == n + p) */
2710
- if (top_op == OP_add ) {
2711
- ptr_var = rs2 ;
2712
- int_var = rs1 ;
2713
-
2714
- /* Calculate element size */
2715
- if (rs2 -> ptr_level && rs2 -> type ) {
2716
- element_size = rs2 -> type -> size ;
2717
- } else if (rs2 -> type && rs2 -> type -> ptr_level > 0 ) {
2718
- /* Typedef pointer */
2719
- switch (rs2 -> type -> base_type ) {
2720
- case TYPE_char :
2721
- element_size = TY_char -> size ;
2722
- break ;
2723
- case TYPE_int :
2724
- element_size = TY_int -> size ;
2725
- break ;
2726
- case TYPE_void :
2727
- element_size = 1 ;
2728
- break ;
2729
- default :
2730
- element_size =
2731
- rs2 -> type ? rs2 -> type -> size : PTR_SIZE ;
2732
- break ;
2733
- }
2734
- }
2735
- /* Swap operands so pointer is rs1 */
2736
- rs1 = ptr_var ;
2737
- rs2 = int_var ;
2738
- }
2739
- }
2740
-
2741
- /* If we need to scale the integer operand */
2742
- if (ptr_var && element_size > 1 ) {
2743
- /* Create multiplication by element size */
2744
- var_t * size_const = require_var (parent );
2745
- gen_name_to (size_const -> var_name );
2746
- size_const -> init_val = element_size ;
2747
- add_insn (parent , * bb , OP_load_constant , size_const , NULL , NULL ,
2748
- 0 , NULL );
2749
-
2750
- var_t * scaled = require_var (parent );
2751
- gen_name_to (scaled -> var_name );
2752
- add_insn (parent , * bb , OP_mul , scaled , int_var , size_const , 0 ,
2753
- NULL );
2754
-
2755
- /* Use scaled value as rs2 */
2756
- rs2 = scaled ;
2757
- }
2641
+ /* Pointer arithmetic handling */
2642
+ if (is_pointer_operation (top_op , rs1 , rs2 )) {
2643
+ handle_pointer_arithmetic (parent , bb , top_op , rs1 , rs2 );
2644
+ continue ; /* skip normal processing */
2758
2645
}
2759
2646
2760
2647
/* Constant folding for binary operations */
@@ -4496,9 +4383,8 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
4496
4383
if (lex_accept (T_assign )) {
4497
4384
if (lex_peek (T_open_curly , NULL ) &&
4498
4385
(var -> array_size > 0 || var -> ptr_level > 0 )) {
4499
- parse_array_init (
4500
- var , parent , & bb ,
4501
- 1 ); /* FIXED: Emit code for locals in functions */
4386
+ /* Emit code for locals in functions */
4387
+ parse_array_init (var , parent , & bb , 1 );
4502
4388
} else if (lex_peek (T_open_curly , NULL ) &&
4503
4389
(var -> type -> base_type == TYPE_struct ||
4504
4390
var -> type -> base_type == TYPE_typedef )) {
@@ -4609,8 +4495,8 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
4609
4495
if (lex_accept (T_assign )) {
4610
4496
if (lex_peek (T_open_curly , NULL ) &&
4611
4497
(nv -> array_size > 0 || nv -> ptr_level > 0 )) {
4612
- parse_array_init ( nv , parent , & bb ,
4613
- 1 ); /* FIXED: Emit code for locals */
4498
+ /* Emit code for locals */
4499
+ parse_array_init ( nv , parent , & bb , 1 );
4614
4500
} else if (lex_peek (T_open_curly , NULL ) &&
4615
4501
(nv -> type -> base_type == TYPE_struct ||
4616
4502
nv -> type -> base_type == TYPE_typedef )) {
0 commit comments