Preserve passed procedure parameters

This commit is contained in:
2025-12-17 00:52:46 +01:00
parent 1cf71f1a5f
commit 18f5a4bd2f

View File

@@ -26,7 +26,9 @@ type
name: Word;
length: Word;
body: Word;
stack: Word
stack: Word;
parameters: Word;
count: Word
end;
ElnaTreeNode = record
kind: Word
@@ -239,11 +241,6 @@ type
kind: Word;
_type: Word
end;
ElnaSymbolParameterInfo = record
kind: Word;
offset: Word;
variable_type: Word
end;
ElnaSymbolTemporaryInfo = record
kind: Word;
offset: Word;
@@ -467,8 +464,8 @@ type
allocate_stack,
ret
);
ElnaTacOperand = (temporary, immediate, symbol, stack, pseudo, list);
ElnaRtlOperand = (register, immediate, symbol, offset, pseudo);
ElnaTacOperand = (temporary, immediate, symbol, pseudo, list);
ElnaRtlOperand = (register, immediate, symbol, pseudo, offset);
ElnaRtlRegister = (
zero,
ra,
@@ -833,10 +830,6 @@ begin
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);
@@ -1074,13 +1067,7 @@ begin
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
if operand_type = ElnaTacOperand.stack then
result := elna_rtl_instruction_create(ElnaRtlOperator.add);
elna_rtl_copy_operand(tac_instruction, 1, result);
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.register, ElnaRtlRegister.sp, 0);
elna_rtl_instruction_set_operand(result, 3, ElnaRtlOperand.immediate, operand_value, 0)
elsif operand_type = ElnaTacOperand.symbol then
if operand_type = ElnaTacOperand.symbol then
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
elna_rtl_copy_operand(tac_instruction, 1, result);
@@ -1126,9 +1113,7 @@ begin
operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2);
operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
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.pseudo then
if operand_type = ElnaTacOperand.pseudo then
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.pseudo, operand_value, operand_length)
end;
if operands = 0 then
@@ -1589,7 +1574,7 @@ var
stack_instruction: ^ElnaInstructionList;
begin
.elna_alloc_procedure_loop;
temporary_variable_counter := 32;
temporary_variable_counter := 4;
variable_map := 0;
elna_alloc_instructions(rtl_declaration^.body);
@@ -1837,20 +1822,14 @@ end;
proc _elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var
lookup_result: ^ElnaSymbolParameterInfo;
lookup_result: ^ElnaSymbolTemporaryInfo;
begin
lookup_result := _symbol_table_lookup(symbol_table, variable_expression^.name, variable_expression^.length);
if lookup_result <> nil then
if lookup_result^.kind = ElnaSymbolInfoKind.temporary_info then
operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := variable_expression^.name;
operand_length^ := variable_expression^.length
else
operand_type^ := ElnaTacOperand.stack;
operand_value^ := lookup_result^.offset;
operand_length^ := 0
end
operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := variable_expression^.name;
operand_length^ := variable_expression^.length
else
operand_type^ := ElnaTacOperand.symbol;
operand_value^ := variable_expression^.name;
@@ -3365,27 +3344,6 @@ begin
return result
end;
(**
* Parameters:
* parameter_index - Parameter index.
* parameter_type - Parameter type.
*)
proc _parameter_info_create(parameter_index: Word, parameter_type: Word);
var
offset: Word;
result: ^ElnaSymbolParameterInfo;
begin
result := malloc(ElnaSymbolParameterInfo_size());
result^.kind := ElnaSymbolInfoKind.parameter_info;
(* Calculate the stack offset: 28 - (4 * parameter_counter) *)
offset := parameter_index * 4;
result^.offset := 28 - offset;
result^.variable_type := parameter_type;
return result
end;
proc _type_info_create(type_representation: Word);
var
result: ^ElnaSymbolTypeInfo;
@@ -3431,21 +3389,6 @@ begin
return result
end;
(**
* Parameters:
* parameter_index - Parameter index.
*)
proc elna_name_procedure_parameter(parser_node: ^ElnaTreeVariableDeclaration, parameter_index: Word, symbol_table: Word);
var
info: Word;
variable_type1: Word;
begin
variable_type1 := elna_name_type_expression(parser_node^._type);
info := _parameter_info_create(parameter_index, variable_type1);
_symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info)
end;
(**
* Parameters:
* variable_index - Variable index.
@@ -3552,39 +3495,43 @@ begin
return result
end;
proc _elna_tac_parameters(current_parameter: ^ElnaTreeDeclaration, new_symbol_table: Word);
proc _elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word);
var
name_pointer: Word;
name_length: Word;
parameter_counter: Word;
instruction: Word;
first_instruction: Word;
current_instruction: Word;
symbol_info: ^ElnaSymbolParameterInfo;
ast_parameter: ^ElnaTreeDeclaration;
parameter_index: Word;
current_parameter: Word;
parameter_list: Word;
begin
first_instruction := 0;
parameter_counter := 0;
ast_parameter := ast_list;
parameter_count^ := 0;
.elna_tac_parameters_count;
if ast_parameter <> nil then
ast_parameter := ast_parameter^.next;
parameter_count^ := parameter_count^ + 1;
goto elna_tac_parameters_count
end;
(* The parameters are saved as an array of name pointer + name length. *)
parameter_list := malloc(parameter_count^ * 8);
current_parameter := parameter_list;
ast_parameter := ast_list;
parameter_index := 0;
.elna_tac_parameters_loop;
if current_parameter <> 0 then
symbol_info := _symbol_table_lookup(new_symbol_table, current_parameter^.name, current_parameter^.length);
if parameter_index < parameter_count^ then
current_parameter^ := ast_parameter^.name;
current_parameter := current_parameter + 4;
current_parameter^ := ast_parameter^.length;
current_parameter := current_parameter + 4;
instruction := _elna_tac_instruction_create(ElnaTacOperator.store);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 11 + parameter_counter, 0);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, symbol_info^.offset, 0);
if first_instruction = nil then
first_instruction := instruction
else
elna_instruction_list_concatenate(current_instruction, instruction)
end;
current_instruction := instruction;
parameter_counter := parameter_counter + 1;
current_parameter := current_parameter^.next;
parameter_index := parameter_index + 1;
ast_parameter := ast_parameter^.next;
goto elna_tac_parameters_loop
end;
return first_instruction
return parameter_list
end;
proc elna_rtl_global_declaration(tac_declaration: ^ElnaInstructionDeclaration);
@@ -3601,9 +3548,48 @@ begin
return result
end;
proc elna_rtl_parameters(parameters: Word, count: Word);
var
result: Word;
current_instruction: Word;
last_instruction: Word;
parameter_index: Word;
parameter_name: Word;
name_length: Word;
begin
result := nil;
parameter_index := 0;
.elna_rtl_parameters_loop;
if parameter_index < count then
parameter_name := parameters^;
parameters := parameters + 4;
name_length := parameters^;
parameters := parameters + 4;
current_instruction := elna_rtl_instruction_create(ElnaRtlOperator.move);
elna_rtl_instruction_set_operand(current_instruction, 1, ElnaRtlOperand.pseudo, parameter_name, name_length);
elna_rtl_instruction_set_operand(current_instruction, 2, ElnaRtlOperand.register, 11 + parameter_index, 0);
if result = nil then
result := current_instruction
else
elna_instruction_list_concatenate(last_instruction, current_instruction)
end;
last_instruction := current_instruction;
parameter_index := parameter_index + 1;
goto elna_rtl_parameters_loop
end;
return result
end;
proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaInstructionDeclaration);
var
result: ^ElnaInstructionDeclaration;
body: ^ElnaInstructionList;
parameters: ^ElnaInstructionList;
begin
result := malloc(ElnaInstructionDeclaration_size());
@@ -3611,20 +3597,19 @@ begin
result^.name := tac_declaration^.name;
result^.length := tac_declaration^.length;
result^.stack := tac_declaration^.stack;
result^.body := elna_rtl_instructions(tac_declaration^.body);
parameters = elna_rtl_parameters(tac_declaration^.parameters, tac_declaration^.count);
body := elna_rtl_instructions(tac_declaration^.body);
result^.body := elna_instruction_list_concatenate(parameters, body);
return result
end;
proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
var
current_parameter: Word;
new_symbol_table: Word;
symbol_info: ^ElnaSymbolProcedureInfo;
instruction: Word;
first_instruction: Word;
result: ^ElnaInstructionDeclaration;
result_size: Word;
parameter_count: Word;
begin
result := malloc(ElnaInstructionDeclaration_size());
@@ -3635,15 +3620,10 @@ begin
result^.length := parser_node^.length;
symbol_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length);
new_symbol_table := symbol_info^.symbol_table;
current_parameter := parser_node^.parameters;
first_instruction := _elna_tac_parameters(current_parameter, new_symbol_table);
instruction := _elna_tac_statements(parser_node^.body, new_symbol_table);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction);
result^.body := first_instruction;
result^.parameters := _elna_tac_parameters(parser_node^.parameters, @parameter_count);
result^.count := parameter_count;
result^.body := _elna_tac_statements(parser_node^.body, symbol_info^.symbol_table);
return result
end;
@@ -4128,23 +4108,12 @@ end;
proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration);
var
new_symbol_table: Word;
parameter_counter: Word;
symbol_info: Word;
current_parameter: ^ElnaTreeDeclaration;
begin
new_symbol_table := _symbol_table_create();
symbol_info := _procedure_info_create(new_symbol_table);
current_parameter := parser_node^.parameters;
parameter_counter := 0;
.elna_name_procedure_declaration_parameter;
if current_parameter <> nil then
elna_name_procedure_parameter(current_parameter, parameter_counter, new_symbol_table);
parameter_counter := parameter_counter + 1;
current_parameter := current_parameter^.next;
goto elna_name_procedure_declaration_parameter
end;
elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table);
elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table);
_symbol_table_enter(@symbol_table_global, parser_node^.name, parser_node^.length, symbol_info)
@@ -4278,7 +4247,6 @@ end;
proc elna_type_variable_expression(parser_node: ^ElnaTreeVariableExpression, symbol_table: Word);
var
variable_info: ^ElnaSymbolInfo;
parameter_info: ^ElnaSymbolParameterInfo;
temporary_info: ^ElnaSymbolTemporaryInfo;
begin
variable_info := _symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length);
@@ -4286,11 +4254,7 @@ begin
if variable_info = nil then
variable_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length)
end;
if variable_info^.kind = ElnaSymbolInfoKind.parameter_info then
parameter_info := variable_info;
parser_node^.type_decoration := parameter_info^.variable_type
elsif variable_info^.kind = ElnaSymbolInfoKind.temporary_info then
if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then
temporary_info := variable_info;
parser_node^.type_decoration := temporary_info^.variable_type
end