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 return result
end; end;
proc _elna_tac_label(counter: Word, length: Word); proc elna_tac_label(counter: Word, length: Word);
var var
result1: Word; result1: Word;
begin begin
@@ -1264,7 +1264,7 @@ begin
return result1 return result1
end; end;
proc _elna_writer_instruction_name(instruction_kind: Word); proc elna_riscv_instruction_name(instruction_kind: Word);
var var
argument_count: Word; argument_count: Word;
begin begin
@@ -1344,13 +1344,13 @@ begin
return argument_count return argument_count
end; end;
proc _elna_writer_register(register: Word); proc elna_riscv_register(register: Word);
begin begin
_write_c('x'); _write_c('x');
_write_i(register - 1) _write_i(register - 1)
end; end;
proc _elna_writer_operand(instruction: Word, n: Word); proc elna_riscv_operand(instruction: Word, n: Word);
var var
operand_value: Word; operand_value: Word;
operand_length: Word; operand_length: Word;
@@ -1362,11 +1362,11 @@ begin
_write_c(' '); _write_c(' ');
if operand_type = ElnaRtlOperand.register then if operand_type = ElnaRtlOperand.register then
_elna_writer_register(operand_value) elna_riscv_register(operand_value)
elsif operand_type = ElnaRtlOperand.offset then elsif operand_type = ElnaRtlOperand.offset then
_write_i(operand_length); _write_i(operand_length);
_write_c('('); _write_c('(');
_elna_writer_register(operand_value); elna_riscv_register(operand_value);
_write_c(')') _write_c(')')
elsif operand_type = ElnaRtlOperand.symbol then elsif operand_type = ElnaRtlOperand.symbol then
if operand_length = 0 then if operand_length = 0 then
@@ -1394,6 +1394,36 @@ begin
return pseudo_symbol1 return pseudo_symbol1
end; 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); proc elna_alloc_instruction(instruction: ^ElnaInstructionList);
var var
instruction_kind: Word; instruction_kind: Word;
@@ -1448,7 +1478,9 @@ begin
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0); elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol, 0);
goto elna_alloc_instruction_end goto elna_alloc_instruction_end
end end;
elna_alloc_operation_target(instruction)
elsif instruction_kind = ElnaRtlOperator.sw then elsif instruction_kind = ElnaRtlOperator.sw then
operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); operand_type := elna_rtl_instruction_get_operand_type(instruction, 2);
operand_value := elna_rtl_instruction_get_operand_value(instruction, 2); operand_value := elna_rtl_instruction_get_operand_value(instruction, 2);
@@ -1469,11 +1501,53 @@ begin
goto elna_alloc_instruction_end goto elna_alloc_instruction_end
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; end;
.elna_alloc_instruction_end; .elna_alloc_instruction_end;
end; end;
proc _elna_writer_instruction(instruction: Word); proc elna_riscv_instruction(instruction: Word);
var var
argument_count: Word; argument_count: Word;
instruction_kind: 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); 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) fflush(nil)
else else
argument_count := _elna_writer_instruction_name(instruction_kind) argument_count := elna_riscv_instruction_name(instruction_kind)
end; end;
current_argument := 1; current_argument := 1;
.elna_writer_instruction_loop; .elna_riscv_instruction_loop;
if current_argument <= argument_count then if current_argument <= argument_count then
_elna_writer_operand(instruction, current_argument); elna_riscv_operand(instruction, current_argument);
current_argument := current_argument + 1 current_argument := current_argument + 1
end; end;
if current_argument <= argument_count then if current_argument <= argument_count then
_write_c(','); _write_c(',');
goto elna_writer_instruction_loop goto elna_riscv_instruction_loop
end; end;
_write_c('\n') _write_c('\n')
@@ -1559,13 +1633,13 @@ begin
end end
end; end;
proc _elna_writer_instructions(instruction: ^ElnaInstructionList); proc elna_riscv_instructions(instruction: ^ElnaInstructionList);
begin begin
.elna_writer_instructions_start; .elna_riscv_instructions_start;
if instruction <> nil then if instruction <> nil then
_elna_writer_instruction(instruction); elna_riscv_instruction(instruction);
instruction := instruction^.next; instruction := instruction^.next;
goto elna_writer_instructions_start goto elna_riscv_instructions_start
end end
end; end;
@@ -1596,9 +1670,9 @@ begin
end end
end; end;
proc _elna_writer_procedure(procedure: ^ElnaInstructionDeclaration); proc elna_riscv_procedure(procedure: ^ElnaInstructionDeclaration);
begin begin
.elna_writer_procedure_loop; .elna_riscv_procedure_loop;
(* Write .type _procedure_name, @function. *) (* Write .type _procedure_name, @function. *)
_write_z(".type \0"); _write_z(".type \0");
@@ -1610,18 +1684,18 @@ begin
_write_s(procedure^.name, procedure^.length); _write_s(procedure^.name, procedure^.length);
_write_z(":\n\0"); _write_z(":\n\0");
_elna_writer_instructions(procedure^.body); elna_riscv_instructions(procedure^.body);
_write_z("\tret\n\0"); _write_z("\tret\n\0");
procedure := procedure^.next; procedure := procedure^.next;
if procedure <> nil then if procedure <> nil then
goto elna_writer_procedure_loop goto elna_riscv_procedure_loop
end end
end; end;
proc _elna_writer_variable(variable: ^ElnaInstructionDeclaration); proc elna_riscv_variable(variable: ^ElnaInstructionDeclaration);
begin begin
.elna_writer_variable_loop; .elna_riscv_variable_loop;
if variable <> 0 then if variable <> 0 then
_write_z(".type \0"); _write_z(".type \0");
_write_s(variable^.name, variable^.length); _write_s(variable^.name, variable^.length);
@@ -1636,7 +1710,7 @@ begin
_write_c('\n'); _write_c('\n');
variable := variable^.next; variable := variable^.next;
goto elna_writer_variable_loop goto elna_riscv_variable_loop
end end
end; end;
@@ -1656,7 +1730,7 @@ begin
elna_alloc_procedure(pair^.code) elna_alloc_procedure(pair^.code)
end; end;
proc _elna_writer_module(pair: ^ElnaInstructionModule); proc elna_riscv_module(pair: ^ElnaInstructionModule);
var var
compiler_strings_copy: Word; compiler_strings_copy: Word;
compiler_strings_end: Word; compiler_strings_end: Word;
@@ -1665,13 +1739,13 @@ begin
_write_z(".globl main\n\n\0"); _write_z(".globl main\n\n\0");
_write_z(".section .data\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(".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 _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"); _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_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0");
_write_c('"'); _write_c('"');
@@ -1679,13 +1753,13 @@ begin
compiler_strings_copy := @compiler_strings; compiler_strings_copy := @compiler_strings;
compiler_strings_end := compiler_strings_position; compiler_strings_end := compiler_strings_position;
.elna_writer_module_loop; .elna_riscv_module_loop;
if compiler_strings_copy < compiler_strings_end then if compiler_strings_copy < compiler_strings_end then
current_byte := _load_byte(compiler_strings_copy); current_byte := _load_byte(compiler_strings_copy);
compiler_strings_copy := compiler_strings_copy + 1; compiler_strings_copy := compiler_strings_copy + 1;
_write_c(current_byte); _write_c(current_byte);
goto elna_writer_module_loop goto elna_riscv_module_loop
end; end;
_write_c('"'); _write_c('"');
_write_c('\n'); _write_c('\n');
@@ -1743,7 +1817,7 @@ begin
return result return result
end; 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 begin
operand_type^ := ElnaTacOperand.immediate; operand_type^ := ElnaTacOperand.immediate;
operand_value^ := integer_literal_node^.value; operand_value^ := integer_literal_node^.value;
@@ -1752,7 +1826,7 @@ begin
return nil return nil
end; 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 begin
operand_type^ := ElnaTacOperand.immediate; operand_type^ := ElnaTacOperand.immediate;
operand_value^ := boolean_literal_node^.value; operand_value^ := boolean_literal_node^.value;
@@ -1761,7 +1835,7 @@ begin
return nil return nil
end; 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 begin
operand_type^ := ElnaTacOperand.immediate; operand_type^ := ElnaTacOperand.immediate;
operand_value^ := 0; operand_value^ := 0;
@@ -1791,7 +1865,7 @@ begin
return result return result
end; 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 begin
operand_type^ := ElnaTacOperand.immediate; operand_type^ := ElnaTacOperand.immediate;
operand_value^ := character_literal_node^.value; operand_value^ := character_literal_node^.value;
@@ -1820,7 +1894,7 @@ begin
return result return result
end; 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: ^ElnaSymbolTemporaryInfo; lookup_result: ^ElnaSymbolTemporaryInfo;
begin begin
@@ -1945,22 +2019,22 @@ begin
return simple_expression return simple_expression
end; 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 var
instruction: Word; instruction: Word;
begin begin
if parser_node^.kind = ElnaTreeKind.character_literal then 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 elsif parser_node^.kind = ElnaTreeKind.string_literal then
instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length) instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length)
elsif parser_node^.kind = ElnaTreeKind.integer_literal then 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 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 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 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; end;
return instruction return instruction
end; end;
@@ -2000,7 +2074,7 @@ begin
return result return result
end; 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 var
current_character: Word; current_character: Word;
token_kind: Word; token_kind: Word;
@@ -2022,7 +2096,7 @@ begin
end; end;
if operator = '@' then 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); instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address);
_elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); _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) first_instruction := elna_instruction_list_concatenate(first_instruction, instruction)
else else
current_character := operand_type^; 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^; operand := operand_type^;
if is_address then if is_address then
@@ -2142,7 +2216,7 @@ begin
return result return result
end; 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 var
first_instruction: Word; first_instruction: Word;
instruction: Word; instruction: Word;
@@ -2152,12 +2226,12 @@ var
lhs_length: Word; lhs_length: Word;
begin begin
if parser_node^.kind <> ElnaTreeKind.binary_expression then 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 else
lhs_type := 0; lhs_type := 0;
lhs_value := 0; lhs_value := 0;
lhs_length := 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. *) (* Save the value of the left expression on the stack. *)
instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
@@ -2174,7 +2248,7 @@ begin
lhs_type := 0; lhs_type := 0;
lhs_value := 0; lhs_value := 0;
lhs_length := 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); current_instruction := elna_instruction_list_concatenate(current_instruction, instruction);
if parser_node^.operator = ElnaLexerKind.plus then if parser_node^.operator = ElnaLexerKind.plus then
@@ -2206,15 +2280,15 @@ begin
elsif parser_node^.operator = ElnaLexerKind.not_equal then elsif parser_node^.operator = ElnaLexerKind.not_equal then
instruction := _elna_tac_instruction_create(ElnaTacOperator.not_equal) instruction := _elna_tac_instruction_create(ElnaTacOperator.not_equal)
end; 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, 2, ElnaTacOperand.pseudo, "$lhs", 4);
_elna_tac_instruction_set_operand(instruction, 3, lhs_type, lhs_value, lhs_length); _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; elna_instruction_list_concatenate(current_instruction, instruction)
operand_value^ := 6;
operand_length^ := 0
end; end;
return first_instruction return first_instruction
end; end;
@@ -2293,7 +2367,7 @@ begin
return result return result
end; end;
proc _elna_tac_call(parsed_call: Word, symbol_table: Word); proc elna_tac_call(parsed_call: Word, symbol_table: Word);
var var
argument_count: Word; argument_count: Word;
name_length: Word; name_length: Word;
@@ -2338,7 +2412,7 @@ begin
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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 if first_instruction = 0 then
first_instruction := instruction first_instruction := instruction
else else
@@ -2400,7 +2474,7 @@ begin
return result1 return result1
end; end;
proc _elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement); proc elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement);
var var
label_length1: Word; label_length1: Word;
label_with_dot1: Word; label_with_dot1: Word;
@@ -2441,11 +2515,11 @@ begin
return result return result
end; end;
proc _elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration); proc elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration);
return _elna_tac_label(parser_node^.label, parser_node^.length) return elna_tac_label(parser_node^.label, parser_node^.length)
end; 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 var
enumeration_type: ^ElnaTypeEnumeration; enumeration_type: ^ElnaTypeEnumeration;
members: Word; members: Word;
@@ -2509,7 +2583,7 @@ begin
return result return result
end; 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 var
field_access_expression: ^ElnaTreeFieldAccessExpression; field_access_expression: ^ElnaTreeFieldAccessExpression;
dereference_expression: ^ElnaTreeDereferenceExpression; dereference_expression: ^ElnaTreeDereferenceExpression;
@@ -2524,7 +2598,7 @@ var
begin begin
if parser_node^.kind = ElnaTreeKind.dereference_expression then if parser_node^.kind = ElnaTreeKind.dereference_expression then
dereference_expression := parser_node; 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); 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, 1, ElnaTacOperand.temporary, 6, 0);
@@ -2541,11 +2615,11 @@ begin
expression_type := field_access_expression^.type_decoration; expression_type := field_access_expression^.type_decoration;
if expression_type^.kind = ElnaTypeKind.enumeration then 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 is_address^ := 0
else else
designator_base := field_access_expression^.aggregate; 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; aggregate_type := designator_base^.type_decoration;
field_count := aggregate_type^.length; field_count := aggregate_type^.length;
@@ -2573,14 +2647,14 @@ begin
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction) first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction)
end; end;
elsif parser_node^.kind = ElnaTreeKind.call then 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_type^ := ElnaTacOperand.temporary;
operand_value^ := 11; operand_value^ := 11;
operand_length^ := 0; operand_length^ := 0;
is_address^ := 0 is_address^ := 0
else 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 is_address^ := 0
end; end;
return first_instruction return first_instruction
@@ -2606,7 +2680,7 @@ begin
return result return result
end; end;
proc _elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: Word); proc elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: Word);
var var
is_address: Word; is_address: Word;
first_instruction: Word; first_instruction: Word;
@@ -2619,7 +2693,7 @@ begin
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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 if operand_type = ElnaTacOperand.pseudo then
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy);
@@ -2628,26 +2702,22 @@ begin
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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); _elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction) first_instruction := elna_instruction_list_concatenate(instruction, current_instruction)
else else
(* Save the assignee address on the stack. *)
current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); 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); _elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); 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. *) (* Compile the assignment. *)
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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 if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction); elna_instruction_list_concatenate(current_instruction, instruction);
@@ -2684,7 +2754,7 @@ begin
return result return result
end; end;
proc _elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word); proc elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word);
var var
first_instruction: Word; first_instruction: Word;
instruction: Word; instruction: Word;
@@ -2695,7 +2765,7 @@ begin
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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); instruction := _elna_tac_instruction_create(ElnaTacOperator._return);
_elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); _elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
@@ -2746,7 +2816,7 @@ begin
return result return result
end; 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 var
condition_label: Word; condition_label: Word;
instruction: Word; instruction: Word;
@@ -2760,7 +2830,7 @@ begin
operand_type := 0; operand_type := 0;
operand_value := 0; operand_value := 0;
operand_length := 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 is the label in front of the next elsif condition or end. *)
condition_label := label_counter; condition_label := label_counter;
@@ -2772,7 +2842,7 @@ begin
elna_instruction_list_concatenate(first_instruction, current_instruction); 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 if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction); elna_instruction_list_concatenate(current_instruction, instruction);
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_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.symbol, after_end_label, 0);
elna_instruction_list_concatenate(current_instruction, instruction); 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); elna_instruction_list_concatenate(instruction, current_instruction);
return first_instruction return first_instruction
@@ -2884,7 +2954,7 @@ begin
return first_statement return first_statement
end; end;
proc _elna_tac_statements(parser_node: Word, symbol_table: Word); proc elna_tac_statements(parser_node: Word, symbol_table: Word);
var var
current_statement: ^ElnaTreeStatement; current_statement: ^ElnaTreeStatement;
instruction: Word; instruction: Word;
@@ -2896,7 +2966,7 @@ begin
.elna_tac_statements_loop; .elna_tac_statements_loop;
if current_statement <> nil then 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; current_statement := current_statement^.next;
if instruction = 0 then if instruction = 0 then
goto elna_tac_statements_loop goto elna_tac_statements_loop
@@ -2912,7 +2982,7 @@ begin
return first_instruction return first_instruction
end; end;
proc _elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word); proc elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word);
var var
current_node: ^ElnaTreeConditionalStatements; current_node: ^ElnaTreeConditionalStatements;
after_end_label: Word; after_end_label: Word;
@@ -2925,13 +2995,13 @@ begin
label_counter := label_counter + 1; label_counter := label_counter + 1;
current_node := parser_node^.conditionals; 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; current_instruction := first_instruction;
.elna_tac_if_statement_loop; .elna_tac_if_statement_loop;
current_node := current_node^.next; current_node := current_node^.next;
if current_node <> nil then 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); elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction; current_instruction := instruction;
goto elna_tac_if_statement_loop goto elna_tac_if_statement_loop
@@ -2939,34 +3009,34 @@ begin
current_node := parser_node^._else; current_node := parser_node^._else;
if parser_node^._else <> nil then 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 if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction); elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction current_instruction := instruction
end end
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); elna_instruction_list_concatenate(current_instruction, instruction);
return first_instruction return first_instruction
end; end;
proc _elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: Word); proc elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: Word);
var var
instruction: Word; instruction: Word;
begin begin
if parser_node^.kind = ElnaTreeKind.goto_statement then 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 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 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 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 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 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 else
instruction := nil instruction := nil
end; end;
@@ -3495,7 +3565,7 @@ begin
return result return result
end; end;
proc _elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word); proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word);
var var
ast_parameter: ^ElnaTreeDeclaration; ast_parameter: ^ElnaTreeDeclaration;
parameter_index: Word; parameter_index: Word;
@@ -3605,7 +3675,7 @@ begin
return result return result
end; end;
proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration); proc elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration);
var var
symbol_info: ^ElnaSymbolProcedureInfo; symbol_info: ^ElnaSymbolProcedureInfo;
result: ^ElnaInstructionDeclaration; result: ^ElnaInstructionDeclaration;
@@ -3621,9 +3691,9 @@ begin
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);
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^.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 return result
end; end;
@@ -3715,7 +3785,7 @@ begin
return first_copy return first_copy
end; end;
proc _elna_tac_procedures(parser_node: ^ElnaTreeDeclaration); proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration);
var var
result: Word; result: Word;
current_procedure: ^ElnaInstructionList; current_procedure: ^ElnaInstructionList;
@@ -3727,7 +3797,7 @@ begin
if parser_node = 0 then if parser_node = 0 then
goto elna_tac_procedures_end goto elna_tac_procedures_end
end; end;
result := _elna_tac_procedure_declaration(parser_node); result := elna_tac_procedure_declaration(parser_node);
if first_procedure = nil then if first_procedure = nil then
first_procedure := result first_procedure := result
else else
@@ -3874,7 +3944,7 @@ begin
return result return result
end; end;
proc _elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration); proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration);
var var
name: Word; name: Word;
name_length: Word; name_length: Word;
@@ -3904,7 +3974,7 @@ begin
return result return result
end; 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 var
result: ^ElnaInstructionDeclaration; result: ^ElnaInstructionDeclaration;
instruction: Word; instruction: Word;
@@ -3934,7 +4004,7 @@ begin
return result return result
end; end;
proc _elna_tac_type_part(parser_node: ^ElnaTreeDeclaration); proc elna_tac_type_part(parser_node: ^ElnaTreeDeclaration);
var var
result: Word; result: Word;
first_result: Word; first_result: Word;
@@ -3956,7 +4026,7 @@ begin
type_kind := info_type^.kind; type_kind := info_type^.kind;
if type_kind = ElnaTypeKind._record then 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 else
result := 0; result := 0;
out_result := 0 out_result := 0
@@ -4015,7 +4085,7 @@ begin
return result return result
end; end;
proc _elna_tac_var_part(parser_node: ^ElnaTreeDeclaration); proc elna_tac_var_part(parser_node: ^ElnaTreeDeclaration);
var var
node: Word; node: Word;
current_variable: ^ElnaInstructionList; current_variable: ^ElnaInstructionList;
@@ -4027,7 +4097,7 @@ begin
end; end;
.elna_tac_var_part_loop; .elna_tac_var_part_loop;
node := _elna_tac_variable_declaration(parser_node); node := elna_tac_variable_declaration(parser_node);
if first_variable = 0 then if first_variable = 0 then
first_variable := node first_variable := node
else else
@@ -4079,7 +4149,7 @@ end;
(** (**
* Process the source code and print the generated code. * 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 var
data_part: Word; data_part: Word;
code_part: Word; code_part: Word;
@@ -4087,9 +4157,9 @@ var
current_declaration: ^ElnaInstructionList; current_declaration: ^ElnaInstructionList;
next_declaration: Word; next_declaration: Word;
begin begin
type_part := _elna_tac_type_part(parser_node^.types); type_part := elna_tac_type_part(parser_node^.types);
data_part := _elna_tac_var_part(parser_node^.globals); data_part := elna_tac_var_part(parser_node^.globals);
code_part := _elna_tac_procedures(parser_node^.procedures); code_part := elna_tac_procedures(parser_node^.procedures);
current_declaration := code_part; current_declaration := code_part;
@@ -4466,10 +4536,10 @@ begin
if compiled then if compiled then
elna_name_module_declaration(parser_node); elna_name_module_declaration(parser_node);
elna_type_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); rtl := elna_rtl_module_declaration(tac);
elna_alloc_module(rtl); elna_alloc_module(rtl);
_elna_writer_module(rtl); elna_riscv_module(rtl);
end; end;
return compiled return compiled