[wip] bir: add a custom pass to that generates cfg->cxx

This commit is contained in:
Daniel Kochmański 2023-10-31 12:03:07 +01:00
parent 42c674d539
commit e8eec5e451
3 changed files with 689 additions and 0 deletions

View file

@ -0,0 +1,144 @@
;;;;
;;;; Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya
;;;; Copyright (c) 1990, Giuseppe Attardi
;;;; Copyright (c) 2001, Juan Jose Garcia Ripoll
;;;; Copyright (c) 2023, Daniel Kochmański
;;;;
;;;; See the file 'LICENSE' for the copyright details.
;;;;
;;;;
;;;; CMPPASS2-BIR -- BIR->CXX code generator. This code generator is a rewrite of
;;;; the old one that tranpsiled AST->CXX.
(in-package "COMPILER")
(defun compiler-pass/generate-cxx*
(module c-pathname h-pathname data-pathname init-name source)
(with-cxx-env ()
(optimize-cxx-data *referenced-objects*)
(setq *compiler-phase* 't2)
(with-open-file (*compiler-output1* c-pathname :direction :output
:if-does-not-exist :create
:if-exists :supersede)
(with-open-file (*compiler-output2* h-pathname :direction :output
:if-does-not-exist :create
:if-exists :supersede)
(wt-print-header source)
(transpile-module module init-name c-pathname h-pathname data-pathname)
(terpri *compiler-output1*)
(terpri *compiler-output2*)))
(data-c-dump data-pathname)))
(defvar *cxx-pprint-dispatch* (copy-pprint-dispatch))
(defmacro define-cxx-pprint ((object type-specifier)
(&key (priority 0)
(table '*cxx-pprint-dispatch*)
(stream '*standard-output*))
&body body)
`(set-pprint-dispatch ',type-specifier
(lambda (,stream ,object) ,@body)
,priority ,table))
(defun format-iblocks (enter)
(let ((visited (make-hash-table)))
(labels ((iblock-index (i)
(gethash i visited))
(count-iblock (i)
(unless (gethash i visited)
(setf (gethash i visited)
(hash-table-count visited))))
(print-iblock (i)
(cond ((not (emptyp (iblock-outputs i)))
(wt-comment-nl "~2,'0d: ~20a -> ~{~2,'0d~^ ~}"
(gethash i visited)
(iblock-name i)
(map 'list #'iblock-index (iblock-outputs i))))
((not (null (iblock-unwind i)))
(wt-comment-nl "~2,'0d: ~20a >> ~2,'0d"
(gethash i visited)
(iblock-name i)
(iblock-index (iblock-unwind i))))
(t
(wt-comment-nl "~2,'0d: ~20a" (gethash i visited) i)))
(b2expr i)))
(map-iblocks #'count-iblock enter)
(map-iblocks #'print-iblock enter))))
(define-cxx-pprint (module module) ()
(wt-comment-nl (format nil "~74,,,'-a" ""))
(wt-comment-nl "Constants: ~s" (length (constants module)))
(wt-comment-nl "Functions: ~s" (length (functions module)))
(wt-comment-nl "Top-level: ~s" (top-level module))
(wt-nl)
(wt-nl1 "#include " *cmpinclude*)
(wt-nl)
(dolist (fun (functions module))
(wt-comment-nl (format nil "~a" (fun-name (bir-parent fun))))
(wt-nl "void lfun(...)")
(wt-nl-open-brace)
(format-iblocks (bir-enter fun))
(wt-nl-close-brace)
(wt-nl))
(wt-nl "void lambda(...)")
(wt-nl-open-brace)
(format-iblocks (bir-enter (top-level module)))
(wt-nl-close-brace))
(defun format-bir (bir &optional (*compiler-output1* *standard-output*)) ()
(wt-nl "void lambda(...)")
(wt-nl-open-brace)
(format-iblocks (bir-enter bir))
(wt-nl-close-brace))
(defun b2expr (iblock)
(b2instr (iblock-instructions iblock)))
(defun emit-c1form (opcode)
(case (c1form-name opcode)
;; (location (wt-nl "#<loc> = ") (wt-loc (c1form-arg 0 opcode)) (wt ";"))
;; (variable (wt-nl "#<var> = ") (wt-var (c1form-arg 0 opcode)) (wt ";"))
;; (variable (wt-nl "#<var> = ") (wt "...") (wt ";"))
;; (cl:setq (wt-nl "#<var> <- ...;"))
;; (fcall (wt-nl "#<fun>(#<arg>, #<arg>, ...);"))
;; (si:fset (wt-nl "#<fun> = ...;"))
;; (fmla-not (wt-nl "#<test> = (not ...);"))
;; (fmla-and (wt-nl "#<test> = (and ...);"))
;; (fmla-or (wt-nl "#<test> = (or ...);"))
;; (cl:if (wt-nl "if (#<test>)"))
;; (cl:go (wt-nl "goto " (format nil "~a" (tag-name (c1form-arg 0 opcode))) ";"))
(otherwise
(wt-nl "unknown " (format nil "~a" (c1form-name opcode)) ";"))))
(defun emit-other (opcode)
(wt-comment-nl (format nil " ~a" opcode) ";"))
(defun emit-opcode (opcode)
(typecase opcode
(c1form (emit-c1form opcode))
(otherwise (emit-other opcode))))
(defun b2instr (instructions)
(loop for instr across instructions
for opcode = (instruction-opcode instr) do
(emit-opcode opcode)))
;;; Default pretty printers output comments.
#+ (or)
(define-cxx-pprint (i iblock) ()
;(wt-comment-nl "this is iblock")
;(map nil #'print (iblock-instructions i))
)
;; (define-cxx-pprint (instr instruction) ()
;; (ext:if-let ((output (instruction-output instr)))
;; (wt-comment-nl " ~24a -> ~a" instr output)
;; (wt-comment-nl " ~a" instr)))
(defun transpile-module (module init-name c-pathname h-pathname data-pathname)
(let ((*print-pprint-dispatch* *cxx-pprint-dispatch*))
(pprint module *compiler-output1*)))

543
src/cmp/cmpbackend-tir.lsp Normal file
View file

@ -0,0 +1,543 @@
(in-package "COMPILER")
(ext:package-lock '#:cl nil)
(setf ext:*register-with-pde-hook* nil)
;;; Module represents a compilation unit. Each compilation unit maintains
;;; constants, a set of functions, and a special block of code "top-level" that
;;; is executed when the module is loaded.
(defclass module ()
((constants :reader constants :initform (make-array 0 :adjustable t :fill-pointer t))
(top-level :accessor top-level :initarg :top-level)
(functions :accessor functions :initarg :functions)))
(defgeneric dynamic-environment (object)
(:method ((object null))
nil)
(:method ((object module))
object)
(:method ((object fun))
object))
(defun make-module ()
(let ((module (make-instance 'module)))
(setf (top-level module) (make-bir module))
module))
;;; IBLOCK is a block of instructions that may be executed without changing the
;;; dynamic environment and corresponds to a basic block in contemporary CFG.
;;;
;;; C1FORMs representation is essentially the AST of the program. In this pass
;;; we convert it to the control flow graph composed of iblocks (c.f cleavir).
(defclass iblock ()
((name
:accessor iblock-name
:initarg :name)
(denv
:accessor dynamic-environment
:initarg :denv)
(inputs
:accessor iblock-inputs
:initform (make-array 0 :adjustable t :fill-pointer t))
(outputs
:accessor iblock-outputs
:initform (make-array 0 :adjustable t :fill-pointer t))
;; Unwind is currently mutually exclusive with outputs. It means that we
;; escape a dynamic context. When the target is not known, like CL:THROW,
;; iblock-unwind points to a designated node BIR-ELUDE.
(unwind
:accessor iblock-unwind
:initform nil)
(instrucitons
:reader iblock-instructions
:initform (make-array 0 :adjustable t :fill-pointer t))))
(defun make-iblock (name)
(make-instance 'iblock :name name :denv *unwind-exit*))
(defmethod print-object ((object iblock) stream)
(print-unreadable-object (object stream :type nil :identity nil)
(format stream "~s" (iblock-name object))))
(defun connect-iblocks (from to)
(assert (null (iblock-unwind from)))
(vector-push-extend to (iblock-outputs from))
(vector-push-extend from (iblock-inputs to))
to)
(defun abscond-iblocks (from to)
(assert (emptyp (iblock-outputs from)))
(setf (iblock-unwind from) to)
(vector-push-extend from (iblock-inputs to))
to)
(defun map-iblocks (fun enter)
(let ((visited (make-hash-table))
(fcalled (make-hash-table)))
(labels ((%fnc (iblock)
(unless (gethash iblock fcalled)
(setf (gethash iblock fcalled) t)
(funcall fun iblock)))
(%map (iblock)
(unless (gethash iblock visited)
(setf (gethash iblock visited) t)
(map nil #'%fnc (iblock-outputs iblock))
(map nil #'%map (iblock-outputs iblock))
(ext:when-let ((unwind (iblock-unwind iblock)))
(%fnc unwind)
(%map unwind)))))
(%fnc enter)
(%map enter))))
(defun extend-iblock (this-instruction iblock)
(setf (instruction-iblock this-instruction) iblock)
(let* ((instructions (iblock-instructions iblock))
(n (length instructions)))
(unless (zerop n)
(let ((last-instruction (aref instructions (1- n))))
(setf (instruction-next last-instruction) this-instruction
(instruction-prev this-instruction) last-instruction))))
(vector-push-extend this-instruction (iblock-instructions iblock))
iblock)
;;; The class instruction is important because it holds references to input and
;;; output values. Instructions are derived from c1forms, but there may be many
;;; instructions referencing the same node.
(defclass instruction ()
(;; The name is used to tell aparat different operators. Alternatively we may
;; create a class hierarchy when each class represents the instruction type.
(opcode :initarg :opcode :accessor instruction-opcode)
;; Arguments accepted by the instruction.
(inputs :initarg :inputs :accessor instruction-inputs)
;; Values returned by the instruction.
(output :initarg :output :accessor instruction-output)
;; Backpointer.
(iblock :accessor instruction-iblock)
;; Leader has no prececessors, terminator has no successors.
(prev :initform nil :accessor instruction-prev)
(next :initform nil :accessor instruction-next))
(:default-initargs :opcode (error "~s is required." :opcode)
:inputs (error "~s is required." :inputs)
:output (error "~s is required." :output)))
;;; IBLOCK, PREV and NEXT are fixed in the function EXTEND-BLOCK.
;;; INPUTS depend on the particular operator.
;;; OUTPUTS depend on the particular caller.
(defun make-instruction (opcode inputs)
(make-instance 'instruction :opcode opcode
:inputs inputs
:output *destination*))
;;; In principle we could construct CFG with IBLOCK and operators defined for
;;; them. BIR is used to track the CFG first and current IBLOCKs. This aids the
;;; recursive construction of the graph.
;;;
;;; BIR-ENTER is the entry point and does not change.
;;; BIR-TRAIL may be modified at any time.
;;;
;;; Extending the graph:
;;;
;;; - BIR-INSERT bir iblock :: connect to iblock, update the trail
;;; - BIR-RETURN bir iblock :: connect to iblock, delete the trail
;;; - BIR-ESCAPE bir iblock :: dynamic to iblock, delete the trail
;;; - BIR-REWIND bir iblock :: abandon the trail, update the trail
;;;
;;; Extending the trail:
;;;
;;; - BIR-EXTEND bir instruction :: add an instruction to the trail (if any)
;;;
;;; Dynamic environments of two connected iblocks may differ and transitioning
;;; between them may involve arbitrary operations.
(defclass bir ()
(;; parent may be a module or a function.
(parent :initarg :parent :accessor bir-parent)
(enter :initarg :enter :accessor bir-enter)
(leave :initarg :leave :accessor bir-leave)
(elude :initarg :elude :accessor bir-elude)
(trail :initarg :trail :accessor bir-trail)
;; backpointers are added to find destination iblocks.
(backs :initarg :backs :accessor bir-backs))
(:default-initargs :backs (make-hash-table)))
(defmethod dynamic-environment ((object bir))
(or (dynamic-environment (bir-trail object))
(dynamic-environment (bir-enter object))))
(defun get-iblock (bir iblock-key)
(or (gethash iblock-key (bir-backs bir))
(error "can't find ~s" iblock-key)))
(defun set-iblock (bir iblock)
(setf (gethash (iblock-name iblock) (bir-backs bir)) iblock))
(defun make-bir (parent)
(let* ((enter (make-iblock :enter))
(leave (make-iblock :leave))
(elude (make-iblock :elude)))
(make-instance 'bir :parent parent
:enter enter :leave leave :elude elude :trail enter)))
(defun bir-insert (bir target)
(ext:when-let ((trail (bir-trail bir)))
(connect-iblocks trail target))
;; Even when the trail is broken the iblock may be a destination of a jump.
(setf (bir-trail bir) target))
(defun bir-escape (bir target)
(ext:when-let ((trail (bir-trail bir)))
(abscond-iblocks trail target)
(setf (bir-trail bir) nil)))
(defun bir-return (bir target)
(when (bir-trail bir)
(bir-insert bir target)
(setf (bir-trail bir) nil)))
(defun bir-rewind (bir iblock)
(setf (bir-trail bir) iblock))
(defun bir-extend (bir instruction)
(when (bir-trail bir)
(extend-iblock instruction (bir-trail bir))))
;;; Exit manager.
(defvar *exit* nil)
(defvar *unwind-exit* nil)
(defvar *destination* nil)
;;; The exit block denotes the continuation of the body. When the body returns
;;; (bir-trail is not null), and the dynamic environment does not change, and
;;; the exit block is not a target of a jump, then we don't need to create it.
(defun exit-iblock-necessary-p (bir iblock)
(not (and (bir-trail bir)
(eq (dynamic-environment iblock) (rest *unwind-exit*))
(emptyp (iblock-inputs iblock)))))
(defmacro with-exit-iblock ((bir block destination) &body body)
`(let* ((,block (make-iblock ',block))
(*unwind-exit* (cons ,block *unwind-exit*))
(*destination* ,destination))
,@body
(when (exit-iblock-necessary-p ,bir ,block)
(bir-insert ,bir ,block))))
;;; This function jumps to EXIT without setting the destination.
;; (defun unwind-jump (exit))
;;; This function jumps to EXIT and sets the destination to location.
;; (defun unwind-exit (exit location))
;;; C1FORMS have a single class and are distinguished by a name, that's why we
;;; trampoline to the handler by expanding the name. Handlers are defined with
;;; the macro DEFINE-BIR-METHOD.
(defgeneric %bir-from-c1form (bir form name)
;; This default method should ERROR before merging this pass to develop.
(:method ((bir bir) (form c1form) (name t))
(bir-insert bir (make-iblock `(:unknown ,name)))))
(defun bir-from-c1form (bir form)
(typecase form
(c1form
(%bir-from-c1form bir form (c1form-name form) ))
(otherwise
(bir-insert bir (make-iblock (cons :not-c1form form))))))
(defun bir-from-function (bir fun)
(bir-insert bir (make-iblock (cons :function (fun-name fun)))))
(defmacro define-bir-method ((bir var node-name) args &body body)
(let ((name (gensym)))
`(defmethod %bir-from-c1form
((,bir bir) (,var c1form) (,name (eql ',node-name)))
(destructuring-bind ,args (c1form-args ,var)
,@body))))
(progn
(define-bir-method (bir form ext:compiler-let) (symbols values body)
(progv symbols values
(bir-from-c1form bir body)))
(define-bir-method (bir form cl:load-time-value) (dest-loc value-c1form)
(with-exit-iblock (bir *exit* dest-loc)
(bir-from-c1form bir value-c1form)))
(define-bir-method (bir form make-form) (dest-loc value-c1form)
(with-exit-iblock (bir *exit* dest-loc)
(bir-from-c1form bir value-c1form)))
(define-bir-method (bir form init-form) (vv-loc value-c1form)
(declare (ignore vv-loc))
(with-exit-iblock (bir *exit* nil)
(bir-from-c1form bir value-c1form)))
(define-bir-method (bir form ordinary) (c1form)
(with-exit-iblock (bir *exit* nil)
(bir-from-c1form bir c1form)))
(define-bir-method (bir form cl:progn) (body)
(with-exit-iblock (bir *exit* *destination*)
(loop while (bir-trail bir)
for (form . rest) on body
do (if (null rest)
(let ((*destination* nil))
(bir-from-c1form bir form))
(bir-from-c1form bir form))))))
;;; Places, assignment and binding
(progn
;; FIXME this is a stub
(define-bir-method (bir form location) (loc)
(declare (ignore loc))
(let ((instruction (make-instruction form 0)))
(bir-extend bir instruction)))
;; FIXME this is a stub
;; VALUE is a VV location if it is known at compile time.
(define-bir-method (bir form variable) (var value)
(declare (ignore var value))
(let ((instruction (make-instruction form 0)))
(bir-extend bir instruction)))
;; FIXME this is a stub
(define-bir-method (bir form cl:setq)
(var value-c1form)
(let ((instruction (make-instruction form 1)))
(let ((*destination* var))
(bir-from-c1form bir value-c1form))
(bir-extend bir instruction)))
;; IMPLEMENTME
(define-bir-method (bir form cl:psetq) (var-list value-c1form-list)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form cl:progv) (symbols values form)
(call-next-method))
;; FIXME this is a stub
(define-bir-method (bir form cl:let*) (vars-list var-init-c1form-list decl-body-c1form)
(loop for var in vars-list
for val in var-init-c1form-list
do (let ((*destionation* var))
(bir-from-c1form bir val)))
(bir-from-c1form bir decl-body-c1form))
;; IMPLEMENTME
(define-bir-method (bir form cl:multiple-value-setq) (vars-list values-c1form-list)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form cl:multiple-value-bind) (vars-list init-c1form body)
(call-next-method)))
;;; Function namespace
(progn
;; FIXME this is a stub
(define-bir-method (bir form si:fset)
(function-object vv-loc macro-p pprint-p lambda-form)
(declare (ignore function-object vv-loc macro-p pprint-p lambda-form))
(let ((instruction (make-instruction form 4)))
(bir-extend bir instruction)))
;; IMPLEMENTME
(define-bir-method (bir form cl:function) (fname)
(call-next-method))
;; FIXME this is a stub
(define-bir-method (bir form locals) (local-fun-list body labels-p)
(bir-from-c1form bir body)))
;;; Specialized accessors
(progn
;; IMPLEMENTME
(define-bir-method (bir form si:structure-ref)
(struct-c1form type-name slot-index)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form si:structure-set)
(struct-c1form type-name slot-index value-c1form)
(call-next-method)))
;;; Control structures
(progn
(define-bir-method (bir form cl:block) (blk-var progn-c1form)
(let ((exit (make-iblock blk-var)))
(set-iblock bir exit)
(bir-from-c1form bir progn-c1form)
(bir-insert bir exit)))
;; FIXME value is ignored(!)
(define-bir-method (bir form cl:return-from) (blk-var nonlocal value)
(let ((cont (get-iblock bir blk-var)))
(if nonlocal
(bir-escape bir cont)
(bir-return bir cont))))
(define-bir-method (bir form cl:tagbody) (tag-var tag-body)
;; We go in two passes - first we estabilish target iblocks and only after
;; that we /do our thing/. This is important because cl:go requires iblocks.
(dolist (form tag-body)
(when (tag-p form)
(set-iblock bir (make-iblock form))))
(dolist (form tag-body)
(if (tag-p form)
(bir-insert bir (get-iblock bir form))
(bir-from-c1form bir form))))
(define-bir-method (bir form cl:go) (tag nonlocal)
(let ((cont (get-iblock bir tag)))
(if nonlocal
(bir-escape bir cont)
(bir-return bir cont))))
;; This one is symmetrical to block/return-from, but catch-value is a dynamic
;; variable. Generally similar, but we always escape.
(define-bir-method (bir form cl:catch) (catch-value body)
(let ((exit (make-iblock :catch)))
(set-iblock bir exit)
(bir-from-c1form bir body)
(bir-insert bir exit)
(bir-rewind bir (bir-elude bir))
(bir-insert bir exit)))
;; This one is symmetrical to block/return-from, but catch-value is a dynamic
;; variable. Generally similar, but we always escape.
(define-bir-method (bir form cl:throw) (catch-value output-value)
(bir-escape bir (bir-elude bir)))
(define-bir-method (bir form cl:unwind-protect) (protected-c1form body)
(let* ((enter (make-iblock :op_protect))
(clean (make-iblock :op_protect_normal))
(leave (make-iblock :op_protect_exit)))
(bir-insert bir enter)
(bir-from-c1form bir protected-c1form)
(bir-insert bir clean)
(let ((*destination* nil))
(bir-from-c1form bir body))
;; EXIT is responsible for reinstating values and (when due) unwinding.
(bir-insert bir leave))))
;;; Control structures*
(progn
(define-bir-method (bir form cl:if) (fmla-c1form true-c1form false-c1form)
(let ((if-true (make-iblock :if-true))
(if-false (make-iblock :if-false))
(if-merge (make-iblock :if-merge))
;;
(instruction (make-instruction form 1))
(if-merge-list '()))
(let ((*destination* (list instruction 0)))
(bir-from-c1form bir fmla-c1form))
(flet ((add-branch (iblock c1form)
(bir-insert bir iblock)
(bir-from-c1form bir c1form)
(when (bir-trail bir)
(push (bir-trail bir) if-merge-list))))
(ext:when-let ((if-split (bir-trail bir)))
(bir-extend bir instruction)
(add-branch if-true true-c1form)
(bir-rewind bir if-split)
(add-branch if-false false-c1form)
(ecase (length if-merge-list)
(0 nil)
(1 (bir-rewind bir (first if-merge-list)))
(2 (dolist (iblock if-merge-list)
(bir-rewind bir iblock)
(bir-insert bir if-merge))))))))
;; FIXME this is a stub
(define-bir-method (bir form fmla-not) (c1form)
(let ((instruction (make-instruction form 1)))
(let ((*destination* (list instruction 0)))
(bir-from-c1form bir c1form))
(bir-extend bir instruction)))
;; IMPLEMENTME
(define-bir-method (bir form fmla-and) (&rest c1forms)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form fmla-or) (&rest c1forms)
(call-next-method)))
;;; Function calls
(progn
(define-bir-method (bir form fcall) (fun-form args fun type)
(declare (ignore fun-form fun type))
(let ((instruction (make-instruction form (length args))))
;; FIXME each argument has a separate position destination-wise.
(loop for arg in args
for n from 0
do (let ((*destination* (list instruction n)))
(bir-from-c1form bir arg)))
(bir-extend bir instruction)))
;; IMPLEMENTME
(define-bir-method (bir form mcall) (fun-form args fun type)
(call-next-method)))
;;; Other operators
(progn
;; IMPLEMENTME
(define-bir-method (bir form lambda) (lambda-list doc body-c1form)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form values) (values-c1form-list)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form mv-prog1) (form body)
(call-next-method)))
;;; Extensions
(progn
;; IMPLEMENTME
(define-bir-method (bir form ext:compiler-typecase) (var expressions)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form ext:checked-value) (type value-c1form let-form)
(call-next-method)))
;;; Backend-specific operators
(progn
;; IMPLEMENTME
(define-bir-method (bir form ffi:c-inline) (arg-forms arg-types return-type
c-expression-string
side-effects-p one-liner-p)
(call-next-method))
;; IMPLEMENTME
(define-bir-method (bir form ffi:c-progn) (variables forms)
(call-next-method)))
;;; The IR maintains nodes that are defined in `cmptables.lsp:+all-c1-forms+'.
;;; Common Lisp treats some forms specially when they are top-level. That is
;;; reflected in the internal representation by simple means of nesting.
;;;
;;; When we process a top-level form with the special meaning then the c1form of
;;; the appropriate type is created, otherwise a c1form of type `ordinary' is
;;; created and the real c1form is its argument.
;;;
;;; Some c1forms have locations as arguments. Locations are values that are
;;; expected to be available at runtime.
(defvar *last-mod* nil)
(defun compiler-pass/custom-pass ()
(cmpprogress "~&;;; Constructing BIR.")
(let* ((module (make-module))
(top-level (top-level module))
(*destination* nil))
(dolist (form *make-forms*)
(bir-from-c1form top-level form))
(dolist (form *top-level-forms*)
(bir-from-c1form top-level form))
(bir-return top-level (bir-leave top-level))
(setf (functions module)
(loop for fun in *functions*
for bir = (make-bir fun)
do (bir-from-function bir fun)
collect bir))
(setf *last-mod* module)
(compiler-pass/generate-cxx*
module
"/tmp/foo.c" "/tmp/foo.h" "/tmp/foo.data"
"dummy_init_name" "dummy_source.lsp")))

View file

@ -68,6 +68,7 @@
"src:cmp;cmpbackend-cxx;cmppass2-loc.lsp"
"src:cmp;cmpbackend-cxx;cmppass2-fun.lsp"
"src:cmp;cmpbackend-cxx;cmppass2-ffi.lsp"
"src:cmp;cmpbackend-cxx;cmppass2-bir.lsp" ;wip bir->cxx
"src:cmp;cmpbackend-cxx;cmpbackend-cxx.lsp"
;; Optimizations
"src:cmp;cmpmap.lsp"
@ -85,6 +86,7 @@
;; Other
"src:cmp;cmpos-run.lsp"
"src:cmp;cmpos-features.lsp"
"src:cmp;cmpbackend-tir.lsp" ; playground
"src:cmp;cmpmain.lsp"
"src:cmp;proclamations.lsp"))