mescc: Have micro-mes use strcmp to print help.
[mes.git] / module / language / c99 / compiler.mes
1 ;;; -*-scheme-*-
2
3 ;;; Mes --- Maxwell Equations of Software
4 ;;; Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;;
6 ;;; This file is part of Mes.
7 ;;;
8 ;;; Mes is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
12 ;;;
13 ;;; Mes is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;;; GNU General Public License for more details.
17 ;;;
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with Mes.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;;; compiler.mes produces an i386 binary from the C produced by
24 ;;; Nyacc c99.
25
26 ;;; Code:
27
28 (cond-expand
29  (guile-2
30   (set-port-encoding! (current-output-port) "ISO-8859-1"))
31  (guile)
32  (mes
33   (mes-use-module (nyacc lang c99 parser))
34   (mes-use-module (mes elf-util))
35   (mes-use-module (mes pmatch))
36   (mes-use-module (mes elf))
37   (mes-use-module (mes libc-i386))
38   (mes-use-module (mes optargs))))
39
40 (define (logf port string . rest)
41   (apply format (cons* port string rest))
42   (force-output port)
43   #t)
44
45 (define (stderr string . rest)
46   (apply logf (cons* (current-error-port) string rest)))
47
48 (define (gnuc-xdef? name mode) (if (equal? name "__GNUC__") #f (eq? mode 'code)))
49
50 (define (mescc)
51   (parse-c99
52    #:inc-dirs (string-split (getenv "C_INCLUDE_PATH") #\:)
53    #:cpp-defs '(
54                 ("__GNUC__" . "0")
55                 ("__NYACC__" . "1")
56                 ("VERSION" . "0.4")
57                 ("PREFIX" . "")
58                 )
59    #:xdef? gnuc-xdef?
60    #:mode 'code
61    ))
62
63 (define (write-any x)
64   (write-char (cond ((char? x) x)
65                     ((number? x) (integer->char (if (>= x 0) x (+ x 256))))
66                     (else (stderr "write-any: ~a\n" x) barf))))
67
68 (define (ast:function? o)
69   (and (pair? o) (eq? (car o) 'fctn-defn)))
70
71 (define (.name o)
72   (pmatch o
73     ((fctn-defn _ (ftn-declr (ident ,name) _) _) name)
74     ((fctn-defn _ (ptr-declr (pointer) (ftn-declr (ident ,name) _)) _) name)
75     ((param-decl _ (param-declr (ident ,name))) name)
76     ((param-decl _ (param-declr (ptr-declr (pointer) (ident ,name)))) name)
77     ((param-decl _ (param-declr (ptr-declr (pointer) (array-of (ident ,name))))) name)
78     (_
79      (format (current-error-port) "SKIP .name =~a\n" o))))
80
81 (define (.statements o)
82   (pmatch o
83     ((fctn-defn _ (ftn-declr (ident ,name) _) (compd-stmt (block-item-list . ,statements))) statements)
84     ((fctn-defn _ (ptr-declr (pointer) (ftn-declr (ident ,name) _)) (compd-stmt (block-item-list . ,statements))) statements)))
85
86 (define <info> '<info>)
87 (define <functions> '<functions>)
88 (define <globals> '<globals>)
89 (define <locals> '<locals>)
90 (define <text> '<text>)
91 (define* (make o #:key (functions '()) (globals '()) (locals '()) (text '()))
92   (pmatch o
93     (<info> (list <info>
94                   (cons <functions> functions)
95                   (cons <globals> globals)
96                   (cons <locals> locals)
97                   (cons <text> text)))))
98
99 (define (.functions o)
100   (pmatch o
101     ((<info> . ,alist) (assq-ref alist <functions>))))
102
103 (define (.globals o)
104   (pmatch o
105     ((<info> . ,alist) (assq-ref alist <globals>))))
106
107 (define (.locals o)
108   (pmatch o
109     ((<info> . ,alist) (assq-ref alist <locals>))))
110
111 (define (.text o)
112   (pmatch o
113     ((<info> . ,alist) (assq-ref alist <text>))))
114
115 (define (info? o)
116   (and (pair? o) (eq? (car o) <info>)))
117
118 (define (clone o . rest)
119   (cond ((info? o)
120          (let ((functions (.functions o))
121                (globals (.globals o))
122                (locals (.locals o))
123                (text (.text o)))
124            (let-keywords rest
125                          #f
126                          ((functions functions)
127                           (globals globals)
128                           (locals locals)
129                           (text text))
130                          (make <info> #:functions functions #:globals globals #:locals locals #:text text))))))
131
132 (define (ref-local locals)
133   (lambda (o)
134     ;; (stderr "IDENT REF[~a]: ~a => ~a\n" o (assoc-ref locals o) (i386:ref-local (assoc-ref locals o)))
135     (i386:ref-local (assoc-ref locals o))))
136
137 (define (ref-global globals)
138   (lambda (o)
139     (lambda (f g t d)
140       (i386:ref-global (+ (data-offset o g;;lobals
141                                        ) d)))))
142
143 (define (expr->arg globals locals) ;; FIXME: get Mes curried-definitions
144   (lambda (o)
145     (pmatch o
146       ((p-expr (fixed ,value)) (string->number value))
147       ((p-expr (string ,string)) ((ref-global globals) string))
148       ((p-expr (ident ,name)) ((ref-local locals) name))
149
150       ((array-ref (p-expr (fixed ,value)) (p-expr (ident ,name)))
151        (let ((value (string->number value))
152              (size 4)) ;; FIXME: type: int
153          (lambda (f g t d)
154            (append
155             ((ident->base locals) name)
156             (i386:value->accu (* size value)) ;; FIXME: type: int
157             (i386:mem->accu) ;; FIXME: type: int
158             (i386:push-accu) ;; hmm
159             ))))
160
161       (_
162        (format (current-error-port) "SKIP expr->arg=~a\n" o)     
163        0))))
164
165 (define (ident->accu locals)
166   (lambda (o)
167     (i386:local->accu (assoc-ref locals o))))
168
169 (define (accu->ident locals)
170   (lambda (o)
171     (i386:accu->local (assoc-ref locals o))))
172
173 (define (ident->base locals)
174   (lambda (o)
175     (i386:local->base (assoc-ref locals o))))
176
177 (define (expr->accu info)
178   (lambda (o)
179     (pmatch o
180       ((p-expr (fixed ,value)) (string->number value))
181       ((p-expr (ident ,name)) ((ident->accu (.locals info)) name))
182       ((fctn-call . _) ((ast->info info) `(expr-stmt ,o)))
183       ((sub . _) ((ast->info info) o)) ;; FIXME: expr-stmt
184       (_
185        (format (current-error-port) "SKIP expr->accu=~a\n" o)
186        0)
187       )))
188
189 (define (string->global string)
190   (cons string (append (string->list string) (list #\nul))))
191
192 (define (expr->global o)
193   (pmatch o
194     ((p-expr (string ,string)) (string->global string))
195     (_ #f)))
196
197 (define (dec->hex o)
198   (number->string o 16))
199
200 (define (byte->hex o)
201   (string->number (string-drop o 2) 16))
202
203 (define (asm->hex o)
204   (let ((prefix ".byte "))
205     (if (not (string-prefix? prefix o)) (begin (stderr "SKIP:~a\n" o)'())
206         (let ((s (string-drop o (string-length prefix))))
207           (map byte->hex (string-split s #\space))))))
208
209 (define (ast->info info)
210   (lambda (o)
211     (let ((globals (.globals info))
212           (locals (.locals info))
213           (text (.text info)))
214       (define (add-local name)
215          (acons name (1+ (or (and=> (member 1 (map cdr locals)) length) 0)) locals))
216
217       ;; (stderr "S=~a\n" o)
218       ;; (stderr "   info=~a\n" info)
219       ;; (stderr "   globals=~a\n" globals)
220       (pmatch o
221         (((trans-unit . _) . _) ((ast-list->info info) o))
222         ((trans-unit . ,elements) ((ast-list->info info) elements))
223         ((fctn-defn . _) ((function->info info) o))
224         ((comment . _) info)
225         ((cpp-stmt (define (name ,name) (repl ,value)))
226          (stderr "SKIP: #define ~s ~s\n" name value)
227          info)
228
229         ((compd-stmt (block-item-list . ,statements)) ((ast-list->info info) statements))
230         
231         ((expr-stmt (fctn-call (p-expr (ident ,name))
232                                (expr-list (p-expr (string ,string)))))
233          ;;(stderr "S1 string=~a\n" string)
234          (if (equal? name "asm") (clone info #:text (append text (list (lambda (f g t d) (asm->hex string)))))
235              (let ((globals (append globals (list (string->global string)))))
236                (clone info #:text
237                       (append text (list (lambda (f g t d)
238                                            (i386:call f g t d
239                                                       (+ t (function-offset name f))
240                                                       (+ d (data-offset string g))))))
241                       #:globals globals))))
242         
243         ((expr-stmt (fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)))
244          ;;(stderr "S1 expr-list=~a\n" expr-list)
245          (let* ((globals (append globals (filter-map expr->global expr-list)))
246                 (args (map (expr->arg globals locals) expr-list)))
247            (clone info #:text
248                   (append text (list (lambda (f g t d)
249                                        (apply i386:call (cons* f g t d
250                                                                (+ t (function-offset name f)) args)))))
251                   #:globals globals)))
252
253         ((if (gt (p-expr (ident ,name)) (p-expr (fixed ,value))) ,body)
254          (let* ((value (string->number value))
255                 (info (clone info #:text '()))
256                 (body-info ((ast->info info) body))
257                 (body-text (.text body-info))
258                 (body-length (length (text->list body-text))))
259
260            (clone info #:text
261                   (append text
262                           (list (lambda (f g t d)
263                                   (append
264                                    (i386:local-test (assoc-ref locals name) value)
265                                    (i386:jump-le body-length))))
266                           body-text)
267                   #:globals (.globals body-info))))
268
269         ((if (not (fctn-call . ,call)) ,body)
270          (let* ((call-info ((ast->info info) `(expr-stmt (fctn-call . ,call))))
271                 (info (clone info #:text '()))
272                 (body-info ((ast->info info) body))
273                 (body-text (.text body-info))
274                 (body-length (length (text->list body-text))))
275
276            (clone info #:text
277                   (append (.text call-info)
278                           (list (lambda (f g t d)
279                                   (append
280                                    ;;(i386:local-test (assoc-ref locals name) 0)
281                                    ;;(i386:accu-test (assoc-ref locals name) 0)
282                                    (i386:jump-nz body-length))))
283                           body-text)
284                   #:globals (append (.globals call-info)
285                                     (.globals body-info)))))
286
287         (;;(for ,init ,test ,step ,body)
288          (for ,init
289               ;; FIXME: ,test
290               (lt (p-expr (ident ,name)) (p-expr (fixed ,value)))
291               ,step ,body)
292          (let* ((value (string->number value))
293                 (info (clone info #:text '()))
294
295                 (info ((ast->info info) init))
296
297                 (init-text (.text info))
298                 (init-locals (.locals info))
299                 (info (clone info #:text '()))
300
301                 (body-info ((ast->info info) body))
302                 (body-text (.text body-info))
303                 (body-length (length (text->list body-text)))
304
305                 (step-info ((ast->info info) `(expr-stmt ,step)))
306                 (step-text (.text step-info))
307                 (step-length (length (text->list step-text)))
308
309                 ;; (test-info ((ast->info info) test))
310                 ;; (test-text (.text test-info))
311                 ;; (test-length (length (text->list test-text)))
312                 )
313
314            (clone info #:text
315                   (append text
316                           init-text
317                           (list (lambda (f g t d) (i386:jump body-length)))
318                           body-text
319                           step-text
320                           ;;test-text
321                           ;;(list (lambda (f g t d) (i386:jump-byte-nz (- (+ body-length test-length)))))
322                           (list (lambda (f g t d)
323                                   (append
324                                    (i386:local-test (assoc-ref init-locals name) value)
325                                    (i386:jump-le (- (+ body-length step-length 2) ;;test-length
326                                                     )))))
327                           )
328                   #:globals (append globals (.globals body-info))
329                   #:locals locals)))
330
331         ((while ,test ,body)
332          (let* ((info (clone info #:text '()))
333                 (body-info ((ast->info info) body))
334                 (body-text (.text body-info))
335                 (body-length (length (text->list body-text)))
336
337                 (test-info ((ast->info info) test))
338                 (test-text (.text test-info))
339                 (test-length (length (text->list test-text))))
340
341            (clone info #:text
342                   (append text
343                           (list (lambda (f g t d) (i386:jump body-length)))
344                           body-text
345                           test-text
346                           (list (lambda (f g t d) (i386:jump-byte-nz (- (+ body-length test-length))))))
347                   #:globals (append globals (.globals body-info)))))
348
349         ;;(and (and (de-ref (p-expr (ident "a"))) (de-ref (p-expr (ident "b")))) (eq (de-ref (p-expr (ident "a"))) (de-ref (p-expr (ident "b")))))
350         
351         ((de-ref (p-expr (ident ,name)))
352          (clone info #:text
353                 (append text
354                         (list (lambda (f g t d)
355                                 (append (i386:local->accu (assoc-ref locals name))
356                                         (i386:Xmem-byte->accu)))))))
357
358         ((and ,a ,b)
359          (let* ((info (clone info #:text '()))
360                 (a-info ((ast->info info) a))
361                 (a-text (.text a-info))
362                 (a-length (length (text->list a-text)))
363
364                 (b-info ((ast->info info) b))
365                 (b-text (.text b-info))
366                 (b-length (length (text->list b-text))))
367
368            (clone info #:text
369                   (append text
370                           a-text
371                           (list (lambda (f g t d) (i386:jump-byte-z (+ b-length
372                                                                        2))))  ;; FIXME: need jump after last test
373                           b-text))))
374
375         ((eq (de-ref (p-expr (ident ,a))) (de-ref (p-expr (ident ,b))))
376            (clone info #:text
377                   (append text
378                           (list (lambda (f g t d)
379                                   (append
380                                    (append (i386:local->accu (assoc-ref locals a))
381                                            (i386:Xmem-byte->base)
382                                            (i386:local->accu (assoc-ref locals b))
383                                            (i386:Xmem-byte->accu)
384                                            (i386:test-byte-base))))))))
385
386         ((sub (de-ref (p-expr (ident ,a))) (de-ref (p-expr (ident ,b))))
387          (clone info #:text
388                 (append text
389                         (list (lambda (f g t d)
390                                 (append (i386:local->accu (assoc-ref locals a))
391                                         (i386:Xmem-byte->base)
392                                         (i386:local->accu (assoc-ref locals b))
393                                         (i386:Xmem-byte->accu)
394                                         (i386:sub-byte-base)))))))
395
396         ((array-ref (p-expr (fixed ,value)) (p-expr (ident ,name)))
397          (let ((value (string->number value)))
398            (clone info #:text
399                   (append text (list (lambda (f g t d)
400                                        (append
401                                         ((ident->base locals) name)
402                                         (i386:value->accu value)
403                                         (i386:mem-byte->accu)))))))) ; FIXME: type: char
404         
405         ((array-ref (p-expr (ident ,name)) (p-expr (ident ,index)))
406          (clone info #:text
407                 (append text (list (lambda (f g t d)
408                                      (append
409                                       ((ident->base locals) name)
410                                       ((ident->accu locals) index)
411                                       (i386:mem-byte->accu))))))) ; FIXME: type: char
412         
413         ;; i++
414         ((expr-stmt (post-inc (p-expr (ident ,name))))
415          (clone info #:text
416                 (append text (list (lambda (f g t d)
417                                      (i386:local-add (assoc-ref locals name) 1))))))
418
419         ;; ++i -- same for now FIXME
420         ((expr-stmt (pre-inc (p-expr (ident ,name))))
421          (clone info #:text
422                 (append text (list (lambda (f g t d)
423                                      (i386:local-add (assoc-ref locals name) 1))))))
424
425         ((return ,expr)
426          (let ((accu ((expr->accu info) expr)))
427            (if (info? accu)
428                (clone accu #:text
429                       (append (.text accu) (list (i386:ret (lambda _ '())))))
430                (clone info #:text
431                       (append text (list (i386:ret ((expr->accu info) expr))))))))
432
433         ;; int i;
434         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name))))
435          (clone info #:locals (add-local name)))
436
437         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (fixed ,value))))))
438          (let ((locals (add-local name)))
439            (let ((value (string->number value)))
440              (clone info #:text
441                     (append text (list (lambda (f g t d)
442                                        (i386:local-assign (assoc-ref locals name) value))))
443                   #:locals locals))))
444
445         ;; int i = argc;
446         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (ident ,local))))))
447          (let ((locals (add-local name)))
448           (clone info #:text
449                  (append text (list (lambda (f g t d)
450                                       (append
451                                        ((ident->accu locals) local)
452                                        ((accu->ident locals) name)))))
453                  #:locals locals)))
454
455         ;; SCM i = argc;
456         ((decl (decl-spec-list (type-spec (typename ,type))) (init-declr-list (init-declr (ident ,name) (initzer (p-expr (ident ,local))))))
457          (let ((locals (add-local name)))
458            (clone info #:text
459                 (append text (list (lambda (f g t d)
460                                      (append
461                                       ((ident->accu locals) local)
462                                       ((accu->ident locals) name)))))
463                 #:locals locals)))
464         
465         ;; int i = f ();
466         ((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ident ,name) (initzer (fctn-call . ,call)))))
467          (let* ((locals (add-local name))
468                 (info (clone info #:locals locals)))
469            (let ((info ((ast->info info) `(expr-stmt (fctn-call ,@call)))))
470              (clone info
471                     #:text
472                     (append (.text info)
473                             (list (lambda (f g t d)
474                                     (i386:ret-local (assoc-ref locals name)))))
475                     #:locals locals))))
476         
477         ;; i = 0;
478         ((expr-stmt (assn-expr (p-expr (ident ,name)) (op _) (p-expr (fixed ,value))))
479          ;;(stderr "RET LOCAL[~a]: ~a\n" name (assoc-ref locals name))
480          (let ((value (string->number value)))
481            (clone info #:text (append text (list (lambda (f g t d) (i386:local-assign (assoc-ref locals name) value)))))))
482         
483         ((expr-stmt (assn-expr (p-expr (ident ,name)) (op _) (fctn-call . ,call)))
484          (let* ((info ((ast->info info) `(expr-stmt (fctn-call ,@call)))))
485            (clone info #:text (append (.text info) (list (lambda (f g t d) (i386:ret-local (assoc-ref locals name))))))))
486
487         (_
488          (format (current-error-port) "SKIP statement=~s\n" o)
489          info)))))
490
491 (define (info->exe info)
492   (display "dumping elf\n" (current-error-port))
493   (map write-any (make-elf (.functions info) (.globals info))))
494
495 (define (.formals o)
496   (pmatch o
497     ((fctn-defn _ (ftn-declr _ ,formals) _) formals)
498     ((fctn-defn _ (ptr-declr (pointer) (ftn-declr _ ,formals)) _) formals)
499     (_ (format (current-error-port) ".formals: no match: ~a\n" o)
500        barf)))
501
502 (define (formal->text n)
503   (lambda (o i)
504     ;;(i386:formal i n)
505     '()
506     ))
507
508 (define (formals->text o)
509   (pmatch o
510     ((param-list . ,formals)
511      (let ((n (length formals)))
512        (list (lambda (f g t d)
513                (append
514                 (i386:function-preamble)
515                 (append-map (formal->text n) formals (iota n))
516                 (i386:function-locals))))))
517     (_ (format (current-error-port) "formals->text: no match: ~a\n" o)
518        barf)))
519
520 (define (formals->locals o)
521   (pmatch o
522     ((param-list . ,formals)
523      (let ((n (length formals)))
524        ;;(stderr "FORMALS: ~a ==> ~a\n" formals n)
525        (map cons (map .name formals) (iota n -2 -1))))
526     (_ (format (current-error-port) "formals->info: no match: ~a\n" o)
527        barf)))
528
529 (define (function->info info)
530   (lambda (o)
531     ;;(stderr "\n")
532     (format (current-error-port) "compiling ~a\n" (.name o))
533     ;;(stderr "formals=~a\n" (.formals o))
534     (let* ((text (formals->text (.formals o)))
535            (locals (formals->locals (.formals o))))
536       ;;(stderr "locals=~a\n" locals)
537       (let loop ((statements (.statements o))
538                  (info (clone info #:locals locals #:text text)))
539         (if (null? statements) (clone info
540                                       #:functions (append (.functions info) (list (cons (.name o) (.text info)))))
541             (let* ((statement (car statements)))
542               (loop (cdr statements) ((ast->info info) (car statements)))))))))
543
544 (define (ast-list->info info)
545   (lambda (elements)
546     (let loop ((elements elements) (info info))
547       (if (null? elements) info
548           (loop (cdr elements) ((ast->info info) (car elements)))))))
549
550 (define _start
551   (let* ((argc-argv
552           (string-append ".byte"
553                          " 0x89 0xe8"      ; mov    %ebp,%eax
554                          " 0x83 0xc0 0x08" ; add    $0x8,%eax
555                          " 0x50"           ; push   %eax
556                          " 0x89 0xe8"      ; mov    %ebp,%eax
557                          " 0x83 0xc0 0x04" ; add    $0x4,%eax
558                          " 0x0f 0xb6 0x00" ; movzbl (%eax),%eax
559                          " 0x50"           ; push   %eax
560                          ))
561          (ast (with-input-from-string
562                   
563                   (string-append "int _start () {int i;asm(\"" argc-argv "\");i=main ();exit (i);}")
564                 parse-c99)))
565     ast))
566
567 (define strlen
568   (let* ((ast (with-input-from-string
569                   "
570 int
571 strlen (char const* s)
572 {
573   int i = 0;
574   while (s[i]) i++;
575   return i;
576 }
577 "
578 ;;paredit:"
579                 parse-c99)))
580     ast))
581
582 (define eputs
583   (let* ((ast (with-input-from-string
584                   "
585 int
586 eputs (char const* s)
587 {
588   //write (STDERR, s, strlen (s));
589   //write (2, s, strlen (s));
590   int i = strlen (s);
591   write (2, s, i);
592   return 0;
593 }
594 "
595 ;;paredit:"
596                 parse-c99)))
597     ast))
598
599 (define fputs
600   (let* ((ast (with-input-from-string
601                   "
602 int
603 fputs (char const* s, int fd)
604 {
605  int i = strlen (s);
606   write (fd, s, i);
607   return 0;
608 }
609 "
610 ;;paredit:"
611                 parse-c99)))
612     ast))
613
614 (define puts
615   (let* ((ast (with-input-from-string
616                   "
617 int
618 puts (char const* s)
619 {
620   //write (STDOUT, s, strlen (s));
621   //int i = write (STDOUT, s, strlen (s));
622   int i = strlen (s);
623   write (1, s, i);
624   return 0;
625 }
626 "
627 ;;paredit:"
628                 parse-c99)))
629     ast))
630
631 (define strcmp
632   (let* ((ast (with-input-from-string
633                   "
634 int
635 strcmp (char const* a, char const* b)
636 {
637   while (*a && *b && *a == *b) 
638     {
639       a++;b++;
640     }
641   return *a - *b;
642 }
643 "
644 ;;paredit:"
645                 parse-c99)))
646     ast))
647
648 (define i386:libc
649   (list
650    (cons "exit" (list i386:exit))
651    (cons "write" (list i386:write))))
652
653 (define libc
654   (list
655    strlen
656    eputs
657    fputs
658    puts
659    strcmp))
660
661 (define (compile)
662   (let* ((ast (mescc))
663          (info (make <info> #:functions i386:libc))
664          (info ((ast->info info) libc))
665          (info ((ast->info info) ast))
666          (info ((ast->info info) _start)))
667     (info->exe info)))