summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/stage15.elna588
1 files changed, 424 insertions, 164 deletions
diff --git a/boot/stage15.elna b/boot/stage15.elna
index 431ad6b..cf5c69b 100644
--- a/boot/stage15.elna
+++ b/boot/stage15.elna
@@ -177,7 +177,10 @@ type
jump,
beqz,
ret,
- label
+ label,
+ procedure,
+ variable,
+ _module
);
ElnaGeneratorOperand = (register, immediate, symbol, offset);
ElnaGeneratorRegister = (
@@ -587,7 +590,14 @@ end;
proc _elna_generator_instruction_set_next(this: Word, value: Word);
begin
+ .elna_generator_instruction_set_next_loop;
this := this + 4;
+ if value <> 0 then
+ if this^ <> 0 then
+ this := this^;
+ goto elna_generator_instruction_set_next_loop
+ end
+ end;
this^ := value
end;
@@ -651,6 +661,67 @@ begin
return result
end;
+proc _elna_generator_procedure_size();
+ return 20
+end;
+
+proc _elna_generator_procedure_get_kind(this: Word);
+ return this^
+end;
+
+proc _elna_generator_procedure_set_kind(this: Word, value: Word);
+begin
+ this^ := value
+end;
+
+proc _elna_generator_procedure_get_next(this: Word);
+begin
+ this := this + 4;
+ return this^
+end;
+
+proc _elna_generator_procedure_set_next(this: Word, value: Word);
+begin
+ this := this + 4;
+ this^ := value
+end;
+
+proc _elna_generator_procedure_get_name(this: Word);
+begin
+ this := this + 8;
+ return this^
+end;
+
+proc _elna_generator_procedure_set_name(this: Word, value: Word);
+begin
+ this := this + 8;
+ this^ := value
+end;
+
+proc _elna_generator_procedure_get_length(this: Word);
+begin
+ this := this + 12;
+ return this^
+end;
+
+proc _elna_generator_procedure_set_length(this: Word, value: Word);
+begin
+ this := this + 12;
+ this^ := value
+end;
+
+proc _elna_generator_procedure_get_body(this: Word);
+begin
+ this := this + 16;
+ return this^
+end;
+
+proc _elna_generator_procedure_set_body(this: Word, value: Word);
+begin
+ this := this + 16;
+ this^ := value
+end;
+
proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word);
var
result: Word;
@@ -1110,6 +1181,102 @@ begin
end
end;
+proc _elna_writer_procedure(procedure: Word);
+var
+ name_pointer: Word;
+ name_length: Word;
+ body_statements: Word;
+begin
+ .elna_writer_procedure_loop;
+ name_pointer := _elna_generator_procedure_get_name(procedure);
+ name_length := _elna_generator_procedure_get_length(procedure);
+ body_statements := _elna_generator_procedure_get_body(procedure);
+
+ (* Write .type _procedure_name, @function. *)
+ _write_z(".type \0");
+
+ _write_s(name_pointer, name_length);
+ _write_z(", @function\n\0");
+
+ (* Write procedure label, _procedure_name: *)
+ _write_s(name_pointer, name_length);
+ _write_z(":\n\0");
+
+ _elna_writer_instructions(body_statements);
+ procedure := _elna_generator_procedure_get_next(procedure);
+ if procedure <> 0 then
+ goto elna_writer_procedure_loop
+ end
+end;
+
+proc _elna_writer_variable(variable: Word);
+var
+ name: Word;
+ name_length: Word;
+ size: Word;
+begin
+ .elna_writer_variable_loop;
+ if variable <> 0 then
+ name := _elna_generator_procedure_get_name(variable);
+ name_length := _elna_generator_procedure_get_length(variable);
+ size := _elna_generator_procedure_get_body(variable);
+
+ _write_z(".type \0");
+ _write_s(name, name_length);
+ _write_z(", @object\n\0");
+
+ _write_s(name, name_length);
+ _write_c(':');
+
+ _write_z(" .zero \0");
+ _write_i(size);
+
+ _write_c('\n');
+ variable := _elna_generator_procedure_get_next(variable);
+
+ goto elna_writer_variable_loop
+ end
+end;
+
+proc _elna_writer_module(pair: Word);
+var
+ compiler_strings_copy: Word;
+ compiler_strings_end: Word;
+ current_byte: Word;
+ current_part: Word;
+begin
+ _write_z(".globl _start\n\n\0");
+ _write_z(".section .data\n\0");
+
+ current_part := _elna_generator_procedure_get_name(pair);
+ _elna_writer_variable(current_part);
+
+ _write_z(".section .text\n\n\0");
+ _write_z(".type _syscall, @function\n_syscall:\n\tmv a7, a6\n\tecall\n\tret\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");
+
+ current_part := _elna_generator_procedure_get_body(pair);
+ _elna_writer_procedure(current_part);
+
+ _write_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0");
+ _write_c('"');
+
+ compiler_strings_copy := @compiler_strings;
+ compiler_strings_end := compiler_strings_position;
+
+ .compile_module_declaration_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 compile_module_declaration_loop
+ end;
+ _write_c('"');
+ _write_c('\n');
+end;
+
proc _node_set_kind(this: Word, kind: Word);
begin
this^ := kind
@@ -1477,7 +1644,7 @@ begin
instruction := _compile_variable_expression(parser_node, symbol_table);
is_address^ := 1
end;
- _elna_writer_instructions(instruction)
+ return instruction
end;
proc _unary_expression_size();
@@ -1552,6 +1719,7 @@ var
operator: Word;
operand: Word;
is_address: Word;
+ first_instruction: Word;
instruction: Word;
begin
operator := 0;
@@ -1567,21 +1735,22 @@ begin
end;
if operator = '@' then
- _compile_designator(operand, symbol_table, @is_address)
+ first_instruction := _compile_designator(operand, symbol_table, @is_address)
else
- _compile_designator(operand, symbol_table, @is_address);
+ first_instruction := _compile_designator(operand, symbol_table, @is_address);
if is_address then
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
- _elna_writer_instruction(instruction)
+ _elna_generator_instruction_set_next(first_instruction, instruction)
end
end;
if operator = '-' then
instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
- _elna_writer_instruction(instruction)
+ _elna_generator_instruction_set_next(first_instruction, instruction)
elsif operator = '~' then
instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
- _elna_writer_instruction(instruction)
- end
+ _elna_generator_instruction_set_next(first_instruction, instruction)
+ end;
+ return first_instruction
end;
proc _binary_expression_size();
@@ -1700,65 +1869,94 @@ var
operand_node: Word;
first_instruction: Word;
instruction: Word;
+ current_instruction: Word;
begin
expression_kind := _node_get_kind(parser_node);
if expression_kind <> NodeKind.binary_expression then
- _compile_unary_expression(parser_node, symbol_table)
+ first_instruction := _compile_unary_expression(parser_node, symbol_table)
else
token_kind := _binary_expression_get_operator(parser_node);
operand_node := _binary_expression_get_lhs(parser_node);
- _compile_unary_expression(operand_node, symbol_table);
+ first_instruction := _compile_unary_expression(operand_node, symbol_table);
+
(* Save the value of the left expression on the stack. *)
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 64);
- _elna_writer_instruction(instruction);
+ _elna_generator_instruction_set_next(first_instruction, instruction);
+ current_instruction := instruction;
operand_node := _binary_expression_get_rhs(parser_node);
- _compile_unary_expression(operand_node, symbol_table);
+ instruction := _compile_unary_expression(operand_node, symbol_table);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
+
(* Load the left expression from the stack; *)
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 64);
- _elna_writer_instruction(instruction);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
if token_kind = LexerTokenKind.plus then
- first_instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_add(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.minus then
- first_instruction := _elna_generator_sub(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
+ instruction := _elna_generator_sub(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.multiplication then
- first_instruction := _elna_generator_mul(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_mul(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.and then
- first_instruction := _elna_generator_and(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_and(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind._or then
- first_instruction := _elna_generator_or(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_or(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind._xor then
- first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.equals then
- first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
+
instruction := _elna_generator_seqz(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
- _elna_generator_instruction_set_next(first_instruction, instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.remainder then
- first_instruction := _elna_generator_rem(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
+ instruction := _elna_generator_rem(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.division then
- first_instruction := _elna_generator_div(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
+ instruction := _elna_generator_div(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.less_than then
- first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0)
+ instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.greater_than then
- first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1)
+ instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.less_equal then
- first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
+
instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1);
- _elna_generator_instruction_set_next(first_instruction, instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.not_equal then
- first_instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ instruction := _elna_generator_xor(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
+
instruction := _elna_generator_snez(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
- _elna_generator_instruction_set_next(first_instruction, instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction)
elsif token_kind = LexerTokenKind.greater_equal then
- first_instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ instruction := _elna_generator_slt(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, ElnaGeneratorRegister.t0);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
+
instruction := _elna_generator_xor_immediate(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 1);
- _elna_generator_instruction_set_next(first_instruction, instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction)
end;
- _elna_writer_instructions(first_instruction)
- end
+ end;
+ return first_instruction
end;
(* 4 bytes node kind + 4 byte pointer to variable expression + 4 * 7 for arguments. *)
@@ -1860,19 +2058,25 @@ begin
if parsed_expression = 0 then
goto compile_call_finalize
else
- _compile_binary_expression(parsed_expression, symbol_table);
+ instruction := _compile_binary_expression(parsed_expression, symbol_table);
+ if first_instruction = 0 then
+ first_instruction := instruction
+ else
+ _elna_generator_instruction_set_next(current_instruction, instruction)
+ end;
+ current_instruction := instruction;
(* Save the argument on the stack. *)
stack_offset := argument_count * 4;
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0,
ElnaGeneratorRegister.sp, 116 - stack_offset);
- _elna_writer_instruction(instruction);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
argument_count := argument_count + 1;
goto compile_call_loop
end;
-
.compile_call_finalize;
(* Load the argument from the stack. *)
@@ -1884,11 +2088,7 @@ begin
(* Calculate the stack offset: 116 - (4 * argument_counter) *)
instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count,
ElnaGeneratorRegister.sp, 116 - stack_offset);
- if first_instruction = 0 then
- first_instruction := instruction
- else
- _elna_generator_instruction_set_next(current_instruction, instruction)
- end;
+ _elna_generator_instruction_set_next(current_instruction, instruction);
current_instruction := instruction;
goto compile_call_finalize
@@ -1899,7 +2099,7 @@ begin
else
_elna_generator_instruction_set_next(current_instruction, instruction)
end;
- _elna_writer_instructions(first_instruction)
+ return first_instruction
end;
(**
@@ -2147,22 +2347,22 @@ begin
name_length := _field_access_expression_get_length(field_access_expression);
counter := 1;
+ instruction := 0;
.compile_enumeration_value_members;
if members_length > 0 then
member_name := members^;
member_length := members + 4;
member_length := member_length^;
- if _lexer_compare_keyword(value_name, name_length, member_name, member_length) then
- else
+ if _lexer_compare_keyword(value_name, name_length, member_name, member_length) = 0 then
members_length := members_length - 1;
members := members + 8;
counter := counter + 1;
goto compile_enumeration_value_members
end;
- instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0);
- _elna_writer_instructions(instruction)
- end
+ instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0)
+ end;
+ return instruction
end;
proc _parse_field_access_expression(aggregate: Word);
@@ -2199,103 +2399,109 @@ var
token_kind: Word;
parser_node: Word;
node_kind: Word;
+ first_instruction: Word;
instruction: Word;
begin
node_kind := _node_get_kind(parser_node);
if node_kind = NodeKind.dereference_expression then
parser_node := _dereference_expression_get_pointer(parser_node);
- _compile_simple_expression(parser_node, symbol_table, is_address);
+ first_instruction := _compile_simple_expression(parser_node, symbol_table, is_address);
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
- _elna_writer_instructions(instruction)
+ _elna_generator_instruction_set_next(first_instruction, instruction);
elsif node_kind = NodeKind.field_access_expression then
- _compile_enumeration_value(parser_node);
+ first_instruction := _compile_enumeration_value(parser_node);
is_address^ := 0
elsif node_kind = NodeKind.call then
- _compile_call(parser_node, symbol_table);
+ first_instruction := _compile_call(parser_node, symbol_table);
instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0);
- _elna_writer_instructions(instruction);
+ _elna_generator_instruction_set_next(first_instruction, instruction);
is_address^ := 0
else
- _compile_simple_expression(parser_node, symbol_table, is_address)
+ first_instruction := _compile_simple_expression(parser_node, symbol_table, is_address)
end;
- return is_address
+ return first_instruction
end;
-proc _assignment_statement_size();
+proc _assign_statement_size();
return 16
end;
-proc _assignment_statement_get_assignee(this: Word);
+proc _assign_statement_get_assignee(this: Word);
begin
this := this + 8;
return this^
end;
-proc _assignment_statement_set_assignee(this: Word, value: Word);
+proc _assign_statement_set_assignee(this: Word, value: Word);
begin
this := this + 8;
this^ := value
end;
-proc _assignment_statement_get_assignment(this: Word);
+proc _assign_statement_get_assignment(this: Word);
begin
this := this + 12;
return this^
end;
-proc _assignment_statement_set_assignment(this: Word, value: Word);
+proc _assign_statement_set_assignment(this: Word, value: Word);
begin
this := this + 12;
this^ := value
end;
-proc _parse_assignment_statement(assignee: Word);
+proc _parse_assign_statement(assignee: Word);
var
statement_size: Word;
result: Word;
token_kind: Word;
assignment_node: Word;
begin
- statement_size := _assignment_statement_size();
+ statement_size := _assign_statement_size();
result := _allocate(statement_size);
- _node_set_kind(result, NodeKind.assignment_statement);
+ _node_set_kind(result, NodeKind.assign_statement);
_statement_set_next(result, 0);
- _assignment_statement_set_assignee(result, assignee);
+ _assign_statement_set_assignee(result, assignee);
(* Skip the assignment sign (:=) with surrounding whitespaces. *)
_lexer_read_token(@token_kind);
_lexer_skip_token();
assignment_node := _parse_binary_expression();
- _assignment_statement_set_assignment(result, assignment_node);
+ _assign_statement_set_assignment(result, assignment_node);
return result
end;
-proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word);
+proc _compile_assign_statement(parser_tree: Word, symbol_table: Word);
var
current_expression: Word;
is_address: Word;
first_instruction: Word;
instruction: Word;
+ current_instruction: Word;
begin
- current_expression := _assignment_statement_get_assignee(parser_tree);
- _compile_designator(current_expression, symbol_table, @is_address);
+ current_expression := _assign_statement_get_assignee(parser_tree);
+ first_instruction := _compile_designator(current_expression, symbol_table, @is_address);
(* Save the assignee address on the stack. *)
- instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60);
- _elna_writer_instructions(instruction);
+ current_instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60);
+ _elna_generator_instruction_set_next(first_instruction, current_instruction);
(* Compile the assignment. *)
- current_expression := _assignment_statement_get_assignment(parser_tree);
- _compile_binary_expression(current_expression, symbol_table);
+ current_expression := _assign_statement_get_assignment(parser_tree);
+ instruction := _compile_binary_expression(current_expression, symbol_table);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+
+ current_instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 60);
+ _elna_generator_instruction_set_next(instruction, current_instruction);
- first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 60);
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, 0);
- _elna_generator_instruction_set_next(first_instruction, instruction);
- _elna_writer_instructions(first_instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+
+ return first_instruction
end;
proc _return_statement_size();
@@ -2341,12 +2547,14 @@ end;
proc _compile_return_statement(parser_node: Word, symbol_table: Word);
var
return_expression: Word;
+ first_instruction: Word;
instruction: Word;
begin
return_expression := _return_statement_get_returned(parser_node);
- _compile_binary_expression(return_expression, symbol_table);
+ first_instruction := _compile_binary_expression(return_expression, symbol_table);
instruction := _elna_generator_move(ElnaGeneratorRegister.a0, ElnaGeneratorRegister.t0);
- _elna_writer_instructions(instruction)
+ _elna_generator_instruction_set_next(first_instruction, instruction);
+ return first_instruction
end;
(**
@@ -2403,26 +2611,34 @@ var
condition_label: Word;
current_node: Word;
instruction: Word;
+ current_instruction: Word;
+ first_instruction: Word;
begin
(* Compile condition. *)
current_node := _conditional_statements_get_condition(parser_node);
- _compile_binary_expression(current_node, symbol_table);
+ first_instruction := _compile_binary_expression(current_node, symbol_table);
(* condition_label is the label in front of the next elsif condition or end. *)
condition_label := label_counter;
label_counter := label_counter + 1;
- instruction := _elna_generator_beqz(ElnaGeneratorRegister.t0, condition_label, 0);
- _elna_writer_instructions(instruction);
+ current_instruction := _elna_generator_beqz(ElnaGeneratorRegister.t0, condition_label, 0);
+ _elna_generator_instruction_set_next(first_instruction, current_instruction);
current_node := _conditional_statements_get_statements(parser_node);
- _compile_statements(current_node, symbol_table);
+ instruction := _compile_statements(current_node, symbol_table);
+ if instruction <> 0 then
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction
+ end;
instruction := _elna_generator_jump(after_end_label, 0);
- _elna_writer_instructions(instruction);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
- instruction := _elna_generator_label(condition_label, 0);
- _elna_writer_instructions(instruction)
+ current_instruction := _elna_generator_label(condition_label, 0);
+ _elna_generator_instruction_set_next(instruction, current_instruction);
+
+ return first_instruction
end;
(**
@@ -2554,7 +2770,7 @@ begin
result := _parse_designator();
if _node_get_kind(result) <> NodeKind.call then
- result := _parse_assignment_statement(result)
+ result := _parse_assign_statement(result)
end
end;
return result
@@ -2598,15 +2814,29 @@ end;
proc _compile_statements(parser_node: Word, symbol_table: Word);
var
current_statement: Word;
+ instruction: Word;
+ first_instruction: Word;
+ current_instruction: Word;
begin
current_statement := parser_node;
+ first_instruction := 0;
.compile_statements_loop;
if current_statement <> 0 then
- _compile_statement(current_statement, symbol_table);
+ instruction := _compile_statement(current_statement, symbol_table);
current_statement := _statement_get_next(current_statement);
+ if instruction = 0 then
+ goto compile_statements_loop
+ end;
+ if first_instruction = 0 then
+ first_instruction := instruction
+ else
+ _elna_generator_instruction_set_next(current_instruction, instruction)
+ end;
+ current_instruction := instruction;
goto compile_statements_loop
- end
+ end;
+ return first_instruction
end;
proc _compile_if_statement(parser_node: Word, symbol_table: Word);
@@ -2614,27 +2844,38 @@ var
current_node: Word;
after_end_label: Word;
condition_label: Word;
+ first_instruction: Word;
instruction: Word;
+ current_instruction: Word;
begin
after_end_label := label_counter;
label_counter := label_counter + 1;
current_node := _if_statement_get_conditionals(parser_node);
- _compile_conditional_statements(current_node, after_end_label, symbol_table);
+ first_instruction := _compile_conditional_statements(current_node, after_end_label, symbol_table);
+ current_instruction := first_instruction;
.compile_if_statement_loop;
current_node := _conditional_statements_get_next(current_node);
if current_node <> 0 then
- _compile_conditional_statements(current_node, after_end_label, symbol_table);
+ instruction := _compile_conditional_statements(current_node, after_end_label, symbol_table);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction;
goto compile_if_statement_loop
end;
current_node := _if_statement_get_else(parser_node);
if current_node <> 0 then
- _compile_statements(current_node, symbol_table)
+ instruction := _compile_statements(current_node, symbol_table);
+ if instruction <> 0 then
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction
+ end
end;
instruction := _elna_generator_label(after_end_label, 0);
- _elna_writer_instructions(instruction)
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+
+ return first_instruction
end;
proc _compile_statement(parser_node: Word, symbol_table: Word);
@@ -2645,20 +2886,21 @@ begin
statement_kind := _node_get_kind(parser_node);
if statement_kind = NodeKind.goto_statement then
- instruction := _compile_goto_statement(parser_node);
- _elna_writer_instructions(instruction)
+ instruction := _compile_goto_statement(parser_node)
elsif statement_kind = NodeKind.if_statement then
- _compile_if_statement(parser_node, symbol_table)
+ instruction := _compile_if_statement(parser_node, symbol_table)
elsif statement_kind = NodeKind.return_statement then
- _compile_return_statement(parser_node, symbol_table)
+ instruction := _compile_return_statement(parser_node, symbol_table)
elsif statement_kind = NodeKind.label_declaration then
- instruction := _compile_label_declaration(parser_node);
- _elna_writer_instructions(instruction)
+ instruction := _compile_label_declaration(parser_node)
elsif statement_kind = NodeKind.call then
- _compile_call(parser_node, symbol_table)
- elsif statement_kind = NodeKind.assignment_statement then
- _compile_assignment_statement(parser_node, symbol_table)
- end
+ instruction := _compile_call(parser_node, symbol_table)
+ elsif statement_kind = NodeKind.assign_statement then
+ instruction := _compile_assign_statement(parser_node, symbol_table)
+ else
+ instruction := 0
+ end;
+ return instruction
end;
(**
@@ -3269,23 +3511,24 @@ var
instruction: Word;
first_instruction: Word;
current_instruction: Word;
+ result: Word;
+ result_size: Word;
begin
+ result_size := _elna_generator_procedure_size();
+ result := _allocate(result_size);
+
+ _elna_generator_procedure_set_kind(result, ElnaGeneratorKind.procedure);
+ _elna_generator_procedure_set_next(result, 0);
+
name_pointer := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node);
+ _elna_generator_procedure_set_name(result, name_pointer);
+ _elna_generator_procedure_set_length(result, name_length);
+
symbol_info := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length);
new_symbol_table := _procedure_info_get_symbol_table(symbol_info);
- (* Write .type _procedure_name, @function. *)
- _write_z(".type \0");
-
- _write_s(name_pointer, name_length);
- _write_z(", @function\n\0");
-
- (* Write procedure label, _procedure_name: *)
- _write_s(name_pointer, name_length);
- _write_z(":\n\0");
-
(* Write the prologue. *)
first_instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, -128);
current_instruction := _elna_generator_store_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
@@ -3307,11 +3550,7 @@ begin
instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter,
ElnaGeneratorRegister.sp, symbol_info);
- if first_instruction = 0 then
- first_instruction := instruction
- else
- _elna_generator_instruction_set_next(current_instruction, instruction)
- end;
+ _elna_generator_instruction_set_next(current_instruction, instruction);
current_instruction := instruction;
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
@@ -3320,19 +3559,28 @@ begin
current_parameter := _declaration_get_next(current_parameter);
goto compile_procedure_declaration_parameters
end;
- _elna_writer_instructions(first_instruction);
current_parameter := _procedure_declaration_get_body(parser_node);
- _compile_statements(current_parameter, new_symbol_table);
+
+ instruction := _compile_statements(current_parameter, new_symbol_table);
+ if instruction <> 0 then
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+ current_instruction := instruction
+ end;
(* Write the epilogue. *)
- first_instruction := _elna_generator_load_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
+ instruction := _elna_generator_load_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
+ _elna_generator_instruction_set_next(current_instruction, instruction);
+
current_instruction := _elna_generator_load_word(ElnaGeneratorRegister.s0, ElnaGeneratorRegister.sp, 120);
- _elna_generator_instruction_set_next(first_instruction, current_instruction);
+ _elna_generator_instruction_set_next(instruction, current_instruction);
instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, 128);
_elna_generator_instruction_set_next(current_instruction, instruction);
current_instruction := _elna_generator_instruction_create(ElnaGeneratorKind.ret);
_elna_generator_instruction_set_next(instruction, current_instruction);
- _elna_writer_instructions(first_instruction)
+
+ _elna_generator_procedure_set_body(result, first_instruction);
+
+ return result
end;
proc _parse_procedures();
@@ -3369,16 +3617,28 @@ end;
proc _compile_procedures(parser_node: Word);
var
result: Word;
+ current_procedure: Word;
+ first_procedure: Word;
begin
+ first_procedure := 0;
+
.compile_procedures_loop;
if parser_node = 0 then
goto compile_procedures_end
end;
- _compile_procedure_declaration(parser_node);
+ result := _compile_procedure_declaration(parser_node);
+ if first_procedure = 0 then
+ first_procedure := result
+ else
+ _elna_generator_procedure_set_next(current_procedure, result)
+ end;
+ current_procedure := result;
+
parser_node := _declaration_get_next(parser_node);
goto compile_procedures_loop;
- .compile_procedures_end
+ .compile_procedures_end;
+ return first_procedure
end;
(**
@@ -3551,31 +3811,33 @@ proc _compile_variable_declaration(parser_tree: Word);
var
name: Word;
name_length: Word;
- token_kind: Word;
variable_type: Word;
+ result: Word;
+ result_size: Word;
begin
+ result_size := _elna_generator_procedure_size();
+ result := _allocate(result_size);
+
+ _elna_generator_procedure_set_kind(result, ElnaGeneratorKind.variable);
+ _elna_generator_procedure_set_next(result, 0);
+
name := _declaration_get_name(parser_tree);
name_length := _declaration_get_length(parser_tree);
variable_type := _variable_declaration_get_type(parser_tree);
- _write_z(".type \0");
- _write_s(name, name_length);
- _write_z(", @object\n\0");
-
- _write_s(name, name_length);
- _write_c(':');
+ _elna_generator_procedure_set_name(result, name);
+ _elna_generator_procedure_set_length(result, name_length);
- _lexer_read_token(@token_kind);
name := _named_type_expression_get_name(variable_type);
name_length := _named_type_expression_get_length(variable_type);
if _lexer_compare_keyword("Array", 5, name, name_length) then
(* Else we assume this is a zeroed 4096 bytes big array. *)
- _write_z(" .zero 4096\0")
+ _elna_generator_procedure_set_body(result, 4096)
else
- _write_z(" .word 0\n\0")
+ _elna_generator_procedure_set_body(result, 4)
end;
- _write_c('\n')
+ return result
end;
proc _parse_var_part();
@@ -3619,21 +3881,32 @@ begin
end;
proc _compile_var_part(parser_node: Word);
+var
+ node: Word;
+ current_variable: Word;
+ first_variable: Word;
begin
+ first_variable := 0;
if parser_node = 0 then
goto compile_var_part_end
end;
- _write_z(".section .data\n\0");
.compile_var_part_loop;
- _compile_variable_declaration(parser_node);
+ node := _compile_variable_declaration(parser_node);
+ if first_variable = 0 then
+ first_variable := node
+ else
+ _elna_generator_procedure_set_next(current_variable, node)
+ end;
+ current_variable := node;
parser_node := _declaration_get_next(parser_node);
if parser_node <> 0 then
goto compile_var_part_loop
end;
- .compile_var_part_end
+ .compile_var_part_end;
+ return first_variable
end;
proc _module_declaration_size();
@@ -3705,39 +3978,24 @@ end;
proc _compile_module_declaration(parser_node: Word);
var
current_part: Word;
- compiler_strings_copy: Word;
- compiler_strings_end: Word;
- current_byte: Word;
+ result: Word;
+ result_size: Word;
begin
- _write_z(".globl _start\n\n\0");
+ result_size := _elna_generator_procedure_size();
+ result := _allocate(result_size);
- current_part := _module_declaration_get_globals(parser_node);
- _compile_var_part(current_part);
+ _elna_generator_procedure_set_kind(result, ElnaGeneratorKind._module);
+ _elna_generator_procedure_set_next(result, 0);
- _write_z(".section .text\n\n\0");
- _write_z(".type _syscall, @function\n_syscall:\n\tmv a7, a6\n\tecall\n\tret\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");
+ current_part := _module_declaration_get_globals(parser_node);
+ current_part := _compile_var_part(current_part);
+ _elna_generator_procedure_set_name(result, current_part);
current_part := _module_declaration_get_procedures(parser_node);
- _compile_procedures(current_part);
-
- _write_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0");
- _write_c('"');
-
- compiler_strings_copy := @compiler_strings;
- compiler_strings_end := compiler_strings_position;
-
- .compile_module_declaration_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);
+ current_part := _compile_procedures(current_part);
+ _elna_generator_procedure_set_body(result, current_part);
- goto compile_module_declaration_loop
- end;
- _write_c('"');
- _write_c('\n')
+ return result
end;
proc _read_procedure_declaration(parser_node: Word);
@@ -3798,10 +4056,12 @@ end;
proc _compile();
var
parser_node: Word;
+ tac: Word;
begin
parser_node := _parse_module_declaration();
_read_module_declaration(parser_node);
- _compile_module_declaration(parser_node)
+ tac := _compile_module_declaration(parser_node);
+ _elna_writer_module(tac)
end;
(**