From 305032b53476267083457b706ce25bf81afcf0c5 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 9 Dec 2025 17:16:31 +0100 Subject: [PATCH] Assign stack offset to local variables in a later pass --- boot/stage17/cl.elna | 842 ++++++++++++++++++++++++------------------- 1 file changed, 469 insertions(+), 373 deletions(-) diff --git a/boot/stage17/cl.elna b/boot/stage17/cl.elna index e10be76..6483c85 100644 --- a/boot/stage17/cl.elna +++ b/boot/stage17/cl.elna @@ -8,6 +8,7 @@ program; (* Stage 17 compiler. *) (* - true and false boolean literals. *) +(* - the number of local variables is not limited. *) type (** @@ -231,28 +232,36 @@ type base: Word; length: Word end; - _info = record + ElnaSymbolInfo = record kind: Word end; - _type_info = record + ElnaSymbolTypeInfo = record kind: Word; _type: Word end; - _parameter_info = record + ElnaSymbolParameterInfo = record kind: Word; offset: Word; variable_type: Word end; - _temporary_info = record + ElnaSymbolTemporaryInfo = record kind: Word; offset: Word; variable_type: Word end; - _procedure_info = record + ElnaSymbolProcedureInfo = record kind: Word; symbol_table: Word end; + ElnaErrorList = record + first: Word; + last: Word + end; + ElnaError = record + next: Word + end; + ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited); (** @@ -399,7 +408,7 @@ type array_type_expression, null ); - InfoKind = (type_info, parameter_info, temporary_info, procedure_info); + ElnaSymbolInfoKind = (type_info, parameter_info, temporary_info, procedure_info); ElnaTypeKind = (primitive, enumeration, _record, pointer, array); ElnaTacOperator = ( get_address, @@ -458,8 +467,8 @@ type allocate_stack, ret ); - ElnaTacOperand = (temporary, immediate, symbol, stack); - ElnaRtlOperand = (register, immediate, symbol, offset); + ElnaTacOperand = (temporary, immediate, symbol, stack, pseudo); + ElnaRtlOperand = (register, immediate, symbol, offset, pseudo); ElnaRtlRegister = ( zero, ra, @@ -499,6 +508,7 @@ var symbol_table_global: Array; compiler_strings: Array; classification: Array; + variable_map: Array; source_code: Word; compiler_strings_position: Word; @@ -518,22 +528,22 @@ var *) proc _string_length(string: Word); var - counter: Word; - current_byte: Word; + counter1: Word; + current_byte1: Word; begin (* Reset the counter. *) - counter := 0; + counter1 := 0; .string_length_loop; string := string + 1; - current_byte := _load_byte(string); - if current_byte <> '"' then - counter := counter + 1; + current_byte1 := _load_byte(string); + if current_byte1 <> '"' then + counter1 := counter1 + 1; goto string_length_loop end; - return counter + return counter1 end; (** @@ -546,40 +556,27 @@ end; *) proc _add_string(string: Word); var - contents: Word; - result: Word; - current_byte: Word; + contents1: Word; + result1: Word; + current_byte1: Word; begin - contents := string + 1; - result := compiler_strings_length; + contents1 := string + 1; + result1 := compiler_strings_length; .add_string_loop; - current_byte := _load_byte(contents); - if current_byte <> '"' then - _store_byte(current_byte, compiler_strings_position); + current_byte1 := _load_byte(contents1); + if current_byte1 <> '"' then + _store_byte(current_byte1, compiler_strings_position); compiler_strings_position := compiler_strings_position + 1; - contents := contents + 1; + contents1 := contents1 + 1; - if current_byte <> '\\' then + if current_byte1 <> '\\' then compiler_strings_length := compiler_strings_length + 1 end; goto add_string_loop end; - return result -end; - -(** - * Reads standard input into a buffer. - * - * Parameters: - * buffer - Buffer pointer. - * size - Buffer size. - * - * Returns the amount of bytes written in a0. - *) -proc _read_file(buffer: Word, size: Word); - return _syscall(0, buffer, size, 0, 0, 0, 63) + return result1 end; (** @@ -591,53 +588,7 @@ end; *) proc _write_s(buffer: Word, size: Word); begin - _syscall(1, buffer, size, 0, 0, 0, 64) -end; - -(** - * Writes a number to a string buffer. - * - * Parameters: - * number - Whole number. - * output_buffer - Buffer pointer. - * - * Sets a0 to the length of the written number. - *) -proc _print_i(number: Word, output_buffer: Word); -var - local_buffer: Word; - is_negative: Word; - current_character: Word; - result: Word; -begin - local_buffer := @result + 11; - - if number >= 0 then - is_negative := 0 - else - number = -number; - is_negative := 1 - end; - - .print_i_digit10; - current_character := number % 10; - _store_byte(current_character + '0', local_buffer); - - number := number / 10; - local_buffer := local_buffer - 1; - - if number <> 0 then - goto print_i_digit10 - end; - if is_negative = 1 then - _store_byte('-', local_buffer); - local_buffer := local_buffer - 1 - end; - result := @result + 11; - result := result - local_buffer; - memcpy(output_buffer, local_buffer + 1, result); - - return result + write(1, buffer, size) end; (** @@ -647,12 +598,9 @@ end; * number - Whole number. *) proc _write_i(number: Word); -var - local_buffer: Word; - length: Word; begin - length := _print_i(number, @local_buffer); - _write_s(@local_buffer, length) + printf("%i\0", number); + fflush(nil) end; (** @@ -663,7 +611,7 @@ end; *) proc _write_c(character: Word); begin - _write_s(@character, 1) + write(1, @character, 1) end; (** @@ -673,19 +621,9 @@ end; * string - String. *) proc _write_z(string: Word); -var - next_byte: Word; begin - (* Check for 0 character. *) - next_byte := _load_byte(string); - - if next_byte <> 0 then - (* Print a character. *) - _write_c(next_byte); - - (* Advance the input string by one byte. *) - _write_z(string + 1) - end + printf("%s\0", string); + fflush(nil) end; (** @@ -698,11 +636,11 @@ end; *) proc _is_alpha(character: Word); var - is_underscore: Word; + is_underscore1: Word; begin - is_underscore := character = '_'; + is_underscore1 := character = '_'; - return isalpha(character) or is_underscore + return isalpha(character) or is_underscore1 end; proc _is_alnum(character: Word); @@ -727,13 +665,13 @@ end; proc elna_instruction_list_concatenate(this: Word, value: Word); var - start: Word; + start1: Word; begin if this = 0 then - start := value; + start1 := value; goto elna_instruction_list_concatenate_end else - start := this + start1 := this end; .elna_instruction_list_concatenate_loop; if value <> 0 then @@ -744,7 +682,7 @@ begin end; this^ := value; .elna_instruction_list_concatenate_end; - return start + return start1 end; proc _elna_tac_instruction_get_operand_type(this: Word, n: Word); @@ -795,26 +733,26 @@ end; proc _elna_tac_instruction_create(kind: Word); var - result: Word; + result1: Word; begin - result := malloc(_elna_tac_instruction_size()); + result1 := malloc(_elna_tac_instruction_size()); - _elna_tac_instruction_set_kind(result, kind); - elna_instruction_list_concatenate(result, 0); + _elna_tac_instruction_set_kind(result1, kind); + elna_instruction_list_concatenate(result1, 0); - return result + return result1 end; proc elna_rtl_instruction_create(kind: Word); var - result: ^ElnaInstructionList; + result1: ^ElnaInstructionList; begin - result := malloc(elna_rtl_instruction_size()); + result1 := malloc(elna_rtl_instruction_size()); - elna_rtl_instruction_set_kind(result, kind); - result^.next := nil; + elna_rtl_instruction_set_kind(result1, kind); + result1^.next := nil; - return result + return result1 end; proc elna_rtl_instruction_size(); @@ -881,41 +819,45 @@ end; proc elna_rtl_load_operand_value(tac_instruction: Word, operand_number: Word, into: Word); var - result: ^ElnaInstructionList; - operand_value: Word; - operand_length: Word; - operand_type: Word; + result1: ^ElnaInstructionList; + operand_value1: Word; + operand_length1: Word; + operand_type1: Word; next_instruction: Word; begin - operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, operand_number); - operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, operand_number); - operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, operand_number); + operand_value1 := _elna_tac_instruction_get_operand_value(tac_instruction, operand_number); + operand_length1 := _elna_tac_instruction_get_operand_length(tac_instruction, operand_number); + operand_type1 := _elna_tac_instruction_get_operand_type(tac_instruction, operand_number); - if operand_type = ElnaTacOperand.immediate then - result := elna_rtl_instruction_create(ElnaRtlOperator.li); - elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); - elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.immediate, operand_value, operand_length) - elsif operand_type = ElnaTacOperand.stack then - result := elna_rtl_instruction_create(ElnaRtlOperator.lw); - elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); - elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value) - elsif operand_type = ElnaTacOperand.symbol then - result := elna_rtl_instruction_create(ElnaRtlOperator.la); - elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); - elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.symbol, operand_value, operand_length); + if operand_type1 = ElnaTacOperand.immediate then + result1 := elna_rtl_instruction_create(ElnaRtlOperator.li); + elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.immediate, operand_value1, operand_length1) + elsif operand_type1 = ElnaTacOperand.stack then + result1 := elna_rtl_instruction_create(ElnaRtlOperator.lw); + elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value1) + elsif operand_type1 = ElnaTacOperand.symbol then + result1 := elna_rtl_instruction_create(ElnaRtlOperator.la); + elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.symbol, operand_value1, operand_length1); next_instruction := elna_rtl_instruction_create(ElnaRtlOperator.lw); elna_rtl_instruction_set_operand(next_instruction, 1, ElnaRtlOperand.register, into, 0); elna_rtl_instruction_set_operand(next_instruction, 2, ElnaRtlOperand.offset, into, 0); - result^.next := next_instruction - elsif operand_type = ElnaTacOperand.temporary then - result := elna_rtl_instruction_create(ElnaRtlOperator.move); - elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); - elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.register, operand_value, 0) + result1^.next := next_instruction + elsif operand_type1 = ElnaTacOperand.temporary then + result1 := elna_rtl_instruction_create(ElnaRtlOperator.move); + elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.register, operand_value1, 0) + elsif operand_type1 = ElnaTacOperand.pseudo then + result1 := elna_rtl_instruction_create(ElnaRtlOperator.move); + elna_rtl_instruction_set_operand(result1, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result1, 2, ElnaRtlOperand.pseudo, operand_value1, operand_length1) end; - return result + return result1 end; proc elna_rtl_load_operand_address(tac_instruction: Word, operand_number: Word, into: Word); @@ -937,6 +879,10 @@ begin result := elna_rtl_instruction_create(ElnaRtlOperator.la); elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.symbol, operand_value, operand_length) + elsif operand_type = ElnaTacOperand.pseudo then + result := elna_rtl_instruction_create(ElnaRtlOperator.la); + elna_rtl_instruction_set_operand(result, 1, ElnaRtlOperand.register, into, 0); + elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.pseudo, operand_value, operand_length) end; return result @@ -1053,23 +999,23 @@ end; proc elna_rtl_instruction(tac_instruction: Word, next_instruction: ^^ElnaInstructionList); var result: ^ElnaInstructionList; - instruction_size: Word; instruction_kind: Word; operand_type: Word; operand_value: Word; + operand_length: Word; operands: ^ElnaInstructionList; intermediate_instruction: ^ElnaInstructionList; begin - instruction_size := elna_rtl_instruction_size(); - result := malloc(instruction_size); + result := malloc(elna_rtl_instruction_size()); instruction_kind := _elna_tac_instruction_get_kind(tac_instruction); next_instruction^ := nil; if instruction_kind = ElnaTacOperator.get_address then operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2); + operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); + operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2); if operand_type = ElnaTacOperand.stack then - operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); result := elna_rtl_instruction_create(ElnaRtlOperator.add); elna_rtl_copy_operand(tac_instruction, 1, result); @@ -1085,6 +1031,11 @@ begin elna_rtl_copy_operand(tac_instruction, 1, result); elna_rtl_copy_operand(tac_instruction, 2, result) + elsif operand_type = ElnaTacOperand.pseudo then + result := elna_rtl_instruction_create(ElnaRtlOperator.la); + + elna_rtl_copy_operand(tac_instruction, 1, result); + elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.pseudo, operand_value, operand_length) end elsif instruction_kind = ElnaTacOperator.add then result := elna_rtl_binary_arithmetic(tac_instruction, next_instruction, ElnaRtlOperator.add) @@ -1108,6 +1059,13 @@ begin elna_rtl_copy_operand(tac_instruction, 1, result); operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.offset, operand_value, 0) + elsif operand_type = ElnaTacOperand.pseudo then + operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); + operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2); + + result := elna_rtl_instruction_create(ElnaRtlOperator.lw); + elna_rtl_copy_operand(tac_instruction, 1, result); + elna_rtl_instruction_set_operand(result, 2, ElnaRtlOperand.pseudo, operand_value, operand_length) end elsif instruction_kind = ElnaTacOperator.store then operands := elna_rtl_load_operand_value(tac_instruction, 1, ElnaRtlRegister.t0); @@ -1118,12 +1076,14 @@ begin elna_rtl_instruction_set_operand(next_instruction^, 1, ElnaRtlOperand.register, ElnaRtlRegister.t0, 0); operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 2); + operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); + operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 2); if operand_type = ElnaTacOperand.stack then - operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value) elsif operand_type = ElnaTacOperand.temporary then - operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 2); elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, operand_value, 0) + elsif operand_type = ElnaTacOperand.pseudo then + elna_rtl_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.pseudo, operand_value, operand_length) end; if operands = 0 then result^.next := next_instruction^ @@ -1224,6 +1184,7 @@ begin elsif instruction_kind = ElnaTacOperator.copy then operand_type := _elna_tac_instruction_get_operand_type(tac_instruction, 1); operand_value := _elna_tac_instruction_get_operand_value(tac_instruction, 1); + operand_length := _elna_tac_instruction_get_operand_length(tac_instruction, 1); if operand_type = ElnaTacOperand.temporary then result := elna_rtl_load_operand_value(tac_instruction, 2, operand_value); @@ -1237,6 +1198,20 @@ begin _elna_tac_instruction_set_operand(next_instruction^, 1, ElnaRtlOperand.register, ElnaRtlRegister.t4, 0); _elna_tac_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, operand_value); + if operands = nil then + result^.next := next_instruction^ + else + operands^.next := next_instruction^ + end + elsif operand_type = ElnaTacOperand.pseudo then + operands := elna_rtl_load_operand_value(tac_instruction, 2, ElnaRtlRegister.t4); + result := operands; + operands := result^.next; + + next_instruction^ := elna_rtl_instruction_create(ElnaRtlOperator.move); + _elna_tac_instruction_set_operand(next_instruction^, 1, ElnaRtlOperand.pseudo, operand_value, operand_length); + _elna_tac_instruction_set_operand(next_instruction^, 2, ElnaRtlOperand.register, ElnaRtlRegister.t4, 0); + if operands = nil then result^.next := next_instruction^ else @@ -1264,13 +1239,13 @@ end; proc _elna_tac_label(counter: Word, length: Word); var - result: Word; + result1: Word; begin - result := _elna_tac_instruction_create(ElnaTacOperator.label); + result1 := _elna_tac_instruction_create(ElnaTacOperator.label); - _elna_tac_instruction_set_operand(result, 1, ElnaTacOperand.symbol, counter, length); + _elna_tac_instruction_set_operand(result1, 1, ElnaTacOperand.symbol, counter, length); - return result + return result1 end; proc _elna_writer_instruction_name(instruction_kind: Word); @@ -1349,8 +1324,6 @@ begin elsif instruction_kind = ElnaRtlOperator.bnez then argument_count := 2; _write_s("\tbnez", 5) - else (* ElnaRtlOperator.allocate_stack or ElnaRtlOperator.ret *) - argument_count := 0 end; return argument_count end; @@ -1392,22 +1365,110 @@ begin end end; -proc _elna_writer_instruction(instruction: Word); +proc elna_alloc_variable(operand_value: Word, operand_length: Word); +var + pseudo_symbol1: Word; +begin + pseudo_symbol1 := _symbol_table_lookup(@variable_map, operand_value, operand_length); + if pseudo_symbol1 = nil then + _symbol_table_enter(@variable_map, operand_value, operand_length, temporary_variable_counter); + pseudo_symbol1 := temporary_variable_counter; + temporary_variable_counter := temporary_variable_counter + 4 + end; + return pseudo_symbol1 +end; + +proc elna_alloc_instruction(instruction: Word); var instruction_kind: Word; + operand_type: Word; + operand_value: Word; + operand_length: Word; + pseudo_symbol1: Word; +begin + instruction_kind := elna_rtl_instruction_get_kind(instruction); + + if instruction_kind = ElnaRtlOperator.move then + operand_type := elna_rtl_instruction_get_operand_type(instruction, 1); + operand_value := elna_rtl_instruction_get_operand_value(instruction, 1); + operand_length := elna_rtl_instruction_get_operand_length(instruction, 1); + + if operand_type = ElnaRtlOperand.pseudo then + pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length); + elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.sw); + + operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); + operand_value := elna_rtl_instruction_get_operand_value(instruction, 2); + operand_length := elna_rtl_instruction_get_operand_length(instruction, 2); + + elna_rtl_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol1); + + goto elna_alloc_instruction_end + end; + + operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); + operand_value := elna_rtl_instruction_get_operand_value(instruction, 2); + operand_length := elna_rtl_instruction_get_operand_length(instruction, 2); + + if operand_type = ElnaRtlOperand.pseudo then + pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length); + elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.lw); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.offset, ElnaRtlRegister.sp, pseudo_symbol1); + + goto elna_alloc_instruction_end + end + elsif instruction_kind = ElnaRtlOperator.la then + operand_type := elna_rtl_instruction_get_operand_type(instruction, 2); + operand_value := elna_rtl_instruction_get_operand_value(instruction, 2); + operand_length := elna_rtl_instruction_get_operand_length(instruction, 2); + + if operand_type = ElnaRtlOperand.pseudo then + (* Debug. Error stream output. + printf("# %i %.*s\n\0", operand_length, operand_length, operand_value); + fflush(nil); *) + + pseudo_symbol1 := elna_alloc_variable(operand_value, operand_length); + elna_rtl_instruction_set_kind(instruction, ElnaRtlOperator.addi); + + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlOperand.register, ElnaRtlRegister.sp, 0); + elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlOperand.immediate, pseudo_symbol1, 0); + + goto elna_alloc_instruction_end + end + end; + .elna_alloc_instruction_end; +end; + +proc _elna_writer_instruction(instruction: Word); +var argument_count: Word; + instruction_kind: Word; current_argument: Word; operand_value: Word; operand_length: Word; begin instruction_kind := elna_rtl_instruction_get_kind(instruction); + argument_count := 0; if instruction_kind = ElnaRtlOperator.label then - argument_count := 0; operand_value := elna_rtl_instruction_get_operand_value(instruction, 1); operand_length := elna_rtl_instruction_get_operand_length(instruction, 1); _write_label(operand_value, operand_length); _write_c(':') + elsif instruction_kind = ElnaRtlOperator.allocate_stack then + operand_value := elna_rtl_instruction_get_operand_value(instruction, 1); + + (* Write the prologue. *) + printf("\taddi sp, sp, -%i\n\tsw ra, %i(sp)\n\tsw s0, %i(sp)\n\taddi s0, sp, %i\n\0", + operand_value + 8, operand_value + 4, operand_value, operand_value + 8); + fflush(nil) + elsif instruction_kind = ElnaRtlOperator.ret then + operand_value := elna_rtl_instruction_get_operand_value(instruction, 1); + + (* Write the epilogue. *) + printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value + 4, operand_value, operand_value + 8); + fflush(nil) else argument_count := _elna_writer_instruction_name(instruction_kind) end; @@ -1428,10 +1489,10 @@ end; proc elna_rtl_instructions(instruction: ^ElnaInstructionList); var + last_copy1: ^ElnaInstructionList; current_copy: ^ElnaInstructionList; next_copy: ^ElnaInstructionList; first_copy: ^ElnaInstructionList; - last_copy: ^ElnaInstructionList; begin if instruction <> nil then first_copy := elna_rtl_instruction(instruction, @current_copy); @@ -1443,27 +1504,65 @@ begin .elna_rtl_instructions_start; if instruction <> nil then - next_copy := elna_rtl_instruction(instruction, @last_copy); + next_copy := elna_rtl_instruction(instruction, @last_copy1); instruction := instruction^.next; current_copy^.next := next_copy; - current_copy := last_copy; + current_copy := last_copy1; goto elna_rtl_instructions_start end; return first_copy end; +proc elna_alloc_instructions(instruction: ^ElnaInstructionList); +begin + .elna_alloc_instructions_start; + + if instruction <> nil then + elna_alloc_instruction(instruction); + instruction := instruction^.next; + goto elna_alloc_instructions_start + end +end; + proc _elna_writer_instructions(instruction: ^ElnaInstructionList); begin .elna_writer_instructions_start; - if instruction <> 0 then + if instruction <> nil then _elna_writer_instruction(instruction); instruction := instruction^.next; goto elna_writer_instructions_start end end; +proc elna_alloc_procedure(rtl_declaration: ^ElnaInstructionDeclaration); +var + stack_instruction: ^ElnaInstructionList; +begin + .elna_alloc_procedure_loop; + temporary_variable_counter := 60; + variable_map := 0; + + elna_alloc_instructions(rtl_declaration^.body); + if rtl_declaration^.stack then + stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack); + stack_instruction^.next := rtl_declaration^.body; + elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlOperand.immediate, temporary_variable_counter, 0); + + rtl_declaration^.body := stack_instruction; + stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.ret); + elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlOperand.immediate, temporary_variable_counter, 0); + + elna_instruction_list_concatenate(rtl_declaration^.body, stack_instruction) + end; + + rtl_declaration := rtl_declaration^.next; + if rtl_declaration <> nil then + goto elna_alloc_procedure_loop + end +end; + proc _elna_writer_procedure(procedure: ^ElnaInstructionDeclaration); begin .elna_writer_procedure_loop; @@ -1478,19 +1577,11 @@ begin _write_s(procedure^.name, procedure^.length); _write_z(":\n\0"); - (* Write the prologue. *) - if procedure^.stack then - _write_z("\taddi sp, sp, -144\n\tsw ra, 140(sp)\n\tsw s0, 136(sp)\n\taddi s0, sp, 144\n\0") - end; _elna_writer_instructions(procedure^.body); - (* Write the epilogue. *) - if procedure^.stack then - _write_z("\tlw ra, 140(sp)\n\tlw s0, 136(sp)\n\taddi sp, sp, 144\n\0") - end; _write_z("\tret\n\0"); procedure := procedure^.next; - if procedure <> 0 then + if procedure <> nil then goto elna_writer_procedure_loop end end; @@ -1527,6 +1618,11 @@ begin return elna_instruction_module_create(data_part, code_part) end; +proc elna_alloc_module(pair: ^ElnaInstructionModule); +begin + elna_alloc_procedure(pair^.code) +end; + proc _elna_writer_module(pair: ^ElnaInstructionModule); var compiler_strings_copy: Word; @@ -1539,7 +1635,6 @@ begin _elna_writer_variable(pair^.data); _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"); @@ -1694,13 +1789,20 @@ end; proc _elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); var - lookup_result: ^_parameter_info; + lookup_result: ^ElnaSymbolParameterInfo; begin lookup_result := _symbol_table_lookup(symbol_table, variable_expression^.name, variable_expression^.length); + if lookup_result <> nil then - operand_type^ := ElnaTacOperand.stack; - operand_value^ := lookup_result^.offset; - operand_length^ := 0 + if lookup_result^.kind = ElnaSymbolInfoKind.temporary_info then + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := variable_expression^.name; + operand_length^ := variable_expression^.length + else + operand_type^ := ElnaTacOperand.stack; + operand_value^ := lookup_result^.offset; + operand_length^ := 0 + end else operand_type^ := ElnaTacOperand.symbol; operand_value^ := variable_expression^.name; @@ -1796,20 +1898,20 @@ end; proc elna_parser_designator(); var simple_expression: Word; - token_kind: Word; + token_kind1: Word; begin simple_expression := elna_parser_simple_expression(); .elna_parser_designator_loop; - _elna_lexer_read_token(@token_kind); + _elna_lexer_read_token(@token_kind1); - if token_kind = ElnaLexerKind.hat then + if token_kind1 = ElnaLexerKind.hat then simple_expression := elna_parser_dereference_expression(simple_expression); goto elna_parser_designator_loop - elsif token_kind = ElnaLexerKind.dot then + elsif token_kind1 = ElnaLexerKind.dot then simple_expression := elna_parser_field_access_expression(simple_expression); goto elna_parser_designator_loop - elsif token_kind = ElnaLexerKind.left_paren then + elsif token_kind1 = ElnaLexerKind.left_paren then simple_expression := elna_parser_call(simple_expression); goto elna_parser_designator_loop end; @@ -2015,8 +2117,6 @@ end; proc _elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); var - token_kind: Word; - operand_node: Word; first_instruction: Word; instruction: Word; current_instruction: Word; @@ -2027,17 +2127,14 @@ begin if parser_node^.kind <> ElnaTreeKind.binary_expression then first_instruction := _elna_tac_unary_expression(parser_node, symbol_table, operand_type, operand_value, operand_length) else - token_kind := parser_node^.operator; - - operand_node := parser_node^.lhs; lhs_type := 0; lhs_value := 0; lhs_length := 0; - first_instruction := _elna_tac_unary_expression(operand_node, symbol_table, @lhs_type, @lhs_value, @lhs_length); + first_instruction := _elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs_type, @lhs_value, @lhs_length); (* Save the value of the left expression on the stack. *) instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.stack, 72, 0); + _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.pseudo, "$lhs", 4); _elna_tac_instruction_set_operand(instruction, 2, lhs_type, lhs_value, lhs_length); if first_instruction = 0 then @@ -2047,53 +2144,52 @@ begin end; current_instruction := instruction; - operand_node := parser_node^.rhs; lhs_type := 0; lhs_value := 0; lhs_length := 0; - instruction := _elna_tac_unary_expression(operand_node, symbol_table, @lhs_type, @lhs_value, @lhs_length); + instruction := _elna_tac_unary_expression(parser_node^.rhs, symbol_table, @lhs_type, @lhs_value, @lhs_length); current_instruction := elna_instruction_list_concatenate(current_instruction, instruction); (* Load the left expression from the stack; *) instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 7, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 72, 0); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$lhs", 4); elna_instruction_list_concatenate(current_instruction, instruction); current_instruction := instruction; - if token_kind = ElnaLexerKind.plus then + if parser_node^.operator = ElnaLexerKind.plus then instruction := _elna_tac_instruction_create(ElnaTacOperator.add) - elsif token_kind = ElnaLexerKind.minus then + elsif parser_node^.operator = ElnaLexerKind.minus then instruction := _elna_tac_instruction_create(ElnaTacOperator.subtract) - elsif token_kind = ElnaLexerKind.multiplication then + elsif parser_node^.operator = ElnaLexerKind.multiplication then instruction := _elna_tac_instruction_create(ElnaTacOperator.multiply) - elsif token_kind = ElnaLexerKind.and then + elsif parser_node^.operator = ElnaLexerKind.and then instruction := _elna_tac_instruction_create(ElnaTacOperator.and) - elsif token_kind = ElnaLexerKind._or then + elsif parser_node^.operator = ElnaLexerKind._or then instruction := _elna_tac_instruction_create(ElnaTacOperator._or) - elsif token_kind = ElnaLexerKind._xor then + elsif parser_node^.operator = ElnaLexerKind._xor then instruction := _elna_tac_instruction_create(ElnaTacOperator._xor) - elsif token_kind = ElnaLexerKind.equals then + elsif parser_node^.operator = ElnaLexerKind.equals then instruction := _elna_tac_instruction_create(ElnaTacOperator.equal) - elsif token_kind = ElnaLexerKind.remainder then + elsif parser_node^.operator = ElnaLexerKind.remainder then instruction := _elna_tac_instruction_create(ElnaTacOperator.remainder) - elsif token_kind = ElnaLexerKind.division then + elsif parser_node^.operator = ElnaLexerKind.division then instruction := _elna_tac_instruction_create(ElnaTacOperator.divide) - elsif token_kind = ElnaLexerKind.less_than then + elsif parser_node^.operator = ElnaLexerKind.less_than then instruction := _elna_tac_instruction_create(ElnaTacOperator.less_than) - elsif token_kind = ElnaLexerKind.greater_than then + elsif parser_node^.operator = ElnaLexerKind.greater_than then instruction := _elna_tac_instruction_create(ElnaTacOperator.greater_than) - elsif token_kind = ElnaLexerKind.less_equal then + elsif parser_node^.operator = ElnaLexerKind.less_equal then instruction := _elna_tac_instruction_create(ElnaTacOperator.less_or_equal) - elsif token_kind = ElnaLexerKind.greater_equal then + elsif parser_node^.operator = ElnaLexerKind.greater_equal then instruction := _elna_tac_instruction_create(ElnaTacOperator.greater_or_equal) - elsif token_kind = ElnaLexerKind.not_equal then + elsif parser_node^.operator = ElnaLexerKind.not_equal then instruction := _elna_tac_instruction_create(ElnaTacOperator.not_equal) end; _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 6, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 72, 0); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.pseudo, "$lhs", 4); _elna_tac_instruction_set_operand(instruction, 3, lhs_type, lhs_value, lhs_length); elna_instruction_list_concatenate(current_instruction, instruction); @@ -2181,9 +2277,9 @@ end; proc _elna_tac_call(parsed_call: Word, symbol_table: Word); var + argument_count1: Word; name_length: Word; name: Word; - argument_count: Word; stack_offset: Word; parsed_expression: ^ElnaTreeVariableExpression; instruction: Word; @@ -2196,12 +2292,12 @@ begin parsed_expression := _call_get_name(parsed_call); name := parsed_expression^.name; name_length := parsed_expression^.length; - argument_count := 0; + argument_count1 := 0; first_instruction := 0; .elna_tac_call_loop; - parsed_expression := _call_get_argument(parsed_call, argument_count + 1); + parsed_expression := _call_get_argument(parsed_call, argument_count1 + 1); if parsed_expression = 0 then goto elna_tac_call_finalize else @@ -2219,11 +2315,11 @@ begin end; (* Save the argument on the stack. *) - stack_offset := argument_count * 4; + stack_offset := argument_count1 * 4; instruction := _elna_tac_instruction_create(ElnaTacOperator.store); _elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 132 - stack_offset, 0); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 56 - stack_offset, 0); if first_instruction = 0 then first_instruction := instruction else @@ -2231,21 +2327,21 @@ begin end; current_instruction := instruction; - argument_count := argument_count + 1; + argument_count1 := argument_count1 + 1; goto elna_tac_call_loop end; .elna_tac_call_finalize; (* Load the argument from the stack. *) - if argument_count <> 0 then + if argument_count1 <> 0 then (* Decrement the argument counter. *) - argument_count := argument_count - 1; - stack_offset := argument_count * 4; + argument_count1 := argument_count1 - 1; + stack_offset := argument_count1 * 4; - (* Calculate the stack offset: 132 - (4 * argument_counter) *) + (* Calculate the stack offset: 56 - (4 * argument_counter) *) instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 11 + argument_count, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 132 - stack_offset, 0); + _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 11 + argument_count1, 0); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 56 - stack_offset, 0); elna_instruction_list_concatenate(current_instruction, instruction); current_instruction := instruction; @@ -2263,43 +2359,38 @@ end; proc elna_parser_goto_statement(); var - token_kind: Word; - label_name: Word; - label_length: Word; - result: ^ElnaTreeGotoStatement; + token_kind1: Word; + result1: ^ElnaTreeGotoStatement; begin _elna_lexer_skip_token(); - _elna_lexer_read_token(@token_kind); + _elna_lexer_read_token(@token_kind1); + + result1 := malloc(ElnaTreeGotoStatement_size()); + result1^.kind := ElnaTreeKind.goto_statement; + result1^.next := nil; + result1^.label := _elna_lexer_global_get_start(); + result1^.length := _elna_lexer_global_get_end() - result1^.label; - label_name := _elna_lexer_global_get_start(); - label_length := _elna_lexer_global_get_end() - label_name; _elna_lexer_skip_token(); - result := malloc(ElnaTreeGotoStatement_size()); - - result^.kind := ElnaTreeKind.goto_statement; - result^.next := nil; - result^.label := label_name; - result^.length := label_length; - - return result + return result1 end; proc _elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement); var - label_length: Word; - label_with_dot: Word; - instruction: Word; + label_length1: Word; + label_with_dot1: Word; + instruction1: Word; begin - label_length := parser_node^.length + 1; - label_with_dot := malloc(label_length); + label_length1 := parser_node^.length + 1; + label_with_dot1 := malloc(label_length1); - _store_byte('.', label_with_dot); - memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length); + _store_byte('.', label_with_dot1); + memcpy(label_with_dot1 + 1, parser_node^.label, parser_node^.length); - instruction := _elna_tac_instruction_create(ElnaTacOperator.jump); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.symbol, label_with_dot, label_length); - return instruction + instruction1 := _elna_tac_instruction_create(ElnaTacOperator.jump); + _elna_tac_instruction_set_operand(instruction1, 1, ElnaTacOperand.symbol, label_with_dot1, label_length1); + return instruction1 end; proc elna_parser_label_declaration(); @@ -2336,7 +2427,7 @@ var members: Word; members_length: Word; token_type: Word; - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; member_name: Word; member_length: Word; counter: Word; @@ -2375,25 +2466,21 @@ end; proc elna_parser_field_access_expression(aggregate: Word); var token_kind: Word; - name_pointer: Word; - name_length: Word; result: ^ElnaTreeFieldAccessExpression; begin (* Skip dot. Read the enumeration value. *) _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); - name_pointer := _elna_lexer_global_get_start(); - name_length := _elna_lexer_global_get_end() - name_pointer; - - _elna_lexer_skip_token(); result := malloc(ElnaTreeFieldAccessExpression_size()); result^.kind := ElnaTreeKind.field_access_expression; - result^.aggregate := aggregate; - result^.field := name_pointer; - result^.length := name_length; result^.type_decoration := nil; + result^.aggregate := aggregate; + result^.field := _elna_lexer_global_get_start(); + result^.length := _elna_lexer_global_get_end() - result^.field; + + _elna_lexer_skip_token(); return result end; @@ -2516,41 +2603,53 @@ begin operand_length := 0; first_instruction := _elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @operand_type, @operand_value, @operand_length); - current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); - _elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0); - _elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length); - first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); + if operand_type = ElnaTacOperand.pseudo then + current_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); + _elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); - (* Save the assignee address on the stack. *) - current_instruction := _elna_tac_instruction_create(ElnaTacOperator.store); - _elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0); - _elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacOperand.stack, 76, 0); - elna_instruction_list_concatenate(first_instruction, current_instruction); + operand_type := 0; + operand_value := 0; + operand_length := 0; + instruction := _elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length); + _elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length); - (* Compile the assignment. *) - operand_type := 0; - operand_value := 0; - operand_length := 0; - instruction := _elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length); + first_instruction := elna_instruction_list_concatenate(instruction, current_instruction) + else + current_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); + _elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0); + _elna_tac_instruction_set_operand(current_instruction, 2, operand_type, operand_value, operand_length); + first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); + + (* Save the assignee address on the stack. *) + current_instruction := _elna_tac_instruction_create(ElnaTacOperator.store); + _elna_tac_instruction_set_operand(current_instruction, 1, ElnaTacOperand.temporary, 6, 0); + _elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacOperand.stack, 0, 0); + elna_instruction_list_concatenate(first_instruction, current_instruction); + + (* Compile the assignment. *) + operand_type := 0; + operand_value := 0; + operand_length := 0; + instruction := _elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @operand_type, @operand_value, @operand_length); + + if instruction <> 0 then + elna_instruction_list_concatenate(current_instruction, instruction); + current_instruction := instruction + end; + + instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); + _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 7, 0); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 0, 0); + + elna_instruction_list_concatenate(current_instruction, instruction); + current_instruction := instruction; + + instruction := _elna_tac_instruction_create(ElnaTacOperator.store); + _elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); + _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.temporary, 7, 0); - if instruction <> 0 then elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction end; - - instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); - _elna_tac_instruction_set_operand(instruction, 1, ElnaTacOperand.temporary, 7, 0); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.stack, 76, 0); - - elna_instruction_list_concatenate(current_instruction, instruction); - current_instruction := instruction; - - instruction := _elna_tac_instruction_create(ElnaTacOperator.store); - _elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length); - _elna_tac_instruction_set_operand(instruction, 2, ElnaTacOperand.temporary, 7, 0); - - elna_instruction_list_concatenate(current_instruction, instruction); - return first_instruction end; @@ -3214,7 +3313,7 @@ end; proc elna_name_type_expression(parser_node: ^ElnaTreeNode); var named_type_expression: ^ElnaTreeNamedTypeExpression; - type_symbol: ^_type_info; + type_symbol: ^ElnaSymbolTypeInfo; result: Word; begin if parser_node^.kind = ElnaTreeKind.named_type_expression then @@ -3243,14 +3342,14 @@ end; proc _parameter_info_create(parameter_index: Word, parameter_type: Word); var offset: Word; - result: ^_parameter_info; + result: ^ElnaSymbolParameterInfo; begin - result := malloc(_parameter_info_size()); - result^.kind := InfoKind.parameter_info; + result := malloc(ElnaSymbolParameterInfo_size()); + result^.kind := ElnaSymbolInfoKind.parameter_info; - (* Calculate the stack offset: 104 - (4 * parameter_counter) *) + (* Calculate the stack offset: 28 - (4 * parameter_counter) *) offset := parameter_index * 4; - result^.offset := 104 - offset; + result^.offset := 28 - offset; result^.variable_type := parameter_type; return result @@ -3258,10 +3357,10 @@ end; proc _type_info_create(type_representation: Word); var - result: ^_type_info; + result: ^ElnaSymbolTypeInfo; begin - result := malloc(_type_info_size()); - result^.kind := InfoKind.type_info; + result := malloc(ElnaSymbolTypeInfo_size()); + result^.kind := ElnaSymbolInfoKind.type_info; result^._type := type_representation; return result @@ -3274,10 +3373,10 @@ end; *) proc _temporary_info_create(temporary_index: Word, temporary_type: Word); var - result: ^_temporary_info; + result: ^ElnaSymbolTemporaryInfo; begin - result := malloc(_temporary_info_size()); - result^.kind := InfoKind.temporary_info; + result := malloc(ElnaSymbolTemporaryInfo_size()); + result^.kind := ElnaSymbolInfoKind.temporary_info; (* Calculate the stack offset: 4 * variable_counter. *) result^.offset := temporary_index * 4; @@ -3292,10 +3391,10 @@ end; *) proc _procedure_info_create(symbol_table: Word); var - result: ^_procedure_info; + result: ^ElnaSymbolProcedureInfo; begin - result := malloc(_procedure_info_size()); - result^.kind := InfoKind.procedure_info; + result := malloc(ElnaSymbolProcedureInfo_size()); + result^.kind := ElnaSymbolInfoKind.procedure_info; result^.symbol_table := symbol_table; return result @@ -3308,11 +3407,11 @@ end; proc elna_name_procedure_parameter(parser_node: ^ElnaTreeVariableDeclaration, parameter_index: Word, symbol_table: Word); var info: Word; - variable_type: Word; + variable_type1: Word; begin - variable_type := elna_name_type_expression(parser_node^._type); + variable_type1 := elna_name_type_expression(parser_node^._type); - info := _parameter_info_create(parameter_index, variable_type); + info := _parameter_info_create(parameter_index, variable_type1); _symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info) end; @@ -3323,11 +3422,11 @@ end; proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, variable_index: Word, symbol_table: Word); var info: Word; - variable_type: Word; + variable_type1: Word; begin - variable_type := elna_name_type_expression(parser_node^._type); + variable_type1 := elna_name_type_expression(parser_node^._type); - info := _temporary_info_create(variable_index, variable_type); + info := _temporary_info_create(variable_index, variable_type1); _symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info) end; @@ -3430,7 +3529,7 @@ var instruction: Word; first_instruction: Word; current_instruction: Word; - symbol_info: ^_parameter_info; + symbol_info: ^ElnaSymbolParameterInfo; begin first_instruction := 0; parameter_counter := 0; @@ -3473,25 +3572,15 @@ end; proc elna_rtl_procedure_declaration(tac_declaration: ^ElnaInstructionDeclaration); var - body: Word; result: ^ElnaInstructionDeclaration; - return_instruction: ^ElnaInstructionList; begin result := malloc(ElnaInstructionDeclaration_size()); - body := tac_declaration^.body; - body := elna_rtl_instructions(body); - - return_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack); - return_instruction^.next := body; - body := return_instruction; - return_instruction := elna_rtl_instruction_create(ElnaRtlOperator.ret); - elna_instruction_list_concatenate(body, return_instruction); result^.next := nil; result^.name := tac_declaration^.name; result^.length := tac_declaration^.length; result^.stack := tac_declaration^.stack; - result^.body := body; + result^.body := elna_rtl_instructions(tac_declaration^.body); return result end; @@ -3500,7 +3589,7 @@ proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration); var current_parameter: Word; new_symbol_table: Word; - symbol_info: ^_procedure_info; + symbol_info: ^ElnaSymbolProcedureInfo; instruction: Word; first_instruction: Word; result: ^ElnaInstructionDeclaration; @@ -3621,14 +3710,14 @@ var current_procedure: ^ElnaInstructionList; first_procedure: Word; begin - first_procedure := 0; + first_procedure := nil; .elna_tac_procedures_loop; if parser_node = 0 then goto elna_tac_procedures_end end; result := _elna_tac_procedure_declaration(parser_node); - if first_procedure = 0 then + if first_procedure = nil then first_procedure := result else current_procedure^.next := result @@ -3749,7 +3838,7 @@ var token_kind: Word; name: Word; name_length: Word; - variable_type: Word; + variable_type1: Word; result: ^ElnaTreeVariableDeclaration; begin _elna_lexer_read_token(@token_kind); @@ -3762,14 +3851,14 @@ begin _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); - variable_type := elna_parser_type_expression(); + variable_type1 := elna_parser_type_expression(); result := malloc(ElnaTreeVariableDeclaration_size()); result^.kind := ElnaTreeKind.variable_declaration; result^.next := nil; result^.name := name; result^.length := name_length; - result^._type := variable_type; + result^._type := variable_type1; return result end; @@ -3838,7 +3927,7 @@ proc _elna_tac_type_part(parser_node: ^ElnaTreeDeclaration); var result: Word; first_result: Word; - symbol: ^_type_info; + symbol: ^ElnaSymbolTypeInfo; info_type: ^ElnaType; type_kind: Word; current_result: ^ElnaInstructionList; @@ -3944,11 +4033,12 @@ begin return first_variable end; -proc elna_parser_module_declaration(); +proc elna_parser_module_declaration(error_list: ^ElnaErrorList); var parser_node: Word; result: ^ElnaTreeModuleDeclaration; token_kind: Word; + parser_error: ^ElnaError; begin result := malloc(ElnaTreeModuleDeclaration_size()); result^.kind := ElnaTreeKind.module_declaration; @@ -3956,14 +4046,22 @@ begin (* Skip "program;". *) _skip_empty_lines(); _elna_lexer_read_token(@token_kind); - _elna_lexer_skip_token(); - _elna_lexer_read_token(@token_kind); - _elna_lexer_skip_token(); - result^.types := elna_parser_type_part(); - result^.globals := elna_parser_var_part(); - result^.procedures := elna_parser_procedures(); + if token_kind <> ElnaLexerKind._program then + parser_error := malloc(ElnaError_size()); + parser_error^.next := nil; + error_list^.first := parser_error; + error_list^.last := parser_error + else + _elna_lexer_skip_token(); + _elna_lexer_read_token(@token_kind); + _elna_lexer_skip_token(); + + result^.types := elna_parser_type_part(); + result^.globals := elna_parser_var_part(); + result^.procedures := elna_parser_procedures() + end; return result end; @@ -4108,7 +4206,7 @@ end; proc elna_type_character_literal(parser_node: ^ElnaTreeCharacterLiteral); var - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; begin symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); parser_node^.type_decoration := symbol_info^._type @@ -4116,7 +4214,7 @@ end; proc elna_type_integer_literal(parser_node: ^ElnaTreeIntegerLiteral); var - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; begin symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); parser_node^.type_decoration := symbol_info^._type @@ -4124,7 +4222,7 @@ end; proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral); var - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; begin symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); parser_node^.type_decoration := symbol_info^._type @@ -4132,7 +4230,7 @@ end; proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral); var - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; begin symbol_info := _symbol_table_lookup(@symbol_table_global, "Bool", 4); parser_node^.type_decoration := symbol_info^._type @@ -4140,7 +4238,7 @@ end; proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral); var - symbol_info: ^_type_info; + symbol_info: ^ElnaSymbolTypeInfo; begin symbol_info := _symbol_table_lookup(@symbol_table_global, "Pointer", 7); parser_node^.type_decoration := symbol_info^._type @@ -4148,9 +4246,9 @@ end; proc elna_type_variable_expression(parser_node: ^ElnaTreeVariableExpression, symbol_table: Word); var - variable_info: ^_info; - parameter_info: ^_parameter_info; - temporary_info: ^_temporary_info; + variable_info: ^ElnaSymbolInfo; + parameter_info: ^ElnaSymbolParameterInfo; + temporary_info: ^ElnaSymbolTemporaryInfo; begin variable_info := _symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length); @@ -4158,10 +4256,10 @@ begin variable_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length) end; - if variable_info^.kind = InfoKind.parameter_info then + if variable_info^.kind = ElnaSymbolInfoKind.parameter_info then parameter_info := variable_info; parser_node^.type_decoration := parameter_info^.variable_type - elsif variable_info^.kind = InfoKind.temporary_info then + elsif variable_info^.kind = ElnaSymbolInfoKind.temporary_info then temporary_info := variable_info; parser_node^.type_decoration := temporary_info^.variable_type end @@ -4207,8 +4305,8 @@ proc elna_type_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpressi var variable_expression: ^ElnaTreeVariableExpression; base_type: Word; - type_kind: ^_type_info; - symbol_info: ^_info; + type_kind: ^ElnaSymbolTypeInfo; + symbol_info: ^ElnaSymbolInfo; aggregate_type: ^ElnaTypeRecord; field_count: Word; current_field: ^ElnaTypeField; @@ -4222,7 +4320,7 @@ begin if symbol_info <> nil then type_kind := symbol_info; - if symbol_info^.kind = InfoKind.type_info then + if symbol_info^.kind = ElnaSymbolInfoKind.type_info then base_type := type_kind^._type end end @@ -4238,11 +4336,6 @@ begin .elna_type_field_access_expression_field; if string_compare(parser_node^.field, parser_node^.length, current_field^.name, current_field^.length) = 0 then - (* Debug. Error stream output. - _syscall(2, name_pointer, name_length, 0, 0, 0, 64); - printf("# if %.*s\n\0", name_length, name_pointer); - fflush(0) *) - field_count := field_count - 1; current_field := current_field + ElnaTypeField_size(); goto elna_type_field_access_expression_field @@ -4298,7 +4391,7 @@ end; proc elna_type_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration); var - procedure_info: ^_procedure_info; + procedure_info: ^ElnaSymbolProcedureInfo; symbol_table: Word; begin procedure_info := _symbol_table_lookup(@symbol_table_global, parser_node^.name, parser_node^.length); @@ -4365,24 +4458,26 @@ var parser_node: Word; tac: Word; rtl: Word; + error_list: ^ElnaErrorList; + compiled: Word; begin - parser_node := elna_parser_module_declaration(); - elna_name_module_declaration(parser_node); - elna_type_module_declaration(parser_node); - tac := _elna_tac_module_declaration(parser_node); - rtl := elna_rtl_module_declaration(tac); - _elna_writer_module(rtl) -end; + error_list := malloc(ElnaErrorList_size()); + error_list^.first := nil; + error_list^.last := nil; -(** - * Terminates the program. a0 contains the return code. - * - * Parameters: - * a0 - Status code. - *) -proc _exit(status: Word); -begin - _syscall(status, 0, 0, 0, 0, 0, 93) + parser_node := elna_parser_module_declaration(error_list); + compiled := error_list^.first = nil; + + if compiled then + elna_name_module_declaration(parser_node); + elna_type_module_declaration(parser_node); + tac := _elna_tac_module_declaration(parser_node); + rtl := elna_rtl_module_declaration(tac); + elna_alloc_module(rtl); + _elna_writer_module(rtl); + end; + + return compiled end; (** @@ -4502,7 +4597,7 @@ end; proc _symbol_table_build(); var - current_info: ^_type_info; + current_info: ^ElnaSymbolTypeInfo; current_type: ^ElnaType; begin (* Set the table length to 0. *) @@ -5312,7 +5407,6 @@ begin compiler_strings_position := @compiler_strings; source_code := malloc(495616); symbol_table_store := malloc(4194304); - temporary_variable_counter := 0 end; (* @@ -5332,12 +5426,14 @@ begin .start_read; (* Second argument is buffer size. Modifying update the source_code definition. *) - last_read := _read_file(offset, 409600); + last_read := read(0, offset, 409600); if last_read > 0 then offset := offset + last_read; goto start_read end; - _compile(); - - _exit(0) + if _compile() then + exit(0) + else + exit(4) + end; end;