Add code generator procedures and enumerations
This commit is contained in:
@@ -152,6 +152,46 @@ type
|
|||||||
);
|
);
|
||||||
InfoKind = (type_info, parameter_info, temporary_info, procedure_info);
|
InfoKind = (type_info, parameter_info, temporary_info, procedure_info);
|
||||||
TypeKind = (primitive, enumeration);
|
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
|
var
|
||||||
symbol_table_global: Array;
|
symbol_table_global: Array;
|
||||||
@@ -504,6 +544,178 @@ proc _node_get_kind(this: Word);
|
|||||||
return this^
|
return this^
|
||||||
end;
|
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);
|
proc _node_set_kind(this: Word, kind: Word);
|
||||||
begin
|
begin
|
||||||
this^ := kind
|
this^ := kind
|
||||||
@@ -564,14 +776,13 @@ var
|
|||||||
integer_token: Word;
|
integer_token: Word;
|
||||||
integer_length: Word;
|
integer_length: Word;
|
||||||
token_kind: Word;
|
token_kind: Word;
|
||||||
|
instruction: Word;
|
||||||
begin
|
begin
|
||||||
_write_z("\tli t0, \0");
|
|
||||||
|
|
||||||
integer_token := _integer_literal_node_get_value(integer_literal_node);
|
integer_token := _integer_literal_node_get_value(integer_literal_node);
|
||||||
integer_length := _integer_literal_node_get_length(integer_literal_node);
|
integer_length := _integer_literal_node_get_length(integer_literal_node);
|
||||||
|
|
||||||
_write_s(integer_token, integer_length);
|
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, integer_token, integer_length);
|
||||||
_write_c('\n')
|
_elna_writer_instructions(instruction)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _character_literal_node_size();
|
proc _character_literal_node_size();
|
||||||
@@ -628,13 +839,13 @@ proc _compile_character_literal(character_literal_node: Word);
|
|||||||
var
|
var
|
||||||
character: Word;
|
character: Word;
|
||||||
character_length: Word;
|
character_length: Word;
|
||||||
|
instruction: Word;
|
||||||
begin
|
begin
|
||||||
character := _character_literal_node_get_value(character_literal_node);
|
character := _character_literal_node_get_value(character_literal_node);
|
||||||
character_length := _character_literal_node_get_length(character_literal_node);
|
character_length := _character_literal_node_get_length(character_literal_node);
|
||||||
|
|
||||||
_write_z("\tli t0, \0");
|
instruction := _elna_generator_load_immediate(ElnaGeneratorRegister.t0, character, character_length);
|
||||||
_write_s(character, character_length);
|
_elna_writer_instructions(instruction)
|
||||||
_write_c('\n')
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _variable_expression_size();
|
proc _variable_expression_size();
|
||||||
@@ -767,16 +978,18 @@ var
|
|||||||
token_start: Word;
|
token_start: Word;
|
||||||
length: Word;
|
length: Word;
|
||||||
offset: Word;
|
offset: Word;
|
||||||
|
instruction: Word;
|
||||||
|
first_instruction: Word;
|
||||||
begin
|
begin
|
||||||
token_start := _string_literal_node_get_value(string_literal_node);
|
token_start := _string_literal_node_get_value(string_literal_node);
|
||||||
length := _string_literal_node_get_length(string_literal_node);
|
length := _string_literal_node_get_length(string_literal_node);
|
||||||
offset := _add_string(token_start);
|
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");
|
_elna_writer_instructions(first_instruction);
|
||||||
_write_i(offset);
|
|
||||||
_write_c('\n');
|
|
||||||
|
|
||||||
_write_z("\tadd t0, t0, t1\n\0")
|
_write_z("\tadd t0, t0, t1\n\0")
|
||||||
end;
|
end;
|
||||||
@@ -2385,6 +2598,12 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
proc _procedure_info_get_symbol_table(this: Word);
|
||||||
|
begin
|
||||||
|
this := this + 4;
|
||||||
|
return this^
|
||||||
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* parameter_index - Parameter index.
|
* parameter_index - Parameter index.
|
||||||
@@ -2398,17 +2617,8 @@ begin
|
|||||||
name_position := _declaration_get_name(parser_node);
|
name_position := _declaration_get_name(parser_node);
|
||||||
name_length := _declaration_get_length(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);
|
info := _parameter_info_create(parameter_index);
|
||||||
_symbol_table_enter(symbol_table, name_position, name_length, info);
|
_symbol_table_enter(symbol_table, name_position, name_length, info)
|
||||||
|
|
||||||
info := _parameter_info_get_offset(info);
|
|
||||||
_write_i(info);
|
|
||||||
|
|
||||||
_write_z("(sp)\n\0")
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(**
|
(**
|
||||||
@@ -2612,12 +2822,12 @@ var
|
|||||||
new_symbol_table: Word;
|
new_symbol_table: Word;
|
||||||
symbol_info: Word;
|
symbol_info: Word;
|
||||||
begin
|
begin
|
||||||
new_symbol_table := _symbol_table_create();
|
|
||||||
symbol_info := _procedure_info_create(new_symbol_table);
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
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 .type _procedure_name, @function. *)
|
||||||
_write_z(".type \0");
|
_write_z(".type \0");
|
||||||
|
|
||||||
@@ -2633,23 +2843,27 @@ begin
|
|||||||
|
|
||||||
current_parameter := _procedure_declaration_get_parameters(parser_node);
|
current_parameter := _procedure_declaration_get_parameters(parser_node);
|
||||||
parameter_counter := 0;
|
parameter_counter := 0;
|
||||||
.compile_procedure_declaration_parameter;
|
.compile_procedure_declaration_parameters;
|
||||||
if current_parameter = 0 then
|
if current_parameter <> 0 then
|
||||||
goto compile_procedure_declaration_end
|
name_pointer := _declaration_get_name(current_parameter);
|
||||||
end;
|
name_length := _declaration_get_length(current_parameter);
|
||||||
_read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table);
|
symbol_info := _symbol_table_lookup(new_symbol_table, name_pointer, name_length);
|
||||||
|
|
||||||
|
symbol_info := _parameter_info_get_offset(symbol_info);
|
||||||
|
|
||||||
|
_write_z("\tsw a\0");
|
||||||
|
_write_i(parameter_counter);
|
||||||
|
_write_z(", \0");
|
||||||
|
_write_i(symbol_info);
|
||||||
|
|
||||||
|
_write_z("(sp)\n\0");
|
||||||
|
|
||||||
|
(* _read_procedure_parameter(current_parameter, parameter_counter, new_symbol_table); *)
|
||||||
parameter_counter := parameter_counter + 1;
|
parameter_counter := parameter_counter + 1;
|
||||||
|
|
||||||
current_parameter := _declaration_get_next(current_parameter);
|
current_parameter := _declaration_get_next(current_parameter);
|
||||||
goto compile_procedure_declaration_parameter;
|
goto compile_procedure_declaration_parameters
|
||||||
|
end;
|
||||||
.compile_procedure_declaration_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);
|
|
||||||
|
|
||||||
current_parameter := _procedure_declaration_get_body(parser_node);
|
current_parameter := _procedure_declaration_get_body(parser_node);
|
||||||
_compile_statements(current_parameter, new_symbol_table);
|
_compile_statements(current_parameter, new_symbol_table);
|
||||||
|
|
||||||
@@ -2821,20 +3035,6 @@ begin
|
|||||||
return result
|
return result
|
||||||
end;
|
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();
|
proc _variable_declaration_size();
|
||||||
return 20
|
return 20
|
||||||
end;
|
end;
|
||||||
@@ -3076,12 +3276,59 @@ begin
|
|||||||
_write_c('\n')
|
_write_c('\n')
|
||||||
end;
|
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);
|
proc _read_module_declaration(parser_node: Word);
|
||||||
var
|
var
|
||||||
current_part: Word;
|
current_part: Word;
|
||||||
|
result: Word;
|
||||||
begin
|
begin
|
||||||
current_part := _module_declaration_get_types(parser_node);
|
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;
|
end;
|
||||||
|
|
||||||
proc _compile();
|
proc _compile();
|
||||||
|
|||||||
Reference in New Issue
Block a user