Compare commits
4 commits
0ceb455031
...
54d2341ce3
Author | SHA1 | Date | |
---|---|---|---|
54d2341ce3 | |||
f1cf8ad488 | |||
4899d888aa | |||
c41fb46457 |
2 changed files with 42 additions and 17 deletions
|
@ -1,7 +1,8 @@
|
||||||
(in-package #:user-side-compiler)
|
(in-package #:user-side-compiler)
|
||||||
|
|
||||||
(defclass asm-object ()
|
(defclass asm-object ()
|
||||||
((%source :accessor source :initarg :source :initform nil)))
|
((%source :accessor source :initarg :source :initform nil)
|
||||||
|
(%next :accessor next :initform nil)))
|
||||||
|
|
||||||
(defclass asm-label (asm-object)
|
(defclass asm-label (asm-object)
|
||||||
((%name :accessor name :initarg :name)
|
((%name :accessor name :initarg :name)
|
||||||
|
@ -12,19 +13,31 @@
|
||||||
(%operand :accessor operand :initarg :operand :initform nil)
|
(%operand :accessor operand :initarg :operand :initform nil)
|
||||||
(%byte-length :accessor byte-length :initarg :byte-length)))
|
(%byte-length :accessor byte-length :initarg :byte-length)))
|
||||||
|
|
||||||
(defvar *asm-output* '())
|
(defvar *asm-labels* (make-hash-table :test #'equal)
|
||||||
|
"A hash table connecting identities (names) to ASM-LABEL objects.")
|
||||||
|
|
||||||
|
(defvar *asm-head* nil
|
||||||
|
"The first assembly object, used for traversal.")
|
||||||
|
(defvar *asm-foot* nil
|
||||||
|
"The (so far) last assembly object, used for construction.")
|
||||||
|
|
||||||
(defun emit-asm-object (obj)
|
(defun emit-asm-object (obj)
|
||||||
(check-type obj asm-object)
|
(if (null *asm-foot*)
|
||||||
(setf *asm-output* (append *asm-output* (list obj))))
|
(setf *asm-head* obj)
|
||||||
|
(setf (next *asm-foot*) obj))
|
||||||
|
(setf *asm-foot* obj))
|
||||||
|
|
||||||
(defun emit-asm-instruction (&rest initargs)
|
(defun emit-asm-instruction (&rest initargs)
|
||||||
(emit-asm-object (apply #'make-instance
|
(let ((new-instruction (apply #'make-instance
|
||||||
'asm-instruction
|
'asm-instruction
|
||||||
initargs)))
|
initargs)))
|
||||||
|
(emit-asm-object new-instruction)))
|
||||||
|
|
||||||
(defun emit-asm-label (identity)
|
(defun emit-asm-label (identity)
|
||||||
(emit-asm-object (make-instance 'asm-label :name identity)))
|
(let ((label (make-instance 'asm-label :name identity)))
|
||||||
|
(setf (gethash identity *asm-labels*)
|
||||||
|
label)
|
||||||
|
(emit-asm-object label)))
|
||||||
|
|
||||||
(defvar *variable-allocations* (make-hash-table))
|
(defvar *variable-allocations* (make-hash-table))
|
||||||
(defvar *last-instruction* '(:nop))
|
(defvar *last-instruction* '(:nop))
|
||||||
|
@ -104,6 +117,9 @@
|
||||||
(defmethod compile-ir ((inst ir-inst))
|
(defmethod compile-ir ((inst ir-inst))
|
||||||
(warn "Skipped compiling ~A; no COMPILE-IR method" inst))
|
(warn "Skipped compiling ~A; no COMPILE-IR method" inst))
|
||||||
|
|
||||||
|
(defmethod compile-ir ((inst ir-return))
|
||||||
|
(emit-asm-instruction :opcode #x60 :byte-length 1))
|
||||||
|
|
||||||
(defmethod compile-ir ((inst ir-plus))
|
(defmethod compile-ir ((inst ir-plus))
|
||||||
(unless (= (length (inputs inst)) 2)
|
(unless (= (length (inputs inst)) 2)
|
||||||
(error "During the final code generation step, IR-PLUS must have exactly 2 operands."))
|
(error "During the final code generation step, IR-PLUS must have exactly 2 operands."))
|
||||||
|
@ -132,16 +148,23 @@
|
||||||
(emit-asm-instruction :opcode #x20 :operand (callee inst) :byte-length 1)
|
(emit-asm-instruction :opcode #x20 :operand (callee inst) :byte-length 1)
|
||||||
(emit-store-result (output inst)))
|
(emit-store-result (output inst)))
|
||||||
|
|
||||||
(defun link-assembly (assembly-list origin-address)
|
(defun link-compute-addresses (start-instruction origin-address)
|
||||||
|
"First linking pass, computes the addresses of all labels."
|
||||||
(let ((address origin-address))
|
(let ((address origin-address))
|
||||||
(loop :for asm-obj :in assembly-list
|
(loop :for asm-obj := start-instruction :then (next asm-obj)
|
||||||
|
:until (null asm-obj)
|
||||||
:do (cond ((typep asm-obj 'asm-label)
|
:do (cond ((typep asm-obj 'asm-label)
|
||||||
(setf (address asm-obj) address))
|
(setf (address asm-obj) address))
|
||||||
((typep asm-obj 'asm-instruction)
|
((typep asm-obj 'asm-instruction)
|
||||||
(incf address (byte-length asm-obj)))))
|
(incf address (byte-length asm-obj)))))
|
||||||
;; TODO: Second pass, replacing labels with their addresses, both for
|
(values start-instruction address)))
|
||||||
;; constant labels such as assembly routines and for generated labels.
|
|
||||||
(values assembly-list address)))
|
(defun link-assembly (start-instruction origin-address)
|
||||||
|
(link-compute-addresses start-instruction origin-address)
|
||||||
|
;; TODO: Second pass, replacing labels with their addresses, both for
|
||||||
|
;; constant labels such as assembly routines and for generated labels.
|
||||||
|
;;(values start-instruction address)
|
||||||
|
)
|
||||||
|
|
||||||
(defun quick-and-dirty-test-compile (text &key print-ir-p print-alloc-p make-asm-p)
|
(defun quick-and-dirty-test-compile (text &key print-ir-p print-alloc-p make-asm-p)
|
||||||
(with-input-from-string (source-stream text)
|
(with-input-from-string (source-stream text)
|
||||||
|
@ -169,9 +192,10 @@
|
||||||
(terpri))
|
(terpri))
|
||||||
(when make-asm-p
|
(when make-asm-p
|
||||||
(with-variable-allocations allocations
|
(with-variable-allocations allocations
|
||||||
(let ((*asm-output* '()))
|
(let ((*asm-head* nil)
|
||||||
|
(*asm-foot* nil))
|
||||||
(do-iblocks (ib rb)
|
(do-iblocks (ib rb)
|
||||||
(emit-asm-label ib)
|
(emit-asm-label ib)
|
||||||
(do-instructions (inst ib)
|
(do-instructions (inst ib)
|
||||||
(compile-ir inst)))
|
(compile-ir inst)))
|
||||||
(link-assembly *asm-output* #x8000)))))))))
|
(link-assembly *asm-head* #x8000)))))))))
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
(defsystem #:user-side-compiler
|
(defsystem #:user-side-compiler
|
||||||
:serial t
|
:serial t
|
||||||
:depends-on (#:closer-mop)
|
:depends-on (#:closer-mop #:alexandria)
|
||||||
:components
|
:components
|
||||||
((:file "package")
|
((:file "package")
|
||||||
(:file "toolkit")
|
(:file "toolkit")
|
||||||
|
@ -32,4 +32,5 @@
|
||||||
(:module "backend"
|
(:module "backend"
|
||||||
:depends-on ("middle")
|
:depends-on ("middle")
|
||||||
:serial t
|
:serial t
|
||||||
:components ((:file "value-allocator")))))
|
:components ((:file "value-allocator")
|
||||||
|
(:file "code-generator")))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue