@@ -95,10 +95,10 @@ let create_context ?(global_variables = []) symbol_table = {
9595 variable_types = Hashtbl. create 32 ;
9696}
9797
98- (* * Register allocation *)
98+ (* * Allocate a new register for intermediate values *)
9999let allocate_register ctx =
100100 let reg = ctx.next_register in
101- ctx.next_register < - ctx.next_register + 1 ;
101+ ctx.next_register < - reg + 1 ;
102102 reg
103103
104104(* * Get or allocate register for variable *)
@@ -543,36 +543,7 @@ let rec lower_expression ctx (expr : Ast.expr) =
543543 (* Check if this is a variable holding a function pointer or a direct function call *)
544544 if name = " register" then
545545 (* Special handling for register() builtin function *)
546- if List. length arg_vals = 1 then
547- let struct_arg = List. hd args in
548- (* Handle impl block references specially *)
549- let struct_val = match struct_arg.expr_desc with
550- | Ast. Identifier impl_name ->
551- (* Check if this is an impl block name in the symbol table *)
552- (match Symbol_table. lookup_symbol ctx.symbol_table impl_name with
553- | Some symbol ->
554- (match symbol.kind with
555- | Symbol_table. TypeDef _ ->
556- (* This is an impl block - use the name directly *)
557- let ir_type = IRStruct (impl_name, [] , false ) in
558- make_ir_value (IRVariable impl_name) ir_type struct_arg.expr_pos
559- | _ ->
560- (* Regular variable - use normal processing *)
561- lower_expression ctx struct_arg)
562- | None ->
563- (* Not found in symbol table - use normal processing *)
564- lower_expression ctx struct_arg)
565- | _ ->
566- (* Not an identifier - use normal processing *)
567- lower_expression ctx struct_arg
568- in
569- let result_reg = allocate_register ctx in
570- let result_val = make_ir_value (IRRegister result_reg) IRU32 expr.expr_pos in
571- let instr = make_ir_instruction (IRStructOpsRegister (result_val, struct_val)) expr.expr_pos in
572- emit_instruction ctx instr;
573- result_val
574- else
575- failwith " register() takes exactly one argument"
546+ handle_register_builtin_call ctx args expr.expr_pos ()
576547 else if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
577548 (* This is a variable holding a function pointer - use FunctionPointerCall *)
578549 let callee_val = lower_expression ctx callee_expr in
@@ -977,6 +948,45 @@ let rec lower_expression ctx (expr : Ast.expr) =
977948 generate_match_conditions arms;
978949 result_val
979950
951+ (* * Helper function to handle register() builtin function calls *)
952+ and handle_register_builtin_call ctx args expr_pos ?target_register ?target_type () =
953+ if List. length args = 1 then
954+ let struct_arg = List. hd args in
955+ (* Handle impl block references specially *)
956+ let struct_val = match struct_arg.Ast. expr_desc with
957+ | Ast. Identifier impl_name ->
958+ (* Check if this is an impl block name in the symbol table *)
959+ (match Symbol_table. lookup_symbol ctx.symbol_table impl_name with
960+ | Some symbol ->
961+ (match symbol.kind with
962+ | Symbol_table. TypeDef _ ->
963+ (* This is an impl block - use the name directly *)
964+ let ir_type = IRStruct (impl_name, [] , false ) in
965+ make_ir_value (IRVariable impl_name) ir_type struct_arg.Ast. expr_pos
966+ | _ ->
967+ (* Regular variable - use normal processing *)
968+ lower_expression ctx struct_arg)
969+ | None ->
970+ (* Not found in symbol table - use normal processing *)
971+ lower_expression ctx struct_arg)
972+ | _ ->
973+ (* Not an identifier - use normal processing *)
974+ lower_expression ctx struct_arg
975+ in
976+ (* Create result value - use provided target or allocate new register *)
977+ let result_val = match target_register, target_type with
978+ | Some reg , Some typ -> make_ir_value (IRRegister reg) typ expr_pos
979+ | None , _ ->
980+ let result_reg = allocate_register ctx in
981+ make_ir_value (IRRegister result_reg) IRU32 expr_pos
982+ | Some reg , None -> make_ir_value (IRRegister reg) IRU32 expr_pos
983+ in
984+ let instr = make_ir_instruction (IRStructOpsRegister (result_val, struct_val)) expr_pos in
985+ emit_instruction ctx instr;
986+ result_val
987+ else
988+ failwith " register() takes exactly one argument"
989+
980990(* * Helper function to resolve type aliases and track them *)
981991and resolve_type_alias ctx reg ast_type =
982992 match ast_type with
@@ -1021,22 +1031,29 @@ and resolve_declaration_type_and_init ctx reg typ_opt expr_opt =
10211031 (match expr.Ast. expr_desc with
10221032 | Ast. Call (callee_expr , args ) ->
10231033 (* Handle function call that should return to the target register *)
1024- let arg_vals = List. map (lower_expression ctx) args in
1025- let result_val = make_ir_value (IRRegister reg) target_type expr.Ast. expr_pos in
1026- let call_target = match callee_expr.Ast. expr_desc with
1027- | Ast. Identifier name ->
1028- if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1029- let callee_val = lower_expression ctx callee_expr in
1030- FunctionPointerCall callee_val
1031- else
1032- DirectCall name
1033- | _ ->
1034- let callee_val = lower_expression ctx callee_expr in
1035- FunctionPointerCall callee_val
1036- in
1037- let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1038- emit_instruction ctx instr;
1039- (target_type, None )
1034+ (* Special handling for register() builtin function *)
1035+ (match callee_expr.Ast. expr_desc with
1036+ | Ast. Identifier "register" ->
1037+ let _ = handle_register_builtin_call ctx args expr.Ast. expr_pos ~target_register: reg ~target_type: target_type () in
1038+ (target_type, None )
1039+ | _ ->
1040+ (* Regular function call handling *)
1041+ let arg_vals = List. map (lower_expression ctx) args in
1042+ let result_val = make_ir_value (IRRegister reg) target_type expr.Ast. expr_pos in
1043+ let call_target = match callee_expr.Ast. expr_desc with
1044+ | Ast. Identifier name ->
1045+ if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1046+ let callee_val = lower_expression ctx callee_expr in
1047+ FunctionPointerCall callee_val
1048+ else
1049+ DirectCall name
1050+ | _ ->
1051+ let callee_val = lower_expression ctx callee_expr in
1052+ FunctionPointerCall callee_val
1053+ in
1054+ let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1055+ emit_instruction ctx instr;
1056+ (target_type, None ))
10401057 | _ ->
10411058 (* Non-function call - use normal processing *)
10421059 let value = lower_expression ctx expr in
@@ -1050,22 +1067,29 @@ and resolve_declaration_type_and_init ctx reg typ_opt expr_opt =
10501067 | Some ast_type -> ast_type_to_ir_type_with_context ctx.symbol_table ast_type
10511068 | None -> IRU32 (* Default fallback *)
10521069 in
1053- let arg_vals = List. map (lower_expression ctx) args in
1054- let result_val = make_ir_value (IRRegister reg) inferred_type expr.Ast. expr_pos in
1055- let call_target = match callee_expr.Ast. expr_desc with
1056- | Ast. Identifier name ->
1057- if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1058- let callee_val = lower_expression ctx callee_expr in
1059- FunctionPointerCall callee_val
1060- else
1061- DirectCall name
1062- | _ ->
1063- let callee_val = lower_expression ctx callee_expr in
1064- FunctionPointerCall callee_val
1065- in
1066- let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1067- emit_instruction ctx instr;
1068- (inferred_type, None )
1070+ (* Special handling for register() builtin function *)
1071+ (match callee_expr.Ast. expr_desc with
1072+ | Ast. Identifier "register" ->
1073+ let _ = handle_register_builtin_call ctx args expr.Ast. expr_pos ~target_register: reg ~target_type: inferred_type () in
1074+ (inferred_type, None )
1075+ | _ ->
1076+ (* Regular function call handling *)
1077+ let arg_vals = List. map (lower_expression ctx) args in
1078+ let result_val = make_ir_value (IRRegister reg) inferred_type expr.Ast. expr_pos in
1079+ let call_target = match callee_expr.Ast. expr_desc with
1080+ | Ast. Identifier name ->
1081+ if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1082+ let callee_val = lower_expression ctx callee_expr in
1083+ FunctionPointerCall callee_val
1084+ else
1085+ DirectCall name
1086+ | _ ->
1087+ let callee_val = lower_expression ctx callee_expr in
1088+ FunctionPointerCall callee_val
1089+ in
1090+ let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1091+ emit_instruction ctx instr;
1092+ (inferred_type, None ))
10691093 | _ ->
10701094 (* Non-function call - use normal processing *)
10711095 let value = lower_expression ctx expr in
@@ -1310,7 +1334,7 @@ and lower_statement ctx stmt =
13101334
13111335 (* Handle function call declarations elegantly by proper instruction ordering *)
13121336 (match expr_opt with
1313- | Some expr when (match expr.Ast. expr_desc with Ast. Call _ -> true | _ -> false ) ->
1337+ | Some expr when (match expr.expr_desc with Ast. Call _ -> true | _ -> false ) ->
13141338 (* For function calls: emit declaration first, then call with assignment *)
13151339 let target_type = match typ_opt with
13161340 | Some ast_type -> resolve_type_alias ctx reg ast_type
@@ -1327,21 +1351,28 @@ and lower_statement ctx stmt =
13271351 (* Then emit function call as assignment *)
13281352 (match expr.Ast. expr_desc with
13291353 | Ast. Call (callee_expr , args ) ->
1330- let arg_vals = List. map (lower_expression ctx) args in
1331- let result_val = make_ir_value (IRRegister reg) target_type expr.Ast. expr_pos in
1332- let call_target = match callee_expr.Ast. expr_desc with
1333- | Ast. Identifier name ->
1334- if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1335- let callee_val = lower_expression ctx callee_expr in
1336- FunctionPointerCall callee_val
1337- else
1338- DirectCall name
1339- | _ ->
1340- let callee_val = lower_expression ctx callee_expr in
1341- FunctionPointerCall callee_val
1342- in
1343- let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1344- emit_instruction ctx instr
1354+ (* Special handling for register() builtin function *)
1355+ (match callee_expr.Ast. expr_desc with
1356+ | Ast. Identifier "register" ->
1357+ let _ = handle_register_builtin_call ctx args expr.Ast. expr_pos ~target_register: reg ~target_type: target_type () in
1358+ ()
1359+ | _ ->
1360+ (* Regular function call handling *)
1361+ let arg_vals = List. map (lower_expression ctx) args in
1362+ let result_val = make_ir_value (IRRegister reg) target_type expr.Ast. expr_pos in
1363+ let call_target = match callee_expr.Ast. expr_desc with
1364+ | Ast. Identifier name ->
1365+ if Hashtbl. mem ctx.variables name || Hashtbl. mem ctx.function_parameters name then
1366+ let callee_val = lower_expression ctx callee_expr in
1367+ FunctionPointerCall callee_val
1368+ else
1369+ DirectCall name
1370+ | _ ->
1371+ let callee_val = lower_expression ctx callee_expr in
1372+ FunctionPointerCall callee_val
1373+ in
1374+ let instr = make_ir_instruction (IRCall (call_target, arg_vals, Some result_val)) expr.Ast. expr_pos in
1375+ emit_instruction ctx instr)
13451376 | _ -> () ) (* Shouldn't happen due to our guard *)
13461377 | _ ->
13471378 (* Non-function call declarations: use existing logic *)
0 commit comments