1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-11 00:52:44 +03:00

Moving error handler into exceptions.asm

Needed by core routines, so will need to add
to earlier steps.
This commit is contained in:
Ben Dudson 2017-12-26 23:41:15 +00:00
parent e8915efe8e
commit e64592a1da
2 changed files with 163 additions and 135 deletions

138
nasm/exceptions.asm Normal file
View File

@ -0,0 +1,138 @@
;; ----------------------------------------------
;;
;; Error handling
;;
;; A handler consists of:
;; - A stack pointer address to reset to
;; - An address to jump to
;; - An optional data structure to pass
;;
;; When jumped to, an error handler will be given:
;; - the object thrown in RSI
;; - the optional data structure in RDI
;;
section .bss
;; Error handler list
error_handler: resq 1
section .text
;; Add an error handler to the front of the list
;;
;; Input: RSI - Stack pointer
;; RDI - Address to jump to
;; RCX - Data structure. Set to zero for none.
;; If not zero, reference count incremented
;;
;; Modifies registers:
;; RAX
;; RBX
error_handler_push:
call alloc_cons
; car will point to a list (stack, addr, data)
; cdr will point to the previous handler
mov [rax], BYTE (block_cons + container_list + content_pointer)
mov rbx, [error_handler]
cmp rbx, 0 ; Check if previous handler was zero
je .create_handler ; Zero, so leave null
; Not zero, so create pointer to it
mov [rax + Cons.typecdr], BYTE content_pointer
mov [rax + Cons.cdr], rbx
; note: not incrementing reference count, since
; we're replacing one reference with another
.create_handler:
mov [error_handler], rax ; new error handler
mov rdx, rax
call alloc_cons
mov [rdx + Cons.car], rax
; Store stack pointer
mov [rax], BYTE (block_cons + container_list + content_function)
mov [rax + Cons.car], rsi ; stack pointer
mov rdx, rax
call alloc_cons
mov [rdx + Cons.typecdr], BYTE content_pointer
mov [rdx + Cons.cdr], rax
; Store function pointer to jump to
; Note: This can't use content_pointer or release
; will try to release this memory address
mov [rax], BYTE (block_cons + container_list + content_function)
mov [rax + Cons.car], rdi
; Check if there is an object to pass to handler
cmp rcx, 0
je .done
; Set the final CDR to point to the object
mov [rax + Cons.typecdr], BYTE content_pointer
mov [rax + Cons.cdr], rcx
mov rsi, rcx
call incref_object
.done:
ret
;; Removes an error handler from the list
;;
;; Modifies registers:
;; RSI
;; RAX
;; RCX
error_handler_pop:
; get the address
mov rsi, [error_handler]
cmp rsi, 0
je .done ; Nothing to remove
push rsi
mov rsi, [rsi + Cons.cdr] ; next handler
mov [error_handler], rsi
;call incref_object ; needed because releasing soon
pop rsi ; handler being removed
mov [rsi + Cons.typecdr], BYTE 0
call release_cons
.done:
ret
;; Throw an error
;; Object to pass to handler should be in RSI
error_throw:
; Get the next error handler
mov rax, [error_handler]
cmp rax, 0
je .no_handler
; Got a handler
mov rax, [rax + Cons.car] ; handler
mov rbx, [rax + Cons.car] ; stack pointer
mov rax, [rax + Cons.cdr]
mov rcx, [rax + Cons.car] ; function
mov rdi, [rax + Cons.cdr] ; data structure
; Reset stack
mov rsp, rbx
; Jump to the handler
jmp rcx
.no_handler:
; Print the object in RSI then quit
cmp rsi, 0
je .done ; nothing to print
mov rdi, 1 ; print_readably
call pr_str
mov rsi, rax
call print_string
.done:
jmp quit_error

View File

