compile-glil.scm 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. ;;; TREE-IL -> GLIL compiler
  2. ;; Copyright (C) 2001,2008,2009,2010 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Code:
  17. (define-module (language tree-il compile-glil)
  18. #:use-module (system base syntax)
  19. #:use-module (system base pmatch)
  20. #:use-module (system base message)
  21. #:use-module (ice-9 receive)
  22. #:use-module (language glil)
  23. #:use-module (system vm instruction)
  24. #:use-module (language tree-il)
  25. #:use-module (language tree-il optimize)
  26. #:use-module (language tree-il analyze)
  27. #:use-module ((srfi srfi-1) #:select (filter-map))
  28. #:export (compile-glil))
  29. ;; allocation:
  30. ;; sym -> {lambda -> address}
  31. ;; lambda -> (labels . free-locs)
  32. ;; lambda-case -> (gensym . nlocs)
  33. ;;
  34. ;; address ::= (local? boxed? . index)
  35. ;; labels ::= ((sym . lambda) ...)
  36. ;; free-locs ::= ((sym0 . address0) (sym1 . address1) ...)
  37. ;; free variable addresses are relative to parent proc.
  38. (define *comp-module* (make-fluid))
  39. (define %warning-passes
  40. `((unused-variable . ,unused-variable-analysis)
  41. (unused-toplevel . ,unused-toplevel-analysis)
  42. (unbound-variable . ,unbound-variable-analysis)
  43. (arity-mismatch . ,arity-analysis)))
  44. (define (compile-glil x e opts)
  45. (define warnings
  46. (or (and=> (memq #:warnings opts) cadr)
  47. '()))
  48. ;; Go through the warning passes.
  49. (let ((analyses (filter-map (lambda (kind)
  50. (assoc-ref %warning-passes kind))
  51. warnings)))
  52. (analyze-tree analyses x e))
  53. (let* ((x (make-lambda (tree-il-src x) '()
  54. (make-lambda-case #f '() #f #f #f '() '() x #f)))
  55. (x (optimize! x e opts))
  56. (allocation (analyze-lexicals x)))
  57. (with-fluids ((*comp-module* e))
  58. (values (flatten-lambda x #f allocation)
  59. e
  60. e))))
  61. (define *primcall-ops* (make-hash-table))
  62. (for-each
  63. (lambda (x) (hash-set! *primcall-ops* (car x) (cdr x)))
  64. '(((eq? . 2) . eq?)
  65. ((eqv? . 2) . eqv?)
  66. ((equal? . 2) . equal?)
  67. ((= . 2) . ee?)
  68. ((< . 2) . lt?)
  69. ((> . 2) . gt?)
  70. ((<= . 2) . le?)
  71. ((>= . 2) . ge?)
  72. ((+ . 2) . add)
  73. ((- . 2) . sub)
  74. ((1+ . 1) . add1)
  75. ((1- . 1) . sub1)
  76. ((* . 2) . mul)
  77. ((/ . 2) . div)
  78. ((quotient . 2) . quo)
  79. ((remainder . 2) . rem)
  80. ((modulo . 2) . mod)
  81. ((ash . 2) . ash)
  82. ((logand . 2) . logand)
  83. ((logior . 2) . logior)
  84. ((logxor . 2) . logxor)
  85. ((not . 1) . not)
  86. ((pair? . 1) . pair?)
  87. ((cons . 2) . cons)
  88. ((car . 1) . car)
  89. ((cdr . 1) . cdr)
  90. ((set-car! . 2) . set-car!)
  91. ((set-cdr! . 2) . set-cdr!)
  92. ((null? . 1) . null?)
  93. ((list? . 1) . list?)
  94. (list . list)
  95. (vector . vector)
  96. ((class-of . 1) . class-of)
  97. ((@slot-ref . 2) . slot-ref)
  98. ((@slot-set! . 3) . slot-set)
  99. ((vector-ref . 2) . vector-ref)
  100. ((vector-set! . 3) . vector-set)
  101. ((variable-ref . 1) . variable-ref)
  102. ;; nb, *not* variable-set! -- the args are switched
  103. ((variable-bound? . 1) . variable-bound?)
  104. ((struct? . 1) . struct?)
  105. ((struct-vtable . 1) . struct-vtable)
  106. ((struct-ref . 2) . struct-ref)
  107. ((struct-set! . 3) . struct-set)
  108. (make-struct/no-tail . make-struct)
  109. ;; hack for javascript
  110. ((return . 1) . return)
  111. ((bytevector-u8-ref . 2) . bv-u8-ref)
  112. ((bytevector-u8-set! . 3) . bv-u8-set)
  113. ((bytevector-s8-ref . 2) . bv-s8-ref)
  114. ((bytevector-s8-set! . 3) . bv-s8-set)
  115. ((bytevector-u16-ref . 3) . bv-u16-ref)
  116. ((bytevector-u16-set! . 4) . bv-u16-set)
  117. ((bytevector-u16-native-ref . 2) . bv-u16-native-ref)
  118. ((bytevector-u16-native-set! . 3) . bv-u16-native-set)
  119. ((bytevector-s16-ref . 3) . bv-s16-ref)
  120. ((bytevector-s16-set! . 4) . bv-s16-set)
  121. ((bytevector-s16-native-ref . 2) . bv-s16-native-ref)
  122. ((bytevector-s16-native-set! . 3) . bv-s16-native-set)
  123. ((bytevector-u32-ref . 3) . bv-u32-ref)
  124. ((bytevector-u32-set! . 4) . bv-u32-set)
  125. ((bytevector-u32-native-ref . 2) . bv-u32-native-ref)
  126. ((bytevector-u32-native-set! . 3) . bv-u32-native-set)
  127. ((bytevector-s32-ref . 3) . bv-s32-ref)
  128. ((bytevector-s32-set! . 4) . bv-s32-set)
  129. ((bytevector-s32-native-ref . 2) . bv-s32-native-ref)
  130. ((bytevector-s32-native-set! . 3) . bv-s32-native-set)
  131. ((bytevector-u64-ref . 3) . bv-u64-ref)
  132. ((bytevector-u64-set! . 4) . bv-u64-set)
  133. ((bytevector-u64-native-ref . 2) . bv-u64-native-ref)
  134. ((bytevector-u64-native-set! . 3) . bv-u64-native-set)
  135. ((bytevector-s64-ref . 3) . bv-s64-ref)
  136. ((bytevector-s64-set! . 4) . bv-s64-set)
  137. ((bytevector-s64-native-ref . 2) . bv-s64-native-ref)
  138. ((bytevector-s64-native-set! . 3) . bv-s64-native-set)
  139. ((bytevector-ieee-single-ref . 3) . bv-f32-ref)
  140. ((bytevector-ieee-single-set! . 4) . bv-f32-set)
  141. ((bytevector-ieee-single-native-ref . 2) . bv-f32-native-ref)
  142. ((bytevector-ieee-single-native-set! . 3) . bv-f32-native-set)
  143. ((bytevector-ieee-double-ref . 3) . bv-f64-ref)
  144. ((bytevector-ieee-double-set! . 4) . bv-f64-set)
  145. ((bytevector-ieee-double-native-ref . 2) . bv-f64-native-ref)
  146. ((bytevector-ieee-double-native-set! . 3) . bv-f64-native-set)))
  147. (define (make-label) (gensym ":L"))
  148. (define (vars->bind-list ids vars allocation proc)
  149. (map (lambda (id v)
  150. (pmatch (hashq-ref (hashq-ref allocation v) proc)
  151. ((#t ,boxed? . ,n)
  152. (list id boxed? n))
  153. (,x (error "badness" id v x))))
  154. ids
  155. vars))
  156. (define (emit-bindings src ids vars allocation proc emit-code)
  157. (emit-code src (make-glil-bind
  158. (vars->bind-list ids vars allocation proc))))
  159. (define (with-output-to-code proc)
  160. (let ((out '()))
  161. (define (emit-code src x)
  162. (set! out (cons x out))
  163. (if src
  164. (set! out (cons (make-glil-source src) out))))
  165. (proc emit-code)
  166. (reverse out)))
  167. (define (flatten-lambda x self-label allocation)
  168. (record-case x
  169. ((<lambda> src meta body)
  170. (make-glil-program
  171. meta
  172. (with-output-to-code
  173. (lambda (emit-code)
  174. ;; write source info for proc
  175. (if src (emit-code #f (make-glil-source src)))
  176. ;; emit pre-prelude label for self tail calls in which the
  177. ;; number of arguments doesn't check out at compile time
  178. (if self-label
  179. (emit-code #f (make-glil-label self-label)))
  180. ;; compile the body, yo
  181. (flatten body allocation x self-label (car (hashq-ref allocation x))
  182. emit-code)))))))
  183. (define (flatten x allocation self self-label fix-labels emit-code)
  184. (define (emit-label label)
  185. (emit-code #f (make-glil-label label)))
  186. (define (emit-branch src inst label)
  187. (emit-code src (make-glil-branch inst label)))
  188. ;; RA: "return address"; #f unless we're in a non-tail fix with labels
  189. ;; MVRA: "multiple-values return address"; #f unless we're in a let-values
  190. (let comp ((x x) (context 'tail) (RA #f) (MVRA #f))
  191. (define (comp-tail tree) (comp tree context RA MVRA))
  192. (define (comp-push tree) (comp tree 'push #f #f))
  193. (define (comp-drop tree) (comp tree 'drop #f #f))
  194. (define (comp-vals tree MVRA) (comp tree 'vals #f MVRA))
  195. (define (comp-fix tree RA) (comp tree context RA MVRA))
  196. ;; A couple of helpers. Note that if we are in tail context, we
  197. ;; won't have an RA.
  198. (define (maybe-emit-return)
  199. (if RA
  200. (emit-branch #f 'br RA)
  201. (if (eq? context 'tail)
  202. (emit-code #f (make-glil-call 'return 1)))))
  203. (record-case x
  204. ((<void>)
  205. (case context
  206. ((push vals tail)
  207. (emit-code #f (make-glil-void))))
  208. (maybe-emit-return))
  209. ((<const> src exp)
  210. (case context
  211. ((push vals tail)
  212. (emit-code src (make-glil-const exp))))
  213. (maybe-emit-return))
  214. ;; FIXME: should represent sequence as exps tail
  215. ((<sequence> exps)
  216. (let lp ((exps exps))
  217. (if (null? (cdr exps))
  218. (comp-tail (car exps))
  219. (begin
  220. (comp-drop (car exps))
  221. (lp (cdr exps))))))
  222. ((<application> src proc args)
  223. ;; FIXME: need a better pattern-matcher here
  224. (cond
  225. ((and (primitive-ref? proc)
  226. (eq? (primitive-ref-name proc) '@apply)
  227. (>= (length args) 1))
  228. (let ((proc (car args))
  229. (args (cdr args)))
  230. (cond
  231. ((and (primitive-ref? proc) (eq? (primitive-ref-name proc) 'values)
  232. (not (eq? context 'push)) (not (eq? context 'vals)))
  233. ;; tail: (lambda () (apply values '(1 2)))
  234. ;; drop: (lambda () (apply values '(1 2)) 3)
  235. ;; push: (lambda () (list (apply values '(10 12)) 1))
  236. (case context
  237. ((drop) (for-each comp-drop args) (maybe-emit-return))
  238. ((tail)
  239. (for-each comp-push args)
  240. (emit-code src (make-glil-call 'return/values* (length args))))))
  241. (else
  242. (case context
  243. ((tail)
  244. (comp-push proc)
  245. (for-each comp-push args)
  246. (emit-code src (make-glil-call 'tail-apply (1+ (length args)))))
  247. ((push)
  248. (emit-code src (make-glil-call 'new-frame 0))
  249. (comp-push proc)
  250. (for-each comp-push args)
  251. (emit-code src (make-glil-call 'apply (1+ (length args))))
  252. (maybe-emit-return))
  253. ((vals)
  254. (comp-vals
  255. (make-application src (make-primitive-ref #f 'apply)
  256. (cons proc args))
  257. MVRA)
  258. (maybe-emit-return))
  259. ((drop)
  260. ;; Well, shit. The proc might return any number of
  261. ;; values (including 0), since it's in a drop context,
  262. ;; yet apply does not create a MV continuation. So we
  263. ;; mv-call out to our trampoline instead.
  264. (comp-drop
  265. (make-application src (make-primitive-ref #f 'apply)
  266. (cons proc args)))
  267. (maybe-emit-return)))))))
  268. ((and (primitive-ref? proc) (eq? (primitive-ref-name proc) 'values)
  269. (not (eq? context 'push)))
  270. ;; tail: (lambda () (values '(1 2)))
  271. ;; drop: (lambda () (values '(1 2)) 3)
  272. ;; push: (lambda () (list (values '(10 12)) 1))
  273. ;; vals: (let-values (((a b ...) (values 1 2 ...))) ...)
  274. (case context
  275. ((drop) (for-each comp-drop args) (maybe-emit-return))
  276. ((vals)
  277. (for-each comp-push args)
  278. (emit-code #f (make-glil-const (length args)))
  279. (emit-branch src 'br MVRA))
  280. ((tail)
  281. (for-each comp-push args)
  282. (emit-code src (make-glil-call 'return/values (length args))))))
  283. ((and (primitive-ref? proc)
  284. (eq? (primitive-ref-name proc) '@call-with-values)
  285. (= (length args) 2))
  286. ;; CONSUMER
  287. ;; PRODUCER
  288. ;; (mv-call MV)
  289. ;; ([tail]-call 1)
  290. ;; goto POST
  291. ;; MV: [tail-]call/nargs
  292. ;; POST: (maybe-drop)
  293. (case context
  294. ((vals)
  295. ;; Fall back.
  296. (comp-vals
  297. (make-application src (make-primitive-ref #f 'call-with-values)
  298. args)
  299. MVRA)
  300. (maybe-emit-return))
  301. (else
  302. (let ((MV (make-label)) (POST (make-label))
  303. (producer (car args)) (consumer (cadr args)))
  304. (if (not (eq? context 'tail))
  305. (emit-code src (make-glil-call 'new-frame 0)))
  306. (comp-push consumer)
  307. (emit-code src (make-glil-call 'new-frame 0))
  308. (comp-push producer)
  309. (emit-code src (make-glil-mv-call 0 MV))
  310. (case context
  311. ((tail) (emit-code src (make-glil-call 'tail-call 1)))
  312. (else (emit-code src (make-glil-call 'call 1))
  313. (emit-branch #f 'br POST)))
  314. (emit-label MV)
  315. (case context
  316. ((tail) (emit-code src (make-glil-call 'tail-call/nargs 0)))
  317. (else (emit-code src (make-glil-call 'call/nargs 0))
  318. (emit-label POST)
  319. (if (eq? context 'drop)
  320. (emit-code #f (make-glil-call 'drop 1)))
  321. (maybe-emit-return)))))))
  322. ((and (primitive-ref? proc)
  323. (eq? (primitive-ref-name proc) '@call-with-current-continuation)
  324. (= (length args) 1))
  325. (case context
  326. ((tail)
  327. (comp-push (car args))
  328. (emit-code src (make-glil-call 'tail-call/cc 1)))
  329. ((vals)
  330. (comp-vals
  331. (make-application
  332. src (make-primitive-ref #f 'call-with-current-continuation)
  333. args)
  334. MVRA)
  335. (maybe-emit-return))
  336. ((push)
  337. (comp-push (car args))
  338. (emit-code src (make-glil-call 'call/cc 1))
  339. (maybe-emit-return))
  340. ((drop)
  341. ;; Crap. Just like `apply' in drop context.
  342. (comp-drop
  343. (make-application
  344. src (make-primitive-ref #f 'call-with-current-continuation)
  345. args))
  346. (maybe-emit-return))))
  347. ;; A hack for variable-set, the opcode for which takes its args
  348. ;; reversed, relative to the variable-set! function
  349. ((and (primitive-ref? proc)
  350. (eq? (primitive-ref-name proc) 'variable-set!)
  351. (= (length args) 2))
  352. (comp-push (cadr args))
  353. (comp-push (car args))
  354. (emit-code src (make-glil-call 'variable-set 2))
  355. (case context
  356. ((tail push vals) (emit-code #f (make-glil-void))))
  357. (maybe-emit-return))
  358. ((and (primitive-ref? proc)
  359. (or (hash-ref *primcall-ops*
  360. (cons (primitive-ref-name proc) (length args)))
  361. (hash-ref *primcall-ops* (primitive-ref-name proc))))
  362. => (lambda (op)
  363. (for-each comp-push args)
  364. (emit-code src (make-glil-call op (length args)))
  365. (case (instruction-pushes op)
  366. ((0)
  367. (case context
  368. ((tail push vals) (emit-code #f (make-glil-void))))
  369. (maybe-emit-return))
  370. ((1)
  371. (case context
  372. ((drop) (emit-code #f (make-glil-call 'drop 1))))
  373. (maybe-emit-return))
  374. (else
  375. (error "bad primitive op: too many pushes"
  376. op (instruction-pushes op))))))
  377. ;; self-call in tail position
  378. ((and (lexical-ref? proc)
  379. self-label (eq? (lexical-ref-gensym proc) self-label)
  380. (eq? context 'tail))
  381. ;; first, evaluate new values, pushing them on the stack
  382. (for-each comp-push args)
  383. (let lp ((lcase (lambda-body self)))
  384. (cond
  385. ((and (lambda-case? lcase)
  386. (not (lambda-case-kw lcase))
  387. (not (lambda-case-opt lcase))
  388. (not (lambda-case-rest lcase))
  389. (= (length args) (length (lambda-case-req lcase))))
  390. ;; we have a case that matches the args; rename variables
  391. ;; and goto the case label
  392. (for-each (lambda (sym)
  393. (pmatch (hashq-ref (hashq-ref allocation sym) self)
  394. ((#t #f . ,index) ; unboxed
  395. (emit-code #f (make-glil-lexical #t #f 'set index)))
  396. ((#t #t . ,index) ; boxed
  397. ;; new box
  398. (emit-code #f (make-glil-lexical #t #t 'box index)))
  399. (,x (error "what" x))))
  400. (reverse (lambda-case-gensyms lcase)))
  401. (emit-branch src 'br (car (hashq-ref allocation lcase))))
  402. ((lambda-case? lcase)
  403. ;; no match, try next case
  404. (lp (lambda-case-alternate lcase)))
  405. (else
  406. ;; no cases left; shuffle args down and jump before the prelude.
  407. (for-each (lambda (i)
  408. (emit-code #f (make-glil-lexical #t #f 'set i)))
  409. (reverse (iota (length args))))
  410. (emit-branch src 'br self-label)))))
  411. ;; lambda, the ultimate goto
  412. ((and (lexical-ref? proc)
  413. (assq (lexical-ref-gensym proc) fix-labels))
  414. ;; like the self-tail-call case, though we can handle "drop"
  415. ;; contexts too. first, evaluate new values, pushing them on
  416. ;; the stack
  417. (for-each comp-push args)
  418. ;; find the specific case, rename args, and goto the case label
  419. (let lp ((lcase (lambda-body
  420. (assq-ref fix-labels (lexical-ref-gensym proc)))))
  421. (cond
  422. ((and (lambda-case? lcase)
  423. (not (lambda-case-kw lcase))
  424. (not (lambda-case-opt lcase))
  425. (not (lambda-case-rest lcase))
  426. (= (length args) (length (lambda-case-req lcase))))
  427. ;; we have a case that matches the args; rename variables
  428. ;; and goto the case label
  429. (for-each (lambda (sym)
  430. (pmatch (hashq-ref (hashq-ref allocation sym) self)
  431. ((#t #f . ,index) ; unboxed
  432. (emit-code #f (make-glil-lexical #t #f 'set index)))
  433. ((#t #t . ,index) ; boxed
  434. (emit-code #f (make-glil-lexical #t #t 'box index)))
  435. (,x (error "what" x))))
  436. (reverse (lambda-case-gensyms lcase)))
  437. (emit-branch src 'br (car (hashq-ref allocation lcase))))
  438. ((lambda-case? lcase)
  439. ;; no match, try next case
  440. (lp (lambda-case-alternate lcase)))
  441. (else
  442. ;; no cases left. we can't really handle this currently.
  443. ;; ideally we would push on a new frame, then do a "local
  444. ;; call" -- which doesn't require consing up a program
  445. ;; object. but for now error, as this sort of case should
  446. ;; preclude label allocation.
  447. (error "couldn't find matching case for label call" x)))))
  448. (else
  449. (if (not (eq? context 'tail))
  450. (emit-code src (make-glil-call 'new-frame 0)))
  451. (comp-push proc)
  452. (for-each comp-push args)
  453. (let ((len (length args)))
  454. (case context
  455. ((tail) (emit-code src (make-glil-call 'tail-call len)))
  456. ((push) (emit-code src (make-glil-call 'call len))
  457. (maybe-emit-return))
  458. ((vals) (emit-code src (make-glil-mv-call len MVRA))
  459. (maybe-emit-return))
  460. ((drop) (let ((MV (make-label)) (POST (make-label)))
  461. (emit-code src (make-glil-mv-call len MV))
  462. (emit-code #f (make-glil-call 'drop 1))
  463. (emit-branch #f 'br (or RA POST))
  464. (emit-label MV)
  465. (emit-code #f (make-glil-mv-bind 0 #f))
  466. (if RA
  467. (emit-branch #f 'br RA)
  468. (emit-label POST)))))))))
  469. ((<conditional> src test consequent alternate)
  470. ;; TEST
  471. ;; (br-if-not L1)
  472. ;; consequent
  473. ;; (br L2)
  474. ;; L1: alternate
  475. ;; L2:
  476. (let ((L1 (make-label)) (L2 (make-label)))
  477. ;; need a pattern matcher
  478. (record-case test
  479. ((<application> proc args)
  480. (record-case proc
  481. ((<primitive-ref> name)
  482. (let ((len (length args)))
  483. (cond
  484. ((and (eq? name 'eq?) (= len 2))
  485. (comp-push (car args))
  486. (comp-push (cadr args))
  487. (emit-branch src 'br-if-not-eq L1))
  488. ((and (eq? name 'null?) (= len 1))
  489. (comp-push (car args))
  490. (emit-branch src 'br-if-not-null L1))
  491. ((and (eq? name 'not) (= len 1))
  492. (let ((app (car args)))
  493. (record-case app
  494. ((<application> proc args)
  495. (let ((len (length args)))
  496. (record-case proc
  497. ((<primitive-ref> name)
  498. (cond
  499. ((and (eq? name 'eq?) (= len 2))
  500. (comp-push (car args))
  501. (comp-push (cadr args))
  502. (emit-branch src 'br-if-eq L1))
  503. ((and (eq? name 'null?) (= len 1))
  504. (comp-push (car args))
  505. (emit-branch src 'br-if-null L1))
  506. (else
  507. (comp-push app)
  508. (emit-branch src 'br-if L1))))
  509. (else
  510. (comp-push app)
  511. (emit-branch src 'br-if L1)))))
  512. (else
  513. (comp-push app)
  514. (emit-branch src 'br-if L1)))))
  515. (else
  516. (comp-push test)
  517. (emit-branch src 'br-if-not L1)))))
  518. (else
  519. (comp-push test)
  520. (emit-branch src 'br-if-not L1))))
  521. (else
  522. (comp-push test)
  523. (emit-branch src 'br-if-not L1)))
  524. (comp-tail consequent)
  525. ;; if there is an RA, comp-tail will cause a jump to it -- just
  526. ;; have to clean up here if there is no RA.
  527. (if (and (not RA) (not (eq? context 'tail)))
  528. (emit-branch #f 'br L2))
  529. (emit-label L1)
  530. (comp-tail alternate)
  531. (if (and (not RA) (not (eq? context 'tail)))
  532. (emit-label L2))))
  533. ((<primitive-ref> src name)
  534. (cond
  535. ((eq? (module-variable (fluid-ref *comp-module*) name)
  536. (module-variable the-root-module name))
  537. (case context
  538. ((tail push vals)
  539. (emit-code src (make-glil-toplevel 'ref name))))
  540. (maybe-emit-return))
  541. ((module-variable the-root-module name)
  542. (case context
  543. ((tail push vals)
  544. (emit-code src (make-glil-module 'ref '(guile) name #f))))
  545. (maybe-emit-return))
  546. (else
  547. (case context
  548. ((tail push vals)
  549. (emit-code src (make-glil-module
  550. 'ref (module-name (fluid-ref *comp-module*)) name #f))))
  551. (maybe-emit-return))))
  552. ((<lexical-ref> src gensym)
  553. (case context
  554. ((push vals tail)
  555. (pmatch (hashq-ref (hashq-ref allocation gensym) self)
  556. ((,local? ,boxed? . ,index)
  557. (emit-code src (make-glil-lexical local? boxed? 'ref index)))
  558. (,loc
  559. (error "badness" x loc)))))
  560. (maybe-emit-return))
  561. ((<lexical-set> src gensym exp)
  562. (comp-push exp)
  563. (pmatch (hashq-ref (hashq-ref allocation gensym) self)
  564. ((,local? ,boxed? . ,index)
  565. (emit-code src (make-glil-lexical local? boxed? 'set index)))
  566. (,loc
  567. (error "badness" x loc)))
  568. (case context
  569. ((tail push vals)
  570. (emit-code #f (make-glil-void))))
  571. (maybe-emit-return))
  572. ((<module-ref> src mod name public?)
  573. (emit-code src (make-glil-module 'ref mod name public?))
  574. (case context
  575. ((drop) (emit-code #f (make-glil-call 'drop 1))))
  576. (maybe-emit-return))
  577. ((<module-set> src mod name public? exp)
  578. (comp-push exp)
  579. (emit-code src (make-glil-module 'set mod name public?))
  580. (case context
  581. ((tail push vals)
  582. (emit-code #f (make-glil-void))))
  583. (maybe-emit-return))
  584. ((<toplevel-ref> src name)
  585. (emit-code src (make-glil-toplevel 'ref name))
  586. (case context
  587. ((drop) (emit-code #f (make-glil-call 'drop 1))))
  588. (maybe-emit-return))
  589. ((<toplevel-set> src name exp)
  590. (comp-push exp)
  591. (emit-code src (make-glil-toplevel 'set name))
  592. (case context
  593. ((tail push vals)
  594. (emit-code #f (make-glil-void))))
  595. (maybe-emit-return))
  596. ((<toplevel-define> src name exp)
  597. (comp-push exp)
  598. (emit-code src (make-glil-toplevel 'define name))
  599. (case context
  600. ((tail push vals)
  601. (emit-code #f (make-glil-void))))
  602. (maybe-emit-return))
  603. ((<lambda>)
  604. (let ((free-locs (cdr (hashq-ref allocation x))))
  605. (case context
  606. ((push vals tail)
  607. (emit-code #f (flatten-lambda x #f allocation))
  608. (if (not (null? free-locs))
  609. (begin
  610. (for-each
  611. (lambda (loc)
  612. (pmatch loc
  613. ((,local? ,boxed? . ,n)
  614. (emit-code #f (make-glil-lexical local? #f 'ref n)))
  615. (else (error "what" x loc))))
  616. free-locs)
  617. (emit-code #f (make-glil-call 'make-closure
  618. (length free-locs))))))))
  619. (maybe-emit-return))
  620. ((<lambda-case> src req opt rest kw inits gensyms alternate body)
  621. ;; o/~ feature on top of feature o/~
  622. ;; req := (name ...)
  623. ;; opt := (name ...) | #f
  624. ;; rest := name | #f
  625. ;; kw: (allow-other-keys? (keyword name var) ...) | #f
  626. ;; gensyms: (sym ...)
  627. ;; init: tree-il in context of gensyms
  628. ;; gensyms map to named arguments in the following order:
  629. ;; required, optional (positional), rest, keyword.
  630. (let* ((nreq (length req))
  631. (nopt (if opt (length opt) 0))
  632. (rest-idx (and rest (+ nreq nopt)))
  633. (opt-names (or opt '()))
  634. (allow-other-keys? (if kw (car kw) #f))
  635. (kw-indices (map (lambda (x)
  636. (pmatch x
  637. ((,key ,name ,var)
  638. (cons key (list-index gensyms var)))
  639. (else (error "bad kwarg" x))))
  640. (if kw (cdr kw) '())))
  641. (nargs (apply max (+ nreq nopt (if rest 1 0))
  642. (map 1+ (map cdr kw-indices))))
  643. (nlocs (cdr (hashq-ref allocation x)))
  644. (alternate-label (and alternate (make-label))))
  645. (or (= nargs
  646. (length gensyms)
  647. (+ nreq (length inits) (if rest 1 0)))
  648. (error "something went wrong"
  649. req opt rest kw inits gensyms nreq nopt kw-indices nargs))
  650. ;; the prelude, to check args & reset the stack pointer,
  651. ;; allowing room for locals
  652. (emit-code
  653. src
  654. (cond
  655. (kw
  656. (make-glil-kw-prelude nreq nopt rest-idx kw-indices
  657. allow-other-keys? nlocs alternate-label))
  658. ((or rest opt)
  659. (make-glil-opt-prelude nreq nopt rest-idx nlocs alternate-label))
  660. (#t
  661. (make-glil-std-prelude nreq nlocs alternate-label))))
  662. ;; box args if necessary
  663. (for-each
  664. (lambda (v)
  665. (pmatch (hashq-ref (hashq-ref allocation v) self)
  666. ((#t #t . ,n)
  667. (emit-code #f (make-glil-lexical #t #f 'ref n))
  668. (emit-code #f (make-glil-lexical #t #t 'box n)))))
  669. gensyms)
  670. ;; write bindings info
  671. (if (not (null? gensyms))
  672. (emit-bindings
  673. #f
  674. (let lp ((kw (if kw (cdr kw) '()))
  675. (names (append (reverse opt-names) (reverse req)))
  676. (gensyms (list-tail gensyms (+ nreq nopt
  677. (if rest 1 0)))))
  678. (pmatch kw
  679. (()
  680. ;; fixme: check that gensyms is empty
  681. (reverse (if rest (cons rest names) names)))
  682. (((,key ,name ,var) . ,kw)
  683. (if (memq var gensyms)
  684. (lp kw (cons name names) (delq var gensyms))
  685. (lp kw names gensyms)))
  686. (,kw (error "bad keywords, yo" kw))))
  687. gensyms allocation self emit-code))
  688. ;; init optional/kw args
  689. (let lp ((inits inits) (n nreq) (gensyms (list-tail gensyms nreq)))
  690. (cond
  691. ((null? inits)) ; done
  692. ((and rest-idx (= n rest-idx))
  693. (lp inits (1+ n) (cdr gensyms)))
  694. (#t
  695. (pmatch (hashq-ref (hashq-ref allocation (car gensyms)) self)
  696. ((#t ,boxed? . ,n*) (guard (= n* n))
  697. (let ((L (make-label)))
  698. (emit-code #f (make-glil-lexical #t boxed? 'bound? n))
  699. (emit-code #f (make-glil-branch 'br-if L))
  700. (comp-push (car inits))
  701. (emit-code #f (make-glil-lexical #t boxed? 'set n))
  702. (emit-label L)
  703. (lp (cdr inits) (1+ n) (cdr gensyms))))
  704. (#t (error "what" inits))))))
  705. ;; post-prelude case label for label calls
  706. (emit-label (car (hashq-ref allocation x)))
  707. (comp-tail body)
  708. (if (not (null? gensyms))
  709. (emit-code #f (make-glil-unbind)))
  710. (if alternate-label
  711. (begin
  712. (emit-label alternate-label)
  713. (comp-tail alternate)))))
  714. ((<let> src names gensyms vals body)
  715. (for-each comp-push vals)
  716. (emit-bindings src names gensyms allocation self emit-code)
  717. (for-each (lambda (v)
  718. (pmatch (hashq-ref (hashq-ref allocation v) self)
  719. ((#t #f . ,n)
  720. (emit-code src (make-glil-lexical #t #f 'set n)))
  721. ((#t #t . ,n)
  722. (emit-code src (make-glil-lexical #t #t 'box n)))
  723. (,loc (error "badness" x loc))))
  724. (reverse gensyms))
  725. (comp-tail body)
  726. (emit-code #f (make-glil-unbind)))
  727. ((<letrec> src in-order? names gensyms vals body)
  728. ;; First prepare heap storage slots.
  729. (for-each (lambda (v)
  730. (pmatch (hashq-ref (hashq-ref allocation v) self)
  731. ((#t #t . ,n)
  732. (emit-code src (make-glil-lexical #t #t 'empty-box n)))
  733. (,loc (error "badness" x loc))))
  734. gensyms)
  735. ;; Even though the slots are empty, the bindings are valid.
  736. (emit-bindings src names gensyms allocation self emit-code)
  737. (cond
  738. (in-order?
  739. ;; For letrec*, bind values in order.
  740. (for-each (lambda (name v val)
  741. (pmatch (hashq-ref (hashq-ref allocation v) self)
  742. ((#t #t . ,n)
  743. (comp-push val)
  744. (emit-code src (make-glil-lexical #t #t 'set n)))
  745. (,loc (error "badness" x loc))))
  746. names gensyms vals))
  747. (else
  748. ;; But for letrec, eval all values, then bind.
  749. (for-each comp-push vals)
  750. (for-each (lambda (v)
  751. (pmatch (hashq-ref (hashq-ref allocation v) self)
  752. ((#t #t . ,n)
  753. (emit-code src (make-glil-lexical #t #t 'set n)))
  754. (,loc (error "badness" x loc))))
  755. (reverse gensyms))))
  756. (comp-tail body)
  757. (emit-code #f (make-glil-unbind)))
  758. ((<fix> src names gensyms vals body)
  759. ;; The ideal here is to just render the lambda bodies inline, and
  760. ;; wire the code together with gotos. We can do that if
  761. ;; analyze-lexicals has determined that a given var has "label"
  762. ;; allocation -- which is the case if it is in `fix-labels'.
  763. ;;
  764. ;; But even for closures that we can't inline, we can do some
  765. ;; tricks to avoid heap-allocation for the binding itself. Since
  766. ;; we know the vals are lambdas, we can set them to their local
  767. ;; var slots first, then capture their bindings, mutating them in
  768. ;; place.
  769. (let ((new-RA (if (or (eq? context 'tail) RA) #f (make-label))))
  770. (for-each
  771. (lambda (x v)
  772. (cond
  773. ((hashq-ref allocation x)
  774. ;; allocating a closure
  775. (emit-code #f (flatten-lambda x v allocation))
  776. (let ((free-locs (cdr (hashq-ref allocation x))))
  777. (if (not (null? free-locs))
  778. ;; Need to make-closure first, so we have a fresh closure on
  779. ;; the heap, but with a temporary free values.
  780. (begin
  781. (for-each (lambda (loc)
  782. (emit-code #f (make-glil-const #f)))
  783. free-locs)
  784. (emit-code #f (make-glil-call 'make-closure
  785. (length free-locs))))))
  786. (pmatch (hashq-ref (hashq-ref allocation v) self)
  787. ((#t #f . ,n)
  788. (emit-code src (make-glil-lexical #t #f 'set n)))
  789. (,loc (error "badness" x loc))))
  790. (else
  791. ;; labels allocation: emit label & body, but jump over it
  792. (let ((POST (make-label)))
  793. (emit-branch #f 'br POST)
  794. (let lp ((lcase (lambda-body x)))
  795. (if lcase
  796. (record-case lcase
  797. ((<lambda-case> src req gensyms body alternate)
  798. (emit-label (car (hashq-ref allocation lcase)))
  799. ;; FIXME: opt & kw args in the bindings
  800. (emit-bindings #f req gensyms allocation self emit-code)
  801. (if src
  802. (emit-code #f (make-glil-source src)))
  803. (comp-fix body (or RA new-RA))
  804. (emit-code #f (make-glil-unbind))
  805. (lp alternate)))
  806. (emit-label POST)))))))
  807. vals
  808. gensyms)
  809. ;; Emit bindings metadata for closures
  810. (let ((binds (let lp ((out '()) (gensyms gensyms) (names names))
  811. (cond ((null? gensyms) (reverse! out))
  812. ((assq (car gensyms) fix-labels)
  813. (lp out (cdr gensyms) (cdr names)))
  814. (else
  815. (lp (acons (car gensyms) (car names) out)
  816. (cdr gensyms) (cdr names)))))))
  817. (emit-bindings src (map cdr binds) (map car binds)
  818. allocation self emit-code))
  819. ;; Now go back and fix up the bindings for closures.
  820. (for-each
  821. (lambda (x v)
  822. (let ((free-locs (if (hashq-ref allocation x)
  823. (cdr (hashq-ref allocation x))
  824. ;; can hit this latter case for labels allocation
  825. '())))
  826. (if (not (null? free-locs))
  827. (begin
  828. (for-each
  829. (lambda (loc)
  830. (pmatch loc
  831. ((,local? ,boxed? . ,n)
  832. (emit-code #f (make-glil-lexical local? #f 'ref n)))
  833. (else (error "what" x loc))))
  834. free-locs)
  835. (pmatch (hashq-ref (hashq-ref allocation v) self)
  836. ((#t #f . ,n)
  837. (emit-code #f (make-glil-lexical #t #f 'fix n)))
  838. (,loc (error "badness" x loc)))))))
  839. vals
  840. gensyms)
  841. (comp-tail body)
  842. (if new-RA
  843. (emit-label new-RA))
  844. (emit-code #f (make-glil-unbind))))
  845. ((<let-values> src exp body)
  846. (record-case body
  847. ((<lambda-case> req opt kw rest gensyms body alternate)
  848. (if (or opt kw alternate)
  849. (error "unexpected lambda-case in let-values" x))
  850. (let ((MV (make-label)))
  851. (comp-vals exp MV)
  852. (emit-code #f (make-glil-const 1))
  853. (emit-label MV)
  854. (emit-code src (make-glil-mv-bind
  855. (vars->bind-list
  856. (append req (if rest (list rest) '()))
  857. gensyms allocation self)
  858. (and rest #t)))
  859. (for-each (lambda (v)
  860. (pmatch (hashq-ref (hashq-ref allocation v) self)
  861. ((#t #f . ,n)
  862. (emit-code src (make-glil-lexical #t #f 'set n)))
  863. ((#t #t . ,n)
  864. (emit-code src (make-glil-lexical #t #t 'box n)))
  865. (,loc (error "badness" x loc))))
  866. (reverse gensyms))
  867. (comp-tail body)
  868. (emit-code #f (make-glil-unbind))))))
  869. ;; much trickier than i thought this would be, at first, due to the need
  870. ;; to have body's return value(s) on the stack while the unwinder runs,
  871. ;; then proceed with returning or dropping or what-have-you, interacting
  872. ;; with RA and MVRA. What have you, I say.
  873. ((<dynwind> src body winder unwinder)
  874. (comp-push winder)
  875. (comp-push unwinder)
  876. (comp-drop (make-application src winder '()))
  877. (emit-code #f (make-glil-call 'wind 2))
  878. (case context
  879. ((tail)
  880. (let ((MV (make-label)))
  881. (comp-vals body MV)
  882. ;; one value: unwind...
  883. (emit-code #f (make-glil-call 'unwind 0))
  884. (comp-drop (make-application src unwinder '()))
  885. ;; ...and return the val
  886. (emit-code #f (make-glil-call 'return 1))
  887. (emit-label MV)
  888. ;; multiple values: unwind...
  889. (emit-code #f (make-glil-call 'unwind 0))
  890. (comp-drop (make-application src unwinder '()))
  891. ;; and return the values.
  892. (emit-code #f (make-glil-call 'return/nvalues 1))))
  893. ((push)
  894. ;; we only want one value. so ask for one value
  895. (comp-push body)
  896. ;; and unwind, leaving the val on the stack
  897. (emit-code #f (make-glil-call 'unwind 0))
  898. (comp-drop (make-application src unwinder '())))
  899. ((vals)
  900. (let ((MV (make-label)))
  901. (comp-vals body MV)
  902. ;; one value: push 1 and fall through to MV case
  903. (emit-code #f (make-glil-const 1))
  904. (emit-label MV)
  905. ;; multiple values: unwind...
  906. (emit-code #f (make-glil-call 'unwind 0))
  907. (comp-drop (make-application src unwinder '()))
  908. ;; and goto the MVRA.
  909. (emit-branch #f 'br MVRA)))
  910. ((drop)
  911. ;; compile body, discarding values. then unwind...
  912. (comp-drop body)
  913. (emit-code #f (make-glil-call 'unwind 0))
  914. (comp-drop (make-application src unwinder '()))
  915. ;; and fall through, or goto RA if there is one.
  916. (if RA
  917. (emit-branch #f 'br RA)))))
  918. ((<dynlet> src fluids vals body)
  919. (for-each comp-push fluids)
  920. (for-each comp-push vals)
  921. (emit-code #f (make-glil-call 'wind-fluids (length fluids)))
  922. (case context
  923. ((tail)
  924. (let ((MV (make-label)))
  925. ;; NB: in tail case, it is possible to preserve asymptotic tail
  926. ;; recursion, via merging unwind-fluids structures -- but we'd need
  927. ;; to compile in the body twice (once in tail context, assuming the
  928. ;; caller unwinds, and once with this trampoline thing, unwinding
  929. ;; ourselves).
  930. (comp-vals body MV)
  931. ;; one value: unwind and return
  932. (emit-code #f (make-glil-call 'unwind-fluids 0))
  933. (emit-code #f (make-glil-call 'return 1))
  934. (emit-label MV)
  935. ;; multiple values: unwind and return values
  936. (emit-code #f (make-glil-call 'unwind-fluids 0))
  937. (emit-code #f (make-glil-call 'return/nvalues 1))))
  938. ((push)
  939. (comp-push body)
  940. (emit-code #f (make-glil-call 'unwind-fluids 0)))
  941. ((vals)
  942. (let ((MV (make-label)))
  943. (comp-vals body MV)
  944. ;; one value: push 1 and fall through to MV case
  945. (emit-code #f (make-glil-const 1))
  946. (emit-label MV)
  947. ;; multiple values: unwind and goto MVRA
  948. (emit-code #f (make-glil-call 'unwind-fluids 0))
  949. (emit-branch #f 'br MVRA)))
  950. ((drop)
  951. ;; compile body, discarding values. then unwind...
  952. (comp-drop body)
  953. (emit-code #f (make-glil-call 'unwind-fluids 0))
  954. ;; and fall through, or goto RA if there is one.
  955. (if RA
  956. (emit-branch #f 'br RA)))))
  957. ((<dynref> src fluid)
  958. (case context
  959. ((drop)
  960. (comp-drop fluid))
  961. ((push vals tail)
  962. (comp-push fluid)
  963. (emit-code #f (make-glil-call 'fluid-ref 1))))
  964. (maybe-emit-return))
  965. ((<dynset> src fluid exp)
  966. (comp-push fluid)
  967. (comp-push exp)
  968. (emit-code #f (make-glil-call 'fluid-set 2))
  969. (case context
  970. ((push vals tail)
  971. (emit-code #f (make-glil-void))))
  972. (maybe-emit-return))
  973. ;; What's the deal here? The deal is that we are compiling the start of a
  974. ;; delimited continuation. We try to avoid heap allocation in the normal
  975. ;; case; so the body is an expression, not a thunk, and we try to render
  976. ;; the handler inline. Also we did some analysis, in analyze.scm, so that
  977. ;; if the continuation isn't referenced, we don't reify it. This makes it
  978. ;; possible to implement catch and throw with delimited continuations,
  979. ;; without any overhead.
  980. ((<prompt> src tag body handler)
  981. (let ((H (make-label))
  982. (POST (make-label))
  983. (escape-only? (hashq-ref allocation x)))
  984. ;; First, set up the prompt.
  985. (comp-push tag)
  986. (emit-code src (make-glil-prompt H escape-only?))
  987. ;; Then we compile the body, with its normal return path, unwinding
  988. ;; before proceeding.
  989. (case context
  990. ((tail)
  991. (let ((MV (make-label)))
  992. (comp-vals body MV)
  993. ;; one value: unwind and return
  994. (emit-code #f (make-glil-call 'unwind 0))
  995. (emit-code #f (make-glil-call 'return 1))
  996. ;; multiple values: unwind and return
  997. (emit-label MV)
  998. (emit-code #f (make-glil-call 'unwind 0))
  999. (emit-code #f (make-glil-call 'return/nvalues 1))))
  1000. ((push)
  1001. ;; we only want one value. so ask for one value, unwind, and jump to
  1002. ;; post
  1003. (comp-push body)
  1004. (emit-code #f (make-glil-call 'unwind 0))
  1005. (emit-branch #f 'br POST))
  1006. ((vals)
  1007. (let ((MV (make-label)))
  1008. (comp-vals body MV)
  1009. ;; one value: push 1 and fall through to MV case
  1010. (emit-code #f (make-glil-const 1))
  1011. ;; multiple values: unwind and goto MVRA
  1012. (emit-label MV)
  1013. (emit-code #f (make-glil-call 'unwind 0))
  1014. (emit-branch #f 'br MVRA)))
  1015. ((drop)
  1016. ;; compile body, discarding values, then unwind & fall through.
  1017. (comp-drop body)
  1018. (emit-code #f (make-glil-call 'unwind 0))
  1019. (emit-branch #f 'br (or RA POST))))
  1020. (emit-label H)
  1021. ;; Now the handler. The stack is now made up of the continuation, and
  1022. ;; then the args to the continuation (pushed separately), and then the
  1023. ;; number of args, including the continuation.
  1024. (record-case handler
  1025. ((<lambda-case> req opt kw rest gensyms body alternate)
  1026. (if (or opt kw alternate)
  1027. (error "unexpected lambda-case in prompt" x))
  1028. (emit-code src (make-glil-mv-bind
  1029. (vars->bind-list
  1030. (append req (if rest (list rest) '()))
  1031. gensyms allocation self)
  1032. (and rest #t)))
  1033. (for-each (lambda (v)
  1034. (pmatch (hashq-ref (hashq-ref allocation v) self)
  1035. ((#t #f . ,n)
  1036. (emit-code src (make-glil-lexical #t #f 'set n)))
  1037. ((#t #t . ,n)
  1038. (emit-code src (make-glil-lexical #t #t 'box n)))
  1039. (,loc (error "badness" x loc))))
  1040. (reverse gensyms))
  1041. (comp-tail body)
  1042. (emit-code #f (make-glil-unbind))))
  1043. (if (or (eq? context 'push)
  1044. (and (eq? context 'drop) (not RA)))
  1045. (emit-label POST))))
  1046. ((<abort> src tag args tail)
  1047. (comp-push tag)
  1048. (for-each comp-push args)
  1049. (comp-push tail)
  1050. (emit-code src (make-glil-call 'abort (length args)))
  1051. ;; so, the abort can actually return. if it does, the values will be on
  1052. ;; the stack, then the MV marker, just as in an MV context.
  1053. (case context
  1054. ((tail)
  1055. ;; Return values.
  1056. (emit-code #f (make-glil-call 'return/nvalues 1)))
  1057. ((drop)
  1058. ;; Drop all values and goto RA, or otherwise fall through.
  1059. (emit-code #f (make-glil-mv-bind 0 #f))
  1060. (if RA (emit-branch #f 'br RA)))
  1061. ((push)
  1062. ;; Truncate to one value.
  1063. (emit-code #f (make-glil-mv-bind 1 #f)))
  1064. ((vals)
  1065. ;; Go to MVRA.
  1066. (emit-branch #f 'br MVRA)))))))