1 ;;;; scheduling assembler
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!ASSEM")
14 ;;;; assembly control parameters
16 (defvar *assem-scheduler-p* nil)
17 (declaim (type boolean *assem-scheduler-p*))
19 (defvar *assem-instructions* (make-hash-table :test 'equal))
20 (declaim (type hash-table *assem-instructions*))
22 (defvar *assem-max-locations* 0)
23 (declaim (type index *assem-max-locations*))
25 ;;;; the SEGMENT structure
27 ;;; This structure holds the state of the assembler.
28 (defstruct (segment (:copier nil))
29 ;; the name of this segment (for debugging output and stuff)
30 (name "unnamed" :type simple-string)
31 ;; Ordinarily this is a vector where instructions are written. If
32 ;; the segment is made invalid (e.g. by APPEND-SEGMENT) then the
33 ;; vector can be replaced by NIL.
37 :element-type 'assembly-unit)
38 :type (or null (vector assembly-unit)))
39 ;; whether or not to run the scheduler. Note: if the instruction
40 ;; definitions were not compiled with the scheduler turned on, this
43 ;; If a function, then this is funcalled for each inst emitted with
44 ;; the segment, the VOP, the name of the inst (as a string), and the
46 (inst-hook nil :type (or function null))
47 ;; what position does this correspond to? Initially, positions and
48 ;; indexes are the same, but after we start collapsing choosers,
49 ;; positions can change while indexes stay the same.
50 (current-posn 0 :type index)
51 ;; a list of all the annotations that have been output to this segment
52 (annotations nil :type list)
53 ;; a pointer to the last cons cell in the annotations list. This is
54 ;; so we can quickly add things to the end of the annotations list.
55 (last-annotation nil :type list)
56 ;; the number of bits of alignment at the last time we synchronized
57 (alignment max-alignment :type alignment)
58 ;; the position the last time we synchronized
59 (sync-posn 0 :type index)
60 ;; The posn and index everything ends at. This is not maintained
61 ;; while the data is being generated, but is filled in after.
62 ;; Basically, we copy CURRENT-POSN and CURRENT-INDEX so that we can
63 ;; trash them while processing choosers and back-patches.
64 (final-posn 0 :type index)
65 (final-index 0 :type index)
66 ;; *** State used by the scheduler during instruction queueing.
68 ;; a list of postits. These are accumulated between instructions.
69 (postits nil :type list)
70 ;; ``Number'' for last instruction queued. Used only to supply insts
71 ;; with unique sset-element-number's.
72 (inst-number 0 :type index)
73 ;; SIMPLE-VECTORs mapping locations to the instruction that reads them and
74 ;; instructions that write them
75 (readers (make-array *assem-max-locations* :initial-element nil)
77 (writers (make-array *assem-max-locations* :initial-element nil)
79 ;; The number of additional cycles before the next control transfer,
80 ;; or NIL if a control transfer hasn't been queued. When a delayed
81 ;; branch is queued, this slot is set to the delay count.
82 (branch-countdown nil :type (or null (and fixnum unsigned-byte)))
83 ;; *** These two slots are used both by the queuing noise and the
86 ;; All the instructions that are pending and don't have any
87 ;; unresolved dependents. We don't list branches here even if they
88 ;; would otherwise qualify. They are listed above.
89 (emittable-insts-sset (make-sset) :type sset)
90 ;; list of queued branches. We handle these specially, because they
91 ;; have to be emitted at a specific place (e.g. one slot before the
93 (queued-branches nil :type list)
94 ;; *** state used by the scheduler during instruction scheduling
96 ;; the instructions who would have had a read dependent removed if
97 ;; it were not for a delay slot. This is a list of lists. Each
98 ;; element in the top level list corresponds to yet another cycle of
99 ;; delay. Each element in the second level lists is a dotted pair,
100 ;; holding the dependency instruction and the dependent to remove.
101 (delayed nil :type list)
102 ;; The emittable insts again, except this time as a list sorted by depth.
103 (emittable-insts-queue nil :type list)
104 ;; Whether or not to collect dynamic statistics. This is just the same as
105 ;; *COLLECT-DYNAMIC-STATISTICS* but is faster to reference.
107 (collect-dynamic-statistics nil))
108 (sb!c::defprinter (segment)
111 ;;; where the next byte of output goes
112 #!-sb-fluid (declaim (inline segment-current-index))
113 (defun segment-current-index (segment)
114 (fill-pointer (segment-buffer segment)))
115 (defun (setf segment-current-index) (new-value segment)
116 ;; FIXME: It would be lovely to enforce this, but first FILL-IN will
117 ;; need to be convinced to stop rolling SEGMENT-CURRENT-INDEX
120 ;; Enforce an observed regularity which makes it easier to think
121 ;; about what's going on in the (legacy) code: The segment never
122 ;; shrinks. -- WHN the reverse engineer
123 #+nil (aver (>= new-value (segment-current-index segment)))
124 (let ((buffer (segment-buffer segment)))
125 ;; Make sure that the array is big enough.
127 ((>= (array-dimension buffer 0) new-value))
128 ;; When we have to increase the size of the array, we want to
129 ;; roughly double the vector length: that way growing the array
130 ;; to size N conses only O(N) bytes in total. But just doubling
131 ;; the length would leave a zero-length vector unchanged. Hence,
132 ;; take the MAX with 1..
133 (adjust-array buffer (max 1 (* 2 (array-dimension buffer 0)))))
134 ;; Now that the array has the intended next free byte, we can point to it.
135 (setf (fill-pointer buffer) new-value)))
138 ;;; Various functions (like BACK-PATCH-FUN or CHOOSER-WORST-CASE-FUN)
139 ;;; aren't cleanly parameterized, but instead use
140 ;;; SEGMENT-CURRENT-INDEX and/or SEGMENT-CURRENT-POSN as global
141 ;;; variables. So code which calls such functions needs to modify
142 ;;; SEGMENT-CURRENT-INDEX and SEGMENT-CURRENT-POSN. This is left over
143 ;;; from the old new-assem.lisp C-style code, and so all the
144 ;;; destruction happens to be done after other uses of these slots are
145 ;;; done and things basically work. However, (1) it's fundamentally
146 ;;; nasty, and (2) at least one thing doesn't work right: OpenMCL
147 ;;; properly points out that SUBSEQ's indices aren't supposed to
148 ;;; exceed its logical LENGTH, i.e. its FILL-POINTER, i.e.
149 ;;; SEGMENT-CURRENT-INDEX.
151 ;;; As a quick fix involving minimal modification of legacy code,
152 ;;; we do such sets of SEGMENT-CURRENT-INDEX and SEGMENT-CURRENT-POSN
153 ;;; using this macro, which restores 'em afterwards.
155 ;;; FIXME: It'd probably be better to cleanly parameterize things like
156 ;;; BACK-PATCH-FUN so we can avoid this nastiness altogether.
157 (defmacro with-modified-segment-index-and-posn ((segment index posn)
159 (with-unique-names (n-segment old-index old-posn)
160 `(let* ((,n-segment ,segment)
161 (,old-index (segment-current-index ,n-segment))
162 (,old-posn (segment-current-posn ,n-segment)))
165 (setf (segment-current-index ,n-segment) ,index
166 (segment-current-posn ,n-segment) ,posn)
168 (setf (segment-current-index ,n-segment) ,old-index
169 (segment-current-posn ,n-segment) ,old-posn)))))
171 ;;;; structures/types used by the scheduler
173 (!def-boolean-attribute instruction
174 ;; This attribute is set if the scheduler can freely flush this
175 ;; instruction if it thinks it is not needed. Examples are NOP and
176 ;; instructions that have no side effect not described by the
179 ;; This attribute is set when an instruction can cause a control
180 ;; transfer. For test instructions, the delay is used to determine
181 ;; how many instructions follow the branch.
183 ;; This attribute indicates that this ``instruction'' can be
184 ;; variable length, and therefore had better never be used in a
185 ;; branch delay slot.
188 (def!struct (instruction
189 (:include sset-element)
191 (:constructor make-instruction (number emitter attributes delay))
193 ;; The function to envoke to actually emit this instruction. Gets called
194 ;; with the segment as its one argument.
195 (emitter (missing-arg) :type (or null function))
196 ;; The attributes of this instruction.
197 (attributes (instruction-attributes) :type sb!c:attributes)
198 ;; Number of instructions or cycles of delay before additional
199 ;; instructions can read our writes.
200 (delay 0 :type (and fixnum unsigned-byte))
201 ;; the maximum number of instructions in the longest dependency
202 ;; chain from this instruction to one of the independent
203 ;; instructions. This is used as a heuristic at to which
204 ;; instructions should be scheduled first.
205 (depth nil :type (or null (and fixnum unsigned-byte)))
206 ;; Note: When trying remember which of the next four is which, note
207 ;; that the ``read'' or ``write'' always refers to the dependent
208 ;; (second) instruction.
210 ;; instructions whose writes this instruction tries to read
211 (read-dependencies (make-sset) :type sset)
212 ;; instructions whose writes or reads are overwritten by this instruction
213 (write-dependencies (make-sset) :type sset)
214 ;; instructions which write what we read or write
215 (write-dependents (make-sset) :type sset)
216 ;; instructions which read what we write
217 (read-dependents (make-sset) :type sset))
218 #!+sb-show-assem (defvar *inst-ids* (make-hash-table :test 'eq))
219 #!+sb-show-assem (defvar *next-inst-id* 0)
220 (sb!int:def!method print-object ((inst instruction) stream)
221 (print-unreadable-object (inst stream :type t :identity t)
223 (princ (or (gethash inst *inst-ids*)
224 (setf (gethash inst *inst-ids*)
225 (incf *next-inst-id*)))
228 #!+sb-show-assem " emitter=~S" #!-sb-show-assem "emitter=~S"
229 (let ((emitter (inst-emitter inst)))
231 (multiple-value-bind (lambda lexenv-p name)
232 (function-lambda-expression emitter)
233 (declare (ignore lambda lexenv-p))
236 (when (inst-depth inst)
237 (format stream ", depth=~W" (inst-depth inst)))))
240 (defun reset-inst-ids ()
242 (setf *next-inst-id* 0))
244 ;;;; the scheduler itself
246 (defmacro without-scheduling ((&optional (segment '(%%current-segment%%)))
249 "Execute BODY (as a PROGN) without scheduling any of the instructions
250 generated inside it. This is not protected by UNWIND-PROTECT, so
251 DO NOT use THROW or RETURN-FROM to escape from it."
252 ;; FIXME: Why not just use UNWIND-PROTECT? Or is there some other
253 ;; reason why we shouldn't use THROW or RETURN-FROM?
256 `(let* ((,seg ,segment)
257 (,var (segment-run-scheduler ,seg)))
259 (schedule-pending-instructions ,seg)
260 (setf (segment-run-scheduler ,seg) nil))
262 (setf (segment-run-scheduler ,seg) ,var))))
264 (defmacro note-dependencies ((segment inst) &body body)
265 (sb!int:once-only ((segment segment) (inst inst))
266 `(macrolet ((reads (loc) `(note-read-dependency ,',segment ,',inst ,loc))
267 (writes (loc &rest keys)
268 `(note-write-dependency ,',segment ,',inst ,loc ,@keys)))
271 (defun note-read-dependency (segment inst read)
272 (multiple-value-bind (loc-num size)
273 (sb!c:location-number read)
274 #!+sb-show-assem (format *trace-output*
275 "~&~S reads ~S[~W for ~W]~%"
276 inst read loc-num size)
278 ;; Iterate over all the locations for this TN.
279 (do ((index loc-num (1+ index))
280 (end-loc (+ loc-num (or size 1))))
282 (declare (type (mod 2048) index end-loc))
283 (let ((writers (svref (segment-writers segment) index)))
285 ;; The inst that wrote the value we want to read must have
287 (let ((writer (car writers)))
288 (sset-adjoin writer (inst-read-dependencies inst))
289 (sset-adjoin inst (inst-read-dependents writer))
290 (sset-delete writer (segment-emittable-insts-sset segment))
291 ;; And it must have been completed *after* all other
292 ;; writes to that location. Actually, that isn't quite
293 ;; true. Each of the earlier writes could be done
294 ;; either before this last write, or after the read, but
295 ;; we have no way of representing that.
296 (dolist (other-writer (cdr writers))
297 (sset-adjoin other-writer (inst-write-dependencies writer))
298 (sset-adjoin writer (inst-write-dependents other-writer))
299 (sset-delete other-writer
300 (segment-emittable-insts-sset segment))))
301 ;; And we don't need to remember about earlier writes any
302 ;; more. Shortening the writers list means that we won't
303 ;; bother generating as many explicit arcs in the graph.
304 (setf (cdr writers) nil)))
305 (push inst (svref (segment-readers segment) index)))))
308 (defun note-write-dependency (segment inst write &key partially)
309 (multiple-value-bind (loc-num size)
310 (sb!c:location-number write)
311 #!+sb-show-assem (format *trace-output*
312 "~&~S writes ~S[~W for ~W]~%"
313 inst write loc-num size)
315 ;; Iterate over all the locations for this TN.
316 (do ((index loc-num (1+ index))
317 (end-loc (+ loc-num (or size 1))))
319 (declare (type (mod 2048) index end-loc))
320 ;; All previous reads of this location must have completed.
321 (dolist (prev-inst (svref (segment-readers segment) index))
322 (unless (eq prev-inst inst)
323 (sset-adjoin prev-inst (inst-write-dependencies inst))
324 (sset-adjoin inst (inst-write-dependents prev-inst))
325 (sset-delete prev-inst (segment-emittable-insts-sset segment))))
327 ;; All previous writes to the location must have completed.
328 (dolist (prev-inst (svref (segment-writers segment) index))
329 (sset-adjoin prev-inst (inst-write-dependencies inst))
330 (sset-adjoin inst (inst-write-dependents prev-inst))
331 (sset-delete prev-inst (segment-emittable-insts-sset segment)))
332 ;; And we can forget about remembering them, because
333 ;; depending on us is as good as depending on them.
334 (setf (svref (segment-writers segment) index) nil))
335 (push inst (svref (segment-writers segment) index)))))
338 ;;; This routine is called by due to uses of the INST macro when the
339 ;;; scheduler is turned on. The change to the dependency graph has
340 ;;; already been computed, so we just have to check to see whether the
341 ;;; basic block is terminated.
342 (defun queue-inst (segment inst)
343 #!+sb-show-assem (format *trace-output* "~&queuing ~S~%" inst)
344 #!+sb-show-assem (format *trace-output*
345 " reads ~S~% writes ~S~%"
346 (sb!int:collect ((reads))
347 (do-sset-elements (read
348 (inst-read-dependencies inst))
351 (sb!int:collect ((writes))
352 (do-sset-elements (write
353 (inst-write-dependencies inst))
356 (aver (segment-run-scheduler segment))
357 (let ((countdown (segment-branch-countdown segment)))
360 (aver (not (instruction-attributep (inst-attributes inst)
362 (cond ((instruction-attributep (inst-attributes inst) branch)
364 (setf countdown (inst-delay inst)))
365 (push (cons countdown inst)
366 (segment-queued-branches segment)))
368 (sset-adjoin inst (segment-emittable-insts-sset segment))))
370 (setf (segment-branch-countdown segment) countdown)
371 (when (zerop countdown)
372 (schedule-pending-instructions segment))))
375 ;;; Emit all the pending instructions, and reset any state. This is
376 ;;; called whenever we hit a label (i.e. an entry point of some kind)
377 ;;; and when the user turns the scheduler off (otherwise, the queued
378 ;;; instructions would sit there until the scheduler was turned back
379 ;;; on, and emitted in the wrong place).
380 (defun schedule-pending-instructions (segment)
381 (aver (segment-run-scheduler segment))
383 ;; Quick blow-out if nothing to do.
384 (when (and (sset-empty (segment-emittable-insts-sset segment))
385 (null (segment-queued-branches segment)))
386 (return-from schedule-pending-instructions
389 #!+sb-show-assem (format *trace-output*
390 "~&scheduling pending instructions..~%")
392 ;; Note that any values live at the end of the block have to be
394 (let ((emittable-insts (segment-emittable-insts-sset segment))
395 (writers (segment-writers segment)))
396 (dotimes (index (length writers))
397 (let* ((writer (svref writers index))
399 (overwritten (cdr writer)))
402 (let ((write-dependencies (inst-write-dependencies inst)))
403 (dolist (other-inst overwritten)
404 (sset-adjoin inst (inst-write-dependents other-inst))
405 (sset-adjoin other-inst write-dependencies)
406 (sset-delete other-inst emittable-insts))))
407 ;; If the value is live at the end of the block, we can't flush it.
408 (setf (instruction-attributep (inst-attributes inst) flushable)
411 ;; Grovel through the entire graph in the forward direction finding
412 ;; all the leaf instructions.
413 (labels ((grovel-inst (inst)
415 (do-sset-elements (dep (inst-write-dependencies inst))
416 (let ((dep-depth (or (inst-depth dep) (grovel-inst dep))))
417 (when (> dep-depth max)
418 (setf max dep-depth))))
419 (do-sset-elements (dep (inst-read-dependencies inst))
421 (+ (or (inst-depth dep) (grovel-inst dep))
423 (when (> dep-depth max)
424 (setf max dep-depth))))
425 (cond ((and (sset-empty (inst-read-dependents inst))
426 (instruction-attributep (inst-attributes inst)
428 #!+sb-show-assem (format *trace-output*
431 (setf (inst-emitter inst) nil)
432 (setf (inst-depth inst) max))
434 (setf (inst-depth inst) max))))))
435 (let ((emittable-insts nil)
437 (do-sset-elements (inst (segment-emittable-insts-sset segment))
439 (if (zerop (inst-delay inst))
440 (push inst emittable-insts)
442 (add-to-nth-list delayed inst (1- (inst-delay inst))))))
443 (setf (segment-emittable-insts-queue segment)
444 (sort emittable-insts #'> :key #'inst-depth))
445 (setf (segment-delayed segment) delayed))
446 (dolist (branch (segment-queued-branches segment))
447 (grovel-inst (cdr branch))))
448 #!+sb-show-assem (format *trace-output*
449 "queued branches: ~S~%"
450 (segment-queued-branches segment))
451 #!+sb-show-assem (format *trace-output*
452 "initially emittable: ~S~%"
453 (segment-emittable-insts-queue segment))
454 #!+sb-show-assem (format *trace-output*
455 "initially delayed: ~S~%"
456 (segment-delayed segment))
458 ;; Accumulate the results in reverse order. Well, actually, this
459 ;; list will be in forward order, because we are generating the
460 ;; reverse order in reverse.
463 ;; Schedule all the branches in their exact locations.
464 (let ((insts-from-end (segment-branch-countdown segment)))
465 (dolist (branch (segment-queued-branches segment))
466 (let ((inst (cdr branch)))
467 (dotimes (i (- (car branch) insts-from-end))
468 ;; Each time through this loop we need to emit another
469 ;; instruction. First, we check to see whether there is
470 ;; any instruction that must be emitted before (i.e. must
471 ;; come after) the branch inst. If so, emit it. Otherwise,
472 ;; just pick one of the emittable insts. If there is
473 ;; nothing to do, then emit a nop. ### Note: despite the
474 ;; fact that this is a loop, it really won't work for
475 ;; repetitions other then zero and one. For example, if
476 ;; the branch has two dependents and one of them dpends on
477 ;; the other, then the stuff that grabs a dependent could
478 ;; easily grab the wrong one. But I don't feel like fixing
479 ;; this because it doesn't matter for any of the
480 ;; architectures we are using or plan on using.
481 (flet ((maybe-schedule-dependent (dependents)
482 (do-sset-elements (inst dependents)
483 ;; If do-sset-elements enters the body, then there is a
484 ;; dependent. Emit it.
485 (note-resolved-dependencies segment inst)
486 ;; Remove it from the emittable insts.
487 (setf (segment-emittable-insts-queue segment)
489 (segment-emittable-insts-queue segment)
491 ;; And if it was delayed, removed it from the delayed
492 ;; list. This can happen if there is a load in a
493 ;; branch delay slot.
495 (do ((delayed (segment-delayed segment)
499 (cons (car delayed) (cdr cons)))
501 (when (eq (car cons) inst)
503 (setf (cdr prev) (cdr cons))
504 (setf (car delayed) (cdr cons)))
505 (return-from scan-delayed nil)))))
508 (let ((fill (or (maybe-schedule-dependent
509 (inst-read-dependents inst))
510 (maybe-schedule-dependent
511 (inst-write-dependents inst))
512 (schedule-one-inst segment t)
514 #!+sb-show-assem (format *trace-output*
515 "filling branch delay slot with ~S~%"
517 (push fill results)))
518 (advance-one-inst segment)
519 (incf insts-from-end))
520 (note-resolved-dependencies segment inst)
522 #!+sb-show-assem (format *trace-output* "emitting ~S~%" inst)
523 (advance-one-inst segment))))
525 ;; Keep scheduling stuff until we run out.
527 (let ((inst (schedule-one-inst segment nil)))
531 (advance-one-inst segment)))
533 ;; Now call the emitters, but turn the scheduler off for the duration.
534 (setf (segment-run-scheduler segment) nil)
535 (dolist (inst results)
537 (sb!c:emit-nop segment)
538 (funcall (inst-emitter inst) segment)))
539 (setf (segment-run-scheduler segment) t))
541 ;; Clear out any residue left over.
542 (setf (segment-inst-number segment) 0)
543 (setf (segment-queued-branches segment) nil)
544 (setf (segment-branch-countdown segment) nil)
545 (setf (segment-emittable-insts-sset segment) (make-sset))
546 (fill (segment-readers segment) nil)
547 (fill (segment-writers segment) nil)
549 ;; That's all, folks.
552 ;;; a utility for maintaining the segment-delayed list. We cdr down
553 ;;; list n times (extending it if necessary) and then push thing on
554 ;;; into the car of that cons cell.
555 (defun add-to-nth-list (list thing n)
556 (do ((cell (or list (setf list (list nil)))
557 (or (cdr cell) (setf (cdr cell) (list nil))))
560 (push thing (car cell))
563 ;;; Find the next instruction to schedule and return it after updating
564 ;;; any dependency information. If we can't do anything useful right
565 ;;; now, but there is more work to be done, return :NOP to indicate
566 ;;; that a nop must be emitted. If we are all done, return NIL.
567 (defun schedule-one-inst (segment delay-slot-p)
568 (do ((prev nil remaining)
569 (remaining (segment-emittable-insts-queue segment) (cdr remaining)))
571 (let ((inst (car remaining)))
572 (unless (and delay-slot-p
573 (instruction-attributep (inst-attributes inst)
575 ;; We've got us a live one here. Go for it.
576 #!+sb-show-assem (format *trace-output* "emitting ~S~%" inst)
577 ;; Delete it from the list of insts.
579 (setf (cdr prev) (cdr remaining))
580 (setf (segment-emittable-insts-queue segment)
582 ;; Note that this inst has been emitted.
583 (note-resolved-dependencies segment inst)
585 (return-from schedule-one-inst
586 ;; Are we wanting to flush this instruction?
587 (if (inst-emitter inst)
588 ;; Nope, it's still a go. So return it.
590 ;; Yes, so pick a new one. We have to start
591 ;; over, because note-resolved-dependencies
592 ;; might have changed the emittable-insts-queue.
593 (schedule-one-inst segment delay-slot-p))))))
594 ;; Nothing to do, so make something up.
595 (cond ((segment-delayed segment)
596 ;; No emittable instructions, but we have more work to do. Emit
597 ;; a NOP to fill in a delay slot.
598 #!+sb-show-assem (format *trace-output* "emitting a NOP~%")
604 ;;; This function is called whenever an instruction has been
605 ;;; scheduled, and we want to know what possibilities that opens up.
606 ;;; So look at all the instructions that this one depends on, and
607 ;;; remove this instruction from their dependents list. If we were the
608 ;;; last dependent, then that dependency can be emitted now.
609 (defun note-resolved-dependencies (segment inst)
610 (aver (sset-empty (inst-read-dependents inst)))
611 (aver (sset-empty (inst-write-dependents inst)))
612 (do-sset-elements (dep (inst-write-dependencies inst))
613 ;; These are the instructions who have to be completed before our
614 ;; write fires. Doesn't matter how far before, just before.
615 (let ((dependents (inst-write-dependents dep)))
616 (sset-delete inst dependents)
617 (when (and (sset-empty dependents)
618 (sset-empty (inst-read-dependents dep)))
619 (insert-emittable-inst segment dep))))
620 (do-sset-elements (dep (inst-read-dependencies inst))
621 ;; These are the instructions who write values we read. If there
622 ;; is no delay, then just remove us from the dependent list.
623 ;; Otherwise, record the fact that in n cycles, we should be
625 (if (zerop (inst-delay dep))
626 (let ((dependents (inst-read-dependents dep)))
627 (sset-delete inst dependents)
628 (when (and (sset-empty dependents)
629 (sset-empty (inst-write-dependents dep)))
630 (insert-emittable-inst segment dep)))
631 (setf (segment-delayed segment)
632 (add-to-nth-list (segment-delayed segment)
637 ;;; Process the next entry in segment-delayed. This is called whenever
638 ;;; anyone emits an instruction.
639 (defun advance-one-inst (segment)
640 (let ((delayed-stuff (pop (segment-delayed segment))))
641 (dolist (stuff delayed-stuff)
643 (let* ((dependency (car stuff))
644 (dependent (cdr stuff))
645 (dependents (inst-read-dependents dependency)))
646 (sset-delete dependent dependents)
647 (when (and (sset-empty dependents)
648 (sset-empty (inst-write-dependents dependency)))
649 (insert-emittable-inst segment dependency)))
650 (insert-emittable-inst segment stuff)))))
652 ;;; Note that inst is emittable by sticking it in the
653 ;;; SEGMENT-EMITTABLE-INSTS-QUEUE list. We keep the emittable-insts
654 ;;; sorted with the largest ``depths'' first. Except that if INST is a
655 ;;; branch, don't bother. It will be handled correctly by the branch
656 ;;; emitting code in SCHEDULE-PENDING-INSTRUCTIONS.
657 (defun insert-emittable-inst (segment inst)
658 (unless (instruction-attributep (inst-attributes inst) branch)
659 #!+sb-show-assem (format *trace-output* "now emittable: ~S~%" inst)
660 (do ((my-depth (inst-depth inst))
661 (remaining (segment-emittable-insts-queue segment) (cdr remaining))
662 (prev nil remaining))
663 ((or (null remaining) (> my-depth (inst-depth (car remaining))))
665 (setf (cdr prev) (cons inst remaining))
666 (setf (segment-emittable-insts-queue segment)
667 (cons inst remaining))))))
670 ;;;; structure used during output emission
672 ;;; common supertype for all the different kinds of annotations
673 (def!struct (annotation (:constructor nil)
675 ;; Where in the raw output stream was this annotation emitted?
676 (index 0 :type index)
677 ;; What position does that correspond to?
678 (posn nil :type (or index null)))
680 (def!struct (label (:include annotation)
681 (:constructor gen-label ())
683 ;; (doesn't need any additional information beyond what is in the
684 ;; annotation structure)
686 (sb!int:def!method print-object ((label label) stream)
687 (if (or *print-escape* *print-readably*)
688 (print-unreadable-object (label stream :type t)
689 (prin1 (sb!c:label-id label) stream))
690 (format stream "L~D" (sb!c:label-id label))))
692 ;;; a constraint on how the output stream must be aligned
693 (def!struct (alignment-note (:include annotation)
694 (:conc-name alignment-)
695 (:predicate alignment-p)
696 (:constructor make-alignment (bits size fill-byte))
698 ;; the minimum number of low-order bits that must be zero
699 (bits 0 :type alignment)
700 ;; the amount of filler we are assuming this alignment op will take
701 (size 0 :type (integer 0 #.(1- (ash 1 max-alignment))))
702 ;; the byte used as filling
703 (fill-byte 0 :type (or assembly-unit (signed-byte #.assembly-unit-bits))))
705 ;;; a reference to someplace that needs to be back-patched when
706 ;;; we actually know what label positions, etc. are
707 (def!struct (back-patch (:include annotation)
708 (:constructor make-back-patch (size fun))
710 ;; the area affected by this back-patch
711 (size 0 :type index :read-only t)
712 ;; the function to use to generate the real data
713 (fun nil :type function :read-only t))
715 ;;; This is similar to a BACK-PATCH, but also an indication that the
716 ;;; amount of stuff output depends on label positions, etc.
717 ;;; BACK-PATCHes can't change their mind about how much stuff to emit,
718 ;;; but CHOOSERs can.
719 (def!struct (chooser (:include annotation)
720 (:constructor make-chooser
721 (size alignment maybe-shrink worst-case-fun))
723 ;; the worst case size for this chooser. There is this much space
724 ;; allocated in the output buffer.
725 (size 0 :type index :read-only t)
726 ;; the worst case alignment this chooser is guaranteed to preserve
727 (alignment 0 :type alignment :read-only t)
728 ;; the function to call to determine if we can use a shorter
729 ;; sequence. It returns NIL if nothing shorter can be used, or emits
730 ;; that sequence and returns T.
731 (maybe-shrink nil :type function :read-only t)
732 ;; the function to call to generate the worst case sequence. This is
733 ;; used when nothing else can be condensed.
734 (worst-case-fun nil :type function :read-only t))
736 ;;; This is used internally when we figure out a chooser or alignment
737 ;;; doesn't really need as much space as we initially gave it.
738 (def!struct (filler (:include annotation)
739 (:constructor make-filler (bytes))
741 ;; the number of bytes of filler here
742 (bytes 0 :type index))
744 ;;;; output functions
746 ;;; interface: Emit the supplied BYTE to SEGMENT, growing SEGMENT if
748 (defun emit-byte (segment byte)
749 (declare (type segment segment))
750 (declare (type possibly-signed-assembly-unit byte))
751 (vector-push-extend (logand byte assembly-unit-mask)
752 (segment-buffer segment))
753 (incf (segment-current-posn segment))
756 ;;; interface: Output AMOUNT copies of FILL-BYTE to SEGMENT.
757 (defun emit-skip (segment amount &optional (fill-byte 0))
758 (declare (type segment segment)
761 (emit-byte segment fill-byte))
764 ;;; This is used to handle the common parts of annotation emission. We
765 ;;; just assign the POSN and INDEX of NOTE and tack it on to the end
766 ;;; of SEGMENT's annotations list.
767 (defun emit-annotation (segment note)
768 (declare (type segment segment)
769 (type annotation note))
770 (when (annotation-posn note)
771 (error "attempt to emit ~S a second time" note))
772 (setf (annotation-posn note) (segment-current-posn segment))
773 (setf (annotation-index note) (segment-current-index segment))
774 (let ((last (segment-last-annotation segment))
776 (setf (segment-last-annotation segment)
778 (setf (cdr last) new)
779 (setf (segment-annotations segment) new))))
782 ;;; Note that the instruction stream has to be back-patched when label
783 ;;; positions are finally known. SIZE bytes are reserved in SEGMENT,
784 ;;; and function will be called with two arguments: the segment and
785 ;;; the position. The function should look at the position and the
786 ;;; position of any labels it wants to and emit the correct sequence.
787 ;;; (And it better be the same size as SIZE). SIZE can be zero, which
788 ;;; is useful if you just want to find out where things ended up.
789 (defun emit-back-patch (segment size function)
790 (emit-annotation segment (make-back-patch size function))
791 (emit-skip segment size))
793 ;;; Note that the instruction stream here depends on the actual
794 ;;; positions of various labels, so can't be output until label
795 ;;; positions are known. Space is made in SEGMENT for at least SIZE
796 ;;; bytes. When all output has been generated, the MAYBE-SHRINK
797 ;;; functions for all choosers are called with three arguments: the
798 ;;; segment, the position, and a magic value. The MAYBE- SHRINK
799 ;;; decides if it can use a shorter sequence, and if so, emits that
800 ;;; sequence to the segment and returns T. If it can't do better than
801 ;;; the worst case, it should return NIL (without emitting anything).
802 ;;; When calling LABEL-POSITION, it should pass it the position and
803 ;;; the magic-value it was passed so that LABEL-POSITION can return
804 ;;; the correct result. If the chooser never decides to use a shorter
805 ;;; sequence, the WORST-CASE-FUN will be called, just like a
806 ;;; BACK-PATCH. (See EMIT-BACK-PATCH.)
807 (defun emit-chooser (segment size alignment maybe-shrink worst-case-fun)
808 (declare (type segment segment) (type index size) (type alignment alignment)
809 (type function maybe-shrink worst-case-fun))
810 (let ((chooser (make-chooser size alignment maybe-shrink worst-case-fun)))
811 (emit-annotation segment chooser)
812 (emit-skip segment size)
813 (adjust-alignment-after-chooser segment chooser)))
815 ;;; This is called in EMIT-CHOOSER and COMPRESS-SEGMENT in order to
816 ;;; recompute the current alignment information in light of this
817 ;;; chooser. If the alignment guaranteed byte the chooser is less then
818 ;;; the segments current alignment, we have to adjust the segments
819 ;;; notion of the current alignment.
821 ;;; The hard part is recomputing the sync posn, because it's not just
822 ;;; the chooser's posn. Consider a chooser that emits either one or
823 ;;; three words. It preserves 8-byte (3 bit) alignments, because the
824 ;;; difference between the two choices is 8 bytes.
825 (defun adjust-alignment-after-chooser (segment chooser)
826 (declare (type segment segment) (type chooser chooser))
827 (let ((alignment (chooser-alignment chooser))
828 (seg-alignment (segment-alignment segment)))
829 (when (< alignment seg-alignment)
830 ;; The chooser might change the alignment of the output. So we
831 ;; have to figure out what the worst case alignment could be.
832 (setf (segment-alignment segment) alignment)
833 (let* ((posn (chooser-posn chooser))
834 (sync-posn (segment-sync-posn segment))
835 (offset (- posn sync-posn))
836 (delta (logand offset (1- (ash 1 alignment)))))
837 (setf (segment-sync-posn segment) (- posn delta)))))
840 ;;; This is used internally whenever a chooser or alignment decides it
841 ;;; doesn't need as much space as it originally thought.
842 (defun emit-filler (segment n-bytes)
843 (declare (type index n-bytes))
844 (let ((last (segment-last-annotation segment)))
845 (cond ((and last (filler-p (car last)))
846 (incf (filler-bytes (car last)) n-bytes))
848 (emit-annotation segment (make-filler n-bytes)))))
849 (incf (segment-current-index segment) n-bytes)
852 ;;; EMIT-LABEL (the interface) basically just expands into this,
853 ;;; supplying the SEGMENT and VOP.
854 (defun %emit-label (segment vop label)
855 (when (segment-run-scheduler segment)
856 (schedule-pending-instructions segment))
857 (let ((postits (segment-postits segment)))
858 (setf (segment-postits segment) nil)
859 (dolist (postit postits)
860 (emit-back-patch segment 0 postit)))
861 (let ((hook (segment-inst-hook segment)))
863 (funcall hook segment vop :label label)))
864 (emit-annotation segment label))
866 ;;; Called by the ALIGN macro to emit an alignment note. We check to
867 ;;; see if we can guarantee the alignment restriction by just
868 ;;; outputting a fixed number of bytes. If so, we do so. Otherwise, we
869 ;;; create and emit an alignment note.
870 (defun emit-alignment (segment vop bits &optional (fill-byte 0))
871 (when (segment-run-scheduler segment)
872 (schedule-pending-instructions segment))
873 (let ((hook (segment-inst-hook segment)))
875 (funcall hook segment vop :align bits)))
876 (let ((alignment (segment-alignment segment))
877 (offset (- (segment-current-posn segment)
878 (segment-sync-posn segment))))
879 (cond ((> bits alignment)
880 ;; We need more bits of alignment. First emit enough noise
881 ;; to get back in sync with alignment, and then emit an
882 ;; alignment note to cover the rest.
883 (let ((slop (logand offset (1- (ash 1 alignment)))))
885 (emit-skip segment (- (ash 1 alignment) slop) fill-byte)))
886 (let ((size (logand (1- (ash 1 bits))
887 (lognot (1- (ash 1 alignment))))))
889 (emit-annotation segment (make-alignment bits size fill-byte))
890 (emit-skip segment size fill-byte))
891 (setf (segment-alignment segment) bits)
892 (setf (segment-sync-posn segment) (segment-current-posn segment)))
894 ;; The last alignment was more restrictive then this one.
895 ;; So we can just figure out how much noise to emit
896 ;; assuming the last alignment was met.
897 (let* ((mask (1- (ash 1 bits)))
898 (new-offset (logand (+ offset mask) (lognot mask))))
899 (emit-skip segment (- new-offset offset) fill-byte))
900 ;; But we emit an alignment with size=0 so we can verify
901 ;; that everything works.
902 (emit-annotation segment (make-alignment bits 0 fill-byte)))))
905 ;;; This is used to find how ``aligned'' different offsets are.
906 ;;; Returns the number of low-order 0 bits, up to MAX-ALIGNMENT.
907 (defun find-alignment (offset)
908 (dotimes (i max-alignment max-alignment)
909 (when (logbitp i offset)
912 ;;; Emit a postit. The function will be called as a back-patch with
913 ;;; the position the following instruction is finally emitted. Postits
914 ;;; do not interfere at all with scheduling.
915 (defun %emit-postit (segment function)
916 (push function (segment-postits segment))
919 ;;;; output compression/position assignment stuff
921 ;;; Grovel though all the annotations looking for choosers. When we
922 ;;; find a chooser, invoke the maybe-shrink function. If it returns T,
923 ;;; it output some other byte sequence.
924 (defun compress-output (segment)
925 (dotimes (i 5) ; it better not take more than one or two passes.
927 (setf (segment-alignment segment) max-alignment)
928 (setf (segment-sync-posn segment) 0)
930 (remaining (segment-annotations segment) next)
931 (next (cdr remaining) (cdr remaining)))
933 (let* ((note (car remaining))
934 (posn (annotation-posn note)))
935 (unless (zerop delta)
937 (setf (annotation-posn note) posn))
940 (with-modified-segment-index-and-posn (segment (chooser-index note)
942 (setf (segment-last-annotation segment) prev)
944 ((funcall (chooser-maybe-shrink note) segment posn delta)
945 ;; It emitted some replacement.
946 (let ((new-size (- (segment-current-index segment)
947 (chooser-index note)))
948 (old-size (chooser-size note)))
949 (when (> new-size old-size)
950 (error "~S emitted ~W bytes, but claimed its max was ~W."
951 note new-size old-size))
952 (let ((additional-delta (- old-size new-size)))
953 (when (< (find-alignment additional-delta)
954 (chooser-alignment note))
955 (error "~S shrunk by ~W bytes, but claimed that it ~
956 preserves ~W bits of alignment."
957 note additional-delta (chooser-alignment note)))
958 (incf delta additional-delta)
959 (emit-filler segment additional-delta))
960 (setf prev (segment-last-annotation segment))
962 (setf (cdr prev) (cdr remaining))
963 (setf (segment-annotations segment)
966 ;; The chooser passed on shrinking. Make sure it didn't
968 (unless (= (segment-current-index segment)
969 (chooser-index note))
970 (error "Chooser ~S passed, but not before emitting ~W bytes."
972 (- (segment-current-index segment)
973 (chooser-index note))))
974 ;; Act like we just emitted this chooser.
975 (let ((size (chooser-size note)))
976 (incf (segment-current-index segment) size)
977 (incf (segment-current-posn segment) size))
978 ;; Adjust the alignment accordingly.
979 (adjust-alignment-after-chooser segment note)
980 ;; And keep this chooser for next time around.
981 (setf prev remaining)))))
983 (unless (zerop (alignment-size note))
984 ;; Re-emit the alignment, letting it collapse if we know
985 ;; anything more about the alignment guarantees of the
987 (let ((index (alignment-index note)))
988 (with-modified-segment-index-and-posn (segment index posn)
989 (setf (segment-last-annotation segment) prev)
990 (emit-alignment segment nil (alignment-bits note)
991 (alignment-fill-byte note))
992 (let* ((new-index (segment-current-index segment))
993 (size (- new-index index))
994 (old-size (alignment-size note))
995 (additional-delta (- old-size size)))
996 (when (minusp additional-delta)
997 (error "Alignment ~S needs more space now? It was ~W, ~
1000 (when (plusp additional-delta)
1001 (emit-filler segment additional-delta)
1002 (incf delta additional-delta)))
1003 (setf prev (segment-last-annotation segment))
1005 (setf (cdr prev) (cdr remaining))
1006 (setf (segment-annotations segment)
1007 (cdr remaining)))))))
1009 (setf prev remaining)))))
1012 (decf (segment-final-posn segment) delta)))
1015 ;;; We have run all the choosers we can, so now we have to figure out
1016 ;;; exactly how much space each alignment note needs.
1017 (defun finalize-positions (segment)
1020 (remaining (segment-annotations segment) next)
1021 (next (cdr remaining) (cdr remaining)))
1023 (let* ((note (car remaining))
1024 (posn (- (annotation-posn note) delta)))
1027 (let* ((bits (alignment-bits note))
1028 (mask (1- (ash 1 bits)))
1029 (new-posn (logand (+ posn mask) (lognot mask)))
1030 (size (- new-posn posn))
1031 (old-size (alignment-size note))
1032 (additional-delta (- old-size size)))
1033 (aver (<= 0 size old-size))
1034 (unless (zerop additional-delta)
1035 (setf (segment-last-annotation segment) prev)
1036 (incf delta additional-delta)
1037 (with-modified-segment-index-and-posn (segment
1038 (alignment-index note)
1040 (emit-filler segment additional-delta)
1041 (setf prev (segment-last-annotation segment))
1043 (setf (cdr prev) next)
1044 (setf (segment-annotations segment) next))))))
1046 (setf (annotation-posn note) posn)
1047 (setf prev remaining)
1048 (setf next (cdr remaining))))))
1049 (unless (zerop delta)
1050 (decf (segment-final-posn segment) delta)))
1053 ;;; Grovel over segment, filling in any backpatches. If any choosers
1054 ;;; are left over, we need to emit their worst case varient.
1055 (defun process-back-patches (segment)
1057 (remaining (segment-annotations segment) next)
1058 (next (cdr remaining) (cdr remaining)))
1060 (let ((note (car remaining)))
1061 (flet ((fill-in (function old-size)
1062 (let ((index (annotation-index note))
1063 (posn (annotation-posn note)))
1064 (with-modified-segment-index-and-posn (segment index posn)
1065 (setf (segment-last-annotation segment) prev)
1066 (funcall function segment posn)
1067 (let ((new-size (- (segment-current-index segment) index)))
1068 (unless (= new-size old-size)
1069 (error "~S emitted ~W bytes, but claimed it was ~W."
1070 note new-size old-size)))
1071 (let ((tail (segment-last-annotation segment)))
1073 (setf (cdr tail) next)
1074 (setf (segment-annotations segment) next)))
1075 (setf next (cdr prev))))))
1076 (cond ((back-patch-p note)
1077 (fill-in (back-patch-fun note)
1078 (back-patch-size note)))
1080 (fill-in (chooser-worst-case-fun note)
1081 (chooser-size note)))
1083 (setf prev remaining)))))))
1085 ;;;; interface to the rest of the compiler
1087 ;;; This holds the current segment while assembling. Use ASSEMBLE to
1090 ;;; The double parens in the name are intended to suggest that this
1091 ;;; isn't just any old special variable, it's an extra-special
1092 ;;; variable, because sometimes MACROLET is used to bind it. So be
1093 ;;; careful out there..
1095 ;;; (This used to be called **CURRENT-SEGMENT** in SBCL until 0.7.3,
1096 ;;; and just *CURRENT-SEGMENT* in CMU CL. In both cases, the rebinding
1097 ;;; now done with MACROLET was done with SYMBOL-MACROLET instead. The
1098 ;;; rename-with-double-asterisks was because the SYMBOL-MACROLET made
1099 ;;; it an extra-special variable. The change over to
1100 ;;; %%CURRENT-SEGMENT%% was because ANSI forbids the use of
1101 ;;; SYMBOL-MACROLET on special variable names, and CLISP correctly
1102 ;;; complains about this when being used as a bootstrap host.)
1103 (defmacro %%current-segment%% () '**current-segment**)
1104 (defvar **current-segment**)
1106 ;;; Just like %%CURRENT-SEGMENT%%, except this holds the current vop.
1107 ;;; This is used only to keep track of which vops emit which insts.
1109 ;;; The double asterisks in the name are intended to suggest that this
1110 ;;; isn't just any old special variable, it's an extra-special
1111 ;;; variable, because sometimes MACROLET is used to bind it. So be
1112 ;;; careful out there..
1113 (defmacro %%current-vop%% () '**current-vop**)
1114 (defvar **current-vop** nil)
1116 ;;; We also MACROLET %%CURRENT-SEGMENT%% to a local holding the
1117 ;;; segment so uses of %%CURRENT-SEGMENT%% inside the body don't have
1118 ;;; to keep dereferencing the symbol. Given that ASSEMBLE is the only
1119 ;;; interface to **CURRENT-SEGMENT**, we don't have to worry about the
1120 ;;; special value becomming out of sync with the lexical value. Unless
1121 ;;; some bozo closes over it, but nobody does anything like that...
1123 ;;; FIXME: The way this macro uses MACROEXPAND internally breaks my
1124 ;;; old assumptions about macros which are needed both in the host and
1125 ;;; the target. (This is more or less the same way that PUSH-IN,
1126 ;;; DELETEF-IN, and !DEF-BOOLEAN-ATTRIBUTE break my old assumptions,
1127 ;;; except that they used GET-SETF-EXPANSION instead of MACROEXPAND to
1128 ;;; do the dirty deed.) The quick and dirty "solution" here is the
1129 ;;; same as there: use cut and paste to duplicate the defmacro in a
1130 ;;; (SB!INT:DEF!MACRO FOO (..) .. CL:MACROEXPAND ..) #+SB-XC-HOST
1131 ;;; (DEFMACRO FOO (..) .. SB!XC:MACROEXPAND ..) idiom. This is
1132 ;;; disgusting and unmaintainable, and there are obviously better
1133 ;;; solutions and maybe even good solutions, but I'm disinclined to
1134 ;;; hunt for good solutions until the system works and I can test them
1136 (sb!int:def!macro assemble ((&optional segment vop &key labels) &body body
1139 "Execute BODY (as a progn) with SEGMENT as the current segment."
1140 (flet ((label-name-p (thing)
1141 (and thing (symbolp thing))))
1142 (let* ((seg-var (gensym "SEGMENT-"))
1143 (vop-var (gensym "VOP-"))
1144 (visible-labels (remove-if-not #'label-name-p body))
1146 (multiple-value-bind (expansion expanded)
1147 (macroexpand '..inherited-labels.. env)
1148 (if expanded expansion nil)))
1149 (new-labels (append labels
1150 (set-difference visible-labels
1152 (nested-labels (set-difference (append inherited-labels new-labels)
1154 (when (intersection labels inherited-labels)
1155 (error "duplicate nested labels: ~S"
1156 (intersection labels inherited-labels)))
1157 `(let* ((,seg-var ,(or segment '(%%current-segment%%)))
1158 (,vop-var ,(or vop '(%%current-vop%%)))
1160 `((**current-segment** ,seg-var)))
1162 `((**current-vop** ,vop-var)))
1163 ,@(mapcar (lambda (name)
1164 `(,name (gen-label)))
1166 (declare (ignorable ,vop-var ,seg-var)
1167 ;; Must be done so that contribs and user code doing
1168 ;; low-level stuff don't need to worry about this.
1169 (disable-package-locks %%current-segment%% %%current-vop%%))
1170 (macrolet ((%%current-segment%% () '**current-segment**)
1171 (%%current-vop%% () '**current-vop**))
1172 ;; KLUDGE: Some host lisps (CMUCL 18e Sparc at least)
1173 ;; can't deal with this declaration, so disable it on host.
1174 ;; Ditto for later ENABLE-PACKAGE-LOCKS %%C-S%% declaration.
1176 (declare (enable-package-locks %%current-segment%% %%current-vop%%))
1177 (symbol-macrolet (,@(when (or inherited-labels nested-labels)
1178 `((..inherited-labels.. ,nested-labels))))
1179 ,@(mapcar (lambda (form)
1180 (if (label-name-p form)
1185 (sb!xc:defmacro assemble ((&optional segment vop &key labels)
1189 "Execute BODY (as a progn) with SEGMENT as the current segment."
1190 (flet ((label-name-p (thing)
1191 (and thing (symbolp thing))))
1192 (let* ((seg-var (gensym "SEGMENT-"))
1193 (vop-var (gensym "VOP-"))
1194 (visible-labels (remove-if-not #'label-name-p body))
1196 (multiple-value-bind
1197 (expansion expanded)
1198 (sb!xc:macroexpand '..inherited-labels.. env)
1199 (if expanded expansion nil)))
1200 (new-labels (append labels
1201 (set-difference visible-labels
1203 (nested-labels (set-difference (append inherited-labels new-labels)
1205 (when (intersection labels inherited-labels)
1206 (error "duplicate nested labels: ~S"
1207 (intersection labels inherited-labels)))
1208 `(let* ((,seg-var ,(or segment '(%%current-segment%%)))
1209 (,vop-var ,(or vop '(%%current-vop%%)))
1211 `((**current-segment** ,seg-var)))
1213 `((**current-vop** ,vop-var)))
1214 ,@(mapcar (lambda (name)
1215 `(,name (gen-label)))
1217 (declare (ignorable ,vop-var ,seg-var))
1218 (macrolet ((%%current-segment%% () '**current-segment**)
1219 (%%current-vop%% () '**current-vop**))
1220 (symbol-macrolet (,@(when (or inherited-labels nested-labels)
1221 `((..inherited-labels.. ,nested-labels))))
1222 ,@(mapcar (lambda (form)
1223 (if (label-name-p form)
1228 (defmacro inst (&whole whole instruction &rest args &environment env)
1230 "Emit the specified instruction to the current segment."
1231 (let ((inst (gethash (symbol-name instruction) *assem-instructions*)))
1233 (error "unknown instruction: ~S" instruction))
1235 (funcall inst (cdr whole) env))
1237 `(,inst (%%current-segment%%) (%%current-vop%%) ,@args)))))
1239 ;;; Note: The need to capture MACROLET bindings of %%CURRENT-SEGMENT%%
1240 ;;; and %%CURRENT-VOP%% prevents this from being an ordinary function.
1241 (defmacro emit-label (label)
1243 "Emit LABEL at this location in the current segment."
1244 `(%emit-label (%%current-segment%%) (%%current-vop%%) ,label))
1246 ;;; Note: The need to capture MACROLET bindings of
1247 ;;; %%CURRENT-SEGMENT%% prevents this from being an ordinary function.
1248 (defmacro emit-postit (function)
1249 `(%emit-postit (%%current-segment%%) ,function))
1251 ;;; Note: The need to capture SYMBOL-MACROLET bindings of
1252 ;;; **CURRENT-SEGMENT* and (%%CURRENT-VOP%%) prevents this from being an
1253 ;;; ordinary function.
1254 (defmacro align (bits &optional (fill-byte 0))
1256 "Emit an alignment restriction to the current segment."
1257 `(emit-alignment (%%current-segment%%) (%%current-vop%%) ,bits ,fill-byte))
1258 ;;; FIXME: By analogy with EMIT-LABEL and EMIT-POSTIT, this should be
1259 ;;; called EMIT-ALIGNMENT, and the function that it calls should be
1260 ;;; called %EMIT-ALIGNMENT.
1262 (defun label-position (label &optional if-after delta)
1264 "Return the current position for LABEL. Chooser maybe-shrink functions
1265 should supply IF-AFTER and DELTA in order to ensure correct results."
1266 (let ((posn (label-posn label)))
1267 (if (and if-after (> posn if-after))
1271 (defun append-segment (segment other-segment)
1273 "Append OTHER-SEGMENT to the end of SEGMENT. Don't use OTHER-SEGMENT
1274 for anything after this."
1275 (when (segment-run-scheduler segment)
1276 (schedule-pending-instructions segment))
1277 (let ((postits (segment-postits segment)))
1278 (setf (segment-postits segment) (segment-postits other-segment))
1279 (dolist (postit postits)
1280 (emit-back-patch segment 0 postit)))
1281 (emit-alignment segment nil max-alignment #!+(or x86-64 x86) #x90)
1282 (let ((segment-current-index-0 (segment-current-index segment))
1283 (segment-current-posn-0 (segment-current-posn segment)))
1284 (incf (segment-current-index segment)
1285 (segment-current-index other-segment))
1286 (replace (segment-buffer segment)
1287 (segment-buffer other-segment)
1288 :start1 segment-current-index-0)
1289 (setf (segment-buffer other-segment) nil) ; to prevent accidental reuse
1290 (incf (segment-current-posn segment)
1291 (segment-current-posn other-segment))
1292 (let ((other-annotations (segment-annotations other-segment)))
1293 (when other-annotations
1294 (dolist (note other-annotations)
1295 (incf (annotation-index note) segment-current-index-0)
1296 (incf (annotation-posn note) segment-current-posn-0))
1297 ;; This SEGMENT-LAST-ANNOTATION code is confusing. Is it really
1298 ;; worth enough in efficiency to justify it? -- WHN 19990322
1299 (let ((last (segment-last-annotation segment)))
1301 (setf (cdr last) other-annotations)
1302 (setf (segment-annotations segment) other-annotations)))
1303 (setf (segment-last-annotation segment)
1304 (segment-last-annotation other-segment)))))
1307 (defun finalize-segment (segment)
1309 "Do any final processing of SEGMENT and return the total number of bytes
1310 covered by this segment."
1311 (when (segment-run-scheduler segment)
1312 (schedule-pending-instructions segment))
1313 (setf (segment-run-scheduler segment) nil)
1314 (let ((postits (segment-postits segment)))
1315 (setf (segment-postits segment) nil)
1316 (dolist (postit postits)
1317 (emit-back-patch segment 0 postit)))
1318 (setf (segment-final-index segment) (segment-current-index segment))
1319 (setf (segment-final-posn segment) (segment-current-posn segment))
1320 (setf (segment-inst-hook segment) nil)
1321 (compress-output segment)
1322 (finalize-positions segment)
1323 (process-back-patches segment)
1324 (segment-final-posn segment))
1326 ;;; Call FUNCTION on all the stuff accumulated in SEGMENT. FUNCTION
1327 ;;; should accept a single vector argument. It will be called zero or
1328 ;;; more times on vectors of the appropriate byte type. The
1329 ;;; concatenation of the vector arguments from all the calls is the
1330 ;;; contents of SEGMENT.
1332 ;;; KLUDGE: This implementation is sort of slow and gross, calling
1333 ;;; FUNCTION repeatedly and consing a fresh vector for its argument
1334 ;;; each time. It might be possible to make a more efficient version
1335 ;;; by making FINALIZE-SEGMENT do all the compacting currently done by
1336 ;;; this function: then this function could become trivial and fast,
1337 ;;; calling FUNCTION once on the entire compacted segment buffer. --
1339 (defun on-segment-contents-vectorly (segment function)
1340 (declare (type function function))
1341 (let ((buffer (segment-buffer segment))
1343 (flet ((frob (i0 i1)
1345 (funcall function (subseq buffer i0 i1)))))
1346 (dolist (note (segment-annotations segment))
1347 (when (filler-p note)
1348 (let ((i1 (filler-index note)))
1350 (setf i0 (+ i1 (filler-bytes note))))))
1351 (frob i0 (segment-final-index segment))))
1354 ;;; Write the code accumulated in SEGMENT to STREAM, and return the
1355 ;;; number of bytes written.
1356 (defun write-segment-contents (segment stream)
1358 (declare (type index result))
1359 (on-segment-contents-vectorly segment
1361 (declare (type (vector assembly-unit) v))
1362 (incf result (length v))
1363 (write-sequence v stream)))
1366 ;;;; interface to the instruction set definition
1368 ;;; Define a function named NAME that merges its arguments into a
1369 ;;; single integer and then emits the bytes of that integer in the
1370 ;;; correct order based on the endianness of the target-backend.
1371 (defmacro define-bitfield-emitter (name total-bits &rest byte-specs)
1372 (sb!int:collect ((arg-names) (arg-types))
1373 (let* ((total-bits (eval total-bits))
1374 (overall-mask (ash -1 total-bits))
1375 (num-bytes (multiple-value-bind (quo rem)
1376 (truncate total-bits assembly-unit-bits)
1378 (error "~W isn't an even multiple of ~W."
1379 total-bits assembly-unit-bits))
1381 (bytes (make-array num-bytes :initial-element nil))
1382 (segment-arg (gensym "SEGMENT-")))
1383 (dolist (byte-spec-expr byte-specs)
1384 (let* ((byte-spec (eval byte-spec-expr))
1385 (byte-size (byte-size byte-spec))
1386 (byte-posn (byte-position byte-spec))
1387 (arg (gensym (format nil "~:@(ARG-FOR-~S-~)" byte-spec-expr))))
1388 (when (ldb-test (byte byte-size byte-posn) overall-mask)
1389 (error "The byte spec ~S either overlaps another byte spec, or ~
1390 extends past the end."
1392 (setf (ldb byte-spec overall-mask) -1)
1394 (arg-types `(type (integer ,(ash -1 (1- byte-size))
1395 ,(1- (ash 1 byte-size)))
1397 (multiple-value-bind (start-byte offset)
1398 (floor byte-posn assembly-unit-bits)
1399 (let ((end-byte (floor (1- (+ byte-posn byte-size))
1400 assembly-unit-bits)))
1401 (flet ((maybe-ash (expr offset)
1404 `(ash ,expr ,offset))))
1405 (declare (inline maybe-ash))
1406 (cond ((zerop byte-size))
1407 ((= start-byte end-byte)
1408 (push (maybe-ash `(ldb (byte ,byte-size 0) ,arg)
1410 (svref bytes start-byte)))
1413 `(ldb (byte ,(- assembly-unit-bits offset) 0)
1416 (svref bytes start-byte))
1417 (do ((index (1+ start-byte) (1+ index)))
1418 ((>= index end-byte))
1420 `(ldb (byte ,assembly-unit-bits
1421 ,(- (* assembly-unit-bits
1422 (- index start-byte))
1425 (svref bytes index)))
1426 (let ((len (rem (+ byte-size offset)
1427 assembly-unit-bits)))
1429 `(ldb (byte ,(if (zerop len)
1432 ,(- (* assembly-unit-bits
1433 (- end-byte start-byte))
1436 (svref bytes end-byte))))))))))
1437 (unless (= overall-mask -1)
1438 (error "There are holes."))
1440 (dotimes (i num-bytes)
1441 (let ((pieces (svref bytes i)))
1443 (push `(emit-byte ,segment-arg
1448 `(defun ,name (,segment-arg ,@(arg-names))
1449 (declare (type segment ,segment-arg) ,@(arg-types))
1450 ,@(ecase sb!c:*backend-byte-order*
1451 (:little-endian (nreverse forms))
1452 (:big-endian forms))
1455 (defun grovel-lambda-list (lambda-list vop-var)
1456 (let ((segment-name (car lambda-list))
1457 (vop-var (or vop-var (gensym "VOP-"))))
1458 (sb!int:collect ((new-lambda-list))
1459 (new-lambda-list segment-name)
1460 (new-lambda-list vop-var)
1462 ((grovel (state lambda-list)
1464 (let ((param (car lambda-list)))
1466 ((member param sb!xc:lambda-list-keywords)
1467 (new-lambda-list param)
1468 (grovel param (cdr lambda-list)))
1472 (new-lambda-list param)
1473 `(cons ,param ,(grovel state (cdr lambda-list))))
1475 (multiple-value-bind (name default supplied-p)
1477 (values (first param)
1480 (gensym "SUPPLIED-P-")))
1481 (values param nil (gensym "SUPPLIED-P-")))
1482 (new-lambda-list (list name default supplied-p))
1484 (cons ,(if (consp name)
1487 ,(grovel state (cdr lambda-list))))))
1489 (multiple-value-bind (name default supplied-p)
1491 (values (first param)
1494 (gensym "SUPPLIED-P-")))
1495 (values param nil (gensym "SUPPLIED-P-")))
1496 (new-lambda-list (list name default supplied-p))
1497 (multiple-value-bind (key var)
1499 (values (first name) (second name))
1500 (values (keywordicate name) name))
1501 `(append (and ,supplied-p (list ',key ,var))
1502 ,(grovel state (cdr lambda-list))))))
1504 (new-lambda-list param)
1505 (grovel state (cdr lambda-list))
1507 (let ((reconstructor (grovel nil (cdr lambda-list))))
1508 (values (new-lambda-list)
1513 (defun extract-nths (index glue list-of-lists-of-lists)
1514 (mapcar (lambda (list-of-lists)
1516 (mapcar (lambda (list)
1519 list-of-lists-of-lists))
1521 (defmacro define-instruction (name lambda-list &rest options)
1522 (let* ((sym-name (symbol-name name))
1523 (defun-name (sb!int:symbolicate sym-name "-INST-EMITTER"))
1525 (postits (gensym "POSTITS-"))
1534 (sb!int:/noshow "entering DEFINE-INSTRUCTION" name lambda-list options)
1535 (dolist (option-spec options)
1536 (sb!int:/noshow option-spec)
1537 (multiple-value-bind (option args)
1538 (if (consp option-spec)
1539 (values (car option-spec) (cdr option-spec))
1540 (values option-spec nil))
1541 (sb!int:/noshow option args)
1545 (error "You can only specify :EMITTER once per instruction."))
1546 (setf emitter args))
1548 (setf decls (append decls args)))
1550 (setf attributes (append attributes args)))
1552 (setf cost (first args)))
1554 (setf dependencies (append dependencies args)))
1557 (error "You can only specify :DELAY once per instruction."))
1563 (error "You can only specify :VOP-VAR once per instruction.")
1564 (setf vop-var (car args))))
1566 (sb!int:/noshow "uniquifying :PRINTER with" args)
1567 (push (eval `(list (multiple-value-list
1568 ,(sb!disassem:gen-printer-def-forms-def-form
1570 (format nil "~@:(~A[~A]~)" name args)
1571 (cdr option-spec)))))
1574 ;; same as :PRINTER, but is EVALed first, and is a list of
1579 `(list ,@(mapcar (lambda (printer)
1580 `(multiple-value-list
1581 ,(sb!disassem:gen-printer-def-forms-def-form
1583 (format nil "~@:(~A[~A]~)" ',name printer)
1586 ,(cadr option-spec)))))
1589 (error "unknown option: ~S" option)))))
1590 (sb!int:/noshow "done processing options")
1591 (setf pdefs (nreverse pdefs))
1592 (multiple-value-bind
1593 (new-lambda-list segment-name vop-name arg-reconstructor)
1594 (grovel-lambda-list lambda-list vop-var)
1595 (sb!int:/noshow new-lambda-list segment-name vop-name arg-reconstructor)
1596 (push `(let ((hook (segment-inst-hook ,segment-name)))
1598 (funcall hook ,segment-name ,vop-name ,sym-name
1599 ,arg-reconstructor)))
1601 (push `(dolist (postit ,postits)
1602 (emit-back-patch ,segment-name 0 postit))
1604 (unless cost (setf cost 1))
1606 (push `(when (segment-collect-dynamic-statistics ,segment-name)
1607 (let* ((info (sb!c:ir2-component-dyncount-info
1608 (sb!c:component-info
1609 sb!c:*component-being-compiled*)))
1610 (costs (sb!c:dyncount-info-costs info))
1611 (block-number (sb!c:block-number
1612 (sb!c:ir2-block-block
1613 (sb!c:vop-block ,vop-name)))))
1614 (incf (aref costs block-number) ,cost)))
1616 (when *assem-scheduler-p*
1619 `((when (segment-run-scheduler ,segment-name)
1620 (schedule-pending-instructions ,segment-name))
1623 (gensym (concatenate 'string "EMIT-" sym-name "-INST-")))
1624 (inst-name (gensym "INST-")))
1625 (setf emitter `((flet ((,flet-name (,segment-name)
1627 (if (segment-run-scheduler ,segment-name)
1630 (incf (segment-inst-number
1633 (instruction-attributes
1636 ,@(when dependencies
1637 `((note-dependencies
1638 (,segment-name ,inst-name)
1640 (queue-inst ,segment-name ,inst-name))
1641 (,flet-name ,segment-name))))))))
1643 (defun ,defun-name ,new-lambda-list
1645 `((declare ,@decls)))
1646 (let ((,postits (segment-postits ,segment-name)))
1647 ;; Must be done so that contribs and user code doing
1648 ;; low-level stuff don't need to worry about this.
1649 (declare (disable-package-locks %%current-segment%%))
1650 (setf (segment-postits ,segment-name) nil)
1651 (macrolet ((%%current-segment%% ()
1652 (error "You can't use INST without an ~
1653 ASSEMBLE inside emitters.")))
1654 ;; KLUDGE: Some host lisps (CMUCL 18e Sparc at least)
1655 ;; can't deal with this declaration, so disable it on host
1656 ;; Ditto for earlier ENABLE-PACKAGE-LOCKS %%C-S%% %%C-V%%
1659 (declare (enable-package-locks %%current-segment%%))
1662 (eval-when (:compile-toplevel :load-toplevel :execute)
1663 (%define-instruction ,sym-name ',defun-name))
1664 ,@(extract-nths 1 'progn pdefs)
1666 `((sb!disassem:install-inst-flavors
1668 (append ,@(extract-nths 0 'list pdefs)))))))))
1670 (defmacro define-instruction-macro (name lambda-list &body body)
1671 (with-unique-names (whole env)
1672 (multiple-value-bind (body local-defs)
1673 (sb!kernel:parse-defmacro lambda-list
1679 `(eval-when (:compile-toplevel :load-toplevel :execute)
1680 (%define-instruction ,(symbol-name name)
1681 (lambda (,whole ,env)
1686 (defun %define-instruction (name defun)
1687 (setf (gethash name *assem-instructions*) defun)