Preserve passed procedure parameters
This commit is contained in:
@@ -26,7 +26,9 @@ type
|
|||||||
name: Word;
|
name: Word;
|
||||||
length: Word;
|
length: Word;
|
||||||
body: Word;
|
body: Word;
|
||||||
stack: Word
|
stack: Word;
|
||||||
|
parameters: Word;
|
||||||
|
count: Word
|
||||||
end;
|
end;
|
||||||
ElnaTreeNode = record
|
ElnaTreeNode = record
|
||||||
kind: Word
|
kind: Word
|
||||||
@@ -239,11 +241,6 @@ type
|
|||||||
kind: Word;
|
kind: Word;
|
||||||
_type: Word
|
_type: Word
|
||||||
end;
|
end;
|
||||||
ElnaSymbolParameterInfo = record
|
|
||||||
kind: Word;
|
|
||||||
offset: Word;
|
|
||||||
variable_type: Word
|
|
||||||
end;
|
|
||||||
ElnaSymbolTemporaryInfo = record
|
ElnaSymbolTemporaryInfo = record
|
||||||
kind: Word;
|
kind: Word;
|
||||||
offset: Word;
|
offset: Word;
|
||||||
@@ -467,8 +464,8 @@ type
|
|||||||
allocate_stack,
|
allocate_stack,
|
||||||
ret
|
ret
|
||||||
);
|
);
|
||||||
ElnaTacOperand = (temporary, immediate, symbol, stack, pseudo, list);
|
ElnaTacOperand = (temporary, immediate, symbol, pseudo, list);
|
||||||
ElnaRtlOperand = (register, immediate, symbol, offset, pseudo);
|
ElnaRtlOperand = (register, immediate, symbol, pseudo, offset);
|
||||||
ElnaRtlRegister = (
|
ElnaRtlRegister = (
|
||||||
zero,
|
zero,
|
||||||
ra,
|
ra,
|
||||||
@@ -833,10 +830,6 @@ begin
|
|||||||
result := elna_rtl_instruction_create(ElnaRtlOperator.li);
|
result := elna_rtl_instruction_create(ElnaRtlOperator.li);
|
||||||
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
|
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
|
||||||
elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.immediate, operand_value, operand_length)
|
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
|
elsif operand_type = ElnaTacOperand.symbol then
|
||||||
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
||||||
elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0);
|
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_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2);
|
||||||
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
|
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
|
||||||
|
|
||||||
if operand_type = ElnaTacOperand.stack then
|
if operand_type = ElnaTacOperand.symbol 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
|
|
||||||
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
result := elna_rtl_instruction_create(ElnaRtlOperator.la);
|
||||||
|
|
||||||
elna_rtl_copy_operand(tac_instruction, 1, result);
|
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_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2);
|
||||||
operand_value := _elna_tac_instruction_get_operand_value(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);
|
operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2);
|
||||||
if operand_type = ElnaTacOperand.stack then
|
if operand_type = ElnaTacOperand.pseudo then
|
||||||
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value)
|
|
||||||
elsif operand_type = ElnaTacOperand.pseudo then
|
|
||||||
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.pseudo, operand_value, operand_length)
|
elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.pseudo, operand_value, operand_length)
|
||||||
end;
|
end;
|
||||||
if operands = 0 then
|
if operands = 0 then
|
||||||
@@ -1589,7 +1574,7 @@ var
|
|||||||
stack_instruction: ^ElnaInstructionList;
|
stack_instruction: ^ElnaInstructionList;
|
||||||
begin
|
begin
|
||||||
.elna_alloc_procedure_loop;
|
.elna_alloc_procedure_loop;
|
||||||
temporary_variable_counter := 32;
|
temporary_variable_counter := 4;
|
||||||
variable_map := 0;
|
variable_map := 0;
|
||||||
|
|
||||||
elna_alloc_instructions(rtl_declaration^.body);
|
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);
|
proc _elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
|
||||||
var
|
var
|
||||||
lookup_result: ^ElnaSymbolParameterInfo;
|
lookup_result: ^ElnaSymbolTemporaryInfo;
|
||||||
begin
|
begin
|
||||||
lookup_result := _symbol_table_lookup(symbol_table, variable_expression^.name, variable_expression^.length);
|
lookup_result := _symbol_table_lookup(symbol_table, variable_expression^.name, variable_expression^.length);
|
||||||
|
|
||||||
if lookup_result <> nil then
|
if lookup_result <> nil then
|
||||||
if lookup_result^.kind = ElnaSymbolInfoKind.temporary_info then
|
operand_type^ := ElnaTacOperand.pseudo;
|
||||||
operand_type^ := ElnaTacOperand.pseudo;
|
operand_value^ := variable_expression^.name;
|
||||||
operand_value^ := variable_expression^.name;
|
operand_length^ := variable_expression^.length
|
||||||
operand_length^ := variable_expression^.length
|
|
||||||
else
|
|
||||||
operand_type^ := ElnaTacOperand.stack;
|
|
||||||
operand_value^ := lookup_result^.offset;
|
|
||||||
operand_length^ := 0
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
operand_type^ := ElnaTacOperand.symbol;
|
operand_type^ := ElnaTacOperand.symbol;
|
||||||
operand_value^ := variable_expression^.name;
|
operand_value^ := variable_expression^.name;
|
||||||
@@ -3365,27 +3344,6 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
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);
|
proc _type_info_create(type_representation: Word);
|
||||||
var
|
var
|
||||||
result: ^ElnaSymbolTypeInfo;
|
result: ^ElnaSymbolTypeInfo;
|
||||||
@@ -3431,21 +3389,6 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
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:
|
* Parameters:
|
||||||
* variable_index - Variable index.
|
* variable_index - Variable index.
|
||||||
@@ -3552,39 +3495,43 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _elna_tac_parameters(current_parameter: ^ElnaTreeDeclaration, new_symbol_table: Word);
|
proc _elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word);
|
||||||
var
|
var
|
||||||
name_pointer: Word;
|
ast_parameter: ^ElnaTreeDeclaration;
|
||||||
name_length: Word;
|
parameter_index: Word;
|
||||||
parameter_counter: Word;
|
current_parameter: Word;
|
||||||
instruction: Word;
|
parameter_list: Word;
|
||||||
first_instruction: Word;
|
|
||||||
current_instruction: Word;
|
|
||||||
symbol_info: ^ElnaSymbolParameterInfo;
|
|
||||||
begin
|
begin
|
||||||
first_instruction := 0;
|
ast_parameter := ast_list;
|
||||||
parameter_counter := 0;
|
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;
|
.elna_tac_parameters_loop;
|
||||||
if current_parameter <> 0 then
|
if parameter_index < parameter_count^ then
|
||||||
symbol_info := _symbol_table_lookup(new_symbol_table, current_parameter^.name, current_parameter^.length);
|
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);
|
parameter_index := parameter_index + 1;
|
||||||
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 11 + parameter_counter, 0);
|
ast_parameter := ast_parameter^.next;
|
||||||
_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;
|
|
||||||
goto elna_tac_parameters_loop
|
goto elna_tac_parameters_loop
|
||||||
end;
|
end;
|
||||||
return first_instruction
|
|
||||||
|
return parameter_list
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc elna_rtl_global_declaration(tac_declaration: ^ElnaInstructionDeclaration);
|
proc elna_rtl_global_declaration(tac_declaration: ^ElnaInstructionDeclaration);
|
||||||
@@ -3601,9 +3548,48 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
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);
|
proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaInstructionDeclaration);
|
||||||
var
|
var
|
||||||
result: ^ElnaInstructionDeclaration;
|
result: ^ElnaInstructionDeclaration;
|
||||||
|
body: ^ElnaInstructionList;
|
||||||
|
parameters: ^ElnaInstructionList;
|
||||||
begin
|
begin
|
||||||
result := malloc(ElnaInstructionDeclaration_size());
|
result := malloc(ElnaInstructionDeclaration_size());
|
||||||
|
|
||||||
@@ -3611,20 +3597,19 @@ begin
|
|||||||
result^.name := tac_declaration^.name;
|
result^.name := tac_declaration^.name;
|
||||||
result^.length := tac_declaration^.length;
|
result^.length := tac_declaration^.length;
|
||||||
result^.stack := tac_declaration^.stack;
|
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
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
|
proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
|
||||||
var
|
var
|
||||||
current_parameter: Word;
|
|
||||||
new_symbol_table: Word;
|
|
||||||
symbol_info: ^ElnaSymbolProcedureInfo;
|
symbol_info: ^ElnaSymbolProcedureInfo;
|
||||||
instruction: Word;
|
|
||||||
first_instruction: Word;
|
|
||||||
result: ^ElnaInstructionDeclaration;
|
result: ^ElnaInstructionDeclaration;
|
||||||
result_size: Word;
|
parameter_count: Word;
|
||||||
begin
|
begin
|
||||||
result := malloc(ElnaInstructionDeclaration_size());
|
result := malloc(ElnaInstructionDeclaration_size());
|
||||||
|
|
||||||
@@ -3635,15 +3620,10 @@ begin
|
|||||||
result^.length := parser_node^.length;
|
result^.length := parser_node^.length;
|
||||||
|
|
||||||
symbol_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, 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;
|
result^.parameters := _elna_tac_parameters(parser_node^.parameters, @parameter_count);
|
||||||
first_instruction := _elna_tac_parameters(current_parameter, new_symbol_table);
|
result^.count := parameter_count;
|
||||||
|
result^.body := _elna_tac_statements(parser_node^.body, symbol_info^.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;
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end;
|
end;
|
||||||
@@ -4128,23 +4108,12 @@ end;
|
|||||||
proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration);
|
proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration);
|
||||||
var
|
var
|
||||||
new_symbol_table: Word;
|
new_symbol_table: Word;
|
||||||
parameter_counter: Word;
|
|
||||||
symbol_info: Word;
|
symbol_info: Word;
|
||||||
current_parameter: ^ElnaTreeDeclaration;
|
|
||||||
begin
|
begin
|
||||||
new_symbol_table := _symbol_table_create();
|
new_symbol_table := _symbol_table_create();
|
||||||
symbol_info := _procedure_info_create(new_symbol_table);
|
symbol_info := _procedure_info_create(new_symbol_table);
|
||||||
|
|
||||||
current_parameter := parser_node^.parameters;
|
elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table);
|
||||||
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^.temporaries, 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)
|
_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);
|
proc elna_type_variable_expression(parser_node: ^ElnaTreeVariableExpression, symbol_table: Word);
|
||||||
var
|
var
|
||||||
variable_info: ^ElnaSymbolInfo;
|
variable_info: ^ElnaSymbolInfo;
|
||||||
parameter_info: ^ElnaSymbolParameterInfo;
|
|
||||||
temporary_info: ^ElnaSymbolTemporaryInfo;
|
temporary_info: ^ElnaSymbolTemporaryInfo;
|
||||||
begin
|
begin
|
||||||
variable_info := _symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length);
|
variable_info := _symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length);
|
||||||
@@ -4286,11 +4254,7 @@ begin
|
|||||||
if variable_info = nil then
|
if variable_info = nil then
|
||||||
variable_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length)
|
variable_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length)
|
||||||
end;
|
end;
|
||||||
|
if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then
|
||||||
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
|
|
||||||
temporary_info := variable_info;
|
temporary_info := variable_info;
|
||||||
parser_node^.type_decoration := temporary_info^.variable_type
|
parser_node^.type_decoration := temporary_info^.variable_type
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user