resolve.scm 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. ;;; WebAssembly resolver
  2. ;;; Copyright (C) 2023 Igalia, S.L.
  3. ;;; Copyright (C) 2023 Robin Templeton <robin@spritely.institute>
  4. ;;; Copyright (C) 2023, 2024 David Thompson <dave@spritely.institute>
  5. ;;;
  6. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  7. ;;; you may not use this file except in compliance with the License.
  8. ;;; You may obtain a copy of the License at
  9. ;;;
  10. ;;; http://www.apache.org/licenses/LICENSE-2.0
  11. ;;;
  12. ;;; Unless required by applicable law or agreed to in writing, software
  13. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  14. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ;;; See the License for the specific language governing permissions and
  16. ;;; limitations under the License.
  17. ;;; Commentary:
  18. ;;;
  19. ;;; Lowers WASM with human readable identifiers to WASM with only
  20. ;;; index references.
  21. ;;;
  22. ;;; Code:
  23. (define-module (wasm resolve)
  24. #:use-module (ice-9 match)
  25. #:use-module ((srfi srfi-1) #:select (find list-index))
  26. #:use-module (srfi srfi-11)
  27. #:use-module (wasm types)
  28. #:export (resolve-wasm
  29. unresolve-wasm))
  30. (define (fold1 f l s0)
  31. (let lp ((l l) (s0 s0))
  32. (match l
  33. (() s0)
  34. ((elt . l) (lp l (f elt s0))))))
  35. (define (alist-sort alist)
  36. (sort alist (lambda (a b) (< (car a) (car b)))))
  37. (define (make-name-store)
  38. (let ((count 0)
  39. (ids (make-hash-table)))
  40. (values (lambda (id)
  41. (let ((idx count))
  42. (set! count (1+ count))
  43. (when id (hashq-set! ids id idx))
  44. idx))
  45. (lambda (id)
  46. (cond
  47. ((exact-integer? id) id)
  48. ((hashq-ref ids id))
  49. (else (error "unbound identifier" id))))
  50. (lambda ()
  51. (alist-sort
  52. (hash-fold (lambda (name idx result)
  53. (cons (cons idx name) result))
  54. '() ids))))))
  55. (define (make-indirect-name-store)
  56. (let ((table (make-hash-table)))
  57. (values (lambda (parent-id parent-idx id)
  58. (match (hashq-ref table parent-idx)
  59. (#f
  60. (let-values (((add-id! resolve-id name-map) (make-name-store)))
  61. (let ((procs (list add-id! resolve-id name-map)))
  62. (hashq-set! table parent-idx procs)
  63. (when parent-id
  64. (hashq-set! table parent-id procs)))
  65. (add-id! id)))
  66. ((add-id! resolve-id name-map)
  67. (add-id! id))))
  68. (lambda (parent-id-or-idx id-or-idx)
  69. (if (exact-integer? id-or-idx)
  70. id-or-idx
  71. (match (hashq-ref table parent-id-or-idx)
  72. ((add-id! resolve-id name-map)
  73. (resolve-id id-or-idx)))))
  74. (lambda ()
  75. (alist-sort
  76. (hash-fold
  77. (lambda (id-or-idx procs result)
  78. (if (exact-integer? id-or-idx)
  79. (match procs
  80. ((_ _ name-map)
  81. (match (name-map)
  82. ((name-map ..1) (cons (cons id-or-idx name-map) result))
  83. (_ result))))
  84. result))
  85. '()
  86. table))))))
  87. (define* (resolve-wasm mod #:key name-section?)
  88. (define-values (add-type-id! resolve-type type-name-map) (make-name-store))
  89. (define-values (add-func-id! resolve-func func-name-map) (make-name-store))
  90. (define-values (add-table-id! resolve-table table-name-map) (make-name-store))
  91. (define-values (add-memory-id! resolve-memory memory-name-map) (make-name-store))
  92. (define-values (add-global-id! resolve-global global-name-map) (make-name-store))
  93. (define-values (add-elem-id! resolve-elem elem-name-map) (make-name-store))
  94. (define-values (add-data-id! resolve-data data-name-map) (make-name-store))
  95. (define-values (add-tag-id! resolve-tag tag-name-map) (make-name-store))
  96. (define-values (add-struct-field! resolve-struct-field struct-field-name-map)
  97. (make-indirect-name-store))
  98. (define-values (add-func-local! resolve-func-local func-local-name-map)
  99. (make-indirect-name-store))
  100. (define-values (add-func-label! resolve-func-label func-label-name-map)
  101. (make-indirect-name-store))
  102. (define (add-func-locals! func)
  103. (match func
  104. (($ <func> id ($ <type-use> _ type) locals)
  105. (let ((idx (resolve-func id)))
  106. (for-each (lambda (local-id)
  107. (add-func-local! id idx local-id))
  108. (append (map param-id (func-sig-params type))
  109. (map local-id locals)))))))
  110. (define (add-func-labels! func)
  111. (match func
  112. (($ <func> id _ _ body)
  113. (let ((idx (resolve-func id)))
  114. (let loop ((insts body))
  115. (match insts
  116. (() #t)
  117. ((((or 'block 'loop) label _ body) . rest)
  118. (add-func-label! id idx label)
  119. (loop body)
  120. (loop rest))
  121. ((('if label _ consequent alternate) . rest)
  122. (add-func-label! id idx label)
  123. (loop consequent)
  124. (loop alternate)
  125. (loop rest))
  126. ((_ . rest)
  127. (loop rest))))))))
  128. (define (resolve-memarg memarg)
  129. (match memarg
  130. (($ <mem-arg> id offset align)
  131. (make-mem-arg (resolve-memory id) offset align))))
  132. (define interned-strings (make-hash-table))
  133. (define interned-string-count 0)
  134. (define (intern-string string)
  135. (or (hash-ref interned-strings string)
  136. (let ((idx interned-string-count))
  137. (hash-set! interned-strings string idx)
  138. (set! interned-string-count (1+ idx))
  139. idx)))
  140. (define functions-used-as-values (make-hash-table))
  141. (define (record-function-used-as-value idx)
  142. (unless (exact-integer? idx) (error "expected resolved idx"))
  143. (hashv-set! functions-used-as-values idx #t)
  144. idx)
  145. (define (type-use-matcher params results)
  146. (define param-type (match-lambda (($ <param> id type) type)))
  147. (lambda (rec type-id type-idx supers type)
  148. (and (null? supers)
  149. (match type
  150. (($ <func-sig> params' results')
  151. (and (equal? (map param-type params)
  152. (map param-type params'))
  153. (equal? results results')
  154. (make-type-use type-idx (make-func-sig params results))))
  155. (_ #f)))))
  156. (define (adjoin-types-from-type-uses types funcs imports tags)
  157. (define (adjoin-type-use type types)
  158. (match type
  159. (($ <type-use> #f ($ <func-sig> params results))
  160. (if (find-type (type-use-matcher params results) types)
  161. types
  162. (append types
  163. (list (make-type #f (make-func-sig params results))))))
  164. (($ <type-use>) types)))
  165. (define (adjoin-type-uses-from-import import types)
  166. (match import
  167. (($ <import> mod name 'func id type)
  168. (adjoin-type-use type types))
  169. (($ <import>) types)))
  170. (define (adjoin-type-uses-from-tag tag types)
  171. (match tag
  172. (($ <tag> id type) (adjoin-type-use type types))))
  173. (define (adjoin-type-uses-from-func func types)
  174. (define (adjoin-type-use-for-block-type x types)
  175. (match x
  176. (($ <type-use> #f ($ <func-sig> () (or () (_))))
  177. types)
  178. (_ (adjoin-type-use x types))))
  179. (define (adjoin-type-uses-for-inst inst types)
  180. (match inst
  181. (((or 'block 'loop) label type body)
  182. (fold1 adjoin-type-uses-for-inst body
  183. (adjoin-type-use-for-block-type type types)))
  184. (('if label type consequent alternate)
  185. (adjoin-type-uses-from-body
  186. consequent
  187. (adjoin-type-uses-from-body
  188. alternate
  189. (adjoin-type-use-for-block-type type types))))
  190. (('try label type body catches catch-all)
  191. (fold1 adjoin-type-uses-from-body (append body catches)
  192. (adjoin-type-use-for-block-type
  193. type
  194. (if catch-all
  195. (adjoin-type-uses-from-body catch-all types)
  196. types))))
  197. (('try_delegate label type body handler)
  198. (adjoin-type-uses-from-body
  199. body
  200. (adjoin-type-use-for-block-type type types)))
  201. (((or 'call_indirect 'return_call_indirect) table type)
  202. (adjoin-type-use type types))
  203. (_ types)))
  204. (define (adjoin-type-uses-from-body insts types)
  205. (fold1 adjoin-type-uses-for-inst insts types))
  206. (match func
  207. (($ <func> id type locals body)
  208. (adjoin-type-uses-from-body body (adjoin-type-use type types)))))
  209. (fold1 adjoin-type-uses-from-func funcs
  210. (fold1 adjoin-type-uses-from-tag tags
  211. (fold1 adjoin-type-uses-from-import imports types))))
  212. (match mod
  213. (($ <wasm> id %types imports funcs tables memories globals exports start
  214. elems datas tags strings custom)
  215. (define (generate-names)
  216. (make-names id
  217. (func-name-map)
  218. (func-local-name-map)
  219. (func-label-name-map)
  220. (type-name-map)
  221. (table-name-map)
  222. (memory-name-map)
  223. (global-name-map)
  224. (elem-name-map)
  225. (data-name-map)
  226. (struct-field-name-map)
  227. (tag-name-map)))
  228. (define types (adjoin-types-from-type-uses %types funcs imports tags))
  229. (for-each (match-lambda (($ <type> id type) (add-type-id! id))
  230. (($ <rec-group> (($ <type> id type) ...))
  231. (for-each add-type-id! id)))
  232. types)
  233. (for-each (match-lambda (($ <import> mod name kind id type)
  234. (match kind
  235. ('func (add-func-id! id))
  236. ('global (add-global-id! id))
  237. ('table (add-table-id! id))
  238. ('memory (add-memory-id! id)))))
  239. imports)
  240. (for-each (match-lambda (($ <func> id type locals body)
  241. (add-func-id! id)))
  242. funcs)
  243. (for-each (match-lambda (($ <table> id type init)
  244. (add-table-id! id)))
  245. tables)
  246. (for-each (match-lambda (($ <memory> id type)
  247. (add-memory-id! id)))
  248. memories)
  249. (for-each (match-lambda (($ <global> id type init)
  250. (add-global-id! id)))
  251. globals)
  252. (for-each (match-lambda (($ <elem> id mode table type offset init)
  253. (add-elem-id! id)))
  254. elems)
  255. (for-each (match-lambda (($ <data> id mode mem offset init)
  256. (add-data-id! id)))
  257. datas)
  258. (for-each (match-lambda (($ <tag> id type)
  259. (add-tag-id! id)))
  260. tags)
  261. (for-each intern-string strings)
  262. (find-type (lambda (rec type-id type-idx supers type)
  263. (match type
  264. (($ <struct-type>
  265. (($ <field> field-id mutable? type) ...))
  266. (for-each
  267. (lambda (field-id)
  268. (add-struct-field! type-id type-idx field-id))
  269. field-id))
  270. (_ (values)))
  271. #f)
  272. types)
  273. (when name-section?
  274. (for-each add-func-locals! funcs)
  275. (for-each add-func-labels! funcs))
  276. (define (type-by-idx idx)
  277. (or (find-type (lambda (rec type-id type-idx supers type)
  278. (and (eqv? type-idx idx)
  279. type))
  280. types)
  281. (error "unknown type" idx)))
  282. (define (resolve-heap-type ht)
  283. (match ht
  284. ((or 'func 'extern
  285. 'any 'eq 'i31 'noextern 'nofunc 'struct 'array 'none
  286. 'string 'stringview_wtf8 'stringview_wtf16 'stringview_iter)
  287. ht)
  288. (_ (resolve-type ht))))
  289. (define (resolve-val-type vt)
  290. (match vt
  291. ((or 'i32 'i64 'f32 'f64 'v128
  292. 'funcref 'externref 'anyref 'eqref 'i31ref
  293. 'nullexternref 'nullfuncref
  294. 'structref 'arrayref 'nullref
  295. 'stringref
  296. 'stringview_wtf8ref 'stringview_wtf16ref 'stringview_iterref)
  297. vt)
  298. (($ <ref-type> nullable? ht)
  299. (make-ref-type nullable? (resolve-heap-type ht)))))
  300. (define (resolve-ref-type rt)
  301. (resolve-val-type rt))
  302. (define (resolve-storage-type type)
  303. (match type
  304. ((or 'i8 'i16) type)
  305. (_ (resolve-val-type type))))
  306. (define (resolve-param param)
  307. (match param
  308. (($ <param> id type)
  309. (make-param id (resolve-val-type type)))))
  310. (define (resolve-type-use x)
  311. ;; Transform symbolic or anonymous type uses to indexed type
  312. ;; uses.
  313. (define (lookup-type-use params results)
  314. (or (find-type (type-use-matcher params results) types)
  315. (error "unreachable")))
  316. (match x
  317. (($ <type-use> idx (and use-sig ($ <func-sig> params results)))
  318. (if idx
  319. (let ((idx (resolve-type idx)))
  320. (let ((def-sig (type-by-idx idx)))
  321. (make-type-use idx
  322. (if (and (null? params) (null? results))
  323. def-sig
  324. use-sig))))
  325. (match (lookup-type-use params results)
  326. (($ <type-use> idx ($ <func-sig> params results))
  327. (let ((params (map resolve-param params))
  328. (results (map resolve-val-type results)))
  329. (make-type-use idx (make-func-sig params results)))))))))
  330. (define (resolve-type-use-as-idx x)
  331. (match (resolve-type-use x)
  332. (($ <type-use> idx func-sig)
  333. idx)))
  334. (define (resolve-block-type x)
  335. (match x
  336. (($ <type-use> #f ($ <func-sig> () ()))
  337. x)
  338. (($ <type-use> #f ($ <func-sig> () (ret)))
  339. (let ((ret (resolve-val-type ret)))
  340. (make-type-use #f (make-func-sig '() (list ret)))))
  341. (_ (resolve-type-use-as-idx x))))
  342. (define (resolve-instructions insts locals labels)
  343. (define (resolve-i32 x)
  344. (if (< x (ash 1 31)) x (- x (ash 1 32))))
  345. (define (resolve-i64 x)
  346. (if (< x (ash 1 63)) x (- x (ash 1 64))))
  347. (define (resolve-label label)
  348. (match label
  349. ((? exact-integer?) label)
  350. (_
  351. (or (list-index (lambda (x) (eqv? x label)) labels)
  352. (error "unbound label" label labels)))))
  353. (define (resolve-local id)
  354. (match id
  355. ((? exact-integer?) id)
  356. (_
  357. (let ((local (list-index
  358. (lambda (local)
  359. (match local
  360. (($ <local> id* _) (eqv? id id*))
  361. (($ <param> id* _) (eqv? id id*))
  362. (_ #f)))
  363. locals)))
  364. (unless local
  365. (error "unbound local" id locals))
  366. local))))
  367. (map
  368. (match-lambda
  369. (((and inst (or 'block 'loop)) label type body)
  370. (let ((labels (cons label labels)))
  371. `(,inst ,label ,(resolve-block-type type)
  372. ,(resolve-instructions body locals labels))))
  373. (('if label type consequent alternate)
  374. (let ((labels (cons label labels)))
  375. `(if ,label ,(resolve-block-type type)
  376. ,(resolve-instructions consequent locals labels)
  377. ,(resolve-instructions alternate locals labels))))
  378. (('try label type body catches catch-all)
  379. (let ((labels (cons label labels)))
  380. `(try ,label ,(resolve-block-type type)
  381. ,(resolve-instructions body locals labels)
  382. ,(map (lambda (body)
  383. (resolve-instructions body locals labels))
  384. catches)
  385. ,(and catch-all
  386. (resolve-instructions catch-all locals labels)))))
  387. (('try_delegate label type body handler)
  388. (let ((labels (cons label labels)))
  389. `(try_delegate ,label ,(resolve-block-type type)
  390. ,(resolve-instructions body locals labels)
  391. ,(resolve-label handler))))
  392. (((and inst (or 'throw 'rethrow)) tag) `(,inst ,(resolve-tag tag)))
  393. (((and inst (or 'br 'br_if)) label)
  394. `(,inst ,(resolve-label label)))
  395. (('br_table targets default)
  396. `(br_table ,(map resolve-label targets) ,(resolve-label default)))
  397. (((and inst (or 'call 'return_call)) label)
  398. `(,inst ,(resolve-func label)))
  399. (('call_indirect table type)
  400. `(call_indirect ,(resolve-table table) ,(resolve-type-use-as-idx type)))
  401. (((and inst (or 'call_ref 'return_call_ref)) type)
  402. `(,inst ,(resolve-type type)))
  403. (('select types) `(select ,(map resolve-val-type types)))
  404. (((and inst (or 'local.get 'local.set 'local.tee)) local)
  405. `(,inst ,(resolve-local local)))
  406. (((and inst (or 'global.get 'global.set)) global)
  407. `(,inst ,(resolve-global global)))
  408. (((and inst (or 'table.get 'table.set)) table)
  409. `(,inst ,(resolve-table table)))
  410. (((and inst (or 'memory.size 'memory.grow)) mem)
  411. `(,inst ,(resolve-memory mem)))
  412. (((and inst (or 'i32.load 'i64.load 'f32.load 'f64.load
  413. 'i32.load8_s 'i32.load8_u 'i32.load16_s 'i32.load16_u
  414. 'i64.load8_s 'i64.load8_u 'i64.load16_s 'i64.load16_u
  415. 'i64.load32_s 'i64.load32_u
  416. 'i32.store 'i64.store 'f32.store 'f64.store
  417. 'i32.store8 'i32.store16
  418. 'i64.store8 'i64.store16 'i64.store32))
  419. mem)
  420. `(,inst ,(resolve-memarg mem)))
  421. (('i32.const x) `(i32.const ,(resolve-i32 x)))
  422. (('i64.const x) `(i64.const ,(resolve-i64 x)))
  423. (('ref.null ht) `(ref.null ,(resolve-heap-type ht)))
  424. (('ref.func f) `(ref.func ,(record-function-used-as-value
  425. (resolve-func f))))
  426. ;; GC instructions.
  427. (((and inst (or 'ref.test 'ref.cast)) rt)
  428. `(,inst ,(resolve-ref-type rt)))
  429. (((and inst (or 'br_on_cast 'br_on_cast_fail)) label rt1 rt2)
  430. `(,inst ,(resolve-label label)
  431. ,(resolve-ref-type rt1) ,(resolve-ref-type rt2)))
  432. (((and inst (or 'struct.get 'struct.get_s 'struct.get_u 'struct.set))
  433. type field)
  434. `(,inst ,(resolve-type type) ,(resolve-struct-field type field)))
  435. (((and inst (or 'struct.new 'struct.new_default)) type)
  436. `(,inst ,(resolve-type type)))
  437. (((and inst (or 'array.get 'array.get_s 'array.get_u 'array.set)) type)
  438. `(,inst ,(resolve-type type)))
  439. (('array.new_fixed type len)
  440. `(array.new_fixed ,(resolve-type type) ,len))
  441. (((and inst (or 'array.new 'array.new_default)) type)
  442. `(,inst ,(resolve-type type)))
  443. (((and inst (or 'array.new_data 'array.init_data)) type data)
  444. `(,inst ,(resolve-type type) ,(resolve-data data)))
  445. (((and inst (or 'array.new_elem 'array.init_elem)) type elem)
  446. `(,inst ,(resolve-type type) ,(resolve-elem elem)))
  447. (('array.fill type)
  448. `(array.fill ,(resolve-type type)))
  449. (('array.copy dst src)
  450. `(array.copy ,(resolve-type dst) ,(resolve-type src)))
  451. ;; Stringref instructions.
  452. (('string.const (? string? str))
  453. `(string.const ,(intern-string str)))
  454. (((and inst (or 'string.new_utf8 'string.new_lossy_utf8 'string.new_wtf8
  455. 'string.new_wtf16
  456. 'string.encode_utf8 'string.encode_lossy_utf8
  457. 'string.encode_wtf8 'string.encode_wtf16
  458. 'stringview_wtf8.encode_utf8
  459. 'stringview_wtf8.encode_lossy_utf8
  460. 'stringview_wtf8.encode_wtf8
  461. 'stringview_wtf16.encode))
  462. mem)
  463. `(,inst ,(resolve-memarg mem)))
  464. ;; Misc instructions.
  465. (('memory.init data mem)
  466. `(memory.init ,(resolve-data data) ,(resolve-memory mem)))
  467. (('data.drop data)
  468. `(data.drop ,(resolve-data data)))
  469. (('memory.copy dst src)
  470. `(memory.copy ,(resolve-memory dst) ,(resolve-memory src)))
  471. (('memory.fill mem)
  472. `(memory.fill ,(resolve-memory mem)))
  473. (('table.init table elem)
  474. `(table.init ,(resolve-table table) ,(resolve-elem elem)))
  475. (('elem.drop elem)
  476. `(elem.drop ,(resolve-elem elem)))
  477. (('table.copy dst src)
  478. `(table.copy ,(resolve-table dst) ,(resolve-table src)))
  479. (((and inst (or 'table.grow 'table.size 'table.fill)) table)
  480. `(,inst ,(resolve-table table)))
  481. ;; Not yet implemented: simd mem ops, atomic mem ops.
  482. ((? symbol? op) `(,op))
  483. (inst inst))
  484. insts))
  485. (define (visit-type type)
  486. (define (resolve-field field)
  487. (match field
  488. (($ <field> id mutable? type)
  489. (make-field id mutable? (resolve-storage-type type)))))
  490. (define (resolve-base type)
  491. (match type
  492. (($ <func-sig> params results)
  493. (make-func-sig (map resolve-param params)
  494. (map resolve-val-type results)))
  495. (($ <array-type> mutable? type)
  496. (make-array-type mutable? (resolve-storage-type type)))
  497. (($ <struct-type> fields)
  498. (make-struct-type (map resolve-field fields)))))
  499. (define (resolve-sub type)
  500. (match type
  501. (($ <type> id type)
  502. (make-type id
  503. (match type
  504. (($ <sub-type> final? supers type)
  505. (make-sub-type final?
  506. (map resolve-heap-type supers)
  507. (resolve-base type)))
  508. (_ (resolve-base type)))))))
  509. (match type
  510. (($ <rec-group> sub-types)
  511. (make-rec-group (map resolve-sub sub-types)))
  512. (_ (resolve-sub type))))
  513. (define (visit-import import)
  514. (match import
  515. (($ <import> mod name 'func id type)
  516. (make-import mod name 'func id (resolve-type-use type)))
  517. (($ <import> mod name 'global id ($ <global-type> mutable? type))
  518. (make-import mod name 'global id
  519. (make-global-type mutable? (resolve-val-type type))))
  520. ((and import ($ <import> mod name 'memory))
  521. import)
  522. (($ <import> mod name 'table id ($ <table-type> limits type))
  523. (make-import mod name 'table id
  524. (make-table-type limits (resolve-val-type type))))))
  525. (define (visit-export export)
  526. (match export
  527. (($ <export> name 'func id)
  528. (make-export name 'func (resolve-func id)))
  529. (($ <export> name 'table id)
  530. (make-export name 'table (resolve-table id)))
  531. (($ <export> name 'memory id)
  532. (make-export name 'memory (resolve-memory id)))
  533. (($ <export> name 'global id)
  534. (make-export name 'global (resolve-global id)))))
  535. (define (strip-declarative-segments elems)
  536. (filter (match-lambda
  537. (($ <elem> id mode) (not (eq? mode 'declarative))))
  538. elems))
  539. (define (add-declarative-segment elems)
  540. (match (sort (hash-map->list (lambda (k v) k) functions-used-as-values)
  541. <)
  542. (() elems)
  543. (funcs
  544. (let ((declarative (make-elem #f 'declarative #f 'funcref #f
  545. (map (lambda (func-idx)
  546. `((ref.func ,func-idx)))
  547. funcs))))
  548. (append elems (list declarative))))))
  549. (define (visit-elem elem)
  550. (match elem
  551. (($ <elem> id mode table type offset init)
  552. (make-elem id mode (and table (resolve-table table))
  553. (resolve-val-type type)
  554. (and offset (resolve-instructions offset '() '()))
  555. (map (lambda (init)
  556. (resolve-instructions init '() '()))
  557. init)))))
  558. (define (visit-data data)
  559. (match data
  560. (($ <data> id mode mem offset init)
  561. (make-data id mode (and mem (resolve-memory mem))
  562. (and offset (resolve-instructions offset '() '()))
  563. init))))
  564. (define (visit-start start)
  565. (and start (resolve-func start)))
  566. (define (visit-func func)
  567. (define (visit-local local)
  568. (match local
  569. (($ <local> id type)
  570. (make-local id (resolve-val-type type)))))
  571. (match func
  572. (($ <func> id type locals body)
  573. (match (resolve-type-use type)
  574. ((and type ($ <type-use> idx ($ <func-sig> params _)))
  575. (make-func id type (map visit-local locals)
  576. (resolve-instructions body
  577. (append params locals)
  578. '())))))))
  579. (define (visit-table table)
  580. (match table
  581. (($ <table> id ($ <table-type> limits type) init)
  582. (make-table id
  583. (make-table-type limits (resolve-val-type type))
  584. (and init (resolve-instructions init '() '()))))))
  585. (define (visit-memory mem) mem)
  586. (define (visit-global global)
  587. (match global
  588. (($ <global> id ($ <global-type> mutable? type) init)
  589. (make-global id
  590. (make-global-type mutable? (resolve-val-type type))
  591. (resolve-instructions init '() '())))))
  592. (define (visit-tag tag)
  593. (match tag
  594. (($ <tag> id type)
  595. (make-tag id (resolve-type-use type)))))
  596. (let ((types (map visit-type types))
  597. (imports (map visit-import imports))
  598. (exports (map visit-export exports))
  599. (%elems (map visit-elem (strip-declarative-segments elems)))
  600. (datas (map visit-data datas))
  601. (start (visit-start start))
  602. (funcs (map visit-func funcs))
  603. (tables (map visit-table tables))
  604. (memories (map visit-memory memories))
  605. (globals (map visit-global globals))
  606. (tags (map visit-tag tags))
  607. (custom (if name-section?
  608. (cons (generate-names) custom)
  609. custom)))
  610. (define strings
  611. (map car
  612. (sort (hash-map->list cons interned-strings)
  613. (match-lambda*
  614. (((s1 . idx1) (s2 . idx2)) (< idx1 idx2))))))
  615. (define elems (add-declarative-segment %elems))
  616. (make-wasm #f types imports funcs tables memories globals exports start
  617. elems datas tags strings custom)))))
  618. (define (unresolve-wasm mod)
  619. (match mod
  620. (($ <wasm> id types imports funcs tables memories globals exports start
  621. elems datas tags strings custom)
  622. (match (or (find names? custom)
  623. (make-names #f '() '() '() '() '() '() '() '() '() '() '()))
  624. (($ <names> mod-name func-names local-names label-names type-names
  625. table-names memory-names global-names elem-names data-names
  626. field-names tag-names)
  627. (define (make-id prefix idx)
  628. (string->symbol
  629. (string-append "$" prefix (number->string idx))))
  630. (define (name-generator prefix)
  631. (lambda (idx)
  632. (make-id prefix idx)))
  633. (define (unresolver* name-map fallback)
  634. (lambda (idx)
  635. (or (assq-ref name-map idx)
  636. (fallback idx))))
  637. (define (unresolver name-map prefix)
  638. (unresolver* name-map (name-generator prefix)))
  639. (define (indirect-ref name-map parent-idx idx)
  640. (assq-ref (or (assq-ref name-map parent-idx) '()) idx))
  641. (define (indirect-unresolver* name-map fallback)
  642. (lambda (parent-idx idx)
  643. (or (indirect-ref name-map parent-idx idx)
  644. (fallback idx))))
  645. (define (indirect-unresolver name-map prefix)
  646. (indirect-unresolver* name-map (name-generator prefix)))
  647. (define unresolve-func (unresolver func-names "func"))
  648. (define unresolve-local (indirect-unresolver local-names "var"))
  649. (define unresolve-label (indirect-unresolver* label-names (const #f)))
  650. (define unresolve-type (unresolver type-names "type"))
  651. (define unresolve-table (unresolver table-names "table"))
  652. (define unresolve-memory (unresolver memory-names "memory"))
  653. (define unresolve-global (unresolver global-names "global"))
  654. (define unresolve-elem (unresolver elem-names "elem"))
  655. (define unresolve-data (unresolver data-names "data"))
  656. (define unresolve-field (indirect-unresolver field-names "field"))
  657. (define unresolve-tag (unresolver tag-names "tag"))
  658. (define (mapi proc i lst)
  659. (let loop ((lst lst) (i i))
  660. (match lst
  661. (() '())
  662. ((x . rest)
  663. (cons (proc i x) (loop rest (+ i 1)))))))
  664. (define (unresolve-param param)
  665. (match param
  666. (($ <param> id type)
  667. (make-param id (unresolve-val-type type)))))
  668. (define (unresolve-instructions insts func-idx)
  669. (define (unresolve-ref-type rt)
  670. (match rt
  671. (($ <ref-type> nullable? ht)
  672. (make-ref-type nullable? (unresolve-heap-type ht)))))
  673. (define (unresolve-block-type type)
  674. (match type
  675. (#f #f)
  676. ((? type-use? type)
  677. (unresolve-type-use func-idx type))
  678. (_ (unresolve-val-type type))))
  679. (define (unresolve-memarg memarg)
  680. (match memarg
  681. (($ <mem-arg> idx offset align)
  682. (make-mem-arg (unresolve-memory idx) offset align))))
  683. (define label-count 0)
  684. (define (next-label)
  685. (let ((l label-count))
  686. (set! label-count (+ label-count 1))
  687. l))
  688. (define (unresolve-instructions* insts labels)
  689. (define (unresolve-label/block idx)
  690. (or (list-ref labels idx) idx))
  691. (map
  692. (match-lambda
  693. (((and inst (or 'block 'loop)) label type body)
  694. (let* ((label (unresolve-label func-idx (next-label)))
  695. (labels (cons label labels)))
  696. `(,inst ,label
  697. ,(unresolve-block-type type)
  698. ,(unresolve-instructions* body labels))))
  699. (('if label type consequent alternate)
  700. (let ((labels (cons label labels)))
  701. `(if ,label
  702. ,(unresolve-block-type type)
  703. ,(unresolve-instructions* consequent labels)
  704. ,(unresolve-instructions* alternate labels))))
  705. (('try label type body catches catch-all)
  706. (let* ((label (unresolve-label func-idx (next-label)))
  707. (labels (cons label labels)))
  708. `(try ,label
  709. ,(unresolve-block-type type)
  710. ,(unresolve-instructions* body labels)
  711. ,(map (lambda (body)
  712. (unresolve-instructions* body labels))
  713. catches)
  714. ,(and catch-all
  715. (unresolve-instructions* catch-all labels)))))
  716. (('try_delegate label type body handler)
  717. (let* ((label (unresolve-label func-idx (next-label)))
  718. (labels (cons label labels)))
  719. `(try_delegate ,label
  720. ,(unresolve-block-type type)
  721. ,(unresolve-instructions* body labels)
  722. ,(unresolve-label func-idx handler))))
  723. (((and inst (or 'throw 'rethrow)) tag)
  724. `(,inst ,(unresolve-tag tag)))
  725. (((and inst (or 'br 'br_if)) label)
  726. `(,inst ,(unresolve-label/block label)))
  727. (('br_table targets default)
  728. `(br_table ,@(map unresolve-label/block targets)
  729. ,(unresolve-label/block default)))
  730. (((and inst (or 'call 'return_call)) func)
  731. `(,inst ,(unresolve-func func)))
  732. (('call_indirect table type)
  733. `(call_indirect ,(unresolve-table table) ,(unresolve-type-use #f type)))
  734. (((and inst (or 'call_ref 'return_call_ref)) type)
  735. `(,inst ,(unresolve-type type)))
  736. (('select types) `(select ,(map unresolve-val-type types)))
  737. (((and inst (or 'local.get 'local.set 'local.tee)) local)
  738. `(,inst ,(unresolve-local func-idx local)))
  739. (((and inst (or 'global.get 'global.set)) global)
  740. `(,inst ,(unresolve-global global)))
  741. (((and inst (or 'table.get 'table.set)) table)
  742. `(,inst ,(unresolve-table table)))
  743. (((and inst (or 'memory.size 'memory.grow)) mem)
  744. `(,inst ,(unresolve-memory mem)))
  745. (((and inst (or 'i32.load 'i64.load 'f32.load 'f64.load
  746. 'i32.load8_s 'i32.load8_u 'i32.load16_s 'i32.load16_u
  747. 'i64.load8_s 'i64.load8_u 'i64.load16_s 'i64.load16_u
  748. 'i64.load32_s 'i64.load32_u
  749. 'i32.store 'i64.store 'f32.store 'f64.store
  750. 'i32.store8 'i32.store16
  751. 'i64.store8 'i64.store16 'i64.store32))
  752. mem)
  753. `(,inst ,(unresolve-memarg mem)))
  754. (('ref.null ht) `(ref.null ,(unresolve-heap-type ht)))
  755. (('ref.func f) `(ref.func ,(unresolve-func f)))
  756. ;; GC instructions.
  757. (((and inst (or 'ref.test 'ref.cast)) rt)
  758. `(,inst ,(unresolve-ref-type rt)))
  759. (((and inst (or 'br_on_cast 'br_on_cast_fail)) label rt1 rt2)
  760. `(,inst ,(unresolve-label func-idx label)
  761. ,(unresolve-ref-type rt1) ,(unresolve-ref-type rt2)))
  762. (((and inst (or 'struct.get 'struct.get_s 'struct.get_u 'struct.set))
  763. type field)
  764. `(,inst ,(unresolve-type type) ,(unresolve-field type field)))
  765. (((and inst (or 'struct.new 'struct.new_default)) type)
  766. `(,inst ,(unresolve-type type)))
  767. (((and inst (or 'array.get 'array.get_s 'array.get_u 'array.set)) type)
  768. `(,inst ,(unresolve-type type)))
  769. (('array.new_fixed type len)
  770. `(array.new_fixed ,(unresolve-type type) ,len))
  771. (((and inst (or 'array.new 'array.new_default)) type)
  772. `(,inst ,(unresolve-type type)))
  773. (((and inst (or 'array.new_data 'array.init_data)) type data)
  774. `(,inst ,(unresolve-type type) ,(unresolve-data data)))
  775. (((and inst (or 'array.new_elem 'array.init_elem)) type elem)
  776. `(,inst ,(unresolve-type type) ,(unresolve-elem elem)))
  777. (('array.fill type)
  778. `(array.fill ,(unresolve-type type)))
  779. (('array.copy dst src)
  780. `(array.copy ,(unresolve-type dst) ,(unresolve-type src)))
  781. ;; Stringref instructions.
  782. (('string.const idx)
  783. `(string.const (list-ref strings idx)))
  784. (((and inst (or 'string.new_utf8 'string.new_lossy_utf8 'string.new_wtf8
  785. 'string.new_wtf16
  786. 'string.encode_utf8 'string.encode_lossy_utf8
  787. 'string.encode_wtf8 'string.encode_wtf16
  788. 'stringview_wtf8.encode_utf8
  789. 'stringview_wtf8.encode_lossy_utf8
  790. 'stringview_wtf8.encode_wtf8
  791. 'stringview_wtf16.encode))
  792. mem)
  793. `(,inst ,(unresolve-memarg mem)))
  794. ;; Misc instructions.
  795. (('memory.init data mem)
  796. `(memory.init ,(unresolve-data data) ,(unresolve-memory mem)))
  797. (('data.drop data)
  798. `(data.drop ,(unresolve-data data)))
  799. (('memory.copy dst src)
  800. `(memory.copy ,(unresolve-memory dst) ,(unresolve-memory src)))
  801. (('memory.fill mem)
  802. `(memory.fill ,(unresolve-memory mem)))
  803. (('table.init table elem)
  804. `(table.init ,(unresolve-table table) ,(unresolve-elem elem)))
  805. (('elem.drop elem)
  806. `(elem.drop ,(unresolve-elem elem)))
  807. (('table.copy dst src)
  808. `(table.copy ,(unresolve-table dst) ,(unresolve-table src)))
  809. (((and inst (or 'table.grow 'table.size 'table.fill)) table)
  810. `(,inst ,(unresolve-table table)))
  811. ;; Not yet implemented: simd mem ops, atomic mem ops.
  812. ((? symbol? op) `(,op))
  813. (inst inst))
  814. insts))
  815. (unresolve-instructions* insts '()))
  816. (define (unresolve-heap-type ht)
  817. (match ht
  818. ((or 'func 'extern
  819. 'any 'eq 'i31 'noextern 'nofunc 'struct 'array 'none
  820. 'string 'stringview_wtf8 'stringview_wtf16 'stringview_iter)
  821. ht)
  822. (_ (unresolve-type ht))))
  823. (define (unresolve-val-type vt)
  824. (match vt
  825. ((or 'i32 'i64 'f32 'f64 'v128
  826. 'funcref 'externref 'anyref 'eqref 'i31ref
  827. 'nullexternref 'nullfuncref
  828. 'structref 'arrayref 'nullref
  829. 'stringref
  830. 'stringview_wtf8ref 'stringview_wtf16ref 'stringview_iterref)
  831. vt)
  832. (($ <ref-type> nullable? ht)
  833. (make-ref-type nullable? (unresolve-heap-type ht)))))
  834. (define (unresolve-storage-type type)
  835. (match type
  836. ((or 'i8 'i16) type)
  837. (_ (unresolve-val-type type))))
  838. (define (unresolve-type-use func-idx type)
  839. (match type
  840. (($ <type-use> idx ($ <func-sig> params results))
  841. (let ((params (mapi (lambda (idx param)
  842. (match param
  843. (($ <param> id type)
  844. (make-param (unresolve-local func-idx idx)
  845. (unresolve-val-type type)))))
  846. 0 params))
  847. (results (map unresolve-val-type results)))
  848. (make-type-use #f (make-func-sig params results))))))
  849. ;; During resolution, all anonymous function signatures found
  850. ;; in block types are added to the types section. In the
  851. ;; unresolved output we want to remove these, leaving only
  852. ;; function types that are referenced by name.
  853. (define referenced-types (make-hash-table))
  854. (define (mark-type-reference! idx)
  855. (hashq-set! referenced-types idx #t))
  856. (define (type-referenced? idx)
  857. (hashq-ref referenced-types idx))
  858. (define (scan-heap-type ht)
  859. (when (exact-integer? ht)
  860. (mark-type-reference! ht)))
  861. (define (scan-val-type vt)
  862. (match vt
  863. ((? exact-integer?) (mark-type-reference! vt))
  864. ((? symbol?) #f)
  865. (($ <ref-type> nullable? ht)
  866. (scan-heap-type ht))))
  867. (define (scan-param param)
  868. (match param
  869. (($ <param> id type)
  870. (scan-val-type type))))
  871. (define (scan-field field)
  872. (match field
  873. (($ <field> id mutable? type)
  874. (scan-val-type type))))
  875. (define (scan-type type)
  876. (match type
  877. (($ <func-sig> params results)
  878. (for-each scan-param params)
  879. (for-each scan-val-type results))
  880. (($ <sub-type> final? supers type)
  881. (scan-type type))
  882. (($ <struct-type> fields)
  883. (for-each scan-field fields))
  884. (($ <array-type> mutable? type)
  885. (scan-val-type type))))
  886. (define (scan-type-def type)
  887. (match type
  888. (($ <type> id type)
  889. (scan-type type))
  890. (($ <rec-group> types)
  891. (for-each (match-lambda
  892. (($ <type> id type)
  893. (scan-type type)))
  894. types))))
  895. (define (scan-type-use type-use)
  896. (match type-use
  897. (($ <type-use> idx type)
  898. (scan-type type))))
  899. (define (scan-import import)
  900. (match import
  901. (($ <import> mod name 'func id type)
  902. (scan-type-use type))
  903. (($ <import> mod name 'table id ($ <table-type> limits type))
  904. (scan-type type))
  905. (($ <import> mod name 'memory id type)
  906. #t)
  907. (($ <import> mod name 'global id ($ <global-type> mutable? type))
  908. (scan-type type))))
  909. (define (scan-elem elem)
  910. (match elem
  911. (($ <elem> id mode table type offset inits)
  912. (scan-val-type type))))
  913. (define (scan-local local)
  914. (match local
  915. (($ <local> id type)
  916. (scan-val-type type))))
  917. (define (scan-inst inst)
  918. (match inst
  919. (((or 'block 'loop) label type body)
  920. (scan-body body))
  921. (('if label type consequent alternate)
  922. (scan-body consequent)
  923. (scan-body alternate))
  924. (('try label type body catches catch-all)
  925. (scan-body body))
  926. (('try_delegate label type body handler)
  927. (scan-body body))
  928. (((or 'call_indirect 'return_call_indirect) table type)
  929. (scan-type-use type))
  930. (_ #t)))
  931. (define (scan-body body)
  932. (for-each scan-inst body))
  933. (define (scan-func func)
  934. (match func
  935. (($ <func> id type locals body)
  936. (scan-type-use type)
  937. (for-each scan-local locals)
  938. (scan-body body))))
  939. (define (scan-table table)
  940. (match table
  941. (($ <table> id ($ <table-type> limits elem-type) init)
  942. (scan-val-type elem-type)
  943. (when init
  944. (scan-body init)))))
  945. (define (scan-global global)
  946. (match global
  947. (($ <global> id ($ <global-type> mutable? type) init)
  948. (scan-val-type type)
  949. (when init
  950. (scan-body init)))))
  951. (define (scan-tag idx tag)
  952. (match tag
  953. (($ <tag> id type)
  954. (scan-type-use type))))
  955. (for-each scan-type-def types)
  956. (for-each scan-import imports)
  957. (for-each scan-elem elems)
  958. (for-each scan-func funcs)
  959. (for-each scan-table tables)
  960. (for-each scan-global globals)
  961. (for-each scan-tag tags)
  962. (define (visit-types types)
  963. (define (unresolve-base idx type)
  964. (match type
  965. (($ <func-sig> params results)
  966. (make-func-sig (map unresolve-param params)
  967. (map unresolve-val-type results)))
  968. (($ <array-type> mutable? type)
  969. (make-array-type mutable? (unresolve-storage-type type)))
  970. (($ <struct-type> fields)
  971. (make-struct-type
  972. (mapi (lambda (field-idx field)
  973. (match field
  974. (($ <field> id mutable? type)
  975. (make-field (unresolve-field idx field-idx)
  976. mutable?
  977. (unresolve-storage-type type)))))
  978. 0 fields)))))
  979. (define (unresolve-sub idx type)
  980. (match type
  981. (($ <type> id type)
  982. (make-type (unresolve-type idx)
  983. (match type
  984. (($ <sub-type> final? supers type)
  985. (make-sub-type final?
  986. (map unresolve-heap-type supers)
  987. (unresolve-base idx type)))
  988. (_ (unresolve-base idx type)))))))
  989. (let loop ((types types) (idx 0))
  990. (match types
  991. (() '())
  992. ((($ <rec-group> types) . rest)
  993. (cons (make-rec-group (mapi unresolve-sub idx types))
  994. (loop rest (+ idx (length types)))))
  995. (((and type ($ <type> id (? func-sig?))) . rest)
  996. (if (type-referenced? idx)
  997. (cons (unresolve-sub idx type) (loop rest (+ idx 1)))
  998. (loop rest (+ idx 1))))
  999. ((type . rest)
  1000. (cons (unresolve-sub idx type) (loop rest (+ idx 1)))))))
  1001. (define (select-imports kind)
  1002. (filter (lambda (import)
  1003. (eq? (import-kind import) kind))
  1004. imports))
  1005. (define func-imports (select-imports 'func))
  1006. (define table-imports (select-imports 'table))
  1007. (define memory-imports (select-imports 'memory))
  1008. (define global-imports (select-imports 'global))
  1009. (define (visit-imports imports)
  1010. (let loop ((imports imports) (func 0) (table 0) (memory 0) (global 0))
  1011. (match imports
  1012. (() '())
  1013. ((($ <import> mod name 'func id type) . rest)
  1014. (cons (make-import mod name 'func (unresolve-func func)
  1015. (unresolve-type-use #f type))
  1016. (loop rest (+ func 1) table memory global)))
  1017. ((($ <import> mod name 'table id ($ <table-type> limits type)) . rest)
  1018. (cons (make-import mod name 'table (unresolve-table table)
  1019. (make-table-type limits (unresolve-val-type type)))
  1020. (loop rest func (+ table 1) memory global)))
  1021. ((($ <import> mod name 'memory id type) . rest)
  1022. (cons (make-import mod name 'memory (unresolve-memory memory) type)
  1023. (loop rest func table (+ memory 1) global)))
  1024. ((($ <import> mod name 'global id ($ <global-type> mutable? type))
  1025. . rest)
  1026. (cons (make-import mod name 'global (unresolve-global global)
  1027. (make-global-type mutable?
  1028. (unresolve-val-type type)))
  1029. (loop rest func table memory (+ global 1)))))))
  1030. (define (visit-export export)
  1031. (match export
  1032. (($ <export> name 'func idx)
  1033. (make-export name 'func (unresolve-func idx)))
  1034. (($ <export> name 'table idx)
  1035. (make-export name 'table (unresolve-table idx)))
  1036. (($ <export> name 'memory idx)
  1037. (make-export name 'memory (unresolve-memory idx)))
  1038. (($ <export> name 'global idx)
  1039. (make-export name 'global (unresolve-global idx)))))
  1040. (define (visit-elem idx elem)
  1041. (match elem
  1042. (($ <elem> id mode table type offset inits)
  1043. (make-elem (unresolve-elem idx)
  1044. mode
  1045. (and table (unresolve-table table))
  1046. (unresolve-val-type type)
  1047. (and offset (unresolve-instructions offset #f))
  1048. (map (lambda (init)
  1049. (unresolve-instructions init #f))
  1050. inits)))))
  1051. (define (visit-data idx data)
  1052. (match data
  1053. (($ <data> id mode mem offset init)
  1054. (make-data (unresolve-data idx)
  1055. mode
  1056. (and mem (unresolve-memory mem))
  1057. (and offset (unresolve-instructions offset #f))
  1058. init))))
  1059. (define (visit-start start)
  1060. (and start (unresolve-func start)))
  1061. (define (visit-func idx func)
  1062. (match func
  1063. (($ <func> id (and type ($ <type-use> _ ($ <func-sig> params)))
  1064. locals body)
  1065. (make-func (unresolve-func idx)
  1066. (unresolve-type-use idx type)
  1067. (mapi (lambda (local-idx local)
  1068. (match local
  1069. (($ <local> id type)
  1070. (make-local (unresolve-local idx local-idx)
  1071. (unresolve-val-type type)))))
  1072. (length params)
  1073. locals)
  1074. (unresolve-instructions body idx)))))
  1075. (define (visit-table idx table)
  1076. (match table
  1077. (($ <table> id ($ <table-type> limits elem-type) init)
  1078. (make-table (unresolve-table idx)
  1079. (make-table-type limits (unresolve-val-type elem-type))
  1080. (and init (unresolve-instructions init #f))))))
  1081. (define (visit-memory idx memory)
  1082. (match memory
  1083. (($ <memory> id limits)
  1084. (make-memory (unresolve-memory idx) limits))))
  1085. (define (visit-global idx global)
  1086. (match global
  1087. (($ <global> id ($ <global-type> mutable? type) init)
  1088. (make-global (unresolve-global idx)
  1089. (make-global-type mutable? (unresolve-val-type type))
  1090. (unresolve-instructions init #f)))))
  1091. (define (visit-tag idx tag)
  1092. (match tag
  1093. (($ <tag> id type)
  1094. (make-tag (unresolve-tag idx) (unresolve-type-use #f type)))))
  1095. (let ((types (visit-types types))
  1096. (imports (visit-imports imports))
  1097. (exports (map visit-export exports))
  1098. (elems (mapi visit-elem 0 elems))
  1099. (datas (mapi visit-data 0 datas))
  1100. (start (visit-start start))
  1101. (funcs (mapi visit-func (length func-imports) funcs))
  1102. (tables (mapi visit-table (length table-imports) tables))
  1103. (memories (mapi visit-memory (length memory-imports) memories))
  1104. (globals (mapi visit-global (length global-imports) globals))
  1105. (tags (mapi visit-tag 0 tags)))
  1106. (make-wasm mod-name types imports funcs tables memories globals exports start
  1107. elems datas tags strings custom)))))))