~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to comp/inline.lsp

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(in-package "BCOMP")
 
2
 
 
3
(eval-when (compile load eval)
 
4
 
 
5
(defmacro opt (key opt)
 
6
  `(nth ,(position key '(args return flag template )) ,opt))
 
7
)
 
8
(eval-when (eval compile load)
 
9
 
 
10
(defun flags-pos (flag &aux (i 0))
 
11
  (declare (fixnum i))
 
12
  (dolist  (v *flags*)
 
13
    (cond ((member flag v :test 'eq)
 
14
           (return-from flags-pos i)))
 
15
    (setq i (+ i 1)))
 
16
  (error "unknown opt flag"))
 
17
 
 
18
 
 
19
(defvar *flags*
 
20
  '((allocates-new-storage ans)         ; might invoke gbc
 
21
    (side-effect-p set)                 ; no effect on arguments
 
22
    (constantp)                         ; always returns same result,
 
23
                                        ;double eval ok.
 
24
    (result-type-from-args rfa)         ; if passed args of matching
 
25
                                        ;type result is of result type
 
26
    (is);; extends the `integer stack'.
 
27
    (mv);; in a declaration, function may return MV.
 
28
    (safe);; can be used at safety 3
 
29
    (notinline)
 
30
    (touch-mv);;Invoking this may alter the MV locations.
 
31
    (not-1-val) ;; obsoluete
 
32
    (proclaim) ; do a proclaim.
 
33
    ))
 
34
)
 
35
(defmacro flags (&rest lis &aux (i 0))
 
36
  (dolist (v lis)
 
37
    (setq i (logior  i (ash 1 (flags-pos v)))))
 
38
  i)
 
39
 
 
40
 
 
41
(defun print-flag (n &optional safe)
 
42
  (princ "#.(flags")
 
43
  (dotimes (i (length *flags*))
 
44
           (if (logbitp i n) (format t " ~(~s~)"(car (last (nth i *flags*))) )))
 
45
  (if safe (princ " safe"))
 
46
  (princ ")")
 
47
  n)
 
48
;#+assist
 
