summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2025-10-27 12:13:27 +0100
committerEugen Wissner <belka@caraus.de>2025-10-27 22:30:28 +0100
commit788cb4253f0bb98029cec78ada98bfc9dd9148a4 (patch)
tree7a2d5ec90457437c28c459cfc704da3c488ce6f5
parent37a698da91e53f54ee55484e98bb6dfa1d12b9c6 (diff)
downloadelna-788cb4253f0bb98029cec78ada98bfc9dd9148a4.tar.gz
Add code generator procedures and enumerations
-rw-r--r--boot/stage15.elna349
1 files changed, 298 insertions, 51 deletions
diff --git a/boot/stage15.elna b/boot/stage15.elna
index d3e157a..e88c803 100644
--- a/boot/stage15.elna
+++ b/boot/stage15.elna
@@ -152,6 +152,46 @@ type
);
InfoKind = (type_info, parameter_info, temporary_info, procedure_info);
TypeKind = (primitive, enumeration);
+ ElnaGeneratorKind = (
+ load_immediate,
+ load_address,
+ add
+ );
+ ElnaGeneratorOperand = (register, immediate, symbol);
+ ElnaGeneratorRegister = (
+ zero,
+ ra,
+ sp,
+ gp,
+ tp,
+ t0,
+ t1,
+ t2,
+ s0,
+ s1,
+ a0,
+ a1,
+ a2,
+ a3,
+ a4,
+ a5,
+ a6,
+ a7,
+ s2,
+ s3,
+ s4,
+ s5,
+ s6,
+ s7,
+ s8,
+ s9,
+ s10,
+ s11,
+ t3,
+ t4,
+ t5,
+ t6
+ );
var
symbol_table_global: Array;
@@ -504,6 +544,178 @@ proc _node_get_kind(this: Word);
return this^
end;
+proc _elna_generator_instruction_size();
+ return 44
+end;
+
+proc _elna_generator_instruction_get_kind(this: Word);
+ return this^
+end;
+
+proc _elna_generator_instruction_set_kind(this: Word, value: Word);
+begin
+ this^ := value
+end;
+
+proc _elna_generator_instruction_get_next(this: Word);
+begin
+ this := this + 4;
+ return this^
+end;
+
+proc _elna_generator_instruction_set_next(this: Word, value: Word);
+begin
+ this := this + 4;
+ this^ := value
+end;
+
+proc _elna_generator_instruction_get_operand_type(this: Word, n: Word);
+begin
+ n := n - 1;
+ n := n * 12;
+ this := this + 8;
+ this := this + n;
+
+ return this^
+end;
+
+proc _elna_generator_instruction_get_operand_value(this: Word, n: Word);
+begin
+ n := n - 1;
+ n := n * 12;
+ this := this + 8;
+ this := this + n;
+
+ this := this + 4;
+ return this^
+end;
+
+proc _elna_generator_instruction_get_operand_length(this: Word, n: Word);
+begin
+ n := n - 1;
+ n := n * 12;
+ this := this + 8;
+ this := this + n;
+
+ this := this + 8;
+ return this^
+end;
+
+proc _elna_generator_instruction_set_operand(this: Word, n: Word, operand_type: Word, operand_value: Word, operand_length: Word);
+begin
+ n := n - 1;
+ n := n * 12;
+ this := this + 8;
+ this := this + n;
+
+ this^ := operand_type;
+ this := this + 4;
+ this^ := operand_value;
+ this := this + 4;
+ this^ := operand_length
+end;
+
+proc _elna_generator_load_immediate(target_register: Word, source_immediate: Word, immediate_length: Word);
+var
+ result: Word;
+ instruction_size: Word;
+begin
+ instruction_size := _elna_generator_instruction_size();
+ result := _allocate(instruction_size);
+
+ _elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_immediate);
+ _elna_generator_instruction_set_next(result, 0);
+ _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0);
+ _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.immediate, source_immediate, immediate_length);
+
+ return result
+end;
+
+proc _elna_generator_load_address(target_register: Word, source_symbol: Word, symbol_length: Word);
+var
+ result: Word;
+ instruction_size: Word;
+begin
+ instruction_size := _elna_generator_instruction_size();
+ result := _allocate(instruction_size);
+
+ _elna_generator_instruction_set_kind(result, ElnaGeneratorKind.load_address);
+ _elna_generator_instruction_set_next(result, 0);
+ _elna_generator_instruction_set_operand(result, 1, ElnaGeneratorOperand.register, target_register, 0);
+ _elna_generator_instruction_set_operand(result, 2, ElnaGeneratorOperand.symbol, source_symbol, symbol_length);
+
+ return result
+end;
+
+proc _elna_writer_instruction_name(instruction_kind: Word);
+var
+ argument_count: Word;
+begin
+ if instruction_kind = ElnaGeneratorKind.load_immediate then
+ argument_count := 2;
+ _write_s("\tli", 3)
+ elsif instruction_kind = ElnaGeneratorKind.load_address then
+ argument_count := 2;
+ _write_s("\tla", 3)
+ elsif instruction_kind = ElnaGeneratorKind.add then
+ argument_count := 3;
+ _write_s("\tadd", 4)
+ end;
+ return argument_count
+end;
+
+proc _elna_writer_register(register: Word);
+var
+ number: Word;
+begin
+ _write_c('x');
+ number := register - 1;
+ _write_i(number)
+end;
+
+proc _elna_writer_operand(instruction: Word, n: Word);
+var
+ operand_value: Word;
+ operand_length: Word;
+ operand_type: Word;
+begin
+ operand_type := _elna_generator_instruction_get_operand_type(instruction, n);
+ operand_value := _elna_generator_instruction_get_operand_value(instruction, n);
+ operand_length := _elna_generator_instruction_get_operand_length(instruction, n);
+
+ _write_c(' ');
+ if operand_type = ElnaGeneratorOperand.register then
+ _elna_writer_register(operand_value)
+ elsif operand_length = 0 then
+ _write_i(operand_value)
+ else
+ _write_s(operand_value, operand_length)
+ end
+end;
+
+proc _elna_writer_instruction(instruction: Word);
+var
+ instruction_kind: Word;
+begin
+ instruction_kind := _elna_generator_instruction_get_kind(instruction);
+ _elna_writer_instruction_name(instruction_kind);
+
+ _elna_writer_operand(instruction, 1);
+ _write_c(',');
+ _elna_writer_operand(instruction, 2);
+
+ _write_c('\n')
+end;
+
+proc _elna_writer_instructions(instruction: Word);
+begin
+ if instruction <> 0 then
+ _elna_writer_instruction(instruction);
+ instruction := _elna_generator_instruction_get_next(instruction);
+ _elna_writer_instructions(instruction)
+ end
+end;
+
proc _node_set_kind(this: Word, kind: Word);
begin
this^ := kind
@@ -564,14 +776,13 @@ var
integer_token: Word;
integer_length: Word;
token_kind: Word;
+ instruction: Word;
begin
- _write_z("\tli t0, \0");
-
integer_token := _integer_literal_node_get_value(integer_literal_node);
integer_length := _integer_literal_node_get_length(integer_literal_node);
- _write_s(integer_token, integer_length);
- _write_c('\n')
+ instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length);
+ _elna_writer_instructions(instruction)
end;
proc _character_literal_node_size();
@@ -628,13 +839,13 @@ proc _compile_character_literal(character_literal_node: Word);
var
character: Word;
character_length: Word;
+ instruction: Word;
begin
character := _character_literal_node_get_value(character_literal_node);
character_length := _character_literal_node_get_length(character_literal_node);
- _write_z("\tli t0, \0");
- _write_s(character, character_length);
- _write_c('\n')
+ instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length);
+ _elna_writer_instructions(instruction)
end;
proc _variable_expression_size();
@@ -767,16 +978,18 @@ var
token_start: Word;
length: Word;
offset: Word;
+ instruction: Word;
+ first_instruction: Word;
begin
token_start := _string_literal_node_get_value(string_literal_node);
length := _string_literal_node_get_length(string_literal_node);
offset := _add_string(token_start);
- _write_z("\tla t0, strings\n\0");
+ first_instruction := _elna_generator_load_address(ElnaGeneratorRegister.t0, "strings", 7);
+ instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t1, offset, 0);
+ _elna_generator_instruction_set_next(first_instruction, instruction);
- _write_z("\tli t1, \0");
- _write_i(offset);
- _write_c('\n');
+ _elna_writer_instructions(first_instruction);
_write_z("\tadd t0, t0, t1\n\0")
end;
@@ -2385,6 +2598,12 @@ begin
return result
end;
+proc _procedure_info_get_symbol_table(this: Word);
+begin
+ this := this + 4;
+ return this^
+end;
+
(**
* Parameters:
* parameter_index - Parameter index.
@@ -2398,17 +2617,8 @@ begin
name_position := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node);
- _write_z("\tsw a\0");
- _write_i(parameter_index);
- _write_z(", \0");
-
info := _parameter_info_create(parameter_index);
- _symbol_table_enter(symbol_table, name_position, name_length, info);
-
- info := _parameter_info_get_offset(info);
- _write_i(info);
-
- _write_z("(sp)\n\0")
+ _symbol_table_enter(symbol_table, name_position, name_length, info)
end;
(**
@@ -2612,12 +2822,12 @@ var
new_symbol_table: Word;
symbol_info: Word;
begin
- new_symbol_table := _symbol_table_create();
- symbol_info := _procedure_info_create(new_symbol_table);
-
name_pointer := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node);
+ 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");
@@ -2633,23 +2843,27 @@ begin
current_parameter := _procedure_declaration_get_parameters(parser_node);
parameter_counter := 0;
- .compile_procedure_declaration_parameter;
- if current_parameter = 0 then
- goto compile_procedure_declaration_end
- end;
- _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table);
- parameter_counter := parameter_counter + 1;
+ .compile_procedure_declaration_parameters;
+ if current_parameter <> 0 then
+ name_pointer := _declaration_get_name(current_parameter);
+ name_length := _declaration_get_length(current_parameter);
+ symbol_info := _symbol_table_lookup(new_symbol_table, name_pointer, name_length);
- current_parameter := _declaration_get_next(current_parameter);
- goto compile_procedure_declaration_parameter;
+ symbol_info := _parameter_info_get_offset(symbol_info);
- .compile_procedure_declaration_end;
+ _write_z("\tsw a\0");
+ _write_i(parameter_counter);
+ _write_z(", \0");
+ _write_i(symbol_info);
- current_parameter := _procedure_declaration_get_temporaries(parser_node);
- _read_procedure_temporaries(current_parameter, new_symbol_table);
+ _write_z("(sp)\n\0");
- _symbol_table_enter(@symbol_table_global, name_pointer, name_length, symbol_info);
+ (* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
+ parameter_counter := parameter_counter + 1;
+ current_parameter := _declaration_get_next(current_parameter);
+ goto compile_procedure_declaration_parameters
+ end;
current_parameter := _procedure_declaration_get_body(parser_node);
_compile_statements(current_parameter, new_symbol_table);
@@ -2821,20 +3035,6 @@ begin
return result
end;
-proc _read_type_part(parser_node: Word);
-begin
- .read_type_part_loop;
- if parser_node = 0 then
- goto read_type_part_end
- end;
-
- _read_type_declaration(parser_node);
- parser_node := _declaration_get_next(parser_node);
-
- goto read_type_part_loop;
- .read_type_part_end
-end;
-
proc _variable_declaration_size();
return 20
end;
@@ -3076,12 +3276,59 @@ begin
_write_c('\n')
end;
+proc _read_procedure_declaration(parser_node: Word);
+var
+ name_pointer: Word;
+ name_length: Word;
+ new_symbol_table: Word;
+ parameter_counter: Word;
+ symbol_info: Word;
+ current_parameter: Word;
+begin
+ new_symbol_table := _symbol_table_create();
+ symbol_info := _procedure_info_create(new_symbol_table);
+
+ name_pointer := _declaration_get_name(parser_node);
+ name_length := _declaration_get_length(parser_node);
+
+ current_parameter := _procedure_declaration_get_parameters(parser_node);
+ parameter_counter := 0;
+ .compile_procedure_declaration_parameter;
+ if current_parameter <> 0 then
+ _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table);
+ parameter_counter := parameter_counter + 1;
+
+ current_parameter := _declaration_get_next(current_parameter);
+ goto compile_procedure_declaration_parameter
+ end;
+ current_parameter := _procedure_declaration_get_temporaries(parser_node);
+ _read_procedure_temporaries(current_parameter, new_symbol_table);
+
+ _symbol_table_enter(@symbol_table_global, name_pointer, name_length, symbol_info)
+end;
+
proc _read_module_declaration(parser_node: Word);
var
current_part: Word;
+ result: Word;
begin
current_part := _module_declaration_get_types(parser_node);
- _read_type_part(current_part)
+ .read_module_declaration_type;
+ if current_part <> 0 then
+ _read_type_declaration(current_part);
+ current_part := _declaration_get_next(current_part);
+
+ goto read_module_declaration_type
+ end;
+
+ current_part := _module_declaration_get_procedures(parser_node);
+ .read_module_declaration_procedure;
+ if current_part <> 0 then
+ _read_procedure_declaration(current_part);
+ current_part := _declaration_get_next(current_part);
+
+ goto read_module_declaration_procedure
+ end
end;
proc _compile();