hoot.scm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. ;;; Continuation-passing style (CPS) intermediate language (IL)
  2. ;; Copyright (C) 2023 Free Software Foundation, Inc.
  3. ;;; This library is free software; you can redistribute it and/or modify it
  4. ;;; under the terms of the GNU Lesser General Public License as published by
  5. ;;; the Free Software Foundation; either version 3 of the License, or (at
  6. ;;; your option) any later version.
  7. ;;;
  8. ;;; This library is distributed in the hope that it will be useful, but
  9. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
  11. ;;; General Public License for more details.
  12. ;;;
  13. ;;; You should have received a copy of the GNU Lesser General Public License
  14. ;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Backend-specific lowering and optimization when targetting the Hoot
  18. ;;; Wasm/GC run-time.
  19. ;;;
  20. ;;; Code:
  21. (define-module (language cps hoot)
  22. #:use-module (ice-9 match)
  23. #:use-module (language cps dce)
  24. #:use-module (language cps simplify)
  25. #:use-module ((language cps utils) #:select (primcall-raw-representations))
  26. #:use-module (language cps verify)
  27. #:use-module (language cps hoot lower-primcalls)
  28. #:use-module (language cps hoot tailify)
  29. #:use-module (language cps hoot unify-returns)
  30. #:use-module (wasm types)
  31. #:export (hoot-primcall-raw-representations
  32. make-lowerer
  33. available-optimizations
  34. target-hash
  35. target-symbol-hash
  36. target-symbol-hash-bits
  37. target-keyword-hash
  38. target-has-unbound-boxes?))
  39. (define (hoot-primcall-raw-representations name param)
  40. (case name
  41. ((restore) param) ;; param is list of representations.
  42. ((flonum->f64 compnum-real compnum-imag) '(f64))
  43. ((inline-wasm)
  44. (match param
  45. (($ <func> id
  46. ($ <type-use> #f ($ <func-sig> params results))
  47. locals body)
  48. (map (match-lambda
  49. (($ <ref-type> #f 'eq) 'scm)
  50. ('i64 's64)
  51. ('f64 'f64))
  52. results))))
  53. ((import-wasm) '())
  54. (else (primcall-raw-representations name param))))
  55. (define *debug?* #f)
  56. (define (maybe-verify program)
  57. (if *debug?*
  58. (verify program)
  59. program))
  60. (define-syntax-rule (define-optimizer optimize (pass kw) ...)
  61. (define* (optimize program #:optional (opts '()))
  62. (let* ((program (maybe-verify program))
  63. (program (if (assq-ref opts kw)
  64. (maybe-verify (pass program))
  65. program))
  66. ...)
  67. program)))
  68. (define (available-optimizations)
  69. '((#:eliminate-dead-code? 2)
  70. (#:simplify? 1)))
  71. (define-optimizer optimize-hoot-backend-cps
  72. (eliminate-dead-code #:eliminate-dead-code?)
  73. (simplify #:simplify?))
  74. (define (select-optimizations optimization-level opts all-opts)
  75. (define (kw-arg-ref args kw default)
  76. (match (memq kw args)
  77. ((_ val . _) val)
  78. (_ default)))
  79. (define (enabled-for-level? level) (<= level optimization-level))
  80. (let lp ((all-opts all-opts))
  81. (match all-opts
  82. (() '())
  83. (((kw level) . all-opts)
  84. (acons kw (kw-arg-ref opts kw (enabled-for-level? level))
  85. (lp all-opts))))))
  86. (define (make-lowerer optimization-level opts)
  87. (let ((opts (select-optimizations optimization-level opts
  88. (available-optimizations))))
  89. (lambda (exp env)
  90. (optimize-hoot-backend-cps
  91. (unify-returns
  92. (tailify
  93. (lower-primcalls exp)
  94. #:primcall-raw-representations hoot-primcall-raw-representations))
  95. opts))))
  96. ;; Thomas Wang's 32-bit integer hasher, from
  97. ;; http://www.cris.com/~Ttwang/tech/inthash.htm.
  98. (define (hash-i32 i)
  99. ;; 32-bit hash
  100. (define (i32 i) (logand i #xffffffff))
  101. (let* ((i (i32 i))
  102. (i (i32 (logxor (logxor i 61) (ash i -16))))
  103. (i (i32 (+ i (i32 (ash i 3)))))
  104. (i (i32 (logxor i (ash i -4))))
  105. (i (i32 (* i #x27d4eb2d))))
  106. (i32 (logxor i (ash i -15)))))
  107. (define (finish-heap-object-hash h)
  108. (let ((h (hash-i32 h)))
  109. (if (= h 0)
  110. (hash-i32 42)
  111. h)))
  112. ;; FIXME: leakage of host hash function to guest. Though it's valid for
  113. ;; our use case to generate hashq values, it's not reproducible.
  114. (define (hashq-constant x)
  115. (finish-heap-object-hash (hash x (ash 1 32))))
  116. (define (target-hash obj)
  117. (hashq-constant obj))
  118. (define (target-symbol-hash str)
  119. (finish-heap-object-hash
  120. (string-fold (lambda (ch h)
  121. (logand #xffffffff (+ (* h 31) (char->integer ch))))
  122. 0
  123. str)))
  124. (define target-symbol-hash-bits 32)
  125. (define (target-keyword-hash str)
  126. (finish-heap-object-hash (target-symbol-hash str)))
  127. (define target-has-unbound-boxes? #f)