Add builtin symbols
This commit is contained in:
parent
40701008f0
commit
3f11d63a0f
@ -2,6 +2,10 @@
|
|||||||
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
# 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/.
|
# obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tokens.
|
||||||
|
#
|
||||||
|
|
||||||
# The constant should match the index in the keywords array in tokenizer.s.
|
# The constant should match the index in the keywords array in tokenizer.s.
|
||||||
|
|
||||||
.equ TOKEN_PROGRAM, 1
|
.equ TOKEN_PROGRAM, 1
|
||||||
@ -52,3 +56,8 @@
|
|||||||
|
|
||||||
.equ TOKEN_ASSIGN, 43
|
.equ TOKEN_ASSIGN, 43
|
||||||
.equ TOKEN_INTEGER, 44
|
.equ TOKEN_INTEGER, 44
|
||||||
|
|
||||||
|
#
|
||||||
|
# Symbols.
|
||||||
|
#
|
||||||
|
.equ TYPE_PRIMITIVE, 1
|
||||||
|
265
boot/stage1.s
265
boot/stage1.s
@ -411,14 +411,6 @@ _build_expression:
|
|||||||
call _tokenize_next
|
call _tokenize_next
|
||||||
sw a0, 20(sp)
|
sw a0, 20(sp)
|
||||||
|
|
||||||
/* DEBUG
|
|
||||||
lw a0, 32(sp)
|
|
||||||
lw a1, 28(sp)
|
|
||||||
call _write_error
|
|
||||||
lw a0, 28(sp)
|
|
||||||
li a1, 8
|
|
||||||
call _write_error */
|
|
||||||
|
|
||||||
lw a0, 24(sp)
|
lw a0, 24(sp)
|
||||||
|
|
||||||
li t0, TOKEN_MINUS
|
li t0, TOKEN_MINUS
|
||||||
@ -754,74 +746,6 @@ _compile_call:
|
|||||||
addi sp, sp, 32
|
addi sp, sp, 32
|
||||||
ret
|
ret
|
||||||
|
|
||||||
# Skips the spaces till the next non space character.
|
|
||||||
.type _skip_spaces, @function
|
|
||||||
_skip_spaces:
|
|
||||||
.Lspace_loop_do:
|
|
||||||
lbu t0, (s1) # t0 = Current character.
|
|
||||||
|
|
||||||
li t1, ' '
|
|
||||||
beq t0, t1, .Lspace_loop_repeat
|
|
||||||
li t1, '\t'
|
|
||||||
beq t0, t1, .Lspace_loop_repeat
|
|
||||||
li t1, '\n'
|
|
||||||
beq t0, t1, .Lspace_loop_repeat
|
|
||||||
li t1, '\r'
|
|
||||||
beq t0, t1, .Lspace_loop_repeat
|
|
||||||
|
|
||||||
j .Lspace_loop_end
|
|
||||||
.Lspace_loop_repeat:
|
|
||||||
addi s1, s1, 1
|
|
||||||
j .Lspace_loop_do
|
|
||||||
|
|
||||||
.Lspace_loop_end:
|
|
||||||
ret
|
|
||||||
|
|
||||||
# Parameters:
|
|
||||||
# a0 - Line length.
|
|
||||||
.type _skip_comment, @function
|
|
||||||
_skip_comment:
|
|
||||||
# Prologue.
|
|
||||||
addi sp, sp, -16
|
|
||||||
sw ra, 12(sp)
|
|
||||||
sw s0, 8(sp)
|
|
||||||
addi s0, sp, 16
|
|
||||||
|
|
||||||
# Check whether this is a comment.
|
|
||||||
li t0, 0x2a28 # (*
|
|
||||||
sw t0, 4(sp)
|
|
||||||
addi a0, sp, 4
|
|
||||||
mv a1, s1
|
|
||||||
li a2, 2
|
|
||||||
call _memcmp
|
|
||||||
bnez a0, .Lskip_comment_end
|
|
||||||
|
|
||||||
addi s1, s1, 2 # Skip (*.
|
|
||||||
|
|
||||||
li t0, 0x292a # *)
|
|
||||||
sw t0, 4(sp)
|
|
||||||
|
|
||||||
.Lskip_comment_loop:
|
|
||||||
addi a0, sp, 4
|
|
||||||
mv a1, s1
|
|
||||||
li a2, 2
|
|
||||||
call _memcmp
|
|
||||||
beqz a0, .Lskip_comment_close
|
|
||||||
|
|
||||||
addi s1, s1, 1
|
|
||||||
|
|
||||||
j .Lskip_comment_loop
|
|
||||||
|
|
||||||
.Lskip_comment_close:
|
|
||||||
addi s1, s1, 2 # Skip *).
|
|
||||||
|
|
||||||
.Lskip_comment_end:
|
|
||||||
# Epilogue.
|
|
||||||
lw ra, 12(sp)
|
|
||||||
lw s0, 8(sp)
|
|
||||||
addi sp, sp, 16
|
|
||||||
ret
|
|
||||||
|
|
||||||
# Walks through the procedure definitions.
|
# Walks through the procedure definitions.
|
||||||
.type _compile_procedure_section, @function
|
.type _compile_procedure_section, @function
|
||||||
_compile_procedure_section:
|
_compile_procedure_section:
|
||||||
@ -832,9 +756,6 @@ _compile_procedure_section:
|
|||||||
addi s0, sp, 32
|
addi s0, sp, 32
|
||||||
|
|
||||||
.Lcompile_procedure_section_loop:
|
.Lcompile_procedure_section_loop:
|
||||||
call _skip_spaces
|
|
||||||
call _skip_comment
|
|
||||||
|
|
||||||
mv a0, s1
|
mv a0, s1
|
||||||
addi a1, sp, 4
|
addi a1, sp, 4
|
||||||
call _tokenize_next
|
call _tokenize_next
|
||||||
@ -1083,28 +1004,9 @@ _compile_procedure:
|
|||||||
call _tokenize_next
|
call _tokenize_next
|
||||||
mv s1, a0
|
mv s1, a0
|
||||||
|
|
||||||
# .type identifier, @function
|
lw a0, 16(sp)
|
||||||
la a0, asm_type
|
lw a1, 20(sp)
|
||||||
li a1, ASM_TYPE_SIZE
|
call _write_procedure_head
|
||||||
call _write_out
|
|
||||||
|
|
||||||
lw a0, 20(sp)
|
|
||||||
lw a1, 16(sp)
|
|
||||||
call _write_out
|
|
||||||
|
|
||||||
la a0, asm_type_function
|
|
||||||
li a1, ASM_TYPE_FUNCTION_SIZE
|
|
||||||
call _write_out
|
|
||||||
|
|
||||||
lw a0, 20(sp)
|
|
||||||
lw a1, 16(sp)
|
|
||||||
call _write_out
|
|
||||||
|
|
||||||
li t0, 0x0a3a # :\n
|
|
||||||
sw t0, 12(sp)
|
|
||||||
addi a0, sp, 12
|
|
||||||
li a1, 2
|
|
||||||
call _write_out
|
|
||||||
|
|
||||||
# Skip all declarations until we find the "begin" keyword, denoting the
|
# Skip all declarations until we find the "begin" keyword, denoting the
|
||||||
# beginning of the procedure body.
|
# beginning of the procedure body.
|
||||||
@ -1128,21 +1030,24 @@ _compile_procedure:
|
|||||||
call _write_out
|
call _write_out
|
||||||
|
|
||||||
# Generate the body of the procedure.
|
# Generate the body of the procedure.
|
||||||
.Lcompile_procedure_body:
|
call _compile_statements
|
||||||
li t0, 0x0a646e65 # end\n
|
mv s1, a0 # Skip end.
|
||||||
sw t0, 8(sp)
|
|
||||||
mv a0, s1
|
|
||||||
addi a1, sp, 8
|
|
||||||
li a2, 4
|
|
||||||
call _memcmp
|
|
||||||
|
|
||||||
beqz a0, .Lcompile_procedure_end
|
/* DEBUG
|
||||||
|
sw a0, 8(sp)
|
||||||
call _compile_statement
|
lw a1, 12(sp)
|
||||||
j .Lcompile_procedure_body
|
li a2, TOKEN_END
|
||||||
|
sub a1, a1, a2
|
||||||
.Lcompile_procedure_end:
|
seqz a1, a1
|
||||||
add s1, s1, 4 # Skip end\n.
|
seqz a0, a0
|
||||||
|
addi a0, a0, '0'
|
||||||
|
addi a1, a1, '0'
|
||||||
|
sb a0, 4(sp)
|
||||||
|
sb a1, 5(sp)
|
||||||
|
addi a0, sp, 4
|
||||||
|
li a1, 2
|
||||||
|
call _write_error
|
||||||
|
lw a0, 8(sp) */
|
||||||
|
|
||||||
# Generate the procedure epilogue with a predefined stack size.
|
# Generate the procedure epilogue with a predefined stack size.
|
||||||
la a0, epilogue
|
la a0, epilogue
|
||||||
@ -1288,21 +1193,8 @@ _compile_if:
|
|||||||
li a0, '\n'
|
li a0, '\n'
|
||||||
call _put_char
|
call _put_char
|
||||||
|
|
||||||
.Lcompile_if_loop:
|
call _compile_statements
|
||||||
mv a0, s1
|
mv s1, a0 # Skip end.
|
||||||
addi a1, sp, 0
|
|
||||||
call _tokenize_next
|
|
||||||
|
|
||||||
lw t0, 0(sp)
|
|
||||||
li t1, TOKEN_END
|
|
||||||
beq t0, t1, .Lcompile_if_end
|
|
||||||
|
|
||||||
call _compile_statement
|
|
||||||
|
|
||||||
j .Lcompile_if_loop
|
|
||||||
|
|
||||||
.Lcompile_if_end:
|
|
||||||
mv s1, a0 # Skip the end with newline. a0 is set by the last call to _tokenize_next.
|
|
||||||
|
|
||||||
# Write the label prefix.
|
# Write the label prefix.
|
||||||
addi a0, sp, 20
|
addi a0, sp, 20
|
||||||
@ -1328,6 +1220,95 @@ _compile_if:
|
|||||||
addi sp, sp, 32
|
addi sp, sp, 32
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
# Writes:
|
||||||
|
# .type identifier, @function
|
||||||
|
# identifier:
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# a0 - Identifier length.
|
||||||
|
# a0 - Identifier pointer.
|
||||||
|
.type _write_procedure_head, @function
|
||||||
|
_write_procedure_head:
|
||||||
|
# Prologue.
|
||||||
|
addi sp, sp, -32
|
||||||
|
sw ra, 28(sp)
|
||||||
|
sw s0, 24(sp)
|
||||||
|
addi s0, sp, 32
|
||||||
|
|
||||||
|
sw a0, 16(sp)
|
||||||
|
sw a1, 20(sp)
|
||||||
|
|
||||||
|
# .type identifier, @function
|
||||||
|
la a0, asm_type
|
||||||
|
li a1, ASM_TYPE_SIZE
|
||||||
|
call _write_out
|
||||||
|
|
||||||
|
lw a0, 20(sp)
|
||||||
|
lw a1, 16(sp)
|
||||||
|
call _write_out
|
||||||
|
|
||||||
|
la a0, asm_type_function
|
||||||
|
li a1, ASM_TYPE_FUNCTION_SIZE
|
||||||
|
call _write_out
|
||||||
|
|
||||||
|
lw a0, 20(sp)
|
||||||
|
lw a1, 16(sp)
|
||||||
|
call _write_out
|
||||||
|
|
||||||
|
li t0, 0x0a3a # :\n
|
||||||
|
sw t0, 12(sp)
|
||||||
|
addi a0, sp, 12
|
||||||
|
li a1, 2
|
||||||
|
call _write_out
|
||||||
|
|
||||||
|
# Epilogue.
|
||||||
|
lw ra, 28(sp)
|
||||||
|
lw s0, 24(sp)
|
||||||
|
addi sp, sp, 32
|
||||||
|
ret
|
||||||
|
|
||||||
|
# Compiles a list of statements delimited by semicolons.
|
||||||
|
#
|
||||||
|
# Sets a0 to the end of the token finishing the list
|
||||||
|
# (should be the "end" token in a valid program).
|
||||||
|
.type _compile_statements, @function
|
||||||
|
_compile_statements:
|
||||||
|
# Prologue.
|
||||||
|
addi sp, sp, -32
|
||||||
|
sw ra, 28(sp)
|
||||||
|
sw s0, 24(sp)
|
||||||
|
addi s0, sp, 32
|
||||||
|
|
||||||
|
# Generate the body of the procedure.
|
||||||
|
mv a0, s1
|
||||||
|
addi a1, sp, 0
|
||||||
|
call _tokenize_next
|
||||||
|
lw t0, 0(sp)
|
||||||
|
li t1, TOKEN_END
|
||||||
|
|
||||||
|
beq t0, t1, .Lcompile_statements_end
|
||||||
|
|
||||||
|
.Lcompile_statements_body:
|
||||||
|
call _compile_statement
|
||||||
|
|
||||||
|
mv a0, s1
|
||||||
|
addi a1, sp, 0
|
||||||
|
call _tokenize_next
|
||||||
|
lw t0, 0(sp)
|
||||||
|
li t1, TOKEN_SEMICOLON
|
||||||
|
|
||||||
|
bne t0, t1, .Lcompile_statements_end
|
||||||
|
mv s1, a0
|
||||||
|
|
||||||
|
j .Lcompile_statements_body
|
||||||
|
|
||||||
|
.Lcompile_statements_end:
|
||||||
|
# Epilogue.
|
||||||
|
lw ra, 28(sp)
|
||||||
|
lw s0, 24(sp)
|
||||||
|
addi sp, sp, 32
|
||||||
|
ret
|
||||||
|
|
||||||
# Checks for the type of the current statement and compiles it.
|
# Checks for the type of the current statement and compiles it.
|
||||||
.type _compile_statement, @function
|
.type _compile_statement, @function
|
||||||
_compile_statement:
|
_compile_statement:
|
||||||
@ -1357,7 +1338,7 @@ _compile_statement:
|
|||||||
li t1, TOKEN_DOT
|
li t1, TOKEN_DOT
|
||||||
beq t0, t1, .Lcompile_statement_label
|
beq t0, t1, .Lcompile_statement_label
|
||||||
|
|
||||||
j .Lcompile_statement_empty # Else.
|
unimp # Else.
|
||||||
|
|
||||||
.Lcompile_statement_if:
|
.Lcompile_statement_if:
|
||||||
call _compile_if
|
call _compile_if
|
||||||
@ -1379,10 +1360,6 @@ _compile_statement:
|
|||||||
call _compile_identifier
|
call _compile_identifier
|
||||||
j .Lcompile_statement_end
|
j .Lcompile_statement_end
|
||||||
|
|
||||||
.Lcompile_statement_empty:
|
|
||||||
addi s1, s1, 1
|
|
||||||
j .Lcompile_statement_end
|
|
||||||
|
|
||||||
.Lcompile_statement_end:
|
.Lcompile_statement_end:
|
||||||
# Epilogue.
|
# Epilogue.
|
||||||
lw ra, 28(sp)
|
lw ra, 28(sp)
|
||||||
@ -1422,23 +1399,14 @@ _compile_entry_point:
|
|||||||
li a1, ASM_START_SIZE
|
li a1, ASM_START_SIZE
|
||||||
call _write_out
|
call _write_out
|
||||||
|
|
||||||
addi s1, s1, 6 # Skip begin\n.
|
|
||||||
|
|
||||||
# Generate the body of the procedure.
|
|
||||||
.Lcompile_entry_point_body:
|
|
||||||
mv a0, s1
|
mv a0, s1
|
||||||
addi a1, sp, 4
|
addi a1, sp, 4
|
||||||
call _tokenize_next
|
call _tokenize_next
|
||||||
|
mv s1, a0 # Skip begin.
|
||||||
|
|
||||||
lw t0, 4(sp)
|
# Generate the body of the procedure.
|
||||||
li t1, TOKEN_END
|
call _compile_statements
|
||||||
beq t0, t1, .Lcompile_entry_point_end
|
mv s1, a0 # Skip end.
|
||||||
|
|
||||||
call _compile_statement
|
|
||||||
j .Lcompile_entry_point_body
|
|
||||||
|
|
||||||
.Lcompile_entry_point_end:
|
|
||||||
mv s1, a0 # Skip end. a0 is set by the last _tokenize_next call.
|
|
||||||
|
|
||||||
la a0, asm_exit
|
la a0, asm_exit
|
||||||
li a1, ASM_EXIT_SIZE
|
li a1, ASM_EXIT_SIZE
|
||||||
@ -1481,6 +1449,7 @@ _start:
|
|||||||
call _read_file
|
call _read_file
|
||||||
|
|
||||||
li s2, 1
|
li s2, 1
|
||||||
|
call symbol_table_build
|
||||||
call _compile
|
call _compile
|
||||||
|
|
||||||
# Call exit.
|
# Call exit.
|
||||||
|
@ -8,7 +8,6 @@ const
|
|||||||
var
|
var
|
||||||
source_code: [81920]Byte
|
source_code: [81920]Byte
|
||||||
|
|
||||||
(* Ignores the import. *)
|
|
||||||
proc _compile_import()
|
proc _compile_import()
|
||||||
var loca0: Word
|
var loca0: Word
|
||||||
begin
|
begin
|
||||||
@ -61,7 +60,7 @@ begin
|
|||||||
loca24 := _token_compare(loca12, loca20, @loca16);
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
||||||
if loca24 = 0 then
|
if loca24 = 0 then
|
||||||
goto .L_build_binary_expression_minus
|
goto .L_build_binary_expression_minus
|
||||||
end
|
end;
|
||||||
|
|
||||||
loca16 := 0x2a;
|
loca16 := 0x2a;
|
||||||
loca24 := _token_compare(loca12, loca20, @loca16);
|
loca24 := _token_compare(loca12, loca20, @loca16);
|
||||||
@ -181,7 +180,7 @@ begin
|
|||||||
_put_char(0x0a);
|
_put_char(0x0a);
|
||||||
|
|
||||||
goto .Lcompile_identifier_expression_end
|
goto .Lcompile_identifier_expression_end
|
||||||
end
|
end;
|
||||||
|
|
||||||
loca8 := 0x6120616c;
|
loca8 := 0x6120616c;
|
||||||
_write_out(@loca8, 4);
|
_write_out(@loca8, 4);
|
||||||
@ -409,7 +408,7 @@ begin
|
|||||||
loca0 := _front(loca8) = 0x2c;
|
loca0 := _front(loca8) = 0x2c;
|
||||||
if loca0 = 0 then
|
if loca0 = 0 then
|
||||||
goto .Lcompile_call_paren
|
goto .Lcompile_call_paren
|
||||||
end
|
end;
|
||||||
|
|
||||||
loca12 := loca12 + 1;
|
loca12 := loca12 + 1;
|
||||||
|
|
||||||
@ -567,7 +566,7 @@ begin
|
|||||||
loca0 := _front(loca0);
|
loca0 := _front(loca0);
|
||||||
loca4 := loca4 + 1;
|
loca4 := loca4 + 1;
|
||||||
|
|
||||||
if loca0 = 0x3d then
|
if loca0 = 0x3d then
|
||||||
goto .Ltoken_character_single
|
goto .Ltoken_character_single
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
@ -605,43 +604,6 @@ begin
|
|||||||
.Lspace_loop_end
|
.Lspace_loop_end
|
||||||
end
|
end
|
||||||
|
|
||||||
proc _skip_comment(loca84: Word)
|
|
||||||
var
|
|
||||||
loca0: ^Byte
|
|
||||||
loca4: Word
|
|
||||||
loca8: Int
|
|
||||||
begin
|
|
||||||
loca0 := _current();
|
|
||||||
|
|
||||||
loca4 := 0x2a28;
|
|
||||||
loca8 := _memcmp(loca0, @loca4, 2);
|
|
||||||
if loca8 = 0 then
|
|
||||||
goto .Lskip_comment_continue
|
|
||||||
end;
|
|
||||||
goto .Lskip_comment_end;
|
|
||||||
|
|
||||||
.Lskip_comment_continue;
|
|
||||||
_advance(2);
|
|
||||||
|
|
||||||
loca4 := 0x292a;
|
|
||||||
|
|
||||||
.Lskip_comment_loop;
|
|
||||||
loca0 := _current();
|
|
||||||
loca8 := _memcmp(loca0, @loca4, 2);
|
|
||||||
if loca8 = 0 then
|
|
||||||
goto .Lskip_comment_close
|
|
||||||
end;
|
|
||||||
|
|
||||||
_advance(1);
|
|
||||||
|
|
||||||
goto .Lskip_comment_loop;
|
|
||||||
|
|
||||||
.Lskip_comment_close;
|
|
||||||
_advance(2);
|
|
||||||
|
|
||||||
.Lskip_comment_end
|
|
||||||
end
|
|
||||||
|
|
||||||
proc _compile_assembly(loca84: Word)
|
proc _compile_assembly(loca84: Word)
|
||||||
var loca0: ^Byte
|
var loca0: ^Byte
|
||||||
begin
|
begin
|
||||||
@ -748,9 +710,11 @@ begin
|
|||||||
.Lcompile_variable_section_item;
|
.Lcompile_variable_section_item;
|
||||||
_skip_spaces();
|
_skip_spaces();
|
||||||
loca4 := _current();
|
loca4 := _current();
|
||||||
loca0 := _front(loca4);
|
|
||||||
|
|
||||||
if _is_lower(loca0) = 0 then
|
loca0 := 0x636f7270;
|
||||||
|
loca0 := _memcmp(@loca0, loca4, 4);
|
||||||
|
|
||||||
|
if loca0 = 0 then
|
||||||
goto .Lcompile_variable_section_end
|
goto .Lcompile_variable_section_end
|
||||||
end;
|
end;
|
||||||
_compile_variable();
|
_compile_variable();
|
||||||
@ -1096,7 +1060,7 @@ proc _compile_return()
|
|||||||
begin
|
begin
|
||||||
_advance(6);
|
_advance(6);
|
||||||
_skip_spaces();
|
_skip_spaces();
|
||||||
_build_binary_expression();
|
_build_binary_expression()
|
||||||
end
|
end
|
||||||
|
|
||||||
proc _compile_if()
|
proc _compile_if()
|
||||||
@ -1164,10 +1128,6 @@ begin
|
|||||||
|
|
||||||
loca16 := _current();
|
loca16 := _current();
|
||||||
loca0 := _front(loca16);
|
loca0 := _front(loca16);
|
||||||
if loca0 = 0x28 then
|
|
||||||
goto .Lcompile_line_comment
|
|
||||||
end;
|
|
||||||
loca16 := _current();
|
|
||||||
|
|
||||||
loca12 := 0x676f7270;
|
loca12 := 0x676f7270;
|
||||||
loca4 := _memcmp(loca16, @loca12, 4);
|
loca4 := _memcmp(loca16, @loca12, 4);
|
||||||
@ -1308,10 +1268,6 @@ begin
|
|||||||
_compile_program();
|
_compile_program();
|
||||||
goto .Lcompile_line_section;
|
goto .Lcompile_line_section;
|
||||||
|
|
||||||
.Lcompile_line_comment;
|
|
||||||
_skip_comment(loca84);
|
|
||||||
goto .Lcompile_line_section;
|
|
||||||
|
|
||||||
.Lcompile_line_empty;
|
.Lcompile_line_empty;
|
||||||
_advance(1);
|
_advance(1);
|
||||||
goto .Lcompile_line_section;
|
goto .Lcompile_line_section;
|
||||||
@ -1325,7 +1281,6 @@ begin
|
|||||||
|
|
||||||
.Lcompile_line_end;
|
.Lcompile_line_end;
|
||||||
_skip_spaces();
|
_skip_spaces();
|
||||||
_skip_comment();
|
|
||||||
|
|
||||||
return loca8
|
return loca8
|
||||||
end
|
end
|
||||||
|
104
boot/symbol.s
Normal file
104
boot/symbol.s
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# 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_build
|
||||||
|
|
||||||
|
.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"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
.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
|
||||||
|
|
||||||
|
# Build the initial symbols.
|
||||||
|
#
|
||||||
|
# Sets a0 to the pointer to the global symbol table.
|
||||||
|
.type symbol_build, @function
|
||||||
|
symbol_table_build:
|
||||||
|
la a0, symbol_table
|
||||||
|
addi t0, a0, 4
|
||||||
|
|
||||||
|
li t1, 3 # Length of the word "Int".
|
||||||
|
sw t1, 0(t0)
|
||||||
|
la t1, symbol_builtin_name_int
|
||||||
|
sw t1, 4(t0)
|
||||||
|
la t1, symbol_builtin_type_int
|
||||||
|
sw t1, 8(t0)
|
||||||
|
lw t1, 0(a0)
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, 0(a0)
|
||||||
|
addi t0, t0, 12
|
||||||
|
|
||||||
|
li t1, 4 # Length of the word "Word".
|
||||||
|
sw t1, 0(t0)
|
||||||
|
la t1, symbol_builtin_name_word
|
||||||
|
sw t1, 4(t0)
|
||||||
|
la t1, symbol_builtin_type_word
|
||||||
|
sw t1, 8(t0)
|
||||||
|
lw t1, 0(a0)
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, 0(a0)
|
||||||
|
addi t0, t0, 12
|
||||||
|
|
||||||
|
li t1, 4 # Length of the word "Byte".
|
||||||
|
sw t1, 0(t0)
|
||||||
|
la t1, symbol_builtin_name_byte
|
||||||
|
sw t1, 4(t0)
|
||||||
|
la t1, symbol_builtin_type_byte
|
||||||
|
sw t1, 8(t0)
|
||||||
|
lw t1, 0(a0)
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, 0(a0)
|
||||||
|
addi t0, t0, 12
|
||||||
|
|
||||||
|
li t1, 4 # Length of the word "Char".
|
||||||
|
sw t1, 0(t0)
|
||||||
|
la t1, symbol_builtin_name_char
|
||||||
|
sw t1, 4(t0)
|
||||||
|
la t1, symbol_builtin_type_char
|
||||||
|
sw t1, 8(t0)
|
||||||
|
lw t1, 0(a0)
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, 0(a0)
|
||||||
|
addi t0, t0, 12
|
||||||
|
|
||||||
|
ret
|
@ -309,17 +309,6 @@ namespace :cross do
|
|||||||
sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path
|
sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path
|
||||||
sh env, 'make', 'install', chdir: cwd.to_path
|
sh env, 'make', 'install', chdir: cwd.to_path
|
||||||
end
|
end
|
||||||
|
|
||||||
task :init, [:target] do |_, args|
|
|
||||||
options = find_build_target GCC_VERSION, args
|
|
||||||
env = {
|
|
||||||
'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}"
|
|
||||||
}
|
|
||||||
sh env, 'riscv32-unknown-linux-gnu-gcc',
|
|
||||||
'-ffreestanding', '-static',
|
|
||||||
'-o', (options.tools + 'init').to_path,
|
|
||||||
'tools/init.c'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Build cross toolchain'
|
desc 'Build cross toolchain'
|
||||||
@ -329,7 +318,6 @@ task cross: [
|
|||||||
'cross:headers',
|
'cross:headers',
|
||||||
'cross:kernel',
|
'cross:kernel',
|
||||||
'cross:glibc',
|
'cross:glibc',
|
||||||
'cross:gcc2',
|
'cross:gcc2'
|
||||||
'cross:init'
|
|
||||||
] do
|
] do
|
||||||
end
|
end
|
||||||
|
@ -21,16 +21,20 @@ def assemble_stage(output, compiler, source)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
library = []
|
||||||
|
|
||||||
Dir.glob('boot/*.s').each do |assembly_source|
|
Dir.glob('boot/*.s').each do |assembly_source|
|
||||||
target_object = Pathname.new('build/boot') + Pathname.new(assembly_source).basename.sub_ext('.o')
|
source_basename = Pathname.new(assembly_source).basename
|
||||||
|
target_object = Pathname.new('build/boot') + source_basename.sub_ext('.o')
|
||||||
|
|
||||||
file target_object.to_s => [assembly_source, 'build/boot'] do |t|
|
file target_object.to_s => [assembly_source, 'build/boot'] do |t|
|
||||||
sh CROSS_GCC, '-c', '-o', t.name, assembly_source
|
sh CROSS_GCC, '-c', '-o', t.name, assembly_source
|
||||||
end
|
end
|
||||||
|
library << assembly_source unless source_basename.to_s.start_with? 'stage'
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Initial stage'
|
desc 'Initial stage'
|
||||||
file 'build/boot/stage1' => ['build/boot/tokenizer.o', 'build/boot/stage1.o', 'build/boot/common-boot.o'] do |t|
|
file 'build/boot/stage1' => ['build/boot/stage1.o', *library] do |t|
|
||||||
sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites
|
sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,7 +47,7 @@ file 'build/boot/stage2a.s' => ['build/boot/stage1', 'boot/stage2.elna'] do |t|
|
|||||||
end
|
end
|
||||||
|
|
||||||
['build/boot/stage2a', 'build/boot/stage2b'].each do |exe|
|
['build/boot/stage2a', 'build/boot/stage2b'].each do |exe|
|
||||||
file exe => [exe.ext('.s'), 'build/boot/common-boot.o'] do |t|
|
file exe => [exe.ext('.s'), *library] do |t|
|
||||||
sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites
|
sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
204
tools/init.c
204
tools/init.c
@ -1,204 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/reboot.h>
|
|
||||||
|
|
||||||
#define FILENAME_BUFFER_SIZE 256
|
|
||||||
|
|
||||||
size_t read_command(int descriptor, char *command_buffer)
|
|
||||||
{
|
|
||||||
ssize_t bytes_read = 0;
|
|
||||||
size_t read_so_far = 0;
|
|
||||||
|
|
||||||
while ((bytes_read = read(descriptor, command_buffer + read_so_far, FILENAME_BUFFER_SIZE - read_so_far - 1)) > 0)
|
|
||||||
{
|
|
||||||
read_so_far += bytes_read;
|
|
||||||
if (read_so_far >= FILENAME_BUFFER_SIZE - 1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
command_buffer[read_so_far] = 0;
|
|
||||||
return read_so_far;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum status
|
|
||||||
{
|
|
||||||
status_success,
|
|
||||||
status_failure,
|
|
||||||
status_warning,
|
|
||||||
status_fatal
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int make_path(char *destination, const char *directory, const char *filename, const char *extension)
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
for (; i < FILENAME_BUFFER_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (directory[i] == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
destination[i] = directory[i];
|
|
||||||
}
|
|
||||||
for (int j = 0; i < FILENAME_BUFFER_SIZE; i++, j++)
|
|
||||||
{
|
|
||||||
if (filename[j] == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
destination[i] = filename[j];
|
|
||||||
}
|
|
||||||
if (extension == NULL)
|
|
||||||
{
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
for (int j = 0; i < FILENAME_BUFFER_SIZE; i++, j++)
|
|
||||||
{
|
|
||||||
if (extension[j] == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
destination[i] = extension[j];
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
destination[i] = 0;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum status run_test(const char *file_entry_name)
|
|
||||||
{
|
|
||||||
printf("Running %s. ", file_entry_name);
|
|
||||||
|
|
||||||
char filename[FILENAME_BUFFER_SIZE];
|
|
||||||
char command_buffer[FILENAME_BUFFER_SIZE];
|
|
||||||
char file_buffer[256];
|
|
||||||
int pipe_ends[2];
|
|
||||||
|
|
||||||
if (pipe(pipe_ends) == -1)
|
|
||||||
{
|
|
||||||
perror("pipe");
|
|
||||||
return status_fatal;
|
|
||||||
}
|
|
||||||
make_path(filename, "./tests/", file_entry_name, NULL);
|
|
||||||
|
|
||||||
int child_pid = fork();
|
|
||||||
if (child_pid == -1)
|
|
||||||
{
|
|
||||||
return status_fatal;
|
|
||||||
}
|
|
||||||
else if (child_pid == 0)
|
|
||||||
{
|
|
||||||
close(STDIN_FILENO);
|
|
||||||
close(STDERR_FILENO);
|
|
||||||
close(pipe_ends[0]); // Close the read end.
|
|
||||||
|
|
||||||
if (dup2(pipe_ends[1], STDOUT_FILENO) == -1)
|
|
||||||
{
|
|
||||||
perror("dup2");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
execl(filename, filename);
|
|
||||||
perror("execl");
|
|
||||||
}
|
|
||||||
close(STDOUT_FILENO);
|
|
||||||
close(pipe_ends[1]);
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close(pipe_ends[1]); // Close the write end.
|
|
||||||
read_command(pipe_ends[0], command_buffer);
|
|
||||||
close(pipe_ends[0]);
|
|
||||||
|
|
||||||
int wait_status = 0;
|
|
||||||
|
|
||||||
make_path(filename, "./expectations/", file_entry_name, ".txt");
|
|
||||||
|
|
||||||
FILE *expectation_descriptor = fopen(filename, "r");
|
|
||||||
|
|
||||||
if (expectation_descriptor == NULL)
|
|
||||||
{
|
|
||||||
return status_warning;
|
|
||||||
}
|
|
||||||
size_t read_from_file = fread(file_buffer, 1, sizeof(file_buffer) - 1, expectation_descriptor);
|
|
||||||
fclose(expectation_descriptor);
|
|
||||||
|
|
||||||
file_buffer[read_from_file] = 0;
|
|
||||||
for (unsigned int i = 0; ; ++i)
|
|
||||||
{
|
|
||||||
if (command_buffer[i] == 0 && file_buffer[i] == 0)
|
|
||||||
{
|
|
||||||
fwrite("\n", 1, 1, stdout);
|
|
||||||
return status_success;
|
|
||||||
}
|
|
||||||
else if (command_buffer[i] != file_buffer[i])
|
|
||||||
{
|
|
||||||
printf("Failed. Got:\n%s", command_buffer);
|
|
||||||
return status_failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct summary
|
|
||||||
{
|
|
||||||
size_t total;
|
|
||||||
size_t failure;
|
|
||||||
size_t success;
|
|
||||||
};
|
|
||||||
|
|
||||||
void walk()
|
|
||||||
{
|
|
||||||
DIR *directory_stream = opendir("./tests");
|
|
||||||
struct dirent *file_entry;
|
|
||||||
|
|
||||||
struct summary test_summary = { .total = 0, .failure = 0, .success = 0 };
|
|
||||||
|
|
||||||
while ((file_entry = readdir(directory_stream)) != NULL)
|
|
||||||
{
|
|
||||||
if (file_entry->d_name[0] == '.')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
++test_summary.total;
|
|
||||||
switch (run_test(file_entry->d_name))
|
|
||||||
{
|
|
||||||
case status_failure:
|
|
||||||
++test_summary.failure;
|
|
||||||
break;
|
|
||||||
case status_success:
|
|
||||||
++test_summary.success;
|
|
||||||
break;
|
|
||||||
case status_warning:
|
|
||||||
break;
|
|
||||||
case status_fatal:
|
|
||||||
goto end_walk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("Successful: %lu, Failed: %lu, Total: %lu.\n",
|
|
||||||
test_summary.success, test_summary.failure, test_summary.total);
|
|
||||||
end_walk:
|
|
||||||
closedir(directory_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int dev_console = open("/dev/console", O_WRONLY);
|
|
||||||
if (dev_console != -1)
|
|
||||||
{
|
|
||||||
dup2(dev_console, STDOUT_FILENO);
|
|
||||||
walk();
|
|
||||||
close(dev_console);
|
|
||||||
}
|
|
||||||
sync();
|
|
||||||
reboot(RB_POWER_OFF);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user