Use pseudo register in binary expressions

This commit is contained in:
2025-12-22 20:38:26 +01:00
parent 3a8bf8ae88
commit b4eabfae4e

View File

@@ -1253,7 +1253,7 @@ begin
return result
end;
proc _elna_tac_label(counter: Word, length: Word);
proc elna_tac_label(counter: Word, length: Word);
var
result1: Word;
begin
@@ -1264,7 +1264,7 @@ begin
return result1
end;
proc _elna_writer_instruction_name(instruction_kind: Word);
proc elna_riscv_instruction_name(instruction_kind: Word);
var
argument_count: Word;
begin
@@ -1344,13 +1344,13 @@ begin
return argument_count
end;
proc _elna_writer_register(register: Word);
proc elna_riscv_register(register: Word);
begin
_write_c('x');
_write_i(register - 1)
end;
proc _elna_writer_operand(instruction: Word, n: Word);
proc elna_riscv_operand(instruction: Word, n: Word);
var
operand_value: Word;
operand_length: Word;
@@ -1362,11 +1362,11 @@ begin
_write_c(' ');
if operand_type = ElnaRtlOperand.register then
_elna_writer_register(operand_value)
elna_riscv_register(operand_value)
elsif operand_type = ElnaRtlOperand.offset then
_write_i(operand_length);
_write_c('(');
_elna_writer_register(operand_value);
elna_riscv_register(operand_value);
_write_c(')')
elsif operand_type = ElnaRtlOperand.symbol then
if operand_length = 0 then
@@ -1394,6 +1394,36 @@ begin
return pseudo_symbol1
end;
(**
* If the first operand of an instruction is an operation target and expected
* to be a register, but is not a register, then this procedure rewrites it
* to a temporary register and preserves its value in the following instruction.
*)
proc elna_alloc_operation_target(instruction: ^ElnaInstructionList);
var
operand_type: Word;
operand_value: Word;
operand_length: Word;
pseudo_symbol: Word;
store_instruction: ^ElnaInstructionList;
begin
operand_type := elna_rtl_instruction_get_operand_type(instruction, 1);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 1);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 1);
if operand_type = ElnaRtlOperand.pseudo then
store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
store_instruction^.next := instruction^.next;
pseudo_symbol := elna_alloc_variable(operand_value, operand_length);
elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol);
instruction^.next := store_instruction;
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlOperand.register, ElnaRtlRegister.t0, 0)
end
end;
proc elna_alloc_instruction(instruction: ^ElnaInstructionList);
var
instruction_kind: Word;
@@ -1448,7 +1478,9 @@ begin
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0);
goto elna_alloc_instruction_end
end
end;
elna_alloc_operation_target(instruction)
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);
@@ -1469,11 +1501,53 @@ begin
goto elna_alloc_instruction_end
end
elsif instruction_kind = ElnaRtlOperator._or then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.and then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.mul then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.sub then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.add then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator._xor then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.rem then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.slt then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.beqz then
operand_type := elna_rtl_instruction_get_operand_type(instruction, 1);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 1);
operand_length := elna_rtl_instruction_get_operand_length(instruction, 1);
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.t0, 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, 1, ElnaRtlOperand.register, ElnaRtlRegister.t0, 0);
goto elna_alloc_instruction_end
end
elsif instruction_kind = ElnaRtlOperator.seqz then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.snez then
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.xori then
elna_alloc_operation_target(instruction)
end;
.elna_alloc_instruction_end;
end;
proc _elna_writer_instruction(instruction: Word);
proc elna_riscv_instruction(instruction: Word);
var
argument_count: Word;
instruction_kind: Word;
@@ -1503,18 +1577,18 @@ begin
printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value + 4, operand_value, operand_value + 8);
fflush(nil)
else
argument_count := _elna_writer_instruction_name(instruction_kind)
argument_count := elna_riscv_instruction_name(instruction_kind)
end;
current_argument := 1;
.elna_writer_instruction_loop;
.elna_riscv_instruction_loop;
if current_argument <= argument_count then
_elna_writer_operand(instruction, current_argument);
elna_riscv_operand(instruction, current_argument);
current_argument := current_argument + 1
end;
if current_argument <= argument_count then
_write_c(',');
goto elna_writer_instruction_loop
goto elna_riscv_instruction_loop
end;
_write_c('\n')
@@ -1559,13 +1633,13 @@ begin
end
end;
proc _elna_writer_instructions(instruction: ^ElnaInstructionList);
proc elna_riscv_instructions(instruction: ^ElnaInstructionList);
begin
.elna_writer_instructions_start;
.elna_riscv_instructions_start;
if instruction <> nil then
_elna_writer_instruction(instruction);
elna_riscv_instruction(instruction);
instruction := instruction^.next;
goto elna_writer_instructions_start
goto elna_riscv_instructions_start
end
end;
@@ -1596,9 +1670,9 @@ begin
end
end;
proc _elna_writer_procedure(procedure: ^ElnaInstructionDeclaration);
proc elna_riscv_procedure(procedure: ^ElnaInstructionDeclaration);
begin
.elna_writer_procedure_loop;
.elna_riscv_procedure_loop;
(* Write .type _procedure_name, @function. *)
_write_z(".type \0");
@@ -1610,18 +1684,18 @@ begin
_write_s(procedure^.name, procedure^.length);
_write_z(":\n\0");
_elna_writer_instructions(procedure^.body);
elna_riscv_instructions(procedure^.body);
_write_z("\tret\n\0");
procedure := procedure^.next;
if procedure <> nil then
goto elna_writer_procedure_loop
goto elna_riscv_procedure_loop
end
end;
proc _elna_writer_variable(variable: ^ElnaInstructionDeclaration);
proc elna_riscv_variable(variable: ^ElnaInstructionDeclaration);
begin
.elna_writer_variable_loop;
.elna_riscv_variable_loop;
if variable <> 0 then
_write_z(".type \0");
_write_s(variable^.name, variable^.length);
@@ -1636,7 +1710,7 @@ begin
_write_c('\n');
variable := variable^.next;
goto elna_writer_variable_loop
goto elna_riscv_variable_loop
end
end;
@@ -1656,7 +1730,7 @@ begin
elna_alloc_procedure(pair^.code)
end;
proc _elna_writer_module(pair: ^ElnaInstructionModule);
proc elna_riscv_module(pair: ^ElnaInstructionModule);
var
compiler_strings_copy: Word;
compiler_strings_end: Word;
@@ -1665,13 +1739,13 @@ begin
_write_z(".globl main\n\n\0");
_write_z(".section .data\n\0");
_elna_writer_variable(pair^.data);
elna_riscv_variable(pair^.data);
_write_z(".section .text\n\n\0");
_write_z(".type _load_byte, @function\n_load_byte:\n\tlb a0, (a0)\nret\n\n\0");
_write_z(".type _store_byte, @function\n_store_byte:\n\tsb a0, (a1)\nret\n\n\0");
_elna_writer_procedure(pair^.code);
elna_riscv_procedure(pair^.code);
_write_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0");
_write_c('"');
@@ -1679,13 +1753,13 @@ begin
compiler_strings_copy := @compiler_strings;
compiler_strings_end := compiler_strings_position;
.elna_writer_module_loop;
.elna_riscv_module_loop;
if compiler_strings_copy < compiler_strings_end then
current_byte := _load_byte(compiler_strings_copy);
compiler_strings_copy := compiler_strings_copy + 1;
_write_c(current_byte);
goto elna_writer_module_loop
goto elna_riscv_module_loop
end;
_write_c('"');
_write_c('\n');
@@ -1743,7 +1817,7 @@ begin
return result
end;
proc _elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
begin
operand_type^ := ElnaTacOperand.immediate;
operand_value^ := integer_literal_node^.value;
@@ -1752,7 +1826,7 @@ begin
return nil
end;
proc _elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
begin
operand_type^ := ElnaTacOperand.immediate;
operand_value^ := boolean_literal_node^.value;
@@ -1761,7 +1835,7 @@ begin
return nil
end;
proc _elna_tac_nil_literal(nil_node: Word, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_nil_literal(nil_node: Word, operand_type: Word, operand_value: Word, operand_length: Word);
begin
operand_type^ := ElnaTacOperand.immediate;
operand_value^ := 0;
@@ -1791,7 +1865,7 @@ begin
return result
end;
proc _elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral, operand_type: Word, operand_value: Word, operand_length: Word);
begin
operand_type^ := ElnaTacOperand.immediate;
operand_value^ := character_literal_node^.value;
@@ -1820,7 +1894,7 @@ begin
return result
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
lookup_result: ^ElnaSymbolTemporaryInfo;
begin
@@ -1945,22 +2019,22 @@ begin
return simple_expression
end;
proc _elna_tac_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var
instruction: Word;
begin
if parser_node^.kind = ElnaTreeKind.character_literal then
instruction := _elna_tac_character_literal(parser_node, operand_type, operand_value, operand_length)
instruction := elna_tac_character_literal(parser_node, operand_type, operand_value, operand_length)
elsif parser_node^.kind = ElnaTreeKind.string_literal then
instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length)
elsif parser_node^.kind = ElnaTreeKind.integer_literal then
instruction := _elna_tac_integer_literal(parser_node, operand_type, operand_value, operand_length)
instruction := elna_tac_integer_literal(parser_node, operand_type, operand_value, operand_length)
elsif parser_node^.kind = ElnaTreeKind.boolean_literal then
instruction := _elna_tac_boolean_literal(parser_node, operand_type, operand_value, operand_length)
instruction := elna_tac_boolean_literal(parser_node, operand_type, operand_value, operand_length)
elsif parser_node^.kind = ElnaTreeKind.null then
instruction := _elna_tac_nil_literal(parser_node, operand_type, operand_value, operand_length)
instruction := elna_tac_nil_literal(parser_node, operand_type, operand_value, operand_length)
else
instruction := _elna_tac_variable_expression(parser_node, symbol_table, operand_type, operand_value, operand_length)
instruction := elna_tac_variable_expression(parser_node, symbol_table, operand_type, operand_value, operand_length)
end;
return instruction
end;
@@ -2000,7 +2074,7 @@ begin
return result
end;
proc _elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var
current_character: Word;
token_kind: Word;
@@ -2022,7 +2096,7 @@ begin
end;
if operator = '@' then
first_instruction := _elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0);
@@ -2035,7 +2109,7 @@ begin
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction)
else
current_character := operand_type^;
first_instruction := _elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
first_instruction := elna_tac_designator(operand, symbol_table, @is_address, operand_type, operand_value, operand_length);
operand := operand_type^;
if is_address then
@@ -2142,7 +2216,7 @@ begin
return result
end;
proc _elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var
first_instruction: Word;
instruction: Word;
@@ -2152,12 +2226,12 @@ var
lhs_length: Word;
begin
if parser_node^.kind <> ElnaTreeKind.binary_expression then
first_instruction := _elna_tac_unary_expression(parser_node, symbol_table, operand_type, operand_value, operand_length)
first_instruction := elna_tac_unary_expression(parser_node, symbol_table, operand_type, operand_value, operand_length)
else
lhs_type := 0;
lhs_value := 0;
lhs_length := 0;
first_instruction := _elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
first_instruction := elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
(* Save the value of the left expression on the stack. *)
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
@@ -2174,7 +2248,7 @@ begin
lhs_type := 0;
lhs_value := 0;
lhs_length := 0;
instruction := _elna_tac_unary_expression(parser_node^.rhs, symbol_table, @lhs_type, @lhs_value, @lhs_length);
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);
if parser_node^.operator = ElnaLexerKind.plus then
@@ -2206,15 +2280,15 @@ begin
elsif parser_node^.operator = ElnaLexerKind.not_equal then
instruction := _elna_tac_instruction_create(ElnaTacOperator.not_equal)
end;
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$binary", 7);
_elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$lhs", 4);
_elna_tac_instruction_set_operand(instruction, 3, lhs_type, lhs_value, lhs_length);
elna_instruction_list_concatenate(current_instruction, instruction);
operand_type^ := ElnaTacOperand.pseudo;
operand_value^ := "$binary";
operand_length^ := 7;
operand_type^ := ElnaTacOperand.temporary;
operand_value^ := 6;
operand_length^ := 0
elna_instruction_list_concatenate(current_instruction, instruction)
end;
return first_instruction
end;
@@ -2293,7 +2367,7 @@ begin
return result
end;
proc _elna_tac_call(parsed_call: Word, symbol_table: Word);
proc elna_tac_call(parsed_call: Word, symbol_table: Word);
var
argument_count: Word;
name_length: Word;
@@ -2338,7 +2412,7 @@ begin
operand_type := 0;
operand_value := 0;
operand_length := 0;
instruction := _elna_tac_binary_expression(parsed_expression, symbol_table, @operand_type, @operand_value, @operand_length);
instruction := elna_tac_binary_expression(parsed_expression, symbol_table, @operand_type, @operand_value, @operand_length);
if first_instruction = 0 then
first_instruction := instruction
else
@@ -2400,7 +2474,7 @@ begin
return result1
end;
proc _elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement);
proc elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement);
var
label_length1: Word;
label_with_dot1: Word;
@@ -2441,11 +2515,11 @@ begin
return result
end;
proc _elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration);
return _elna_tac_label(parser_node^.label, parser_node^.length)
proc elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration);
return elna_tac_label(parser_node^.label, parser_node^.length)
end;
proc _elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand_type: Word, operand_value: Word, operand_length: Word);
var
enumeration_type: ^ElnaTypeEnumeration;
members: Word;
@@ -2509,7 +2583,7 @@ begin
return result
end;
proc _elna_tac_designator(parser_node: ^ElnaTreeExpression, symbol_table: Word, is_address: Word, operand_type: Word, operand_value: Word, operand_length: Word);
proc elna_tac_designator(parser_node: ^ElnaTreeExpression, symbol_table: Word, is_address: Word, operand_type: Word, operand_value: Word, operand_length: Word);
var
field_access_expression: ^ElnaTreeFieldAccessExpression;
dereference_expression: ^ElnaTreeDereferenceExpression;
@@ -2524,7 +2598,7 @@ var
begin
if parser_node^.kind = ElnaTreeKind.dereference_expression then
dereference_expression := parser_node;
first_instruction := _elna_tac_designator(dereference_expression^.pointer, symbol_table, is_address, operand_type, operand_value, operand_length);
first_instruction := elna_tac_designator(dereference_expression^.pointer, symbol_table, is_address, operand_type, operand_value, operand_length);
last_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
_elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.temporary, 6, 0);
@@ -2541,11 +2615,11 @@ begin
expression_type := field_access_expression^.type_decoration;
if expression_type^.kind = ElnaTypeKind.enumeration then
first_instruction := _elna_tac_enumeration_value(field_access_expression, operand_type, operand_value, operand_length);
first_instruction := elna_tac_enumeration_value(field_access_expression, operand_type, operand_value, operand_length);
is_address^ := 0
else
designator_base := field_access_expression^.aggregate;
first_instruction := _elna_tac_designator(designator_base, symbol_table, is_address, operand_type, operand_value, operand_length);
first_instruction := elna_tac_designator(designator_base, symbol_table, is_address, operand_type, operand_value, operand_length);
aggregate_type := designator_base^.type_decoration;
field_count := aggregate_type^.length;
@@ -2573,14 +2647,14 @@ begin
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction)
end;
elsif parser_node^.kind = ElnaTreeKind.call then
first_instruction := _elna_tac_call(parser_node, symbol_table);
first_instruction := elna_tac_call(parser_node, symbol_table);
operand_type^ := ElnaTacOperand.temporary;
operand_value^ := 11;
operand_length^ := 0;
is_address^ := 0
else
first_instruction := _elna_tac_simple_expression(parser_node, symbol_table, operand_type, operand_value, operand_length);
first_instruction := elna_tac_simple_expression(parser_node, symbol_table, operand_type, operand_value, operand_length);
is_address^ := 0
end;
return first_instruction
@@ -2606,7 +2680,7 @@ begin
return result
end;
proc _elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: Word);
proc elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: Word);
var
is_address: Word;
first_instruction: Word;
@@ -2619,7 +2693,7 @@ begin
operand_type := 0;
operand_value := 0;
operand_length := 0;
first_instruction := _elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length);
first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length);
if operand_type = ElnaTacOperand.pseudo then
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
@@ -2628,26 +2702,22 @@ begin
operand_type := 0;
operand_value := 0;
operand_length := 0;
instruction := _elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
_elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction)
else
(* Save the assignee address on the stack. *)
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
_elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0);
_elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.pseudo, "$assign", 7);
_elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
(* Save the assignee address on the stack. *)
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;
operand_length := 0;
instruction := _elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length);
if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
@@ -2684,7 +2754,7 @@ begin
return result
end;
proc _elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word);
proc elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word);
var
first_instruction: Word;
instruction: Word;
@@ -2695,7 +2765,7 @@ begin
operand_type := 0;
operand_value := 0;
operand_length := 0;
first_instruction := _elna_tac_binary_expression(parser_node^.returned, symbol_table, @operand_type, @operand_value, @operand_length);
first_instruction := elna_tac_binary_expression(parser_node^.returned, symbol_table, @operand_type, @operand_value, @operand_length);
instruction := _elna_tac_instruction_create(ElnaTacOperator._return);
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
@@ -2746,7 +2816,7 @@ begin
return result
end;
proc _elna_tac_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, after_end_label: Word, symbol_table: Word);
proc elna_tac_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, after_end_label: Word, symbol_table: Word);
var
condition_label: Word;
instruction: Word;
@@ -2760,7 +2830,7 @@ begin
operand_type := 0;
operand_value := 0;
operand_length := 0;
first_instruction := _elna_tac_binary_expression(parser_node^.condition, symbol_table, @operand_type, @operand_value, @operand_length);
first_instruction := elna_tac_binary_expression(parser_node^.condition, symbol_table, @operand_type, @operand_value, @operand_length);
(* condition_label is the label in front of the next elsif condition or end. *)
condition_label := label_counter;
@@ -2772,7 +2842,7 @@ begin
elna_instruction_list_concatenate(first_instruction, current_instruction);
instruction := _elna_tac_statements(parser_node^.statements, symbol_table);
instruction := elna_tac_statements(parser_node^.statements, symbol_table);
if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
@@ -2782,7 +2852,7 @@ begin
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.symbol, after_end_label, 0);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := _elna_tac_label(condition_label, 0);
current_instruction := elna_tac_label(condition_label, 0);
elna_instruction_list_concatenate(instruction, current_instruction);
return first_instruction
@@ -2884,7 +2954,7 @@ begin
return first_statement
end;
proc _elna_tac_statements(parser_node: Word, symbol_table: Word);
proc elna_tac_statements(parser_node: Word, symbol_table: Word);
var
current_statement: ^ElnaTreeStatement;
instruction: Word;
@@ -2896,7 +2966,7 @@ begin
.elna_tac_statements_loop;
if current_statement <> nil then
instruction := _elna_tac_statement(current_statement, symbol_table);
instruction := elna_tac_statement(current_statement, symbol_table);
current_statement := current_statement^.next;
if instruction = 0 then
goto elna_tac_statements_loop
@@ -2912,7 +2982,7 @@ begin
return first_instruction
end;
proc _elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word);
proc elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word);
var
current_node: ^ElnaTreeConditionalStatements;
after_end_label: Word;
@@ -2925,13 +2995,13 @@ begin
label_counter := label_counter + 1;
current_node := parser_node^.conditionals;
first_instruction := _elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
first_instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
current_instruction := first_instruction;
.elna_tac_if_statement_loop;
current_node := current_node^.next;
if current_node <> nil then
instruction := _elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
goto elna_tac_if_statement_loop
@@ -2939,34 +3009,34 @@ begin
current_node := parser_node^._else;
if parser_node^._else <> nil then
instruction := _elna_tac_statements(parser_node^._else, symbol_table);
instruction := elna_tac_statements(parser_node^._else, symbol_table);
if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end
end;
instruction := _elna_tac_label(after_end_label, 0);
instruction := elna_tac_label(after_end_label, 0);
elna_instruction_list_concatenate(current_instruction, instruction);
return first_instruction
end;
proc _elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: Word);
proc elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: Word);
var
instruction: Word;
begin
if parser_node^.kind = ElnaTreeKind.goto_statement then
instruction := _elna_tac_goto_statement(parser_node)
instruction := elna_tac_goto_statement(parser_node)
elsif parser_node^.kind = ElnaTreeKind.if_statement then
instruction := _elna_tac_if_statement(parser_node, symbol_table)
instruction := elna_tac_if_statement(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.return_statement then
instruction := _elna_tac_return_statement(parser_node, symbol_table)
instruction := elna_tac_return_statement(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.label_declaration then
instruction := _elna_tac_label_declaration(parser_node)
instruction := elna_tac_label_declaration(parser_node)
elsif parser_node^.kind = ElnaTreeKind.call then
instruction := _elna_tac_call(parser_node, symbol_table)
instruction := elna_tac_call(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.assign_statement then
instruction := _elna_tac_assign_statement(parser_node, symbol_table)
instruction := elna_tac_assign_statement(parser_node, symbol_table)
else
instruction := nil
end;
@@ -3495,7 +3565,7 @@ begin
return result
end;
proc _elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word);
proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word);
var
ast_parameter: ^ElnaTreeDeclaration;
parameter_index: Word;
@@ -3605,7 +3675,7 @@ begin
return result
end;
proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
proc elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
var
symbol_info: ^ElnaSymbolProcedureInfo;
result: ^ElnaInstructionDeclaration;
@@ -3621,9 +3691,9 @@ begin
symbol_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length);
result^.parameters := _elna_tac_parameters(parser_node^.parameters, @parameter_count);
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);
result^.body := elna_tac_statements(parser_node^.body, symbol_info^.symbol_table);
return result
end;
@@ -3715,7 +3785,7 @@ begin
return first_copy
end;
proc _elna_tac_procedures(parser_node: ^ElnaTreeDeclaration);
proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration);
var
result: Word;
current_procedure: ^ElnaInstructionList;
@@ -3727,7 +3797,7 @@ begin
if parser_node = 0 then
goto elna_tac_procedures_end
end;
result := _elna_tac_procedure_declaration(parser_node);
result := elna_tac_procedure_declaration(parser_node);
if first_procedure = nil then
first_procedure := result
else
@@ -3874,7 +3944,7 @@ begin
return result
end;
proc _elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration);
proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration);
var
name: Word;
name_length: Word;
@@ -3904,7 +3974,7 @@ begin
return result
end;
proc _elna_tac_type_record(name_pointer: Word, name_length: Word, type_representation: ^ElnaTypeRecord, current_result: Word);
proc elna_tac_type_record(name_pointer: Word, name_length: Word, type_representation: ^ElnaTypeRecord, current_result: Word);
var
result: ^ElnaInstructionDeclaration;
instruction: Word;
@@ -3934,7 +4004,7 @@ begin
return result
end;
proc _elna_tac_type_part(parser_node: ^ElnaTreeDeclaration);
proc elna_tac_type_part(parser_node: ^ElnaTreeDeclaration);
var
result: Word;
first_result: Word;
@@ -3956,7 +4026,7 @@ begin
type_kind := info_type^.kind;
if type_kind = ElnaTypeKind._record then
result := _elna_tac_type_record(parser_node^.name, parser_node^.length, info_type, @out_result)
result := elna_tac_type_record(parser_node^.name, parser_node^.length, info_type, @out_result)
else
result := 0;
out_result := 0
@@ -4015,7 +4085,7 @@ begin
return result
end;
proc _elna_tac_var_part(parser_node: ^ElnaTreeDeclaration);
proc elna_tac_var_part(parser_node: ^ElnaTreeDeclaration);
var
node: Word;
current_variable: ^ElnaInstructionList;
@@ -4027,7 +4097,7 @@ begin
end;
.elna_tac_var_part_loop;
node := _elna_tac_variable_declaration(parser_node);
node := elna_tac_variable_declaration(parser_node);
if first_variable = 0 then
first_variable := node
else
@@ -4079,7 +4149,7 @@ end;
(**
* Process the source code and print the generated code.
*)
proc _elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration);
proc elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration);
var
data_part: Word;
code_part: Word;
@@ -4087,9 +4157,9 @@ var
current_declaration: ^ElnaInstructionList;
next_declaration: Word;
begin
type_part := _elna_tac_type_part(parser_node^.types);
data_part := _elna_tac_var_part(parser_node^.globals);
code_part := _elna_tac_procedures(parser_node^.procedures);
type_part := elna_tac_type_part(parser_node^.types);
data_part := elna_tac_var_part(parser_node^.globals);
code_part := elna_tac_procedures(parser_node^.procedures);
current_declaration := code_part;
@@ -4466,10 +4536,10 @@ begin
if compiled then
elna_name_module_declaration(parser_node);
elna_type_module_declaration(parser_node);
tac := _elna_tac_module_declaration(parser_node);
tac := elna_tac_module_declaration(parser_node);
rtl := elna_rtl_module_declaration(tac);
elna_alloc_module(rtl);
_elna_writer_module(rtl);
elna_riscv_module(rtl);
end;
return compiled