Make TAC generation stage
This commit is contained in:
@@ -177,7 +177,10 @@ type
|
|||||||
jump,
|
jump,
|
||||||
beqz,
|
beqz,
|
||||||
ret,
|
ret,
|
||||||
label
|
label,
|
||||||
|
procedure,
|
||||||
|
variable,
|
||||||
|
_module
|
||||||
);
|
);
|
||||||
ElnaGeneratorOperand = (register, immediate, symbol, offset);
|
ElnaGeneratorOperand = (register, immediate, symbol, offset);
|
||||||
ElnaGeneratorRegister = (
|
ElnaGeneratorRegister = (
|
||||||
@@ -587,7 +590,14 @@ end;
|
|||||||
|
|
||||||
proc _elna_generator_instruction_set_next(this: Word, value: Word);
|
proc _elna_generator_instruction_set_next(this: Word, value: Word);
|
||||||
begin
|
begin
|
||||||
|
.elna_generator_instruction_set_next_loop;
|
||||||
this := this + 4;
|
this := this + 4;
|
||||||
|
if value <> 0 then
|
||||||
|
if this^ <> 0 then
|
||||||
|
this := this^;
|
||||||
|
goto elna_generator_instruction_set_next_loop
|
||||||
|
end
|
||||||
|
end;
|
||||||
this^ := value
|
this^ := value
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -651,6 +661,67 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
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);
|
proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word);
|
||||||
var
|
var
|
||||||
result: Word;
|
result: Word;
|
||||||
@@ -1110,6 +1181,102 @@ begin
|
|||||||
end
|
end
|
||||||
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);
|
proc _node_set_kind(this: Word, kind: Word);
|
||||||
begin
|
begin
|
||||||
this^ := kind
|
this^ := kind
|
||||||
@@ -1477,7 +1644,7 @@ begin
|
|||||||
instruction := _compile_variable_expression(parser_node, symbol_table);
|
instruction := _compile_variable_expression(parser_node, symbol_table);
|
||||||
is_address^ := 1
|
is_address^ := 1
|
||||||
end;
|
end;
|
||||||
_elna_writer_instructions(instruction)
|
return instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _unary_expression_size();
|
proc _unary_expression_size();
|
||||||
@@ -1552,6 +1719,7 @@ var
|
|||||||
operator: Word;
|
operator: Word;
|
||||||
operand: Word;
|
operand: Word;
|
||||||
is_address: Word;
|
is_address: Word;
|
||||||
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
begin
|
begin
|
||||||
operator := 0;
|
operator := 0;
|
||||||
@@ -1567,21 +1735,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if operator = '@' then
|
if operator = '@' then
|
||||||
_compile_designator(operand, symbol_table, @is_address)
|
first_instruction := _compile_designator(operand, symbol_table, @is_address)
|
||||||
else
|
else
|
||||||
_compile_designator(operand, symbol_table, @is_address);
|
first_instruction := _compile_designator(operand, symbol_table, @is_address);
|
||||||
if is_address then
|
if is_address then
|
||||||
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
|
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0, 0);
|
||||||
_elna_writer_instruction(instruction)
|
_elna_generator_instruction_set_next(first_instruction, instruction)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
if operator = '-' then
|
if operator = '-' then
|
||||||
instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
|
instruction := _elna_generator_neg(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
|
||||||
_elna_writer_instruction(instruction)
|
_elna_generator_instruction_set_next(first_instruction, instruction)
|
||||||
elsif operator = '~' then
|
elsif operator = '~' then
|
||||||
instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
|
instruction := _elna_generator_not(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t0);
|
||||||
_elna_writer_instruction(instruction)
|
_elna_generator_instruction_set_next(first_instruction, instruction)
|
||||||
end
|
end;
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _binary_expression_size();
|
proc _binary_expression_size();
|
||||||
@@ -1700,65 +1869,94 @@ var
|
|||||||
operand_node: Word;
|
operand_node: Word;
|
||||||
first_instruction: Word;
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
|
current_instruction: Word;
|
||||||
begin
|
begin
|
||||||
expression_kind := _node_get_kind(parser_node);
|
expression_kind := _node_get_kind(parser_node);
|
||||||
|
|
||||||
if expression_kind <> NodeKind.binary_expression then
|
if expression_kind <> NodeKind.binary_expression then
|
||||||
_compile_unary_expression(parser_node, symbol_table)
|
first_instruction := _compile_unary_expression(parser_node, symbol_table)
|
||||||
else
|
else
|
||||||
token_kind := _binary_expression_get_operator(parser_node);
|
token_kind := _binary_expression_get_operator(parser_node);
|
||||||
|
|
||||||
operand_node := _binary_expression_get_lhs(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. *)
|
(* Save the value of the left expression on the stack. *)
|
||||||
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 64);
|
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);
|
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; *)
|
(* Load the left expression from the stack; *)
|
||||||
instruction := _elna_generator_load_word(ElnaGeneratorRegister.t1, ElnaGeneratorRegister.sp, 64);
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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);
|
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
|
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
|
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
|
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
|
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
|
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);
|
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
|
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);
|
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
|
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);
|
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;
|
end;
|
||||||
_elna_writer_instructions(first_instruction)
|
end;
|
||||||
end
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(* 4 bytes node kind + 4 byte pointer to variable expression + 4 * 7 for arguments. *)
|
(* 4 bytes node kind + 4 byte pointer to variable expression + 4 * 7 for arguments. *)
|
||||||
@@ -1860,19 +2058,25 @@ begin
|
|||||||
if parsed_expression = 0 then
|
if parsed_expression = 0 then
|
||||||
goto compile_call_finalize
|
goto compile_call_finalize
|
||||||
else
|
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. *)
|
(* Save the argument on the stack. *)
|
||||||
stack_offset := argument_count * 4;
|
stack_offset := argument_count * 4;
|
||||||
|
|
||||||
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0,
|
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0,
|
||||||
ElnaGeneratorRegister.sp, 116 - stack_offset);
|
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;
|
argument_count := argument_count + 1;
|
||||||
goto compile_call_loop
|
goto compile_call_loop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
.compile_call_finalize;
|
.compile_call_finalize;
|
||||||
|
|
||||||
(* Load the argument from the stack. *)
|
(* Load the argument from the stack. *)
|
||||||
@@ -1884,11 +2088,7 @@ begin
|
|||||||
(* Calculate the stack offset: 116 - (4 * argument_counter) *)
|
(* Calculate the stack offset: 116 - (4 * argument_counter) *)
|
||||||
instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count,
|
instruction := _elna_generator_load_word(ElnaGeneratorRegister.a0 + argument_count,
|
||||||
ElnaGeneratorRegister.sp, 116 - stack_offset);
|
ElnaGeneratorRegister.sp, 116 - stack_offset);
|
||||||
if first_instruction = 0 then
|
_elna_generator_instruction_set_next(current_instruction, instruction);
|
||||||
first_instruction := instruction
|
|
||||||
else
|
|
||||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
|
||||||
end;
|
|
||||||
current_instruction := instruction;
|
current_instruction := instruction;
|
||||||
|
|
||||||
goto compile_call_finalize
|
goto compile_call_finalize
|
||||||
@@ -1899,7 +2099,7 @@ begin
|
|||||||
else
|
else
|
||||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
_elna_generator_instruction_set_next(current_instruction, instruction)
|
||||||
end;
|
end;
|
||||||
_elna_writer_instructions(first_instruction)
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -2147,22 +2347,22 @@ begin
|
|||||||
name_length := _field_access_expression_get_length(field_access_expression);
|
name_length := _field_access_expression_get_length(field_access_expression);
|
||||||
counter := 1;
|
counter := 1;
|
||||||
|
|
||||||
|
instruction := 0;
|
||||||
.compile_enumeration_value_members;
|
.compile_enumeration_value_members;
|
||||||
if members_length > 0 then
|
if members_length > 0 then
|
||||||
member_name := members^;
|
member_name := members^;
|
||||||
member_length := members + 4;
|
member_length := members + 4;
|
||||||
member_length := member_length^;
|
member_length := member_length^;
|
||||||
|
|
||||||
if _lexer_compare_keyword(value_name, name_length, member_name, member_length) then
|
if _lexer_compare_keyword(value_name, name_length, member_name, member_length) = 0 then
|
||||||
else
|
|
||||||
members_length := members_length - 1;
|
members_length := members_length - 1;
|
||||||
members := members + 8;
|
members := members + 8;
|
||||||
counter := counter + 1;
|
counter := counter + 1;
|
||||||
goto compile_enumeration_value_members
|
goto compile_enumeration_value_members
|
||||||
end;
|
end;
|
||||||
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0);
|
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, counter, 0)
|
||||||
_elna_writer_instructions(instruction)
|
end;
|
||||||
end
|
return instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _parse_field_access_expression(aggregate: Word);
|
proc _parse_field_access_expression(aggregate: Word);
|
||||||
@@ -2199,103 +2399,109 @@ var
|
|||||||
token_kind: Word;
|
token_kind: Word;
|
||||||
parser_node: Word;
|
parser_node: Word;
|
||||||
node_kind: Word;
|
node_kind: Word;
|
||||||
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
begin
|
begin
|
||||||
node_kind := _node_get_kind(parser_node);
|
node_kind := _node_get_kind(parser_node);
|
||||||
|
|
||||||
if node_kind = NodeKind.dereference_expression then
|
if node_kind = NodeKind.dereference_expression then
|
||||||
parser_node := _dereference_expression_get_pointer(parser_node);
|
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);
|
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
|
elsif node_kind = NodeKind.field_access_expression then
|
||||||
_compile_enumeration_value(parser_node);
|
first_instruction := _compile_enumeration_value(parser_node);
|
||||||
is_address^ := 0
|
is_address^ := 0
|
||||||
elsif node_kind = NodeKind.call then
|
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);
|
instruction := _elna_generator_move(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.a0);
|
||||||
_elna_writer_instructions(instruction);
|
_elna_generator_instruction_set_next(first_instruction, instruction);
|
||||||
is_address^ := 0
|
is_address^ := 0
|
||||||
else
|
else
|
||||||
_compile_simple_expression(parser_node, symbol_table, is_address)
|
first_instruction := _compile_simple_expression(parser_node, symbol_table, is_address)
|
||||||
end;
|
end;
|
||||||
return is_address
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _assignment_statement_size();
|
proc _assign_statement_size();
|
||||||
return 16
|
return 16
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _assignment_statement_get_assignee(this: Word);
|
proc _assign_statement_get_assignee(this: Word);
|
||||||
begin
|
begin
|
||||||
this := this + 8;
|
this := this + 8;
|
||||||
return this^
|
return this^
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _assignment_statement_set_assignee(this: Word, value: Word);
|
proc _assign_statement_set_assignee(this: Word, value: Word);
|
||||||
begin
|
begin
|
||||||
this := this + 8;
|
this := this + 8;
|
||||||
this^ := value
|
this^ := value
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _assignment_statement_get_assignment(this: Word);
|
proc _assign_statement_get_assignment(this: Word);
|
||||||
begin
|
begin
|
||||||
this := this + 12;
|
this := this + 12;
|
||||||
return this^
|
return this^
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _assignment_statement_set_assignment(this: Word, value: Word);
|
proc _assign_statement_set_assignment(this: Word, value: Word);
|
||||||
begin
|
begin
|
||||||
this := this + 12;
|
this := this + 12;
|
||||||
this^ := value
|
this^ := value
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _parse_assignment_statement(assignee: Word);
|
proc _parse_assign_statement(assignee: Word);
|
||||||
var
|
var
|
||||||
statement_size: Word;
|
statement_size: Word;
|
||||||
result: Word;
|
result: Word;
|
||||||
token_kind: Word;
|
token_kind: Word;
|
||||||
assignment_node: Word;
|
assignment_node: Word;
|
||||||
begin
|
begin
|
||||||
statement_size := _assignment_statement_size();
|
statement_size := _assign_statement_size();
|
||||||
result := _allocate(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);
|
_statement_set_next(result, 0);
|
||||||
_assignment_statement_set_assignee(result, assignee);
|
_assign_statement_set_assignee(result, assignee);
|
||||||
|
|
||||||
(* Skip the assignment sign (:=) with surrounding whitespaces. *)
|
(* Skip the assignment sign (:=) with surrounding whitespaces. *)
|
||||||
_lexer_read_token(@token_kind);
|
_lexer_read_token(@token_kind);
|
||||||
_lexer_skip_token();
|
_lexer_skip_token();
|
||||||
|
|
||||||
assignment_node := _parse_binary_expression();
|
assignment_node := _parse_binary_expression();
|
||||||
_assignment_statement_set_assignment(result, assignment_node);
|
_assign_statement_set_assignment(result, assignment_node);
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _compile_assignment_statement(parser_tree: Word, symbol_table: Word);
|
proc _compile_assign_statement(parser_tree: Word, symbol_table: Word);
|
||||||
var
|
var
|
||||||
current_expression: Word;
|
current_expression: Word;
|
||||||
is_address: Word;
|
is_address: Word;
|
||||||
first_instruction: Word;
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
|
current_instruction: Word;
|
||||||
begin
|
begin
|
||||||
current_expression := _assignment_statement_get_assignee(parser_tree);
|
current_expression := _assign_statement_get_assignee(parser_tree);
|
||||||
_compile_designator(current_expression, symbol_table, @is_address);
|
first_instruction := _compile_designator(current_expression, symbol_table, @is_address);
|
||||||
|
|
||||||
(* Save the assignee address on the stack. *)
|
(* Save the assignee address on the stack. *)
|
||||||
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60);
|
current_instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.sp, 60);
|
||||||
_elna_writer_instructions(instruction);
|
_elna_generator_instruction_set_next(first_instruction, current_instruction);
|
||||||
|
|
||||||
(* Compile the assignment. *)
|
(* Compile the assignment. *)
|
||||||
current_expression := _assignment_statement_get_assignment(parser_tree);
|
current_expression := _assign_statement_get_assignment(parser_tree);
|
||||||
_compile_binary_expression(current_expression, symbol_table);
|
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);
|
instruction := _elna_generator_store_word(ElnaGeneratorRegister.t0, ElnaGeneratorRegister.t1, 0);
|
||||||
_elna_generator_instruction_set_next(first_instruction, instruction);
|
_elna_generator_instruction_set_next(current_instruction, instruction);
|
||||||
_elna_writer_instructions(first_instruction)
|
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _return_statement_size();
|
proc _return_statement_size();
|
||||||
@@ -2341,12 +2547,14 @@ end;
|
|||||||
proc _compile_return_statement(parser_node: Word, symbol_table: Word);
|
proc _compile_return_statement(parser_node: Word, symbol_table: Word);
|
||||||
var
|
var
|
||||||
return_expression: Word;
|
return_expression: Word;
|
||||||
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
begin
|
begin
|
||||||
return_expression := _return_statement_get_returned(parser_node);
|
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);
|
instruction := _elna_generator_move(ElnaGeneratorRegister.a0, ElnaGeneratorRegister.t0);
|
||||||
_elna_writer_instructions(instruction)
|
_elna_generator_instruction_set_next(first_instruction, instruction);
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -2403,26 +2611,34 @@ var
|
|||||||
condition_label: Word;
|
condition_label: Word;
|
||||||
current_node: Word;
|
current_node: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
|
current_instruction: Word;
|
||||||
|
first_instruction: Word;
|
||||||
begin
|
begin
|
||||||
(* Compile condition. *)
|
(* Compile condition. *)
|
||||||
current_node := _conditional_statements_get_condition(parser_node);
|
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 is the label in front of the next elsif condition or end. *)
|
||||||
condition_label := label_counter;
|
condition_label := label_counter;
|
||||||
label_counter := label_counter + 1;
|
label_counter := label_counter + 1;
|
||||||
|
|
||||||
instruction := _elna_generator_beqz(ElnaGeneratorRegister.t0, condition_label, 0);
|
current_instruction := _elna_generator_beqz(ElnaGeneratorRegister.t0, condition_label, 0);
|
||||||
_elna_writer_instructions(instruction);
|
_elna_generator_instruction_set_next(first_instruction, current_instruction);
|
||||||
|
|
||||||
current_node := _conditional_statements_get_statements(parser_node);
|
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);
|
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);
|
current_instruction := _elna_generator_label(condition_label, 0);
|
||||||
_elna_writer_instructions(instruction)
|
_elna_generator_instruction_set_next(instruction, current_instruction);
|
||||||
|
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -2554,7 +2770,7 @@ begin
|
|||||||
result := _parse_designator();
|
result := _parse_designator();
|
||||||
|
|
||||||
if _node_get_kind(result) <> NodeKind.call then
|
if _node_get_kind(result) <> NodeKind.call then
|
||||||
result := _parse_assignment_statement(result)
|
result := _parse_assign_statement(result)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
return result
|
return result
|
||||||
@@ -2598,15 +2814,29 @@ end;
|
|||||||
proc _compile_statements(parser_node: Word, symbol_table: Word);
|
proc _compile_statements(parser_node: Word, symbol_table: Word);
|
||||||
var
|
var
|
||||||
current_statement: Word;
|
current_statement: Word;
|
||||||
|
instruction: Word;
|
||||||
|
first_instruction: Word;
|
||||||
|
current_instruction: Word;
|
||||||
begin
|
begin
|
||||||
current_statement := parser_node;
|
current_statement := parser_node;
|
||||||
|
first_instruction := 0;
|
||||||
|
|
||||||
.compile_statements_loop;
|
.compile_statements_loop;
|
||||||
if current_statement <> 0 then
|
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);
|
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
|
goto compile_statements_loop
|
||||||
end
|
end;
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _compile_if_statement(parser_node: Word, symbol_table: Word);
|
proc _compile_if_statement(parser_node: Word, symbol_table: Word);
|
||||||
@@ -2614,27 +2844,38 @@ var
|
|||||||
current_node: Word;
|
current_node: Word;
|
||||||
after_end_label: Word;
|
after_end_label: Word;
|
||||||
condition_label: Word;
|
condition_label: Word;
|
||||||
|
first_instruction: Word;
|
||||||
instruction: Word;
|
instruction: Word;
|
||||||
|
current_instruction: Word;
|
||||||
begin
|
begin
|
||||||
after_end_label := label_counter;
|
after_end_label := label_counter;
|
||||||
label_counter := label_counter + 1;
|
label_counter := label_counter + 1;
|
||||||
|
|
||||||
current_node := _if_statement_get_conditionals(parser_node);
|
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;
|
.compile_if_statement_loop;
|
||||||
current_node := _conditional_statements_get_next(current_node);
|
current_node := _conditional_statements_get_next(current_node);
|
||||||
if current_node <> 0 then
|
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
|
goto compile_if_statement_loop
|
||||||
end;
|
end;
|
||||||
current_node := _if_statement_get_else(parser_node);
|
current_node := _if_statement_get_else(parser_node);
|
||||||
|
|
||||||
if current_node <> 0 then
|
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;
|
end;
|
||||||
instruction := _elna_generator_label(after_end_label, 0);
|
instruction := _elna_generator_label(after_end_label, 0);
|
||||||
_elna_writer_instructions(instruction)
|
_elna_generator_instruction_set_next(current_instruction, instruction);
|
||||||
|
|
||||||
|
return first_instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _compile_statement(parser_node: Word, symbol_table: Word);
|
proc _compile_statement(parser_node: Word, symbol_table: Word);
|
||||||
@@ -2645,20 +2886,21 @@ begin
|
|||||||
statement_kind := _node_get_kind(parser_node);
|
statement_kind := _node_get_kind(parser_node);
|
||||||
|
|
||||||
if statement_kind = NodeKind.goto_statement then
|
if statement_kind = NodeKind.goto_statement then
|
||||||
instruction := _compile_goto_statement(parser_node);
|
instruction := _compile_goto_statement(parser_node)
|
||||||
_elna_writer_instructions(instruction)
|
|
||||||
elsif statement_kind = NodeKind.if_statement then
|
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
|
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
|
elsif statement_kind = NodeKind.label_declaration then
|
||||||
instruction := _compile_label_declaration(parser_node);
|
instruction := _compile_label_declaration(parser_node)
|
||||||
_elna_writer_instructions(instruction)
|
|
||||||
elsif statement_kind = NodeKind.call then
|
elsif statement_kind = NodeKind.call then
|
||||||
_compile_call(parser_node, symbol_table)
|
instruction := _compile_call(parser_node, symbol_table)
|
||||||
elsif statement_kind = NodeKind.assignment_statement then
|
elsif statement_kind = NodeKind.assign_statement then
|
||||||
_compile_assignment_statement(parser_node, symbol_table)
|
instruction := _compile_assign_statement(parser_node, symbol_table)
|
||||||
end
|
else
|
||||||
|
instruction := 0
|
||||||
|
end;
|
||||||
|
return instruction
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -3269,23 +3511,24 @@ var
|
|||||||
instruction: Word;
|
instruction: Word;
|
||||||
first_instruction: Word;
|
first_instruction: Word;
|
||||||
current_instruction: Word;
|
current_instruction: Word;
|
||||||
|
result: Word;
|
||||||
|
result_size: Word;
|
||||||
begin
|
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_pointer := _declaration_get_name(parser_node);
|
||||||
name_length := _declaration_get_length(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);
|
symbol_info := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length);
|
||||||
new_symbol_table := _procedure_info_get_symbol_table(symbol_info);
|
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. *)
|
(* Write the prologue. *)
|
||||||
first_instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, -128);
|
first_instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, -128);
|
||||||
current_instruction := _elna_generator_store_word(ElnaGeneratorRegister.ra, ElnaGeneratorRegister.sp, 124);
|
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,
|
instruction := _elna_generator_store_word(ElnaGeneratorRegister.a0 + parameter_counter,
|
||||||
ElnaGeneratorRegister.sp, symbol_info);
|
ElnaGeneratorRegister.sp, symbol_info);
|
||||||
if first_instruction = 0 then
|
_elna_generator_instruction_set_next(current_instruction, instruction);
|
||||||
first_instruction := instruction
|
|
||||||
else
|
|
||||||
_elna_generator_instruction_set_next(current_instruction, instruction)
|
|
||||||
end;
|
|
||||||
current_instruction := instruction;
|
current_instruction := instruction;
|
||||||
|
|
||||||
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
|
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
|
||||||
@@ -3320,19 +3559,28 @@ begin
|
|||||||
current_parameter := _declaration_get_next(current_parameter);
|
current_parameter := _declaration_get_next(current_parameter);
|
||||||
goto compile_procedure_declaration_parameters
|
goto compile_procedure_declaration_parameters
|
||||||
end;
|
end;
|
||||||
_elna_writer_instructions(first_instruction);
|
|
||||||
current_parameter := _procedure_declaration_get_body(parser_node);
|
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. *)
|
(* 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);
|
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);
|
instruction := _elna_generator_add_immediate(ElnaGeneratorRegister.sp, ElnaGeneratorRegister.sp, 128);
|
||||||
_elna_generator_instruction_set_next(current_instruction, instruction);
|
_elna_generator_instruction_set_next(current_instruction, instruction);
|
||||||
current_instruction := _elna_generator_instruction_create(ElnaGeneratorKind.ret);
|
current_instruction := _elna_generator_instruction_create(ElnaGeneratorKind.ret);
|
||||||
_elna_generator_instruction_set_next(instruction, current_instruction);
|
_elna_generator_instruction_set_next(instruction, current_instruction);
|
||||||
_elna_writer_instructions(first_instruction)
|
|
||||||
|
_elna_generator_procedure_set_body(result, first_instruction);
|
||||||
|
|
||||||
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _parse_procedures();
|
proc _parse_procedures();
|
||||||
@@ -3369,16 +3617,28 @@ end;
|
|||||||
proc _compile_procedures(parser_node: Word);
|
proc _compile_procedures(parser_node: Word);
|
||||||
var
|
var
|
||||||
result: Word;
|
result: Word;
|
||||||
|
current_procedure: Word;
|
||||||
|
first_procedure: Word;
|
||||||
begin
|
begin
|
||||||
|
first_procedure := 0;
|
||||||
|
|
||||||
.compile_procedures_loop;
|
.compile_procedures_loop;
|
||||||
if parser_node = 0 then
|
if parser_node = 0 then
|
||||||
goto compile_procedures_end
|
goto compile_procedures_end
|
||||||
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);
|
parser_node := _declaration_get_next(parser_node);
|
||||||
goto compile_procedures_loop;
|
goto compile_procedures_loop;
|
||||||
|
|
||||||
.compile_procedures_end
|
.compile_procedures_end;
|
||||||
|
return first_procedure
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -3551,31 +3811,33 @@ proc _compile_variable_declaration(parser_tree: Word);
|
|||||||
var
|
var
|
||||||
name: Word;
|
name: Word;
|
||||||
name_length: Word;
|
name_length: Word;
|
||||||
token_kind: Word;
|
|
||||||
variable_type: Word;
|
variable_type: Word;
|
||||||
|
result: Word;
|
||||||
|
result_size: Word;
|
||||||
begin
|
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 := _declaration_get_name(parser_tree);
|
||||||
name_length := _declaration_get_length(parser_tree);
|
name_length := _declaration_get_length(parser_tree);
|
||||||
variable_type := _variable_declaration_get_type(parser_tree);
|
variable_type := _variable_declaration_get_type(parser_tree);
|
||||||
|
|
||||||
_write_z(".type \0");
|
_elna_generator_procedure_set_name(result, name);
|
||||||
_write_s(name, name_length);
|
_elna_generator_procedure_set_length(result, name_length);
|
||||||
_write_z(", @object\n\0");
|
|
||||||
|
|
||||||
_write_s(name, name_length);
|
|
||||||
_write_c(':');
|
|
||||||
|
|
||||||
_lexer_read_token(@token_kind);
|
|
||||||
name := _named_type_expression_get_name(variable_type);
|
name := _named_type_expression_get_name(variable_type);
|
||||||
name_length := _named_type_expression_get_length(variable_type);
|
name_length := _named_type_expression_get_length(variable_type);
|
||||||
|
|
||||||
if _lexer_compare_keyword("Array", 5, name, name_length) then
|
if _lexer_compare_keyword("Array", 5, name, name_length) then
|
||||||
(* Else we assume this is a zeroed 4096 bytes big array. *)
|
(* Else we assume this is a zeroed 4096 bytes big array. *)
|
||||||
_write_z(" .zero 4096\0")
|
_elna_generator_procedure_set_body(result, 4096)
|
||||||
else
|
else
|
||||||
_write_z(" .word 0\n\0")
|
_elna_generator_procedure_set_body(result, 4)
|
||||||
end;
|
end;
|
||||||
_write_c('\n')
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _parse_var_part();
|
proc _parse_var_part();
|
||||||
@@ -3619,21 +3881,32 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
proc _compile_var_part(parser_node: Word);
|
proc _compile_var_part(parser_node: Word);
|
||||||
|
var
|
||||||
|
node: Word;
|
||||||
|
current_variable: Word;
|
||||||
|
first_variable: Word;
|
||||||
begin
|
begin
|
||||||
|
first_variable := 0;
|
||||||
if parser_node = 0 then
|
if parser_node = 0 then
|
||||||
goto compile_var_part_end
|
goto compile_var_part_end
|
||||||
end;
|
end;
|
||||||
_write_z(".section .data\n\0");
|
|
||||||
|
|
||||||
.compile_var_part_loop;
|
.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);
|
parser_node := _declaration_get_next(parser_node);
|
||||||
if parser_node <> 0 then
|
if parser_node <> 0 then
|
||||||
goto compile_var_part_loop
|
goto compile_var_part_loop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
.compile_var_part_end
|
.compile_var_part_end;
|
||||||
|
return first_variable
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _module_declaration_size();
|
proc _module_declaration_size();
|
||||||
@@ -3705,39 +3978,24 @@ end;
|
|||||||
proc _compile_module_declaration(parser_node: Word);
|
proc _compile_module_declaration(parser_node: Word);
|
||||||
var
|
var
|
||||||
current_part: Word;
|
current_part: Word;
|
||||||
compiler_strings_copy: Word;
|
result: Word;
|
||||||
compiler_strings_end: Word;
|
result_size: Word;
|
||||||
current_byte: Word;
|
|
||||||
begin
|
begin
|
||||||
_write_z(".globl _start\n\n\0");
|
result_size := _elna_generator_procedure_size();
|
||||||
|
result := _allocate(result_size);
|
||||||
|
|
||||||
|
_elna_generator_procedure_set_kind(result, ElnaGeneratorKind._module);
|
||||||
|
_elna_generator_procedure_set_next(result, 0);
|
||||||
|
|
||||||
current_part := _module_declaration_get_globals(parser_node);
|
current_part := _module_declaration_get_globals(parser_node);
|
||||||
_compile_var_part(current_part);
|
current_part := _compile_var_part(current_part);
|
||||||
|
_elna_generator_procedure_set_name(result, 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 := _module_declaration_get_procedures(parser_node);
|
current_part := _module_declaration_get_procedures(parser_node);
|
||||||
_compile_procedures(current_part);
|
current_part := _compile_procedures(current_part);
|
||||||
|
_elna_generator_procedure_set_body(result, current_part);
|
||||||
|
|
||||||
_write_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0");
|
return result
|
||||||
_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;
|
end;
|
||||||
|
|
||||||
proc _read_procedure_declaration(parser_node: Word);
|
proc _read_procedure_declaration(parser_node: Word);
|
||||||
@@ -3798,10 +4056,12 @@ end;
|
|||||||
proc _compile();
|
proc _compile();
|
||||||
var
|
var
|
||||||
parser_node: Word;
|
parser_node: Word;
|
||||||
|
tac: Word;
|
||||||
begin
|
begin
|
||||||
parser_node := _parse_module_declaration();
|
parser_node := _parse_module_declaration();
|
||||||
_read_module_declaration(parser_node);
|
_read_module_declaration(parser_node);
|
||||||
_compile_module_declaration(parser_node)
|
tac := _compile_module_declaration(parser_node);
|
||||||
|
_elna_writer_module(tac)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
|
|||||||
Reference in New Issue
Block a user