| 1 | ;-*- MODE: LISP; PACKAGE: COMPILER; BASE: 8 -*- |
|---|
| 2 | ; ** (c) Copyright 1980 Massachusetts Institute of Technology ** |
|---|
| 3 | |
|---|
| 4 | (DEFVAR *MA-PARAM-LIST*) ;alist of parameter assignments |
|---|
| 5 | |
|---|
| 6 | ; cubbyholes |
|---|
| 7 | ; a cubbyhole is the basic home of a variable, although due to optimizations |
|---|
| 8 | ;it does not necessarily always "contain" the variable. Cubbyholes are identified |
|---|
| 9 | ;by specifiers carried thru from the macrocode, ie (ARG n) or (LOCBLOCK n). |
|---|
| 10 | ;(Note, however, that (LOCBLOCK n) just serves as a name and does not imply |
|---|
| 11 | ;anything about actual position on the stack). |
|---|
| 12 | ;(SPECIAL FOO) is also possible. However, this is only of significance until a |
|---|
| 13 | ;DO-SPECBIND is seen, since after that value is in the special cell. |
|---|
| 14 | ;Cubbyholes for the required args are created at MA-MAKE-INITIAL-STATE. |
|---|
| 15 | ;The micro-compiler "signals" creation of other cubbyholes by inserting a START-CUBBYHOLE, |
|---|
| 16 | ;followed by code, then by (CREATE-CUBBYHOLE <name>) which says the thing on top of |
|---|
| 17 | ;the stack is to be considereda cubbyhole and gives the specifier. This delimits |
|---|
| 18 | ;the code to be flushed in case it is decided to colapse the cubbyhole. |
|---|
| 19 | |
|---|
| 20 | (DEFVAR *MA-CUBBYHOLES*) |
|---|
| 21 | (DEFVAR *MA-CUBBYHOLE-ALIST*) ;alist <name> . <cubbyhole-structure> |
|---|
| 22 | (DEFVAR *MA-FUNCTION-EXITS*) ;all insts which can leave function. |
|---|
| 23 | |
|---|
| 24 | (DEFSTRUCT (MA-CUBBYHOLE :NAMED :ARRAY) |
|---|
| 25 | MA-CUBBYHOLE-NAME |
|---|
| 26 | MA-CUBBYHOLE-ALL-NAMES |
|---|
| 27 | MA-CUBBYHOLE-REFS) ;a list (<FETCH or STORE> <inst>) |
|---|
| 28 | |
|---|
| 29 | ;cubbyhole optimizations: |
|---|
| 30 | ; two stores with no intervening reference |
|---|
| 31 | |
|---|
| 32 | ;Colapsing cubbyholes: |
|---|
| 33 | ; Sometimes two cubbyholes have non-overlapping lifetimes. If so, the same storage |
|---|
| 34 | ;slot can be used for both. A particularily important case is where one is initialized |
|---|
| 35 | ;from the other. Then the two can be merged into one, also saving the initialization. |
|---|
| 36 | ;This often happens as a result of the (lambda (n) (do ((n n (1-n)) ..) ..) ..) style. |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | ; A ordinary sequence is an ordered list of instructions which necessarily follow each |
|---|
| 40 | ;other logically. |
|---|
| 41 | ;There can be no branches into the middle of a sequence, nor can an a fork in control |
|---|
| 42 | ;structure occur in the middle of a sequence. Thus, a merge point may only be the first |
|---|
| 43 | ;instruction of a sequence, and a conditional branch the last. Every instruction belongs |
|---|
| 44 | ;to exactly one sequence. |
|---|
| 45 | |
|---|
| 46 | ; *MA-SEQUENCES* is created by a traversal of the code in a possible execution order. |
|---|
| 47 | |
|---|
| 48 | (DEFVAR *MA-SEQUENCES*) |
|---|
| 49 | (DEFVAR *MA-FIRST-SEQUENCE*) |
|---|
| 50 | |
|---|
| 51 | (DEFSTRUCT (MA-ELEM :NAMED) ;never instantiated, just included below. |
|---|
| 52 | MA-ELEM-MEMBERS ;must be INSTs for sequences, can be bubbles or loops for |
|---|
| 53 | ; bubbles or loops. |
|---|
| 54 | MA-ELEM-BUBBLES ;BUBBLES "directly" a member of. |
|---|
| 55 | MA-ELEM-LOOPS) ;LOOPS "directly" a member of. |
|---|
| 56 | |
|---|
| 57 | (DEFSTRUCT (MA-SEQUENCE :NAMED :ARRAY (:INCLUDE MA-ELEM)) |
|---|
| 58 | MA-SEQ-NEXT-SEQUENCE ;seq this one "drops into" |
|---|
| 59 | MA-SEQ-PRECEEDING-SEQUENCES ;sequences which execute immediately before this one. |
|---|
| 60 | MA-SEQ-FOLLOWING-SEQUENCES ;sequences which execute immediately after this one. |
|---|
| 61 | MA-SEQ-ALL-LOOPS ;all loops a member of, including those of my bubbles and loops, etc |
|---|
| 62 | MA-SEQ-CHANGED ;instruction altered during optimization |
|---|
| 63 | ;following used by CHART-TOPOLOGY |
|---|
| 64 | MA-SEQ-PENDING-FS |
|---|
| 65 | MA-SEQ-APATHS ;Access paths by which we get here. |
|---|
| 66 | MA-SEQ-LOOP-PATHS |
|---|
| 67 | MA-SEQ-BUBBLE-PATHS |
|---|
| 68 | MA-SEQ-LOOP-HEADS |
|---|
| 69 | MA-SEQ-BUBBLE-HEADS |
|---|
| 70 | ) |
|---|
| 71 | |
|---|
| 72 | ;Charting things out: |
|---|
| 73 | ; A BUBBLE has a top, a bottom and two or more ways from getting from one to the other. |
|---|
| 74 | ; A LOOP is any kind of a cyclic structure. |
|---|
| 75 | |
|---|
| 76 | ;*** For a BUBBLE to be SIMPLE, each path must be "direct", ie cannot contain branches |
|---|
| 77 | ;to unrelated stuff. A branch can have a fully contained loop or bubble, however. |
|---|
| 78 | ; For a LOOP it must be a straighforward cycle of elements, "singularily connected". |
|---|
| 79 | ;Ie, there must be a single entry point and a single exit point which connect to the |
|---|
| 80 | ;rest of the world. However, in addition to the main exit point, |
|---|
| 81 | ;multiple "exit stubs" (paths which exit the entire function) are allowed. |
|---|
| 82 | ; Simple BUBBLEs and LOOPs both look like simple sequences from above. |
|---|
| 83 | |
|---|
| 84 | ; Finding BUBBLES and LOOPS simplemindedly. We start with initial sequence and walk |
|---|
| 85 | ;the program recursively, keeping a list of the current path. If a segment on this list |
|---|
| 86 | ;is encountered, the walker has closed a loop. The members of the loop, (ie the segment |
|---|
| 87 | ;of the path list after the previous occurance), is added to the MA-SEQ-LOOP-HEADS |
|---|
| 88 | ;list of the intersecting segment. |
|---|
| 89 | ; Also, each time a sequence is encountered, the current path is added to the |
|---|
| 90 | ;MA-SEQ-APATHS component of the sequence. So if we encounter a sequence for the |
|---|
| 91 | ;second time, with the current path and the previous path we can find the BUBBLE, if any, |
|---|
| 92 | ;and add it to the MA-SEQ-BUBBLE-PATHS component of the head sequence. |
|---|
| 93 | ; One problem is avoiding pseudo-duplicate loops and/or bubbles when several loops |
|---|
| 94 | ;and/or bubbles are nested. For example, if there is a bubble inside a loop, we dont |
|---|
| 95 | ;want to find two loops, one through each fork of the bubble. To help deal with this, |
|---|
| 96 | ;we first find PATH sequences. When the recursive walk is about to ascend from a |
|---|
| 97 | ;sequence, the MA-SEQ-LOOP-PATH and MA-SEQ-BUBBLE-PATH components are examined. |
|---|
| 98 | ;At this time all "lower" nodes have been exhaustively examined, thus, the HEAD nodes |
|---|
| 99 | ;of all lower loops and bubbles have been identified. The members of the PATHS |
|---|
| 100 | ;list are examined, and if any of them are head nodes of a loop or bubble, they are |
|---|
| 101 | ;replaced with that loop or bubble structure, and all following nodes which are members |
|---|
| 102 | ;of the same loop or bubble are deleted. (Loops are considered more "outer" than bubbles). |
|---|
| 103 | ;Finally, duplicates are deleted, and the node becomes the head node for any remaining |
|---|
| 104 | ;loops and/or bubbles. |
|---|
| 105 | |
|---|
| 106 | (DEFVAR *MA-BUBBLES*) |
|---|
| 107 | |
|---|
| 108 | (DEFSTRUCT (MA-BUBBLE :NAMED :ARRAY (:INCLUDE MA-ELEM)) |
|---|
| 109 | MA-BUBBLE-TOP |
|---|
| 110 | MA-BUBBLE-BOTTOM |
|---|
| 111 | MA-BUBBLE-PATHS ;members of this list can be sequences, bubbles, or loops. |
|---|
| 112 | ;each path includes the head-sequence. |
|---|
| 113 | ) |
|---|
| 114 | |
|---|
| 115 | (DEFVAR *MA-LOOPS*) |
|---|
| 116 | |
|---|
| 117 | ;A loop is a cyclic structure. It may or may not partially coincide with other |
|---|
| 118 | ;loops. |
|---|
| 119 | (DEFSTRUCT (MA-LOOP :NAMED :ARRAY (:INCLUDE MA-ELEM)) |
|---|
| 120 | MA-LOOP-ENTRIES ;A list, (loop-seq . non-loop seq) |
|---|
| 121 | MA-LOOP-EXITS ; likewise. |
|---|
| 122 | ) |
|---|
| 123 | |
|---|
| 124 | ;A simple-loop is a straighforward cycle of elements. It must |
|---|
| 125 | ; be "singularily connected", ie, there must be a single entry |
|---|
| 126 | ; point and at most a single exit point which connect to the |
|---|
| 127 | ; rest of the world. However, in addition to the main exit point, |
|---|
| 128 | ; multiple "exit stubs" (paths which exit the entire function) |
|---|
| 129 | ; are allowed. |
|---|
| 130 | |
|---|
| 131 | ;Ordering relations between states |
|---|
| 132 | ; Given two states and a context, exactly one of the following relations holds: |
|---|
| 133 | ;BEFORE AFTER INDETERMINANT EXCLUSIVE. The context is usually the whole function or a |
|---|
| 134 | ;loop. The relation is relative to a particular execution |
|---|
| 135 | ;of context. Thus if the context is the whole function, all instructions |
|---|
| 136 | ;within a loop are INDETERMINANT relative to each other. |
|---|
| 137 | |
|---|
| 138 | ;a STATE is a specification of what logical register slots are in existance, |
|---|
| 139 | ; and the current contents of each. The current contents of a register are |
|---|
| 140 | ; described by a OPERAND structure. |
|---|
| 141 | |
|---|
| 142 | ;A program is a sequence of instructions. Each instruction may take 1 or 2 operands |
|---|
| 143 | ; and may produce a result. If produced, the result is described by an OPERAND structure. |
|---|
| 144 | ;Before each instruction the machine is in some state (BEFORE-STATE) and following |
|---|
| 145 | ;the instruction it is in some other state (AFTER-STATE). The AFTER-STATE |
|---|
| 146 | ;is produced by copying the BEFORE-STATE, the meta-simulating the operation |
|---|
| 147 | ;of the instruction. The copying is only to one level, however, ie the AFTER-STATE |
|---|
| 148 | ;points to EQ quantity structures as the BEFORE state, except as modified by |
|---|
| 149 | ;the meta-simulation. |
|---|
| 150 | |
|---|
| 151 | ;An OPERAND structure consists mainly of a list of QUANTITY descriptions. |
|---|
| 152 | ;Usually, this list is only a single element long, but it may be longer if |
|---|
| 153 | ;there have been merges in the flow of control. It that case, each element |
|---|
| 154 | ;represents an alternative possibility for the OPERAND. |
|---|
| 155 | |
|---|
| 156 | ;A QUANTITY structure contains the state serial number the quantity was generated at, |
|---|
| 157 | ; a pointer to the generating instruction, the data type of the quantity, |
|---|
| 158 | ; and a property list where notes can be made about the quantity. |
|---|
| 159 | ; Each QUANTITY comes to have a list of all the instructions that may USE it. |
|---|
| 160 | |
|---|
| 161 | ;All methods of getting to a particular instruction had better lead to the same |
|---|
| 162 | ; form of STATE, or you are clearly losing. |
|---|
| 163 | |
|---|
| 164 | ;Getting everything all hooked up.. |
|---|
| 165 | ; Until the hook-up pass over the program is completed, all OPERANDs may be |
|---|
| 166 | ;incomplete, ie, we may discover branches which lead to additional possible |
|---|
| 167 | ;quantities. |
|---|
| 168 | |
|---|
| 169 | ; First generate an output state for every instruction that needs one. |
|---|
| 170 | |
|---|
| 171 | ; After an unconditional branch, the state can be "discontinuous" between |
|---|
| 172 | ;contiguous instructions. |
|---|
| 173 | |
|---|
| 174 | ;The pdl buffer index |
|---|
| 175 | ; This hardware register addresses the PDL-BUFFER. It is not saved across |
|---|
| 176 | ;subroutine calls. (Even CAR might get an error or send a message and clobber |
|---|
| 177 | ;it). |
|---|
| 178 | |
|---|
| 179 | ;The pdl buffer pass around path. |
|---|
| 180 | ; Unfortunately, the CADR processor doesnt have one. The result is that new data |
|---|
| 181 | ;written is not "visible" on the cycle immediately following the writing cycle. |
|---|
| 182 | ;This rarely matters if no optimizations are being attempted since it normally |
|---|
| 183 | ;takes a cycle to set up the PDL-BUFFER-INDEX to the desired variable, during which |
|---|
| 184 | ;a previous write can "happen". However, if one tries to be clever, one can lose. |
|---|
| 185 | ;Also a C-PDL-BUFFER-POINTER-PUSH destination followed by C-PDL-BUFFER-POINTER or |
|---|
| 186 | ;C-PDL-BUFFER-POINTER-POP source will lose. For now, this problem arises in inline |
|---|
| 187 | ;code only; any jump takes a cycle which lets the writes really happen. However, if |
|---|
| 188 | ;one were to get fancy with -XCT-NEXT frobs, one could lose. |
|---|
| 189 | |
|---|
| 190 | ;coding conventions: |
|---|
| 191 | ; The TYPED-POINTER part of the word (low 29. bits) is of interest. Unfortunately |
|---|
| 192 | ;the rest is there. The general assumption is that quantities in the A and M registers |
|---|
| 193 | ;are clean, while those in functional sources (notably MD) and PDL-BUFFER are dirty. |
|---|
| 194 | ;MOVE automatically masks when comming from dirty sources. |
|---|
| 195 | |
|---|
| 196 | ;optimization switches. Hopefully it helps to isolate bugs to be able to turn various |
|---|
| 197 | ; cleverness off. |
|---|
| 198 | (DEFCONST *ma-optimize-pdl-index* t) |
|---|
| 199 | (DEFCONST *ma-colapse-cubbyholes* t) |
|---|
| 200 | (DEFCONST *ma-chart-topology* t) ;do hairy topology analysis |
|---|
| 201 | (DEFCONST *ma-optimize* t) |
|---|
| 202 | (DEFCONST *ma-make-mclap-sequence-wise* t) ;otherwise do it INST wise |
|---|
| 203 | (DEFCONST *ma-hack-xct-next* t) |
|---|
| 204 | |
|---|
| 205 | (defvar *ma-first-inst*) ;Main input. List of MA-INST defstructs. |
|---|
| 206 | (defvar *ma-inst-tail*) ;current or last MA-INST. |
|---|
| 207 | (defvar *ma-initial-state*) ;state prior to first inst. |
|---|
| 208 | |
|---|
| 209 | (defvar *ma-opt-flag*) ;set if optimizer manages to do something. |
|---|
| 210 | |
|---|
| 211 | ;for expansion phase |
|---|
| 212 | (DEFVAR *SEQ*) ;current sequence (optimizer phase) |
|---|
| 213 | (DEFVAR *INST*) ;current instruction |
|---|
| 214 | (DEFVAR *ALIST*) ;current alist (optimizer phase) |
|---|
| 215 | (DEFVAR *PATTERN*) ;current pattern (optimizer phase) |
|---|
| 216 | (DEFVAR *EMIT-LIST*) ;list of instructions emitted so far |
|---|
| 217 | (DEFVAR *PDL-BUFFER-INDEX*) ;absolute slot number pdl buffer is set to or NIL. |
|---|
| 218 | ; (ie arg 1 is absolute slot 0, etc) |
|---|
| 219 | (DEFVAR *PDL-BUFFER-WRITE-HAPPENING*) ;absolute slot number stored in on last cycle |
|---|
| 220 | ;either via pdl-buffer-index, c-pdl-buffer-pointer, |
|---|
| 221 | ;or c-pdl-buffer-pointer-push. This is cleared by |
|---|
| 222 | ;MA-EMIT-EXECUTE, so should be set up after MA-EMIT ing |
|---|
| 223 | ;the inst that does the write. |
|---|
| 224 | (DEFVAR *MA-SPECBIND-DONE*) ;Until this, ref special vars that have cubbyholes |
|---|
| 225 | ; on stack instead of in special cells. |
|---|
| 226 | |
|---|
| 227 | (DEFCONST *M-REGISTERS* '(T B R C TEM)) ;M-registers. |
|---|
| 228 | |
|---|
| 229 | (DEFMACRO DOINSTS ((VAR FORM) . BODY) |
|---|
| 230 | `(DO ((,VAR ,FORM (MA-INST-NEXT-INST ,VAR))) |
|---|
| 231 | ((NULL ,VAR)) |
|---|
| 232 | . ,BODY)) |
|---|
| 233 | |
|---|
| 234 | (DEFSTRUCT (MA-INST :NAMED :ARRAY) |
|---|
| 235 | MA-INST-CODE ;instruction as produced by micro-compiler |
|---|
| 236 | MA-INST-TAGS-BEFORE ;list of tags immediately before this inst. |
|---|
| 237 | MA-INST-PREVIOUS-INST ;textually previous guy |
|---|
| 238 | MA-INST-NEXT-INST ;textually next guy |
|---|
| 239 | MA-INST-BEFORE-STATE |
|---|
| 240 | MA-INST-AFTER-STATE |
|---|
| 241 | MA-INST-OP1 ;slot quantity (ie element of ma-state-register-alist or |
|---|
| 242 | ; ma-state-stack-alist). Thus CAR is NIL or the |
|---|
| 243 | ; cubbyhole specifier, CDR is a list of alternative OPERANDS. |
|---|
| 244 | ;may be a list of such if INST pops pdl. |
|---|
| 245 | MA-INST-OP2 ;likewise operand 2 |
|---|
| 246 | MA-INST-RESULT-OPERAND ;result |
|---|
| 247 | MA-INST-EXPANSION ;list of MCLAP words |
|---|
| 248 | MA-INST-SEQUENCE ;sequence this belongs to |
|---|
| 249 | MA-INST-CHANGED ;if T, CODE changed by optimizer. Operands may |
|---|
| 250 | ; not be right. |
|---|
| 251 | ) ;update ma-clear-code when adding.... |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | (DEFSTRUCT (MA-STATE :NAMED :ARRAY) ;machine state |
|---|
| 255 | MA-STATE-INST ;instruction this belongs to or BEGINNING-OF-FUNCTION |
|---|
| 256 | MA-STATE-FILLED ;If NIL, none of the other field have been filled in yet. |
|---|
| 257 | MA-STATE-PRECEEDING-STATES ;A list of the states which logically immediately |
|---|
| 258 | ; preceed this one. Normally the AFTER state of the |
|---|
| 259 | ; preceeding instruction plus any branches in. |
|---|
| 260 | MA-STATE-FOLLOWING-STATES ;A list of states which logically immediately follow |
|---|
| 261 | ; this one. The "drop thru" case, if any, is first on the |
|---|
| 262 | ; list. |
|---|
| 263 | MA-STATE-REGISTER-ALIST ;Associates LAP ADDRESS with operand-list |
|---|
| 264 | ; Keeps track of state in M, A registers, etc |
|---|
| 265 | ; These operand lists are normally one long, but can be longer as a result of |
|---|
| 266 | ;merges in the flow of control.The first element of the operand list may be INVALID |
|---|
| 267 | ;which means the slot was completely unspecified by some state which was merged in. |
|---|
| 268 | ;Note that since just the top level list is copied |
|---|
| 269 | MA-STATE-STACK-ALIST ;List corresponds to stack slots. Key is cubbyhole, |
|---|
| 270 | ;or NIL if temporary part of the stack. Used to compute |
|---|
| 271 | ;stack indexing (particularily considering the fact that |
|---|
| 272 | ;stack slots may be "removed" to registers.) Each entry is |
|---|
| 273 | ;a CONS, CDR of which is a QUANTITY list. |
|---|
| 274 | MA-STATE-PDL-BUFFER-INDEX |
|---|
| 275 | MA-STATE-PDL-BUFFER-WRITE-HAPPENING |
|---|
| 276 | ) ;update MA-CLEAR-STATE when adding these ... |
|---|
| 277 | |
|---|
| 278 | ;duplicate state so modifications wont affect original. |
|---|
| 279 | (DEFUN MA-COPY-STATE (FROM-STATE TO-STATE) |
|---|
| 280 | (SETF (MA-STATE-REGISTER-ALIST TO-STATE) |
|---|
| 281 | (APPEND (MA-STATE-REGISTER-ALIST FROM-STATE) NIL)) |
|---|
| 282 | (SETF (MA-STATE-STACK-ALIST TO-STATE) |
|---|
| 283 | (APPEND (MA-STATE-STACK-ALIST FROM-STATE) NIL)) |
|---|
| 284 | (SETF (MA-STATE-FILLED TO-STATE) T) |
|---|
| 285 | TO-STATE) |
|---|
| 286 | |
|---|
| 287 | ;Actually represents an operand-instance, ie, this is not modified once it is generated |
|---|
| 288 | ; except to notate additional uses. |
|---|
| 289 | (defstruct (ma-operand :named :array) |
|---|
| 290 | ma-operand-source ;inst that generated this, or nil if "magic" (ie initial) |
|---|
| 291 | ma-operand-name ;identification for printing |
|---|
| 292 | ma-operand-type ;NIL for normal, DTP-FIX, T-OR-NIL |
|---|
| 293 | ma-operand-defects ;funny things about this frob. For now, mostly whether there |
|---|
| 294 | ; is garbage in the CDR-CODE and FLAG bits. |
|---|
| 295 | ;ma-original-source ;attempts to be transparent to MOVEs. This loses because other |
|---|
| 296 | ; paths may merge in. |
|---|
| 297 | ma-operand-uses ;list of insts that use this. |
|---|
| 298 | ) |
|---|
| 299 | |
|---|
| 300 | |
|---|
| 301 | (DEFUN (MA-INST NAMED-STRUCTURE-INVOKE) (MESSAGE &OPTIONAL SELF &REST ARGS) |
|---|
| 302 | (SELECTQ MESSAGE |
|---|
| 303 | (:WHICH-OPERATIONS '(:PRINT-SELF)) |
|---|
| 304 | ((:PRINT-SELF) |
|---|
| 305 | (SI:PRINTING-RANDOM-OBJECT (SELF (CAR ARGS) :NO-POINTER) |
|---|
| 306 | (FORMAT (CAR ARGS) "MA-INST ~A" (MA-INST-CODE SELF)))) |
|---|
| 307 | (OTHERWISE (FERROR NIL "~S unknown" MESSAGE)))) |
|---|
| 308 | |
|---|
| 309 | (DEFUN (MA-STATE NAMED-STRUCTURE-INVOKE) (MESSAGE &OPTIONAL SELF &REST ARGS) |
|---|
| 310 | (SELECTQ MESSAGE |
|---|
| 311 | (:WHICH-OPERATIONS '(:PRINT-SELF)) |
|---|
| 312 | ((:PRINT-SELF) |
|---|
| 313 | (SI:PRINTING-RANDOM-OBJECT (SELF (CAR ARGS) :NO-POINTER) |
|---|
| 314 | (FORMAT (CAR ARGS) "MA-STATE ~A ~A, PDL LEN ~D" |
|---|
| 315 | (COND ((SYMBOLP (MA-STATE-INST SELF))) |
|---|
| 316 | ((EQ SELF (MA-INST-BEFORE-STATE (MA-STATE-INST SELF))) |
|---|
| 317 | 'BEFORE) |
|---|
| 318 | (T 'AFTER)) |
|---|
| 319 | (MA-STATE-INST SELF) |
|---|
| 320 | (LENGTH (MA-STATE-STACK-ALIST SELF))))) |
|---|
| 321 | (OTHERWISE (FERROR NIL "~S unknown" MESSAGE)))) |
|---|
| 322 | |
|---|
| 323 | (DEFUN (MA-OPERAND NAMED-STRUCTURE-INVOKE) (MESSAGE &OPTIONAL SELF &REST ARGS) |
|---|
| 324 | (SELECTQ MESSAGE |
|---|
| 325 | (:WHICH-OPERATIONS '(:PRINT-SELF)) |
|---|
| 326 | ((:PRINT-SELF) |
|---|
| 327 | (SI:PRINTING-RANDOM-OBJECT (SELF (CAR ARGS) :NO-POINTER) |
|---|
| 328 | (FORMAT (CAR ARGS) "MA-OPERAND ~A" (MA-OPERAND-NAME SELF)))) |
|---|
| 329 | (OTHERWISE (FERROR NIL "~S unknown" MESSAGE)))) |
|---|
| 330 | |
|---|
| 331 | (DEFUN (MA-CUBBYHOLE NAMED-STRUCTURE-INVOKE) (MESSAGE &OPTIONAL SELF &REST ARGS) |
|---|
| 332 | (SELECTQ MESSAGE |
|---|
| 333 | (:WHICH-OPERATIONS '(:PRINT-SELF)) |
|---|
| 334 | ((:PRINT-SELF) |
|---|
| 335 | (SI:PRINTING-RANDOM-OBJECT (SELF (CAR ARGS) :NO-POINTER) |
|---|
| 336 | (FORMAT (CAR ARGS) "MA-CUBBYHOLE ~A" (MA-CUBBYHOLE-NAME SELF)))) |
|---|
| 337 | (OTHERWISE (FERROR NIL "~S unknown" MESSAGE)))) |
|---|
| 338 | |
|---|
| 339 | |
|---|
| 340 | (DEFMACRO MA-EMIT (&REST FIELD-VALUE-PAIRS) |
|---|
| 341 | `(MA-EMIT-EXECUTE1 (MA-EVAL ,@FIELD-VALUE-PAIRS))) |
|---|
| 342 | |
|---|
| 343 | (DEFUN MA-EMIT-EXECUTE1 (VAL) |
|---|
| 344 | (SETQ *EMIT-LIST* (NCONC *EMIT-LIST* (LIST VAL))) |
|---|
| 345 | (SETQ *PDL-BUFFER-WRITE-HAPPENING* NIL)) |
|---|
| 346 | |
|---|
| 347 | ;arg is a list of <field> <value>. <field> is usually a constant (number or symbol |
|---|
| 348 | ; with value) at compile time. If <value> is also a constant, the combination is |
|---|
| 349 | ; performed at macro-expand time. Otherwise, it is expanded into a call to MA-RUNTIME-EVAL. |
|---|
| 350 | |
|---|
| 351 | (DEFUN MA-EVAL MACRO (X) |
|---|
| 352 | (LET ((CONSTANT 0) |
|---|
| 353 | (SPECIFIED-BITS 0) |
|---|
| 354 | (RUNTIME-LETLIST NIL) |
|---|
| 355 | (RUNTIME-EXPS NIL)) |
|---|
| 356 | (PROG (FIELD VALUE L) |
|---|
| 357 | (SETQ L (CDR X)) |
|---|
| 358 | L (COND ((NULL L) (RETURN NIL))) |
|---|
| 359 | (SETQ FIELD (CAR L) VALUE (CADR L)) |
|---|
| 360 | L1 (COND ((AND (NUMBERP FIELD) (NUMBERP VALUE)) |
|---|
| 361 | (COND ((NOT (ZEROP (LDB FIELD SPECIFIED-BITS))) |
|---|
| 362 | (FERROR NIL " |
|---|
| 363 | Overlapping fields. This field ~S, this value ~S, previously specified mask ~S" |
|---|
| 364 | FIELD VALUE SPECIFIED-BITS))) |
|---|
| 365 | (SETQ CONSTANT (DPB VALUE FIELD CONSTANT)) |
|---|
| 366 | (SETQ SPECIFIED-BITS (DPB -1 FIELD SPECIFIED-BITS))) |
|---|
| 367 | ((AND (SYMBOLP FIELD) |
|---|
| 368 | (BOUNDP FIELD) |
|---|
| 369 | (NUMBERP (SYMEVAL FIELD))) |
|---|
| 370 | (SETQ FIELD (SYMEVAL FIELD)) |
|---|
| 371 | (GO L1)) |
|---|
| 372 | ((AND (SYMBOLP VALUE) |
|---|
| 373 | (BOUNDP VALUE) |
|---|
| 374 | (NUMBERP (SYMEVAL VALUE))) |
|---|
| 375 | (SETQ VALUE (SYMEVAL VALUE)) |
|---|
| 376 | (GO L1)) |
|---|
| 377 | ((NOT (OR (SYMBOLP FIELD) (NUMBERP FIELD))) |
|---|
| 378 | (LET ((GS (GENSYM))) |
|---|
| 379 | (SETQ RUNTIME-LETLIST |
|---|
| 380 | (NCONC RUNTIME-LETLIST |
|---|
| 381 | (LIST `(,GS ,FIELD)))) |
|---|
| 382 | (SETQ FIELD GS)) |
|---|
| 383 | (GO L1)) |
|---|
| 384 | ((NOT (OR (SYMBOLP VALUE) (NUMBERP VALUE))) |
|---|
| 385 | (LET ((GS (GENSYM))) |
|---|
| 386 | (SETQ RUNTIME-LETLIST |
|---|
| 387 | (NCONC RUNTIME-LETLIST |
|---|
| 388 | (LIST `(,GS ,VALUE)))) |
|---|
| 389 | (SETQ VALUE GS)) |
|---|
| 390 | (GO L1)) |
|---|
| 391 | (T (SETQ RUNTIME-EXPS (NCONC RUNTIME-EXPS (LIST FIELD VALUE))))) |
|---|
| 392 | (SETQ L (CDDR L)) |
|---|
| 393 | (GO L)) |
|---|
| 394 | `(LET ,RUNTIME-LETLIST |
|---|
| 395 | (MA-RUNTIME-EVAL ,CONSTANT ,SPECIFIED-BITS ,@RUNTIME-EXPS)) |
|---|
| 396 | )) |
|---|
| 397 | |
|---|
| 398 | ;SPECIFIED-BITS is just for error checking. |
|---|
| 399 | (DEFUN MA-RUNTIME-EVAL (CONSTANT SPECIFIED-BITS &REST FIELD-VALUES) |
|---|
| 400 | (PROG (FIELD VALUE L sym-fields) |
|---|
| 401 | (SETQ L FIELD-VALUES) |
|---|
| 402 | L (COND ((NULL L) |
|---|
| 403 | (RETURN (COND (SYM-FIELDS |
|---|
| 404 | (LIST CONSTANT SYM-FIELDS)) |
|---|
| 405 | (T CONSTANT))))) |
|---|
| 406 | (SETQ FIELD (CAR L) VALUE (CADR L)) |
|---|
| 407 | L1 (COND ((AND (NUMBERP FIELD) (NUMBERP VALUE)) |
|---|
| 408 | (COND ((NOT (ZEROP (LDB FIELD SPECIFIED-BITS))) |
|---|
| 409 | (FERROR NIL " |
|---|
| 410 | Overlapping fields. This field ~S, this value ~S, previously specified mask ~S" FIELD VALUE SPECIFIED-BITS))) |
|---|
| 411 | (SETQ CONSTANT (DPB VALUE FIELD CONSTANT)) |
|---|
| 412 | (SETQ SPECIFIED-BITS (DPB -1 FIELD SPECIFIED-BITS))) |
|---|
| 413 | ((AND (SYMBOLP FIELD) |
|---|
| 414 | (BOUNDP FIELD) |
|---|
| 415 | (NUMBERP (SYMEVAL FIELD))) |
|---|
| 416 | (SETQ FIELD (SYMEVAL FIELD)) |
|---|
| 417 | (GO L1)) |
|---|
| 418 | ((AND (SYMBOLP VALUE) |
|---|
| 419 | (BOUNDP VALUE) |
|---|
| 420 | (NUMBERP (SYMEVAL VALUE))) |
|---|
| 421 | (SETQ VALUE (SYMEVAL VALUE)) |
|---|
| 422 | (GO L1)) |
|---|
| 423 | (T |
|---|
| 424 | (SETQ SPECIFIED-BITS (DPB -1 FIELD SPECIFIED-BITS)) |
|---|
| 425 | (SETQ SYM-FIELDS |
|---|
| 426 | (CONS (LIST FIELD VALUE) SYM-FIELDS)))) |
|---|
| 427 | (SETQ L (CDDR L)) |
|---|
| 428 | (GO L))) |
|---|