diff --git a/boot/stage15.elna b/boot/stage15.elna index d3e157a..2bfe520 100644 --- a/boot/stage15.elna +++ b/boot/stage15.elna @@ -152,6 +152,42 @@ type ); InfoKind = (type_info, parameter_info, temporary_info, procedure_info); TypeKind = (primitive, enumeration); + ElnaGeneratorKind = (load_immediate); + ElnaGeneratorOperand = (register, immediate); + 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 +540,107 @@ 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_writer_instruction(instruction: Word); +var + immediate_value: Word; + immediate_length: Word; +begin + _write_z("\tli t0, \0"); + + immediate_value := _elna_generator_instruction_get_operand_value(instruction, 2); + immediate_length := _elna_generator_instruction_get_operand_length(instruction, 2); + + _write_s(immediate_value, immediate_length); + _write_c('\n') +end; + proc _node_set_kind(this: Word, kind: Word); begin this^ := kind @@ -564,14 +701,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_instruction(instruction) end; proc _character_literal_node_size(); @@ -628,13 +764,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_instruction(instruction) end; proc _variable_expression_size(); @@ -2385,6 +2521,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 +2540,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 +2745,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 +2766,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 + .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); + + 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; + + current_parameter := _declaration_get_next(current_parameter); + goto compile_procedure_declaration_parameters end; - _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; - - .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); _compile_statements(current_parameter, new_symbol_table); @@ -2821,20 +2958,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 +3199,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();