@@ -2198,7 +2198,164 @@ void read_expr(block_t *parent, basic_block_t **bb)
21982198 vd = require_var (parent );
21992199 gen_name_to (vd -> var_name );
22002200 opstack_push (vd );
2201- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2201+
2202+ /* Handle pointer arithmetic:
2203+ * - If both operands are pointers (subtraction), divide by
2204+ * element size
2205+ * - If one operand is a pointer, handle scaling
2206+ * appropriately
2207+ */
2208+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2209+ /* Subtracting two pointers - divide by element size */
2210+ var_t * diff = require_var (parent );
2211+ gen_name_to (diff -> var_name );
2212+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2213+
2214+ /* Get the element size */
2215+ int elem_size = 4 ; /* Default to int size */
2216+ if (rs1 -> type ) {
2217+ /* For pointers, check what they point to */
2218+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2219+ switch (rs1 -> type -> base_type ) {
2220+ case TYPE_char :
2221+ elem_size = 1 ;
2222+ break ;
2223+ case TYPE_int :
2224+ elem_size = 4 ;
2225+ break ;
2226+ default :
2227+ elem_size = 4 ;
2228+ break ;
2229+ }
2230+ } else {
2231+ /* For non-pointers, use the type size */
2232+ if (rs1 -> type -> size > 0 ) {
2233+ elem_size = rs1 -> type -> size ;
2234+ } else {
2235+ elem_size = 4 ;
2236+ }
2237+ }
2238+ }
2239+
2240+ /* Divide by element size */
2241+ if (elem_size > 1 ) {
2242+ var_t * size_const = require_var (parent );
2243+ size_const -> init_val = elem_size ;
2244+ gen_name_to (size_const -> var_name );
2245+ add_insn (parent , * bb , OP_load_constant , size_const ,
2246+ NULL , NULL , 0 , NULL );
2247+ add_insn (parent , * bb , OP_div , vd , diff , size_const ,
2248+ 0 , NULL );
2249+ } else {
2250+ /* If element size is 1, no division needed - use
2251+ * assignment */
2252+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2253+ NULL );
2254+ }
2255+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2256+ (rs1 -> is_ptr ||
2257+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2258+ !rs2 -> is_ptr ) {
2259+ /* Pointer +/- integer: scale the integer by element
2260+ * size */
2261+ int elem_size = 4 ;
2262+ if (rs1 -> type ) {
2263+ /* For pointers, check what they point to */
2264+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2265+ switch (rs1 -> type -> base_type ) {
2266+ case TYPE_char :
2267+ elem_size = 1 ;
2268+ break ;
2269+ case TYPE_int :
2270+ elem_size = 4 ;
2271+ break ;
2272+ default :
2273+ elem_size = 4 ;
2274+ break ;
2275+ }
2276+ } else {
2277+ /* For non-pointers, use the type size */
2278+ if (rs1 -> type -> size > 0 ) {
2279+ elem_size = rs1 -> type -> size ;
2280+ } else {
2281+ elem_size = 4 ;
2282+ }
2283+ }
2284+ }
2285+
2286+ /* Scale the integer operand if needed */
2287+ if (elem_size > 1 ) {
2288+ var_t * scaled = require_var (parent );
2289+ gen_name_to (scaled -> var_name );
2290+ var_t * size_const = require_var (parent );
2291+ size_const -> init_val = elem_size ;
2292+ gen_name_to (size_const -> var_name );
2293+ add_insn (parent , * bb , OP_load_constant , size_const ,
2294+ NULL , NULL , 0 , NULL );
2295+ add_insn (parent , * bb , OP_mul , scaled , rs2 ,
2296+ size_const , 0 , NULL );
2297+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 ,
2298+ NULL );
2299+ } else {
2300+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2301+ NULL );
2302+ }
2303+ /* Result is still a pointer */
2304+ vd -> is_ptr = rs1 -> is_ptr ;
2305+ vd -> type = rs1 -> type ;
2306+ } else if ((top_op == OP_add ) && !rs1 -> is_ptr &&
2307+ (rs2 -> is_ptr ||
2308+ (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2309+ /* Integer + pointer: scale the integer by element size
2310+ */
2311+ int elem_size = 4 ;
2312+ if (rs2 -> type ) {
2313+ /* For pointers, check what they point to */
2314+ if (rs2 -> is_ptr || rs2 -> type -> ptr_level > 0 ) {
2315+ switch (rs2 -> type -> base_type ) {
2316+ case TYPE_char :
2317+ elem_size = 1 ;
2318+ break ;
2319+ case TYPE_int :
2320+ elem_size = 4 ;
2321+ break ;
2322+ default :
2323+ elem_size = 4 ;
2324+ break ;
2325+ }
2326+ } else {
2327+ /* For non-pointers, use the type size */
2328+ if (rs2 -> type -> size > 0 ) {
2329+ elem_size = rs2 -> type -> size ;
2330+ } else {
2331+ elem_size = 4 ;
2332+ }
2333+ }
2334+ }
2335+
2336+ /* Scale the integer operand if needed */
2337+ if (elem_size > 1 ) {
2338+ var_t * scaled = require_var (parent );
2339+ gen_name_to (scaled -> var_name );
2340+ var_t * size_const = require_var (parent );
2341+ size_const -> init_val = elem_size ;
2342+ gen_name_to (size_const -> var_name );
2343+ add_insn (parent , * bb , OP_load_constant , size_const ,
2344+ NULL , NULL , 0 , NULL );
2345+ add_insn (parent , * bb , OP_mul , scaled , rs1 ,
2346+ size_const , 0 , NULL );
2347+ add_insn (parent , * bb , top_op , vd , scaled , rs2 , 0 ,
2348+ NULL );
2349+ } else {
2350+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2351+ NULL );
2352+ }
2353+ /* Result is a pointer */
2354+ vd -> is_ptr = rs2 -> is_ptr ;
2355+ vd -> type = rs2 -> type ;
2356+ } else {
2357+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2358+ }
22022359
22032360 oper_stack_idx -- ;
22042361 } else
@@ -2390,14 +2547,205 @@ void read_expr(block_t *parent, basic_block_t **bb)
23902547 vd = require_var (parent );
23912548 gen_name_to (vd -> var_name );
23922549 opstack_push (vd );
2393- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2550+
2551+ /* Handle pointer subtraction */
2552+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2553+ var_t * diff = require_var (parent );
2554+ gen_name_to (diff -> var_name );
2555+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2556+
2557+ int elem_size = 4 ;
2558+ if (rs1 -> type ) {
2559+ /* For pointers, check what they point to */
2560+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2561+ switch (rs1 -> type -> base_type ) {
2562+ case TYPE_char :
2563+ elem_size = 1 ;
2564+ break ;
2565+ case TYPE_int :
2566+ elem_size = 4 ;
2567+ break ;
2568+ default :
2569+ elem_size = 4 ;
2570+ break ;
2571+ }
2572+ } else {
2573+ /* For non-pointers, use the type size */
2574+ if (rs1 -> type -> size > 0 ) {
2575+ elem_size = rs1 -> type -> size ;
2576+ } else {
2577+ elem_size = 4 ;
2578+ }
2579+ }
2580+ }
2581+
2582+ if (elem_size > 1 ) {
2583+ var_t * size_const = require_var (parent );
2584+ size_const -> init_val = elem_size ;
2585+ gen_name_to (size_const -> var_name );
2586+ add_insn (parent , * bb , OP_load_constant , size_const ,
2587+ NULL , NULL , 0 , NULL );
2588+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2589+ NULL );
2590+ } else {
2591+ /* If element size is 1, no division needed - use
2592+ * assignment */
2593+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2594+ NULL );
2595+ }
2596+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2597+ (rs1 -> is_ptr ||
2598+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2599+ !rs2 -> is_ptr ) {
2600+ /* Pointer +/- integer: scale the integer by element size */
2601+ int elem_size = 4 ;
2602+ if (rs1 -> type ) {
2603+ /* For pointers, check what they point to */
2604+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2605+ switch (rs1 -> type -> base_type ) {
2606+ case TYPE_char :
2607+ elem_size = 1 ;
2608+ break ;
2609+ case TYPE_int :
2610+ elem_size = 4 ;
2611+ break ;
2612+ default :
2613+ elem_size = 4 ;
2614+ break ;
2615+ }
2616+ } else {
2617+ /* For non-pointers, use the type size */
2618+ if (rs1 -> type -> size > 0 ) {
2619+ elem_size = rs1 -> type -> size ;
2620+ } else {
2621+ elem_size = 4 ;
2622+ }
2623+ }
2624+ }
2625+
2626+ /* Scale the integer operand if needed */
2627+ if (elem_size > 1 ) {
2628+ var_t * scaled = require_var (parent );
2629+ gen_name_to (scaled -> var_name );
2630+ var_t * size_const = require_var (parent );
2631+ size_const -> init_val = elem_size ;
2632+ gen_name_to (size_const -> var_name );
2633+ add_insn (parent , * bb , OP_load_constant , size_const ,
2634+ NULL , NULL , 0 , NULL );
2635+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const ,
2636+ 0 , NULL );
2637+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2638+ } else {
2639+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2640+ }
2641+ /* Result is still a pointer */
2642+ vd -> is_ptr = rs1 -> is_ptr ;
2643+ vd -> type = rs1 -> type ;
2644+ } else {
2645+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2646+ }
23942647 }
23952648 } else {
23962649 /* Normal operation */
23972650 vd = require_var (parent );
23982651 gen_name_to (vd -> var_name );
23992652 opstack_push (vd );
2400- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2653+
2654+ /* Handle pointer subtraction */
2655+ if (top_op == OP_sub && rs1 -> is_ptr && rs2 -> is_ptr ) {
2656+ var_t * diff = require_var (parent );
2657+ gen_name_to (diff -> var_name );
2658+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2659+
2660+ int elem_size = 4 ;
2661+ if (rs1 -> type ) {
2662+ /* For pointers, check what they point to */
2663+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2664+ switch (rs1 -> type -> base_type ) {
2665+ case TYPE_char :
2666+ elem_size = 1 ;
2667+ break ;
2668+ case TYPE_int :
2669+ elem_size = 4 ;
2670+ break ;
2671+ default :
2672+ elem_size = 4 ;
2673+ break ;
2674+ }
2675+ } else {
2676+ /* For non-pointers, use the type size */
2677+ if (rs1 -> type -> size > 0 ) {
2678+ elem_size = rs1 -> type -> size ;
2679+ } else {
2680+ elem_size = 4 ;
2681+ }
2682+ }
2683+ }
2684+
2685+ if (elem_size > 1 ) {
2686+ var_t * size_const = require_var (parent );
2687+ size_const -> init_val = elem_size ;
2688+ gen_name_to (size_const -> var_name );
2689+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2690+ NULL , 0 , NULL );
2691+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2692+ NULL );
2693+ } else {
2694+ /* If element size is 1, no division needed - use assignment
2695+ */
2696+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 , NULL );
2697+ }
2698+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2699+ (rs1 -> is_ptr ||
2700+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2701+ !rs2 -> is_ptr ) {
2702+ /* Pointer +/- integer: scale the integer by element size */
2703+ int elem_size = 4 ;
2704+ if (rs1 -> type ) {
2705+ /* For pointers, check what they point to */
2706+ if (rs1 -> is_ptr || rs1 -> type -> ptr_level > 0 ) {
2707+ switch (rs1 -> type -> base_type ) {
2708+ case TYPE_char :
2709+ elem_size = 1 ;
2710+ break ;
2711+ case TYPE_int :
2712+ elem_size = 4 ;
2713+ break ;
2714+ default :
2715+ elem_size = 4 ;
2716+ break ;
2717+ }
2718+ } else {
2719+ /* For non-pointers, use the type size */
2720+ if (rs1 -> type -> size > 0 ) {
2721+ elem_size = rs1 -> type -> size ;
2722+ } else {
2723+ elem_size = 4 ;
2724+ }
2725+ }
2726+ }
2727+
2728+ /* Scale the integer operand if needed */
2729+ if (elem_size > 1 ) {
2730+ var_t * scaled = require_var (parent );
2731+ gen_name_to (scaled -> var_name );
2732+ var_t * size_const = require_var (parent );
2733+ size_const -> init_val = elem_size ;
2734+ gen_name_to (size_const -> var_name );
2735+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2736+ NULL , 0 , NULL );
2737+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const , 0 ,
2738+ NULL );
2739+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2740+ } else {
2741+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2742+ }
2743+ /* Result is still a pointer */
2744+ vd -> is_ptr = rs1 -> is_ptr ;
2745+ vd -> type = rs1 -> type ;
2746+ } else {
2747+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2748+ }
24012749 }
24022750 }
24032751 while (has_prev_log_op ) {
0 commit comments