Support simple variable assignment
This commit is contained in:
		
							
								
								
									
										20
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								Rakefile
									
									
									
									
									
								
							| @@ -44,13 +44,15 @@ task :convert do | |||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
| STAGES.each do |stage| | rule /^build\/[[:alpha:]]+\/stage[[:digit:]]+$/ => ->(match) { | ||||||
|   previous = stage.delete_prefix('stage').to_i.pred |   "#{match}.s" | ||||||
|  | } do |t| | ||||||
|   file "build/valid/#{stage}" => "build/valid/#{stage}.s" do |t| |  | ||||||
|   sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites |   sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites | ||||||
| end | 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| |   file "build/valid/#{stage}.s" => ["build/boot/#{stage}", "boot/#{stage}.elna"] do |t| | ||||||
|     exe, source = t.prerequisites |     exe, source = t.prerequisites | ||||||
|  |  | ||||||
| @@ -61,10 +63,6 @@ STAGES.each do |stage| | |||||||
|     IO.copy_stream last_stdout, t.name |     IO.copy_stream last_stdout, t.name | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   file "build/boot/#{stage}" => "build/boot/#{stage}.s" do |t| |  | ||||||
|     sh CROSS_GCC, '-nostdlib', '-o', t.name, *t.prerequisites |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   file "build/boot/#{stage}.s" => ["build/valid/stage#{previous}", "boot/#{stage}.elna"] do |t| |   file "build/boot/#{stage}.s" => ["build/valid/stage#{previous}", "boot/#{stage}.elna"] do |t| | ||||||
|     exe, source = t.prerequisites |     exe, source = t.prerequisites | ||||||
|  |  | ||||||
| @@ -80,12 +78,6 @@ end | |||||||
| # Stage 1. | # Stage 1. | ||||||
| # | # | ||||||
|  |  | ||||||
| file 'build/valid/stage1' => ['build/valid', 'build/valid/stage1.s'] do |t| |  | ||||||
|   source = t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' } |  | ||||||
|  |  | ||||||
|   sh CROSS_GCC, '-nostdlib', '-o', t.name, *source |  | ||||||
| end |  | ||||||
|  |  | ||||||
| file 'build/valid/stage1.s' => ['build/boot/stage1', 'boot/stage1.s', 'build/valid'] do |t| | file 'build/valid/stage1.s' => ['build/boot/stage1', 'boot/stage1.s', 'build/valid'] do |t| | ||||||
|   source, exe, = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.s' } |   source, exe, = t.prerequisites.partition { |prerequisite| prerequisite.end_with? '.s' } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,11 @@ | |||||||
| # 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/. | ||||||
|  |  | ||||||
|  | # Stage1 compiler. | ||||||
|  | # | ||||||
|  | # It supports declaring and calling procedures without arguments. | ||||||
|  | # A procedure name should start with an underscore. | ||||||
|  |  | ||||||
| .equ SOURCE_BUFFER_SIZE, 81920 | .equ SOURCE_BUFFER_SIZE, 81920 | ||||||
|  |  | ||||||
| .equ SYS_READ, 63 | .equ SYS_READ, 63 | ||||||
|   | |||||||
| @@ -4,8 +4,12 @@ | |||||||
|  |  | ||||||
| # Stage2 compiler. | # Stage2 compiler. | ||||||
| # | # | ||||||
| # It supports declaring and calling procedures without arguments. | # - Procedures without none or one argument. | ||||||
| # A procedure name should start with an underscore. | # - Goto statements. | ||||||
|  | # - Character and integer literals. | ||||||
|  | # - Passing local variables to procedures. | ||||||
|  | # - Local variables should have the format: v00, | ||||||
|  | #   where 00 is its offset from the sp register. | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,12 +4,8 @@ | |||||||
|  |  | ||||||
| # Stage3 compiler. | # Stage3 compiler. | ||||||
| # | # | ||||||
| # - Procedures without none or one argument. | # - Procedures with multiple arguments. | ||||||
| # - Goto statements. | # - Character literals with and without escaping. | ||||||
| # - Character and integer literals. |  | ||||||
| # - Passing local variables to procedures. |  | ||||||
| # - Local variables should have the format: v00, |  | ||||||
| #   where 00 is its offset from the sp register. |  | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										211
									
								
								boot/stage4.elna
									
									
									
									
									
								
							
							
						
						
									
										211
									
								
								boot/stage4.elna
									
									
									
									
									
								
							| @@ -2,14 +2,11 @@ | |||||||
