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