1 ;;;; This file contains compiler code and compiler-related stuff which
2 ;;;; can be built early on. Some of the stuff may be here because it's
3 ;;;; needed early on, some other stuff (e.g. constants) just because
4 ;;;; it might as well be done early so we don't have to think about
5 ;;;; whether it's done early enough.
7 ;;;; This software is part of the SBCL system. See the README file for
10 ;;;; This software is derived from the CMU CL system, which was
11 ;;;; written at Carnegie Mellon University and released into the
12 ;;;; public domain. The software is in the public domain and is
13 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
14 ;;;; files for more information.
18 ;;; ANSI limits on compilation
19 ;;; On AMD64 we prefer to use the ECX (not RCX) register,
20 ;;; which means that there can only be 32 bits of precision,
21 ;;; so accounting for the fixnum tag and 1 bit for the sign,
22 ;;; this leaves 30 bits. Of course this number is ridiculous
23 ;;; as a call with that many args would consume 8 GB of stack,
24 ;;; but it's surely not as ridiculous as ARRAY-DIMENSION-LIMIT.
25 (defconstant call-arguments-limit
27 #-x86-64 array-dimension-limit
28 "The exclusive upper bound on the number of arguments which may be passed
29 to a function, including &REST args.")
30 (defconstant lambda-parameters-limit call-arguments-limit
31 "The exclusive upper bound on the number of parameters which may be specified
32 in a given lambda list. This is actually the limit on required and &OPTIONAL
33 parameters. With &KEY and &AUX you can get more.")
34 (defconstant multiple-values-limit call-arguments-limit
35 "The exclusive upper bound on the number of multiple VALUES that you can
39 ;;;; miscellaneous types used both in the cross-compiler and on the target
41 (defstruct (dxable-args (:constructor make-dxable-args
(list))
44 (list nil
:read-only t
))
45 (defstruct (inlining-data (:include dxable-args
)
46 (:constructor make-inlining-data
(expansion list
))
49 (expansion nil
:read-only t
))
50 (declaim (freeze-type dxable-args
))
52 (defstruct (ir1-namespace (:conc-name
"") (:copier nil
) (:predicate nil
))
53 ;; FREE-VARS translates from the names of variables referenced
54 ;; globally to the LEAF structures for them. FREE-FUNS is like
55 ;; FREE-VARS, only it deals with function names.
57 ;; We must preserve the property that a proclamation for a global
58 ;; thing only affects the code after it. This takes some work, since
59 ;; a proclamation may appear in the middle of a block being
60 ;; compiled. If there are references before the proclaim, then we
61 ;; copy the current entry before modifying it. Code converted before
62 ;; the proclaim sees the old Leaf, while code after it sees the new
64 (free-vars (make-hash-table :test
'eq
) :read-only t
:type hash-table
)
65 (free-funs (make-hash-table :test
#'equal
) :read-only t
:type hash-table
)
66 ;; We use the same CONSTANT structure to represent all EQL anonymous
67 ;; constants. This hashtable translates from constants to the LEAFs
68 ;; that represent them.
69 (eql-constants (make-hash-table :test
'eql
) :read-only t
:type hash-table
)
70 ;; During file compilation we are allowed to coalesce similar
71 ;; constants. This coalescing is distinct from the coalescing done
72 ;; in the dumper, since the effect here is to reduce the number of
73 ;; boxed constants appearing in a code component.
74 (similar-constants (make-similarity-table) :read-only t
:type hash-table
))
75 (declaim (freeze-type ir1-namespace
))
77 (sb-impl::define-thread-local
*ir1-namespace
*)
78 (declaim (type ir1-namespace
*ir1-namespace
*))
80 ;;; *ALLOW-INSTRUMENTING* controls whether we should allow the
81 ;;; insertion of instrumenting code (like a (CATCH ...)) around code
82 ;;; to allow the debugger RETURN and STEP commands to function (we
83 ;;; disallow it for internal stuff).
84 (defvar *allow-instrumenting
*)
86 ;;; miscellaneous forward declarations
87 (defvar *component-being-compiled
*)
88 (defvar *compiler-error-context
*)
89 ;;; Bind this to a stream to capture various internal debugging output.
90 (defvar *compiler-trace-output
* nil
)
91 ;;; These are the default, but the list can also include
92 ;;; :pre-ir2-optimize, :symbolic-asm.
93 (defvar *compile-trace-targets
* '(:ir1
:ir2
:vop
:symbolic-asm
:disassemble
))
94 (defvar *current-path
*)
95 (defvar *current-component
*)
96 (defvar *elsewhere-label
*)
97 (defvar *source-info
*)
98 (defvar *source-plist
*)
99 (defvar *source-namestring
*)
101 (defvar *handled-conditions
* nil
)
102 (defvar *disabled-package-locks
* nil
)
105 ;;;; miscellaneous utilities
107 ;;; COMPILE-FILE usually puts all nontoplevel code in immobile space, but COMPILE
108 ;;; offers a choice. Because the immobile space GC does not run often enough (yet),
109 ;;; COMPILE usually places code in the dynamic space managed by our copying GC.
110 ;;; Change this variable if your application always demands immobile code.
111 ;;; In particular, ELF cores shrink the immobile code space down to just enough
112 ;;; to contain all code, plus about 1/2 MiB of spare, which means that you can't
113 ;;; subsequently compile a whole lot into immobile space.
114 ;;; The value is changed to :AUTO in make-target-2-load.lisp which supresses
115 ;;; codegen optimizations for immobile space, but nonetheless prefers to allocate
116 ;;; the code there, falling back to dynamic space if there is no room left.
117 ;;; These controls exist whether or not the immobile-space feature is present.
118 (declaim (type (member :immobile
:dynamic
:auto
) *compile-to-memory-space
*)
119 (type (member :immobile
:dynamic
) *compile-file-to-memory-space
*))
120 (defvar *compile-to-memory-space
* :immobile
) ; BUILD-TIME default
121 (export '*compile-file-to-memory-space
*) ; silly user code looks at, even if no immobile-space
122 (defvar *compile-file-to-memory-space
* :immobile
) ; BUILD-TIME default
124 (defun compile-perfect-hash (lambda test-inputs
)
125 ;; Don't blindly trust the hash generator: assert that computed values are
126 ;; in range and not repeated.
127 (let ((seen (make-array (power-of-two-ceiling (length test-inputs
))
128 :element-type
'bit
:initial-element
0))
129 (f #-sb-xc-host
; use fasteval if possible
131 ((< (length test-inputs
) 100) ; interpreting is faster
132 (let ((*evaluator-mode
* :interpret
))
134 (t (let ((*compile-to-memory-space
* :dynamic
))
135 (compile nil lambda
))))
137 (destructuring-bind (head lambda-list . body
) lambda
138 (aver (eq head
'lambda
))
139 (multiple-value-bind (forms decls
) (parse-body body nil
)
140 (declare (ignore decls
))
141 ;; Give the host a definition for SB-C::UINT32-MODULARLY and remove _all_
142 ;; OPTIMIZE decls hidden within. We don't need to pedantically correctly
143 ;; code-walk here, because hash expressions are largely boilerplate that
144 ;; will not confusingly match forms such as (LET ((OPTIMIZE ...))).
146 `(macrolet ((uint32-modularly (&whole form
&rest exprs
)
147 (declare (ignore exprs
))
148 (funcall (sb-xc:macro-function
'sb-c
::uint32-modularly
)
150 ,@(subst-if '(optimize)
151 (lambda (x) (typep x
'(cons (eql optimize
) (not null
))))
153 (compile nil
`(lambda ,lambda-list
,new-body
)))))))
154 (loop for input across test-inputs
155 do
(let ((h (funcall f input
)))
156 (unless (zerop (bit seen h
))
157 (bug "Perfect hash generator failed on ~X" test-inputs
))
158 (setf (bit seen h
) 1)))
161 (declaim (ftype (sfunction () list
) name-context
))
162 (defun debug-name (type thing
&optional context
)
163 (let ((name (list* type thing
(when context
(name-context)))))
164 (when (legal-fun-name-p name
)
165 (bug "~S is a legal function name, and cannot be used as a ~
169 ;;; Bound during eval-when :compile-time evaluation.
170 (defvar *compile-time-eval
* nil
)
171 (declaim (always-bound *compile-time-eval
*))
173 #-immobile-code
(defmacro code-immobile-p
(thing) `(progn ,thing nil
))
174 #-sb-xc-host
; not needed for make-hlst-1
175 (defmacro maybe-with-system-tlab
((source-object) allocator
)
176 (declare (ignorable source-object
))
177 #+system-tlabs
`(if (sb-vm::force-to-heap-p
,source-object
)
178 (locally (declare (sb-c::tlab
:system
)) ,allocator
)
180 #-system-tlabs allocator
)
181 ;;; TLAB selection is an aspect of a POLICY but this sets the global choice
182 (defvar *force-system-tlab
* nil
)
184 ;;; The allocation quantum for boxed code header words.
185 ;;; 2 implies an even length boxed header; 1 implies no restriction.
186 (defconstant code-boxed-words-align
(+ 2 #+(or x86 x86-64
) -
1))
188 ;;; Unique number assigned into high 4 bytes of 64-bit code size slot
189 ;;; so that we can sort the contents of text space in a more-or-less
190 ;;; predictable manner based on the order in which code was loaded.
191 ;;; This wraps around at 32 bits, but it's still deterministic.
192 (define-load-time-global *code-serialno
* 0)
193 (declaim (fixnum *code-serialno
*))
197 ;; Might as well be as specific as we can.
198 ;; Really it should be (satisfies array-has-fill-pointer-p)
199 ;; but that predicate is not total (errors on NIL).
200 ;; And who knows what the host considers "simple".
201 #-sb-xc-host
(not simple-array
)))
203 (defstruct (compilation (:copier nil
)
206 (fun-names-in-this-file)
207 ;; for constant coalescing across code components, and/or for situations
208 ;; where SIMILARP does not do what you want.
210 ;; When compiling within the extent of *macro-policy* we have to store up
211 ;; any DECLAIMs for later replay. The logic is explained in EVAL-COMPILE-TLF.
212 ;; This slot is set to NIL before use and reset when done.
213 (saved-optimize-decls :none
)
214 (coverage-metadata nil
:type
(or (cons hash-table hash-table
) null
) :read-only t
)
215 (msan-unpoison nil
:read-only t
)
216 (sset-counter 1 :type fixnum
)
217 ;; Map of function name -> something about how many calls were converted
218 ;; as ordinary calls not in the scope of a local or global notinline declaration.
219 ;; Useful for finding functions that were supposed to have been converted
220 ;; through some kind of transformation but were not.
221 ;; FIXME: this should be scoped to a compile/load but there are
222 ;; apparently some difficulties in doing so.
223 ; (emitted-full-calls (make-hash-table :test 'equal))
224 ;; if emitting a cfasl, the fasl stream to that
225 (compile-toplevel-object nil
:read-only t
)
226 ;; The current block compilation state. These are initialized to
227 ;; the :Block-Compile and :Entry-Points arguments that COMPILE-FILE
228 ;; was called with. Subsequent START-BLOCK or END-BLOCK
229 ;; declarations alter the values.
230 (block-compile nil
:type
(member nil t
:specified
))
231 (entry-points nil
:type list
)
232 ;; When block compiling, used by PROCESS-FORM to accumulate top
233 ;; level lambdas resulting from compiling subforms. (In reverse
235 (toplevel-lambdas nil
:type list
)
236 ;; We build a list of top-level lambdas, and then periodically smash them
237 ;; together into a single component and compile it.
238 (pending-toplevel-lambdas nil
:type list
)
239 ;; We record whether the package environment has changed during the
240 ;; compilation of some sequence top level forms. This allows the
241 ;; compiler to dump symbols in such a way that the loader can
242 ;; reconstruct them in the correct package.
243 (package-environment-changed nil
:type boolean
)
244 ;; Bidrectional map between IR1/IR2/assembler abstractions and a corresponding
245 ;; small integer or string identifier. One direction could be done by adding
246 ;; the ID as slot to each object, but we want both directions.
247 ;; These could just as well be scoped by WITH-IR1-NAMESPACE, but
248 ;; since it's primarily a debugging tool, it's nicer to have
249 ;; a wider unique scope by ID.
250 (objmap-obj-to-id (make-hash-table :test
'eq
) :read-only t
)
251 (objmap-id-to-node nil
:type
(or null id-array
)) ; number -> NODE
252 (objmap-id-to-comp nil
:type
(or null id-array
)) ; number -> COMPONENT
253 (objmap-id-to-leaf nil
:type
(or null id-array
)) ; number -> LEAF
254 (objmap-id-to-cont nil
:type
(or null id-array
)) ; number -> CTRAN or LVAR
255 (objmap-id-to-ir2block nil
:type
(or null id-array
)) ; number -> IR2-BLOCK
256 (objmap-id-to-tn nil
:type
(or null id-array
)) ; number -> TN
257 (objmap-id-to-label nil
:type
(or null id-array
)) ; number -> LABEL
258 deleted-source-paths
)
259 (declaim (freeze-type compilation
))
261 (sb-impl::define-thread-local
*compilation
*)
262 (declaim (type compilation
*compilation
*))
264 ;; from 'llvm/projects/compiler-rt/lib/msan/msan.h':
265 ;; "#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)"
266 #+linux
; shadow space differs by OS
267 (defconstant sb-vm
::msan-mem-to-shadow-xor-const
#x500000000000
)
269 (define-load-time-global *emitted-full-calls
*
270 (make-hash-table :test
'equal
#-sb-xc-host
:synchronized
#-sb-xc-host t
))
272 (defmacro get-emitted-full-calls
(name)
273 ;; Todo: probably remove the wrapping cons. It was for globaldb
274 ;; which is particularly inefficient at updates (because it can only
275 ;; use an R/C/U paradigm, and so conses on every insert,
276 ;; unlike a hash-table which can just update the cell)
277 `(gethash ,name
*emitted-full-calls
*))
279 ;; Return the number of calls to NAME that IR2 emitted as full calls,
280 ;; not counting calls via #'F that went untracked.
281 ;; Return 0 if the answer is nonzero but a warning was already signaled
282 ;; about any full calls were emitted. This return convention satisfies the
283 ;; intended use of this statistic - to decide whether to generate a warning
284 ;; about failure to inline NAME, which is shown at most once per name
285 ;; to avoid unleashing a flood of identical warnings.
286 (defun emitted-full-call-count (name)
287 (let ((status (get-emitted-full-calls name
)))
288 (and (integerp status
)
289 ;; Bit 0 tells whether any call was NOT in the presence of
290 ;; a 'notinline' declaration, thus eligible to be inline.
291 ;; Bit 1 tells whether any warning was emitted yet.
292 (= (logand status
3) #b01
)
293 (ash status -
2)))) ; the call count as tracked by IR2
295 (defun accumulate-full-calls (data)
296 (loop for
(name status
) in data
298 (let ((existing (gethash name
*emitted-full-calls
* 0)))
299 (setf (gethash name
*emitted-full-calls
*)
300 (logior (+ (logand existing
#b11
) ; old flag bits
301 (logand status
#b11
)) ; new flag bits
302 (logand existing -
4) ; old count
303 (logand status -
4)))))) ; new count
305 (declaim (type (simple-array (unsigned-byte 16) 1) *asm-routine-offsets
*))
306 (define-load-time-global *asm-routine-offsets
*
307 (make-array 0 :element-type
'(unsigned-byte 16)))