reify-primitives.scm 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. ;;; Continuation-passing style (CPS) intermediate language (IL)
  2. ;; Copyright (C) 2013-2021 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. ;;; Commentary:
  17. ;;;
  18. ;;; A pass to reify lone $prim's that were never folded into a
  19. ;;; $primcall, and $primcall's to primitives that don't have a
  20. ;;; corresponding VM op.
  21. ;;;
  22. ;;; Code:
  23. (define-module (language cps reify-primitives)
  24. #:use-module (ice-9 match)
  25. #:use-module (language cps)
  26. #:use-module (language cps utils)
  27. #:use-module (language cps with-cps)
  28. #:use-module (language cps intmap)
  29. #:use-module (language bytecode)
  30. #:use-module (system base target)
  31. #:use-module (system base types internal)
  32. #:export (reify-primitives))
  33. (define (primitive-module name)
  34. (case name
  35. ((bytevector?
  36. bytevector-length
  37. bytevector-u8-ref bytevector-u8-set!
  38. bytevector-s8-ref bytevector-s8-set!
  39. bytevector-u16-ref bytevector-u16-set!
  40. bytevector-u16-native-ref bytevector-u16-native-set!
  41. bytevector-s16-ref bytevector-s16-set!
  42. bytevector-s16-native-ref bytevector-s16-native-set!
  43. bytevector-u32-ref bytevector-u32-set!
  44. bytevector-u32-native-ref bytevector-u32-native-set!
  45. bytevector-s32-ref bytevector-s32-set!
  46. bytevector-s32-native-ref bytevector-s32-native-set!
  47. bytevector-u64-ref bytevector-u64-set!
  48. bytevector-u64-native-ref bytevector-u64-native-set!
  49. bytevector-s64-ref bytevector-s64-set!
  50. bytevector-s64-native-ref bytevector-s64-native-set!
  51. bytevector-ieee-single-ref bytevector-ieee-single-set!
  52. bytevector-ieee-single-native-ref bytevector-ieee-single-native-set!
  53. bytevector-ieee-double-ref bytevector-ieee-double-set!
  54. bytevector-ieee-double-native-ref bytevector-ieee-double-native-set!)
  55. '(rnrs bytevectors))
  56. ((atomic-box?
  57. make-atomic-box atomic-box-ref atomic-box-set!
  58. atomic-box-swap! atomic-box-compare-and-swap!)
  59. '(ice-9 atomic))
  60. ((current-thread) '(ice-9 threads))
  61. ((class-of) '(oop goops))
  62. ((u8vector-ref
  63. u8vector-set! s8vector-ref s8vector-set!
  64. u16vector-ref u16vector-set! s16vector-ref s16vector-set!
  65. u32vector-ref u32vector-set! s32vector-ref s32vector-set!
  66. u64vector-ref u64vector-set! s64vector-ref s64vector-set!
  67. f32vector-ref f32vector-set! f64vector-ref f64vector-set!)
  68. '(srfi srfi-4))
  69. (else '(guile))))
  70. (define (primitive-ref cps name k src)
  71. (with-cps cps
  72. (letv box)
  73. (letk kbox ($kargs ('box) (box)
  74. ($continue k src
  75. ($primcall 'scm-ref/immediate '(box . 1) (box)))))
  76. ($ ((hashq-ref *ephemeral-reifiers* 'cached-module-box)
  77. kbox src (list (primitive-module name) name #f #t) '()))))
  78. (define (builtin-ref cps idx k src)
  79. (with-cps cps
  80. (build-term
  81. ($continue k src ($primcall 'builtin-ref idx ())))))
  82. (define (reify-clause cps)
  83. (with-cps cps
  84. (let$ body
  85. (with-cps-constants ((wna 'wrong-number-of-args)
  86. (args '(#f "Wrong number of arguments" () #f)))
  87. (build-term ($throw #f 'throw #f (wna args)))))
  88. (letk kbody ($kargs () () ,body))
  89. (letk kclause ($kclause ('() '() #f '() #f) kbody #f))
  90. kclause))
  91. (define (wrap-unary cps k src wrap unwrap op param a)
  92. (with-cps cps
  93. (letv a* res*)
  94. (letk kres ($kargs ('res*) (res*)
  95. ($continue k src
  96. ($primcall 'u64->s64 #f (res*)))))
  97. (letk ka ($kargs ('a*) (a*)
  98. ($continue kres src
  99. ($primcall op param (a*)))))
  100. (build-term
  101. ($continue ka src
  102. ($primcall 's64->u64 #f (a))))))
  103. (define (wrap-binary cps k src wrap unwrap op param a b)
  104. (with-cps cps
  105. (letv a* b* res*)
  106. (letk kres ($kargs ('res*) (res*)
  107. ($continue k src
  108. ($primcall 'u64->s64 #f (res*)))))
  109. (letk kb ($kargs ('b*) (b*)
  110. ($continue kres src
  111. ($primcall op param (a* b*)))))
  112. (letk ka ($kargs ('a*) (a*)
  113. ($continue kb src
  114. ($primcall 's64->u64 #f (b)))))
  115. (build-term
  116. ($continue ka src
  117. ($primcall 's64->u64 #f (a))))))
  118. (define (wrap-binary/exp cps k src wrap unwrap op param a b-exp)
  119. (with-cps cps
  120. (letv a* b* res*)
  121. (letk kres ($kargs ('res*) (res*)
  122. ($continue k src
  123. ($primcall 'u64->s64 #f (res*)))))
  124. (letk kb ($kargs ('b*) (b*)
  125. ($continue kres src
  126. ($primcall op param (a* b*)))))
  127. (letk ka ($kargs ('a*) (a*)
  128. ($continue kb src ,b-exp)))
  129. (build-term
  130. ($continue ka src
  131. ($primcall 's64->u64 #f (a))))))
  132. ;; Primitives that we need to remove.
  133. (define *ephemeral-reifiers* (make-hash-table))
  134. (define-syntax-rule (define-ephemeral (name cps k src param arg ...)
  135. . body)
  136. (hashq-set! *ephemeral-reifiers* 'name
  137. (lambda (cps k src param args)
  138. (match args ((arg ...) (let () . body))))))
  139. (define-ephemeral (fadd/immediate cps k src param a)
  140. (with-cps cps
  141. (letv b)
  142. (letk kb ($kargs ('b) (b)
  143. ($continue k src
  144. ($primcall 'fadd #f (a b)))))
  145. (build-term
  146. ($continue kb src
  147. ($primcall 'load-f64 param ())))))
  148. (define-syntax-rule (define-binary-signed-ephemeral name uname)
  149. (define-ephemeral (name cps k src param a b)
  150. (wrap-binary cps k src 's64->u64 'u64->s64 'uname #f a b)))
  151. (define-binary-signed-ephemeral sadd uadd)
  152. (define-binary-signed-ephemeral ssub usub)
  153. (define-binary-signed-ephemeral smul umul)
  154. (define-syntax-rule (define-binary-signed-ephemeral/imm name/imm
  155. uname/imm uname)
  156. (define-ephemeral (name/imm cps k src param a)
  157. (if (and (exact-integer? param) (<= 0 param 255))
  158. (wrap-unary cps k src 's64->u64 'u64->s64 'uname/imm param a)
  159. (wrap-binary/exp cps k src 's64->u64 'u64->s64 'uname #f a
  160. (let ((param (logand param (1- (ash 1 64)))))
  161. (build-exp ($primcall 'load-u64 param ())))))))
  162. (define-binary-signed-ephemeral/imm sadd/immediate uadd/immediate uadd)
  163. (define-binary-signed-ephemeral/imm ssub/immediate usub/immediate usub)
  164. (define-binary-signed-ephemeral/imm smul/immediate umul/immediate umul)
  165. (define-ephemeral (slsh cps k src param a b)
  166. (wrap-binary/exp cps k src 's64->u64 'u64->s64 'ulsh #f a
  167. (build-exp ($values (b)))))
  168. (define-ephemeral (slsh/immediate cps k src param a)
  169. (wrap-unary cps k src 's64->u64 'u64->s64 'ulsh/immediate param a))
  170. (define (reify-lookup cps src mod-var name assert-bound? have-var)
  171. (with-cps cps
  172. (letv name-var var)
  173. (let$ body (have-var var))
  174. (letk kres ($kargs ('var) (var) ,body))
  175. (letk klookup ($kargs ('name) (name-var)
  176. ($continue kres src
  177. ($primcall (if assert-bound? 'lookup-bound 'lookup) #f
  178. (mod-var name-var)))))
  179. (build-term ($continue klookup src ($const name)))))
  180. (define (reify-resolve-module cps k src module public?)
  181. (with-cps cps
  182. (letv mod-name)
  183. (letk kresolve
  184. ($kargs ('mod-name) (mod-name)
  185. ($continue k src
  186. ($primcall 'resolve-module public? (mod-name)))))
  187. (build-term
  188. ($continue kresolve src ($const module)))))
  189. (define-ephemeral (cached-module-box cps k src param)
  190. (match param
  191. ((module name public? #t)
  192. (let ((cache-key param))
  193. (with-cps cps
  194. (letv cached var)
  195. (letk k* ($kargs () () ($continue k src ($values (var)))))
  196. (letk kcache ($kargs ('var) (var)
  197. ($continue k* src
  198. ($primcall 'cache-set! cache-key (var)))))
  199. (letk kinit ($kargs () ()
  200. ($continue kcache src
  201. ($primcall (if public?
  202. 'lookup-bound-public
  203. 'lookup-bound-private)
  204. (list module name) ()))))
  205. (letk kok ($kargs () ()
  206. ($continue k src ($values (cached)))))
  207. (letk ktest
  208. ($kargs ('cached) (cached)
  209. ($branch kinit kok src 'heap-object? #f (cached))))
  210. (build-term
  211. ($continue ktest src
  212. ($primcall 'cache-ref cache-key ()))))))
  213. ((module name public? bound?)
  214. (let ((cache-key param))
  215. (with-cps cps
  216. (letv mod cached)
  217. (let$ lookup
  218. (reify-lookup
  219. src mod name bound?
  220. (lambda (cps var)
  221. (with-cps cps
  222. (letk k* ($kargs () () ($continue k src ($values (var)))))
  223. (build-term
  224. ($continue k* src
  225. ($primcall 'cache-set! cache-key (var))))))))
  226. (letk kmod ($kargs ('mod) (mod) ,lookup))
  227. (let$ module (reify-resolve-module kmod src module public?))
  228. (letk kinit ($kargs () () ,module))
  229. (letk kok ($kargs () () ($continue k src ($values (cached)))))
  230. (letk ktest
  231. ($kargs ('cached) (cached)
  232. ($branch kinit kok src 'heap-object? #f (cached))))
  233. (build-term
  234. ($continue ktest src
  235. ($primcall 'cache-ref cache-key ()))))))))
  236. (define-ephemeral (cache-current-module! cps k src param mod)
  237. (match param
  238. ((scope)
  239. (with-cps cps
  240. (build-term
  241. ($continue k src
  242. ($primcall 'cache-set! scope (mod))))))))
  243. (define-ephemeral (cached-toplevel-box cps k src param)
  244. (match param
  245. ((scope name bound?)
  246. (let ((cache-key (cons scope name)))
  247. (with-cps cps
  248. (letv mod cached)
  249. (let$ lookup
  250. (reify-lookup
  251. src mod name bound?
  252. (lambda (cps var)
  253. (with-cps cps
  254. (letk k* ($kargs () () ($continue k src ($values (var)))))
  255. (build-term
  256. ($continue k* src
  257. ($primcall 'cache-set! cache-key (var))))))))
  258. (letk kmod ($kargs ('mod) (mod) ,lookup))
  259. (letk kinit ($kargs () ()
  260. ($continue kmod src ($primcall 'cache-ref scope ()))))
  261. (letk kok ($kargs () () ($continue k src ($values (cached)))))
  262. (letk ktest
  263. ($kargs ('cached) (cached)
  264. ($branch kinit kok src 'heap-object? #f (cached))))
  265. (build-term
  266. ($continue ktest src
  267. ($primcall 'cache-ref cache-key ()))))))))
  268. ;; FIXME: Instead of having to check this, instead every primcall that's
  269. ;; not ephemeral should be handled by compile-bytecode.
  270. (define (compute-known-primitives)
  271. (define *macro-instructions*
  272. '(add
  273. add/immediate
  274. sub
  275. sub/immediate
  276. mul
  277. div
  278. quo
  279. rem
  280. mod
  281. inexact
  282. sqrt
  283. abs
  284. floor
  285. ceiling
  286. sin
  287. cos
  288. tan
  289. asin
  290. acos
  291. atan
  292. atan2
  293. fsqrt
  294. fabs
  295. ffloor
  296. fceiling
  297. fsin
  298. fcos
  299. ftan
  300. fasin
  301. facos
  302. fatan
  303. fatan2
  304. logand
  305. logior
  306. logxor
  307. logsub
  308. string-set!
  309. string->number
  310. string->symbol
  311. symbol->keyword
  312. class-of
  313. scm->f64
  314. s64->u64 s64->scm scm->s64
  315. u64->s64 u64->scm scm->u64 scm->u64/truncate
  316. wind unwind
  317. push-fluid pop-fluid fluid-ref fluid-set!
  318. push-dynamic-state pop-dynamic-state
  319. lsh rsh lsh/immediate rsh/immediate
  320. cache-ref cache-set!
  321. current-module resolve-module
  322. module-variable define!
  323. lookup lookup-bound lookup-bound-public lookup-bound-private))
  324. (let ((table (make-hash-table)))
  325. (for-each
  326. (match-lambda ((inst . _) (hashq-set! table inst #t)))
  327. (instruction-list))
  328. (for-each
  329. (lambda (prim) (hashq-set! table prim #t))
  330. *macro-instructions*)
  331. table))
  332. (define *known-primitives* (delay (compute-known-primitives)))
  333. (define (known-primitive? name)
  334. "Is @var{name} a primitive that can be lowered to bytecode?"
  335. (hashq-ref (force *known-primitives*) name))
  336. (define (reify-primitives cps)
  337. (define (visit-cont label cont cps)
  338. (define (resolve-prim cps name k src)
  339. (cond
  340. ((builtin-name->index name)
  341. => (lambda (idx) (builtin-ref cps idx k src)))
  342. (else
  343. (primitive-ref cps name k src))))
  344. (match cont
  345. (($ $kfun src meta self tail #f)
  346. (with-cps cps
  347. (let$ clause (reify-clause))
  348. (setk label ($kfun src meta self tail clause))))
  349. (($ $kargs names vars ($ $continue k src ($ $prim name)))
  350. (with-cps cps
  351. (let$ body (resolve-prim name k src))
  352. (setk label ($kargs names vars ,body))))
  353. (($ $kargs names vars
  354. ($ $continue k src ($ $primcall 'call-thunk/no-inline #f (proc))))
  355. (with-cps cps
  356. (setk label ($kargs names vars ($continue k src ($call proc ()))))))
  357. (($ $kargs names vars
  358. ($ $continue k src ($ $primcall 'f64->scm #f (f64))))
  359. (with-cps cps
  360. (letv scm tag ptr uidx)
  361. (letk kdone ($kargs () ()
  362. ($continue k src ($values (scm)))))
  363. (letk kinit ($kargs ('uidx) (uidx)
  364. ($continue kdone src
  365. ($primcall 'f64-set! 'flonum (scm ptr uidx f64)))))
  366. (letk kidx ($kargs ('ptr) (ptr)
  367. ($continue kinit src ($primcall 'load-u64 0 ()))))
  368. (letk kptr ($kargs () ()
  369. ($continue kidx src
  370. ($primcall 'tail-pointer-ref/immediate
  371. `(flonum . ,(match (target-word-size)
  372. (4 2)
  373. (8 1)))
  374. (scm)))))
  375. (letk ktag1 ($kargs ('tag) (tag)
  376. ($continue kptr src
  377. ($primcall 'word-set!/immediate '(flonum . 0) (scm tag)))))
  378. (letk ktag0 ($kargs ('scm) (scm)
  379. ($continue ktag1 src
  380. ($primcall 'load-u64 %tc16-flonum ()))))
  381. (setk label ($kargs names vars
  382. ($continue ktag0 src
  383. ($primcall 'allocate-pointerless-words/immediate
  384. `(flonum . ,(match (target-word-size)
  385. (4 4)
  386. (8 2)))
  387. ()))))))
  388. (($ $kargs names vars
  389. ($ $continue k src ($ $primcall 'u64->scm/unlikely #f (u64))))
  390. (with-cps cps
  391. (setk label ($kargs names vars
  392. ($continue k src ($primcall 'u64->scm #f (u64)))))))
  393. (($ $kargs names vars
  394. ($ $continue k src ($ $primcall 's64->scm/unlikely #f (s64))))
  395. (with-cps cps
  396. (setk label ($kargs names vars
  397. ($continue k src ($primcall 's64->scm #f (s64)))))))
  398. (($ $kargs names vars
  399. ($ $continue k src ($ $primcall 'tag-fixnum/unlikely #f (s64))))
  400. (with-cps cps
  401. (setk label ($kargs names vars
  402. ($continue k src ($primcall 'tag-fixnum #f (s64)))))))
  403. (($ $kargs names vars
  404. ($ $continue k src ($ $primcall 'load-const/unlikely val ())))
  405. (with-cps cps
  406. (setk label ($kargs names vars ($continue k src ($const val))))))
  407. (($ $kargs names vars
  408. ($ $continue k src ($ $primcall 'mul/immediate b (a))))
  409. (with-cps cps
  410. (letv b*)
  411. (letk kb ($kargs ('b) (b*)
  412. ($continue k src ($primcall 'mul #f (a b*)))))
  413. (setk label ($kargs names vars
  414. ($continue kb src ($const b))))))
  415. (($ $kargs names vars
  416. ($ $continue k src
  417. ($ $primcall (or 'assume-u64 'assume-s64) (lo . hi) (val))))
  418. (with-cps cps
  419. (setk label ($kargs names vars
  420. ($continue k src ($values (val)))))))
  421. (($ $kargs names vars ($ $continue k src ($ $primcall name param args)))
  422. (cond
  423. ((hashq-ref *ephemeral-reifiers* name)
  424. => (lambda (reify)
  425. (with-cps cps
  426. (let$ body (reify k src param args))
  427. (setk label ($kargs names vars ,body)))))
  428. ((known-primitive? name)
  429. ;; Assume arities are correct.
  430. (let ()
  431. (define (u6? val) (and (exact-integer? val) (<= 0 val 63)))
  432. (define (u8? val) (and (exact-integer? val) (<= 0 val 255)))
  433. (define-syntax-rule (reify-constants
  434. wrap
  435. ((op (pred? c) in ...) (op* out ...))
  436. ...
  437. (_ default))
  438. (match name
  439. ('op
  440. (if (pred? param)
  441. cps
  442. (match args
  443. ((in ...)
  444. (with-cps cps
  445. (letv c)
  446. (letk kconst ($kargs ('c) (c)
  447. ($continue k src
  448. ($primcall 'op* #f (out ...)))))
  449. (setk label
  450. ($kargs names vars
  451. ($continue kconst src wrap))))))))
  452. ...
  453. (_ default)))
  454. (define-syntax-rule (reify-scm-constants clause ...)
  455. (reify-constants ($const param) clause ...))
  456. (define-syntax-rule (reify-u64-constants clause ...)
  457. (reify-constants ($primcall 'load-u64 param ()) clause ...))
  458. (reify-scm-constants
  459. ((add/immediate (u8? y) x) (add x y))
  460. ((sub/immediate (u8? y) x) (sub x y))
  461. (_
  462. (reify-u64-constants
  463. ((uadd/immediate (u8? y) x) (uadd x y))
  464. ((usub/immediate (u8? y) x) (usub x y))
  465. ((umul/immediate (u8? y) x) (umul x y))
  466. ((rsh/immediate (u6? y) x) (rsh x y))
  467. ((lsh/immediate (u6? y) x) (lsh x y))
  468. ;; These should all be u6's by construction.
  469. ;; ((ursh/immediate (u6? y) x) (ursh x y))
  470. ;; ((srsh/immediate (u6? y) x) (srsh x y))
  471. ;; ((ulsh/immediate (u6? y) x) (ulsh x y))
  472. (_
  473. (match (cons name args)
  474. (((or 'allocate-words/immediate
  475. 'allocate-pointerless-words/immediate))
  476. (define op
  477. (match name
  478. ('allocate-words/immediate
  479. 'allocate-words)
  480. ('allocate-pointerless-words/immediate
  481. 'allocate-pointerless-words)))
  482. (match param
  483. ((ann . n)
  484. (if (u8? n)
  485. cps
  486. (with-cps cps
  487. (letv n*)
  488. (letk kop ($kargs ('n) (n*)
  489. ($continue k src
  490. ($primcall op ann (n*)))))
  491. (setk label ($kargs names vars
  492. ($continue kop src
  493. ($primcall 'load-u64 n ())))))))))
  494. ;; Assume (tail-)pointer-ref/immediate is within u8 range.
  495. (((or 'word-ref/immediate 'scm-ref/immediate) obj)
  496. (match param
  497. ((ann . idx)
  498. (if (u8? idx)
  499. cps
  500. (let ((op (match name
  501. ('word-ref/immediate 'word-ref)
  502. ('scm-ref/immediate 'scm-ref))))
  503. (with-cps cps
  504. (letv idx*)
  505. (letk kop ($kargs ('idx) (idx*)
  506. ($continue k src
  507. ($primcall op ann (obj idx*)))))
  508. (setk label ($kargs names vars
  509. ($continue kop src
  510. ($primcall 'load-u64 idx ()))))))))))
  511. (((or 'word-set!/immediate 'scm-set!/immediate) obj val)
  512. (match param
  513. ((ann . idx)
  514. (if (u8? idx)
  515. cps
  516. (let ((op (match name
  517. ('word-set!/immediate 'word-set!)
  518. ('scm-set!/immediate 'scm-set!))))
  519. (with-cps cps
  520. (letv idx*)
  521. (letk kop ($kargs ('idx) (idx*)
  522. ($continue k src
  523. ($primcall op ann (obj idx* val)))))
  524. (setk label ($kargs names vars
  525. ($continue kop src
  526. ($primcall 'load-u64 idx ()))))))))))
  527. (_ cps))))))))
  528. (param (error "unexpected param to reified primcall" name))
  529. (else
  530. (with-cps cps
  531. (letv proc)
  532. (letk krecv ($kreceive '(res) #f k))
  533. (letk kproc ($kargs ('proc) (proc)
  534. ($continue krecv src ($call proc args))))
  535. (let$ body (resolve-prim name kproc src))
  536. (setk label ($kargs names vars ,body))))))
  537. (($ $kargs names vars ($ $branch kf kt src name param args))
  538. (let ()
  539. (define (u11? val) (<= 0 val #x7ff))
  540. (define (u12? val) (<= 0 val #xfff))
  541. (define (s12? val) (<= (- #x800) val #x7ff))
  542. (define (imm16? val)
  543. (and=> (scm->immediate-bits val)
  544. (lambda (bits)
  545. (truncate-bits bits 16 #t))))
  546. (define (load-u64 k param)
  547. (build-term ($continue k src ($primcall 'load-u64 param ()))))
  548. (define (load-s64 k param)
  549. (build-term ($continue k src ($primcall 'load-s64 param ()))))
  550. (define (load-const k param)
  551. (build-term ($continue k src ($const param))))
  552. (define-syntax-rule (reify-constants ((op (pred? c) in ...)
  553. wrap (op* out ...))
  554. ...
  555. (_ default))
  556. (match name
  557. ('op
  558. (if (pred? param)
  559. cps
  560. (match args
  561. ((in ...)
  562. (with-cps cps
  563. (letv c)
  564. (letk kconst
  565. ($kargs ('c) (c)
  566. ($branch kf kt src 'op* #f (out ...))))
  567. (setk label
  568. ($kargs names vars ,(wrap kconst param))))))))
  569. ...
  570. (_ default)))
  571. (reify-constants
  572. ((u64-imm-= (u11? b) a) load-u64 (u64-= a b))
  573. ((u64-imm-< (u12? b) a) load-u64 (u64-< a b))
  574. ((imm-u64-< (u12? a) b) load-u64 (u64-< a b))
  575. ((s64-imm-= (s12? b) a) load-s64 (s64-= a b))
  576. ((s64-imm-< (s12? b) a) load-s64 (s64-< a b))
  577. ((imm-s64-< (s12? a) b) load-s64 (s64-< a b))
  578. ((eq-constant? (imm16? b) a) load-const (eq? a b))
  579. (_ cps))))
  580. (_ cps)))
  581. (with-fresh-name-state cps
  582. (persistent-intmap (intmap-fold visit-cont cps cps))))