summaryrefslogtreecommitdiff
path: root/04b/in03
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-11-21 17:23:09 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-11-21 17:23:09 -0500
commitd03916a3f804c13805d0383e3d74ab446bf81d6e (patch)
treea948a73dbaa7118ecaff65bfe544558d375e3e04 /04b/in03
parent4b9596e8923982a3ae190b60ab1f4be56e7f2c4c (diff)
fix function prologue/epilogue, 2nd pass
Diffstat (limited to '04b/in03')
-rw-r--r--04b/in03213
1 files changed, 192 insertions, 21 deletions
diff --git a/04b/in03 b/04b/in03
index 0995296..cd4b4b1 100644
--- a/04b/in03
+++ b/04b/in03
@@ -34,6 +34,7 @@ A=d3
J=A
?J<0:output_file_error
+:second_pass_starting_point
; write ELF header
J=d4
I=:ELF_header
@@ -150,6 +151,24 @@ D=A
!:read_line
:eof
+ C=:second_pass
+ D=1C
+ ?D!0:exit_success
+ ; set 2nd pass to 1
+ 1C=d1
+ ; seek both files back to start
+ J=d3
+ I=d0
+ D=d0
+ syscall x8
+ J=d4
+ I=d0
+ D=d0
+ syscall x8
+
+ !:second_pass_starting_point
+
+:exit_success
J=d0
syscall x3c
@@ -177,7 +196,7 @@ align
C=:local_start
8C=I
J=:local_variables
- D=d9
+ D=d5
call :ident_lookup
C=A
?C!0:local_redeclaration
@@ -192,9 +211,9 @@ align
J+=d1
; store address
D=:stack_end
- D=8D
- 8J=D
- J+=d8
+ D=4D
+ 4J=D
+ J+=d4
; store null terminator
1J=0
; update :stack_end
@@ -222,6 +241,11 @@ align
reserve d8
:handle_global
+ ; ignore if this is the second pass
+ C=:second_pass
+ C=1C
+ ?C!0:read_line
+
; skip ' '
I+=d1
call :read_type
@@ -234,7 +258,7 @@ align
C=:global_start
8C=I
J=:global_variables
- D=d9
+ D=d5
call :ident_lookup
C=A
?C!0:global_redeclaration
@@ -250,9 +274,9 @@ align
J+=d1
; store address
D=:static_memory_end
- D=8D
- 8J=D
- J+=d8
+ D=4D
+ 4J=D
+ J+=d4
; store null terminator
1J=0
; update :static_memory_end
@@ -267,10 +291,10 @@ align
!:read_line
:handle_function
- ; emit "mov rbp, rsp"
+ ; emit prologue
J=d4
- I=:mov_rbp_rsp
- D=d3
+ I=:function_prologue
+ D=d14
syscall x1
; reset local variable table
@@ -282,10 +306,50 @@ align
; go read the next line
!:read_line
-:mov_rbp_rsp
+:function_prologue
+ ; sub rsp, 8
+ x48
+ x81
+ xec
+ x08
+ x00
+ x00
+ x00
+ ; mov [rsp], rbp
+ x48
+ x89
+ x2c
+ x24
+ ; mov rbp, rsp
R=S
+ ; total length: 7 + 4 + 3 = 14 bytes
+
+:function_epilogue
+ ; mov rsp, rbp
+ S=R
+ ; mov rbp, [rsp]
+ x48
+ x8b
+ x2c
+ x24
+ ; add rsp, 8
+ x48
+ x81
+ xc4
+ x08
+ x00
+ x00
+ x00
+ ; ret
+ return
+ ; total length = 15 bytes
:handle_label_definition
+ ; ignore if this is the second pass
+ C=:second_pass
+ C=1C
+ ?C!0:read_line
+
; make sure label only has identifier characters
I=:line
I+=d1
@@ -338,16 +402,9 @@ align
; @TODO: handle argument
- ; emit "mov rsp, rbp"
- J=d4
- I=:mov_rsp_rbp
- D=d3
- syscall x1
-
- ; emit "ret"
J=d4
- I=:ret
- D=d1
+ I=:function_epilogue
+ D=d15
syscall x1
; go read the next lines
@@ -391,6 +448,11 @@ align
; look up identifier rsi in list rdi with separation rdx between entries
; returns address of whatever's right after the identifier in the list, or 0 if not found
:ident_lookup
+ C=:second_pass
+ C=1C
+ ; use default of 0 on first pass
+ ?C!0:return_0
+
C=:ident_lookup_sep
8C=D
C=:ident_lookup_i
@@ -432,6 +494,104 @@ align
?B=A:return_1
!:return_0
+; set rax to the term in rsi
+:set_rax_to_term
+ R=I
+
+ C=1I
+ D=''
+ ?C=D:term_char
+
+ C=1I
+ D=d58
+ ?C<D:term_number
+
+ ; variable
+ J=:local_variables
+ D=d5
+ call :ident_lookup
+ C=A
+ ?C=0:rax2term_try_global
+ ; it's a local variable
+ ; skip over its type
+ C+=d1
+ ; read the offset from rbp
+ D=4C
+ ; put negated offset in rcx
+ C=d0
+ C-=D
+ ; store negated offset in :rax2term_addr
+ D=:rax2term_addr
+ 4D=C
+
+ J=d4
+ I=:load_rbp_offset_prefix
+ D=d3
+ syscall x1
+ J=d4
+ I=:rax2term_addr
+ D=d4
+ syscall x1
+
+
+ :rax2term_try_global
+ J=:global_variables
+ D=d5
+ call :ident_lookup
+ C=A
+ ?C=0:bad_term
+ ; it's a global variable
+ ; skip over its type
+ C+=d1
+ C=4C
+ D=:rax2term_addr
+ 4D=C
+
+ ; put address in rbx
+ J=d4
+ I=:mov_ebx_imm32_prefix
+ D=d1
+ syscall x1
+ J=d4
+ I=:rax2term_addr
+ D=d4
+ syscall x1
+
+ ; now load [rbx] into rax
+ J=d4
+ I=:mov_rax_[rbx]
+ D=d3
+ syscall x1
+
+ return
+
+:term_char
+ ; @TODO
+ xcc
+
+:term_number
+ ; @TODO
+ xcc
+
+align
+:rax2term_addr
+ reserve d4
+
+:mov_ebx_imm32_prefix
+ xbb
+
+:mov_rax_[rbx]
+ x48
+ x8b
+ x03
+
+; prefix for mov rax, [rbp+IMM32]
+:load_rbp_offset_prefix
+ x48
+ x8b
+ x85
+
+
; read the space-terminated type from rsi, advance rsi, and set rax to the corresponding type number:
; 0 for non-pointer types
; 1 for pointer to char
@@ -532,6 +692,15 @@ align
xa
x0
+:bad_term
+ B=:bad_term_error_message
+ !:program_error
+
+:bad_term_error_message
+ str Bad term.
+ xa
+ x0
+
:label_redefinition
B=:label_redefinition_error_message
!:program_error
@@ -796,6 +965,8 @@ align
reserve d20000
:labels
reserve d200000
+:second_pass
+ reserve d1
:ELF_header
x7f