@ -13,15 +13,13 @@ global _start
%include "reader.asm" ; String -> Data structures
%include "core.asm" ; Core functions
%include "printer.asm" ; Data structures -> String
%include "exceptions.asm" ; Error handling
section .bss
;; Top-level (REPL) environment
repl_env:resq 1
;; Error handler list
error_handler: resq 1
section .data
;; ------------------------------------------
@ -87,139 +85,9 @@ section .data
;; Command to run at start of REPL
static mal_startup_header, db "(println (str ",34,"Mal [",34," *host-language* ",34,"]",34,"))"
section .text
;; ----------------------------------------------
;;
;; Error handling
;;
;; A handler consists of:
;; - A stack pointer address to reset to
;; - An address to jump to
;; - An optional data structure to pass
;;
;; When jumped to, an error handler will be given:
;; - the object thrown in RSI
;; - the optional data structure in RDI
;;
;; Add an error handler to the front of the list
;;
;; Input: RSI - Stack pointer
;; RDI - Address to jump to
;; RCX - Data structure. Set to zero for none.
;; If not zero, reference count incremented
;;
;; Modifies registers:
;; RAX
;; RBX
error_handler_push:
call alloc_cons
; car will point to a list (stack, addr, data)
; cdr will point to the previous handler
mov [rax], BYTE (block_cons + container_list + content_pointer)
mov rbx, [error_handler]
cmp rbx, 0 ; Check if previous handler was zero
je .create_handler ; Zero, so leave null
; Not zero, so create pointer to it
mov [rax + Cons.typecdr], BYTE content_pointer
mov [rax + Cons.cdr], rbx
; note: not incrementing reference count, since
; we're replacing one reference with another
.create_handler:
mov [error_handler], rax ; new error handler
mov rdx, rax
call alloc_cons
mov [rdx + Cons.car], rax
; Store stack pointer
mov [rax], BYTE (block_cons + container_list + content_function)
mov [rax + Cons.car], rsi ; stack pointer
mov rdx, rax
call alloc_cons
mov [rdx + Cons.typecdr], BYTE content_pointer
mov [rdx + Cons.cdr], rax
; Store function pointer to jump to
; Note: This can't use content_pointer or release
; will try to release this memory address
mov [rax], BYTE (block_cons + container_list + content_function)
mov [rax + Cons.car], rdi
; Check if there is an object to pass to handler
cmp rcx, 0
je .done
; Set the final CDR to point to the object
mov [rax + Cons.typecdr], BYTE content_pointer
mov [rax + Cons.cdr], rcx
mov rsi, rcx
call incref_object
.done:
ret
;; Removes an error handler from the list
;;
;; Modifies registers:
;; RSI
;; RAX
;; RCX
error_handler_pop:
; get the address
mov rsi, [error_handler]
cmp rsi, 0
je .done ; Nothing to remove
push rsi
mov rsi, [rsi + Cons.cdr] ; next handler
mov [error_handler], rsi
;call incref_object ; needed because releasing soon
pop rsi ; handler being removed
mov [rsi + Cons.typecdr], BYTE 0
call release_cons
.done:
ret
;; Throw an error
;; Object to pass to handler should be in RSI
error_throw:
; Get the next error handler
mov rax, [error_handler]
cmp rax, 0
je .no_handler
; Got a handler
mov rax, [rax + Cons.car] ; handler
mov rbx, [rax + Cons.car] ; stack pointer
mov rax, [rax + Cons.cdr]
mov rcx, [rax + Cons.car] ; function
mov rdi, [rax + Cons.cdr] ; data structure
; Reset stack
mov rsp, rbx
; Jump to the handler
jmp rcx
.no_handler:
; Print the object in RSI then quit
cmp rsi, 0
je .done ; nothing to print
mov rdi, 1 ; print_readably
call pr_str
mov rsi, rax
call print_string
.done:
jmp quit_error
;; ----------------------------------------------
;; Evaluates a form
;;
@ -1946,6 +1814,28 @@ apply_fn:
mov rax, [rax + Cons.cdr]
mov rax, [rax + Cons.car] ; Body
pop rcx ; Exprs
;;;
; push rax
; push rcx
; push rsi
; push rdi
; push rdx
; push r15
; push r13
; mov rsi, rcx
; call core_println
; pop r13
; pop r15
; pop rdx
; pop rdi
; pop rsi
; pop rcx
; pop rax
;;;
; Check the type of the body
mov bl, BYTE [rax]