@@ -2331,7 +2331,168 @@ void read_expr(block_t *parent, basic_block_t **bb)
23312331 vd = require_var (parent );
23322332 gen_name_to (vd -> var_name );
23332333 opstack_push (vd );
2334- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2334+
2335+ /* Handle pointer arithmetic:
2336+ * - If both operands are pointers (subtraction), divide by
2337+ * element size
2338+ * - If one operand is a pointer, handle scaling
2339+ * appropriately
2340+ */
2341+ if (top_op == OP_sub && rs1 -> ptr_level > 0 &&
2342+ rs2 -> ptr_level > 0 ) {
2343+ /* Subtracting two pointers - divide by element size */
2344+ var_t * diff = require_var (parent );
2345+ gen_name_to (diff -> var_name );
2346+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2347+
2348+ /* Get the element size */
2349+ int elem_size = 4 ; /* Default to int size */
2350+ if (rs1 -> type ) {
2351+ /* For pointers, check what they point to */
2352+ if (rs1 -> ptr_level > 0 ||
2353+ rs1 -> type -> ptr_level > 0 ) {
2354+ switch (rs1 -> type -> base_type ) {
2355+ case TYPE_char :
2356+ elem_size = 1 ;
2357+ break ;
2358+ case TYPE_int :
2359+ elem_size = 4 ;
2360+ break ;
2361+ default :
2362+ elem_size = 4 ;
2363+ break ;
2364+ }
2365+ } else {
2366+ /* For non-pointers, use the type size */
2367+ if (rs1 -> type -> size > 0 ) {
2368+ elem_size = rs1 -> type -> size ;
2369+ } else {
2370+ elem_size = 4 ;
2371+ }
2372+ }
2373+ }
2374+
2375+ /* Divide by element size */
2376+ if (elem_size > 1 ) {
2377+ var_t * size_const = require_var (parent );
2378+ size_const -> init_val = elem_size ;
2379+ gen_name_to (size_const -> var_name );
2380+ add_insn (parent , * bb , OP_load_constant , size_const ,
2381+ NULL , NULL , 0 , NULL );
2382+ add_insn (parent , * bb , OP_div , vd , diff , size_const ,
2383+ 0 , NULL );
2384+ } else {
2385+ /* If element size is 1, no division needed - use
2386+ * assignment */
2387+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2388+ NULL );
2389+ }
2390+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2391+ (rs1 -> ptr_level > 0 ||
2392+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2393+ rs2 -> ptr_level == 0 ) {
2394+ /* Pointer +/- integer: scale the integer by element
2395+ * size */
2396+ int elem_size = 4 ;
2397+ if (rs1 -> type ) {
2398+ /* For pointers, check what they point to */
2399+ if (rs1 -> ptr_level > 0 ||
2400+ rs1 -> type -> ptr_level > 0 ) {
2401+ switch (rs1 -> type -> base_type ) {
2402+ case TYPE_char :
2403+ elem_size = 1 ;
2404+ break ;
2405+ case TYPE_int :
2406+ elem_size = 4 ;
2407+ break ;
2408+ default :
2409+ elem_size = 4 ;
2410+ break ;
2411+ }
2412+ } else {
2413+ /* For non-pointers, use the type size */
2414+ if (rs1 -> type -> size > 0 ) {
2415+ elem_size = rs1 -> type -> size ;
2416+ } else {
2417+ elem_size = 4 ;
2418+ }
2419+ }
2420+ }
2421+
2422+ /* Scale the integer operand if needed */
2423+ if (elem_size > 1 ) {
2424+ var_t * scaled = require_var (parent );
2425+ gen_name_to (scaled -> var_name );
2426+ var_t * size_const = require_var (parent );
2427+ size_const -> init_val = elem_size ;
2428+ gen_name_to (size_const -> var_name );
2429+ add_insn (parent , * bb , OP_load_constant , size_const ,
2430+ NULL , NULL , 0 , NULL );
2431+ add_insn (parent , * bb , OP_mul , scaled , rs2 ,
2432+ size_const , 0 , NULL );
2433+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 ,
2434+ NULL );
2435+ } else {
2436+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2437+ NULL );
2438+ }
2439+ /* Result is still a pointer */
2440+ vd -> ptr_level = rs1 -> ptr_level ;
2441+ vd -> type = rs1 -> type ;
2442+ } else if ((top_op == OP_add ) && rs1 -> ptr_level == 0 &&
2443+ (rs2 -> ptr_level > 0 ||
2444+ (rs2 -> type && rs2 -> type -> ptr_level > 0 ))) {
2445+ /* Integer + pointer: scale the integer by element size
2446+ */
2447+ int elem_size = 4 ;
2448+ if (rs2 -> type ) {
2449+ /* For pointers, check what they point to */
2450+ if (rs2 -> ptr_level > 0 ||
2451+ rs2 -> type -> ptr_level > 0 ) {
2452+ switch (rs2 -> type -> base_type ) {
2453+ case TYPE_char :
2454+ elem_size = 1 ;
2455+ break ;
2456+ case TYPE_int :
2457+ elem_size = 4 ;
2458+ break ;
2459+ default :
2460+ elem_size = 4 ;
2461+ break ;
2462+ }
2463+ } else {
2464+ /* For non-pointers, use the type size */
2465+ if (rs2 -> type -> size > 0 ) {
2466+ elem_size = rs2 -> type -> size ;
2467+ } else {
2468+ elem_size = 4 ;
2469+ }
2470+ }
2471+ }
2472+
2473+ /* Scale the integer operand if needed */
2474+ if (elem_size > 1 ) {
2475+ var_t * scaled = require_var (parent );
2476+ gen_name_to (scaled -> var_name );
2477+ var_t * size_const = require_var (parent );
2478+ size_const -> init_val = elem_size ;
2479+ gen_name_to (size_const -> var_name );
2480+ add_insn (parent , * bb , OP_load_constant , size_const ,
2481+ NULL , NULL , 0 , NULL );
2482+ add_insn (parent , * bb , OP_mul , scaled , rs1 ,
2483+ size_const , 0 , NULL );
2484+ add_insn (parent , * bb , top_op , vd , scaled , rs2 , 0 ,
2485+ NULL );
2486+ } else {
2487+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 ,
2488+ NULL );
2489+ }
2490+ /* Result is a pointer */
2491+ vd -> ptr_level = rs2 -> ptr_level ;
2492+ vd -> type = rs2 -> type ;
2493+ } else {
2494+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2495+ }
23352496
23362497 oper_stack_idx -- ;
23372498 } else
@@ -2609,14 +2770,206 @@ void read_expr(block_t *parent, basic_block_t **bb)
26092770 vd = require_var (parent );
26102771 gen_name_to (vd -> var_name );
26112772 opstack_push (vd );
2612- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2773+
2774+ /* Handle pointer subtraction */
2775+ if (top_op == OP_sub && rs1 -> ptr_level > 0 &&
2776+ rs2 -> ptr_level > 0 ) {
2777+ var_t * diff = require_var (parent );
2778+ gen_name_to (diff -> var_name );
2779+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2780+
2781+ int elem_size = 4 ;
2782+ if (rs1 -> type ) {
2783+ /* For pointers, check what they point to */
2784+ if (rs1 -> ptr_level > 0 || rs1 -> type -> ptr_level > 0 ) {
2785+ switch (rs1 -> type -> base_type ) {
2786+ case TYPE_char :
2787+ elem_size = 1 ;
2788+ break ;
2789+ case TYPE_int :
2790+ elem_size = 4 ;
2791+ break ;
2792+ default :
2793+ elem_size = 4 ;
2794+ break ;
2795+ }
2796+ } else {
2797+ /* For non-pointers, use the type size */
2798+ if (rs1 -> type -> size > 0 ) {
2799+ elem_size = rs1 -> type -> size ;
2800+ } else {
2801+ elem_size = 4 ;
2802+ }
2803+ }
2804+ }
2805+
2806+ if (elem_size > 1 ) {
2807+ var_t * size_const = require_var (parent );
2808+ size_const -> init_val = elem_size ;
2809+ gen_name_to (size_const -> var_name );
2810+ add_insn (parent , * bb , OP_load_constant , size_const ,
2811+ NULL , NULL , 0 , NULL );
2812+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2813+ NULL );
2814+ } else {
2815+ /* If element size is 1, no division needed - use
2816+ * assignment */
2817+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 ,
2818+ NULL );
2819+ }
2820+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2821+ (rs1 -> ptr_level > 0 ||
2822+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2823+ rs2 -> ptr_level == 0 ) {
2824+ /* Pointer +/- integer: scale the integer by element size */
2825+ int elem_size = 4 ;
2826+ if (rs1 -> type ) {
2827+ /* For pointers, check what they point to */
2828+ if (rs1 -> ptr_level > 0 || rs1 -> type -> ptr_level > 0 ) {
2829+ switch (rs1 -> type -> base_type ) {
2830+ case TYPE_char :
2831+ elem_size = 1 ;
2832+ break ;
2833+ case TYPE_int :
2834+ elem_size = 4 ;
2835+ break ;
2836+ default :
2837+ elem_size = 4 ;
2838+ break ;
2839+ }
2840+ } else {
2841+ /* For non-pointers, use the type size */
2842+ if (rs1 -> type -> size > 0 ) {
2843+ elem_size = rs1 -> type -> size ;
2844+ } else {
2845+ elem_size = 4 ;
2846+ }
2847+ }
2848+ }
2849+
2850+ /* Scale the integer operand if needed */
2851+ if (elem_size > 1 ) {
2852+ var_t * scaled = require_var (parent );
2853+ gen_name_to (scaled -> var_name );
2854+ var_t * size_const = require_var (parent );
2855+ size_const -> init_val = elem_size ;
2856+ gen_name_to (size_const -> var_name );
2857+ add_insn (parent , * bb , OP_load_constant , size_const ,
2858+ NULL , NULL , 0 , NULL );
2859+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const ,
2860+ 0 , NULL );
2861+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2862+ } else {
2863+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2864+ }
2865+ /* Result is still a pointer */
2866+ vd -> ptr_level = rs1 -> ptr_level ;
2867+ vd -> type = rs1 -> type ;
2868+ } else {
2869+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2870+ }
26132871 }
26142872 } else {
26152873 /* Normal operation */
26162874 vd = require_var (parent );
26172875 gen_name_to (vd -> var_name );
26182876 opstack_push (vd );
2619- add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2877+
2878+ /* Handle pointer subtraction */
2879+ if (top_op == OP_sub && rs1 -> ptr_level > 0 && rs2 -> ptr_level > 0 ) {
2880+ var_t * diff = require_var (parent );
2881+ gen_name_to (diff -> var_name );
2882+ add_insn (parent , * bb , OP_sub , diff , rs1 , rs2 , 0 , NULL );
2883+
2884+ int elem_size = 4 ;
2885+ if (rs1 -> type ) {
2886+ /* For pointers, check what they point to */
2887+ if (rs1 -> ptr_level > 0 || rs1 -> type -> ptr_level > 0 ) {
2888+ switch (rs1 -> type -> base_type ) {
2889+ case TYPE_char :
2890+ elem_size = 1 ;
2891+ break ;
2892+ case TYPE_int :
2893+ elem_size = 4 ;
2894+ break ;
2895+ default :
2896+ elem_size = 4 ;
2897+ break ;
2898+ }
2899+ } else {
2900+ /* For non-pointers, use the type size */
2901+ if (rs1 -> type -> size > 0 ) {
2902+ elem_size = rs1 -> type -> size ;
2903+ } else {
2904+ elem_size = 4 ;
2905+ }
2906+ }
2907+ }
2908+
2909+ if (elem_size > 1 ) {
2910+ var_t * size_const = require_var (parent );
2911+ size_const -> init_val = elem_size ;
2912+ gen_name_to (size_const -> var_name );
2913+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2914+ NULL , 0 , NULL );
2915+ add_insn (parent , * bb , OP_div , vd , diff , size_const , 0 ,
2916+ NULL );
2917+ } else {
2918+ /* If element size is 1, no division needed - use assignment
2919+ */
2920+ add_insn (parent , * bb , OP_assign , vd , diff , NULL , 0 , NULL );
2921+ }
2922+ } else if ((top_op == OP_add || top_op == OP_sub ) &&
2923+ (rs1 -> ptr_level > 0 ||
2924+ (rs1 -> type && rs1 -> type -> ptr_level > 0 )) &&
2925+ rs2 -> ptr_level == 0 ) {
2926+ /* Pointer +/- integer: scale the integer by element size */
2927+ int elem_size = 4 ;
2928+ if (rs1 -> type ) {
2929+ /* For pointers, check what they point to */
2930+ if (rs1 -> ptr_level > 0 || rs1 -> type -> ptr_level > 0 ) {
2931+ switch (rs1 -> type -> base_type ) {
2932+ case TYPE_char :
2933+ elem_size = 1 ;
2934+ break ;
2935+ case TYPE_int :
2936+ elem_size = 4 ;
2937+ break ;
2938+ default :
2939+ elem_size = 4 ;
2940+ break ;
2941+ }
2942+ } else {
2943+ /* For non-pointers, use the type size */
2944+ if (rs1 -> type -> size > 0 ) {
2945+ elem_size = rs1 -> type -> size ;
2946+ } else {
2947+ elem_size = 4 ;
2948+ }
2949+ }
2950+ }
2951+
2952+ /* Scale the integer operand if needed */
2953+ if (elem_size > 1 ) {
2954+ var_t * scaled = require_var (parent );
2955+ gen_name_to (scaled -> var_name );
2956+ var_t * size_const = require_var (parent );
2957+ size_const -> init_val = elem_size ;
2958+ gen_name_to (size_const -> var_name );
2959+ add_insn (parent , * bb , OP_load_constant , size_const , NULL ,
2960+ NULL , 0 , NULL );
2961+ add_insn (parent , * bb , OP_mul , scaled , rs2 , size_const , 0 ,
2962+ NULL );
2963+ add_insn (parent , * bb , top_op , vd , rs1 , scaled , 0 , NULL );
2964+ } else {
2965+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2966+ }
2967+ /* Result is still a pointer */
2968+ vd -> ptr_level = rs1 -> ptr_level ;
2969+ vd -> type = rs1 -> type ;
2970+ } else {
2971+ add_insn (parent , * bb , top_op , vd , rs1 , rs2 , 0 , NULL );
2972+ }
26202973 }
26212974 }
26222975 while (has_prev_log_op ) {
0 commit comments