Experimental compiler for a minimalistic, specialized language that targets NASM x86_64 assembly on Linux.
- minimalistic language
- gain experience writing compilers
- generate handwritten-like assembler compiled by NASM for x86_64
- super loop program with non-reentrant inlined functions
- built-in integer types (64, 32, 16, 8 bit)
- built-in boolean type
- user defined types
- inlined functions
- keywords:
func
,field
,var
,loop
,if
,else
,continue
,break
,return
- to compile the compiler that compiles
prog.baz
and assembles the generated code run./make.sh
- after that use
./run-baz.sh myprogram.baz
or./run-baz.sh
to compile and runprog.baz
- to run the tests
qa/coverage/run-tests.sh
and see coverage report inqa/coverage/report/
Language files blank comment code
-------------------------------------------------------------------------------
C/C++ Header 35 791 533 4262
C++ 1 51 64 385
-------------------------------------------------------------------------------
SUM: 36 842 597 4647
-------------------------------------------------------------------------------
field hello = "hello world from baz\n"
field input = "............................................................"
field prompt1 = "enter name:\n"
field prompt2 = "that is not a name.\n"
field prompt3 = "hello "
field dot = "."
field nl = "\n"
# all functions are inlined
# arguments can be placed in specified register using `reg_...` syntax
func exit(v : reg_rdi) {
mov(rax, 60) # exit system call
mov(rdi, v) # return code
syscall()
}
func print(len : reg_rdx, ptr : reg_rsi) {
mov(rax, 1) # write system call
mov(rdi, 1) # file descriptor for standard out
mov(rsi, ptr) # buffer address
mov(rdx, len) # buffer size
syscall()
}
func read(len : reg_rdx, ptr : reg_rsi) : i64 nbytes {
mov(rax, 0) # read system call
mov(rdi, 0) # file descriptor for standard input
mov(rsi, ptr) # buffer address
mov(rdx, len) # buffer size
syscall()
mov(nbytes, rax) # return value
}
func assert(expr : bool) {
if not expr exit(1)
}
# user types are defined using keyword `type`
# default type is `i64` and does not need to be specified
type point {x, y}
type object {pos : point, color : i32}
# function arguments are equivalent to mutable references
func foo(pt : point) {
pt.x = 0b10 # binary value 2
pt.y = 0xb # hex value 11
}
# default argument type is `i64`
func bar(arg) {
if arg == 0 return
arg = 0xff
}
# return target is specified as a variable, in this case `res`
func baz(arg) : i64 res {
res = arg * 2
}
func main() {
var p : point = {0, 0}
foo(p)
assert(p.x == 2)
assert(p.y == 0xb)
var i = 0
bar(i)
assert(i == 0)
i = 1
bar(i)
assert(i == 0xff)
var j = 1
var k = baz(j)
assert(k == 2)
k = baz(1)
assert(k == 2)
var p0 : point = {baz(2), 0}
assert(p0.x == 4)
var x = 1
var y = 2
var o1 : object = {{x * 10, y}, 0xff0000}
assert(o1.pos.x == 10)
assert(o1.pos.y == 2)
assert(o1.color == 0xff0000)
var p1 : point = {-x, -y}
o1.pos = p1
assert(o1.pos.x == -1)
assert(o1.pos.y == -2)
var o2 : object = o1
assert(o2.pos.x == -1)
assert(o2.pos.y == -2)
assert(o2.color == 0xff0000)
print(hello.len, hello)
loop {
print(prompt1.len, prompt1)
var len = read(input.len, input) - 1 # -1 don't include the '\n'
if len == 0 {
break
} else if len <= 4 {
print(prompt2.len, prompt2)
continue
} else {
print(prompt3.len, prompt3)
print(len, input)
print(dot.len, dot)
print(nl.len, nl)
}
}
}
; generated by baz
section .bss
stk resd 1024
stk.end:
true equ 1
false equ 0
section .data
;[1:1] field hello = "hello world from baz\n"
hello: db 'hello world from baz',10,''
hello.len equ $-hello
;[2:1] field input = "............................................................"
input: db '............................................................'
input.len equ $-input
;[3:1] field prompt1 = "enter name:\n"
prompt1: db 'enter name:',10,''
prompt1.len equ $-prompt1
;[4:1] field prompt2 = "that is not a name.\n"
prompt2: db 'that is not a name.',10,''
prompt2.len equ $-prompt2
;[5:1] field prompt3 = "hello "
prompt3: db 'hello '
prompt3.len equ $-prompt3
;[6:1] field dot = "."
dot: db '.'
dot.len equ $-dot
;[7:1] field nl = "\n"
nl: db '',10,''
nl.len equ $-nl
section .text
bits 64
global _start
_start:
mov rsp,stk.end
; program
;[9:1] # all functions are inlined
;[11:1] # arguments can be placed in specified register using `reg_...` syntax
;[39:1] # user types are defined using keyword `type`
;[41:1] # default type is `i64` and does not need to be specified
;[46:1] # function arguments are equivalent to mutable references
;[52:1] # default argument type is `i64`
;[58:1] # return target is specified as a variable, in this case `res`
main:
; var p: point @ qword[rsp-16]
; [64:5] var p : point = {0, 0}
; [64:9] p : point = {0, 0}
; [64:21] {0, 0}
; [64:21] {0, 0}
; [64:22] 0
; [64:22] 0
; [64:22] p.x = 0
mov qword[rsp-16], 0
; [64:25] 0
; [64:25] 0
; [64:25] p.y = 0
mov qword[rsp-8], 0
; [65:5] foo(p)
; foo(pt : point)
foo_65_5:
; alias pt -> p
; [48:5] pt.x = 0b10
; [48:12] 0b10
; [48:12] 0b10
; [48:12] pt.x = 0b10
mov qword[rsp-16], 0b10
; [48:20] # binary value 2
; [49:5] pt.y = 0xb
; [49:12] 0xb
; [49:12] 0xb
; [49:12] pt.y = 0xb
mov qword[rsp-8], 0xb
; [49:20] # hex value 11
foo_65_5_end:
; [66:5] assert(p.x == 2)
; alloc r15
; [66:12] p.x == 2
; [66:12] ? p.x == 2
; [66:12] ? p.x == 2
cmp_66_12:
cmp qword[rsp-16], 2
jne bool_false_66_12
bool_true_66_12: ; opt1
mov r15, true
jmp bool_end_66_12
bool_false_66_12:
mov r15, false
bool_end_66_12:
; assert(expr : bool)
assert_66_5:
; alias expr -> r15
if_36_8_66_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_66_5:
cmp r15, false
jne if_36_5_66_5_end
if_36_8_66_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_66_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_66_5_end:
if_36_5_66_5_end:
; free r15
assert_66_5_end:
; [67:5] assert(p.y == 0xb)
; alloc r15
; [67:12] p.y == 0xb
; [67:12] ? p.y == 0xb
; [67:12] ? p.y == 0xb
cmp_67_12:
cmp qword[rsp-8], 0xb
jne bool_false_67_12
bool_true_67_12: ; opt1
mov r15, true
jmp bool_end_67_12
bool_false_67_12:
mov r15, false
bool_end_67_12:
; assert(expr : bool)
assert_67_5:
; alias expr -> r15
if_36_8_67_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_67_5:
cmp r15, false
jne if_36_5_67_5_end
if_36_8_67_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_67_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_67_5_end:
if_36_5_67_5_end:
; free r15
assert_67_5_end:
; var i: i64 @ qword[rsp-24]
; [69:5] var i = 0
; [69:9] i = 0
; [69:13] 0
; [69:13] 0
; [69:13] i = 0
mov qword[rsp-24], 0
; [70:5] bar(i)
; bar(arg)
bar_70_5:
; alias arg -> i
if_54_8_70_5:
; [54:8] ? arg == 0
; [54:8] ? arg == 0
cmp_54_8_70_5:
cmp qword[rsp-24], 0
jne if_54_5_70_5_end
if_54_8_70_5_code: ; opt1
; [54:17] return
jmp bar_70_5_end
if_54_5_70_5_end:
; [55:5] arg = 0xff
; [55:11] 0xff
; [55:11] 0xff
; [55:11] arg = 0xff
mov qword[rsp-24], 0xff
bar_70_5_end:
; [71:5] assert(i == 0)
; alloc r15
; [71:12] i == 0
; [71:12] ? i == 0
; [71:12] ? i == 0
cmp_71_12:
cmp qword[rsp-24], 0
jne bool_false_71_12
bool_true_71_12: ; opt1
mov r15, true
jmp bool_end_71_12
bool_false_71_12:
mov r15, false
bool_end_71_12:
; assert(expr : bool)
assert_71_5:
; alias expr -> r15
if_36_8_71_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_71_5:
cmp r15, false
jne if_36_5_71_5_end
if_36_8_71_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_71_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_71_5_end:
if_36_5_71_5_end:
; free r15
assert_71_5_end:
; [73:5] i = 1
; [73:9] 1
; [73:9] 1
; [73:9] i = 1
mov qword[rsp-24], 1
; [74:5] bar(i)
; bar(arg)
bar_74_5:
; alias arg -> i
if_54_8_74_5:
; [54:8] ? arg == 0
; [54:8] ? arg == 0
cmp_54_8_74_5:
cmp qword[rsp-24], 0
jne if_54_5_74_5_end
if_54_8_74_5_code: ; opt1
; [54:17] return
jmp bar_74_5_end
if_54_5_74_5_end:
; [55:5] arg = 0xff
; [55:11] 0xff
; [55:11] 0xff
; [55:11] arg = 0xff
mov qword[rsp-24], 0xff
bar_74_5_end:
; [75:5] assert(i == 0xff)
; alloc r15
; [75:12] i == 0xff
; [75:12] ? i == 0xff
; [75:12] ? i == 0xff
cmp_75_12:
cmp qword[rsp-24], 0xff
jne bool_false_75_12
bool_true_75_12: ; opt1
mov r15, true
jmp bool_end_75_12
bool_false_75_12:
mov r15, false
bool_end_75_12:
; assert(expr : bool)
assert_75_5:
; alias expr -> r15
if_36_8_75_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_75_5:
cmp r15, false
jne if_36_5_75_5_end
if_36_8_75_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_75_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_75_5_end:
if_36_5_75_5_end:
; free r15
assert_75_5_end:
; var j: i64 @ qword[rsp-32]
; [77:5] var j = 1
; [77:9] j = 1
; [77:13] 1
; [77:13] 1
; [77:13] j = 1
mov qword[rsp-32], 1
; var k: i64 @ qword[rsp-40]
; [78:5] var k = baz(j)
; [78:9] k = baz(j)
; [78:13] baz(j)
; [78:13] baz(j)
; [78:13] k = baz(j)
; [78:13] baz(j)
; baz(arg) : i64 res
baz_78_13:
; alias res -> k
; alias arg -> j
; [60:5] res = arg * 2
; [60:11] arg * 2
; [60:11] arg * 2
; [60:11] res = arg
; alloc r15
mov r15, qword[rsp-32]
mov qword[rsp-40], r15
; free r15
; [60:17] res * 2
; alloc r15
mov r15, qword[rsp-40]
imul r15, 2
mov qword[rsp-40], r15
; free r15
baz_78_13_end:
; [79:5] assert(k == 2)
; alloc r15
; [79:12] k == 2
; [79:12] ? k == 2
; [79:12] ? k == 2
cmp_79_12:
cmp qword[rsp-40], 2
jne bool_false_79_12
bool_true_79_12: ; opt1
mov r15, true
jmp bool_end_79_12
bool_false_79_12:
mov r15, false
bool_end_79_12:
; assert(expr : bool)
assert_79_5:
; alias expr -> r15
if_36_8_79_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_79_5:
cmp r15, false
jne if_36_5_79_5_end
if_36_8_79_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_79_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_79_5_end:
if_36_5_79_5_end:
; free r15
assert_79_5_end:
; [81:5] k = baz(1)
; [81:9] baz(1)
; [81:9] baz(1)
; [81:9] k = baz(1)
; [81:9] baz(1)
; baz(arg) : i64 res
baz_81_9:
; alias res -> k
; alias arg -> 1
; [60:5] res = arg * 2
; [60:11] arg * 2
; [60:11] arg * 2
; [60:11] res = arg
mov qword[rsp-40], 1
; [60:17] res * 2
; alloc r15
mov r15, qword[rsp-40]
imul r15, 2
mov qword[rsp-40], r15
; free r15
baz_81_9_end:
; [82:5] assert(k == 2)
; alloc r15
; [82:12] k == 2
; [82:12] ? k == 2
; [82:12] ? k == 2
cmp_82_12:
cmp qword[rsp-40], 2
jne bool_false_82_12
bool_true_82_12: ; opt1
mov r15, true
jmp bool_end_82_12
bool_false_82_12:
mov r15, false
bool_end_82_12:
; assert(expr : bool)
assert_82_5:
; alias expr -> r15
if_36_8_82_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_82_5:
cmp r15, false
jne if_36_5_82_5_end
if_36_8_82_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_82_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_82_5_end:
if_36_5_82_5_end:
; free r15
assert_82_5_end:
; var p0: point @ qword[rsp-56]
; [84:5] var p0 : point = {baz(2), 0}
; [84:9] p0 : point = {baz(2), 0}
; [84:22] {baz(2), 0}
; [84:22] {baz(2), 0}
; [84:23] baz(2)
; [84:23] baz(2)
; [84:23] p0.x = baz(2)
; [84:23] baz(2)
; baz(arg) : i64 res
baz_84_23:
; alias res -> p0.x
; alias arg -> 2
; [60:5] res = arg * 2
; [60:11] arg * 2
; [60:11] arg * 2
; [60:11] res = arg
mov qword[rsp-56], 2
; [60:17] res * 2
; alloc r15
mov r15, qword[rsp-56]
imul r15, 2
mov qword[rsp-56], r15
; free r15
baz_84_23_end:
; [84:31] 0
; [84:31] 0
; [84:31] p0.y = 0
mov qword[rsp-48], 0
; [85:5] assert(p0.x == 4)
; alloc r15
; [85:12] p0.x == 4
; [85:12] ? p0.x == 4
; [85:12] ? p0.x == 4
cmp_85_12:
cmp qword[rsp-56], 4
jne bool_false_85_12
bool_true_85_12: ; opt1
mov r15, true
jmp bool_end_85_12
bool_false_85_12:
mov r15, false
bool_end_85_12:
; assert(expr : bool)
assert_85_5:
; alias expr -> r15
if_36_8_85_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_85_5:
cmp r15, false
jne if_36_5_85_5_end
if_36_8_85_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_85_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_85_5_end:
if_36_5_85_5_end:
; free r15
assert_85_5_end:
; var x: i64 @ qword[rsp-64]
; [87:5] var x = 1
; [87:9] x = 1
; [87:13] 1
; [87:13] 1
; [87:13] x = 1
mov qword[rsp-64], 1
; var y: i64 @ qword[rsp-72]
; [88:5] var y = 2
; [88:9] y = 2
; [88:13] 2
; [88:13] 2
; [88:13] y = 2
mov qword[rsp-72], 2
; var o1: object @ qword[rsp-92]
; [90:5] var o1 : object = {{x * 10, y}, 0xff0000}
; [90:9] o1 : object = {{x * 10, y}, 0xff0000}
; [90:23] {{x * 10, y}, 0xff0000}
; [90:23] {{x * 10, y}, 0xff0000}
; [90:24] {x * 10, y}
; [90:25] x * 10
; [90:25] x * 10
; [90:25] o1.pos.x = x
; alloc r15
mov r15, qword[rsp-64]
mov qword[rsp-92], r15
; free r15
; [90:29] o1.pos.x * 10
; alloc r15
mov r15, qword[rsp-92]
imul r15, 10
mov qword[rsp-92], r15
; free r15
; [90:33] y
; [90:33] y
; [90:33] o1.pos.y = y
; alloc r15
mov r15, qword[rsp-72]
mov qword[rsp-84], r15
; free r15
; [90:37] 0xff0000
; [90:37] 0xff0000
; [90:37] o1.color = 0xff0000
mov dword[rsp-76], 0xff0000
; [91:5] assert(o1.pos.x == 10)
; alloc r15
; [91:12] o1.pos.x == 10
; [91:12] ? o1.pos.x == 10
; [91:12] ? o1.pos.x == 10
cmp_91_12:
cmp qword[rsp-92], 10
jne bool_false_91_12
bool_true_91_12: ; opt1
mov r15, true
jmp bool_end_91_12
bool_false_91_12:
mov r15, false
bool_end_91_12:
; assert(expr : bool)
assert_91_5:
; alias expr -> r15
if_36_8_91_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_91_5:
cmp r15, false
jne if_36_5_91_5_end
if_36_8_91_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_91_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_91_5_end:
if_36_5_91_5_end:
; free r15
assert_91_5_end:
; [92:5] assert(o1.pos.y == 2)
; alloc r15
; [92:12] o1.pos.y == 2
; [92:12] ? o1.pos.y == 2
; [92:12] ? o1.pos.y == 2
cmp_92_12:
cmp qword[rsp-84], 2
jne bool_false_92_12
bool_true_92_12: ; opt1
mov r15, true
jmp bool_end_92_12
bool_false_92_12:
mov r15, false
bool_end_92_12:
; assert(expr : bool)
assert_92_5:
; alias expr -> r15
if_36_8_92_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_92_5:
cmp r15, false
jne if_36_5_92_5_end
if_36_8_92_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_92_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_92_5_end:
if_36_5_92_5_end:
; free r15
assert_92_5_end:
; [93:5] assert(o1.color == 0xff0000)
; alloc r15
; [93:12] o1.color == 0xff0000
; [93:12] ? o1.color == 0xff0000
; [93:12] ? o1.color == 0xff0000
cmp_93_12:
cmp dword[rsp-76], 0xff0000
jne bool_false_93_12
bool_true_93_12: ; opt1
mov r15, true
jmp bool_end_93_12
bool_false_93_12:
mov r15, false
bool_end_93_12:
; assert(expr : bool)
assert_93_5:
; alias expr -> r15
if_36_8_93_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_93_5:
cmp r15, false
jne if_36_5_93_5_end
if_36_8_93_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_93_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_93_5_end:
if_36_5_93_5_end:
; free r15
assert_93_5_end:
; var p1: point @ qword[rsp-108]
; [95:5] var p1 : point = {-x, -y}
; [95:9] p1 : point = {-x, -y}
; [95:22] {-x, -y}
; [95:22] {-x, -y}
; [95:23] -x
; [95:23] -x
; [95:24] p1.x = -x
; alloc r15
mov r15, qword[rsp-64]
mov qword[rsp-108], r15
; free r15
neg qword[rsp-108]
; [95:27] -y
; [95:27] -y
; [95:28] p1.y = -y
; alloc r15
mov r15, qword[rsp-72]
mov qword[rsp-100], r15
; free r15
neg qword[rsp-100]
; [96:5] o1.pos = p1
; [96:14] p1
; [96:14] p1
; alloc r15
mov r15, qword[rsp-108]
mov qword[rsp-92], r15
; free r15
; alloc r15
mov r15, qword[rsp-100]
mov qword[rsp-84], r15
; free r15
; [97:5] assert(o1.pos.x == -1)
; alloc r15
; [97:12] o1.pos.x == -1
; [97:12] ? o1.pos.x == -1
; [97:12] ? o1.pos.x == -1
cmp_97_12:
cmp qword[rsp-92], -1
jne bool_false_97_12
bool_true_97_12: ; opt1
mov r15, true
jmp bool_end_97_12
bool_false_97_12:
mov r15, false
bool_end_97_12:
; assert(expr : bool)
assert_97_5:
; alias expr -> r15
if_36_8_97_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_97_5:
cmp r15, false
jne if_36_5_97_5_end
if_36_8_97_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_97_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_97_5_end:
if_36_5_97_5_end:
; free r15
assert_97_5_end:
; [98:5] assert(o1.pos.y == -2)
; alloc r15
; [98:12] o1.pos.y == -2
; [98:12] ? o1.pos.y == -2
; [98:12] ? o1.pos.y == -2
cmp_98_12:
cmp qword[rsp-84], -2
jne bool_false_98_12
bool_true_98_12: ; opt1
mov r15, true
jmp bool_end_98_12
bool_false_98_12:
mov r15, false
bool_end_98_12:
; assert(expr : bool)
assert_98_5:
; alias expr -> r15
if_36_8_98_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_98_5:
cmp r15, false
jne if_36_5_98_5_end
if_36_8_98_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_98_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_98_5_end:
if_36_5_98_5_end:
; free r15
assert_98_5_end:
; var o2: object @ qword[rsp-128]
; [100:5] var o2 : object = o1
; [100:9] o2 : object = o1
; [100:23] o1
; [100:23] o1
; [100:23] o1
; alloc r15
mov r15, qword[rsp-92]
mov qword[rsp-128], r15
; free r15
; alloc r15
mov r15, qword[rsp-84]
mov qword[rsp-120], r15
; free r15
; alloc r15
mov r15d, dword[rsp-76]
mov dword[rsp-112], r15d
; free r15
; [101:5] assert(o2.pos.x == -1)
; alloc r15
; [101:12] o2.pos.x == -1
; [101:12] ? o2.pos.x == -1
; [101:12] ? o2.pos.x == -1
cmp_101_12:
cmp qword[rsp-128], -1
jne bool_false_101_12
bool_true_101_12: ; opt1
mov r15, true
jmp bool_end_101_12
bool_false_101_12:
mov r15, false
bool_end_101_12:
; assert(expr : bool)
assert_101_5:
; alias expr -> r15
if_36_8_101_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_101_5:
cmp r15, false
jne if_36_5_101_5_end
if_36_8_101_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_101_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_101_5_end:
if_36_5_101_5_end:
; free r15
assert_101_5_end:
; [102:5] assert(o2.pos.y == -2)
; alloc r15
; [102:12] o2.pos.y == -2
; [102:12] ? o2.pos.y == -2
; [102:12] ? o2.pos.y == -2
cmp_102_12:
cmp qword[rsp-120], -2
jne bool_false_102_12
bool_true_102_12: ; opt1
mov r15, true
jmp bool_end_102_12
bool_false_102_12:
mov r15, false
bool_end_102_12:
; assert(expr : bool)
assert_102_5:
; alias expr -> r15
if_36_8_102_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_102_5:
cmp r15, false
jne if_36_5_102_5_end
if_36_8_102_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_102_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_102_5_end:
if_36_5_102_5_end:
; free r15
assert_102_5_end:
; [103:5] assert(o2.color == 0xff0000)
; alloc r15
; [103:12] o2.color == 0xff0000
; [103:12] ? o2.color == 0xff0000
; [103:12] ? o2.color == 0xff0000
cmp_103_12:
cmp dword[rsp-112], 0xff0000
jne bool_false_103_12
bool_true_103_12: ; opt1
mov r15, true
jmp bool_end_103_12
bool_false_103_12:
mov r15, false
bool_end_103_12:
; assert(expr : bool)
assert_103_5:
; alias expr -> r15
if_36_8_103_5:
; [36:8] ? not expr
; [36:8] ? not expr
cmp_36_8_103_5:
cmp r15, false
jne if_36_5_103_5_end
if_36_8_103_5_code: ; opt1
; [36:17] exit(1)
; alloc rdi
mov rdi, 1
; exit(v : reg_rdi)
exit_36_17_103_5:
; alias v -> rdi
; [13:5] mov(rax, 60)
mov rax, 60
; [13:19] # exit system call
; [14:5] mov(rdi, v)
; [14:19] # return code
; [15:5] syscall()
syscall
; free rdi
exit_36_17_103_5_end:
if_36_5_103_5_end:
; free r15
assert_103_5_end:
; [105:5] print(hello.len, hello)
; alloc rdx
mov rdx, hello.len
; alloc rsi
mov rsi, hello
; print(len : reg_rdx, ptr : reg_rsi)
print_105_5:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_105_5_end:
; [106:5] loop
loop_106_5:
; [107:9] print(prompt1.len, prompt1)
; alloc rdx
mov rdx, prompt1.len
; alloc rsi
mov rsi, prompt1
; print(len : reg_rdx, ptr : reg_rsi)
print_107_9:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_107_9_end:
; var len: i64 @ qword[rsp-136]
; [108:9] var len = read(input.len, input) - 1
; [108:13] len = read(input.len, input) - 1
; [108:19] read(input.len, input) - 1
; [108:19] read(input.len, input) - 1
; [108:19] len = read(input.len, input)
; [108:19] read(input.len, input)
; alloc rdx
mov rdx, input.len
; alloc rsi
mov rsi, input
; read(len : reg_rdx, ptr : reg_rsi) : i64 nbytes
read_108_19:
; alias nbytes -> len
; alias len -> rdx
; alias ptr -> rsi
; [27:5] mov(rax, 0)
mov rax, 0
; [27:19] # read system call
; [28:5] mov(rdi, 0)
mov rdi, 0
; [28:19] # file descriptor for standard input
; [29:5] mov(rsi, ptr)
; [29:19] # buffer address
; [30:5] mov(rdx, len)
; [30:19] # buffer size
; [31:5] syscall()
syscall
; [32:5] mov(nbytes, rax)
mov qword[rsp-136], rax
; [32:22] # return value
; free rsi
; free rdx
read_108_19_end:
; [108:44] len - 1
sub qword[rsp-136], 1
; [108:49] # -1 don't include the '\n'
if_109_12:
; [109:12] ? len == 0
; [109:12] ? len == 0
cmp_109_12:
cmp qword[rsp-136], 0
jne if_111_19
if_109_12_code: ; opt1
; [110:13] break
jmp loop_106_5_end
jmp if_109_9_end
if_111_19:
; [111:19] ? len <= 4
; [111:19] ? len <= 4
cmp_111_19:
cmp qword[rsp-136], 4
jg if_else_109_9
if_111_19_code: ; opt1
; [112:13] print(prompt2.len, prompt2)
; alloc rdx
mov rdx, prompt2.len
; alloc rsi
mov rsi, prompt2
; print(len : reg_rdx, ptr : reg_rsi)
print_112_13:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_112_13_end:
; [113:13] continue
jmp loop_106_5
jmp if_109_9_end
if_else_109_9:
; [115:13] print(prompt3.len, prompt3)
; alloc rdx
mov rdx, prompt3.len
; alloc rsi
mov rsi, prompt3
; print(len : reg_rdx, ptr : reg_rsi)
print_115_13:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_115_13_end:
; [116:13] print(len, input)
; alloc rdx
mov rdx, qword[rsp-136]
; alloc rsi
mov rsi, input
; print(len : reg_rdx, ptr : reg_rsi)
print_116_13:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_116_13_end:
; [117:13] print(dot.len, dot)
; alloc rdx
mov rdx, dot.len
; alloc rsi
mov rsi, dot
; print(len : reg_rdx, ptr : reg_rsi)
print_117_13:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_117_13_end:
; [118:13] print(nl.len, nl)
; alloc rdx
mov rdx, nl.len
; alloc rsi
mov rsi, nl
; print(len : reg_rdx, ptr : reg_rsi)
print_118_13:
; alias len -> rdx
; alias ptr -> rsi
; [19:5] mov(rax, 1)
mov rax, 1
; [19:19] # write system call
; [20:5] mov(rdi, 1)
mov rdi, 1
; [20:19] # file descriptor for standard out
; [21:5] mov(rsi, ptr)
; [21:19] # buffer address
; [22:5] mov(rdx, len)
; [22:19] # buffer size
; [23:5] syscall()
syscall
; free rsi
; free rdx
print_118_13_end:
if_109_9_end:
jmp loop_106_5
loop_106_5_end:
; system call: exit 0
mov rax, 60
mov rdi, 0
syscall
; max scratch registers in use: 3
; max frames in use: 7
; max stack size: 136 B