From d144cb21012c911135d5047059449195a89ea239 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 8 Nov 2025 11:07:39 +0100 Subject: [PATCH] Move stages into subdirectories --- Rakefile | 59 +- boot/{stage10.elna => stage10/cl.elna} | 0 boot/{stage11.elna => stage11/cl.elna} | 0 boot/{stage12.elna => stage12/cl.elna} | 0 boot/{stage13.elna => stage13/cl.elna} | 0 boot/{stage14.elna => stage14/cl.elna} | 0 boot/{stage15.elna => stage15/cl.elna} | 7 +- boot/{stage16.elna => stage16/cl.elna} | 917 +++++++++++++------------ boot/stage16/linker.arg | 0 boot/{stage2.elna => stage2/cl.elna} | 0 boot/{stage3.elna => stage3/cl.elna} | 0 boot/{stage4.elna => stage4/cl.elna} | 0 boot/{stage5.elna => stage5/cl.elna} | 0 boot/{stage6.elna => stage6/cl.elna} | 0 boot/{stage7.elna => stage7/cl.elna} | 0 boot/{stage8.elna => stage8/cl.elna} | 0 boot/{stage9.elna => stage9/cl.elna} | 0 boot/symbol.s | 297 -------- 18 files changed, 530 insertions(+), 750 deletions(-) rename boot/{stage10.elna => stage10/cl.elna} (100%) rename boot/{stage11.elna => stage11/cl.elna} (100%) rename boot/{stage12.elna => stage12/cl.elna} (100%) rename boot/{stage13.elna => stage13/cl.elna} (100%) rename boot/{stage14.elna => stage14/cl.elna} (100%) rename boot/{stage15.elna => stage15/cl.elna} (99%) rename boot/{stage16.elna => stage16/cl.elna} (87%) create mode 100644 boot/stage16/linker.arg rename boot/{stage2.elna => stage2/cl.elna} (100%) rename boot/{stage3.elna => stage3/cl.elna} (100%) rename boot/{stage4.elna => stage4/cl.elna} (100%) rename boot/{stage5.elna => stage5/cl.elna} (100%) rename boot/{stage6.elna => stage6/cl.elna} (100%) rename boot/{stage7.elna => stage7/cl.elna} (100%) rename boot/{stage8.elna => stage8/cl.elna} (100%) rename boot/{stage9.elna => stage9/cl.elna} (100%) delete mode 100644 boot/symbol.s diff --git a/Rakefile b/Rakefile index ec3ae04..54c3bd3 100644 --- a/Rakefile +++ b/Rakefile @@ -4,19 +4,18 @@ # frozen_string_literal: true require 'open3' +require 'pathname' require 'rake/clean' -STAGES = Dir.glob('boot/stage*.elna') - .collect { |stage| File.basename stage, '.elna' } +STAGES = Dir.glob('boot/stage*') + .collect { |stage| File.basename stage } .sort { |a, b| a.delete_prefix('stage').to_i <=> b.delete_prefix('stage').to_i } + .drop(1) # First assembly stage does not count. CLEAN.include 'build/boot', 'build/valid' -directory 'build/boot' -directory 'build/valid' - -def compile(input, output) - sh ENV.fetch('CC', 'gcc'), '-nostdlib', '-fpie', '-g', '-o', output, input +def compile(*arguments) + sh(ENV.fetch('CC', 'gcc'), '-fpie', '-g', *arguments) end def run(exe) @@ -26,9 +25,9 @@ end task default: :boot desc 'Final stage' -task boot: "build/valid/#{STAGES.last}" -task boot: "build/valid/#{STAGES.last}.s" -task boot: "boot/#{STAGES.last}.elna" do |t| +task boot: "build/valid/#{STAGES.last}/cl" +task boot: "build/valid/#{STAGES.last}/cl.s" +task boot: "boot/#{STAGES.last}/cl.elna" do |t| groupped = t.prerequisites.group_by { |stage| File.extname stage }.transform_values(&:first) exe = groupped[''] expected = groupped['.s'] @@ -81,16 +80,33 @@ task :convert do end end -rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+$/ => ->(match) { - "#{match}.s" +rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+\/cl$/ => ->(match) { + "#{match}.o" } do |t| - compile(*t.prerequisites, t.name) + arguments_path = Pathname.new('boot') + Pathname.new(t.name).dirname.basename + 'linker.arg' + if arguments_path.exist? + arguments1 = ['--dynamic-linker', '/lib32/ld-linux-riscv32-ilp32d.so.1', '/usr/lib/crt1.o', '/usr/lib/crti.o', '-lc'] + arguments2 = ['/usr/lib/crtn.o'] + else + arguments1 = arguments2 = [] + end + + sh(ENV.fetch('LD', 'ld'), '-o', t.name, *arguments1, *t.prerequisites, *arguments2) +end + +rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+\/cl.o$/ => ->(match) { + match.ext('.s') +} do |t| + compile('-c', '-o', t.name, *t.prerequisites) end STAGES.each do |stage| previous = stage.delete_prefix('stage').to_i.pred - file "build/valid/#{stage}.s" => ["build/boot/#{stage}", "boot/#{stage}.elna"] do |t| + directory "build/valid/#{stage}" + directory "build/boot/#{stage}" + + file "build/valid/#{stage}/cl.s" => ["build/boot/#{stage}/cl", "boot/#{stage}/cl.elna", "build/valid/#{stage}"] do |t| exe, source = t.prerequisites cat_arguments = ['cat', source] @@ -99,7 +115,7 @@ STAGES.each do |stage| IO.copy_stream last_stdout, t.name end - file "build/boot/#{stage}.s" => ["build/valid/stage#{previous}", "boot/#{stage}.elna"] do |t| + file "build/boot/#{stage}/cl.s" => ["build/valid/stage#{previous}/cl", "boot/#{stage}/cl.elna", "build/boot/#{stage}"] do |t| exe, source = t.prerequisites cat_arguments = ['cat', source] @@ -113,7 +129,14 @@ end # Stage 1. # -file 'build/valid/stage1.s' => ['build/boot/stage1', 'boot/stage1.s', 'build/valid'] do |t| +directory 'build/valid/stage1' +directory 'build/boot/stage1' + +file 'build/valid/stage1/cl' => ['build/valid/stage1.s'] do |t| + compile('-nostdlib', '-o', t.name, *t.prerequisites) +end + +file 'build/valid/stage1.s' => ['build/boot/stage1/cl', 'boot/stage1.s', 'build/valid/stage1'] do |t| source, exe, = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.s' } cat_arguments = ['cat', *source] @@ -122,8 +145,8 @@ file 'build/valid/stage1.s' => ['build/boot/stage1', 'boot/stage1.s', 'build/val IO.copy_stream last_stdout, t.name end -file 'build/boot/stage1' => ['build/boot', 'boot/stage1.s'] do |t| +file 'build/boot/stage1/cl' => ['build/boot/stage1', 'boot/stage1.s'] do |t| source = t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' } - compile(*source, t.name) + compile('-nostdlib', '-o', t.name, *source) end diff --git a/boot/stage10.elna b/boot/stage10/cl.elna similarity index 100% rename from boot/stage10.elna rename to boot/stage10/cl.elna diff --git a/boot/stage11.elna b/boot/stage11/cl.elna similarity index 100% rename from boot/stage11.elna rename to boot/stage11/cl.elna diff --git a/boot/stage12.elna b/boot/stage12/cl.elna similarity index 100% rename from boot/stage12.elna rename to boot/stage12/cl.elna diff --git a/boot/stage13.elna b/boot/stage13/cl.elna similarity index 100% rename from boot/stage13.elna rename to boot/stage13/cl.elna diff --git a/boot/stage14.elna b/boot/stage14/cl.elna similarity index 100% rename from boot/stage14.elna rename to boot/stage14/cl.elna diff --git a/boot/stage15.elna b/boot/stage15/cl.elna similarity index 99% rename from boot/stage15.elna rename to boot/stage15/cl.elna index 987d655..3f2dde2 100644 --- a/boot/stage15.elna +++ b/boot/stage15/cl.elna @@ -6,6 +6,11 @@ (* Stage 15 compiler. *) +(* - Procedure names are not required anymore to start with an underscore. *) +(* - Record declarations are supported. Access is done with generated procedures, + record_name_get_field and record_name_set_field. Record size can be queried with + record_name_size(). *) + type ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited); @@ -1258,7 +1263,7 @@ var current_byte: Word; current_part: Word; begin - _write_z(".globl _start\n\n\0"); + _write_z(".globl _start, main\n\n\0"); _write_z(".section .data\n\0"); current_part := _elna_tac_module_get_data(pair); diff --git a/boot/stage16.elna b/boot/stage16/cl.elna similarity index 87% rename from boot/stage16.elna rename to boot/stage16/cl.elna index cd56cc2..f76edae 100644 --- a/boot/stage16.elna +++ b/boot/stage16/cl.elna @@ -4,7 +4,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. *) -(* Stage 15 compiler. *) +(* Stage 16 compiler. *) type _elna_tac_declaration = record @@ -13,6 +13,12 @@ type length: Word; body: Word end; + elna_rtl_declaration = record + next: Word; + name: Word; + length: Word; + body: Word + end; _node = record kind: Word end; @@ -88,6 +94,10 @@ type data: Word; code: Word end; + elna_rtl_module = record + data: Word; + code: Word + end; _module_declaration = record kind: Word; types: Word; @@ -136,6 +146,25 @@ type name: Word; length: Word end; + _info = record + kind: Word + end; + _type_info = record + kind: Word; + _type: Word + end; + _parameter_info = record + kind: Word; + offset: Word + end; + _temporary_info = record + kind: Word; + offset: Word + end; + _procedure_info = record + kind: Word; + symbol_table: Word + end; (** * Conditional statements is a list of pairs: condition and statements. @@ -350,8 +379,37 @@ type start, ret ); + ElnaRtlOperator = ( + load_immediate, + load_address, + add, + add_immediate, + load_word, + store_word, + jal, + move, + sub, + div, + rem, + mul, + _xor, + _or, + and, + seqz, + snez, + slt, + xor_immediate, + neg, + not, + jump, + beqz, + label, + start, + ret + ); ElnaTacOperand = (register, immediate, symbol, offset); - ElnaTacRegister = ( + ElnaRtlOperand = (register, immediate, symbol, offset); + ElnaRtlRegister = ( zero, ra, sp, @@ -397,9 +455,6 @@ var label_counter: Word; symbol_table_store: Word; - (* Points to a segment of free memory. *) - memory_free_pointer: Word; - (** * Calculates and returns the string token length between quotes, including the * escaping slash characters. @@ -475,15 +530,6 @@ proc _read_file(buffer: Word, size: Word); return _syscall(0, buffer, size, 0, 0, 0, 63) end; -(** - * MAP_ANONYMOUS is 32. - * PROT_READ | PORT_WRITE is (1 | 2). - * MAP_ANONYMOUS | MAP_PRIVATE is (32 | 2) - *) -proc _mmap(length: Word); - return _syscall(0, length, 1 or 2, 32 or 2, -1, 0, 222) -end; - (** * Writes to the standard output. * @@ -537,7 +583,7 @@ begin end; result := @result + 11; result := result - local_buffer; - _memcpy(output_buffer, local_buffer + 1, result); + memcpy(output_buffer, local_buffer + 1, result); return result end; @@ -590,34 +636,6 @@ begin end end; -(** - * Detects if a0 is an uppercase character. Sets a0 to 1 if so, otherwise to 0. - *) -proc _is_upper(character: Word); -var - lhs: Word; - rhs: Word; -begin - lhs := character >= 'A'; - rhs := character <= 'Z'; - - return lhs & rhs -end; - -(** - * Detects if a0 is an lowercase character. Sets a0 to 1 if so, otherwise to 0. - *) -proc _is_lower(character: Word); -var - lhs: Word; - rhs: Word; -begin - lhs := character >= 'a'; - rhs := character <= 'z'; - - return lhs & rhs -end; - (** * Detects if the passed character is a 7-bit alpha character or an underscore. * @@ -628,109 +646,15 @@ end; *) proc _is_alpha(character: Word); var - is_upper_result: Word; - is_lower_result: Word; - is_alpha_result: Word; is_underscore: Word; begin - is_upper_result := _is_upper(character); - is_lower_result := _is_lower(character); is_underscore := character = '_'; - is_alpha_result := is_lower_result or is_upper_result; - return is_alpha_result or is_underscore -end; - -(** - * Detects whether the passed character is a digit (a value between 0 and 9). - * - * Parameters: - * character - Exemined value. - * - * Sets a0 to 1 if it is a digit, to 0 otherwise. - *) -proc _is_digit(character: Word); -var - lhs: Word; - rhs: Word; -begin - lhs := character >= '0'; - rhs := character <= '9'; - - return lhs & rhs + return isalpha(character) or is_underscore end; proc _is_alnum(character: Word); -var - lhs: Word; - rhs: Word; -begin - lhs := _is_alpha(character); - rhs := _is_digit(character); - - return lhs or rhs -end; - -(** - * Parameters: - * lhs - First pointer. - * rhs - Second pointer. - * count - The length to compare. - * - * Returns 0 if memory regions are equal. - *) -proc _memcmp(lhs: Word, rhs: Word, count: Word); -var - lhs_byte: Word; - rhs_byte: Word; - result: Word; -begin - result := 0; - - .memcmp_loop; - if count <> 0 then - lhs_byte := _load_byte(lhs); - rhs_byte := _load_byte(rhs); - result := lhs_byte - rhs_byte; - - lhs := lhs + 1; - rhs := rhs + 1; - count := count - 1; - - if result = 0 then - goto memcmp_loop - end - end; - - return result -end; - -(** - * Copies memory. - * - * Parameters: - * destination - Destination. - * source - Source. - * count - Size. - * - * Returns the destination. - *) -proc _memcpy(destination: Word, source: Word, count: Word); -var - current_byte: Word; -begin - .memcpy_loop; - if count <> 0 then - current_byte := _load_byte(source); - _store_byte(current_byte, destination); - - destination := destination + 1; - source := source + 1; - count := count - 1; - goto memcpy_loop - end; - - return destination + return _is_alpha(character) or isdigit(character) end; proc _elna_tac_instruction_size(); @@ -814,10 +738,8 @@ end; proc _elna_tac_instruction_create(kind: Word); var result: Word; - instruction_size: Word; begin - instruction_size := _elna_tac_instruction_size(); - result := _allocate(instruction_size); + result := malloc(_elna_tac_instruction_size()); _elna_tac_instruction_set_kind(result, kind); _elna_tac_instruction_set_next(result, 0); @@ -825,13 +747,95 @@ begin return result end; +proc elna_rtl_instruction_size(); + return 44 +end; + +proc elna_rtl_instruction_get_kind(this: Word); + return this^ +end; + +proc elna_rtl_instruction_get_next(this: Word); +begin + this := this + 4; + return this^ +end; + +proc elna_rtl_instruction_set_next(this: Word, value: Word); +begin + this := this + 4; + this^ := value +end; + +proc elna_rtl_instruction_set_kind(this: Word, value: Word); +begin + this^ := value +end; + +proc elna_rtl_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_rtl_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_rtl_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_rtl_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_rtl_instruction(tac_instruction: Word); +var + result: Word; + instruction_size: Word; +begin + instruction_size := elna_rtl_instruction_size(); + result := malloc(instruction_size); + + memcpy(result, tac_instruction, instruction_size); + + return result +end; + proc _elna_tac_module_create(data: Word, code: Word); var result: Word; - result_size: Word; begin - result_size := _elna_tac_module_size(); - result := _allocate(result_size); + result := malloc(_elna_tac_module_size()); _elna_tac_module_set_data(result, data); _elna_tac_module_set_code(result, code); @@ -1139,79 +1143,79 @@ proc _elna_writer_instruction_name(instruction_kind: Word); var argument_count: Word; begin - if instruction_kind = ElnaTacOperator.load_immediate then + if instruction_kind = ElnaRtlOperator.load_immediate then argument_count := 2; _write_s("\tli", 3) - elsif instruction_kind = ElnaTacOperator.load_address then + elsif instruction_kind = ElnaRtlOperator.load_address then argument_count := 2; _write_s("\tla", 3) - elsif instruction_kind = ElnaTacOperator.add then + elsif instruction_kind = ElnaRtlOperator.add then argument_count := 3; _write_s("\tadd", 4) - elsif instruction_kind = ElnaTacOperator.add_immediate then + elsif instruction_kind = ElnaRtlOperator.add_immediate then argument_count := 3; _write_s("\taddi", 5) - elsif instruction_kind = ElnaTacOperator.load_word then + elsif instruction_kind = ElnaRtlOperator.load_word then argument_count := 2; _write_s("\tlw", 3) - elsif instruction_kind = ElnaTacOperator.store_word then + elsif instruction_kind = ElnaRtlOperator.store_word then argument_count := 2; _write_s("\tsw", 3) - elsif instruction_kind = ElnaTacOperator.jal then + elsif instruction_kind = ElnaRtlOperator.jal then argument_count := 1; _write_s("\tcall", 5) - elsif instruction_kind = ElnaTacOperator.move then + elsif instruction_kind = ElnaRtlOperator.move then argument_count := 2; _write_s("\tmv", 3) - elsif instruction_kind = ElnaTacOperator.sub then + elsif instruction_kind = ElnaRtlOperator.sub then argument_count := 3; _write_s("\tsub", 4) - elsif instruction_kind = ElnaTacOperator.mul then + elsif instruction_kind = ElnaRtlOperator.mul then argument_count := 3; _write_s("\tmul", 4) - elsif instruction_kind = ElnaTacOperator.div then + elsif instruction_kind = ElnaRtlOperator.div then argument_count := 3; _write_s("\tdiv", 4) - elsif instruction_kind = ElnaTacOperator.rem then + elsif instruction_kind = ElnaRtlOperator.rem then argument_count := 3; _write_s("\trem", 4) - elsif instruction_kind = ElnaTacOperator._xor then + elsif instruction_kind = ElnaRtlOperator._xor then argument_count := 3; _write_s("\txor", 4) - elsif instruction_kind = ElnaTacOperator.xor_immediate then + elsif instruction_kind = ElnaRtlOperator.xor_immediate then argument_count := 3; _write_s("\txori", 5) - elsif instruction_kind = ElnaTacOperator._or then + elsif instruction_kind = ElnaRtlOperator._or then argument_count := 3; _write_s("\tor", 3) - elsif instruction_kind = ElnaTacOperator.and then + elsif instruction_kind = ElnaRtlOperator.and then argument_count := 3; _write_s("\tand", 4) - elsif instruction_kind = ElnaTacOperator.seqz then + elsif instruction_kind = ElnaRtlOperator.seqz then argument_count := 2; _write_s("\tseqz", 5) - elsif instruction_kind = ElnaTacOperator.snez then + elsif instruction_kind = ElnaRtlOperator.snez then argument_count := 2; _write_s("\tsnez", 5) - elsif instruction_kind = ElnaTacOperator.slt then + elsif instruction_kind = ElnaRtlOperator.slt then argument_count := 3; _write_s("\tslt", 4) - elsif instruction_kind = ElnaTacOperator.neg then + elsif instruction_kind = ElnaRtlOperator.neg then argument_count := 2; _write_s("\tneg", 4) - elsif instruction_kind = ElnaTacOperator.not then + elsif instruction_kind = ElnaRtlOperator.not then argument_count := 2; _write_s("\tnot", 4) - elsif instruction_kind = ElnaTacOperator.jump then + elsif instruction_kind = ElnaRtlOperator.jump then argument_count := 1; _write_s("\tj", 2) - elsif instruction_kind = ElnaTacOperator.beqz then + elsif instruction_kind = ElnaRtlOperator.beqz then argument_count := 2; _write_s("\tbeqz", 5) - elsif instruction_kind = ElnaTacOperator.start then + elsif instruction_kind = ElnaRtlOperator.start then argument_count := 0; _write_z("\taddi sp, sp, -128\n\tsw ra, 124(sp)\n\tsw s0, 120(sp)\n\taddi s0, sp, 128\0") - elsif instruction_kind = ElnaTacOperator.ret then + elsif instruction_kind = ElnaRtlOperator.ret then argument_count := 0; _write_z("\tlw ra, 124(sp)\n\tlw s0, 120(sp)\n\taddi sp, sp, 128\0") end; @@ -1230,25 +1234,25 @@ var operand_length: Word; operand_type: Word; begin - operand_type := _elna_tac_instruction_get_operand_type(instruction, n); - operand_value := _elna_tac_instruction_get_operand_value(instruction, n); - operand_length := _elna_tac_instruction_get_operand_length(instruction, n); + operand_type := elna_rtl_instruction_get_operand_type(instruction, n); + operand_value := elna_rtl_instruction_get_operand_value(instruction, n); + operand_length := elna_rtl_instruction_get_operand_length(instruction, n); _write_c(' '); - if operand_type = ElnaTacOperand.register then + if operand_type = ElnaRtlOperand.register then _elna_writer_register(operand_value) - elsif operand_type = ElnaTacOperand.offset then + elsif operand_type = ElnaRtlOperand.offset then _write_i(operand_length); _write_c('('); _elna_writer_register(operand_value); _write_c(')') - elsif operand_type = ElnaTacOperand.symbol then + elsif operand_type = ElnaRtlOperand.symbol then if operand_length = 0 then _write_label(operand_value, 0) else _write_s(operand_value, operand_length) end - elsif operand_length = 0 then (* ElnaTacOperand.immediate *) + elsif operand_length = 0 then (* ElnaRtlOperand.immediate *) _write_i(operand_value) else _write_s(operand_value, operand_length) @@ -1263,12 +1267,12 @@ var operand_value: Word; operand_length: Word; begin - instruction_kind := _elna_tac_instruction_get_kind(instruction); + instruction_kind := elna_rtl_instruction_get_kind(instruction); - if instruction_kind = ElnaTacOperator.label then + if instruction_kind = ElnaRtlOperator.label then argument_count := 0; - operand_value := _elna_tac_instruction_get_operand_value(instruction, 1); - operand_length := _elna_tac_instruction_get_operand_length(instruction, 1); + 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(':') else @@ -1289,12 +1293,41 @@ begin _write_c('\n') end; -proc _elna_writer_instructions(instruction: Word); +proc elna_rtl_instructions(instruction: Word); +var + current_copy: Word; + next_copy: Word; + first_copy: Word; begin if instruction <> 0 then - _elna_writer_instruction(instruction); + first_copy := elna_rtl_instruction(instruction); + instruction := _elna_tac_instruction_get_next(instruction) + else + first_copy := 0; + end; + current_copy := first_copy; + + .elna_rtl_instructions_start; + + if instruction <> 0 then + next_copy := elna_rtl_instruction(instruction); + instruction := _elna_tac_instruction_get_next(instruction); - _elna_writer_instructions(instruction) + elna_rtl_instruction_set_next(current_copy, next_copy); + current_copy := next_copy; + goto elna_rtl_instructions_start + end; + + return first_copy +end; + +proc _elna_writer_instructions(instruction: Word); +begin + .elna_writer_instructions_start; + if instruction <> 0 then + _elna_writer_instruction(instruction); + instruction := elna_rtl_instruction_get_next(instruction); + goto elna_writer_instructions_start end end; @@ -1305,9 +1338,9 @@ var body_statements: Word; begin .elna_writer_procedure_loop; - name_pointer := _elna_tac_declaration_get_name(procedure); - name_length := _elna_tac_declaration_get_length(procedure); - body_statements := _elna_tac_declaration_get_body(procedure); + name_pointer := elna_rtl_declaration_get_name(procedure); + name_length := elna_rtl_declaration_get_length(procedure); + body_statements := elna_rtl_declaration_get_body(procedure); (* Write .type _procedure_name, @function. *) _write_z(".type \0"); @@ -1322,7 +1355,7 @@ begin _elna_writer_instructions(body_statements); _write_z("\tret\n\0"); - procedure := _elna_tac_declaration_get_next(procedure); + procedure := elna_rtl_declaration_get_next(procedure); if procedure <> 0 then goto elna_writer_procedure_loop end @@ -1336,9 +1369,9 @@ var begin .elna_writer_variable_loop; if variable <> 0 then - name := _elna_tac_declaration_get_name(variable); - name_length := _elna_tac_declaration_get_length(variable); - size := _elna_tac_declaration_get_body(variable); + name := elna_rtl_declaration_get_name(variable); + name_length := elna_rtl_declaration_get_length(variable); + size := elna_rtl_declaration_get_body(variable); _write_z(".type \0"); _write_s(name, name_length); @@ -1351,12 +1384,30 @@ begin _write_i(size); _write_c('\n'); - variable := _elna_tac_declaration_get_next(variable); + variable := elna_rtl_declaration_get_next(variable); goto elna_writer_variable_loop end end; +proc elna_rtl_module_declaration(tac_module: Word); +var + result: Word; + current_part: Word; +begin + result := malloc(elna_rtl_module_size()); + + current_part := _elna_tac_module_get_data(tac_module); + current_part := elna_rtl_globals(current_part); + elna_rtl_module_set_data(result, current_part); + + current_part := _elna_tac_module_get_code(tac_module); + current_part := elna_rtl_procedures(current_part); + elna_rtl_module_set_code(result, current_part); + + return result +end; + proc _elna_writer_module(pair: Word); var compiler_strings_copy: Word; @@ -1364,10 +1415,10 @@ var current_byte: Word; current_part: Word; begin - _write_z(".globl _start\n\n\0"); + _write_z(".globl main\n\n\0"); _write_z(".section .data\n\0"); - current_part := _elna_tac_module_get_data(pair); + current_part := elna_rtl_module_get_data(pair); _elna_writer_variable(current_part); _write_z(".section .text\n\n\0"); @@ -1375,7 +1426,7 @@ begin _write_z(".type _load_byte, @function\n_load_byte:\n\tlb a0, (a0)\nret\n\n\0"); _write_z(".type _store_byte, @function\n_store_byte:\n\tsb a0, (a1)\nret\n\n\0"); - current_part := _elna_tac_module_get_code(pair); + current_part := elna_rtl_module_get_code(pair); _elna_writer_procedure(current_part); _write_z(".section .rodata\n.type strings, @object\nstrings: .ascii \0"); @@ -1401,10 +1452,8 @@ var integer_token: Word; integer_length: Word; result: Word; - literal_size: Word; begin - literal_size := _integer_literal_node_size(); - result := _allocate(literal_size); + result := malloc(_integer_literal_node_size()); integer_token := _elna_lexer_global_get_start(); integer_length := _elna_lexer_global_get_end(); @@ -1427,7 +1476,7 @@ begin integer_token := _integer_literal_node_get_value(integer_literal_node); integer_length := _integer_literal_node_get_length(integer_literal_node); - return _elna_tac_load_immediate(ElnaTacRegister.t0, integer_token, integer_length) + return _elna_tac_load_immediate(ElnaRtlRegister.t0, integer_token, integer_length) end; proc _elna_parser_character_literal(); @@ -1435,10 +1484,8 @@ var character: Word; character_length: Word; result: Word; - literal_size: Word; begin - literal_size := _character_literal_node_size(); - result := _allocate(literal_size); + result := malloc(_character_literal_node_size()); character := _elna_lexer_global_get_start(); character_length := _elna_lexer_global_get_end(); @@ -1460,16 +1507,7 @@ begin character := _character_literal_node_get_value(character_literal_node); character_length := _character_literal_node_get_length(character_literal_node); - return _elna_tac_load_immediate(ElnaTacRegister.t0, character, character_length) -end; - -proc _allocate(size: Word); -var - result: Word; -begin - result := memory_free_pointer; - memory_free_pointer := memory_free_pointer + size; - return result + return _elna_tac_load_immediate(ElnaRtlRegister.t0, character, character_length) end; proc _elna_parser_variable_expression(); @@ -1477,15 +1515,13 @@ var name: Word; name_token: Word; result: Word; - memory_size: Word; begin name := _elna_lexer_global_get_start(); name_token := _elna_lexer_global_get_end(); name_token := name_token - name; _elna_lexer_skip_token(); - memory_size := _variable_expression_size(); - result := _allocate(memory_size); + result := malloc(_variable_expression_size()); _node_set_kind(result, NodeKind.variable_expression); _variable_expression_set_name(result, name); @@ -1518,10 +1554,8 @@ var length: Word; token_start: Word; result: Word; - memory_size: Word; begin - memory_size := _string_literal_node_size(); - result := _allocate(memory_size); + result := malloc(_string_literal_node_size()); token_start := _elna_lexer_global_get_start(); length := _string_length(token_start); @@ -1547,10 +1581,10 @@ begin length := _string_literal_node_get_length(string_literal_node); offset := _add_string(token_start); - first_instruction := _elna_tac_load_address(ElnaTacRegister.t0, "strings", 7); - instruction := _elna_tac_load_immediate(ElnaTacRegister.t1, offset, 0); + first_instruction := _elna_tac_load_address(ElnaRtlRegister.t0, "strings", 7); + instruction := _elna_tac_load_immediate(ElnaRtlRegister.t1, offset, 0); _elna_tac_instruction_set_next(first_instruction, instruction); - next_instruction := _elna_tac_add(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + next_instruction := _elna_tac_add(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(instruction, next_instruction); return first_instruction @@ -1580,10 +1614,8 @@ end; proc _elna_parser_dereference_expression(simple_expression: Word); var result: Word; - memory_size: Word; begin - memory_size := _dereference_expression_size(); - result := _allocate(memory_size); + result := malloc(_dereference_expression_size()); _node_set_kind(result, NodeKind.dereference_expression); _dereference_expression_set_pointer(result, simple_expression); @@ -1637,7 +1669,6 @@ proc _elna_parser_unary_expression(); var token_kind: Word; result: Word; - memory_size: Word; operand: Word; operator: Word; begin @@ -1658,8 +1689,7 @@ begin if operator <> 0 then operand := result; - memory_size := _unary_expression_size(); - result := _allocate(memory_size); + result := malloc(_unary_expression_size()); _node_set_kind(result, NodeKind.unary_expression); _unary_expression_set_operand(result, operand); @@ -1697,15 +1727,15 @@ begin else first_instruction := _elna_tac_designator(operand, symbol_table, @is_address); if is_address then - instruction := _elna_tac_load_word(ElnaTacRegister.t0, ElnaTacRegister.t0, 0); + instruction := _elna_tac_load_word(ElnaRtlRegister.t0, ElnaRtlRegister.t0, 0); _elna_tac_instruction_set_next(first_instruction, instruction) end end; if operator = '-' then - instruction := _elna_tac_neg(ElnaTacRegister.t0, ElnaTacRegister.t0); + instruction := _elna_tac_neg(ElnaRtlRegister.t0, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(first_instruction, instruction) elsif operator = '~' then - instruction := _elna_tac_not(ElnaTacRegister.t0, ElnaTacRegister.t0); + instruction := _elna_tac_not(ElnaRtlRegister.t0, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(first_instruction, instruction) end; return first_instruction @@ -1716,7 +1746,6 @@ var lhs_node: Word; rhs_node: Word; token_kind: Word; - memory_size: Word; result: Word; begin lhs_node := _elna_parser_unary_expression(); @@ -1767,8 +1796,7 @@ begin rhs_node := _elna_parser_unary_expression() end; if rhs_node <> 0 then - memory_size := _binary_expression_size(); - result := _allocate(memory_size); + result := malloc(_binary_expression_size()); _node_set_kind(result, NodeKind.binary_expression); _binary_expression_set_lhs(result, lhs_node); @@ -1800,7 +1828,7 @@ begin first_instruction := _elna_tac_unary_expression(operand_node, symbol_table); (* Save the value of the left expression on the stack. *) - instruction := _elna_tac_store_word(ElnaTacRegister.t0, ElnaTacRegister.sp, 64); + instruction := _elna_tac_store_word(ElnaRtlRegister.t0, ElnaRtlRegister.sp, 64); _elna_tac_instruction_set_next(first_instruction, instruction); current_instruction := instruction; @@ -1810,67 +1838,67 @@ begin current_instruction := instruction; (* Load the left expression from the stack; *) - instruction := _elna_tac_load_word(ElnaTacRegister.t1, ElnaTacRegister.sp, 64); + instruction := _elna_tac_load_word(ElnaRtlRegister.t1, ElnaRtlRegister.sp, 64); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; if token_kind = ElnaLexerKind.plus then - instruction := _elna_tac_add(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_add(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.minus then - instruction := _elna_tac_sub(ElnaTacRegister.t0, ElnaTacRegister.t1, ElnaTacRegister.t0); + instruction := _elna_tac_sub(ElnaRtlRegister.t0, ElnaRtlRegister.t1, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.multiplication then - instruction := _elna_tac_mul(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_mul(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.and then - instruction := _elna_tac_and(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_and(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind._or then - instruction := _elna_tac_or(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_or(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind._xor then - instruction := _elna_tac_xor(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_xor(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.equals then - instruction := _elna_tac_xor(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_xor(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; - instruction := _elna_tac_seqz(ElnaTacRegister.t0, ElnaTacRegister.t0); + instruction := _elna_tac_seqz(ElnaRtlRegister.t0, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.remainder then - instruction := _elna_tac_rem(ElnaTacRegister.t0, ElnaTacRegister.t1, ElnaTacRegister.t0); + instruction := _elna_tac_rem(ElnaRtlRegister.t0, ElnaRtlRegister.t1, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.division then - instruction := _elna_tac_div(ElnaTacRegister.t0, ElnaTacRegister.t1, ElnaTacRegister.t0); + instruction := _elna_tac_div(ElnaRtlRegister.t0, ElnaRtlRegister.t1, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.less_than then - instruction := _elna_tac_slt(ElnaTacRegister.t0, ElnaTacRegister.t1, ElnaTacRegister.t0); + instruction := _elna_tac_slt(ElnaRtlRegister.t0, ElnaRtlRegister.t1, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.greater_than then - instruction := _elna_tac_slt(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_slt(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.less_equal then - instruction := _elna_tac_slt(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_slt(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; - instruction := _elna_tac_xor_immediate(ElnaTacRegister.t0, ElnaTacRegister.t0, 1); + instruction := _elna_tac_xor_immediate(ElnaRtlRegister.t0, ElnaRtlRegister.t0, 1); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.not_equal then - instruction := _elna_tac_xor(ElnaTacRegister.t0, ElnaTacRegister.t0, ElnaTacRegister.t1); + instruction := _elna_tac_xor(ElnaRtlRegister.t0, ElnaRtlRegister.t0, ElnaRtlRegister.t1); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; - instruction := _elna_tac_snez(ElnaTacRegister.t0, ElnaTacRegister.t0); + instruction := _elna_tac_snez(ElnaRtlRegister.t0, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction) elsif token_kind = ElnaLexerKind.greater_equal then - instruction := _elna_tac_slt(ElnaTacRegister.t0, ElnaTacRegister.t1, ElnaTacRegister.t0); + instruction := _elna_tac_slt(ElnaRtlRegister.t0, ElnaRtlRegister.t1, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; - instruction := _elna_tac_xor_immediate(ElnaTacRegister.t0, ElnaTacRegister.t0, 1); + instruction := _elna_tac_xor_immediate(ElnaRtlRegister.t0, ElnaRtlRegister.t0, 1); _elna_tac_instruction_set_next(current_instruction, instruction) end end; @@ -1916,10 +1944,8 @@ var result: Word; argument_number: Word; token_kind: Word; - call_size: Word; begin - call_size := _call_size(); - result := _allocate(call_size); + result := malloc(_call_size()); _node_set_kind(result, NodeKind.call); _statement_set_next(result, 0); @@ -1987,8 +2013,8 @@ begin (* Save the argument on the stack. *) stack_offset := argument_count * 4; - instruction := _elna_tac_store_word(ElnaTacRegister.t0, - ElnaTacRegister.sp, 116 - stack_offset); + instruction := _elna_tac_store_word(ElnaRtlRegister.t0, + ElnaRtlRegister.sp, 116 - stack_offset); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; @@ -2004,8 +2030,8 @@ begin stack_offset := argument_count * 4; (* Calculate the stack offset: 116 - (4 * argument_counter) *) - instruction := _elna_tac_load_word(ElnaTacRegister.a0 + argument_count, - ElnaTacRegister.sp, 116 - stack_offset); + instruction := _elna_tac_load_word(ElnaRtlRegister.a0 + argument_count, + ElnaRtlRegister.sp, 116 - stack_offset); _elna_tac_instruction_set_next(current_instruction, instruction); current_instruction := instruction; @@ -2025,7 +2051,6 @@ var token_kind: Word; label_name: Word; label_length: Word; - statement_size: Word; result: Word; begin _elna_lexer_skip_token(); @@ -2035,8 +2060,7 @@ begin label_length := _elna_lexer_global_get_end() - label_name; _elna_lexer_skip_token(); - statement_size := _goto_statement_size(); - result := _allocate(statement_size); + result := malloc(_goto_statement_size()); _node_set_kind(result, NodeKind.goto_statement); _statement_set_next(result, 0); @@ -2055,10 +2079,10 @@ var begin label_name := _goto_statement_get_label(parser_node); label_length := _goto_statement_get_length(parser_node); - label_with_dot := _allocate(label_length + 1); + label_with_dot := malloc(label_length + 1); _store_byte('.', label_with_dot); - _memcpy(label_with_dot + 1, label_name, label_length); + memcpy(label_with_dot + 1, label_name, label_length); return _elna_tac_jump(label_with_dot, label_length + 1) end; @@ -2068,7 +2092,6 @@ var token_kind: Word; label_name: Word; label_length: Word; - statement_size: Word; result: Word; begin _elna_lexer_skip_token(); @@ -2078,8 +2101,7 @@ begin label_length := _elna_lexer_global_get_end() - label_name; _elna_lexer_skip_token(); - statement_size := _label_declaration_size(); - result := _allocate(statement_size); + result := malloc(_label_declaration_size()); _node_set_kind(result, NodeKind.label_declaration); _statement_set_next(result, 0); @@ -2106,7 +2128,7 @@ var begin variable_offset := _parameter_info_get_offset(symbol); - return _elna_tac_add_immediate(ElnaTacRegister.t0, ElnaTacRegister.sp, variable_offset) + return _elna_tac_add_immediate(ElnaRtlRegister.t0, ElnaRtlRegister.sp, variable_offset) end; proc _elna_tac_global_designator(variable_expression: Word); @@ -2117,7 +2139,7 @@ begin name := _variable_expression_get_name(variable_expression); token_length := _variable_expression_get_length(variable_expression); - return _elna_tac_load_address(ElnaTacRegister.t0, name, token_length) + return _elna_tac_load_address(ElnaRtlRegister.t0, name, token_length) end; proc _elna_tac_enumeration_value(field_access_expression: Word); @@ -2140,7 +2162,7 @@ begin symbol := _symbol_table_lookup(@symbol_table_global, value_name, name_length); - enumeration_type := _type_info_get_type(symbol); + enumeration_type := _type_info_get__type(symbol); members := _enumeration_type_get_members(enumeration_type); members_length := _enumeration_type_get_length(enumeration_type); @@ -2157,13 +2179,13 @@ begin member_length := members + 4; member_length := member_length^; - if _string_compare(value_name, name_length, member_name, member_length) = 0 then + if string_compare(value_name, name_length, member_name, member_length) = 0 then members_length := members_length - 1; members := members + 8; counter := counter + 1; goto elna_tac_enumeration_value_members end; - instruction := _elna_tac_load_immediate(ElnaTacRegister.t0, counter, 0) + instruction := _elna_tac_load_immediate(ElnaRtlRegister.t0, counter, 0) end; return instruction end; @@ -2174,7 +2196,6 @@ var name: Word; name_token: Word; result: Word; - memory_size: Word; begin (* Skip dot. Read the enumeration value. *) _elna_lexer_skip_token(); @@ -2183,9 +2204,9 @@ begin name := _elna_lexer_global_get_start(); name_token := _elna_lexer_global_get_end(); name_token := name_token - name; + _elna_lexer_skip_token(); - memory_size := _field_access_expression_size(); - result := _allocate(memory_size); + result := malloc(_field_access_expression_size()); _node_set_kind(result, NodeKind.field_access_expression); _field_access_expression_set_aggregate(result, aggregate); @@ -2210,14 +2231,14 @@ begin if node_kind = NodeKind.dereference_expression then parser_node := _dereference_expression_get_pointer(parser_node); first_instruction := _elna_tac_simple_expression(parser_node, symbol_table, is_address); - instruction := _elna_tac_load_word(ElnaTacRegister.t0, ElnaTacRegister.t0, 0); + instruction := _elna_tac_load_word(ElnaRtlRegister.t0, ElnaRtlRegister.t0, 0); _elna_tac_instruction_set_next(first_instruction, instruction) elsif node_kind = NodeKind.field_access_expression then first_instruction := _elna_tac_enumeration_value(parser_node); is_address^ := 0 elsif node_kind = NodeKind.call then first_instruction := _elna_tac_call(parser_node, symbol_table); - instruction := _elna_tac_move(ElnaTacRegister.t0, ElnaTacRegister.a0); + instruction := _elna_tac_move(ElnaRtlRegister.t0, ElnaRtlRegister.a0); _elna_tac_instruction_set_next(first_instruction, instruction); is_address^ := 0 else @@ -2228,13 +2249,11 @@ end; proc _elna_parser_assign_statement(assignee: Word); var - statement_size: Word; result: Word; token_kind: Word; assignment_node: Word; begin - statement_size := _assign_statement_size(); - result := _allocate(statement_size); + result := malloc(_assign_statement_size()); _node_set_kind(result, NodeKind.assign_statement); _statement_set_next(result, 0); @@ -2262,7 +2281,7 @@ begin first_instruction := _elna_tac_designator(current_expression, symbol_table, @is_address); (* Save the assignee address on the stack. *) - current_instruction := _elna_tac_store_word(ElnaTacRegister.t0, ElnaTacRegister.sp, 60); + current_instruction := _elna_tac_store_word(ElnaRtlRegister.t0, ElnaRtlRegister.sp, 60); _elna_tac_instruction_set_next(first_instruction, current_instruction); (* Compile the assignment. *) @@ -2270,10 +2289,10 @@ begin instruction := _elna_tac_binary_expression(current_expression, symbol_table); _elna_tac_instruction_set_next(current_instruction, instruction); - current_instruction := _elna_tac_load_word(ElnaTacRegister.t1, ElnaTacRegister.sp, 60); + current_instruction := _elna_tac_load_word(ElnaRtlRegister.t1, ElnaRtlRegister.sp, 60); _elna_tac_instruction_set_next(instruction, current_instruction); - instruction := _elna_tac_store_word(ElnaTacRegister.t0, ElnaTacRegister.t1, 0); + instruction := _elna_tac_store_word(ElnaRtlRegister.t0, ElnaRtlRegister.t1, 0); _elna_tac_instruction_set_next(current_instruction, instruction); return first_instruction @@ -2284,7 +2303,6 @@ var token_kind: Word; returned: Word; label_length: Word; - statement_size: Word; result: Word; begin (* Skip "return" keyword and whitespace after it. *) @@ -2292,9 +2310,7 @@ begin _elna_lexer_read_token(@token_kind); returned := _elna_parser_binary_expression(); - - statement_size := _return_statement_size(); - result := _allocate(statement_size); + result := malloc(_return_statement_size()); _node_set_kind(result, NodeKind.return_statement); _statement_set_next(result, 0); @@ -2311,7 +2327,7 @@ var begin return_expression := _return_statement_get_returned(parser_node); first_instruction := _elna_tac_binary_expression(return_expression, symbol_table); - instruction := _elna_tac_move(ElnaTacRegister.a0, ElnaTacRegister.t0); + instruction := _elna_tac_move(ElnaRtlRegister.a0, ElnaRtlRegister.t0); _elna_tac_instruction_set_next(first_instruction, instruction); return first_instruction end; @@ -2340,13 +2356,11 @@ end; proc _elna_parser_conditional_statements(); var - conditional_size: Word; token_kind: Word; current_node: Word; result: Word; begin - conditional_size := _conditional_statements_size(); - result := _allocate(conditional_size); + result := malloc(_conditional_statements_size()); (* Skip "if", "while" or "elsif". *) _elna_lexer_skip_token(); @@ -2381,7 +2395,7 @@ begin condition_label := label_counter; label_counter := label_counter + 1; - current_instruction := _elna_tac_beqz(ElnaTacRegister.t0, condition_label, 0); + current_instruction := _elna_tac_beqz(ElnaRtlRegister.t0, condition_label, 0); _elna_tac_instruction_set_next(first_instruction, current_instruction); current_node := _conditional_statements_get_statements(parser_node); @@ -2404,13 +2418,11 @@ proc _elna_parser_if_statement(); var current_node: Word; result: Word; - object_size: Word; token_kind: Word; previous_conditional: Word; next_conditional: Word; begin - object_size := _if_statement_size(); - result := _allocate(object_size); + result := malloc(_if_statement_size()); _node_set_kind(result, NodeKind.if_statement); _statement_set_next(result, 0); @@ -2615,7 +2627,6 @@ var field_length: Word; field_type: Word; token_kind: Word; - type_expression_size: Word; result: Word; previous_entry: Word; begin @@ -2628,7 +2639,7 @@ begin goto elna_parser_record_type_expression_end end; .elna_parser_record_type_expression_loop; - entry := _allocate(16); + entry := malloc(16); member_count := member_count + 1; field_name := _elna_lexer_global_get_start(); @@ -2668,8 +2679,7 @@ begin .elna_parser_record_type_expression_end; _elna_lexer_skip_token(); - type_expression_size := _enumeration_type_expression_size(); - result := _allocate(type_expression_size); + result := malloc(_enumeration_type_expression_size()); _node_set_kind(result, NodeKind.record_type_expression); _record_type_expression_set_members(result, memory_start); @@ -2686,7 +2696,6 @@ var memory_start: Word; member_count: Word; result: Word; - type_expression_size: Word; entry: Word; previous_entry: Word; begin @@ -2699,7 +2708,7 @@ begin goto elna_parser_enumeration_type_expression_end end; .elna_parser_enumeration_type_expression_loop; - entry := _allocate(12); + entry := malloc(12); member_count := member_count + 1; enumeration_name := _elna_lexer_global_get_start(); @@ -2732,8 +2741,7 @@ begin .elna_parser_enumeration_type_expression_end; _elna_lexer_skip_token(); - type_expression_size := _enumeration_type_expression_size(); - result := _allocate(type_expression_size); + result := malloc(_enumeration_type_expression_size()); _node_set_kind(result, NodeKind.enumeration_type_expression); _enumeration_type_expression_set_members(result, memory_start); @@ -2759,19 +2767,16 @@ var result: Word; memory_start: Word; member_count: Word; - member_array_size: Word; member_array_start: Word; member_array_current: Word; begin - member_array_size := _enumeration_type_size(); - result := _allocate(member_array_size); + result := malloc(_enumeration_type_size()); memory_start := _enumeration_type_expression_get_members(parser_node); member_count := _enumeration_type_expression_get_length(parser_node); (* Copy the list of enumeration members into an array of strings. *) - member_array_size := member_count * 8; - member_array_start := _allocate(member_array_size); + member_array_start := malloc(member_count * 8); member_array_current := member_array_start; .elna_name_type_enumeration_loop; @@ -2803,18 +2808,15 @@ var result: Word; memory_start: Word; member_count: Word; - member_array_size: Word; member_array_start: Word; member_array_current: Word; begin - member_array_size := _record_type_size(); - result := _allocate(member_array_size); + result := malloc(_record_type_size()); memory_start := _record_type_expression_get_members(parser_node); member_count := _record_type_expression_get_length(parser_node); - member_array_size := member_count * 12; - member_array_start := _allocate(member_array_size); + member_array_start := malloc(member_count * 12); member_array_current := member_array_start; .elna_name_type_record_loop; @@ -2847,13 +2849,11 @@ end; proc _elna_parser_named_type_expression(); var - type_expression_size: Word; result: Word; type_name: Word; name_length: Word; begin - type_expression_size := _named_type_expression_size(); - result := _allocate(type_expression_size); + result := malloc(_named_type_expression_size()); _node_set_kind(result, NodeKind.named_type_expression); type_name := _elna_lexer_global_get_start(); @@ -2897,7 +2897,7 @@ begin name_length := _named_type_expression_get_length(parser_node); result := _symbol_table_lookup(@symbol_table_global, type_name, name_length); - result := _type_info_get_type(result) + result := _type_info_get__type(result) elsif token_kind = NodeKind.enumeration_type_expression then result := _elna_name_type_enumeration(parser_node) elsif token_kind = NodeKind.record_type_expression then @@ -2907,12 +2907,6 @@ begin return result end; -proc _type_info_get_type(this: Word); -begin - this := this + 4; - return this^ -end; - (** * Parameters: * parameter_index - Parameter index. @@ -2920,39 +2914,25 @@ end; proc _parameter_info_create(parameter_index: Word); var offset: Word; - current_word: Word; result: Word; begin - result := _allocate(8); - current_word := result; - current_word^ := InfoKind.parameter_info; - - current_word := current_word + 4; + result := malloc(_parameter_info_size()); + _info_set_kind(result, InfoKind.parameter_info); (* Calculate the stack offset: 88 - (4 * parameter_counter) *) offset := parameter_index * 4; - current_word^ := 88 - offset; + _parameter_info_set_offset(result, 88 - offset); return result end; -proc _parameter_info_get_offset(this: Word); -begin - this := this + 4; - return this^ -end; - proc _type_info_create(type_representation: Word); var result: Word; - current_word: Word; begin - result := _allocate(8); - current_word := result; - current_word^ := InfoKind.type_info; - - current_word := current_word + 4; - current_word^ := type_representation; + result := malloc(_type_info_size()); + _info_set_kind(result, InfoKind.type_info); + _type_info_set__type(result, type_representation); return result end; @@ -2963,17 +2943,13 @@ end; *) proc _temporary_info_create(temporary_index: Word); var - offset: Word; - current_word: Word; result: Word; begin - result := _allocate(8); - current_word := result; - current_word^ := InfoKind.temporary_info; - current_word := current_word + 4; + result := malloc(_temporary_info_size()); + _info_set_kind(result, InfoKind.temporary_info); (* Calculate the stack offset: 4 * variable_counter. *) - current_word^ := temporary_index * 4; + _temporary_info_set_offset(result, temporary_index * 4); return result end; @@ -2984,25 +2960,15 @@ end; *) proc _procedure_info_create(symbol_table: Word); var - current_word: Word; result: Word; begin - result := _allocate(8); - current_word := result; - current_word^ := InfoKind.procedure_info; - current_word := current_word + 4; - - current_word^ := symbol_table; + result := malloc(_procedure_info_size()); + _info_set_kind(result, InfoKind.procedure_info); + _procedure_info_set_symbol_table(result, symbol_table); return result end; -proc _procedure_info_get_symbol_table(this: Word); -begin - this := this + 4; - return this^ -end; - (** * Parameters: * parameter_index - Parameter index. @@ -3059,11 +3025,9 @@ var name_length: Word; token_kind: Word; result: Word; - declaration_size: Word; parameter_head: Word; begin - declaration_size := _procedure_declaration_size(); - result := _allocate(declaration_size); + result := malloc(_procedure_declaration_size()); _node_set_kind(result, NodeKind.procedure_declaration); _declaration_set_next(result, 0); @@ -3153,8 +3117,8 @@ begin symbol_info := _parameter_info_get_offset(symbol_info); - instruction := _elna_tac_store_word(ElnaTacRegister.a0 + parameter_counter, - ElnaTacRegister.sp, symbol_info); + instruction := _elna_tac_store_word(ElnaRtlRegister.a0 + parameter_counter, + ElnaRtlRegister.sp, symbol_info); if first_instruction = 0 then first_instruction := instruction else @@ -3170,6 +3134,47 @@ begin return first_instruction end; +proc elna_rtl_global_declaration(tac_declaration: Word); +var + name: Word; + length: Word; + body: Word; + result: Word; +begin + result := malloc(elna_rtl_declaration_size()); + name := _elna_tac_declaration_get_name(tac_declaration); + length := _elna_tac_declaration_get_length(tac_declaration); + body := _elna_tac_declaration_get_body(tac_declaration); + + elna_rtl_declaration_set_next(result, 0); + elna_rtl_declaration_set_name(result, name); + elna_rtl_declaration_set_length(result, length); + elna_rtl_declaration_set_body(result, body); + + return result +end; + +proc elna_rtl_procedure_declaration(tac_declaration: Word); +var + name: Word; + length: Word; + body: Word; + result: Word; +begin + result := malloc(elna_rtl_declaration_size()); + name := _elna_tac_declaration_get_name(tac_declaration); + length := _elna_tac_declaration_get_length(tac_declaration); + body := _elna_tac_declaration_get_body(tac_declaration); + body := elna_rtl_instructions(body); + + elna_rtl_declaration_set_next(result, 0); + elna_rtl_declaration_set_name(result, name); + elna_rtl_declaration_set_length(result, length); + elna_rtl_declaration_set_body(result, body); + + return result +end; + proc _elna_tac_procedure_declaration(parser_node: Word); var name_pointer: Word; @@ -3183,8 +3188,7 @@ var result: Word; result_size: Word; begin - result_size := _elna_tac_declaration_size(); - result := _allocate(result_size); + result := malloc(_elna_tac_declaration_size()); _elna_tac_declaration_set_next(result, 0); @@ -3248,6 +3252,62 @@ begin return result end; +proc elna_rtl_globals(tac_procedure: Word); +var + current_copy: Word; + next_copy: Word; + first_copy: Word; +begin + if tac_procedure <> 0 then + first_copy := elna_rtl_global_declaration(tac_procedure); + tac_procedure := _elna_tac_declaration_get_next(tac_procedure) + else + first_copy := 0; + end; + current_copy := first_copy; + + .elna_rtl_globals_start; + + if tac_procedure <> 0 then + next_copy := elna_rtl_global_declaration(tac_procedure); + + tac_procedure := _elna_tac_declaration_get_next(tac_procedure); + elna_rtl_declaration_set_next(current_copy, next_copy); + current_copy := next_copy; + goto elna_rtl_globals_start + end; + + return first_copy +end; + +proc elna_rtl_procedures(tac_procedure: Word); +var + current_copy: Word; + next_copy: Word; + first_copy: Word; +begin + if tac_procedure <> 0 then + first_copy := elna_rtl_procedure_declaration(tac_procedure); + tac_procedure := _elna_tac_declaration_get_next(tac_procedure) + else + first_copy := 0; + end; + current_copy := first_copy; + + .elna_rtl_procedures_start; + + if tac_procedure <> 0 then + next_copy := elna_rtl_procedure_declaration(tac_procedure); + + tac_procedure := _elna_tac_declaration_get_next(tac_procedure); + elna_rtl_declaration_set_next(current_copy, next_copy); + current_copy := next_copy; + goto elna_rtl_procedures_start + end; + + return first_copy +end; + proc _elna_tac_procedures(parser_node: Word); var result: Word; @@ -3299,7 +3359,6 @@ var name_length: Word; parser_node: Word; result: Word; - declaration_size: Word; begin _elna_lexer_read_token(@token_kind); type_name := _elna_lexer_global_get_start(); @@ -3310,8 +3369,7 @@ begin _elna_lexer_skip_token(); parser_node := _elna_parser_type_expression(); - declaration_size := _type_declaration_size(); - result := _allocate(declaration_size); + result := malloc(_type_declaration_size()); _node_set_kind(result, NodeKind.type_declaration); _declaration_set_next(result, 0); @@ -3387,7 +3445,6 @@ var name_length: Word; variable_type: Word; result: Word; - declaration_size: Word; begin _elna_lexer_read_token(@token_kind); @@ -3398,10 +3455,9 @@ begin _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); - variable_type := _elna_parser_type_expression(); - declaration_size := _variable_declaration_size(); - result := _allocate(declaration_size); + variable_type := _elna_parser_type_expression(); + result := malloc(_variable_declaration_size()); _node_set_kind(result, NodeKind.variable_declaration); _declaration_set_next(result, 0); @@ -3418,10 +3474,8 @@ var name_length: Word; variable_type: Word; result: Word; - result_size: Word; begin - result_size := _elna_tac_declaration_size(); - result := _allocate(result_size); + result := malloc(_elna_tac_declaration_size()); _elna_tac_declaration_set_next(result, 0); @@ -3435,7 +3489,7 @@ begin name := _named_type_expression_get_name(variable_type); name_length := _named_type_expression_get_length(variable_type); - if _string_compare("Array", 5, name, name_length) then + if string_compare("Array", 5, name, name_length) then (* Else we assume this is a zeroed 4096 bytes big array. *) _elna_tac_declaration_set_body(result, 4096) else @@ -3446,7 +3500,6 @@ end; proc _elna_tac_type_field(name_pointer: Word, name_length: Word, field_pointer: Word, field_offset: Word); var - result_size: Word; first_result: Word; second_result: Word; new_name: Word; @@ -3456,49 +3509,48 @@ var name_target: Word; next_instruction: Word; begin - result_size := _elna_tac_declaration_size(); field_length := field_pointer + 4; field_length := field_length^; new_length := field_length + name_length; new_length := new_length + 5; - first_result := _allocate(result_size); + first_result := malloc(_elna_tac_declaration_size()); _elna_tac_declaration_set_next(first_result, 0); - new_name := _allocate(new_length); + new_name := malloc(new_length); name_target := new_name; - _memcpy(name_target, name_pointer, name_length); + memcpy(name_target, name_pointer, name_length); name_target := name_target + name_length; - _memcpy(name_target, "_get_", 5); + memcpy(name_target, "_get_", 5); name_target := name_target + 5; - _memcpy(name_target, field_pointer^, field_length); + memcpy(name_target, field_pointer^, field_length); _elna_tac_declaration_set_name(first_result, new_name); _elna_tac_declaration_set_length(first_result, new_length); - instruction := _elna_tac_add_immediate(ElnaTacRegister.a0, ElnaTacRegister.a0, field_offset, 0); - next_instruction := _elna_tac_load_word(ElnaTacRegister.a0, ElnaTacRegister.a0, 0); + instruction := _elna_tac_add_immediate(ElnaRtlRegister.a0, ElnaRtlRegister.a0, field_offset, 0); + next_instruction := _elna_tac_load_word(ElnaRtlRegister.a0, ElnaRtlRegister.a0, 0); _elna_tac_instruction_set_next(instruction, next_instruction); _elna_tac_declaration_set_body(first_result, instruction); - second_result := _allocate(result_size); + second_result := malloc(_elna_tac_declaration_size()); _elna_tac_declaration_set_next(second_result, 0); - new_name := _allocate(new_length); + new_name := malloc(new_length); name_target := new_name; - _memcpy(name_target, name_pointer, name_length); + memcpy(name_target, name_pointer, name_length); name_target := name_target + name_length; - _memcpy(name_target, "_set_", 5); + memcpy(name_target, "_set_", 5); name_target := name_target + 5; - _memcpy(name_target, field_pointer^, field_length); + memcpy(name_target, field_pointer^, field_length); _elna_tac_declaration_set_name(second_result, new_name); _elna_tac_declaration_set_length(second_result, new_length); - instruction := _elna_tac_add_immediate(ElnaTacRegister.a0, ElnaTacRegister.a0, field_offset, 0); - next_instruction := _elna_tac_store_word(ElnaTacRegister.a1, ElnaTacRegister.a0, 0); + instruction := _elna_tac_add_immediate(ElnaRtlRegister.a0, ElnaRtlRegister.a0, field_offset, 0); + next_instruction := _elna_tac_store_word(ElnaRtlRegister.a1, ElnaRtlRegister.a0, 0); _elna_tac_instruction_set_next(instruction, next_instruction); _elna_tac_declaration_set_body(second_result, instruction); @@ -3509,7 +3561,6 @@ end; proc _elna_tac_type_record(name_pointer: Word, name_length: Word, type_representation: Word, current_result: Word); var - result_size: Word; first_result: Word; result: Word; type_size: Word; @@ -3520,8 +3571,7 @@ var field_offset: Word; field_pointer: Word; begin - result_size := _elna_tac_declaration_size(); - first_result := _allocate(result_size); + first_result := malloc(_elna_tac_declaration_size()); result := 0; (* Debug. Error stream output. @@ -3529,15 +3579,15 @@ begin type_size := _type_get_size(type_representation); new_length := name_length + 5; - new_name := _allocate(new_length); + new_name := malloc(new_length); - _memcpy(new_name, name_pointer, name_length); - _memcpy(new_name + name_length, "_size", 5); + memcpy(new_name, name_pointer, name_length); + memcpy(new_name + name_length, "_size", 5); _elna_tac_declaration_set_name(first_result, new_name); _elna_tac_declaration_set_length(first_result, new_length); - instruction := _elna_tac_load_immediate(ElnaTacRegister.a0, type_size, 0); + instruction := _elna_tac_load_immediate(ElnaRtlRegister.a0, type_size, 0); _elna_tac_declaration_set_body(first_result, instruction); field_count := _record_type_get_length(type_representation); @@ -3584,7 +3634,7 @@ begin name_length := _declaration_get_length(parser_node); symbol := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length); - info_type := _type_info_get_type(symbol); + info_type := _type_info_get__type(symbol); type_kind := _type_get_kind(info_type); if type_kind = TypeKind._record then @@ -3679,11 +3729,9 @@ end; proc _elna_parser_module_declaration(); var parser_node: Word; - declaration_size: Word; result: Word; begin - declaration_size := _module_declaration_size(); - result := _allocate(declaration_size); + result := malloc(_module_declaration_size()); _node_set_kind(result, NodeKind.module_declaration); @@ -3819,12 +3867,14 @@ proc _compile(); var parser_node: Word; tac: Word; + rtl: 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); - _elna_writer_module(tac) + rtl := elna_rtl_module_declaration(tac); + _elna_writer_module(rtl) end; (** @@ -3878,7 +3928,7 @@ begin goto symbol_table_lookup_repeat end; (* If names don't match, exit and return nil. *) - if _memcmp(symbol_name, current_name, name_length) then + if memcmp(symbol_name, current_name, name_length) then goto symbol_table_lookup_repeat end; (* Otherwise, the symbol is found. *) @@ -3961,7 +4011,7 @@ begin (* Set the table length to 0. *) symbol_table_global := 0; - current_type := _allocate(8); + current_type := malloc(_type_size()); _type_set_kind(current_type, TypeKind.primitive); _type_set_size(current_type, 4); @@ -4474,14 +4524,14 @@ begin return _elna_lexer_get_transition(current_state, character_class) end; -proc _string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word); +proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word); var result: Word; begin result := 0; if lhs_length = rhs_length then - result := _memcmp(lhs_pointer, rhs_pointer, lhs_length); + result := memcmp(lhs_pointer, rhs_pointer, lhs_length); result := result = 0 end; return result @@ -4495,37 +4545,37 @@ begin result := ElnaLexerKind.identifier; token_length := position_end - position_start; - if _string_compare(position_start, token_length, "const", 5) then + if string_compare(position_start, token_length, "const", 5) then result := ElnaLexerKind._const - elsif _string_compare(position_start, token_length, "var", 3) then + elsif string_compare(position_start, token_length, "var", 3) then result := ElnaLexerKind._var - elsif _string_compare(position_start, token_length, "proc", 4) then + elsif string_compare(position_start, token_length, "proc", 4) then result := ElnaLexerKind._proc - elsif _string_compare(position_start, token_length, "type", 4) then + elsif string_compare(position_start, token_length, "type", 4) then result := ElnaLexerKind._type - elsif _string_compare(position_start, token_length, "begin", 5) then + elsif string_compare(position_start, token_length, "begin", 5) then result := ElnaLexerKind._begin - elsif _string_compare(position_start, token_length, "end", 3) then + elsif string_compare(position_start, token_length, "end", 3) then result := ElnaLexerKind._end - elsif _string_compare(position_start, token_length, "return", 6) then + elsif string_compare(position_start, token_length, "return", 6) then result := ElnaLexerKind._return - elsif _string_compare(position_start, token_length, "goto", 4) then + elsif string_compare(position_start, token_length, "goto", 4) then result := ElnaLexerKind._goto - elsif _string_compare(position_start, token_length, "if", 2) then + elsif string_compare(position_start, token_length, "if", 2) then result := ElnaLexerKind._if - elsif _string_compare(position_start, token_length, "while", 5) then + elsif string_compare(position_start, token_length, "while", 5) then result := ElnaLexerKind._while - elsif _string_compare(position_start, token_length, "then", 4) then + elsif string_compare(position_start, token_length, "then", 4) then result := ElnaLexerKind._then - elsif _string_compare(position_start, token_length, "else", 4) then + elsif string_compare(position_start, token_length, "else", 4) then result := ElnaLexerKind._else - elsif _string_compare(position_start, token_length, "elsif", 5) then + elsif string_compare(position_start, token_length, "elsif", 5) then result := ElnaLexerKind._elsif - elsif _string_compare(position_start, token_length, "record", 6) then + elsif string_compare(position_start, token_length, "record", 6) then result := ElnaLexerKind._record - elsif _string_compare(position_start, token_length, "or", 2) then + elsif string_compare(position_start, token_length, "or", 2) then result := ElnaLexerKind._or - elsif _string_compare(position_start, token_length, "xor", 2) then + elsif string_compare(position_start, token_length, "xor", 2) then result := ElnaLexerKind._xor end; return result @@ -4739,15 +4789,14 @@ end; proc _initialize_global_state(); begin compiler_strings_position := @compiler_strings; - memory_free_pointer := _mmap(4194304); - source_code := _mmap(495616); - symbol_table_store := _mmap(495616) + source_code := malloc(495616); + symbol_table_store := malloc(4194304) end; (* * Entry point. *) -proc _start(); +proc main(); var last_read: Word; offset: Word; diff --git a/boot/stage16/linker.arg b/boot/stage16/linker.arg new file mode 100644 index 0000000..e69de29 diff --git a/boot/stage2.elna b/boot/stage2/cl.elna similarity index 100% rename from boot/stage2.elna rename to boot/stage2/cl.elna diff --git a/boot/stage3.elna b/boot/stage3/cl.elna similarity index 100% rename from boot/stage3.elna rename to boot/stage3/cl.elna diff --git a/boot/stage4.elna b/boot/stage4/cl.elna similarity index 100% rename from boot/stage4.elna rename to boot/stage4/cl.elna diff --git a/boot/stage5.elna b/boot/stage5/cl.elna similarity index 100% rename from boot/stage5.elna rename to boot/stage5/cl.elna diff --git a/boot/stage6.elna b/boot/stage6/cl.elna similarity index 100% rename from boot/stage6.elna rename to boot/stage6/cl.elna diff --git a/boot/stage7.elna b/boot/stage7/cl.elna similarity index 100% rename from boot/stage7.elna rename to boot/stage7/cl.elna diff --git a/boot/stage8.elna b/boot/stage8/cl.elna similarity index 100% rename from boot/stage8.elna rename to boot/stage8/cl.elna diff --git a/boot/stage9.elna b/boot/stage9/cl.elna similarity index 100% rename from boot/stage9.elna rename to boot/stage9/cl.elna diff --git a/boot/symbol.s b/boot/symbol.s deleted file mode 100644 index fdf4ad2..0000000 --- a/boot/symbol.s +++ /dev/null @@ -1,297 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public License, -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at https://mozilla.org/MPL/2.0/. - -.global symbol_table -.global symbol_table_build, symbol_table_lookup, symbol_table_enter, symbol_table_dump -.global symbol_table_make_pointer, symbol_table_make_parameter, symbol_table_make_local, symbol_table_make_procedure - -.include "boot/definitions.inc" - -.equ SYMBOL_PRIME, 1543 - -.section .rodata - -.type symbol_builtin_name_int, @object -symbol_builtin_name_int: .ascii "Int" -.type symbol_builtin_name_word, @object -symbol_builtin_name_word: .ascii "Word" -.type symbol_builtin_name_byte, @object -symbol_builtin_name_byte: .ascii "Byte" -.type symbol_builtin_name_char, @object -symbol_builtin_name_char: .ascii "Char" -.type symbol_builtin_name_bool, @object -symbol_builtin_name_bool: .ascii "Bool" - -# Every type info starts with a word describing what type it is. - -# Primitive types have only type size. -.type symbol_builtin_type_int, @object -symbol_builtin_type_int: .word TYPE_PRIMITIVE - .word 4 -.type symbol_builtin_type_word, @object -symbol_builtin_type_word: .word TYPE_PRIMITIVE - .word 4 -.type symbol_builtin_type_byte, @object -symbol_builtin_type_byte: .word TYPE_PRIMITIVE - .word 1 -.type symbol_builtin_type_char, @object -symbol_builtin_type_char: .word TYPE_PRIMITIVE - .word 1 -.type symbol_builtin_type_bool, @object -symbol_builtin_type_bool: .word TYPE_PRIMITIVE - .word 1 - -.section .bss - -# The first word of the symbol table is its length. -# Then a list of type infos follows: -# -# record -# name: String -# info: ^TypeInfo -# end -.type symbol_table, @object -symbol_table: .zero SYMBOL_PRIME - -.section .text - -# Prints the list of symbols in the table. -.type symbol_table_dump, @function -symbol_table_dump: - # Prologue. - addi sp, sp, -32 - sw ra, 28(sp) - sw s0, 24(sp) - addi s0, sp, 32 - - sw s1, 20(sp) # Current symbol in the table. - sw s2, 16(sp) # Symbol table length. - - la s1, symbol_table - lw s2, 0(s1) - addi s1, s1, 4 # Advance to the first symbol in the table. - -.Lsymbol_table_dump_loop: - beqz s2, .Lsymbol_table_dump_end - - # Compare string lengths. - lw a0, 4(s1) - lw a1, 0(s1) - call _write_error - - addi s1, s1, 12 - addi s2, s2, -1 - j .Lsymbol_table_dump_loop - -.Lsymbol_table_dump_end: - lw s1, 20(sp) - lw s2, 16(sp) - - # Epilogue. - lw ra, 28(sp) - lw s0, 24(sp) - addi sp, sp, 32 - ret - -# Searches for a symbol by name. -# -# Parameters: -# a0 - Length of the symbol to search. -# a1 - Pointer to the symbol name. -# -# Sets a0 to the symbol info pointer or 0 if the symbol has not been found. -.type symbol_table_lookup, @function -symbol_table_lookup: - # Prologue. - addi sp, sp, -32 - sw ra, 28(sp) - sw s0, 24(sp) - addi s0, sp, 32 - - sw s1, 20(sp) # Current symbol in the table. - sw s2, 16(sp) # Symbol table length. - sw s3, 12(sp) # Length of the symbol to search. - sw s4, 8(sp) # Pointer to the symbol to search. - - mv s3, a0 - mv s4, a1 - - la s1, symbol_table - lw s2, 0(s1) - addi s1, s1, 4 # Advance to the first symbol in the table. - -.Lsymbol_table_lookup_loop: - beqz s2, .Lsymbol_table_lookup_not_found - - # Compare string lengths. - mv a0, s3 - mv a1, s4 - lw a2, 0(s1) - lw a3, 4(s1) - call _string_equal - - beqz a0, .Lsymbol_table_lookup_continue - - lw a0, 8(s1) # Pointer to the symbol. - j .Lsymbol_table_lookup_end - -.Lsymbol_table_lookup_continue: - addi s1, s1, 12 - addi s2, s2, -1 - j .Lsymbol_table_lookup_loop - -.Lsymbol_table_lookup_not_found: - li a0, 0 - -.Lsymbol_table_lookup_end: - lw s1, 20(sp) - lw s2, 16(sp) - lw s3, 12(sp) - lw s4, 8(sp) - - # Epilogue. - lw ra, 28(sp) - lw s0, 24(sp) - addi sp, sp, 32 - ret - -# Creates a pointer type. -# -# Parameters: -# a0 - Pointer to the base type. -# a1 - Output memory. -# -# Sets a0 to the size of newly created type in bytes. -.type symbol_table_make_pointer, @function -symbol_table_make_pointer: - li t0, TYPE_POINTER - sw t0, 0(a1) - sw a0, 4(a1) - - li a0, 8 - ret - -# Creates a parameter info. -# -# Parameters: -# a0 - Pointer to the parameter type. -# a1 - Parameter offset. -# a2 - Output memory. -# -# Sets a0 to the size of newly created info object in bytes. -.type symbol_table_make_parameter, @function -symbol_table_make_parameter: - li t0, INFO_PARAMETER - sw t0, 0(a2) - sw a0, 4(a2) - sw a1, 8(a2) - - li a0, 12 - ret - -# Creates a local variable info. -# -# Parameters: -# a0 - Pointer to the variable type. -# a1 - Variable stack offset. -# a2 - Output memory. -# -# Sets a0 to the size of newly created info object in bytes. -.type symbol_table_make_local, @function -symbol_table_make_local: - li t0, INFO_LOCAL - sw t0, 0(a2) - sw a0, 4(a2) - sw a1, 8(a2) - - li a0, 12 - ret - -# Creates a procedure type and procedure info objects refering the type. -# -# Parameters: -# a0 - Output memory. -# -# Sets a0 to the size of newly created info object in bytes. -.type symbol_table_make_procedure, @function -symbol_table_make_procedure: - li t0, TYPE_PROCEDURE - sw t0, 8(a0) - - li t0, INFO_PROCEDURE - sw t0, 0(a0) - sw a0, 4(a0) # Procedure type stored in the same memory segment. - - li a0, 12 - ret - -# Inserts a symbol into the table. -# -# Parameters: -# a0 - Symbol name length. -# a1 - Symbol name pointer. -# a2 - Symbol pointer. -.type symbol_table_enter, @function -symbol_table_enter: - la t0, symbol_table - - lw t1, 0(t0) # Current table length. - li t2, 12 # Calculate the offset to the next entry. - mul t2, t1, t2 - addi t2, t2, 4 - add t2, t0, t2 - - sw a0, 0(t2) - sw a1, 4(t2) - sw a2, 8(t2) - - addi t1, t1, 1 # Save the new length. - sw t1, 0(t0) - - ret - -# Build the initial symbols. -# -# Sets a0 to the pointer to the global symbol table. -.type symbol_build, @function -symbol_table_build: - # Prologue. - addi sp, sp, -16 - sw ra, 12(sp) - sw s0, 8(sp) - addi s0, sp, 16 - - la a0, symbol_table - addi t0, a0, 4 - - li a0, 3 # Length of the word "Int". - la a1, symbol_builtin_name_int - la a2, symbol_builtin_type_int - call symbol_table_enter - - li a0, 4 # Length of the word "Word". - la a1, symbol_builtin_name_word - la a2, symbol_builtin_type_word - call symbol_table_enter - - li a0, 4 # Length of the word "Byte". - la a1, symbol_builtin_name_byte - la a2, symbol_builtin_type_byte - call symbol_table_enter - - li a0, 4 # Length of the word "Char". - la a1, symbol_builtin_name_char - la a2, symbol_builtin_type_char - call symbol_table_enter - - li a0, 4 # Length of the word "Bool". - la a1, symbol_builtin_name_bool - la a2, symbol_builtin_type_bool - call symbol_table_enter - - # Epilogue. - lw ra, 12(sp) - lw s0, 8(sp) - addi sp, sp, 16 - ret