49
(progn
 
50
  ;; Convert old AKCL opts.
 
51
 
 
52
(defun print-opt (sym prop &aux tem )
 
53
  (unless (get 'compiler::boolean 'comp-type)
 
54
          (setf (get 'compiler::boolean 'comp-type) 'boolean)
 
55
          (setf (get :dynamic-extent 'comp-type) 'dynamic-extent)
 
56
          (setf (get 'compiler::fixnum-float 'comp-type) 'fix-or-sf-or-df))
 
57
  (cond ((setq tem (get sym prop))
 
58
         (format t "~%(defopt ~s" sym)
 
59
         (let ((*print-case* :downcase))
 
60
           (dolist (v (reverse tem))
 
61
             (format t "~% (~s ~s " (mapcar 'comp-type (car v))
 
62
                     (comp-type (second v)))
 
63
             (print-flag (third v) (eq prop 'compiler::inline-always))
 
64
             (format t " ~s)"
 
65
                     (if (stringp (fourth v))
 
66
                         (substitute #\$ #\# (fourth v))
 
67
                       (fourth v)))))
 
68
         (princ ")"))))
 
69
 
 
70
(defun convert-old (&rest props &aux syms)
 
71
  (sloop for pack in '(lisp si compiler)
 
72
     do
 
73
     (sloop for v in-package pack
 
74
        when   (sloop for w in props when (get v w) return t)
 
75
        do (push v syms)))
 
76
  (setq syms (sort syms #'(lambda (x y) (string-lessp (symbol-name x)
 
77
                                                      (symbol-name y)))))
 
78
  (sloop for v in syms
 
79
     do (sloop for w in props
 
80
           do (print-opt v w))))
 
81
 
 
82
;(with-open-file (*standard-output* "/tmp/opts1.lsp" :direction :output)  (convert-old 'compiler::inline-always 'compiler::inline-unsafe))
 
83
;(load "/tmp/opts.lsp")
 
84
;(with-open-file (*standard-output* "/tmp/opts.lsp" :direction :output)  (convert-old 'bcomp-opt))
 
85
 
 
86
)
 
87
 
 
88
(defmacro defopt (fname &rest l)
 
89
  ;; adds additional opts to the front.
 
90
  ;; last added is most significant.
 
91
  `(defopt1 ',fname ',l))
 
92
(defun defopt1 (fname l)
 
93
  (dolist (v l)
 
94
    (let ((fl (opt flag v)))
 
95
      (cond ((flag-p fl proclaim)
 
96
             (proclaim1 `(ftype (function ,(opt args v) ,(opt return v)) ,fname)))))
 
97
    (push v (get fname 'bcomp-opt))))
 
98
 
 
99
(defmacro flag-p (n flag)
 
100
  `(logbitp ,(flags-pos  flag)  ,n))
 
101
 
 
102
(setf (get 'aref 'coerce-arg-types) '(t fixnum fixnum fixnum fixnum))
 
103
(setf (get 'si::aset1 'coerce-arg-types) '(t fixnum ))
 
104
 
 
105
 
 
106
 
 
107
(defun get-inline-template (fname fdecl arg-types ret-type type-wanted  
 
108
                                  &aux lis  opt-ret tem
 
109
                                  (opt-flag 0)
 
110
                                  (mask (if (> *safety* 0) ;*unsafe*
 
111
                                            #.(flags safe)
 
112
                                          #.(flags))))
 
113
  (declare (fixnum mask opt-flag))
 
114
  (or (symbolp fname) (wfs-error))
 
115
  (setq lis (get fname 'bcomp-opt))
 
116
  (or lis (return-from get-inline-template nil))
 
117
  (cond ((eq type-wanted 'mv)
 
118
         (setq type-wanted t) 
 
119
         (unless
 
120
          (and fdecl (not (flag-p (second fdecl) mv)))
 
121
                                        ;function proclaimed to return 1 arg
 
122
          (setq mask (logior mask #. (flags mv)
 
123
                              )))))
 
124
  (when (setq tem (get fname 'coerce-arg-types))
 
125
    (sloop for v on arg-types
 
126
       for w in tem
 
127
       unless (eq w t) do (setf (car v) (type-and (car v) w))))
 
128
  (if (member type-wanted *immediate-types*)
 
129
      (setq ret-type type-wanted))
 
130
  (sloop for opt in lis
 
131
     do
 
132
     (setq opt-ret (opt return opt))
 
133
     (setq opt-flag (opt flag opt))
 
134
     ;; check return return matches
 
135
     do
 
136
     (when
 
137
         (and
 
138
          (eql mask (logand opt-flag mask))
 
139
          (or (eql opt-ret t)
 
140
              (eql opt-ret '*)
 
141
              (comp-subtypep ret-type opt-ret)))
 
142
       (sloop
 
143
          for v on arg-types
 
144
          for w on (opt args opt)
 
145
          do
 
146
          (cond ((eq (car w) '*)
 
147
                 (return-from get-inline-template opt))
 
148
                ((or (comp-subtypep (car v) (car w)) (return nil))))
 
149
          finally
 
150
          (cond ((eq (car w) '*)
 
151
                 (return-from get-inline-template opt))
 
152
                ((and (null v) (null w))
 
153
                 (return-from get-inline-template opt))))))
 
154
  )
 
155
 
 
156
(defun result-from-args (sym argl &aux arg-types)
 
157
  (let ((tem (get sym 'bcomp-opt)))
 
158
    (when tem
 
159
      (sloop for opt in tem
 
160
         when (flag-p (opt flag opt) rfa)
 
161
         do (or arg-types (setq arg-types (mapcar 'result-type argl)))
 
162
         (sloop
 
163
            for v on arg-types
 
164
            for w on (opt args opt)
 
165
            do
 
166
            (cond ((eq (car w) '*)
 
167
                   (return-from result-from-args (opt return opt)))
 
168
                  ((or (subtypep (car v) (car w)) (return nil))))
 
169
            finally
 
170
            (cond ((eq (car w) '*)
 
171
                   (return-from result-from-args (opt return opt))
 
172
                   )
 
173
                  ((and (null v) (null w))
 
174
                   (return-from result-from-args (opt return opt))
 
175
                   ))))
 
176
      (cond ((get sym 'arithmetic-contagion)
 
177
             (or arg-types (setq arg-types (mapcar 'result-type argl)))
 
178
             (setq tem
 
179
                   (or (member 'double-float arg-types )
 
180
                       (member 'short-float arg-types)))
 
181
             (if (and tem (sloop for v in arg-types
 
182
                             always (or (subtypep v 'fixnum)
 
183
                                        (subtypep v 'double-float)
 
184
                                        (subtypep v 'short-float))))
 
185
                 (return-from result-from-args (car tem)))
 
186
             )))))
 
187
 
 
188
(dolist (v '(* + - 1- 1+ /)) (setf (get v 'arithmetic-contagion) t))
 
189
 
 
190
;; symbol_value  ;; the result depends on WHEN the form is evaluated.
 
191
;; list          ;; Different invocations give different results with same
 
192
;;                    args, but order of eval is not important.  Double EVAL is.
 
193
;; (add x y)     ;; May be multiple eval'd.   WHEN is not important.
 
194
;; (aref x i)    ;; May be multiple eval'd.   WHEN is important.
 
195
;; (set x 3)     ;; May be multiple eval'd.   Changes something in x.  WHEN important.
 
196
 
 
197
;; by 'not side-effect' in the property of an inline, means that it may be
 
198
;; multiple eval'd as long as there were no intervening operation which does
 
199
;; not have the no-side-effect property, and the results would be same EXCEPT,
 
200
;; that we might get a different storage location.
 
201
 
 
202
;; by allocates-new-storage we mean that storage is allocated.
 
203
 
 
204
;; A function which has no-side-effect and 'not allocates-new-storage'
 
205
;; must return eq results if multiple-eval'd with no intervening
 
206
;; no-side-effect function.
 
207
 
 
208
;; Call a function  foo and goo `unordered' if
 
209
;;     (setq a (goo x y))
 
210
;;     (setq b (foo x y))
 
211
;; Then no common lisp function could tell whether a or b was computed first.
 
212
;; The set of 'not side-effect' functions are unordered.
 
213
 
 
214
;; This is the case for LIST, CONS, MAKE-ARRAY, APPEND, AREF, ..  
 
215
 
 
216
(defun inline-args (args arg-types &aux type-wanted)
 
217
  ;; returns (cons arglist referred-vars)
 
218
  ;; where REFERRED-VARS is a list of vars which will be eval'd
 
219
  ;; during the inline writeout of the forms in ARGLIST.    The
 
220
  ;; list of these variables is necessary so that INLINE-CALL
 
221
  ;; may produce this list.
 
222
 
 
223
  ;; we check thru each ARG, and any one which we find which does not
 
224
  ;; meet the following criteria, is pre eval'd as a temp.
 
225
  ;; 1: Are them selves inline calls to functions with 'not side-effect-p' flag
 
226
  ;; 2: Refer to vars which are setq'd by subsequent inline-calls (since
 
227
  ;;     it will be to late to eliminate them then.   Those setq's will actually
 
228
  ;;     be written out in the preevalling. )
 
229
  ;; 3: lexical or special vars unless the last arg.
 
230
 
 
231
  ;; eg (foo x (progn (setq x 3) 7))  would require saving initial value of x in a
 
232
  ;; temp, because it is changed by a subsequent arg.
 
233
  ;; In (foo  (progn (setq x 3) 7) x (+ x y))  the second x and the (+ x y)
 
234
  ;; could stay and be inlined.
 
235
  ;; All user functions are presumed to have 'side-effect-p' 
 
236
  
 
237
  (sloop for v on args  with referred = (cons nil nil)
 
238
     do (setf type-wanted
 
239
              (or (equal arg-types '(*)) (pop arg-types)))
 
240
     collect (inline-arg (car v)  type-wanted (cdr v) referred) into all
 
241
     finally (setf (car referred) all)
 
242
     (return referred)))
 
243
 
 
244
(defun function-constant-p (x)
 
245
;; a function which returns something which will be the SAME for a given
 
246
;; set of arguments, where SAME means that there would not be a way in common lisp
 
247
;; of distinguishing between two results of an invocation OTHER than using eq.
 
248
  (member x '(+ * list cons)))
 
249
 
 
250
(defun remaining-args-constant (rest &aux cd)
 
251
  (sloop for v in rest
 
252
     do
 
253
     (cond ((atom v))
 
254
           ((eq (car v) 'var))
 
255
           ((eq (car v) 'call)
 
256
            (setq cd (third v))
 
257
            (unless (and (function-constant-p (call-data-fname cd))
 
258
                         (remaining-args-constant (call-data-arglist cd)))
 
259
                (return nil)))
 
260
           (t (return nil)))
 
261
     finally (return t)))
 
262
 
 
263
(defun is-var-changed (var subsequent-args &aux cd)
 
264
  (sloop for v in subsequent-args
 
265
     do
 
266
     (cond ((or (atom v)  (eq (car v) 'var) (eq (car v) 'dv)) nil)
 
267
           ((not (plain-var-p var))
 
268
            (setq cd (third v))
 
269
            (unless (and
 
270
                     (eq (car v) 'call)
 
271
                     (function-constant-p (call-data-fname cd))
 
272
                     (not (is-var-changed var  (call-data-arglist cd))))
 
273
                    (return t)))
 
274
           ((typep (second v) 'desk)
 
275
            (return (memq var (desk-changed-vars (second v)))))
 
276
           (t (return t)))))
 
277
 
 
278
(defun inline-arg(a type-wanted rest referred  &aux referred-vars result n tem)
 
279
  ;; a value which can be written inline as an arg, and
 
280
  ;; sets referred-vars
 
281
  ;;
 
282
  (when (eq type-wanted 'fix-or-sf-or-df)
 
283
    (let ((x (car (member (result-type a) '(fixnum short-float double-float)))))
 
284
      (and x (setq type-wanted x))))
 
285
 
 
286
  (when (eq type-wanted 'double_ptr)
 
287
    (let ((v (get-temp 'double-float))
 
288
          (tem (inline-arg a 'double-float rest referred)))
 
289
      (wr-set-inline-loc v tem)
 
290
      (return-from inline-arg (list 'address v))))
 
291
      
 
292
  (cond ((atom a)
 
293
         (or (typep a 'var) (wfs-error))
 
294
         (setq result a)
 
295
         (cond ((or (null rest)
 
296
                    (remaining-args-constant rest)
 
297
                    (and (plain-var-p a)
 
298
                         (not (is-var-changed a rest))))
 
299
                (push a (cdr referred)))
 
300
               (t (setq result (get-temp (var-implementation-type a)))
 
301
                  (wr-nl result "=" a ";")))
 
302
         (or (eq (var-implementation-type a) type-wanted)
 
303
             (setq result (list 'inline-loc type-wanted result))))
 
304
        ((eq (car a) 'var)              ;a temp var
 
305
         (setq result a)
 
306
         (or (eq (third a) type-wanted)
 
307
             (setq result (list 'inline-loc type-wanted result))))
 
308
        ((eq (car a) 'dv)
 
309
         (setq result (add-data a))
 
310
         (or (eq t type-wanted)
 
311
             (setq result (list 'inline-loc type-wanted result))))
 
312
        ((eq (car a) 'the)
 
313
         (setq result (inline-arg  (third a) type-wanted rest referred)))
 
314
        ((eq (car a) 'call)
 
315
         (setq result (inline-call a type-wanted ))
 
316
         (setq tem nil)
 
317
         (setf referred-vars (car result)
 
318
               (car result) 'inline-call)
 
319
         (let ((templ (cddr result))
 
320
               tem1)
 
321
           (setq n  (opt flag templ))
 
322
           (cond ( ;; need a temp:
 
323
                  (or (not (or (flag-p n constantp)
 
324
                               (and (not (flag-p n set))
 
325
                                    (not (flag-p n ans)))))
 
326
                      (and (typep (setq tem1 (fourth templ)) 'link)
 
327
                           (or (argd-flag-p  (link-argd tem1) requires-nargs)
 
328
                               (argd-flag-p  (link-argd tem1) requires-fun-passed))))
 
329
                  (setq tem (get-temp type-wanted)))
 
330
                 (rest
 
331
                  (sloop for referred-var  in referred-vars
 
332
                     when (is-var-changed referred-var rest)
 
333
                     do (setq tem (get-temp (opt return templ)))
 
334
                     (loop-finish))))
 
335
           (unless (null tem)
 
336
                   (setq referred-vars nil)
 
337
                   (wr-set-inline-loc  tem result)
 
338
                   (setf result tem))
 
339
           (unless (eq (opt return templ) type-wanted)
 
340
                   (setq result 
 
341
                         (list 'inline-loc type-wanted result)))
 
342
           (if referred-vars
 
343
               (setf (cdr referred) (nconc referred-vars (cdr referred))))
 
344
           ))
 
345
        (t (setq result (get-temp type-wanted))
 
346
           (when *do-pending-open*
 
347
             (setq *do-pending-open* nil)(open-block))
 
348
           (valex (list 'var result) (next-exit) (expr-b2 a))
 
349
           result))
 
350
  result
 
351
  )
 
352
 
 
353
(defun constant-inline-fixnum(x &aux y)
 
354
  (or (and (consp x) (eq (car x) 'inline-loc)
 
355
           (eq (second x) 'fixnum)
 
356
           (and (consp (setq y (third x)))
 
357
                (eq (car y) 'dv)
 
358
                (typep (third y) 'fixnum)))
 
359
      (wfs-error))
 
360
  (third y))
 
361
 
 
362
(setf (get 'boole 'bo2) 'bo2-boole)
 
363
 
 
364
(defun bo2-boole(a type-wanted arg-types)
 
365
  (when (and (equal arg-types '(fixnum fixnum fixnum))
 
366
             (dv-p (car (call-data-arglist (third a)))))
 
367
    (do-inline-call 'boole3 a 'fixnum)))
 
368
 
 
369
(defun wr-inline-boole3 (iargs)
 
370
  (wr-inline-call1 (cdr iargs)
 
371
                   (ecase (constant-inline-fixnum (car iargs))
 
372
                     (#.boole-ior "(($0) | ($1))" )
 
373
                     (#.boole-xor "(($0) ^ ($1))" )
 
374
                     (#.boole-and "(($0) & ($1))" )
 
375
                     (#.boole-eqv "(~(($0) ^ ($1)))" )
 
376
                     (#.boole-nand "(~(($0) & ($1)))" )
 
377
                     (#.boole-nor "(~(($0) | ($1)))" )
 
378
                     (#.boole-andc1 "((~($0)) & ($1))" )
 
379
                     (#.boole-andc2 "(($0) & (~($1)))" )
 
380
                     (#.boole-orc1 "((~($0)) | ($1))" )
 
381
                     (#.boole-orc2 "(($0) | (~($1)))" )
 
382
                     (#.boole-clr "(0)" )
 
383
                     (#.boole-set "(-1)" )
 
384
                     (#.boole-1 "(($0))" )
 
385
                     (#.boole-2 "(($1))" )
 
386
                     (#.boole-c1 "(~($0))" )
 
387
                     (#.boole-c2 "(~($1))" ))))
 
388
 
 
389
 
 
390
(defun do-inline-call (fname a type-wanted)
 
391
  (inline-call (list 'call (second a) (make-call-data
 
392
                                        fname
 
393
                                        (call-data-arglist (third a)) nil nil))
 
394
               type-wanted))
 
395
 
 
396
(defun coerce-to-binary (sym dsk argl &aux first)
 
397
  (setq first
 
398
        `(call ,dsk ,(make-call-data sym (list (car argl)(second argl)) nil nil)))
 
399
  (cond ((cddr argl)
 
400
         (coerce-to-binary sym dsk (cons first (cddr argl))))
 
401
        (t first)))
 
402
 
 
403
(defun bo2-coerce-to-binary (a type-wanted arg-types) arg-types
 
404
  (let* ((form-type (desk-result-type (second a)))
 
405
         (call-dat (third a))
 
406
         (arglist (call-data-arglist (third a))))
 
407
    (cond ((and (cddr arglist)
 
408
                (or (not (eq type-wanted t))
 
409
                    (not (eq form-type t))))
 
410
           (if (eq type-wanted 'mv) (setq type-wanted t))
 
411
           (inline-call (coerce-to-binary (call-data-fname call-dat)
 
412
                                          (make-desk (type-and type-wanted
 
413
                                                               form-type))
 
414
                                          arglist)
 
415
                        type-wanted)))))
 
416
 
 
417
 
 
418
(dolist (v '(+ * - /)) (setf (get v 'bo2) 'bo2-coerce-to-binary))
 
419
 
 
420
(setf (get 'aref 'bo2) 'bo2-aref)
 
421
 
 
422
(defun bo2-aref (a type-wanted arg-types &aux (cd (third a)) argl type size) arg-types
 
423
  (setq argl (call-data-arglist cd))
 
424
  (setq type (result-type (car argl)))
 
425
  (cond ((and
 
426
          (= *safety* 0)
 
427
          (eql 3 (length argl))
 
428
          (consp type)
 
429
          (eq (car type) 'array)
 
430
          (eq (second type) t)
 
431
          (consp (setq size (third type)))
 
432
          (typep (second size) 'fixnum))
 
433
         (if (eq type-wanted 'mv) (setq type-wanted t))
 
434
         (inline-call (list 'call (second a)
 
435
                            (make-call-data
 
436
                             'aref-2d
 
437
                             (append argl
 
438
                                     (list (get-object (second size))))
 
439
                             nil nil))
 
440
                      type-wanted))))
 
441
                        
 
442
 
 
443
(defun inline-call (a type-wanted  &aux call-dat in-args template tem
 
444
                      (*exit* (next-exit)))
 
445
  ;;  The arg A is a (call  ..) as returned from b1-walk.
 
446
  ;;  If TYPE-WANTED is NIL then we may need Mult Values.  
 
447
  ;;  This function returns a list:
 
448
  ;;  (referred-vars inlined-args result-type  flags fname-or-string)
 
449
  ;;  The REFERRED-VARS and RESULT-TYPE and FLAGS are necessary for
 
450
  ;;  recursive calls, while the FNAME-OR-STRING and INLINED-ARGS
 
451
  ;;  are  used to actually write out the result.
 
452
  (setq call-dat (third a))
 
453
  
 
454
  (let* ((fname (call-data-fname call-dat))
 
455
         fdecl   check
 
456
         (arglist (call-data-arglist call-dat))
 
457
         (arg-types (mapcar 'result-type arglist))
 
458
         (form-type (desk-result-type (second a))))
 
459
 
 
460
 
 
461
    (cond ((and (setq tem (get fname 'bo2))
 
462
                (setq tem (funcall tem a type-wanted arg-types)))
 
463
           (return-from inline-call tem)))
 
464
  
 
465
 
 
466
                        
 
467
    (cond ((call-data-local-fun call-dat)
 
468
           (setq check t)
 
469
           (setq template (get-template-fdata
 
470
                           (second (second 
 
471
                                    (call-data-local-fun call-dat))))))
 
472
          ((setq template
 
473
                 (progn
 
474
                   (setq fdecl (function-declaration fname))
 
475
                   (let ((ret (if fdecl (ret-from-argd (fdecl argd fdecl)))))
 
476
                     (cond (ret
 
477
                            (cond ((eq ret 'double_ptr)
 
478
                                   (setq form-type (type-and 'double-float form-type)))
 
479
                                  ((or (eq ret t)(eq ret '*)))
 
480
                                  (t (setq form-type (type-and ret form-type)))))))
 
481
                   (get-inline-template fname fdecl
 
482
                                      arg-types form-type type-wanted))))
 
483
          ((setq template (add-link-template fname fdecl
 
484
                                                     arg-types type-wanted))))
 
485
    ;; now we have template.
 
486
    (when check
 
487
      (sloop for v in (car template) with al = arglist
 
488
         do 
 
489
         (cond ((eq v '*) (return t))
 
490
               ((null al) (comp-error "Too few args passed to ~a " fname))
 
491
               (t (pop al)))))
 
492
    (cond ((flag-p  (opt flag template)is )
 
493
           (sloop for v on *control-stack*
 
494
              when (or (eq (car v) 'avma-bind)
 
495
                       (eq (car v) 'avma-bind-needed))
 
496
              do (setf (car v) 'avma-bind-needed)
 
497
              (return nil)
 
498
              finally (wfs-error))))
 
499
 
 
500
    (setq in-args (inline-args arglist (opt args template)))
 
501
    (list* (cdr in-args)                ; the referred-vars
 
502
           (car in-args)                ; the arglist
 
503
           template)))
 
504
 
 
505
(defun add-link-template (fname fdecl arg-types  type-wanted &aux tem link ans
 
506
                                (leng (length arg-types)))
 
507
  (declare (fixnum leng))
 
508
  (setq tem (assoc fname *file-inline-templates*))
 
509
  (when tem
 
510
    (setq link (fourth tem))
 
511
    (cond ((typep link 'link)
 
512
           (cond ((< leng (argd-minargs (link-argd link)))
 
513
                  (setf  (argd-minargs (link-argd link)) leng))
 
514
                 ((> leng (argd-maxargs (link-argd link)))
 
515
                  (setf  (argd-maxargs (link-argd link)) leng))
 
516
                 (t nil))
 
517
           (if (eq type-wanted 'mv) (setf (argd-flag-p (link-argd link) sets-mv)  t))))
 
518
    (return-from add-link-template (cdr tem)))
 
519
  (let ((ret t)
 
520
        (argl '(*))
 
521
        (flags #.(flags set ans mv))
 
522
        (argd 0)
 
523
        link)
 
524
    (declare (fixnum argd))
 
525
    (cond (fdecl
 
526
           (setq argd (car fdecl))
 
527
           (setq argl (argl-from-argd argd))
 
528
           (setq ret (ret-from-argd argd))
 
529
           (setq flags (second fdecl)))
 
530
          (t (setf (argd-minargs argd) (length arg-types))
 
531
             (setf (argd-maxargs argd) (length arg-types))
 
532
             (setf (argd-flag-p argd requires-nargs) t)
 
533
             (setf (argd-flag-p argd sets-mv) t)))
 
534
    (setq link (make-link fname fdecl))
 
535
    (setf (link-argd link) argd)
 
536
    ;; we need the data object now, so make sure it gets in the vector
 
537
    ;; in time
 
538
    (add-data (get-object fname))
 
539
    (push (setq ans (list fname argl ret flags link))  *file-inline-templates*)
 
540
    (cdr ans)))
 
541
 
 
542
(defun get-template-fdata (fd &aux  fstring tem)
 
543
  ;; make a template for a local fdata
 
544
  (or (typep fd 'fdata) (wfs-error))
 
545
  (cond ((setq tem (fdata-local-template fd))
 
546
         (return-from get-template-fdata tem)))
 
547
  (let* ((vararg (vararg-p fd))
 
548
         (fdecl (fdata-function-declaration fd))
 
549
         (ll (fdata-ll fd)))
 
550
    (unless fdecl
 
551
            (setq fdecl
 
552
                  (increment-function-decl
 
553
                   `(function
 
554
                     , (nconc
 
555
                        (sloop for v in (ll &required ll) collect (value-type v))
 
556
                        (if (ll &optional ll)
 
557
                            (cons '&optional
 
558
                                  (sloop for v in (ll &optional ll) collect
 
559
                                     (value-type (car v)))))
 
560
                        (if (or (ll &rest ll) (ll &key ll)) '(*) nil))
 
561
                       ;; todo arrange that pickup ret type
 
562
                       ;; from fdata some day10q
 
563
                     *)
 
564
                   nil)))
 
565
 
 
566
    (setq fstring (format nil "L~a($@0)"  (fdata-ind fd)))
 
567
    (if vararg (setq fstring (format nil "(VFUN_NARGS = $#,~a)" fstring)))
 
568
;    (wr-h (rep-type t) " L" (fdata-ind fd) "();")
 
569
    ;; it is only fitting that a closure's template `format string' should in
 
570
    ;; fact be a closure.   Takes a closure to know a closure.
 
571
    (cond ((fdata-closure-vars fd)
 
572
           (let ((fdc fd)
 
573
                 (string fstring))
 
574
             (setf fstring #'(lambda (iargs)
 
575
                               (wr "(fcall.fun="
 
576
                                   (or (fdata-closure-self fdc)
 
577
                                       (fdata-to-obj fdc)) ",")
 
578
                                   (wr-inline-call1 iargs string)
 
579
                                   (wr ")"))))))
 
580
    (let ((ans 
 
581
           (list (argl-from-argd (fdecl argd fdecl)) (ret-from-argd (fdecl argd fdecl))
 
582
                 (fdecl flag fdecl) fstring)))
 
583
      (setf (fdata-local-template fd) ans)
 
584
      ans)))
 
585
 
 
586
 
 
587
 
 
588
(defun replace-inline-by-temp (x)
 
589
  (let* ((type (result-type x))
 
590
         (tem (get-temp type)))
 
591
    (wr-set-inline-loc tem x)
 
592
    tem))
 
593
 
 
594
 
 
595
 
 
596
 
 
597
         
 
598
 
 
599