Preserve passed procedure parameters
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user