assemble-wasm.scm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ;;; Assemble --- Command-line Wasm assembler -*- coding: iso-8859-1 -*-
  2. ;;; Copyright (C) 2023 Igalia, S.L.
  3. ;;; Copyright 2005,2008-2011,2013-2015,2017-2020 Free Software Foundation, Inc.
  4. ;;;
  5. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  6. ;;; you may not use this file except in compliance with the License.
  7. ;;; You may obtain a copy of the License at
  8. ;;;
  9. ;;; http://www.apache.org/licenses/LICENSE-2.0
  10. ;;;
  11. ;;; Unless required by applicable law or agreed to in writing, software
  12. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  13. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ;;; See the License for the specific language governing permissions and
  15. ;;; limitations under the License.
  16. ;;; Commentary:
  17. ;;;
  18. ;;; Usage: assemble-wasm [ARGS]
  19. ;;;
  20. ;;; A command-line interface to the Guile Wasm assembler, based on
  21. ;;; Hoot's compile-wasm script.
  22. ;;;
  23. ;;; Code:
  24. (define-module (scripts assemble-wasm)
  25. #:use-module (ice-9 binary-ports)
  26. #:use-module (ice-9 eval-string)
  27. #:use-module (ice-9 format)
  28. #:use-module (ice-9 match)
  29. #:use-module (srfi srfi-1)
  30. #:use-module (srfi srfi-26)
  31. #:use-module (srfi srfi-37)
  32. #:use-module ((wasm assemble) #:select ((assemble-wasm . wasm:assemble-wasm)))
  33. #:use-module (wasm link)
  34. #:use-module (wasm lower)
  35. #:use-module (wasm types)
  36. #:use-module (wasm wat)
  37. #:export (assemble-wasm))
  38. (define %summary "Assemble a Wasm module.")
  39. (define (fail message . args)
  40. (format (current-error-port) "error: ~?~%" message args)
  41. (exit 1))
  42. (define %options
  43. ;; Specifications of the command-line options.
  44. (list (option '(#\h "help") #f #f
  45. (lambda (opt name arg result)
  46. (alist-cons 'help? #t result)))
  47. (option '("version") #f #f
  48. (lambda (opt name arg result)
  49. (show-version)
  50. (exit 0)))
  51. (option '("stdlib") #t #f
  52. (lambda (opt name arg result)
  53. (when (assoc-ref result 'stdlib)
  54. (fail "`--stdlib' option cannot be specified more than once"))
  55. (alist-cons 'stdlib arg result)))
  56. (option '(#\o "output") #t #f
  57. (lambda (opt name arg result)
  58. (if (assoc-ref result 'output-file)
  59. (fail "`-o' option cannot be specified more than once")
  60. (alist-cons 'output-file arg result))))))
  61. (define (parse-args args)
  62. "Parse argument list @var{args} and return an alist with all the relevant
  63. options."
  64. (args-fold args %options
  65. (lambda (opt name arg result)
  66. (format (current-error-port) "~A: unrecognized option~%" name)
  67. (exit 1))
  68. (lambda (file result)
  69. (let ((input-files (assoc-ref result 'input-files)))
  70. (alist-cons 'input-files (cons file input-files)
  71. result)))
  72. ;; default option values
  73. `((input-files))))
  74. (define (show-version)
  75. (format #t "assemble-wasm ~A~%" (version))
  76. (format #t "Copyright (C) 2023 Spritely Institute, Igalia.
  77. Part of guile-hoot:
  78. https://gitlab.com/spritely/guile-hoot
  79. Licensed under the Apache License, Version 2.0:
  80. http://www.apache.org/licenses/LICENSE-2.0
  81. This is free software: you are free to change and redistribute it.
  82. There is NO WARRANTY, to the extent permitted by law.~%"))
  83. (define (read-wat port)
  84. (let ((datum (read port)))
  85. (match datum
  86. (('module . _)
  87. (match (read port)
  88. ((? eof-object?) datum)
  89. (tail (error "unexpected form after (module)" tail))))
  90. (_
  91. (let lp ((datum datum))
  92. (if (eof-object? datum)
  93. '()
  94. (cons datum (lp (read port)))))))))
  95. (define load-stdlib
  96. (let ((module (current-module)))
  97. (lambda (str)
  98. (let ((val (eval-string str #:module module)))
  99. (unless (wasm? val)
  100. (fail "loaded stdlib not a wasm object" val))
  101. val))))
  102. (define (assemble-wasm . args)
  103. (let* ((options (parse-args args))
  104. (help? (assoc-ref options 'help?))
  105. (input-files (assoc-ref options 'input-files))
  106. (output-file (assoc-ref options 'output-file))
  107. (stdlib-expr (assoc-ref options 'stdlib)))
  108. (when (or help? (null? input-files))
  109. (format #t "Usage: assemble-wasm [OPTION] FILE
  110. Compile the WAT source file FILE into a WebAssembly module file.
  111. -h, --help print this help message
  112. --stdlib=EXPR evaluate EXPR to produce a wasm module which
  113. should provide any definitions missing in FILE
  114. -o, --output=OFILE write output to OFILE
  115. Report bugs to <~A>.~%"
  116. %guile-bug-report-address)
  117. (exit 0))
  118. (unless output-file
  119. (fail "missing output file (pass `-o FILE')"))
  120. ;; Install a SIGINT handler. As a side effect, this gives unwind
  121. ;; handlers an opportunity to run upon SIGINT; this includes that of
  122. ;; 'call-with-output-file/atomic', called by 'compile-file', which
  123. ;; removes the temporary output file.
  124. (sigaction SIGINT
  125. (lambda args
  126. (fail "interrupted by the user")))
  127. (define link-stdlib
  128. (if stdlib-expr
  129. (let ((stdlib (load-stdlib stdlib-expr)))
  130. (lambda (wasm) (add-stdlib wasm stdlib)))
  131. (lambda (wasm) wasm)))
  132. (match input-files
  133. (() (fail "missing input file"))
  134. ((input-file)
  135. (let ((expr (call-with-input-file input-file read-wat)))
  136. (call-with-output-file output-file
  137. (cut put-bytevector <>
  138. (wasm:assemble-wasm
  139. (lower-wasm (link-stdlib (wat->wasm expr)))))))
  140. (format #t "wrote `~A'\n" output-file))
  141. (_ (fail "multiple input files not supported")))))
  142. (define main assemble-wasm)