| # 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/. | ||||||
|  |  | ||||||
| # Stage3 compiler. | # Stage4 compiler. | ||||||
| # | # | ||||||
| # - Procedures without none or one argument. | # - Taking value of local and global variables. Variables that doesn't begin | ||||||
| # - Goto statements. | #   with "v" are considered global. | ||||||
| # - Character and integer literals. | # - Simple variable assignment, e.g. v0 := 5 or v0 := global_variable; | ||||||
| # - Passing local variables to procedures. |  | ||||||
| # - Local variables should have the format: v00, |  | ||||||
| #   where 00 is its offset from the sp register. |  | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
| @@ -64,23 +61,26 @@ asm_li: .string "\tli " | |||||||
| .type asm_lw, @object | .type asm_lw, @object | ||||||
| asm_lw: .string "\tlw " | asm_lw: .string "\tlw " | ||||||
|  |  | ||||||
|  | .type asm_la, @object | ||||||
|  | asm_la: .string "\tla " | ||||||
|  |  | ||||||
| .type asm_sw, @object | .type asm_sw, @object | ||||||
| asm_sw: .string "\tsw " | asm_sw: .string "\tsw " | ||||||
|  |  | ||||||
| .type asm_mv, @object | .type asm_addi, @object | ||||||
| asm_mv: .string "mv " | asm_addi: .string "\taddi " | ||||||
|  |  | ||||||
| .type asm_t0, @object | .type asm_t0, @object | ||||||
| asm_t0: .string "t0" | asm_t0: .string "t0" | ||||||
|  |  | ||||||
| .type asm_a0, @object | .type asm_t1, @object | ||||||
| asm_a0: .string "a0" | asm_t1: .string "t1" | ||||||
|  |  | ||||||
| .type asm_comma, @object | .type asm_comma, @object | ||||||
| asm_comma: .string ", " | asm_comma: .string ", " | ||||||
|  |  | ||||||
| .type asm_sp, @object | .type asm_sp, @object | ||||||
| asm_sp: .string "(sp)" | asm_sp: .string "sp" | ||||||
|  |  | ||||||
| .section .bss | .section .bss | ||||||
|  |  | ||||||
| @@ -257,7 +257,7 @@ begin | |||||||
| 	_is_upper(); | 	_is_upper(); | ||||||
| 	sw a0, 4(sp) | 	sw a0, 4(sp) | ||||||
|  |  | ||||||
| 	_is_lower(v00); | 	_is_lower(v0); | ||||||
|  |  | ||||||
| 	lw t0, 0(sp) | 	lw t0, 0(sp) | ||||||
| 	xori t1, t0, '_' | 	xori t1, t0, '_' | ||||||
| @@ -292,7 +292,7 @@ begin | |||||||
| 	_is_alpha(); | 	_is_alpha(); | ||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	_is_digit(v04); | 	_is_digit(v4); | ||||||
|  |  | ||||||
| 	lw a1, 0(sp) | 	lw a1, 0(sp) | ||||||
| 	or a0, a0, a1 | 	or a0, a0, a1 | ||||||
| @@ -491,7 +491,7 @@ begin | |||||||
| 	la a0, asm_li | 	la a0, asm_li | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -509,7 +509,7 @@ begin | |||||||
| 	la a0, asm_li | 	la a0, asm_li | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -542,23 +542,22 @@ end; | |||||||
|  |  | ||||||
| proc _compile_variable_expression(); | proc _compile_variable_expression(); | ||||||
| begin | begin | ||||||
|  | 	_compile_designator(); | ||||||
|  |  | ||||||
| 	la a0, asm_lw | 	la a0, asm_lw | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_advance_token(1); | 	_write_c('('); | ||||||
| 	_read_token(); | 	la a0, asm_t0 | ||||||
| 	_write_token(); |  | ||||||
| 	_advance_token(); |  | ||||||
|  |  | ||||||
| 	la a0, asm_sp |  | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| end; | end; | ||||||
| @@ -568,17 +567,15 @@ begin | |||||||
| 	la t0, source_code_position | 	la t0, source_code_position | ||||||
| 	lw t0, (t0) | 	lw t0, (t0) | ||||||
| 	lb a0, (t0) | 	lb a0, (t0) | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	li t1, '\'' | 	li t1, '\'' | ||||||
| 	beq a0, t1, .compile_expression_character_literal | 	beq a0, t1, .compile_expression_character_literal | ||||||
|  |  | ||||||
| 	li t1, 'v' | 	_is_digit(v0); | ||||||
| 	beq a0, t1, .compile_expression_variable |  | ||||||
|  |  | ||||||
| 	_is_digit(); |  | ||||||
| 	bnez a0, .compile_expression_integer_literal | 	bnez a0, .compile_expression_integer_literal | ||||||
|  |  | ||||||
| 	goto .compile_expression_end; | 	goto .compile_expression_variable; | ||||||
|  |  | ||||||
| .compile_expression_character_literal: | .compile_expression_character_literal: | ||||||
| 	_compile_character_literal(); | 	_compile_character_literal(); | ||||||
| @@ -590,7 +587,7 @@ begin | |||||||
|  |  | ||||||
| .compile_expression_variable: | .compile_expression_variable: | ||||||
| 	_compile_variable_expression(); | 	_compile_variable_expression(); | ||||||
| 	goto .compile_expression_end;; | 	goto .compile_expression_end; | ||||||
|  |  | ||||||
| .compile_expression_end: | .compile_expression_end: | ||||||
| end; | end; | ||||||
| @@ -628,7 +625,7 @@ begin | |||||||
| 	la a0, asm_sw | 	la a0, asm_sw | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -642,8 +639,10 @@ begin | |||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('(') | ||||||
| 	la a0, asm_sp | 	la a0, asm_sp | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  | 	_write_c(')') | ||||||
|  |  | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| @@ -691,9 +690,11 @@ begin | |||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
| 	la a0, asm_sp | 	la a0, asm_sp | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| 	goto .compile_call_finalize; | 	goto .compile_call_finalize; | ||||||
| @@ -702,7 +703,7 @@ begin | |||||||
| 	la a0, asm_call | 	la a0, asm_call | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_s(v04, v00); | 	_write_s(v4, v0); | ||||||
|  |  | ||||||
| 	# Skip the right paren. | 	# Skip the right paren. | ||||||
| 	_advance_token(1); | 	_advance_token(1); | ||||||
| @@ -718,10 +719,143 @@ begin | |||||||
| 	la a0, asm_j | 	la a0, asm_j | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
| 	_advance_token(); | 	_advance_token(); | ||||||
| end; | end; | ||||||
|  |  | ||||||
|  | proc _compile_local_designator(); | ||||||
|  | begin | ||||||
|  | 	# Skip "v" in the local variable name. | ||||||
|  | 	_advance_token(1); | ||||||
|  |  | ||||||
|  | 	la a0, asm_addi | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	# Read local variable stack offset and save it. | ||||||
|  | 	la t0, source_code_position | ||||||
|  | 	lw t0, (t0) | ||||||
|  | 	sw t0, 0(sp) | ||||||
|  |  | ||||||
|  | 	_read_token(); | ||||||
|  | 	sw a0, 4(sp) | ||||||
|  |  | ||||||
|  | 	_write_token(); | ||||||
|  | 	_advance_token(); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_global_designator(); | ||||||
|  | begin | ||||||
|  | 	la a0, asm_la | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_read_token(); | ||||||
|  | 	_write_token(); | ||||||
|  | 	_advance_token(); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_designator(); | ||||||
|  | begin | ||||||
|  | 	la t0, source_code_position | ||||||
|  | 	lw t0, (t0) | ||||||
|  | 	lb a0, (t0) | ||||||
|  |  | ||||||
|  | 	li t1, 'v' | ||||||
|  | 	beq a0, t1, .compile_designator_local | ||||||
|  |  | ||||||
|  | 	goto .compile_designator_global; | ||||||
|  |  | ||||||
|  | .compile_designator_local: | ||||||
|  | 	_compile_local_designator(); | ||||||
|  | 	goto .compile_designator_end; | ||||||
|  |  | ||||||
|  | .compile_designator_global: | ||||||
|  | 	_compile_global_designator(); | ||||||
|  | 	goto .compile_designator_end; | ||||||
|  |  | ||||||
|  | .compile_designator_end: | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_assignment(); | ||||||
|  | begin | ||||||
|  | 	_compile_designator(); | ||||||
|  |  | ||||||
|  | 	# Save the assignee address on the stack. | ||||||
|  | 	la a0, asm_sw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_i(20); | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  | 	# Skip the assignment sign (:=) with surrounding whitespaces. | ||||||
|  | 	_advance_token(4); | ||||||
|  |  | ||||||
|  | 	# Compile the assignment. | ||||||
|  | 	_compile_expression(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_lw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t1 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_i(20); | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | 	la a0, asm_sw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_t1 | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | end; | ||||||
|  |  | ||||||
| proc _compile_statement(); | proc _compile_statement(); | ||||||
| begin | begin | ||||||
| 	# This is a call if the statement starts with an underscore. | 	# This is a call if the statement starts with an underscore. | ||||||
| @@ -737,6 +871,9 @@ begin | |||||||
| 	li t1, 'g' | 	li t1, 'g' | ||||||
| 	beq t0, t1, .compile_statement_goto | 	beq t0, t1, .compile_statement_goto | ||||||
|  |  | ||||||
|  | 	li t1, 'v' | ||||||
|  | 	beq t0, t1, .compile_statement_assignment | ||||||
|  |  | ||||||
| 	_compile_line(); | 	_compile_line(); | ||||||
| 	goto .compile_statement_end; | 	goto .compile_statement_end; | ||||||
|  |  | ||||||
| @@ -752,6 +889,12 @@ begin | |||||||
|  |  | ||||||
| 	goto .compile_statement_semicolon; | 	goto .compile_statement_semicolon; | ||||||
|  |  | ||||||
|  | .compile_statement_assignment: | ||||||
|  | 	_advance_token(1); | ||||||
|  | 	_compile_assignment(); | ||||||
|  |  | ||||||
|  | 	goto .compile_statement_semicolon; | ||||||
|  |  | ||||||
| .compile_statement_semicolon: | .compile_statement_semicolon: | ||||||
| 	_advance_token(2); | 	_advance_token(2); | ||||||
|  |  | ||||||
| @@ -789,13 +932,13 @@ begin | |||||||
| 	la a0, asm_type_directive | 	la a0, asm_type_directive | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_type_function | 	la a0, asm_type_function | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	# Write procedure label, _procedure_name: | 	# Write procedure label, _procedure_name: | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_colon | 	la a0, asm_colon | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|   | |||||||
							
								
								
									
										229
									
								
								boot/stage5.elna
									
									
									
									
									
								
							
							
						
						
									
										229
									
								
								boot/stage5.elna
									
									
									
									
									
								
							| @@ -2,14 +2,8 @@ | |||||||
| # 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/. | ||||||
|  |  | ||||||
| # Stage3 compiler. | # Stage5 compiler. | ||||||
| # | # | ||||||
| # - Procedures without none or one argument. |  | ||||||
| # - Goto statements. |  | ||||||
| # - Character and integer literals. |  | ||||||
| # - Passing local variables to procedures. |  | ||||||
| # - Local variables should have the format: v00, |  | ||||||
| #   where 00 is its offset from the sp register. |  | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
| @@ -64,23 +58,26 @@ asm_li: .string "\tli " | |||||||
| .type asm_lw, @object | .type asm_lw, @object | ||||||
| asm_lw: .string "\tlw " | asm_lw: .string "\tlw " | ||||||
|  |  | ||||||
|  | .type asm_la, @object | ||||||
|  | asm_la: .string "\tla " | ||||||
|  |  | ||||||
| .type asm_sw, @object | .type asm_sw, @object | ||||||
| asm_sw: .string "\tsw " | asm_sw: .string "\tsw " | ||||||
|  |  | ||||||
| .type asm_mv, @object | .type asm_addi, @object | ||||||
| asm_mv: .string "mv " | asm_addi: .string "\taddi " | ||||||
|  |  | ||||||
| .type asm_t0, @object | .type asm_t0, @object | ||||||
| asm_t0: .string "t0" | asm_t0: .string "t0" | ||||||
|  |  | ||||||
| .type asm_a0, @object | .type asm_t1, @object | ||||||
| asm_a0: .string "a0" | asm_t1: .string "t1" | ||||||
|  |  | ||||||
| .type asm_comma, @object | .type asm_comma, @object | ||||||
| asm_comma: .string ", " | asm_comma: .string ", " | ||||||
|  |  | ||||||
| .type asm_sp, @object | .type asm_sp, @object | ||||||
| asm_sp: .string "(sp)" | asm_sp: .string "sp" | ||||||
|  |  | ||||||
| .section .bss | .section .bss | ||||||
|  |  | ||||||
| @@ -257,7 +254,7 @@ begin | |||||||
| 	_is_upper(); | 	_is_upper(); | ||||||
| 	sw a0, 4(sp) | 	sw a0, 4(sp) | ||||||
|  |  | ||||||
| 	_is_lower(v00); | 	_is_lower(v0); | ||||||
|  |  | ||||||
| 	lw t0, 0(sp) | 	lw t0, 0(sp) | ||||||
| 	xori t1, t0, '_' | 	xori t1, t0, '_' | ||||||
| @@ -289,10 +286,10 @@ proc _is_alnum(); | |||||||
| begin | begin | ||||||
| 	sw a0, 4(sp) | 	sw a0, 4(sp) | ||||||
|  |  | ||||||
| 	_is_alpha(); | 	_is_alpha(v4); | ||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	_is_digit(v04); | 	_is_digit(v4); | ||||||
|  |  | ||||||
| 	lw a1, 0(sp) | 	lw a1, 0(sp) | ||||||
| 	or a0, a0, a1 | 	or a0, a0, a1 | ||||||
| @@ -413,12 +410,7 @@ end; | |||||||
| proc _write_token(); | proc _write_token(); | ||||||
| begin | begin | ||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
|  | 	_write_s(source_code_position, v0); | ||||||
| 	la a0, source_code_position |  | ||||||
| 	lw a0, (a0) |  | ||||||
| 	lw a1, 0(sp) |  | ||||||
| 	_write_s(); |  | ||||||
|  |  | ||||||
| 	lw a0, 0(sp) | 	lw a0, 0(sp) | ||||||
| end; | end; | ||||||
|  |  | ||||||
| @@ -491,7 +483,7 @@ begin | |||||||
| 	la a0, asm_li | 	la a0, asm_li | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -509,7 +501,7 @@ begin | |||||||
| 	la a0, asm_li | 	la a0, asm_li | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -542,23 +534,22 @@ end; | |||||||
|  |  | ||||||
| proc _compile_variable_expression(); | proc _compile_variable_expression(); | ||||||
| begin | begin | ||||||
|  | 	_compile_designator(); | ||||||
|  |  | ||||||
| 	la a0, asm_lw | 	la a0, asm_lw | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_advance_token(1); | 	_write_c('('); | ||||||
| 	_read_token(); | 	la a0, asm_t0 | ||||||
| 	_write_token(); |  | ||||||
| 	_advance_token(); |  | ||||||
|  |  | ||||||
| 	la a0, asm_sp |  | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| end; | end; | ||||||
| @@ -568,17 +559,15 @@ begin | |||||||
| 	la t0, source_code_position | 	la t0, source_code_position | ||||||
| 	lw t0, (t0) | 	lw t0, (t0) | ||||||
| 	lb a0, (t0) | 	lb a0, (t0) | ||||||
|  | 	sw a0, 0(sp) | ||||||
|  |  | ||||||
| 	li t1, '\'' | 	li t1, '\'' | ||||||
| 	beq a0, t1, .compile_expression_character_literal | 	beq a0, t1, .compile_expression_character_literal | ||||||
|  |  | ||||||
| 	li t1, 'v' | 	_is_digit(v0); | ||||||
| 	beq a0, t1, .compile_expression_variable |  | ||||||
|  |  | ||||||
| 	_is_digit(); |  | ||||||
| 	bnez a0, .compile_expression_integer_literal | 	bnez a0, .compile_expression_integer_literal | ||||||
|  |  | ||||||
| 	goto .compile_expression_end; | 	goto .compile_expression_variable; | ||||||
|  |  | ||||||
| .compile_expression_character_literal: | .compile_expression_character_literal: | ||||||
| 	_compile_character_literal(); | 	_compile_character_literal(); | ||||||
| @@ -590,7 +579,7 @@ begin | |||||||
|  |  | ||||||
| .compile_expression_variable: | .compile_expression_variable: | ||||||
| 	_compile_variable_expression(); | 	_compile_variable_expression(); | ||||||
| 	goto .compile_expression_end;; | 	goto .compile_expression_end; | ||||||
|  |  | ||||||
| .compile_expression_end: | .compile_expression_end: | ||||||
| end; | end; | ||||||
| @@ -604,11 +593,8 @@ begin | |||||||
|  |  | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| 	sw a0, 0(sp) | 	sw a0, 0(sp) | ||||||
| 	la t0, source_code_position | 	v4 := source_code_position; | ||||||
| 	lw t0, (t0) | 	v8 := 0; | ||||||
| 	sw t0, 4(sp) |  | ||||||
|  |  | ||||||
| 	sw zero, 8(sp) |  | ||||||
|  |  | ||||||
| 	# Skip the identifier and left paren. | 	# Skip the identifier and left paren. | ||||||
| 	addi a0, a0, 1 | 	addi a0, a0, 1 | ||||||
| @@ -628,7 +614,7 @@ begin | |||||||
| 	la a0, asm_sw | 	la a0, asm_sw | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_a0 | 	la a0, asm_t0 | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| @@ -642,8 +628,10 @@ begin | |||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('(') | ||||||
| 	la a0, asm_sp | 	la a0, asm_sp | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  | 	_write_c(')') | ||||||
|  |  | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| @@ -677,8 +665,7 @@ begin | |||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_c('a'); | 	_write_c('a'); | ||||||
| 	lw a0, 8(sp) | 	_write_i(v8); | ||||||
| 	_write_i(); |  | ||||||
|  |  | ||||||
| 	la a0, asm_comma | 	la a0, asm_comma | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
| @@ -691,9 +678,11 @@ begin | |||||||
| 	sub a0, t1, t0 | 	sub a0, t1, t0 | ||||||
| 	_write_i(); | 	_write_i(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
| 	la a0, asm_sp | 	la a0, asm_sp | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c(')'); | ||||||
| 	_write_c('\n'); | 	_write_c('\n'); | ||||||
|  |  | ||||||
| 	goto .compile_call_finalize; | 	goto .compile_call_finalize; | ||||||
| @@ -702,7 +691,7 @@ begin | |||||||
| 	la a0, asm_call | 	la a0, asm_call | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_s(v04, v00); | 	_write_s(v4, v0); | ||||||
|  |  | ||||||
| 	# Skip the right paren. | 	# Skip the right paren. | ||||||
| 	_advance_token(1); | 	_advance_token(1); | ||||||
| @@ -718,10 +707,142 @@ begin | |||||||
| 	la a0, asm_j | 	la a0, asm_j | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
| 	_advance_token(); | 	_advance_token(); | ||||||
| end; | end; | ||||||
|  |  | ||||||
|  | proc _compile_local_designator(); | ||||||
|  | begin | ||||||
|  | 	# Skip "v" in the local variable name. | ||||||
|  | 	_advance_token(1); | ||||||
|  |  | ||||||
|  | 	la a0, asm_addi | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	# Read local variable stack offset and save it. | ||||||
|  | 	v0 := source_code_position; | ||||||
|  |  | ||||||
|  | 	_read_token(); | ||||||
|  | 	sw a0, 4(sp) | ||||||
|  |  | ||||||
|  | 	_write_token(); | ||||||
|  | 	_advance_token(); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_global_designator(); | ||||||
|  | begin | ||||||
|  | 	la a0, asm_la | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_read_token(); | ||||||
|  | 	_write_token(); | ||||||
|  | 	_advance_token(); | ||||||
|  |  | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_designator(); | ||||||
|  | begin | ||||||
|  | 	la t0, source_code_position | ||||||
|  | 	lw t0, (t0) | ||||||
|  | 	lb a0, (t0) | ||||||
|  |  | ||||||
|  | 	li t1, 'v' | ||||||
|  | 	beq a0, t1, .compile_designator_local | ||||||
|  |  | ||||||
|  | 	goto .compile_designator_global; | ||||||
|  |  | ||||||
|  | .compile_designator_local: | ||||||
|  | 	_compile_local_designator(); | ||||||
|  | 	goto .compile_designator_end; | ||||||
|  |  | ||||||
|  | .compile_designator_global: | ||||||
|  | 	_compile_global_designator(); | ||||||
|  | 	goto .compile_designator_end; | ||||||
|  |  | ||||||
|  | .compile_designator_end: | ||||||
|  | end; | ||||||
|  |  | ||||||
|  | proc _compile_assignment(); | ||||||
|  | begin | ||||||
|  | 	_compile_designator(); | ||||||
|  |  | ||||||
|  | 	# Save the assignee address on the stack. | ||||||
|  | 	la a0, asm_sw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_i(20); | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | 	# Skip the assignment sign (:=) with surrounding whitespaces. | ||||||
|  | 	_advance_token(4); | ||||||
|  |  | ||||||
|  | 	# Compile the assignment. | ||||||
|  | 	_compile_expression(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_lw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t1 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_i(20); | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_sp | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | 	_write_c('\n'); | ||||||
|  |  | ||||||
|  | 	la a0, asm_sw | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_t0 | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	la a0, asm_comma | ||||||
|  | 	_write_z(); | ||||||
|  |  | ||||||
|  | 	_write_c('('); | ||||||
|  | 	la a0, asm_t1 | ||||||
|  | 	_write_z(); | ||||||
|  | 	_write_c(')'); | ||||||
|  | end; | ||||||
|  |  | ||||||
| proc _compile_statement(); | proc _compile_statement(); | ||||||
| begin | begin | ||||||
| 	# This is a call if the statement starts with an underscore. | 	# This is a call if the statement starts with an underscore. | ||||||
| @@ -737,6 +858,9 @@ begin | |||||||
| 	li t1, 'g' | 	li t1, 'g' | ||||||
| 	beq t0, t1, .compile_statement_goto | 	beq t0, t1, .compile_statement_goto | ||||||
|  |  | ||||||
|  | 	li t1, 'v' | ||||||
|  | 	beq t0, t1, .compile_statement_assignment | ||||||
|  |  | ||||||
| 	_compile_line(); | 	_compile_line(); | ||||||
| 	goto .compile_statement_end; | 	goto .compile_statement_end; | ||||||
|  |  | ||||||
| @@ -752,6 +876,12 @@ begin | |||||||
|  |  | ||||||
| 	goto .compile_statement_semicolon; | 	goto .compile_statement_semicolon; | ||||||
|  |  | ||||||
|  | .compile_statement_assignment: | ||||||
|  | 	_advance_token(1); | ||||||
|  | 	_compile_assignment(); | ||||||
|  |  | ||||||
|  | 	goto .compile_statement_semicolon; | ||||||
|  |  | ||||||
| .compile_statement_semicolon: | .compile_statement_semicolon: | ||||||
| 	_advance_token(2); | 	_advance_token(2); | ||||||
|  |  | ||||||
| @@ -789,13 +919,13 @@ begin | |||||||
| 	la a0, asm_type_directive | 	la a0, asm_type_directive | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_type_function | 	la a0, asm_type_function | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
|  |  | ||||||
| 	# Write procedure label, _procedure_name: | 	# Write procedure label, _procedure_name: | ||||||
| 	_write_token(v00); | 	_write_token(v0); | ||||||
|  |  | ||||||
| 	la a0, asm_colon | 	la a0, asm_colon | ||||||
| 	_write_z(); | 	_write_z(); | ||||||
| @@ -834,9 +964,6 @@ begin | |||||||
|  |  | ||||||
| 	# Read the symbol type. | 	# Read the symbol type. | ||||||
| 	_read_token(); | 	_read_token(); | ||||||
| 	la t0, source_code_position |  | ||||||
| 	lw t0, (t0) |  | ||||||
| 	sw t0, 12(sp) |  | ||||||
|  |  | ||||||
| 	# Print the symbol type and newline. | 	# Print the symbol type and newline. | ||||||
| 	addi a0, a0, 1 | 	addi a0, a0, 1 | ||||||
|   | |||||||
							
								
								
									
										1093
									
								
								boot/stage6.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1093
									
								
								boot/stage6.elna
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,323 +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/. -} |  | ||||||
| # frozen_string_literal: true |  | ||||||
|  |  | ||||||
| require 'pathname' |  | ||||||
| require 'uri' |  | ||||||
| require 'net/http' |  | ||||||
| require 'rake/clean' |  | ||||||
| require 'open3' |  | ||||||
| require 'etc' |  | ||||||
|  |  | ||||||
| GCC_VERSION = "15.1.0" |  | ||||||
| BINUTILS_VERSION = '2.44' |  | ||||||
| GLIBC_VERSION = '2.41' |  | ||||||
| KERNEL_VERSION = '5.15.181' |  | ||||||
|  |  | ||||||
| CLOBBER.include 'build' |  | ||||||
|  |  | ||||||
| class BuildTarget |  | ||||||
|   attr_accessor(:build, :gcc, :target, :tmp) |  | ||||||
|  |  | ||||||
|   def gxx |  | ||||||
|     @gcc.gsub 'c', '+' |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   def sysroot |  | ||||||
|     tmp + 'sysroot' |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   def rootfs |  | ||||||
|     tmp + 'rootfs' |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   def tools |  | ||||||
|     tmp + 'tools' |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| def gcc_verbose(gcc_binary) |  | ||||||
|   read, write = IO.pipe |  | ||||||
|   sh({'LANG' => 'C'}, gcc_binary, '--verbose', err: write) |  | ||||||
|   write.close |  | ||||||
|   output = read.read |  | ||||||
|   read.close |  | ||||||
|   output |  | ||||||
| end |  | ||||||
|  |  | ||||||
| def find_build_target(gcc_version, task) |  | ||||||
|   gcc_binary = 'gcc' |  | ||||||
|   output = gcc_verbose gcc_binary |  | ||||||
|  |  | ||||||
|   if output.start_with? 'Apple clang' |  | ||||||
|     gcc_binary = "gcc-#{gcc_version.split('.').first}" |  | ||||||
|     output = gcc_verbose gcc_binary |  | ||||||
|   end |  | ||||||
|   result = output |  | ||||||
|     .lines |  | ||||||
|     .each_with_object(BuildTarget.new) do |line, accumulator| |  | ||||||
|       if line.start_with? 'Target: ' |  | ||||||
|         accumulator.build = line.split(' ').last.strip |  | ||||||
|       elsif line.start_with? 'COLLECT_GCC' |  | ||||||
|         accumulator.gcc = line.split('=').last.strip |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   result.tmp = Pathname.new('./build') |  | ||||||
|   task.with_defaults target: 'riscv32-unknown-linux-gnu' |  | ||||||
|   result.target = task[:target] |  | ||||||
|   result |  | ||||||
| end |  | ||||||
|  |  | ||||||
| def download_and_unarchive(url, target) |  | ||||||
|   case File.extname url.path |  | ||||||
|   when '.bz2' |  | ||||||
|     archive_type = '-j' |  | ||||||
|     root_directory = File.basename url.path, '.tar.bz2' |  | ||||||
|   when '.xz' |  | ||||||
|     archive_type = '-J' |  | ||||||
|     root_directory = File.basename url.path, '.tar.xz' |  | ||||||
|   else |  | ||||||
|     raise "Unsupported archive type #{url.path}." |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   Net::HTTP.start(url.host, url.port, use_ssl: url.scheme == 'https') do |http| |  | ||||||
|     request = Net::HTTP::Get.new url.request_uri |  | ||||||
|  |  | ||||||
|     http.request request do |response| |  | ||||||
|       case response |  | ||||||
|       when Net::HTTPRedirection |  | ||||||
|         download_and_unarchive URI.parse(response['location']) |  | ||||||
|       when Net::HTTPSuccess |  | ||||||
|         Open3.popen2 'tar', '-C', target.to_path, archive_type, '-xv' do |stdin, stdout, wait_thread| |  | ||||||
|           Thread.new do |  | ||||||
|             stdout.each { |line| puts line } |  | ||||||
|           end |  | ||||||
|  |  | ||||||
|           response.read_body do |chunk| |  | ||||||
|             stdin.write chunk |  | ||||||
|           end |  | ||||||
|           stdin.close |  | ||||||
|  |  | ||||||
|           wait_thread.value |  | ||||||
|         end |  | ||||||
|       else |  | ||||||
|         response.error! |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
|   target + root_directory |  | ||||||
| end |  | ||||||
|  |  | ||||||
| namespace :cross do |  | ||||||
|   desc 'Build cross binutils' |  | ||||||
|   task :binutils, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     options.tools.mkpath |  | ||||||
|     source_directory = download_and_unarchive( |  | ||||||
|       URI.parse("https://ftp.gnu.org/gnu/binutils/binutils-#{BINUTILS_VERSION}.tar.xz"), |  | ||||||
|       options.tools) |  | ||||||
|  |  | ||||||
|     cwd = source_directory.dirname + 'build-binutils' |  | ||||||
|     cwd.mkpath |  | ||||||
|     options.rootfs.mkpath |  | ||||||
|  |  | ||||||
|     env = { |  | ||||||
|      'CC' => options.gcc, |  | ||||||
|      'CXX' => options.gxx |  | ||||||
|     } |  | ||||||
|     configure_options = [ |  | ||||||
|       "--prefix=#{options.rootfs.realpath}", |  | ||||||
|       "--target=#{options.target}", |  | ||||||
|       '--disable-nls', |  | ||||||
|       '--enable-gprofng=no', |  | ||||||
|       '--disable-werror', |  | ||||||
|       '--enable-default-hash-style=gnu', |  | ||||||
|       '--disable-libquadmath' |  | ||||||
|     ] |  | ||||||
|     configure = source_directory.relative_path_from(cwd) + 'configure' |  | ||||||
|     sh env, configure.to_path, *configure_options, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', 'install', chdir: cwd.to_path |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   desc 'Build stage 1 GCC' |  | ||||||
|   task :gcc1, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     options.tools.mkpath |  | ||||||
|     source_directory = download_and_unarchive( |  | ||||||
|       URI.parse("https://gcc.gnu.org/pub/gcc/releases/gcc-#{GCC_VERSION}/gcc-#{GCC_VERSION}.tar.xz"), |  | ||||||
|       options.tools) |  | ||||||
|  |  | ||||||
|     cwd = source_directory.dirname + 'build-gcc' |  | ||||||
|     cwd.mkpath |  | ||||||
|     options.rootfs.mkpath |  | ||||||
|     options.sysroot.mkpath |  | ||||||
|  |  | ||||||
|     sh 'contrib/download_prerequisites', chdir: source_directory.to_path |  | ||||||
|     configure_options = [ |  | ||||||
|       "--prefix=#{options.rootfs.realpath}", |  | ||||||
|       "--with-sysroot=#{options.sysroot.realpath}", |  | ||||||
|       '--enable-languages=c,c++', |  | ||||||
|       '--disable-shared', |  | ||||||
|       '--with-arch=rv32imafdc', |  | ||||||
|       '--with-abi=ilp32d', |  | ||||||
|       '--with-tune=rocket', |  | ||||||
|       '--with-isa-spec=20191213', |  | ||||||
|       '--disable-bootstrap', |  | ||||||
|       '--disable-multilib', |  | ||||||
|       '--disable-libmudflap', |  | ||||||
|       '--disable-libssp', |  | ||||||
|       '--disable-libquadmath', |  | ||||||
|       '--disable-libsanitizer', |  | ||||||
|       '--disable-threads', |  | ||||||
|       '--disable-libatomic', |  | ||||||
|       '--disable-libgomp', |  | ||||||
|       '--disable-libvtv', |  | ||||||
|       '--disable-libstdcxx', |  | ||||||
|       '--disable-nls', |  | ||||||
|       '--with-newlib', |  | ||||||
|       '--without-headers', |  | ||||||
|       "--target=#{options.target}", |  | ||||||
|       "--build=#{options.build}", |  | ||||||
|       "--host=#{options.build}" |  | ||||||
|     ] |  | ||||||
|     flags = '-O2 -fPIC' |  | ||||||
|     env = { |  | ||||||
|       'CC' => options.gcc, |  | ||||||
|       'CXX' => options.gxx, |  | ||||||
|       'CFLAGS' => flags, |  | ||||||
|       'CXXFLAGS' => flags, |  | ||||||
|       'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}" |  | ||||||
|     } |  | ||||||
|     configure = source_directory.relative_path_from(cwd) + 'configure' |  | ||||||
|     sh env, configure.to_path, *configure_options, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', 'install', chdir: cwd.to_path |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   desc 'Copy glibc headers' |  | ||||||
|   task :headers, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     options.tools.mkpath |  | ||||||
|  |  | ||||||
|     source_directory = download_and_unarchive( |  | ||||||
|       URI.parse("https://ftp.gnu.org/gnu/glibc/glibc-#{GLIBC_VERSION}.tar.xz"), |  | ||||||
|       options.tools) |  | ||||||
|     include_directory = options.tools + 'include' |  | ||||||
|  |  | ||||||
|     include_directory.mkpath |  | ||||||
|     cp (source_directory + 'elf/elf.h'), (include_directory + 'elf.h') |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   desc 'Build linux kernel' |  | ||||||
|   task :kernel, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     options.tools.mkpath |  | ||||||
|  |  | ||||||
|     cwd = download_and_unarchive( |  | ||||||
|       URI.parse("https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-#{KERNEL_VERSION}.tar.xz"), |  | ||||||
|       options.tools) |  | ||||||
|  |  | ||||||
|     env = { |  | ||||||
|       'CROSS_COMPILE' => "#{options.target}-", |  | ||||||
|       'ARCH' => 'riscv', |  | ||||||
|       'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}", |  | ||||||
|       'HOSTCFLAGS' => "-D_UUID_T -D__GETHOSTUUID_H -I#{options.tools.realpath + 'include'}" |  | ||||||
|     } |  | ||||||
|     sh env, 'make', 'rv32_defconfig', chdir: cwd.to_path |  | ||||||
|     sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', 'headers', chdir: cwd.to_path |  | ||||||
|  |  | ||||||
|     user_directory = options.sysroot + 'usr' |  | ||||||
|  |  | ||||||
|     user_directory.mkpath |  | ||||||
|     cp_r (cwd + 'usr/include'), (user_directory + 'include') |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   desc 'Build glibc' |  | ||||||
|   task :glibc, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     source_directory = options.tools + "glibc-#{GLIBC_VERSION}" |  | ||||||
|     configure_options = [ |  | ||||||
|       '--prefix=/usr', |  | ||||||
|       "--host=#{options.target}", |  | ||||||
|       "--target=#{options.target}", |  | ||||||
|       "--build=#{options.build}", |  | ||||||
|       "--enable-kernel=#{KERNEL_VERSION}", |  | ||||||
|       "--with-headers=#{options.sysroot.realpath + 'usr/include'}", |  | ||||||
|       '--disable-nscd', |  | ||||||
|       '--disable-libquadmath', |  | ||||||
|       '--disable-libitm', |  | ||||||
|       '--disable-werror', |  | ||||||
|       'libc_cv_forced_unwind=yes' |  | ||||||
|     ] |  | ||||||
|     bin = options.rootfs.realpath + 'bin' |  | ||||||
|     env = { |  | ||||||
|       'PATH' => "#{bin}:#{ENV['PATH']}", |  | ||||||
|       'MAKE' => 'make' # Otherwise it uses gnumake which can be different and too old. |  | ||||||
|     } |  | ||||||
|     cwd = source_directory.dirname + 'build-glibc' |  | ||||||
|     cwd.mkpath |  | ||||||
|  |  | ||||||
|     configure = source_directory.relative_path_from(cwd) +'./configure' |  | ||||||
|     sh env, configure.to_path, *configure_options, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', "install_root=#{options.sysroot.realpath}", 'install', chdir: cwd.to_path |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   desc 'Build stage 2 GCC' |  | ||||||
|   task :gcc2, [:target] do |_, args| |  | ||||||
|     options = find_build_target GCC_VERSION, args |  | ||||||
|     source_directory = options.tools + "gcc-#{GCC_VERSION}" |  | ||||||
|     cwd = options.tools + 'build-gcc' |  | ||||||
|  |  | ||||||
|     rm_rf cwd |  | ||||||
|     cwd.mkpath |  | ||||||
|  |  | ||||||
|     configure_options = [ |  | ||||||
|       "--prefix=#{options.rootfs.realpath}", |  | ||||||
|       "--with-sysroot=#{options.sysroot.realpath}", |  | ||||||
|       '--enable-languages=c,c++,lto', |  | ||||||
|       '--enable-lto', |  | ||||||
|       '--enable-shared', |  | ||||||
|       '--with-arch=rv32imafdc', |  | ||||||
|       '--with-abi=ilp32d', |  | ||||||
|       '--with-tune=rocket', |  | ||||||
|       '--with-isa-spec=20191213', |  | ||||||
|       '--disable-bootstrap', |  | ||||||
|       '--disable-multilib', |  | ||||||
|       '--enable-checking=release', |  | ||||||
|       '--disable-libssp', |  | ||||||
|       '--disable-libquadmath', |  | ||||||
|       '--enable-threads=posix', |  | ||||||
|       '--with-default-libstdcxx-abi=new', |  | ||||||
|       '--disable-nls', |  | ||||||
|       "--target=#{options.target}", |  | ||||||
|       "--build=#{options.build}", |  | ||||||
|       "--host=#{options.build}" |  | ||||||
|  |  | ||||||
|     ] |  | ||||||
|     flags = '-O2 -fPIC' |  | ||||||
|     env = { |  | ||||||
|       'CFLAGS' => flags, |  | ||||||
|       'CXXFLAGS' => flags, |  | ||||||
|       'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}" |  | ||||||
|     } |  | ||||||
|     configure = source_directory.relative_path_from(cwd) + 'configure' |  | ||||||
|     sh env, configure.to_path, *configure_options, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path |  | ||||||
|     sh env, 'make', 'install', chdir: cwd.to_path |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  |  | ||||||
| desc 'Build cross toolchain' |  | ||||||
| task cross: [ |  | ||||||
|   'cross:binutils', |  | ||||||
|   'cross:gcc1', |  | ||||||
|   'cross:headers', |  | ||||||
|   'cross:kernel', |  | ||||||
|   'cross:glibc', |  | ||||||
|   'cross:gcc2' |  | ||||||
| ] do |  | ||||||
| end |  | ||||||
		Reference in New Issue
	
	Block a user