OSDN Git Service

Add define-rtl-version.
[pf3gnuchains/pf3gnuchains4x.git] / cgen / read.scm
1 ; Top level file for reading and recording .cpu file contents.
2 ; Copyright (C) 2000, 2001, 2006, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4 ; See file COPYING.CGEN for details.
5
6 ; This file [and its subordinates] contain no C code (well, as little as
7 ; possible).  That lives at a layer above us.
8
9 ; A .cpu file consists of several sections:
10 ;
11 ; - basic definitions (e.g. cpu variants, word size, endianness, etc.)
12 ; - enums (enums are used throughout so by convention there is a special
13 ;   section in which they're defined)
14 ; - attributes
15 ; - instruction fields and formats
16 ; - hardware descriptions (e.g. registers, allowable immediate values)
17 ; - model descriptions (e.g. pipelines, latencies, etc.)
18 ; - instruction operands (mapping of insn fields to associated hardware)
19 ; - instruction definitions
20 ; - macro instruction definitions
21
22 ; TODO:
23 ; - memory access, layout, etc.
24 ; - floating point quirks
25 ; - ability to describe an ABI
26 ; - anything else that comes along
27
28 ; Notes:
29 ; - by convention most objects are subclasses of <ident> (having name, comment,
30 ;   and attrs elements and they are the first three elements of any .cpu file
31 ;   entry
32
33 ; Guidelines:
34 ; - Try to conform to R5RS, try to limit guile-ness.
35 ;   The current code is undoubtedly off in many places.
36
37 ; Conventions:
38 ; [I want there to be a plethora of conventions and I want them strictly
39 ; adhered to.  ??? There's probably a few violations here and there.
40 ; No big deal - fix them!]
41 ; These conventions are subject to revision.
42 ;
43 ; - procs/vars local to a file are named "-foo"
44 ; - only routines that emit application code begin with "gen-"
45 ; - symbols beginning with "c-" are either variables containing C code
46 ;   or procedures that generate C code, similarily for C++ and "c++-"
47 ; - variables containing C code begin with "c-"
48 ; - only routines that emit an entire file begin with "cgen-"
49 ; - all .cpu file elements shall have -foo-parse and -foo-read procedures
50 ; - global vars containing class definitions shall be named "<class-name>"
51 ; - procs related to a particular class shall be named "class-name-proc-name",
52 ;   class-name may be abbreviated
53 ; - procs that test whether something is an object of a particular class
54 ;   shall be named "class-name?"
55 ; - in keeping with Scheme conventions, predicates shall have a "?" suffix
56 ; - in keeping with Scheme conventions, methods and procedures that modify an
57 ;   argument or have other side effects shall have a "!" suffix,
58 ;   usually these procs return "*UNSPECIFIED*"
59 ; - all -foo-parse,parse-foo procs shall have `context' as the first arg
60 ;   [FIXME: not all such procs have been converted]
61 ; - stay away from non-portable C symbols.
62 \f
63 ; Variables representing misc. global constants.
64
65 ; A list of three numbers designating the cgen version: major minor fixlevel.
66 ; The "50" is a generic indicator that we're between 1.1 and 1.2.
67 (define -CGEN-VERSION '(1 1 50))
68 (define (cgen-major) (car -CGEN-VERSION))
69 (define (cgen-minor) (cadr -CGEN-VERSION))
70 (define (cgen-fixlevel) (caddr -CGEN-VERSION))
71
72 ; A list of two numbers designating the description language version.
73 ; Note that this is different from -CGEN-VERSION.
74 ; See section "RTL Versions" of the docs.
75 (define -CGEN-RTL-VERSION '(0 7))
76 (define (cgen-rtl-major) (car -CGEN-RTL-VERSION))
77 (define (cgen-rtl-minor) (cadr -CGEN-RTL-VERSION))
78
79 ;; List of supported versions
80 (define -supported-rtl-versions '((0 7)))
81
82 (define (-cmd-define-rtl-version major minor)
83   (if (not (non-negative-integer? major))
84       (parse-error #f "Invalid major version number" major))
85   (if (not (non-negative-integer? minor))
86       (parse-error #f "Invalid minor version number" minor))
87
88   (let ((new-version (list major minor)))
89     (if (not (member new-version -supported-rtl-versions))
90         (parse-error #f "Unsupported/invalid rtl version" new-version))
91     (logit 1 "Setting RTL version to " major "." minor " ...\n")
92     (set! -CGEN-RTL-VERSION new-version))
93 )
94
95 ; Which application is in use (UNKNOWN, DESC, OPCODES, SIMULATOR, ???).
96 ; This is mostly for descriptive purposes.
97 (define APPLICATION 'UNKNOWN)
98 \f
99 ; Things are organized so that files can be compiled with Hobbit for
100 ; experimentation.  Thus we need one file that loads all the other files.
101 ; This is that file, though it would make sense to move the code in this
102 ; file to another.
103
104 ; If a routine to initialize compiled-in code is defined, run it.
105 (if (defined? 'cgen-init-c) (cgen-init-c))
106
107 ; If this is set to #f, the file is always loaded.
108 ; Don't override any current setting, e.g. from dev.scm.
109 (if (not (defined? 'CHECK-LOADED?))
110     (define CHECK-LOADED? #t))
111
112 ; Unlink file if we're reloaded (say in an interactive session).
113 ; Dynamic loading is enabled by setting LIBCPU.SO to the pathname of the .so.
114 (if (and (defined? 'libcpu.so) (dynamic-object? libcpu.so))
115     (dynamic-unlink libcpu.so))
116 (define libcpu.so #f)
117 (if (and (defined? 'LIBCPU.SO)
118          (file-exists? LIBCPU.SO))
119     (set! libcpu.so (dynamic-link LIBCPU.SO))
120 )
121
122 ; List of loaded files.
123
124 (if (not (defined? '-loaded-file-list))
125     (define -loaded-file-list '()))
126
127 ; Return non-zero if FILE was loaded last time through.
128
129 (define (-loaded-file? file)
130   (->bool (memq (string->symbol file) -loaded-file-list))
131 )
132
133 ; Record FILE as compiled in.
134
135 (define (-loaded-file-record! file)
136   (let ((file (string->symbol file)))
137     (if (not (memq file -loaded-file-list))
138         (set! -loaded-file-list (cons file -loaded-file-list))))
139 )
140
141 ; Load FILE if SYM is not compiled in.
142
143 (define (maybe-load file init-func sym)
144   ; Return non-#f if FUNC is present in DYNOBJ.
145   (define (dynamic-func? func dynobj)
146     (catch #t
147            (lambda () (dynamic-func func dynobj))
148            (lambda args #f))
149     )
150
151   (let ((init-func (string-append "init_" (if init-func init-func file))))
152     (cond ((and libcpu.so
153                 (dynamic-func? init-func libcpu.so))
154            (dynamic-call init-func libcpu.so)
155            (display (string-append "Skipping " file ", dynamically loaded.\n")))
156           ((or (not CHECK-LOADED?)
157                (not (defined? sym))
158                (-loaded-file? file))
159            (-loaded-file-record! file)
160            (load file))
161           (else
162            (display (string-append "Skipping " file ", already loaded.\n")))))
163 )
164
165 (maybe-load "pmacros" #f 'define-pmacro)
166 (maybe-load "cos" #f 'make)
167 (maybe-load "slib/logical" #f 'logical:logand)
168 (maybe-load "slib/sort" #f 'sort)
169 ; Used to pretty-print debugging messages.
170 (maybe-load "slib/pp" #f 'pretty-print)
171 ; Used by pretty-print.
172 (maybe-load "slib/random" #f 'random)
173 (maybe-load "slib/genwrite" #f 'generic-write)
174 (maybe-load "utils" #f 'logit)
175 (maybe-load "utils-cgen" "utils_cgen" 'obj:name)
176 (maybe-load "attr" #f '<attribute>)
177 (maybe-load "enum" #f '<enum>)
178 (maybe-load "mach" #f '<mach>)
179 (maybe-load "model" #f '<model>)
180 (maybe-load "types" #f '<scalar>)
181 (maybe-load "mode" #f '<mode>)
182 (maybe-load "ifield" #f '<ifield>)
183 (maybe-load "iformat" #f '<iformat>)
184 (maybe-load "hardware" #f '<hardware-base>)
185 (maybe-load "operand" #f '<operand>)
186 (maybe-load "insn" #f '<insn>)
187 (maybe-load "minsn" #f '<macro-insn>)
188 (maybe-load "decode" #f 'decode-build-table)
189 (maybe-load "rtl" "rtl" '<rtx-func>)
190 (maybe-load "rtl-traverse" "rtl_traverse" 'rtx-traverse)
191 (maybe-load "rtl-xform" "rtx_simplify" 'rtx-simplify)
192 (maybe-load "rtx-funcs" "rtx_funcs" 'def-rtx-funcs)
193 (maybe-load "rtl-c" "rtl_c" '<c-expr>)
194 (maybe-load "semantics" #f 'semantic-compile)
195 (maybe-load "sem-frags" "sem_frags" 'gen-threaded-engine)
196 (maybe-load "utils-gen" "utils_gen" 'attr-gen-decl)
197 (maybe-load "pgmr-tools" "pgmr_tools" 'pgmr-pretty-print-insn-format)
198 \f
199 ; Reader state data.
200 ; All state regarding the reading of a .cpu file is kept in an object of
201 ; class <reader>.
202
203 ; Class to record info for each top-level `command' (for lack of a better
204 ; word) in the description file.
205 ; Top level commands are things like define-*.
206
207 (define <command>
208   (class-make '<command>
209               '(<ident>)
210               '(
211                 ; argument spec to `lambda'
212                 arg-spec
213                 ; lambda that processes the entry
214                 handler
215                 )
216               nil)
217 )
218
219 (define command-arg-spec (elm-make-getter <command> 'arg-spec))
220 (define command-handler (elm-make-getter <command> 'handler))
221
222 ; Return help text for COMMAND.
223
224 (define (command-help cmd)
225   (string-append
226    (obj:comment cmd)
227    "Arguments: "
228    (with-output-to-string (lambda () (write (command-arg-spec cmd))))
229    "\n")
230 )
231
232 ; A pair of two lists: machs to keep, machs to drop.
233 ; The default is "keep all machs", "drop none".
234
235 (define -keep-all-machs '((all)))
236
237 ; Main reader state class.
238
239 (define <reader>
240   (class-make '<reader>
241               nil
242               (list
243                ; Selected machs to keep.
244                ; A pair of two lists: the car lists the machs to keep, the cdr
245                ; lists the machs to drop.  Two special entries are `all' and
246                ; `base'.  Both are only valid in the keep list.  `base' is a
247                ; place holder for objects that are common to all machine
248                ; variants in the architecture, it is the default value of the
249                ; MACH attribute.  If `all' is present the drop list is still
250                ; processed.
251                (cons 'keep-mach -keep-all-machs)
252
253                ; Selected isas to keep or `all'.
254                '(keep-isa . (all))
255
256                ; Boolean indicating if command tracing is on.
257                (cons 'trace-commands? #f)
258
259                ; Boolean indicating if pmacro tracing is on.
260                (cons 'trace-pmacros? #f)
261
262                ; Currently select cpu family, computed from `keep-mach'.
263                ; Some applications don't care, and this is moderately
264                ; expensive to compute so we use delay/force.
265                'current-cpu
266
267                ; Associative list of file entry commands
268                ; (e.g. define-insn, etc.).
269                ; Each entry is (name . command-object).
270                (cons 'commands nil)
271
272                ; The current source location.
273                ; This is recorded here by the higher level reader and is
274                ; fetched by commands as necessary.
275                'location
276                )
277               nil)
278 )
279
280 ; Accessors.
281
282 (define-getters <reader> reader
283   (keep-mach keep-isa
284    trace-commands? trace-pmacros?
285    current-cpu commands location))
286 (define-setters <reader> reader
287   (keep-mach keep-isa
288    trace-commands? trace-pmacros?
289    current-cpu commands location))
290
291 (define (reader-add-command! name comment attrs arg-spec handler)
292   (reader-set-commands! CURRENT-READER
293                         (acons name
294                                (make <command> name comment attrs
295                                      arg-spec handler)
296                                (reader-commands CURRENT-READER)))
297 )
298
299 (define (-reader-lookup-command name)
300   (assq-ref (reader-commands CURRENT-READER) name)
301 )
302
303 ; Reader state for current .cpu file.
304
305 (define CURRENT-READER #f)
306
307 ; Return the current source location in readable form.
308 ; FIXME: Currently unused, keep for reference for awhile.
309
310 (define (-readable-current-location)
311   (let ((loc (current-reader-location)))
312     (if loc
313         (location->string loc)
314         ;; Blech, we don't have a current reader location.  That's odd.
315         ;; Fall back to the current input port's location.
316         (string-append (or (port-filename (current-input-port))
317                             "<input>")
318                         ":"
319                         (number->string (port-line (current-input-port)))
320                         ":")))
321 )
322
323 ;;; Signal a parse error while reading a .cpu file.
324 ;;; If CONTEXT is #f, use a default context of the current reader location
325 ;;; and an empty prefix.
326 ;;; If MAYBE-HELP-TEXT is specified, elide the last trailing \n.
327 ;;; Multiple lines of help text need embedded newlines, and should be no longer
328 ;;; than 79 characters.
329
330 (define (parse-error context message expr . maybe-help-text)
331   (if (not context)
332       (set! context (make <context> (current-reader-location) #f)))
333   (let* ((loc (or (context-location context) (unspecified-location)))
334          (top-sloc (location-top loc))
335          (prefix (context-prefix context)))
336     (error
337      (simple-format
338       #f
339       "While reading description:\n~A: ~A:\n  ~S\nReference chain:\n~A~A"
340       (single-location->simple-string top-sloc)
341       (if prefix
342           (string-append prefix ": " message)
343           message)
344       expr
345       (location->string loc)
346       (if (null? maybe-help-text)
347           ""
348           (string-append "\n" (car maybe-help-text))))))
349 )
350
351 ; Return the current source location.
352 ;
353 ; If CURRENT-READER is uninitialized, return "unspecified" location.
354 ; This is done so that things like define-pmacro work in interactive mode.
355
356 (define (current-reader-location)
357   (if CURRENT-READER
358       (reader-location CURRENT-READER)
359       (unspecified-location))
360 )
361
362 ; Process a macro-expanded entry.
363
364 (define (-reader-process-expanded-1! entry)
365   (let ((location (location-property entry)))
366
367     ;; Set the current source location for better diagnostics.
368     ;; Access with current-reader-location.
369     (reader-set-location! CURRENT-READER location)
370
371     (if (reader-trace-commands? CURRENT-READER)
372         (message "Processing command:\n  @ "
373                  (if location (location->string location) "location unknown")
374                  "\n"
375                  (with-output-to-string (lambda () (pretty-print entry)))))
376
377     (let ((command (-reader-lookup-command (car entry)))
378           (context (make-current-context #f)))
379
380       (if command
381
382           (let* ((handler (command-handler command))
383                  (arg-spec (command-arg-spec command))
384                  (num-args (num-args arg-spec)))
385             (if (cdr num-args)
386                 ;; Variable number of trailing arguments.
387                 (if (< (length (cdr entry)) (car num-args))
388                     (parse-error context
389                                  (string-append "Incorrect number of arguments to "
390                                                 (symbol->string (car entry))
391                                                 ", expecting at least "
392                                                 (number->string (car num-args)))
393                                  entry
394                                  (command-help command))
395                     (apply handler (cdr entry)))
396                 ;; Fixed number of arguments.
397                 (if (!= (length (cdr entry)) (car num-args))
398                     (parse-error context
399                                  (string-append "Incorrect number of arguments to "
400                                                 (symbol->string (car entry))
401                                                 ", expecting "
402                                                 (number->string (car num-args)))
403                                  entry
404                                  (command-help command))
405                     (apply handler (cdr entry)))))
406
407           (parse-error context "unknown entry type" entry))))
408
409   *UNSPECIFIED*
410 )
411
412 ;; Process 1 or more macro-expanded entries.
413 ;; ENTRY is expected to have a location-property object property.
414
415 ;; NOTE: This is "public" so the .eval pmacro can use it.
416 ;; This is also used by -cmd-if.
417
418 (define (reader-process-expanded! entry)
419   ;; () is used to indicate a no-op
420   (cond ((null? entry)
421          #f) ;; nothing to do
422         ;; `begin' is used to group a collection of entries into one,
423         ;; since pmacro can only return one expression (borrowed from
424         ;; Scheme of course).
425         ;; Recurse in case there are nested begins.
426         ((eq? (car entry) 'begin)
427          (for-each reader-process-expanded!
428                    (cdr entry)))
429         (else
430          (-reader-process-expanded-1! entry)))
431
432   *UNSPECIFIED*
433 )
434
435 ; Process file entry ENTRY.
436 ; LOC is a <location> object for ENTRY.
437
438 (define (-reader-process! entry loc)
439   (if (not (form? entry))
440       (parse-error loc "improperly formed entry" entry))
441
442   ; First do macro expansion, but not if define-pmacro of course.
443   ; ??? Singling out define-pmacro this way seems a bit odd.  The way to look
444   ; at it, I guess, is to think of define-pmacro as (currently) the only
445   ; "syntactic" command (it doesn't pre-evaluate its arguments).
446   (let ((expansion (if (eq? (car entry) 'define-pmacro)
447                        (begin (location-property-set! entry loc) entry)
448                        (if (reader-trace-pmacros? CURRENT-READER)
449                            (pmacro-trace entry loc)
450                            (pmacro-expand entry loc)))))
451     (reader-process-expanded! expansion))
452
453   *UNSPECIFIED*
454 )
455
456 ; Read in and process FILE.
457 ;
458 ; It would be nice to get the line number of the beginning of the object,
459 ; but that's extra work, so for now we do the simple thing and use
460 ; port-line after we've read an entry.
461
462 (define (reader-read-file! file)
463   (let ((readit (lambda ()
464                   (let loop ((entry (read)))
465                     (if (eof-object? entry)
466                         #t ; done
467                         (begin
468                           ;; ??? The location we pass here isn't ideal.
469                           ;; Ideally we'd pass the start location of the
470                           ;; expression, instead we currently pass the end
471                           ;; location (it's easier).
472                           ;; ??? Use source-properties of entry, and only if
473                           ;; not present fall back on current-input-location.
474                           (-reader-process! entry (current-input-location #t))
475                           (loop (read)))))))
476         )
477
478     (with-input-from-file file readit))
479
480   *UNSPECIFIED*
481 )
482 \f
483 ; Cpu data is recorded in an object of class <arch>.
484 ; This is necessary as we need to allow recording of multiple cpu descriptions
485 ; simultaneously.
486 ; Class <arch> is defined in mach.scm.
487
488 ; Global containing all data of the currently selected architecture.
489
490 (define CURRENT-ARCH #f)
491 \f
492 ; `keep-mach' processing.
493
494 ; Return the currently selected cpu family.
495 ; If a specific cpu family has been selected, each machine that is kept must
496 ; be in that cpu family [so there's no ambiguity in the result].
497 ; This is a moderately expensive computation so use delay/force.
498
499 (define (current-cpu) (force (reader-current-cpu CURRENT-READER)))
500
501 ; Return a boolean indicating if CPU-NAME is to be kept.
502 ; ??? Currently this is always true.  Note that this doesn't necessarily apply
503 ; to machs in CPU-NAME.
504
505 (define (keep-cpu? cpu-name) #t)
506
507 ; Cover proc to set `keep-mach'.
508 ; MACH-NAME-LIST is a comma separated string of machines to keep and drop
509 ; (if prefixed with !).
510
511 (define (-keep-mach-set! mach-name-list)
512   (let* ((mach-name-list (string-cut mach-name-list #\,))
513          (keep (find (lambda (name) (not (char=? (string-ref name 0) #\!)))
514                      mach-name-list))
515          (drop (map (lambda (name) (string->symbol (string-drop 1 name)))
516                     (find (lambda (name) (char=? (string-ref name 0) #\!))
517                           mach-name-list))))
518     (reader-set-keep-mach! CURRENT-READER
519                            (cons (map string->symbol keep)
520                                  (map string->symbol drop)))
521     ; Reset current-cpu.
522     (reader-set-current-cpu!
523      CURRENT-READER
524      (delay (let ((selected-machs (find (lambda (mach)
525                                           (keep-mach? (list (obj:name mach))))
526                                         (current-mach-list))))
527               (if (= (length selected-machs) 0)
528                   (error "no machs selected"))
529               (if (not (all-true? (map (lambda (mach)
530                                          (eq? (obj:name (mach-cpu mach))
531                                               (obj:name (mach-cpu (car selected-machs)))))
532                                        selected-machs)))
533                   (error "machs from different cpu families selected"))
534               (mach-cpu (car selected-machs)))))
535
536     *UNSPECIFIED*)
537 )
538
539 ; Validate the user-provided keep-mach list against the list of machs
540 ; specified in the .cpu file (in define-arch).
541
542 (define (keep-mach-validate!)
543   (let ((mach-names (cons 'all (current-arch-mach-name-list)))
544         (keep-mach (reader-keep-mach CURRENT-READER)))
545     (for-each (lambda (mach)
546                 (if (not (memq mach mach-names))
547                     (error "unknown mach to keep:" mach)))
548               (car keep-mach))
549     (for-each (lambda (mach)
550                 (if (not (memq mach mach-names))
551                     (error "unknown mach to drop:" mach)))
552               (cdr keep-mach))
553     )
554   *UNSPECIFIED*
555 )
556
557 ; Return #t if a machine in MACH-LIST, a list of symbols, is to be kept.
558 ; If any machine in MACH-LIST is to be kept, the result is #t.
559 ; If MACH-LIST is the empty list (no particular mach specified, thus the base
560 ; mach), the result is #t.
561
562 (define (keep-mach? mach-list)
563   (if (null? mach-list)
564       #t
565       (let* ((keep-mach (reader-keep-mach CURRENT-READER))
566              (keep (cons 'base (car keep-mach)))
567              (drop (cdr keep-mach))
568              (keep? (map (lambda (m) (memq m keep)) mach-list))
569              (all? (memq 'all keep))
570              (drop? (map (lambda (m) (memq m drop)) mach-list)))
571         (any-true? (map (lambda (k d)
572                           ; keep if K(ept) or ALL? and not D(ropped)
573                           (->bool (and (or k all?) (not d))))
574                         keep? drop?))))
575 )
576
577 ; Return non-#f if the object containing ATLIST is to be kept.
578 ; OBJ is the container object or #f if there is none.
579 ; The object is kept if its attribute list specifies a `MACH' that is
580 ; kept (and not dropped) or does not have the `MACH' attribute (which means
581 ; it has the default value which means it's for use with all machines).
582
583 (define (keep-mach-atlist? atlist obj)
584   ; The MACH attribute is not created until the .cpu file is read in which
585   ; is too late for us [we will get called for builtin objects].
586   ; Thus we peek inside the attribute list directly.
587   ; ??? Maybe postpone creation of builtins until after define-arch?
588   (let ((machs (atlist-attr-value-no-default atlist 'MACH obj)))
589     (if (null? machs)
590         #t
591         (keep-mach? (bitset-attr->list machs))))
592 )
593
594 ; Return a boolean indicating if the object containing ATLIST is to be kept.
595 ; OBJ is the container object or #f if there is none.
596 ; The object is kept if both its isa and its mach are kept.
597
598 (define (keep-atlist? atlist obj)
599   (and (keep-mach-atlist? atlist obj)
600        (keep-isa-atlist? atlist obj))
601 )
602
603 ; Return a boolean indicating if multiple cpu families are being kept.
604
605 (define (keep-multiple?)
606   (let ((selected-machs (find (lambda (mach)
607                                 (keep-mach? (list (obj:name mach))))
608                               (current-mach-list))))
609     (not (all-true? (map (lambda (mach)
610                            (eq? (obj:name (mach-cpu mach))
611                                 (obj:name (mach-cpu (car selected-machs)))))
612                          selected-machs))))
613 )
614
615 ; Return a boolean indicating if everything is kept.
616
617 (define (keep-all?)
618   (equal? (reader-keep-mach CURRENT-READER) -keep-all-machs)
619 )
620
621 ; Ensure all cpu families were kept, necessary for generating files that
622 ; encompass the entire architecture.
623
624 (define (assert-keep-all)
625   (if (not (keep-all?))
626       (error "no can do, all cpu families not selected"))
627   *UNSPECIFIED*
628 )
629
630 ; Ensure exactly one cpu family was kept, necessary for generating files that
631 ; are specific to one cpu family.
632
633 (define (assert-keep-one)
634   (if (keep-multiple?)
635       (error "no can do, multiple cpu families selected"))
636   *UNSPECIFIED*
637 )
638 \f
639 ; `keep-isa' processing.
640
641 ; Cover proc to set `keep-isa'.
642 ; ISA-NAME-LIST is a comma separated string of isas to keep.
643 ; ??? We don't support the !drop notation of keep-mach processing.
644 ; Perhaps we should as otherwise there are two different styles the user
645 ; has to remember.  On the other hand, !drop support is moderately complicated,
646 ; and it can be added in an upward compatible manner later.
647
648 (define (-keep-isa-set! isa-name-list)
649   (let ((isa-name-list (map string->symbol (string-cut isa-name-list #\,))))
650     (reader-set-keep-isa! CURRENT-READER isa-name-list)
651     )
652   *UNSPECIFIED*
653 )
654
655 ; Validate the user-provided keep-isa list against the list of isas
656 ; specified in the .cpu file (in define-arch).
657
658 (define (keep-isa-validate!)
659   (let ((isa-names (cons 'all (current-arch-isa-name-list)))
660         (keep-isa (reader-keep-isa CURRENT-READER)))
661     (for-each (lambda (isa)
662                 (if (not (memq isa isa-names))
663                     (error "unknown isa to keep:" isa)))
664               keep-isa)
665     )
666   *UNSPECIFIED*
667 )
668
669 ; Return currently selected isa (there must be exactly one).
670
671 (define (current-isa)
672   (let ((keep-isa (reader-keep-isa CURRENT-READER)))
673     (if (equal? keep-isa '(all))
674         (let ((isas (current-isa-list)))
675           (if (= (length isas) 1)
676               (car isas)
677               (error "multiple isas selected" keep-isa)))
678         (if (= (length keep-isa) 1)
679             (current-isa-lookup (car keep-isa))
680             (error "multiple isas selected" keep-isa))))
681 )
682
683 ; Return #t if an isa in ISA-LIST, a list of symbols, is to be kept.
684 ; If any isa in ISA-LIST is to be kept, the result is #t.
685 ; If ISA-LIST is the empty list (no particular isa specified) use the default
686 ; isa.
687
688 (define (keep-isa? isa-list)
689   (if (null? isa-list)
690       (set! isa-list (list (car (current-arch-isa-name-list)))))
691   (let* ((keep (reader-keep-isa CURRENT-READER))
692          (keep? (map (lambda (i)
693                        (or (memq i keep)
694                            (memq 'all keep)))
695                      isa-list)))
696     (any-true? keep?))
697 )
698
699 ; Return #t if the object containing ATLIST is to be kept.
700 ; OBJ is the container object or #f if there is none.
701 ; The object is kept if its attribute list specifies an `ISA' that is
702 ; kept or does not have the `ISA' attribute (which means it has the default
703 ; value) and the default isa is being kept.
704
705 (define (keep-isa-atlist? atlist obj)
706   (let ((isas (atlist-attr-value atlist 'ISA obj)))
707     (keep-isa? (bitset-attr->list isas)))
708 )
709
710 ; Return non-#f if object OBJ is to be kept, according to its ISA attribute.
711
712 (define (keep-isa-obj? obj)
713   (keep-isa-atlist? (obj-atlist obj) obj)
714 )
715
716 ; Return a boolean indicating if multiple isas are being kept.
717
718 (define (keep-isa-multiple?)
719   (let ((keep (reader-keep-isa CURRENT-READER)))
720     (or (> (length keep) 1)
721         (and (memq 'all keep)
722              (> (length (current-arch-isa-name-list)) 1))))
723 )
724
725 ; Return list of isa names currently being kept.
726
727 (define (current-keep-isa-name-list)
728   (reader-keep-isa CURRENT-READER)
729 )
730 \f
731 ;; Tracing support.
732 ;; This is akin to the "logit" support, but is for specific things that
733 ;; can be named (whereas logit support is based on a simple integer verbosity
734 ;; level).
735
736 ;;; Enable the specified tracing.
737 ;;; TRACE-OPTIONS is a comma-separated list of things to trace.
738 ;;;
739 ;;; Currently supported tracing:
740 ;;; commands - trace invocation of description file commands (e.g. define-insn)
741 ;;; pmacros  - trace pmacro expansion
742 ;;; all      - trace everything
743 ;;;
744 ;;; [If we later need to support disabling some tracing, one way is to
745 ;;; recognize an "-" in front of an option.]
746
747 (define (-set-trace-options! trace-options)
748   (let ((all (list "commands" "pmacros"))
749         (requests (string-cut trace-options #\,)))
750     (if (member "all" requests)
751         (append! requests all))
752     (for-each (lambda (item)
753               (cond ((string=? "commands" item)
754                      (reader-set-trace-commands?! CURRENT-READER #t))
755                     ((string=? "pmacros" item)
756                      (reader-set-trace-pmacros?! CURRENT-READER #t))
757                     ((string=? "all" item)
758                      #t) ;; handled above
759                     (else
760                      (cgen-usage 'unknown (string-append "-t " item)
761                                  common-arguments))))
762               requests))
763
764   *UNSPECIFIED*
765 )
766 \f
767 ; If #f, treat reserved fields as operands and extract them with the insn.
768 ; Code can then be emitted in the extraction routines to validate them.
769 ; If #t, treat reserved fields as part of the opcode.
770 ; This complicates the decoding process as these fields have to be
771 ; checked too.
772 ; ??? Unimplemented.
773
774 (define option:reserved-as-opcode? #f)
775
776 ; Process options passed in on the command line.
777 ; OPTIONS is a space separated string of name=value values.
778 ; Each application is required to provide: option-init!, option-set!.
779
780 (define (set-cgen-options! options)
781   (option-init!)
782   (for-each (lambda (opt)
783               (if (null? opt)
784                   #t ; ignore extraneous spaces
785                   (let ((name (string->symbol (car opt)))
786                         (value (cdr opt)))
787                     (logit 1 "Setting option `" name "' to \""
788                            (apply string-append value) "\".\n")
789                     (option-set! name value))))
790             (map (lambda (opt) (string-cut opt #\=))
791                  (string-cut options #\space)))
792 )
793 \f
794 ; Application specific object creation support.
795 ;
796 ; Each entry in the .cpu file has a basic container class.
797 ; Each application adds functionality by subclassing the container
798 ; and registering with set-for-new! the proper class to create.
799 ; ??? Not sure this is the best way to handle this, but it does keep the
800 ; complexity down while not requiring as dynamic a language as I had before.
801 ; ??? Class local variables would provide a more efficient way to do this.
802 ; Assuming one wants to continue on this route.
803
804 (define -cpu-new-class-list nil)
805
806 (define (set-for-new! parent child)
807   (set! -cpu-new-class-list (acons parent child -cpu-new-class-list))
808 )
809
810 ; Lookup the class registered with set-for-new!
811 ; If none registered, return PARENT.
812
813 (define (lookup-for-new parent)
814   (let ((child (assq-ref -cpu-new-class-list parent)))
815     (if child
816         child
817         parent))
818 )
819 \f
820 ; .cpu file loader support
821
822 ;; Initialize a new <reader> object.
823 ;; This doesn't add cgen-specific commands, leaving each element (ifield,
824 ;; hardware, etc.) to add their own.
825 ;; The "result" is stored in global CURRENT-READER.
826
827 (define (-init-reader!)
828   (set! CURRENT-READER (new <reader>))
829
830   (reader-add-command! 'define-rtl-version
831                        "Specify the RTL version being used.\n"
832                        nil '(major minor) -cmd-define-rtl-version)
833
834   (reader-add-command! 'include
835                        "Include a file.\n"
836                        nil '(file) -cmd-include)
837   (reader-add-command! 'if
838                        "(if test then . else)\n"
839                        nil '(test then . else) -cmd-if)
840
841   ; Rather than add cgen-internal specific stuff to pmacros.scm, we create
842   ; the pmacro commands here.
843   (pmacros-init!)
844   (reader-add-command! 'define-pmacro
845                        "\
846 Define a preprocessor-style macro.
847 "
848                        nil '(name arg1 . arg-rest) define-pmacro)
849
850   *UNSPECIFIED*
851 )
852
853 ; Prepare to parse a .cpu file.
854 ; This initializes the application independent tables.
855 ; KEEP-MACH specifies what machs to keep.
856 ; KEEP-ISA specifies what isas to keep.
857 ; OPTIONS is a list of options to control code generation.
858 ; The values are application dependent.
859
860 (define (-init-parse-cpu! keep-mach keep-isa options)
861   (set! -cpu-new-class-list nil)
862
863   (set! CURRENT-ARCH (new <arch>))
864   (-keep-mach-set! keep-mach)
865   (-keep-isa-set! keep-isa)
866   (set-cgen-options! options)
867
868   ; The order here is important.
869   (arch-init!) ; Must be done first.
870   (enum-init!)
871   (attr-init!)
872   (types-init!)
873   (mach-init!)
874   (model-init!)
875   (mode-init!)
876   (ifield-init!)
877   (hardware-init!)
878   (operand-init!)
879   (insn-init!)
880   (minsn-init!)
881   (rtl-init!)
882   (rtl-c-init!)
883   (utils-init!)
884
885   *UNSPECIFIED*
886 )
887
888 ; Install any builtin objects.
889 ; This is deferred until define-arch is read.
890 ; One reason is that attributes MACH and ISA don't exist until then.
891
892 (define (reader-install-builtin!)
893   ; The order here is important.
894   (attr-builtin!)
895   (mode-builtin!)
896   (ifield-builtin!)
897   (hardware-builtin!)
898   (operand-builtin!)
899   ; This is mainly for the insn attributes.
900   (insn-builtin!)
901   (rtl-builtin!)
902   *UNSPECIFIED*
903 )
904
905 ; Do anything necessary for the application independent parts after parsing
906 ; a .cpu file.
907 ; The lists get cons'd in reverse order.  One thing this does is change them
908 ; back to file order, it makes things easier for the human viewer.
909
910 (define (-finish-parse-cpu!)
911   ; The order here is generally the reverse of init-parse-cpu!.
912   (rtl-finish!)
913   (minsn-finish!)
914   (insn-finish!)
915   (operand-finish!)
916   (hardware-finish!)
917   (ifield-finish!)
918   (mode-finish!)
919   (model-finish!)
920   (mach-finish!)
921   (types-finish!)
922   (attr-finish!)
923   (enum-finish!)
924   (arch-finish!) ; Must be done last.
925
926   *UNSPECIFIED*
927 )
928
929 ; Perform a global error checking pass after the .cpu file has been read in.
930
931 (define (-global-error-checks)
932   ; ??? None yet.
933   ; TODO:
934   ; - all hardware elements with same name must have same rank and
935   ;   compatible modes (which for now means same float mode or all int modes)
936   #f
937 )
938
939 ; .cpu file include mechanism
940
941 (define (-cmd-include file)
942   (logit 1 "Including file " (string-append arch-path "/" file) " ...\n")
943   (reader-read-file! (string-append arch-path "/" file))
944   (logit 2 "Resuming previous file ...\n")
945 )
946
947 ; Version of `if' invokable at the top level of a description file.
948 ; This is a work-in-progress.  Its presence in the description file is ok,
949 ; but the implementation will need to evolve.
950
951 (define (-cmd-if test then . else)
952   (if (> (length else) 1)
953       (parse-error #f
954                    "wrong number of arguments to `if'"
955                    (cons 'if (cons test (cons then else)))))
956   ; ??? rtx-eval test
957   (if (or (not (pair? test))
958           (not (memq (car test) '(keep-isa? keep-mach? application-is?))))
959       (parse-error #f
960                    "only (if (keep-mach?|keep-isa?|application-is? ...) ...) are currently supported"
961                    test))
962   (case (car test)
963     ((keep-isa?)
964      (if (keep-isa? (cadr test))
965          (reader-process-expanded! then)
966          (if (null? else)
967              #f
968              (reader-process-expanded! (car else)))))
969     ((keep-mach?)
970      (if (keep-mach? (cadr test))
971          (reader-process-expanded! then)
972          (if (null? else)
973              #f
974              (reader-process-expanded! (car else)))))
975     ((application-is?)
976      (if (eq? APPLICATION (cadr test))
977          (reader-process-expanded! then)
978          (if (null? else)
979              #f
980              (reader-process-expanded! (car else))))))
981 )
982
983 ; Top level routine for loading .cpu files.
984 ; FILE is the name of the .cpu file to load.
985 ; KEEP-MACH is a string of comma separated machines to keep
986 ; (or not keep if prefixed with !).
987 ; KEEP-ISA is a string of comma separated isas to keep.
988 ; OPTIONS is the OPTIONS argument to -init-parse-cpu!.
989 ; TRACE-OPTIONS is a random list of things to trace.
990 ; APP-INITER! is an application specific zero argument proc (thunk)
991 ; to call after -init-parse-cpu!
992 ; APP-FINISHER! is an application specific zero argument proc to call after
993 ; -finish-parse-cpu!
994 ; ANALYZER! is a zero argument proc to call after loading the .cpu file.
995 ; It is expected to set up various tables and things useful for the application
996 ; in question.
997 ;
998 ; This function isn't local because it's used by dev.scm.
999
1000 (define (cpu-load file keep-mach keep-isa options trace-options
1001                   app-initer! app-finisher! analyzer!)
1002   (-init-reader!)
1003   (-init-parse-cpu! keep-mach keep-isa options)
1004   (-set-trace-options! trace-options)
1005   (app-initer!)
1006   (logit 1 "Loading cpu description " file " ...\n")
1007   (set! arch-path (dirname file))
1008   (reader-read-file! file)
1009   (logit 2 "Processing cpu description " file " ...\n")
1010   (-finish-parse-cpu!)
1011   (app-finisher!)
1012   (-global-error-checks)
1013   (analyzer!)
1014   *UNSPECIFIED*
1015 )
1016 \f
1017 ; Argument parsing utilities.
1018
1019 ; Generate a usage message.
1020 ; ERRTYPE is one of 'help, 'unknown, 'missing.
1021 ; OPTION is the option that had the error or "" if ERRTYPE is 'help.
1022
1023 (define (cgen-usage errtype option arguments)
1024   (let ((cep (current-error-port)))
1025     (case errtype
1026       ((help) #f)
1027       ((unknown) (display (string-append "Unknown option: " option "\n") cep))
1028       ((missing) (display (string-append "Missing argument: " option "\n") cep))
1029       (else (display "Unknown error!\n" cep)))
1030     (display "Usage: cgen arguments ...\n" cep)
1031     (for-each (lambda (arg)
1032                 (display (string-append
1033                           (let ((arg-str (string-append (car arg) " "
1034                                                         (or (cadr arg) ""))))
1035                             (if (< (string-length arg-str) 16)
1036                                 (string-take 16 arg-str)
1037                                 arg-str))
1038                           "  - " (caddr arg)
1039                           (apply string-append
1040                                  (map (lambda (text)
1041                                         (string-append "\n"
1042                                                        (string-take 20 "")
1043                                                        text))
1044                                       (cdddr arg)))
1045                           "\n")
1046                          cep))
1047               arguments)
1048     (display "...\n" cep)
1049     (case errtype
1050       ((help) (quit 0))
1051       ((unknown missing) (quit 1))
1052       (else (quit 2))))
1053 )
1054
1055 ; Poor man's getopt.
1056 ; [We don't know where to find the real one until we've parsed the args,
1057 ; and this isn't something we need to get too fancy about anyways.]
1058 ; The result is always ((a . b) . c).
1059 ; If the argument is valid, the result is ((opt-spec . arg) . remaining-argv),
1060 ; or (('unknown . option) . remaining-argv) if `option' isn't recognized,
1061 ; or (('missing . option) . remaining argv) if `option' is missing a required
1062 ; argument,
1063 ; or ((#f . #f) . #f) if there are no more arguments.
1064 ; OPT-SPEC is a list of option specs.
1065 ; Each element is an alist of at least 3 elements: option argument help-text.
1066 ; `option' is a string or symbol naming the option.  e.g. -a, --help, "-i".
1067 ; symbols are supported for backward compatibility, -i is a complex number.
1068 ; `argument' is a string naming the argument or #f if the option takes no
1069 ; arguments.
1070 ; `help-text' is a string that is printed with the usage information.
1071 ; Elements beyond `help-text' are ignored.
1072
1073 (define (-getopt argv opt-spec)
1074   (if (null? argv)
1075       (cons (cons #f #f) #f)
1076       (let ((opt (assoc (car argv) opt-spec)))
1077         (cond ((not opt) (cons (cons 'unknown (car argv)) (cdr argv)))
1078               ((and (cadr opt) (null? (cdr argv)))
1079                (cons (cons 'missing (car argv)) (cdr argv)))
1080               ((cadr opt) (cons (cons opt (cadr argv)) (cddr argv)))
1081               (else ; must be option that doesn't take an argument
1082                (cons (cons opt #f) (cdr argv))))))
1083 )
1084
1085 ; Return (cadr args) or print a pretty error message if not possible.
1086
1087 (define (option-arg args)
1088   (if (and (pair? args) (pair? (cdr args)))
1089       (cadr args)
1090       (parse-error (make-prefix-context "option processing")
1091                    "missing argument to"
1092                    (car args)))
1093 )
1094
1095 ; List of common arguments.
1096 ;
1097 ; ??? Another useful arg would be one that says "do file generation with
1098 ; arguments specified up til now, then continue with next batch of args".
1099
1100 (define common-arguments
1101   '(("-a" "arch-file" "specify path of .cpu file to load")
1102     ("-b" #f          "use debugging evaluator, for backtraces")
1103     ("-d" #f          "start interactive debugging session")
1104     ("-f" "flags"     "specify a set of flags to control code generation")
1105     ("-h" #f          "print usage information")
1106     ("--help" #f      "print usage information")
1107     ("-i" "isa-list"  "specify isa-list entries to keep")
1108     ("-m" "mach-list" "specify mach-list entries to keep")
1109     ("-s" "srcdir"    "set srcdir")
1110     ("-t" "trace-options" "specify list of things to trace"
1111                        "Options:"
1112                        "commands - trace cgen commands (e.g. define-insn)"
1113                        "pmacros  - trace pmacro expansion"
1114                        "all      - trace everything")
1115     ("-v" #f          "increment verbosity level")
1116     ("--version" #f   "print version info")
1117     )
1118 )
1119
1120 ; Default place to look.
1121 ; This gets overridden to point to the directory of the loaded .cpu file.
1122 ; ??? Ideally this would be local to this file.
1123
1124 (define arch-path (string-append srcdir "/cpu"))
1125
1126 ; Accessors for application option specs
1127
1128 (define (opt-get-first-pass opt)
1129   (or (list-ref opt 3) (lambda args #f)))
1130 (define (opt-get-second-pass opt)
1131   (or (list-ref opt 4) (lambda args #f)))
1132
1133 ; Parse options and call generators.
1134 ; ARGS is a #:keyword delimited list of arguments.
1135 ; #:app-name name
1136 ; #:arg-spec optspec ; FIXME: rename to #:opt-spec
1137 ; #:init init-routine
1138 ; #:finish finish-routine
1139 ; #:analyze analysis-routine
1140 ; #:argv command-line-arguments
1141 ;
1142 ; ARGSPEC is a list of (option option-arg comment option-handler) elements.
1143 ; OPTION-HANDLER is either (lambda () ...) or (lambda (arg) ...) and
1144 ; processes the option.
1145
1146 (define -cgen
1147   (lambda args
1148     (let ((app-name "unknown")
1149           (opt-spec nil)
1150           (app-init! (lambda () #f))
1151           (app-finish! (lambda () #f))
1152           (app-analyze! (lambda () #f))
1153           (argv (list "cgen"))
1154           )
1155       (let loop ((args args))
1156         (if (not (null? args))
1157             (case (car args)
1158               ((#:app-name) (begin
1159                               (set! app-name (option-arg args))
1160                               (loop (cddr args))))
1161               ((#:arg-spec) (begin
1162                               (set! opt-spec (option-arg args))
1163                               (loop (cddr args))))
1164               ((#:init) (begin
1165                           (set! app-init! (option-arg args))
1166                           (loop (cddr args))))
1167               ((#:finish) (begin
1168                             (set! app-finish! (option-arg args))
1169                             (loop (cddr args))))
1170               ((#:analyze) (begin
1171                              (set! app-analyze! (option-arg args))
1172                              (loop (cddr args))))
1173               ((#:argv) (begin
1174                           (set! argv (option-arg args))
1175                           (loop (cddr args))))
1176               (else (error "cgen: unknown argument" (car args))))))
1177
1178       ; ARGS has been processed, now we can process ARGV.
1179
1180       (let (
1181             (opt-spec (append common-arguments opt-spec))
1182             (app-args nil)    ; application's args are queued here
1183             (repl? #f)
1184             (arch-file #f)
1185             (keep-mach "all") ; default is all machs
1186             (keep-isa "all")  ; default is all isas
1187             (flags "")
1188             (moreopts? #t)
1189             (debugging #f)    ; default is off, for speed
1190             (trace-options "")
1191             (cep (current-error-port))
1192             (str=? string=?)
1193             )
1194
1195         (let loop ((argv (cdr argv)))
1196           (let* ((new-argv (-getopt argv opt-spec))
1197                  (opt (caar new-argv))
1198                  (arg (cdar new-argv)))
1199             (case opt
1200               ((#f) (set! moreopts? #f))
1201               ((unknown) (cgen-usage 'unknown arg opt-spec))
1202               ((missing) (cgen-usage 'missing arg opt-spec))
1203               (else
1204                (cond ((str=? "-a" (car opt))
1205                       (set! arch-file arg)
1206                       )
1207                      ((str=? "-b" (car opt))
1208                       (set! debugging #t)
1209                       )
1210                      ((str=? "-d" (car opt))
1211                       (let ((prompt (string-append "cgen-" app-name "> ")))
1212                         (set! repl? #t)
1213                         (set-repl-prompt! prompt)
1214                         (if (feature? 'readline)
1215                             (set-readline-prompt! prompt))
1216                         ))
1217                      ((str=? "-f" (car opt))
1218                       (set! flags arg)
1219                       )
1220                      ((str=? "-h" (car opt))
1221                       (cgen-usage 'help "" opt-spec)
1222                       )
1223                      ((str=? "--help" (car opt))
1224                       (cgen-usage 'help "" opt-spec)
1225                       )
1226                      ((str=? "-i" (car opt))
1227                       (set! keep-isa arg)
1228                       )
1229                      ((str=? "-m" (car opt))
1230                       (set! keep-mach arg)
1231                       )
1232                      ((str=? "-s" (car opt))
1233                       #f ; ignore, already processed by caller
1234                       )
1235                      ((str=? "-t" (car opt))
1236                       (set! trace-options arg)
1237                       )
1238                      ((str=? "-v" (car opt))
1239                       (verbose-inc!)
1240                       )
1241                      ((str=? "--version" (car opt))
1242                       (begin
1243                         (display "Cpu tools GENerator version ")
1244                         (display (cgen-major))
1245                         (display ".")
1246                         (display (cgen-minor))
1247                         (display ".")
1248                         (display (cgen-fixlevel))
1249                         (newline)
1250                         (display "RTL version ")
1251                         (display (cgen-rtl-major))
1252                         (display ".")
1253                         (display (cgen-rtl-minor))
1254                         (newline)
1255                         (quit 0)
1256                         ))
1257                      ; Else this is an application specific option.
1258                      (else
1259                       ; Record it for later processing.  Note that they're
1260                       ; recorded in reverse order (easier).  This is undone
1261                       ; later.
1262                       (set! app-args (acons opt arg app-args)))
1263                      )))
1264             (if moreopts? (loop (cdr new-argv)))
1265             )
1266           ) ; end of loop
1267
1268         ; All arguments have been parsed.
1269
1270         (cgen-call-with-debugging
1271          debugging
1272          (lambda ()
1273
1274            (if (not arch-file)
1275                (error "-a option missing, no architecture specified"))
1276
1277            (if repl?
1278                (debug-repl nil))
1279
1280            (cpu-load arch-file
1281                      keep-mach keep-isa flags trace-options
1282                      app-init! app-finish! app-analyze!)
1283
1284            ;; Start another repl loop if -d.
1285            ;; Awkward.  Both places are useful, though this is more useful.
1286            (if repl?
1287                (debug-repl nil))
1288
1289            ;; Done with processing the arguments.  Application arguments
1290            ;; are processed in two passes.  This is because the app may
1291            ;; have arguments that specify things that affect file
1292            ;; generation (e.g. to specify another input file) and we
1293            ;; don't want to require an ordering of the options.
1294            (for-each (lambda (opt-arg)
1295                        (let ((opt (car opt-arg))
1296                              (arg (cdr opt-arg)))
1297                          (if (cadr opt)
1298                              ((opt-get-first-pass opt) arg)
1299                              ((opt-get-first-pass opt)))))
1300                      (reverse app-args))
1301
1302            (for-each (lambda (opt-arg)
1303                        (let ((opt (car opt-arg))
1304                              (arg (cdr opt-arg)))
1305                          (if (cadr opt)
1306                              ((opt-get-second-pass opt) arg)
1307                              ((opt-get-second-pass opt)))))
1308                      (reverse app-args))))
1309         )
1310       )
1311     #f) ; end of lambda
1312 )
1313
1314 ; Main entry point called by application file generators.
1315
1316 (define cgen
1317   (lambda args
1318     (cgen-debugging-stack-start -cgen args))
1319 )