From 98ae91e0ba8d1c503730b993d835ed6dee47c65b Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 14 Jun 2018 17:27:00 -0600 Subject: [PATCH] expander: repair and further improve flattener Delay reporting of potential problems until an actual problem is detected. Correct a mismatch between original and renamed symbols to restore detection of problems. --- racket/src/expander/Makefile | 13 ++-- .../src/expander/extract/check-and-report.rkt | 62 +++++++++++-------- racket/src/expander/extract/flatten.rkt | 57 +++++++++-------- racket/src/expander/extract/main.rkt | 34 +++++----- racket/src/io/Makefile | 7 +-- racket/src/regexp/Makefile | 9 +-- racket/src/thread/Makefile | 7 +-- 7 files changed, 91 insertions(+), 98 deletions(-) diff --git a/racket/src/expander/Makefile b/racket/src/expander/Makefile index fb148a9646..bffa338b1f 100644 --- a/racket/src/expander/Makefile +++ b/racket/src/expander/Makefile @@ -22,11 +22,6 @@ KNOT = ++knot read read/api.rkt \ # a direct use of the primitive name: DIRECT = ++direct linklet ++direct kernel -# The linklet compiler's simple inference cannot tell that this -# module's keyword-function declarations will have no side effect, but -# we promise that it's pure: -PURE = - # Set `BUILDDIR` as a prefix on "compiled" output (defaults to empty). # Set `DEPENDSDIR` as the same sort of prefix in the generated # makefile-dependency file (also defaults to empty). The `BUILDDIR` @@ -36,7 +31,7 @@ PURE = expander: $(RACO) make bootstrap-run.rkt - $(RACKET) bootstrap-run.rkt -c compiled/cache-src $(KNOT) $(DIRECT) $(PURE) -O $(TREE) + $(RACKET) bootstrap-run.rkt -c compiled/cache-src $(KNOT) $(DIRECT) -O $(TREE) expander-src: $(RACO) make bootstrap-run.rkt @@ -47,7 +42,7 @@ GENERATE_ARGS = -c $(BUILDDIR)compiled/cache-src \ ++depend-module bootstrap-run.rkt \ --depends $(BUILDDIR)compiled/expander-dep.rktd \ --makefile-depends $(DEPENDSDIR)compiled/expander.rktl $(BUILDDIR)compiled/expander.d \ - $(KNOT) $(DIRECT) $(PURE) -k $(TREE) -s -x \ + $(KNOT) $(DIRECT) -k $(TREE) -s -x \ -o $(BUILDDIR)compiled/expander.rktl # This target can be used with a `RACKET` that builds via `-l- setup --chain ...` @@ -75,11 +70,11 @@ run-no-cache: # Writes the extracted, compiled, decompiled expander to compiled/exp.rkt decompile: $(RACO) make bootstrap-run.rkt - $(RACKET) $(RKT_ARGS) bootstrap-run.rkt -c compiled/cache-src $(KNOT) $(PURE) -s -x -D -o compiled/exp.rkt + $(RACKET) $(RKT_ARGS) bootstrap-run.rkt -c compiled/cache-src $(KNOT) -s -x -D -o compiled/exp.rkt # Writes the extracted, compiled expander to compiled/exp.zo bytecode: $(RACO) make bootstrap-run.rkt - $(RACKET) $(RKT_ARGS) bootstrap-run.rkt -c compiled/cache-src $(KNOT) $(PURE) -s -x -B -o compiled/exp.zo + $(RACKET) $(RKT_ARGS) bootstrap-run.rkt -c compiled/cache-src $(KNOT) -s -x -B -o compiled/exp.zo .PHONY: expander expander-src expander-src-generate demo run run-no-cache diff --git a/racket/src/expander/extract/check-and-report.rkt b/racket/src/expander/extract/check-and-report.rkt index 2a059a32e8..d2f834515a 100644 --- a/racket/src/expander/extract/check-and-report.rkt +++ b/racket/src/expander/extract/check-and-report.rkt @@ -1,18 +1,21 @@ #lang racket/base -(require "../run/status.rkt" +(require "../common/set.rkt" + "../run/status.rkt" "../boot/runtime-primitive.rkt" "link.rkt" "linklet-info.rkt" - "linklet.rkt") + "linklet.rkt" + "variable.rkt") -(provide check-and-report!) +(provide check-and-record-report!) -;; Check for bootstrap obstacles and report the results -(define (check-and-report! #:compiled-modules compiled-modules - #:linklets linklets - #:linklets-in-order linklets-in-order - #:needed needed - #:instance-knot-ties instance-knot-ties) +;; Check for bootstrap obstacles, and prepare to report if the +;; obstacles persist +(define (check-and-record-report! #:compiled-modules compiled-modules + #:linklets linklets + #:linklets-in-order linklets-in-order + #:needed needed + #:instance-knot-ties instance-knot-ties) (log-status "Traversed ~s modules" (hash-count compiled-modules)) (log-status "Got ~s relevant linklets" (hash-count linklets)) @@ -40,7 +43,7 @@ ;; Check whether any needed linklet needs an instance of a ;; pre-defined instance that is not part of the runtime system: (define complained? #f) - (define needed-vars null) + (define check-later-vars (make-hash)) ; variable -> (listof complain-proc) (for ([lnk (in-list (unbox linklets-in-order))]) (define needed-reason (hash-ref needed lnk #f)) (when needed-reason @@ -54,20 +57,25 @@ (not (eq? p '#%linklet)) (not (hash-ref instance-knot-ties p #f)) (hash-ref needed in-lnk #t)) - (unless complained? - (log-status "~a\n ~a" - "Unfortunately, some linklets depend on pre-defined host instances" - "that are not part of the runtime system:") - (set! complained? #t)) - (unless complained-this? - (log-status " - ~a at ~s" (link-name lnk) (link-phase lnk)) - (set! complained-this? #t)) - (log-status "~a" (lines (format " needs ~s:" p) in-vars)) - (set! needed-vars (append in-vars needed-vars)))) - (when complained-this? - (log-status " needed by ~s" needed-reason)))) - (when complained? - (log-status "~a\n ~a" - "If these dependencies are not removed by subsequent flattening" - "and simplification, extraction cannot succeed.")) - (and complained? needed-vars)) + ;; Delay the complaint until we know whether the name is + ;; actually used after flattening and pruning + (define (complain really-used-var?) + (unless complained? + (log-status "~a\n ~a\n ~a\n ~a\n ~a" + "Unfortunately, some linklets depend on pre-defined host instances" + "that are not part of the runtime system; at least one the following" + "references is a problem, but not necessarily all of them, because" + "some references may be detected as unused by the flattener (but" + "we've lost track of the connection):") + (set! complained? #t)) + (unless complained-this? + (log-status " - ~a at ~s" (link-name lnk) (link-phase lnk)) + (log-status "~a" (lines (format " needs ~s:" p) + (for/list ([in-var (in-list in-vars)] + #:when (really-used-var? (variable in-lnk in-var))) + in-var))) + (log-status " needed by ~s" needed-reason) + (set! complained-this? #t))) + (for ([in-var (in-list in-vars)]) + (hash-update! check-later-vars (variable in-lnk in-var) (lambda (l) (cons complain l)) null)))))) + check-later-vars) diff --git a/racket/src/expander/extract/flatten.rkt b/racket/src/expander/extract/flatten.rkt index 510d86321f..a905ba94e0 100644 --- a/racket/src/expander/extract/flatten.rkt +++ b/racket/src/expander/extract/flatten.rkt @@ -18,13 +18,14 @@ #:exports exports #:instance-knot-ties instance-knot-ties #:primitive-table-directs primitive-table-directs - #:check-later-names check-later-names) + #:check-later-vars check-later-vars) (log-status "Flattening to a single linklet...") (define needed-linklets-in-order (for/list ([lnk (in-list (unbox linklets-in-order))] #:when (hash-ref needed lnk #f)) lnk)) + ;; variable -> symbol (define variable-names (pick-variable-names #:linklets linklets #:needed-linklets-in-order needed-linklets-in-order @@ -32,32 +33,34 @@ (for ([var (in-hash-keys variable-names)] #:when (symbol? (link-name (variable-link var))) - #:unless (memq (variable-name var) check-later-names)) - (error 'flatten "found a dependency on a non-primitive: ~s from ~s" - (variable-name var) - (link-name (variable-link var)))) - - `(linklet - ;; imports - () - ;; exports - ,(for/list ([ex-sym (in-list (sort (hash-keys exports) symbol