@@ -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 ;
@@ -1250,10 +1251,6 @@ void read_full_var_decl(var_t *vd, int anon, int is_param)
12501251
12511252 vd -> type = type ;
12521253
1253- /* Inherit pointer level from typedef */
1254- if (type -> ptr_level > 0 )
1255- vd -> is_ptr = type -> ptr_level ;
1256-
12571254 read_inner_var_decl (vd , anon , is_param );
12581255}
12591256
@@ -1528,8 +1525,28 @@ void handle_single_dereference(block_t *parent, basic_block_t **bb)
15281525 vd = require_deref_var (parent , var -> type , var -> is_ptr );
15291526 if (lvalue .is_ptr > 1 )
15301527 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+ }
15331550 gen_name_to (vd -> var_name );
15341551 opstack_push (vd );
15351552 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)
15871604 lvalue .is_ptr > i ? lvalue .is_ptr - i - 1 : 0 );
15881605 if (lvalue .is_ptr > i + 1 )
15891606 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+ }
15921630 gen_name_to (vd -> var_name );
15931631 opstack_push (vd );
15941632 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)
21562194 if (get_operator_prio (top_op ) >= get_operator_prio (op )) {
21572195 rs2 = opstack_pop ();
21582196 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+
21592290 vd = require_var (parent );
21602291 gen_name_to (vd -> var_name );
21612292 opstack_push (vd );
@@ -2271,6 +2402,91 @@ void read_expr(block_t *parent, basic_block_t **bb)
22712402 rs2 = opstack_pop ();
22722403 rs1 = opstack_pop ();
22732404
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+
22742490 /* Constant folding for binary operations */
22752491 if (rs1 && rs2 && rs1 -> init_val && !rs1 -> is_ptr && !rs1 -> is_global &&
22762492 rs2 -> init_val && !rs2 -> is_ptr && !rs2 -> is_global ) {
@@ -2421,11 +2637,15 @@ void read_lvalue(lvalue_t *lvalue,
24212637 }
24222638
24232639 /* 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 )
24252643 error ("Cannot apply square operator to non-pointer" );
24262644
24272645 /* 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 ) {
24292649 /* For typedef pointers, get the size of the base type that the
24302650 * pointer points to
24312651 */
@@ -2645,7 +2865,31 @@ void read_lvalue(lvalue_t *lvalue,
26452865 side_effect [se_idx ].opcode = OP_load_constant ;
26462866 vd = require_var (parent );
26472867 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+
26492893 side_effect [se_idx ].rd = vd ;
26502894 side_effect [se_idx ].rs1 = NULL ;
26512895 side_effect [se_idx ].rs2 = NULL ;
@@ -2960,6 +3204,27 @@ bool read_body_assignment(char *token,
29603204 */
29613205 if (lvalue .is_ptr && !lvalue .is_reference )
29623206 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+ }
29633228
29643229 /* If operand is a reference, read the value and push to stack for
29653230 * the incoming addition/subtraction. Otherwise, use the top element
0 commit comments