X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fmain.lisp;h=57ec2ee951cc388d24119db29176a06e40efba18;hb=2de1b72f4bec82ad5289f33a84b34fe9cb62bd0a;hp=6ed7cb3e6969ffbca3e48524f7b1e14918bd9003;hpb=3fc4b561752c5ad4519b882a3b9bdfe7a8207532;p=sbcl.git diff --git a/src/compiler/main.lisp b/src/compiler/main.lisp index 6ed7cb3..57ec2ee 100644 --- a/src/compiler/main.lisp +++ b/src/compiler/main.lisp @@ -37,7 +37,6 @@ (defvar *flame-on-necessarily-undefined-function* nil) (defvar *check-consistency* nil) -(defvar *all-components*) ;;; Set to NIL to disable loop analysis for register allocation. (defvar *loop-analyze* t) @@ -115,6 +114,20 @@ (defvar *compile-object* nil) (declaim (type object *compile-object*)) + +(defvar *fopcompile-label-counter*) + +;; Used during compilation to map code paths to the matching +;; instrumentation conses. +(defvar *code-coverage-records* nil) +;; Used during compilation to keep track of with source paths have been +;; instrumented in which blocks. +(defvar *code-coverage-blocks* nil) +;; Stores the code coverage instrumentation results. Keys are namestrings, +;; the value is a list of (CONS PATH STATE), where STATE is NIL for +;; a path that has not been visited, and T for one that has. +(defvar *code-coverage-info* (make-hash-table :test 'equal)) + ;;;; WITH-COMPILATION-UNIT and WITH-COMPILATION-VALUES @@ -544,6 +557,11 @@ (let* ((*component-being-compiled* component)) + ;; Record xref information before optimization. This way the + ;; stored xref data reflects the real source as closely as + ;; possible. + (record-component-xrefs component) + (ir1-phases component) (when *loop-analyze* @@ -852,16 +870,19 @@ ;;; *TOPLEVEL-LAMBDAS* instead. (defun convert-and-maybe-compile (form path) (declare (list path)) - (let* ((*top-level-form-noted* (note-top-level-form form t)) - (*lexenv* (make-lexenv - :policy *policy* - :handled-conditions *handled-conditions* - :disabled-package-locks *disabled-package-locks*)) - (tll (ir1-toplevel form path nil))) - (if (eq *block-compile* t) - (push tll *toplevel-lambdas*) - (compile-toplevel (list tll) nil)) - nil)) + (if (fopcompilable-p form) + (let ((*fopcompile-label-counter* 0)) + (fopcompile form path nil)) + (let* ((*top-level-form-noted* (note-top-level-form form t)) + (*lexenv* (make-lexenv + :policy *policy* + :handled-conditions *handled-conditions* + :disabled-package-locks *disabled-package-locks*)) + (tll (ir1-toplevel form path nil))) + (if (eq *block-compile* t) + (push tll *toplevel-lambdas*) + (compile-toplevel (list tll) nil)) + nil))) ;;; Macroexpand FORM in the current environment with an error handler. ;;; We only expand one level, so that we retain all the intervening @@ -965,16 +986,27 @@ (debug-name 'initial-component name)) (setf (component-kind component) :initial) (let* ((locall-fun (let ((*allow-instrumenting* t)) - (apply #'ir1-convert-lambdalike - definition - (list :source-name name)))) + (funcall #'ir1-convert-lambdalike + definition + :source-name name))) + (debug-name (debug-name 'tl-xep + (or name + (functional-%source-name locall-fun)))) + ;; Convert the XEP using the policy of the real + ;; function. Otherwise the wrong policy will be used for + ;; deciding whether to type-check the parameters of the + ;; real function (via CONVERT-CALL / PROPAGATE-TO-ARGS). + ;; -- JES, 2007-02-27 + (*lexenv* (make-lexenv :policy (lexenv-policy + (functional-lexenv locall-fun)))) (fun (ir1-convert-lambda (make-xep-lambda-expression locall-fun) :source-name (or name '.anonymous.) - :debug-name (debug-name 'tl-xep name)))) + :debug-name debug-name))) (when name (assert-global-function-definition-type name locall-fun)) (setf (functional-entry-fun fun) locall-fun (functional-kind fun) :external + (functional-has-external-references-p locall-fun) t (functional-has-external-references-p fun) t) fun))) @@ -1004,6 +1036,7 @@ :policy *policy* :handled-conditions *handled-conditions* :disabled-package-locks *disabled-package-locks*)) + (*compiler-sset-counter* 0) (fun (make-functional-from-toplevel-lambda lambda-expression :name name :path path))) @@ -1018,14 +1051,10 @@ (locall-analyze-clambdas-until-done (list fun)) - (multiple-value-bind (components-from-dfo top-components hairy-top) - (find-initial-dfo (list fun)) - (declare (ignore hairy-top)) - - (let ((*all-components* (append components-from-dfo top-components))) - (dolist (component-from-dfo components-from-dfo) - (compile-component component-from-dfo) - (replace-toplevel-xeps component-from-dfo))) + (let ((components-from-dfo (find-initial-dfo (list fun)))) + (dolist (component-from-dfo components-from-dfo) + (compile-component component-from-dfo) + (replace-toplevel-xeps component-from-dfo)) (let ((entry-table (etypecase *compile-object* (fasl-output (fasl-output-entry-table @@ -1121,7 +1150,7 @@ (declare (list path)) (catch 'process-toplevel-form-error-abort - (let* ((path (or (gethash form *source-paths*) (cons form path))) + (let* ((path (or (get-source-path form) (cons form path))) (*compiler-error-bailout* (lambda (&optional condition) (convert-and-maybe-compile @@ -1298,7 +1327,7 @@ (defun compile-load-time-stuff (form for-value) (with-ir1-namespace (let* ((*lexenv* (make-null-lexenv)) - (lambda (ir1-toplevel form *current-path* for-value))) + (lambda (ir1-toplevel form *current-path* for-value nil))) (compile-toplevel (list lambda) t) lambda))) @@ -1377,10 +1406,10 @@ (maybe-mumble "IDFO ") (multiple-value-bind (components top-components hairy-top) (find-initial-dfo lambdas) - (let ((*all-components* (append components top-components))) + (let ((all-components (append components top-components))) (when *check-consistency* (maybe-mumble "[check]~%") - (check-ir1-consistency *all-components*)) + (check-ir1-consistency all-components)) (dolist (component (append hairy-top top-components)) (pre-physenv-analyze-toplevel component)) @@ -1391,7 +1420,7 @@ (when *check-consistency* (maybe-mumble "[check]~%") - (check-ir1-consistency *all-components*)) + (check-ir1-consistency all-components)) (if load-time-value-p (compile-load-time-value-lambda lambdas) @@ -1453,7 +1482,7 @@ (invoke-restart it)))))))) ;;; Read all forms from INFO and compile them, with output to OBJECT. -;;; Return (VALUES NIL WARNINGS-P FAILURE-P). +;;; Return (VALUES ABORT-P WARNINGS-P FAILURE-P). (defun sub-compile-file (info) (declare (type source-info info)) (let ((*package* (sane-package)) @@ -1461,6 +1490,8 @@ (sb!xc:*compile-file-pathname* nil) ; really bound in (sb!xc:*compile-file-truename* nil) ; SUB-SUB-COMPILE-FILE (*policy* *policy*) + (*code-coverage-records* (make-hash-table :test 'equal)) + (*code-coverage-blocks* (make-hash-table :test 'equal)) (*handled-conditions* *handled-conditions*) (*disabled-package-locks* *disabled-package-locks*) (*lexenv* (make-null-lexenv)) @@ -1472,7 +1503,7 @@ (*compiler-error-bailout* (lambda () (compiler-mumble "~2&; fatal error, aborting compilation~%") - (return-from sub-compile-file (values nil t t)))) + (return-from sub-compile-file (values t t t)))) (*current-path* nil) (*last-source-context* nil) (*last-original-source* nil) @@ -1486,6 +1517,7 @@ ;; and it's not obvious whether the rebinding to itself is ;; needed that SBCL doesn't need *BACKEND-INFO-ENVIRONMENT*. (*info-environment* *info-environment*) + (*compiler-sset-counter* 0) (*gensym-counter* 0)) (handler-case (handler-bind (((satisfies handle-condition-p) #'handle-condition-handler)) @@ -1495,6 +1527,19 @@ (sub-sub-compile-file info) + (unless (zerop (hash-table-count *code-coverage-records*)) + ;; Dump the code coverage records into the fasl. + (fopcompile `(record-code-coverage + ',(namestring *compile-file-pathname*) + ',(let (list) + (maphash (lambda (k v) + (declare (ignore k)) + (push v list)) + *code-coverage-records*) + list)) + nil + nil)) + (finish-block-compilation) (let ((object *compile-object*)) (etypecase object @@ -1507,11 +1552,12 @@ ;; the input file. (fatal-compiler-error (condition) (signal condition) - (when *compile-verbose* - (format *standard-output* + (pprint-logical-block (*error-output* nil :per-line-prefix "; ") + (format *error-output* "~@" condition)) - (values nil t t))))) + (finish-output *error-output*) + (values t t t))))) ;;; Return a pathname for the named file. The file must exist. (defun verify-source-file (pathname-designator) @@ -1620,7 +1666,7 @@ SPEED and COMPILATION-SPEED optimization values, and the |# (let* ((fasl-output nil) (output-file-name nil) - (compile-won nil) + (abort-p nil) (warnings-p nil) (failure-p t) ; T in case error keeps this from being set later (input-pathname (verify-source-file input-file)) @@ -1651,31 +1697,34 @@ SPEED and COMPILATION-SPEED optimization values, and the (when sb!xc:*compile-verbose* (print-compile-start-note source-info)) - (let ((*compile-object* fasl-output) - dummy) - (multiple-value-setq (dummy warnings-p failure-p) - (sub-compile-file source-info))) - (setq compile-won t)) + + (let ((*compile-object* fasl-output)) + (setf (values abort-p warnings-p failure-p) + (sub-compile-file source-info)))) (close-source-info source-info) (when fasl-output - (close-fasl-output fasl-output (not compile-won)) + (close-fasl-output fasl-output abort-p) (setq output-file-name (pathname (fasl-output-stream fasl-output))) - (when (and compile-won sb!xc:*compile-verbose*) + (when (and (not abort-p) sb!xc:*compile-verbose*) (compiler-mumble "~2&; ~A written~%" (namestring output-file-name)))) (when sb!xc:*compile-verbose* - (print-compile-end-note source-info compile-won)) + (print-compile-end-note source-info (not abort-p))) (when *compiler-trace-output* (close *compiler-trace-output*))) - (values (if output-file - ;; Hack around filesystem race condition... - (or (probe-file output-file-name) output-file-name) - nil) + ;; CLHS says that the first value is NIL if the "file could not + ;; be created". We interpret this to mean "a valid fasl could not + ;; be created" -- which can happen if the compilation is aborted + ;; before the whole file has been processed, due to eg. a reader + ;; error. + (values (when (and (not abort-p) output-file) + ;; Hack around filesystem race condition... + (or (probe-file output-file-name) output-file-name)) warnings-p failure-p))) @@ -1703,13 +1752,14 @@ SPEED and COMPILATION-SPEED optimization values, and the ;;; -- WHN 2000-12-09 (defun sb!xc:compile-file-pathname (input-file &key - (output-file (cfp-output-file-default - input-file)) + (output-file nil output-file-p) &allow-other-keys) #!+sb-doc "Return a pathname describing what file COMPILE-FILE would write to given these arguments." - (merge-pathnames output-file (merge-pathnames input-file))) + (if output-file-p + (merge-pathnames output-file (cfp-output-file-default input-file)) + (cfp-output-file-default input-file))) ;;;; MAKE-LOAD-FORM stuff @@ -1789,8 +1839,6 @@ SPEED and COMPILATION-SPEED optimization values, and the (:ignore-it nil) (t - (when (fasl-constant-already-dumped-p constant *compile-object*) - (return-from emit-make-load-form nil)) (let* ((name (write-to-string constant :level 1 :length 2)) (info (if init-form (list constant name init-form)