Move procedure call register allocation to RTL

This commit is contained in:
2025-12-12 18:32:01 +01:00
parent 305032b534
commit 1cf71f1a5f

View File

@@ -467,7 +467,7 @@ type
allocate_stack,
ret
);
ElnaTacOperand = (temporary, immediate, symbol, stack, pseudo);
ElnaTacOperand = (temporary, immediate, symbol, stack, pseudo, list);
ElnaRtlOperand = (register, immediate, symbol, offset, pseudo);
ElnaRtlRegister = (
zero,
@@ -819,45 +819,45 @@ end;
proc elna_rtl_load_operand_value(tac_instruction: Word, operand_number: Word, into: Word);
var
result1: ^ElnaInstructionList;
operand_value1: Word;
operand_length1: Word;
operand_type1: Word;
result: ^ElnaInstructionList;
operand_value: Word;
operand_length: Word;
operand_type: Word;
next_instruction: Word;
begin
operand_value1 := _elna_tac_instruction_get_operand_value(tac_instruction, operand_number);
operand_length1 := _elna_tac_instruction_get_operand_length(tac_instruction, operand_number);
operand_type1 := _elna_tac_instruction_get_operand_type(tac_instruction, operand_number);
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, operand_number);
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, operand_number);
operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, operand_number);
if operand_type1 = ElnaTacOperand.immediate then
result1 := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.immediate, operand_value1, operand_length1)
elsif operand_type1 = ElnaTacOperand.stack then
result1 := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value1)
elsif operand_type1 = ElnaTacOperand.symbol then
result1 := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.symbol, operand_value1, operand_length1);
if operand_type = ElnaTacOperand.immediate then
result := elna_rtl_instruction_create(ElnaRtlOperator.li);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.immediate, operand_value, operand_length)
elsif operand_type = ElnaTacOperand.stack then
result := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value)
elsif operand_type = ElnaTacOperand.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.symbol, operand_value, operand_length);
next_instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(next_instruction, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(next_instruction, 2, ElnaRtlOperand.offset, into, 0);
result1^.next := next_instruction
elsif operand_type1 = ElnaTacOperand.temporary then
result1 := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.register, operand_value1, 0)
elsif operand_type1 = ElnaTacOperand.pseudo then
result1 := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.pseudo, operand_value1, operand_length1)
result^.next := next_instruction
elsif operand_type = ElnaTacOperand.temporary then
result := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.register, operand_value, 0)
elsif operand_type = ElnaTacOperand.pseudo then
result := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.pseudo, operand_value, operand_length)
end;
return result1
return result
end;
proc elna_rtl_load_operand_address(tac_instruction: Word, operand_number: Word, into: Word);
@@ -871,11 +871,7 @@ begin
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, operand_number);
operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, operand_number);
if operand_type = ElnaTacOperand.stack then
result := elna_rtl_instruction_create(ElnaRtlOperator.addi);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value)
elsif operand_type = ElnaTacOperand.symbol then
if operand_type = ElnaTacOperand.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.symbol, operand_value, operand_length)
@@ -996,6 +992,69 @@ begin
return result
end;
proc elna_rtl_call(tac_instruction: Word, next_instruction: ^^ElnaInstructionList);
var
argument_count: Word;
current_argument: Word;
argument_type: Word;
argument_value: Word;
argument_length: Word;
argument_move: Word;
current_register: Word;
first_instruction: Word;
current_instruction: Word;
name: Word;
name_length: Word;
begin
current_register := 0;
first_instruction := nil;
current_argument := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
argument_count := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
name := _elna_tac_instruction_get_operand_value(tac_instruction, 1);
name_length := _elna_tac_instruction_get_operand_length(tac_instruction, 1);
.elna_rtl_call_loop;
if argument_count > 0 then
argument_count := argument_count - 1;
argument_type := current_argument^;
current_argument := current_argument + 4;
argument_value := current_argument^;
current_argument := current_argument + 4;
argument_length := current_argument^;
current_argument := current_argument + 4;
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(argument_move, 1, ElnaRtlOperand.register, ElnaRtlRegister.a0 + current_register, 0);
elna_rtl_instruction_set_operand(argument_move, 2, argument_type, argument_value, argument_length);
if first_instruction = nil then
first_instruction := argument_move
else
elna_instruction_list_concatenate(current_instruction, argument_move)
end;
current_instruction := argument_move;
current_register := current_register + 1;
goto elna_rtl_call_loop
end;
argument_move := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, argument_move);
if first_instruction = nil then
first_instruction := argument_move
else
elna_instruction_list_concatenate(current_instruction, argument_move)
end;
next_instruction^ := argument_move;
return first_instruction
end;
proc elna_rtl_instruction(tac_instruction: Word, next_instruction: ^^ElnaInstructionList);
var
result: ^ElnaInstructionList;
@@ -1042,18 +1101,7 @@ begin
elsif instruction_kind = ElnaTacOperator.load then
operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2);
if operand_type = ElnaTacOperand.stack then
result := elna_rtl_instruction_create(ElnaRtlOperator.lw);
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 1);
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(next_instruction^, 1, ElnaRtlOperand.register, operand_value, 0);
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, operand_value, 0);
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value);
result^.next := next_instruction^
elsif operand_type = ElnaTacOperand.temporary then
if operand_type = ElnaTacOperand.temporary then
result := elna_rtl_instruction_create(ElnaRtlOperator.lw);
elna_rtl_copy_operand(tac_instruction, 1, result);
@@ -1080,8 +1128,6 @@ begin
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
if operand_type = ElnaTacOperand.stack then
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value)
elsif operand_type = ElnaTacOperand.temporary then
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, operand_value, 0)
elsif operand_type = ElnaTacOperand.pseudo then
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.pseudo, operand_value, operand_length)
end;
@@ -1091,8 +1137,7 @@ begin
operands^.next := next_instruction^
end
elsif instruction_kind = ElnaTacOperator.proc_call then
result := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_copy_operand(tac_instruction, 1, result)
result := elna_rtl_call(tac_instruction, next_instruction)
elsif instruction_kind = ElnaTacOperator.subtract then
result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.sub)
elsif instruction_kind = ElnaTacOperator.multiply then
@@ -1189,20 +1234,6 @@ begin
if operand_type = ElnaTacOperand.temporary then
result := elna_rtl_load_operand_value(tac_instruction, 2, operand_value);
next_instruction^ := result^.next
elsif operand_type = ElnaTacOperand.stack then
operands := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t4);
result := operands;
operands := result^.next;
next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.sw);
_elna_tac_instruction_set_operand(next_instruction^, 1, ElnaRtlOperand.register, ElnaRtlRegister.t4, 0);
_elna_tac_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value);
if operands = nil then
result^.next := next_instruction^
else
operands^.next := next_instruction^
end
elsif operand_type = ElnaTacOperand.pseudo then
operands := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t4);
result := operands;
@@ -1378,13 +1409,14 @@ begin
return pseudo_symbol1
end;
proc elna_alloc_instruction(instruction: Word);
proc elna_alloc_instruction(instruction: ^ElnaInstructionList);
var
instruction_kind: Word;
operand_type: Word;
operand_value: Word;
operand_length: Word;
pseudo_symbol1: Word;
pseudo_symbol: Word;
old_instruction: ^ElnaInstructionList;
begin
instruction_kind := elna_rtl_instruction_get_kind(instruction);
@@ -1394,7 +1426,7 @@ begin
operand_length := elna_rtl_instruction_get_operand_length(instruction, 1);
if operand_type = ElnaRtlOperand.pseudo then
pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length);
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.sw);
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2);
@@ -1402,7 +1434,7 @@ begin
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
elna_rtl_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol1);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
goto elna_alloc_instruction_end
end;
@@ -1412,9 +1444,9 @@ begin
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length);
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol1);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
goto elna_alloc_instruction_end
end
@@ -1424,15 +1456,31 @@ begin
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
(* Debug. Error stream output.
printf("# %i %.*s\n\0", operand_length, operand_length, operand_value);
fflush(nil); *)
pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length);
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.addi);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.register, ElnaRtlRegister.sp, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol1, 0);
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0);
goto elna_alloc_instruction_end
end
elsif instruction_kind = ElnaRtlOperator.sw then
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 2);
if operand_type = ElnaRtlOperand.pseudo then
old_instruction := malloc(elna_rtl_instruction_size());
memcpy(old_instruction, instruction, elna_rtl_instruction_size());
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t2, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
instruction^.next := old_instruction;
elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.t2, 0);
goto elna_alloc_instruction_end
end
@@ -1541,7 +1589,7 @@ var
stack_instruction: ^ElnaInstructionList;
begin
.elna_alloc_procedure_loop;
temporary_variable_counter := 60;
temporary_variable_counter := 32;
variable_map := 0;
elna_alloc_instructions(rtl_declaration^.body);
@@ -2148,17 +2196,8 @@ begin
lhs_value := 0;
lhs_length := 0;
instruction := _elna_tac_unary_expression(parser_node^.rhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
current_instruction := elna_instruction_list_concatenate(current_instruction, instruction);
(* Load the left expression from the stack; *)
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 7, 0);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$lhs", 4);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
if parser_node^.operator = ElnaLexerKind.plus then
instruction := _elna_tac_instruction_create(ElnaTacOperator.add)
elsif parser_node^.operator = ElnaLexerKind.minus then
@@ -2277,10 +2316,9 @@ end;
proc _elna_tac_call(parsed_call: Word, symbol_table: Word);
var
argument_count1: Word;
argument_count: Word;
name_length: Word;
name: Word;
stack_offset: Word;
parsed_expression: ^ElnaTreeVariableExpression;
instruction: Word;
first_instruction: Word;
@@ -2288,16 +2326,33 @@ var
operand_type: Word;
operand_value: Word;
operand_length: Word;
arguments_operand: Word;
call_instruction: Word;
name_buffer: Word;
begin
parsed_expression := _call_get_name(parsed_call);
name := parsed_expression^.name;
name_length := parsed_expression^.length;
argument_count1 := 0;
argument_count := 0;
first_instruction := 0;
.elna_tac_call_count;
parsed_expression := _call_get_argument(parsed_call, argument_count + 1);
if parsed_expression <> nil ten
argument_count := argument_count + 1;
goto elna_tac_call_count
end;
arguments_operand := malloc(argument_count * 12);
call_instruction := _elna_tac_instruction_create(ElnaTacOperator.proc_call);
_elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacOperand.symbol, name, name_length);
_elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacOperand.list, arguments_operand, argument_count);
argument_count := 0;
.elna_tac_call_loop;
parsed_expression := _call_get_argument(parsed_call, argument_count1 + 1);
parsed_expression := _call_get_argument(parsed_call, argument_count + 1);
if parsed_expression = 0 then
goto elna_tac_call_finalize
else
@@ -2315,11 +2370,11 @@ begin
end;
(* Save the argument on the stack. *)
stack_offset := argument_count1 * 4;
instruction := _elna_tac_instruction_create(ElnaTacOperator.store);
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 56 - stack_offset, 0);
name_buffer := malloc(4);
sprintf(name_buffer, "$ar%i\0", argument_count);
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, name_buffer, 4);
_elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length);
if first_instruction = 0 then
first_instruction := instruction
else
@@ -2327,32 +2382,22 @@ begin
end;
current_instruction := instruction;
argument_count1 := argument_count1 + 1;
arguments_operand^ := ElnaTacOperand.pseudo;
arguments_operand := arguments_operand + 4;
arguments_operand^ := name_buffer;
arguments_operand := arguments_operand + 4;
arguments_operand^ := 4;
arguments_operand := arguments_operand + 4;
argument_count := argument_count + 1;
goto elna_tac_call_loop
end;
.elna_tac_call_finalize;
(* Load the argument from the stack. *)
if argument_count1 <> 0 then
(* Decrement the argument counter. *)
argument_count1 := argument_count1 - 1;
stack_offset := argument_count1 * 4;
(* Calculate the stack offset: 56 - (4 * argument_counter) *)
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 11 + argument_count1, 0);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 56 - stack_offset, 0);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
goto elna_tac_call_finalize
end;
instruction := _elna_tac_instruction_create(ElnaTacOperator.proc_call);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.symbol, name, name_length);
if first_instruction = 0 then
first_instruction := instruction
if first_instruction = nil then
first_instruction := call_instruction
else
elna_instruction_list_concatenate(current_instruction, instruction)
elna_instruction_list_concatenate(current_instruction, call_instruction)
end;
return first_instruction
end;
@@ -2551,15 +2596,9 @@ begin
elsif parser_node^.kind = ElnaTreeKind.call then
first_instruction := _elna_tac_call(parser_node, symbol_table);
last_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacOperand.temporary, 11, 0);
operand_type^ := ElnaTacOperand.temporary;
operand_value^ := 6;
operand_value^ := 11;
operand_length^ := 0;
elna_instruction_list_concatenate(first_instruction, last_instruction);
is_address^ := 0
else
first_instruction := _elna_tac_simple_expression(parser_node, symbol_table, operand_type, operand_value, operand_length);
@@ -2621,11 +2660,10 @@ begin
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
(* Save the assignee address on the stack. *)
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.store);
_elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacOperand.stack, 0, 0);
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.pseudo, "$assign", 7);
_elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacOperand.temporary, 6, 0);
elna_instruction_list_concatenate(first_instruction, current_instruction);
(* Compile the assignment. *)
operand_type := 0;
operand_value := 0;
@@ -2637,16 +2675,9 @@ begin
current_instruction := instruction
end;
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 7, 0);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 0, 0);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
instruction := _elna_tac_instruction_create(ElnaTacOperator.store);
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.temporary, 7, 0);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$assign", 7);
elna_instruction_list_concatenate(current_instruction, instruction);
end;