@@ -2159,7 +2159,164 @@ void read_expr(block_t *parent, basic_block_t **bb)
21592159 vd = require_var (parent );
21602160 gen_name_to (vd -> var_name );
21612161 opstack_push (vd );
2162- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2162+
2163+ /* Handle pointer arithmetic:
2164+ * - If both operands are pointers (subtraction), divide by
2165+ * element size
2166+ * - If one operand is a pointer, handle scaling
2167+ * appropriately
2168+ */
2169+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2170+ /* Subtracting two pointers - divide by element size */
2171+ var_t * diff = require_var (parent );
2172+ gen_name_to (diff -> var_name );
2173+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2174+
2175+ /* Get the element size */
2176+ int elem_size = 4 ; /* Default to int size */
2177+ if (rs1 -> type ) {
2178+ /* For pointers, check what they point to */
2179+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2180+ switch (rs1 -> type -> base_type ) {
2181+ case TYPE_char :
2182+ elem_size = 1 ;
2183+ break ;
2184+ case TYPE_int :
2185+ elem_size = 4 ;
2186+ break ;
2187+ default :
2188+ elem_size = 4 ;
2189+ break ;
2190+ }
2191+ } else {
2192+ /* For non-pointers, use the type size */
2193+ if (rs1 -> type -> size > 0 ) {
2194+ elem_size = rs1 -> type -> size ;
2195+ } else {
2196+ elem_size = 4 ;
2197+ }
2198+ }
2199+ }
2200+
2201+ /* Divide by element size */
2202+ if (elem_size > 1 ) {
2203+ var_t * size_const = require_var (parent );
2204+ size_const -> init_val = elem_size ;
2205+ gen_name_to (size_const -> var_name );
2206+ add_insn (parent , * bb , OP_load_constant , size_const ,
2207+ NULL , NULL , 0 , NULL );
2208+ add_insn (parent , * bb , OP_div , vd , diff , size_const ,
2209+ 0 , NULL );
2210+ } else {
2211+ /* If element size is 1, no division needed - use
2212+ * assignment */
2213+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2214+ NULL );
2215+ }
2216+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2217+ (rs1 -> is_ptr ||
2218+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2219+ !rs2 -> is_ptr ) {
2220+ /* Pointer +/- integer: scale the integer by element
2221+ * size */
2222+ int elem_size = 4 ;
2223+ if (rs1 -> type ) {
2224+ /* For pointers, check what they point to */
2225+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2226+ switch (rs1 -> type -> base_type ) {
2227+ case TYPE_char :
2228+ elem_size = 1 ;
2229+ break ;
2230+ case TYPE_int :
2231+ elem_size = 4 ;
2232+ break ;
2233+ default :
2234+ elem_size = 4 ;
2235+ break ;
2236+ }
2237+ } else {
2238+ /* For non-pointers, use the type size */
2239+ if (rs1 -> type -> size > 0 ) {
2240+ elem_size = rs1 -> type -> size ;
2241+ } else {
2242+ elem_size = 4 ;
2243+ }
2244+ }
2245+ }
2246+
2247+ /* Scale the integer operand if needed */
2248+ if (elem_size > 1 ) {
2249+ var_t * scaled = require_var (parent );
2250+ gen_name_to (scaled -> var_name );
2251+ var_t * size_const = require_var (parent );
2252+ size_const -> init_val = elem_size ;
2253+ gen_name_to (size_const -> var_name );
2254+ add_insn (parent , * bb , OP_load_constant , size_const ,
2255+ NULL , NULL , 0 , NULL );
2256+ add_insn (parent , * bb , OP_mul , scaled , rs2 ,
2257+ size_const , 0 , NULL );
2258+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 ,
2259+ NULL );
2260+ } else {
2261+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2262+ NULL );
2263+ }
2264+ /* Result is still a pointer */
2265+ vd -> is_ptr = rs1 -> is_ptr ;
2266+ vd -> type = rs1 -> type ;
2267+ } else if ((top_op == OP_add ) && !rs1 -> is_ptr &&
2268+ (rs2 -> is_ptr ||
2269+ (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2270+ /* Integer + pointer: scale the integer by element size
2271+ */
2272+ int elem_size = 4 ;
2273+ if (rs2 -> type ) {
2274+ /* For pointers, check what they point to */
2275+ if (rs2 -> is_ptr || rs2 -> type -> ptr_level > 0 ) {
2276+ switch (rs2 -> type -> base_type ) {
2277+ case TYPE_char :
2278+ elem_size = 1 ;
2279+ break ;
2280+ case TYPE_int :
2281+ elem_size = 4 ;
2282+ break ;
2283+ default :
2284+ elem_size = 4 ;
2285+ break ;
2286+ }
2287+ } else {
2288+ /* For non-pointers, use the type size */
2289+ if (rs2 -> type -> size > 0 ) {
2290+ elem_size = rs2 -> type -> size ;
2291+ } else {
2292+ elem_size = 4 ;
2293+ }
2294+ }
2295+ }
2296+
2297+ /* Scale the integer operand if needed */
2298+ if (elem_size > 1 ) {
2299+ var_t * scaled = require_var (parent );
2300+ gen_name_to (scaled -> var_name );
2301+ var_t * size_const = require_var (parent );
2302+ size_const -> init_val = elem_size ;
2303+ gen_name_to (size_const -> var_name );
2304+ add_insn (parent , * bb , OP_load_constant , size_const ,
2305+ NULL , NULL , 0 , NULL );
2306+ add_insn (parent , * bb , OP_mul , scaled , rs1 ,
2307+ size_const , 0 , NULL );
2308+ add_insn (parent , * bb , top_op , vd , scaled , rs2 , 0 ,
2309+ NULL );
2310+ } else {
2311+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2312+ NULL );
2313+ }
2314+ /* Result is a pointer */
2315+ vd -> is_ptr = rs2 -> is_ptr ;
2316+ vd -> type = rs2 -> type ;
2317+ } else {
2318+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2319+ }
21632320
21642321 oper_stack_idx -- ;
21652322 } else
@@ -2351,14 +2508,205 @@ void read_expr(block_t *parent, basic_block_t **bb)
23512508 vd = require_var (parent );
23522509 gen_name_to (vd -> var_name );
23532510 opstack_push (vd );
2354- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2511+
2512+ /* Handle pointer subtraction */
2513+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2514+ var_t * diff = require_var (parent );
2515+ gen_name_to (diff -> var_name );
2516+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2517+
2518+ int elem_size = 4 ;
2519+ if (rs1 -> type ) {
2520+ /* For pointers, check what they point to */
2521+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2522+ switch (rs1 -> type -> base_type ) {
2523+ case TYPE_char :
2524+ elem_size = 1 ;
2525+ break ;
2526+ case TYPE_int :
2527+ elem_size = 4 ;
2528+ break ;
2529+ default :
2530+ elem_size = 4 ;
2531+ break ;
2532+ }
2533+ } else {
2534+ /* For non-pointers, use the type size */
2535+ if (rs1 -> type -> size > 0 ) {
2536+ elem_size = rs1 -> type -> size ;
2537+ } else {
2538+ elem_size = 4 ;
2539+ }
2540+ }
2541+ }
2542+
2543+ if (elem_size > 1 ) {
2544+ var_t * size_const = require_var (parent );
2545+ size_const -> init_val = elem_size ;
2546+ gen_name_to (size_const -> var_name );
2547+ add_insn (parent , * bb , OP_load_constant , size_const ,
2548+ NULL , NULL , 0 , NULL );
2549+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2550+ NULL );
2551+ } else {
2552+ /* If element size is 1, no division needed - use
2553+ * assignment */
2554+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2555+ NULL );
2556+ }
2557+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2558+ (rs1 -> is_ptr ||
2559+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2560+ !rs2 -> is_ptr ) {
2561+ /* Pointer +/- integer: scale the integer by element size */
2562+ int elem_size = 4 ;
2563+ if (rs1 -> type ) {
2564+ /* For pointers, check what they point to */
2565+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2566+ switch (rs1 -> type -> base_type ) {
2567+ case TYPE_char :
2568+ elem_size = 1 ;
2569+ break ;
2570+ case TYPE_int :
2571+ elem_size = 4 ;
2572+ break ;
2573+ default :
2574+ elem_size = 4 ;
2575+ break ;
2576+ }
2577+ } else {
2578+ /* For non-pointers, use the type size */
2579+ if (rs1 -> type -> size > 0 ) {
2580+ elem_size = rs1 -> type -> size ;
2581+ } else {
2582+ elem_size = 4 ;
2583+ }
2584+ }
2585+ }
2586+
2587+ /* Scale the integer operand if needed */
2588+ if (elem_size > 1 ) {
2589+ var_t * scaled = require_var (parent );
2590+ gen_name_to (scaled -> var_name );
2591+ var_t * size_const = require_var (parent );
2592+ size_const -> init_val = elem_size ;
2593+ gen_name_to (size_const -> var_name );
2594+ add_insn (parent , * bb , OP_load_constant , size_const ,
2595+ NULL , NULL , 0 , NULL );
2596+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const ,
2597+ 0 , NULL );
2598+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2599+ } else {
2600+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2601+ }
2602+ /* Result is still a pointer */
2603+ vd -> is_ptr = rs1 -> is_ptr ;
2604+ vd -> type = rs1 -> type ;
2605+ } else {
2606+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2607+ }
23552608 }
23562609 } else {
23572610 /* Normal operation */
23582611 vd = require_var (parent );
23592612 gen_name_to (vd -> var_name );
23602613 opstack_push (vd );
2361- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2614+
2615+ /* Handle pointer subtraction */
2616+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2617+ var_t * diff = require_var (parent );
2618+ gen_name_to (diff -> var_name );
2619+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2620+
2621+ int elem_size = 4 ;
2622+ if (rs1 -> type ) {
2623+ /* For pointers, check what they point to */
2624+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2625+ switch (rs1 -> type -> base_type ) {
2626+ case TYPE_char :
2627+ elem_size = 1 ;
2628+ break ;
2629+ case TYPE_int :
2630+ elem_size = 4 ;
2631+ break ;
2632+ default :
2633+ elem_size = 4 ;
2634+ break ;
2635+ }
2636+ } else {
2637+ /* For non-pointers, use the type size */
2638+ if (rs1 -> type -> size > 0 ) {
2639+ elem_size = rs1 -> type -> size ;
2640+ } else {
2641+ elem_size = 4 ;
2642+ }
2643+ }
2644+ }
2645+
2646+ if (elem_size > 1 ) {
2647+ var_t * size_const = require_var (parent );
2648+ size_const -> init_val = elem_size ;
2649+ gen_name_to (size_const -> var_name );
2650+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2651+ NULL , 0 , NULL );
2652+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2653+ NULL );
2654+ } else {
2655+ /* If element size is 1, no division needed - use assignment
2656+ */
2657+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 , NULL );
2658+ }
2659+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2660+ (rs1 -> is_ptr ||
2661+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2662+ !rs2 -> is_ptr ) {
2663+ /* Pointer +/- integer: scale the integer by element size */
2664+ int elem_size = 4 ;
2665+ if (rs1 -> type ) {
2666+ /* For pointers, check what they point to */
2667+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2668+ switch (rs1 -> type -> base_type ) {
2669+ case TYPE_char :
2670+ elem_size = 1 ;
2671+ break ;
2672+ case TYPE_int :
2673+ elem_size = 4 ;
2674+ break ;
2675+ default :
2676+ elem_size = 4 ;
2677+ break ;
2678+ }
2679+ } else {
2680+ /* For non-pointers, use the type size */
2681+ if (rs1 -> type -> size > 0 ) {
2682+ elem_size = rs1 -> type -> size ;
2683+ } else {
2684+ elem_size = 4 ;
2685+ }
2686+ }
2687+ }
2688+
2689+ /* Scale the integer operand if needed */
2690+ if (elem_size > 1 ) {
2691+ var_t * scaled = require_var (parent );
2692+ gen_name_to (scaled -> var_name );
2693+ var_t * size_const = require_var (parent );
2694+ size_const -> init_val = elem_size ;
2695+ gen_name_to (size_const -> var_name );
2696+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2697+ NULL , 0 , NULL );
2698+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const , 0 ,
2699+ NULL );
2700+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2701+ } else {
2702+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2703+ }
2704+ /* Result is still a pointer */
2705+ vd -> is_ptr = rs1 -> is_ptr ;
2706+ vd -> type = rs1 -> type ;
2707+ } else {
2708+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2709+ }
23622710 }
23632711 }
23642712 while (has_prev_log_op ) {
0 commit comments