0.pre7.38:
[sbcl.git] / src / compiler / entry.lisp
1 ;;;; Code in this file handles VM-independent details of run-time
2 ;;;; function representation that primarily concern IR2 conversion and
3 ;;;; the dumper/loader.
4
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
8 ;;;; This software is derived from the CMU CL system, which was
9 ;;;; written at Carnegie Mellon University and released into the
10 ;;;; public domain. The software is in the public domain and is
11 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
12 ;;;; files for more information.
13
14 (in-package "SB!C")
15
16 ;;; This phase runs before IR2 conversion, initializing each XEP's
17 ;;; ENTRY-INFO structure. We call the VM-supplied
18 ;;; SELECT-COMPONENT-FORMAT function to make VM-dependent
19 ;;; initializations in the IR2-COMPONENT. This includes setting the
20 ;;; IR2-COMPONENT-KIND and allocating fixed implementation overhead in
21 ;;; the constant pool. If there was a forward reference to a function,
22 ;;; then the ENTRY-INFO will already exist, but will be uninitialized.
23 (defun entry-analyze (component)
24   (let ((2comp (component-info component)))
25     (dolist (fun (component-lambdas component))
26       (when (external-entry-point-p fun)
27         (let ((info (or (leaf-info fun)
28                         (setf (leaf-info fun) (make-entry-info)))))
29           (compute-entry-info fun info)
30           (push info (ir2-component-entries 2comp))))))
31
32   (select-component-format component)
33   (values))
34
35 ;;; Takes the list representation of the debug arglist and turns it
36 ;;; into a string.
37 ;;;
38 ;;; FIXME: Why don't we just save this as a list instead of converting
39 ;;; it to a string?
40 (defun make-arg-names (x)
41   (declare (type functional x))
42   (let ((args (functional-arg-documentation x)))
43     (aver (not (eq args :unspecified)))
44     (if (null args)
45         "()"
46         (let ((*print-pretty* t)
47               (*print-escape* t)
48               (*print-base* 10)
49               (*print-radix* nil)
50               (*print-case* :downcase))
51           (write-to-string args)))))
52
53 ;;; Initialize INFO structure to correspond to the XEP LAMBDA FUN.
54 (defun compute-entry-info (fun info)
55   (declare (type clambda fun) (type entry-info info))
56   (let ((bind (lambda-bind fun))
57         (internal-fun (functional-entry-function fun)))
58     (setf (entry-info-closure-p info)
59           (not (null (environment-closure (lambda-environment fun)))))
60     (setf (entry-info-offset info) (gen-label))
61     (setf (entry-info-name info)
62           (let ((name (leaf-name internal-fun)))
63             (or name
64                 (component-name (block-component (node-block bind))))))
65     (when (policy bind (>= debug 1))
66       (setf (entry-info-arguments info) (make-arg-names internal-fun))
67       (setf (entry-info-type info) (type-specifier (leaf-type internal-fun)))))
68   (values))
69
70 ;;; Replace all references to COMPONENT's non-closure XEPs that appear
71 ;;; in top-level or externally-referenced components, changing to
72 ;;; :TOP-LEVEL-XEP FUNCTIONALs. If the cross-component ref is not in a
73 ;;; :TOP-LEVEL/externally-referenced component, or is to a closure,
74 ;;; then substitution is suppressed.
75 ;;;
76 ;;; When a cross-component ref is not substituted, we return T to
77 ;;; indicate that early deletion of this component's IR1 should not be
78 ;;; done. We also return T if this component contains
79 ;;; :TOP-LEVEL/externally-referenced lambdas (though it is not a
80 ;;; :TOP-LEVEL component.)
81 ;;;
82 ;;; We deliberately don't use the normal reference deletion, since we
83 ;;; don't want to trigger deletion of the XEP (although it shouldn't
84 ;;; hurt, since this is called after COMPONENT is compiled.) Instead,
85 ;;; we just clobber the REF-LEAF.
86 (defun replace-top-level-xeps (component)
87   (let ((res nil))
88     (dolist (lambda (component-lambdas component))
89       (case (functional-kind lambda)
90         (:external
91          (unless (lambda-has-external-references-p lambda)
92            (let* ((ef (functional-entry-function lambda))
93                   (new (make-functional :kind :top-level-xep
94                                         :info (leaf-info lambda)
95                                         :name (leaf-name ef)
96                                         :lexenv (make-null-lexenv)))
97                   (closure (environment-closure
98                             (lambda-environment (main-entry ef)))))
99              (dolist (ref (leaf-refs lambda))
100                (let ((ref-component (block-component (node-block ref))))
101                  (cond ((eq ref-component component))
102                        ((or (not (component-top-levelish-p ref-component))
103                             closure)
104                         (setq res t))
105                        (t
106                         (setf (ref-leaf ref) new)
107                         (push ref (leaf-refs new)))))))))
108         (:top-level
109          (setq res t))))
110     res))