root/trunk/lisp/lispm/madefs.lisp @ 283

Revision 283, 18.9 KB (checked in by rjs, 3 years ago)

Update from System 78.

Line 
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 "
363Overlapping 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 "
410Overlapping 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)))
Note: See TracBrowser for help on using the browser.