Move stages into subdirectories
This commit is contained in:
59
Rakefile
59
Rakefile
@@ -4,19 +4,18 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'open3'
|
require 'open3'
|
||||||
|
require 'pathname'
|
||||||
require 'rake/clean'
|
require 'rake/clean'
|
||||||
|
|
||||||
STAGES = Dir.glob('boot/stage*.elna')
|
STAGES = Dir.glob('boot/stage*')
|
||||||
.collect { |stage| File.basename stage, '.elna' }
|
.collect { |stage| File.basename stage }
|
||||||
.sort { |a, b| a.delete_prefix('stage').to_i <=> b.delete_prefix('stage').to_i }
|
.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'
|
CLEAN.include 'build/boot', 'build/valid'
|
||||||
|
|
||||||
directory 'build/boot'
|
def compile(*arguments)
|
||||||
directory 'build/valid'
|
sh(ENV.fetch('CC', 'gcc'), '-fpie', '-g', *arguments)
|
||||||
|
|
||||||
def compile(input, output)
|
|
||||||
sh ENV.fetch('CC', 'gcc'), '-nostdlib', '-fpie', '-g', '-o', output, input
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(exe)
|
def run(exe)
|
||||||
@@ -26,9 +25,9 @@ end
|
|||||||
task default: :boot
|
task default: :boot
|
||||||
|
|
||||||
desc 'Final stage'
|
desc 'Final stage'
|
||||||
task boot: "build/valid/#{STAGES.last}"
|
task boot: "build/valid/#{STAGES.last}/cl"
|
||||||
task boot: "build/valid/#{STAGES.last}.s"
|
task boot: "build/valid/#{STAGES.last}/cl.s"
|
||||||
task boot: "boot/#{STAGES.last}.elna" do |t|
|
task boot: "boot/#{STAGES.last}/cl.elna" do |t|
|
||||||
groupped = t.prerequisites.group_by { |stage| File.extname stage }.transform_values(&:first)
|
groupped = t.prerequisites.group_by { |stage| File.extname stage }.transform_values(&:first)
|
||||||
exe = groupped['']
|
exe = groupped['']
|
||||||
expected = groupped['.s']
|
expected = groupped['.s']
|
||||||
@@ -81,16 +80,33 @@ task :convert do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+$/ => ->(match) {
|
rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+\/cl$/ => ->(match) {
|
||||||
"#{match}.s"
|
"#{match}.o"
|
||||||
} do |t|
|
} 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
|
end
|
||||||
|
|
||||||
STAGES.each do |stage|
|
STAGES.each do |stage|
|
||||||
previous = stage.delete_prefix('stage').to_i.pred
|
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
|
exe, source = t.prerequisites
|
||||||
|
|
||||||
cat_arguments = ['cat', source]
|
cat_arguments = ['cat', source]
|
||||||
@@ -99,7 +115,7 @@ STAGES.each do |stage|
|
|||||||
IO.copy_stream last_stdout, t.name
|
IO.copy_stream last_stdout, t.name
|
||||||
end
|
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
|
exe, source = t.prerequisites
|
||||||
|
|
||||||
cat_arguments = ['cat', source]
|
cat_arguments = ['cat', source]
|
||||||
@@ -113,7 +129,14 @@ end
|
|||||||
# Stage 1.
|
# 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' }
|
source, exe, = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.s' }
|
||||||
|
|
||||||
cat_arguments = ['cat', *source]
|
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
|
IO.copy_stream last_stdout, t.name
|
||||||
end
|
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' }
|
source = t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' }
|
||||||
|
|
||||||
compile(*source, t.name)
|
compile('-nostdlib', '-o', t.name, *source)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
|
|
||||||
(* Stage 15 compiler. *)
|
(* 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
|
type
|
||||||
ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited);
|
ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited);
|
||||||
|
|
||||||
@@ -1258,7 +1263,7 @@ var
|
|||||||
current_byte: Word;
|
current_byte: Word;
|
||||||
current_part: Word;
|
current_part: Word;
|
||||||
begin
|
begin
|
||||||
_write_z(".globl _start\n\n\0");
|
_write_z(".globl _start, main\n\n\0");
|
||||||
_write_z(".section .data\n\0");
|
_write_z(".section .data\n\0");
|
||||||
|
|
||||||
current_part := _elna_tac_module_get_data(pair);
|
current_part := _elna_tac_module_get_data(pair);
|
||||||
File diff suppressed because it is too large
Load Diff
0
boot/stage16/linker.arg
Normal file
0
boot/stage16/linker.arg
Normal file
297
boot/symbol.s
297
boot/symbol.s
@@ -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
|
|
||||||
Reference in New Issue
Block a user