@@ -280,7 +280,8 @@ var_t *truncate_unchecked(block_t *block,
280280var_t * resize_var (block_t * block , basic_block_t * * bb , var_t * from , var_t * to )
281281{
282282 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 );
284285
285286 if (is_from_ptr && is_to_ptr )
286287 return from ;
@@ -1289,10 +1290,6 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
12891290
12901291 vd -> type = type ;
12911292
1292- /* Inherit pointer level from typedef */
1293- if (type -> ptr_level > 0 )
1294- vd -> is_ptr = type -> ptr_level ;
1295-
12961293 read_inner_var_decl (vd , anon , is_param );
12971294}
12981295
@@ -1567,8 +1564,28 @@ void handle_single_dereference(block_t *parent, basic_block_t **bb)
15671564 vd = require_deref_var (parent , var -> type , var -> is_ptr );
15681565 if (lvalue .is_ptr > 1 )
15691566 sz = PTR_SIZE ;
1570- else
1571- sz = lvalue .type -> size ;
1567+ else {
1568+ /* For typedef pointers, get the size of the pointed-to type */
1569+ if (lvalue .type && lvalue .type -> ptr_level > 0 ) {
1570+ /* This is a typedef pointer */
1571+ switch (lvalue .type -> base_type ) {
1572+ case TYPE_char :
1573+ sz = TY_char -> size ;
1574+ break ;
1575+ case TYPE_int :
1576+ sz = TY_int -> size ;
1577+ break ;
1578+ case TYPE_void :
1579+ sz = 1 ;
1580+ break ;
1581+ default :
1582+ sz = lvalue .type -> size ;
1583+ break ;
1584+ }
1585+ } else {
1586+ sz = lvalue .type -> size ;
1587+ }
1588+ }
15721589 gen_name_to (vd -> var_name );
15731590 opstack_push (vd );
15741591 add_insn (parent , * bb , OP_read , vd , rs1 , NULL , sz , NULL );
@@ -1626,8 +1643,29 @@ void handle_multiple_dereference(block_t *parent, basic_block_t **bb)
16261643 lvalue .is_ptr > i ? lvalue .is_ptr - i - 1 : 0 );
16271644 if (lvalue .is_ptr > i + 1 )
16281645 sz = PTR_SIZE ;
1629- else
1630- sz = lvalue .type -> size ;
1646+ else {
1647+ /* For typedef pointers, get the size of the pointed-to type */
1648+ if (lvalue .type && lvalue .type -> ptr_level > 0 &&
1649+ i == deref_count - 1 ) {
1650+ /* This is a typedef pointer on the final dereference */
1651+ switch (lvalue .type -> base_type ) {
1652+ case TYPE_char :
1653+ sz = TY_char -> size ;
1654+ break ;
1655+ case TYPE_int :
1656+ sz = TY_int -> size ;
1657+ break ;
1658+ case TYPE_void :
1659+ sz = 1 ;
1660+ break ;
1661+ default :
1662+ sz = lvalue .type -> size ;
1663+ break ;
1664+ }
1665+ } else {
1666+ sz = lvalue .type -> size ;
1667+ }
1668+ }
16311669 gen_name_to (vd -> var_name );
16321670 opstack_push (vd );
16331671 add_insn (parent , * bb , OP_read , vd , rs1 , NULL , sz , NULL );
@@ -2195,6 +2233,99 @@ void read_expr(block_t *parent, basic_block_t **bb)
21952233 if (get_operator_prio (top_op ) >= get_operator_prio (op )) {
21962234 rs2 = opstack_pop ();
21972235 rs1 = opstack_pop ();
2236+
2237+ /* Handle pointer arithmetic for addition and subtraction */
2238+ if ((top_op == OP_add || top_op == OP_sub ) &&
2239+ (rs1 -> is_ptr ||
2240+ (rs1 -> type && rs1 -> type -> ptr_level > 0 ) ||
2241+ rs2 -> is_ptr ||
2242+ (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2243+ var_t * ptr_var = NULL ;
2244+ var_t * int_var = NULL ;
2245+ int element_size = 0 ;
2246+
2247+ /* Determine which operand is the pointer */
2248+ if (rs1 -> is_ptr ||
2249+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) {
2250+ ptr_var = rs1 ;
2251+ int_var = rs2 ;
2252+
2253+ /* Calculate element size */
2254+ if (rs1 -> is_ptr && rs1 -> type ) {
2255+ element_size = rs1 -> type -> size ;
2256+ } else if (rs1 -> type && rs1 -> type -> ptr_level > 0 ) {
2257+ /* Typedef pointer */
2258+ switch (rs1 -> type -> base_type ) {
2259+ case TYPE_char :
2260+ element_size = TY_char -> size ;
2261+ break ;
2262+ case TYPE_int :
2263+ element_size = TY_int -> size ;
2264+ break ;
2265+ case TYPE_void :
2266+ element_size = 1 ;
2267+ break ;
2268+ default :
2269+ element_size =
2270+ rs1 -> type ? rs1 -> type -> size : PTR_SIZE ;
2271+ break ;
2272+ }
2273+ }
2274+ } else if (rs2 -> is_ptr ||
2275+ (rs2 -> type && rs2 -> type -> ptr_level > 0 )) {
2276+ /* Only for addition (p + n == n + p) */
2277+ if (top_op == OP_add ) {
2278+ ptr_var = rs2 ;
2279+ int_var = rs1 ;
2280+
2281+ /* Calculate element size */
2282+ if (rs2 -> is_ptr && rs2 -> type ) {
2283+ element_size = rs2 -> type -> size ;
2284+ } else if (rs2 -> type &&
2285+ rs2 -> type -> ptr_level > 0 ) {
2286+ /* Typedef pointer */
2287+ switch (rs2 -> type -> base_type ) {
2288+ case TYPE_char :
2289+ element_size = TY_char -> size ;
2290+ break ;
2291+ case TYPE_int :
2292+ element_size = TY_int -> size ;
2293+ break ;
2294+ case TYPE_void :
2295+ element_size = 1 ;
2296+ break ;
2297+ default :
2298+ element_size = rs2 -> type
2299+ ? rs2 -> type -> size
2300+ : PTR_SIZE ;
2301+ break ;
2302+ }
2303+ }
2304+ /* Swap operands so pointer is rs1 */
2305+ rs1 = ptr_var ;
2306+ rs2 = int_var ;
2307+ }
2308+ }
2309+
2310+ /* If we need to scale the integer operand */
2311+ if (ptr_var && element_size > 1 ) {
2312+ /* Create multiplication by element size */
2313+ var_t * size_const = require_var (parent );
2314+ gen_name_to (size_const -> var_name );
2315+ size_const -> init_val = element_size ;
2316+ add_insn (parent , * bb , OP_load_constant , size_const ,
2317+ NULL , NULL , 0 , NULL );
2318+
2319+ var_t * scaled = require_var (parent );
2320+ gen_name_to (scaled -> var_name );
2321+ add_insn (parent , * bb , OP_mul , scaled , int_var ,
2322+ size_const , 0 , NULL );
2323+
2324+ /* Use scaled value as rs2 */
2325+ rs2 = scaled ;
2326+ }
2327+ }
2328+
21982329 vd = require_var (parent );
21992330 gen_name_to (vd -> var_name );
22002331 opstack_push (vd );
@@ -2310,6 +2441,91 @@ void read_expr(block_t *parent, basic_block_t **bb)
23102441 rs2 = opstack_pop ();
23112442 rs1 = opstack_pop ();
23122443
2444+ /* Handle pointer arithmetic for addition and subtraction */
2445+ if ((top_op == OP_add || top_op == OP_sub ) &&
2446+ (rs1 -> is_ptr || (rs1 -> type && rs1 -> type -> ptr_level > 0 ) ||
2447+ rs2 -> is_ptr || (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2448+ var_t * ptr_var = NULL ;
2449+ var_t * int_var = NULL ;
2450+ int element_size = 0 ;
2451+
2452+ /* Determine which operand is the pointer */
2453+ if (rs1 -> is_ptr || (rs1 -> type && rs1 -> type -> ptr_level > 0 )) {
2454+ ptr_var = rs1 ;
2455+ int_var = rs2 ;
2456+
2457+ /* Calculate element size */
2458+ if (rs1 -> is_ptr && rs1 -> type ) {
2459+ element_size = rs1 -> type -> size ;
2460+ } else if (rs1 -> type && rs1 -> type -> ptr_level > 0 ) {
2461+ /* Typedef pointer */
2462+ switch (rs1 -> type -> base_type ) {
2463+ case TYPE_char :
2464+ element_size = TY_char -> size ;
2465+ break ;
2466+ case TYPE_int :
2467+ element_size = TY_int -> size ;
2468+ break ;
2469+ case TYPE_void :
2470+ element_size = 1 ;
2471+ break ;
2472+ default :
2473+ element_size = rs1 -> type ? rs1 -> type -> size : PTR_SIZE ;
2474+ break ;
2475+ }
2476+ }
2477+ } else if (rs2 -> is_ptr || (rs2 -> type && rs2 -> type -> ptr_level > 0 )) {
2478+ /* Only for addition (p + n == n + p) */
2479+ if (top_op == OP_add ) {
2480+ ptr_var = rs2 ;
2481+ int_var = rs1 ;
2482+
2483+ /* Calculate element size */
2484+ if (rs2 -> is_ptr && rs2 -> type ) {
2485+ element_size = rs2 -> type -> size ;
2486+ } else if (rs2 -> type && rs2 -> type -> ptr_level > 0 ) {
2487+ /* Typedef pointer */
2488+ switch (rs2 -> type -> base_type ) {
2489+ case TYPE_char :
2490+ element_size = TY_char -> size ;
2491+ break ;
2492+ case TYPE_int :
2493+ element_size = TY_int -> size ;
2494+ break ;
2495+ case TYPE_void :
2496+ element_size = 1 ;
2497+ break ;
2498+ default :
2499+ element_size =
2500+ rs2 -> type ? rs2 -> type -> size : PTR_SIZE ;
2501+ break ;
2502+ }
2503+ }
2504+ /* Swap operands so pointer is rs1 */
2505+ rs1 = ptr_var ;
2506+ rs2 = int_var ;
2507+ }
2508+ }
2509+
2510+ /* If we need to scale the integer operand */
2511+ if (ptr_var && element_size > 1 ) {
2512+ /* Create multiplication by element size */
2513+ var_t * size_const = require_var (parent );
2514+ gen_name_to (size_const -> var_name );
2515+ size_const -> init_val = element_size ;
2516+ add_insn (parent , * bb , OP_load_constant , size_const , NULL , NULL ,
2517+ 0 , NULL );
2518+
2519+ var_t * scaled = require_var (parent );
2520+ gen_name_to (scaled -> var_name );
2521+ add_insn (parent , * bb , OP_mul , scaled , int_var , size_const , 0 ,
2522+ NULL );
2523+
2524+ /* Use scaled value as rs2 */
2525+ rs2 = scaled ;
2526+ }
2527+ }
2528+
23132529 /* Constant folding for binary operations */
23142530 if (rs1 && rs2 && rs1 -> init_val && !rs1 -> is_ptr && !rs1 -> is_global &&
23152531 rs2 -> init_val && !rs2 -> is_ptr && !rs2 -> is_global ) {
@@ -2460,11 +2676,15 @@ void read_lvalue(lvalue_t *lvalue,
24602676 }
24612677
24622678 /* var must be either a pointer or an array of some type */
2463- if (var -> is_ptr == 0 && var -> array_size == 0 )
2679+ /* For typedef pointers, check the type's ptr_level */
2680+ bool is_typedef_pointer = (var -> type && var -> type -> ptr_level > 0 );
2681+ if (var -> is_ptr == 0 && var -> array_size == 0 && !is_typedef_pointer )
24642682 error ("Cannot apply square operator to non-pointer" );
24652683
24662684 /* if nested pointer, still pointer */
2467- if (var -> is_ptr <= 1 && var -> array_size == 0 ) {
2685+ /* Also handle typedef pointers which have is_ptr == 0 */
2686+ if ((var -> is_ptr <= 1 || is_typedef_pointer ) &&
2687+ var -> array_size == 0 ) {
24682688 /* For typedef pointers, get the size of the base type that the
24692689 * pointer points to
24702690 */
@@ -2693,7 +2913,31 @@ void read_lvalue(lvalue_t *lvalue,
26932913 side_effect [se_idx ].opcode = OP_load_constant ;
26942914 vd = require_var (parent );
26952915 gen_name_to (vd -> var_name );
2696- vd -> init_val = 1 ;
2916+
2917+ /* Calculate increment size based on pointer type */
2918+ int increment_size = 1 ;
2919+ if (lvalue -> is_ptr && !lvalue -> is_reference ) {
2920+ increment_size = lvalue -> type -> size ;
2921+ } else if (!lvalue -> is_reference && lvalue -> type &&
2922+ lvalue -> type -> ptr_level > 0 ) {
2923+ /* This is a typedef pointer */
2924+ switch (lvalue -> type -> base_type ) {
2925+ case TYPE_char :
2926+ increment_size = TY_char -> size ;
2927+ break ;
2928+ case TYPE_int :
2929+ increment_size = TY_int -> size ;
2930+ break ;
2931+ case TYPE_void :
2932+ increment_size = 1 ;
2933+ break ;
2934+ default :
2935+ increment_size = lvalue -> type -> size ;
2936+ break ;
2937+ }
2938+ }
2939+ vd -> init_val = increment_size ;
2940+
26972941 side_effect [se_idx ].rd = vd ;
26982942 side_effect [se_idx ].rs1 = NULL ;
26992943 side_effect [se_idx ].rs2 = NULL ;
@@ -3008,6 +3252,27 @@ bool read_body_assignment(char *token,
30083252 */
30093253 if (lvalue .is_ptr && !lvalue .is_reference )
30103254 increment_size = lvalue .type -> size ;
3255+ /* Also check for typedef pointers which have is_ptr == 0 */
3256+ else if (!lvalue .is_reference && lvalue .type &&
3257+ lvalue .type -> ptr_level > 0 ) {
3258+ /* This is a typedef pointer, get the base type size */
3259+ switch (lvalue .type -> base_type ) {
3260+ case TYPE_char :
3261+ increment_size = TY_char -> size ;
3262+ break ;
3263+ case TYPE_int :
3264+ increment_size = TY_int -> size ;
3265+ break ;
3266+ case TYPE_void :
3267+ /* void pointers treated as byte pointers */
3268+ increment_size = 1 ;
3269+ break ;
3270+ default :
3271+ /* For struct pointers and other types */
3272+ increment_size = lvalue .type -> size ;
3273+ break ;
3274+ }
3275+ }
30113276
30123277 /* If operand is a reference, read the value and push to stack for
30133278 * the incoming addition/subtraction. Otherwise, use the top element
0 commit comments