From a5671dcdab157017cfe94e9f0fc469182e31651f Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sun, 24 May 2020 20:32:10 +0200 Subject: [PATCH] cmp: refactor c1let/let* into two stages First stages handles the bindings, second stage the body, needed to get inlining of local closures right. --- src/cmp/cmplet.lsp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/cmp/cmplet.lsp b/src/cmp/cmplet.lsp index cdd789cd9..56e6488a4 100644 --- a/src/cmp/cmplet.lsp +++ b/src/cmp/cmplet.lsp @@ -59,22 +59,18 @@ (t (c1let/let* 'let* bindings args))))) +;; Processing of a let form is split in two stages: +;; - processing bindings +;; - processing the body +;; This allows reusing the below functions for inlined closures. These +;; are transformed in a let statement for which the body needs to be +;; compiled in a different lexical environment than the bindings. (defun c1let/let* (let/let* bindings body) (let* ((setjmps *setjmps*) (*cmp-env* (cmp-env-copy))) - (multiple-value-bind (vars forms body) + (multiple-value-bind (vars forms specials other-decls body) (process-let-bindings let/let* bindings body) - ;; Try eliminating unused variables, replace constant ones, etc. - (multiple-value-setq (vars forms) - (c1let-optimize-read-only-vars vars forms body)) - ;; Verify that variables are referenced and assign final boxed / unboxed type - (mapc #'check-vref vars) - (let ((sp-change (some #'global-var-p vars))) - (make-c1form* let/let* - :type (c1form-type body) - :volatile (not (eql setjmps *setjmps*)) - :local-vars vars - :args vars forms body))))) + (process-let-body let/let* vars forms specials other-decls body setjmps)))) (defun invalid-let-bindings (let/let* bindings) (cmperr "Syntax error in ~A bindings:~%~4I~A" @@ -123,8 +119,22 @@ (when (eq let/let* 'LET) (mapc #'push-vars vars)) (check-vdecl (mapcar #'var-name vars) types ignoreds) - (mapc #'cmp-env-declare-special specials) - (values vars forms (c1decl-body other-decls body))))) + (values vars forms specials other-decls body)))) + +(defun process-let-body (let/let* vars forms specials other-decls body setjmps) + (mapc #'cmp-env-declare-special specials) + (setf body (c1decl-body other-decls body)) + ;; Try eliminating unused variables, replace constant ones, etc. + (multiple-value-setq (vars forms) + (c1let-optimize-read-only-vars vars forms body)) + ;; Verify that variables are referenced and assign final boxed / unboxed type + (mapc #'check-vref vars) + (let ((sp-change (some #'global-var-p vars))) + (make-c1form* let/let* + :type (c1form-type body) + :volatile (not (eql setjmps *setjmps*)) + :local-vars vars + :args vars forms body))) (defun c1let-optimize-read-only-vars (all-vars all-forms body) (loop with base = (list body)