123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097 |
- ;;; WebAssembly virtual machine
- ;;; Copyright (C) 2023 David Thompson <dave@spritely.institute>
- ;;;
- ;;; Licensed under the Apache License, Version 2.0 (the "License");
- ;;; you may not use this file except in compliance with the License.
- ;;; You may obtain a copy of the License at
- ;;;
- ;;; http://www.apache.org/licenses/LICENSE-2.0
- ;;;
- ;;; Unless required by applicable law or agreed to in writing, software
- ;;; distributed under the License is distributed on an "AS IS" BASIS,
- ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ;;; See the License for the specific language governing permissions and
- ;;; limitations under the License.
- ;;; Commentary:
- ;;;
- ;;; Virtual machine tests.
- ;;;
- ;;; Code:
- (use-modules (ice-9 binary-ports)
- (ice-9 exceptions)
- (ice-9 popen)
- (ice-9 textual-ports)
- (srfi srfi-64)
- (test utils)
- (wasm wat)
- (wasm lower)
- (wasm assemble)
- (wasm vm))
- (define s32-overflow (@@ (wasm vm) s32-overflow))
- (define s64-overflow (@@ (wasm vm) s64-overflow))
- (define (run-d8 read args)
- (let* ((args (cons* "--experimental-wasm-stringref" args))
- (port (apply open-pipe* OPEN_READ d8 args))
- (result (string-trim-both (get-string-all port))))
- (if (zero? (close-pipe port))
- (call-with-input-string result read)
- (throw 'd8-error result))))
- (define (run-wasm-in-d8 wasm func read args)
- (call-with-compiled-wasm-file
- wasm
- (lambda (wasm-file-name)
- (run-d8 read
- (cons* (scope-file "test/load-wasm-and-print-primitive.js")
- "--" wasm-file-name func
- (map (lambda (arg) (format #f "~a" arg)) args))))))
- (define (run-wasm-in-vm wasm func args imports)
- (let ((instance (instantiate-wasm (validate-wasm wasm) #:imports imports)))
- (apply (wasm-instance-export-ref instance func) args)))
- (define (wat->wasm* wat)
- (lower-wasm (wat->wasm wat) #:stringref-lowering 'stringref))
- (define (eval-wat wat func args imports d8? d8-read)
- (let* ((wasm (wat->wasm* wat))
- (our-result (run-wasm-in-vm wasm func args imports)))
- (when d8?
- (let ((d8-result (run-wasm-in-d8 wasm func d8-read args)))
- (unless (if (and (number? our-result) (number? d8-result))
- (= our-result d8-result)
- (equal? our-result d8-result))
- (error "our result differs from d8" our-result d8-result))))
- our-result))
- (define* (test-vm name expected wat #:key
- (func "main") (args '()) (imports '())
- (d8? use-d8?) (d8-read read))
- (test-equal name
- expected
- (eval-wat wat func args imports d8? d8-read)))
- (define (eval-wat/error wat func args imports d8? d8-read)
- (let ((wasm (wat->wasm* wat)))
- (define (handle-error e)
- (if d8?
- (with-exception-handler (lambda (e) #t)
- (lambda ()
- (let ((result (run-wasm-in-d8 wasm func d8-read args)))
- (error "d8 did not throw an error" result))
- #f)
- #:unwind? #t
- #:unwind-for-type 'd8-error)
- #t))
- (with-exception-handler handle-error
- (lambda ()
- (run-wasm-in-vm wasm func args imports)
- #f)
- #:unwind? #t
- #:unwind-for-type &wasm-error)))
- (define* (test-vm/error name wat #:key
- (func "main") (args '()) (imports '())
- (d8? #t) (d8-read read))
- (test-assert name
- (eval-wat/error wat func args imports d8? d8-read)))
- ;; For temporarily testing something that doesn't work in our VM yet.
- (define (eval-d8 wat func read args)
- (run-wasm-in-d8 (wat->wasm* wat) func read args))
- (define* (test-d8 name expected wat #:key (func "main") (args '()) (read read))
- (test-equal name
- expected
- (eval-d8 wat func read args)))
- (test-begin "test-vm")
- (test-vm "i32.eqz true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.eqz (i32.const 0)))))
- (test-vm "i32.eqz false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.eqz (i32.const 42)))))
- (test-vm "i32.eq true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.eq (i32.const 42) (i32.const 42)))))
- (test-vm "i32.eq false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.eq (i32.const 42) (i32.const 7)))))
- (test-vm "i32.ne true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.ne (i32.const 42) (i32.const 7)))))
- (test-vm "i32.ne false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.ne (i32.const 42) (i32.const 42)))))
- (test-vm "i32.lt_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.lt_s (i32.const -42) (i32.const 42)))))
- (test-vm "i32.lt_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.lt_s (i32.const 42) (i32.const -42)))))
- (test-vm "i32.lt_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.lt_s (i32.const 7) (i32.const 42)))))
- (test-vm "i32.lt_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.lt_s (i32.const 42) (i32.const 7)))))
- (test-vm "i32.le_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.le_s (i32.const 42) (i32.const 42)))))
- (test-vm "i32.le_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.le_s (i32.const 42) (i32.const -42)))))
- (test-vm "i32.le_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.le_s (i32.const 42) (i32.const 42)))))
- (test-vm "i32.le_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.le_s (i32.const 42) (i32.const 7)))))
- (test-vm "i32.gt_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.gt_s (i32.const 42) (i32.const -42)))))
- (test-vm "i32.gt_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.gt_s (i32.const -42) (i32.const 42)))))
- (test-vm "i32.gt_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.gt_s (i32.const 42) (i32.const 7)))))
- (test-vm "i32.gt_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.gt_s (i32.const 7) (i32.const 42)))))
- (test-vm "i32.ge_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.ge_s (i32.const 42) (i32.const 42)))))
- (test-vm "i32.ge_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.ge_s (i32.const -42) (i32.const 42)))))
- (test-vm "i32.ge_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i32.ge_s (i32.const 42) (i32.const 42)))))
- (test-vm "i32.ge_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i32.ge_s (i32.const 7) (i32.const 42)))))
- (test-vm "i32.add"
- 80
- '(module
- (func (export "main") (result i32)
- (i32.add (i32.const 42) (i32.const 38)))))
- (test-vm "i32.sub"
- 4
- '(module
- (func (export "main") (result i32)
- (i32.sub (i32.const 42) (i32.const 38)))))
- (test-vm "i32.mul"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.mul (i32.const 7) (i32.const 6)))))
- (test-vm "i32.div_s"
- -6
- '(module
- (func (export "main") (result i32)
- (i32.div_s (i32.const -42) (i32.const 7)))))
- (test-vm "i32.div_u"
- 6
- '(module
- (func (export "main") (result i32)
- (i32.div_u (i32.const 42) (i32.const 7)))))
- (test-vm "i32.rem_s"
- -2
- '(module
- (func (export "main") (result i32)
- (i32.rem_s (i32.const -42) (i32.const 5)))))
- (test-vm "i32.rem_u"
- 2
- '(module
- (func (export "main") (result i32)
- (i32.rem_u (i32.const 42) (i32.const 5)))))
- (test-vm "i32.and"
- #b1010
- '(module
- (func (export "main") (result i32)
- (i32.and (i32.const #b1111) (i32.const #b1010)))))
- (test-vm "i32.or"
- #b1111
- '(module
- (func (export "main") (result i32)
- (i32.or (i32.const #b0101) (i32.const #b1010)))))
- (test-vm "i32.xor"
- #b1110
- '(module
- (func (export "main") (result i32)
- (i32.or (i32.const #b1010) (i32.const #b0100)))))
- (test-vm "i32.shl"
- #b1000
- '(module
- (func (export "main") (result i32)
- (i32.shl (i32.const #b0001) (i32.const 3)))))
- (test-vm "i32.shl - out of 32 bit range"
- 0
- `(module
- (func (export "main") (result i32)
- (i32.shl (i32.const ,(ash -1 31))
- (i32.const 2)))))
- (test-vm "i32.shl - more than 32 bits"
- #b1000
- '(module
- (func (export "main") (result i32)
- (i32.shl (i32.const #b0001) (i32.const 35)))))
- (test-vm "i32.shr_s"
- -2
- '(module
- (func (export "main") (result i32)
- (i32.shr_s (i32.const -16) (i32.const 3)))))
- (test-vm "i32.shr_u"
- #b0001
- '(module
- (func (export "main") (result i32)
- (i32.shr_u (i32.const #b1000) (i32.const 3)))))
- (test-vm "i32.shr_u - more than 32 bits"
- #b0001
- '(module
- (func (export "main") (result i32)
- (i32.shr_u (i32.const #b1000) (i32.const 35)))))
- (test-vm "i32.rotl"
- (s32-overflow #b11000011110000111100001111000011)
- `(module
- (func (export "main") (result i32)
- (i32.rotl (i32.const
- ,(s32-overflow #b11110000111100001111000011110000))
- (i32.const 2)))))
- (test-vm "i32.rotr"
- (s32-overflow #b00111100001111000011110000111100)
- `(module
- (func (export "main") (result i32)
- (i32.rotr (i32.const
- ,(s32-overflow #b11110000111100001111000011110000))
- (i32.const 2)))))
- (test-vm "i32.clz"
- 7
- `(module
- (func (export "main") (result i32)
- (i32.clz (i32.const ,(ash 1 24))))))
- (test-vm "i32.ctz"
- 24
- `(module
- (func (export "main") (result i32)
- (i32.ctz (i32.const ,(ash 1 24))))))
- (test-vm "i32.popcnt"
- 16
- `(module
- (func (export "main") (result i32)
- (i32.popcnt (i32.const ,(s32-overflow #xaaaaAAAA))))))
- (test-vm "i32.wrap_i64 positive"
- 3
- `(module
- (func (export "main") (result i32)
- (i32.wrap_i64 (i64.const ,(+ (ash 1 32) 3))))))
- (test-vm "i32.wrap_i64 negative"
- -3
- `(module
- (func (export "main") (result i32)
- (i32.wrap_i64 (i64.const ,(- (ash -1 32) 3))))))
- (test-vm "i32.trunc_f32_s"
- -1
- `(module
- (func (export "main") (result i32)
- (i32.trunc_f32_s (f32.const -1.2)))))
- (test-vm "i32.trunc_f32_u"
- 1
- `(module
- (func (export "main") (result i32)
- (i32.trunc_f32_u (f32.const 1.2)))))
- (test-vm "i32.trunc_f64_s"
- -1
- `(module
- (func (export "main") (result i32)
- (i32.trunc_f64_s (f64.const -1.2)))))
- (test-vm "i32.trunc_f64_u"
- 1
- `(module
- (func (export "main") (result i32)
- (i32.trunc_f64_u (f64.const 1.2)))))
- (test-vm "i32.reinterpret_f32"
- 1067030938
- `(module
- (func (export "main") (result i32)
- (i32.reinterpret_f32 (f32.const 1.2)))))
- (test-vm "i64.eqz true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.eqz (i64.const 0)))))
- (test-vm "i64.eqz false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.eqz (i64.const 42)))))
- (test-vm "i64.eq true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.eq (i64.const 42) (i64.const 42)))))
- (test-vm "i64.eq false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.eq (i64.const 42) (i64.const 7)))))
- (test-vm "i64.ne true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.ne (i64.const 42) (i64.const 7)))))
- (test-vm "i64.ne false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.ne (i64.const 42) (i64.const 42)))))
- (test-vm "i64.lt_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.lt_s (i64.const -42) (i64.const 42)))))
- (test-vm "i64.lt_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.lt_s (i64.const 42) (i64.const -42)))))
- (test-vm "i64.lt_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.lt_s (i64.const 7) (i64.const 42)))))
- (test-vm "i64.lt_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.lt_s (i64.const 42) (i64.const 7)))))
- (test-vm "i64.le_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.le_s (i64.const 42) (i64.const 42)))))
- (test-vm "i64.le_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.le_s (i64.const 42) (i64.const -42)))))
- (test-vm "i64.le_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.le_s (i64.const 42) (i64.const 42)))))
- (test-vm "i64.le_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.le_s (i64.const 42) (i64.const 7)))))
- (test-vm "i64.gt_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.gt_s (i64.const 42) (i64.const -42)))))
- (test-vm "i64.gt_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.gt_s (i64.const -42) (i64.const 42)))))
- (test-vm "i64.gt_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.gt_s (i64.const 42) (i64.const 7)))))
- (test-vm "i64.gt_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.gt_s (i64.const 7) (i64.const 42)))))
- (test-vm "i64.ge_s true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.ge_s (i64.const 42) (i64.const 42)))))
- (test-vm "i64.ge_s false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.ge_s (i64.const -42) (i64.const 42)))))
- (test-vm "i64.ge_u true"
- 1
- '(module
- (func (export "main") (result i32)
- (i64.ge_s (i64.const 42) (i64.const 42)))))
- (test-vm "i64.ge_u false"
- 0
- '(module
- (func (export "main") (result i32)
- (i64.ge_s (i64.const 7) (i64.const 42)))))
- (test-vm "i64.add"
- 80
- '(module
- (func (export "main") (result i64)
- (i64.add (i64.const 42) (i64.const 38)))))
- (test-vm "i64.sub"
- 4
- '(module
- (func (export "main") (result i64)
- (i64.sub (i64.const 42) (i64.const 38)))))
- (test-vm "i64.mul"
- 42
- '(module
- (func (export "main") (result i64)
- (i64.mul (i64.const 7) (i64.const 6)))))
- (test-vm "i64.div_s"
- -6
- '(module
- (func (export "main") (result i64)
- (i64.div_s (i64.const -42) (i64.const 7)))))
- (test-vm "i64.div_u"
- 6
- '(module
- (func (export "main") (result i64)
- (i64.div_u (i64.const 42) (i64.const 7)))))
- (test-vm "i64.rem_s"
- -2
- '(module
- (func (export "main") (result i64)
- (i64.rem_s (i64.const -42) (i64.const 5)))))
- (test-vm "i64.rem_u"
- 2
- '(module
- (func (export "main") (result i64)
- (i64.rem_u (i64.const 42) (i64.const 5)))))
- (test-vm "i64.and"
- #b1010
- '(module
- (func (export "main") (result i64)
- (i64.and (i64.const #b1111) (i64.const #b1010)))))
- (test-vm "i64.or"
- #b1111
- '(module
- (func (export "main") (result i64)
- (i64.or (i64.const #b0101) (i64.const #b1010)))))
- (test-vm "i64.xor"
- #b1110
- '(module
- (func (export "main") (result i64)
- (i64.or (i64.const #b1010) (i64.const #b0100)))))
- (test-vm "i64.shl"
- #b1000
- '(module
- (func (export "main") (result i64)
- (i64.shl (i64.const #b0001) (i64.const 3)))))
- (test-vm "i64.shr_s"
- -2
- '(module
- (func (export "main") (result i64)
- (i64.shr_s (i64.const -16) (i64.const 3)))))
- (test-vm "i64.shr_u"
- #b0001
- '(module
- (func (export "main") (result i64)
- (i64.shr_u (i64.const #b1000) (i64.const 3)))))
- (test-vm "i64.rotl"
- (s64-overflow #xfff0000ffff0000f)
- `(module
- (func (export "main") (result i64)
- (i64.rotl (i64.const
- ,(s64-overflow #xffff0000ffff0000))
- (i64.const 4)))))
- (test-vm "i64.rotr"
- (s64-overflow #xffff0000ffff0000)
- `(module
- (func (export "main") (result i64)
- (i64.rotr (i64.const
- ,(s64-overflow #xfff0000ffff0000f))
- (i64.const 4)))))
- (test-vm "i64.clz"
- 15
- `(module
- (func (export "main") (result i64)
- (i64.clz (i64.const ,(ash 1 48))))))
- (test-vm "i64.ctz"
- 48
- `(module
- (func (export "main") (result i64)
- (i64.ctz (i64.const ,(ash 1 48))))))
- (test-vm "i64.popcnt"
- 32
- `(module
- (func (export "main") (result i64)
- (i64.popcnt (i64.const ,(s64-overflow #xaaaaAAAAaaaaAAAA))))))
- (test-vm "i64.extend_i32_s"
- -42
- `(module
- (func (export "main") (result i64)
- (i64.extend_i32_s (i32.const -42)))))
- (test-vm "i64.extend_i32_u"
- 42
- `(module
- (func (export "main") (result i64)
- (i64.extend_i32_u (i32.const 42)))))
- (test-vm "i64.trunc_f32_s"
- -1
- `(module
- (func (export "main") (result i64)
- (i64.trunc_f32_s (f32.const -1.2)))))
- (test-vm "i64.trunc_f32_u"
- 1
- `(module
- (func (export "main") (result i64)
- (i64.trunc_f32_u (f32.const 1.2)))))
- (test-vm "i64.trunc_f64_s"
- -1
- `(module
- (func (export "main") (result i64)
- (i64.trunc_f64_s (f64.const -1.2)))))
- (test-vm "i64.trunc_f64_u"
- 1
- `(module
- (func (export "main") (result i64)
- (i64.trunc_f64_u (f64.const 1.2)))))
- (test-vm "i64.reinterpret_f64"
- 4608083138725491507
- `(module
- (func (export "main") (result i64)
- (i64.reinterpret_f64 (f64.const 1.2)))))
- (test-vm "f32.eq true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.eq (f32.const 42.0) (f32.const 42.0)))))
- (test-vm "f32.eq false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.eq (f32.const 42.0) (f32.const 7.0)))))
- (test-vm "f32.ne true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.ne (f32.const 42.0) (f32.const 7.0)))))
- (test-vm "f32.ne false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.ne (f32.const 42.0) (f32.const 42.0)))))
- (test-vm "f32.lt true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.lt (f32.const -42.0) (f32.const 42.0)))))
- (test-vm "f32.lt false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.lt (f32.const 42.0) (f32.const -42.0)))))
- (test-vm "f32.le true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.le (f32.const 42.0) (f32.const 42.0)))))
- (test-vm "f32.le false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.le (f32.const 42.0) (f32.const -42.0)))))
- (test-vm "f32.gt true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.gt (f32.const 42.0) (f32.const -42.0)))))
- (test-vm "f32.gt false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.gt (f32.const -42.0) (f32.const 42.0)))))
- (test-vm "f32.ge true"
- 1
- '(module
- (func (export "main") (result i32)
- (f32.ge (f32.const 42.0) (f32.const 42.0)))))
- (test-vm "f32.ge false"
- 0
- '(module
- (func (export "main") (result i32)
- (f32.ge (f32.const -42.0) (f32.const 42.0)))))
- (test-vm "f32.add"
- 3.5
- '(module
- (func (export "main") (result f32)
- (f32.add (f32.const 1.5) (f32.const 2.0)))))
- (test-vm "f32.sub"
- 2.5
- '(module
- (func (export "main") (result f32)
- (f32.sub (f32.const 3.0) (f32.const 0.5)))))
- (test-vm "f32.mul"
- 4.5
- '(module
- (func (export "main") (result f32)
- (f32.mul (f32.const 1.5) (f32.const 3.0)))))
- (test-vm "f32.div"
- 0.5
- '(module
- (func (export "main") (result f32)
- (f32.div (f32.const 1.0) (f32.const 2.0)))))
- (test-vm "f32.abs"
- 1.5
- '(module
- (func (export "main") (result f32)
- (f32.abs (f32.const -1.5)))))
- (test-vm "f32.neg"
- -1.5
- '(module
- (func (export "main") (result f32)
- (f32.neg (f32.const 1.5)))))
- (test-vm "f32.ceil"
- 2.0
- '(module
- (func (export "main") (result f32)
- (f32.ceil (f32.const 1.5)))))
- (test-vm "f32.floor"
- 1.0
- '(module
- (func (export "main") (result f32)
- (f32.floor (f32.const 1.5)))))
- (test-vm "f32.trunc"
- 1.0
- '(module
- (func (export "main") (result f32)
- (f32.trunc (f32.const 1.5)))))
- (test-vm "f32.nearest"
- 1.0
- '(module
- (func (export "main") (result f32)
- (f32.nearest (f32.const 1.4)))))
- (test-vm "f32.sqrt"
- 2.0
- '(module
- (func (export "main") (result f32)
- (f32.sqrt (f32.const 4.0)))))
- (test-vm "f32.min"
- 0.5
- '(module
- (func (export "main") (result f32)
- (f32.min (f32.const 0.5) (f32.const 1.5)))))
- (test-vm "f32.max"
- 1.5
- '(module
- (func (export "main") (result f32)
- (f32.max (f32.const 0.5) (f32.const 1.5)))))
- (test-vm "f32.copysign"
- -1.5
- '(module
- (func (export "main") (result f32)
- (f32.copysign (f32.const 1.5) (f32.const -2.0)))))
- (test-vm "f32.convert_i32_s"
- -42.0
- '(module
- (func (export "main") (result f32)
- (f32.convert_i32_s (i32.const -42)))))
- (test-vm "f32.convert_i32_u"
- 42.0
- '(module
- (func (export "main") (result f32)
- (f32.convert_i32_u (i32.const 42)))))
- (test-vm "f32.convert_i64_s"
- -42.0
- '(module
- (func (export "main") (result f32)
- (f32.convert_i64_s (i64.const -42)))))
- (test-vm "f32.convert_i64_u"
- 42.0
- '(module
- (func (export "main") (result f32)
- (f32.convert_i64_u (i64.const 42)))))
- (test-vm "f32.demote_f64"
- 42.0
- '(module
- (func (export "main") (result f32)
- (f32.demote_f64 (f64.const 42.0)))))
- (test-vm "f32.reinterpret_i32"
- 1.5
- '(module
- (func (export "main") (result f32)
- (f32.reinterpret_i32 (i32.const 1069547520)))))
- (test-vm "f64.eq true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.eq (f64.const 42.0) (f64.const 42.0)))))
- (test-vm "f64.eq false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.eq (f64.const 42.0) (f64.const 7.0)))))
- (test-vm "f64.ne true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.ne (f64.const 42.0) (f64.const 7.0)))))
- (test-vm "f64.ne false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.ne (f64.const 42.0) (f64.const 42.0)))))
- (test-vm "f64.lt true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.lt (f64.const -42.0) (f64.const 42.0)))))
- (test-vm "f64.lt false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.lt (f64.const 42.0) (f64.const -42.0)))))
- (test-vm "f64.le true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.le (f64.const 42.0) (f64.const 42.0)))))
- (test-vm "f64.le false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.le (f64.const 42.0) (f64.const -42.0)))))
- (test-vm "f64.gt true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.gt (f64.const 42.0) (f64.const -42.0)))))
- (test-vm "f64.gt false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.gt (f64.const -42.0) (f64.const 42.0)))))
- (test-vm "f64.ge true"
- 1
- '(module
- (func (export "main") (result i32)
- (f64.ge (f64.const 42.0) (f64.const 42.0)))))
- (test-vm "f64.ge false"
- 0
- '(module
- (func (export "main") (result i32)
- (f64.ge (f64.const -42.0) (f64.const 42.0)))))
- (test-vm "f64.add"
- 3.5
- '(module
- (func (export "main") (result f64)
- (f64.add (f64.const 1.5) (f64.const 2.0)))))
- (test-vm "f64.sub"
- 2.5
- '(module
- (func (export "main") (result f64)
- (f64.sub (f64.const 3.0) (f64.const 0.5)))))
- (test-vm "f64.mul"
- 4.5
- '(module
- (func (export "main") (result f64)
- (f64.mul (f64.const 1.5) (f64.const 3.0)))))
- (test-vm "f64.div"
- 0.5
- '(module
- (func (export "main") (result f64)
- (f64.div (f64.const 1.0) (f64.const 2.0)))))
- (test-vm "f64.abs"
- 1.5
- '(module
- (func (export "main") (result f64)
- (f64.abs (f64.const -1.5)))))
- (test-vm "f64.neg"
- -1.5
- '(module
- (func (export "main") (result f64)
- (f64.neg (f64.const 1.5)))))
- (test-vm "f64.ceil"
- 2.0
- '(module
- (func (export "main") (result f64)
- (f64.ceil (f64.const 1.5)))))
- (test-vm "f64.floor"
- 1.0
- '(module
- (func (export "main") (result f64)
- (f64.floor (f64.const 1.5)))))
- (test-vm "f64.trunc"
- 1.0
- '(module
- (func (export "main") (result f64)
- (f64.trunc (f64.const 1.5)))))
- (test-vm "f64.nearest"
- 1.0
- '(module
- (func (export "main") (result f64)
- (f64.nearest (f64.const 1.4)))))
- (test-vm "f64.sqrt"
- 2.0
- '(module
- (func (export "main") (result f64)
- (f64.sqrt (f64.const 4.0)))))
- (test-vm "f64.min"
- 0.5
- '(module
- (func (export "main") (result f64)
- (f64.min (f64.const 0.5) (f64.const 1.5)))))
- (test-vm "f64.max"
- 1.5
- '(module
- (func (export "main") (result f64)
- (f64.max (f64.const 0.5) (f64.const 1.5)))))
- (test-vm "f64.copysign"
- -1.5
- '(module
- (func (export "main") (result f64)
- (f64.copysign (f64.const 1.5) (f64.const -2.0)))))
- (test-vm "f64.convert_i32_s"
- -42.0
- '(module
- (func (export "main") (result f64)
- (f64.convert_i32_s (i32.const -42)))))
- (test-vm "f64.convert_i32_u"
- 42.0
- '(module
- (func (export "main") (result f64)
- (f64.convert_i32_u (i32.const 42)))))
- (test-vm "f64.convert_i64_s"
- -42.0
- '(module
- (func (export "main") (result f64)
- (f64.convert_i64_s (i64.const -42)))))
- (test-vm "f64.convert_i64_u"
- 42.0
- '(module
- (func (export "main") (result f64)
- (f64.convert_i64_u (i64.const 42)))))
- (test-vm "f64.promote_f32"
- 42.0
- '(module
- (func (export "main") (result f64)
- (f64.promote_f32 (f32.const 42.0)))))
- (test-vm "f64.reinterpret_i64"
- 1.5
- '(module
- (func (export "main") (result f64)
- (f64.reinterpret_i64 (i64.const 4609434218613702656)))))
- (test-vm "i32.store + i32.load"
- 42
- '(module
- (memory 1)
- (func (export "main") (result i32)
- (i32.store (i32.const 0) (i32.const 42))
- (i32.load (i32.const 0)))))
- (test-vm "i32.store16 + i32.load16_s"
- -42
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store16 (i32.const 0) (i32.const -42))
- (i32.load16_s (i32.const 0)))))
- (test-vm "i32.store16 + i32.load16_s wrap"
- -1
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store16 (i32.const 0) (i32.const -65537))
- (i32.load16_s (i32.const 0)))))
- (test-vm "i32.store16 + i32.load16_u"
- 65535
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store16 (i32.const 0) (i32.const 65535))
- (i32.load16_u (i32.const 0)))))
- (test-vm "i32.store16 + i32.load16_u wrap"
- 65535
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store16 (i32.const 0) (i32.const -65537))
- (i32.load16_u (i32.const 0)))))
- (test-vm "i32.store8 + i32.load8_s"
- -42
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store8 (i32.const 0) (i32.const -42))
- (i32.load8_s (i32.const 0)))))
- (test-vm "i32.store8 + i32.load8_s wrap"
- -1
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store8 (i32.const 0) (i32.const -257))
- (i32.load8_s (i32.const 0)))))
- (test-vm "i32.store8 + i32.load8_u"
- 255
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store8 (i32.const 0) (i32.const 255))
- (i32.load8_u (i32.const 0)))))
- (test-vm "i32.store8 + i32.load8_u wrap"
- 255
- '(module
- (memory $memory 1)
- (func (export "main") (result i32)
- (i32.store8 (i32.const 0) (i32.const -257))
- (i32.load8_u (i32.const 0)))))
- (test-vm "i64.store + i64.load"
- 42
- '(module
- (memory 1)
- (func (export "main") (result i64)
- (i64.store (i32.const 0) (i64.const 42))
- (i64.load (i32.const 0)))))
- (test-vm "i64.store32 + i64.load32_s"
- -42
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store32 (i32.const 0) (i64.const -42))
- (i64.load32_s (i32.const 0)))))
- (test-vm "i64.store32 + i64.load32_s wrap"
- -1
- `(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store32 (i32.const 0) (i64.const ,(- (ash 1 32) 1)))
- (i64.load32_s (i32.const 0)))))
- (test-vm "i64.store32 + i64.load32_u"
- (- (ash 1 32) 1)
- `(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store32 (i32.const 0) (i64.const ,(- (ash 1 32) 1)))
- (i64.load32_u (i32.const 0)))))
- (test-vm "i64.store32 + i64.load32_u wrap"
- (- (ash 1 32) 1)
- `(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store32 (i32.const 0) (i64.const ,(- (ash -1 32) 1)))
- (i64.load32_u (i32.const 0)))))
- (test-vm "i64.store16 + i64.load16_s"
- -42
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store16 (i32.const 0) (i64.const -42))
- (i64.load16_s (i32.const 0)))))
- (test-vm "i64.store16 + i64.load16_s wrap"
- -1
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store16 (i32.const 0) (i64.const -65537))
- (i64.load16_s (i32.const 0)))))
- (test-vm "i64.store16 + i64.load16_u"
- 65535
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store16 (i32.const 0) (i64.const 65535))
- (i64.load16_u (i32.const 0)))))
- (test-vm "i64.store16 + i64.load16_u wrap"
- 65535
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store16 (i32.const 0) (i64.const -65537))
- (i64.load16_u (i32.const 0)))))
- (test-vm "i64.store8 + i64.load8_s"
- -42
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store8 (i32.const 0) (i64.const -42))
- (i64.load8_s (i32.const 0)))))
- (test-vm "i64.store8 + i64.load8_s wrap"
- -1
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store8 (i32.const 0) (i64.const -257))
- (i64.load8_s (i32.const 0)))))
- (test-vm "i64.store8 + i64.load8_u"
- 255
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store8 (i32.const 0) (i64.const 255))
- (i64.load8_u (i32.const 0)))))
- (test-vm "i64.store8 + i64.load8_u wrap"
- 255
- '(module
- (memory $memory 1)
- (func (export "main") (result i64)
- (i64.store8 (i32.const 0) (i64.const -257))
- (i64.load8_u (i32.const 0)))))
- (test-vm "f32.store + f32.load"
- 1.5
- '(module
- (memory 1)
- (func (export "main") (result f32)
- (f32.store (i32.const 0) (f32.const 1.5))
- (f32.load (i32.const 0)))))
- (test-vm "f64.store + f64.load"
- 1.5
- '(module
- (memory 1)
- (func (export "main") (result f64)
- (f64.store (i32.const 0) (f64.const 1.5))
- (f64.load (i32.const 0)))))
- (test-vm "memory.size"
- 1
- '(module
- (memory 1)
- (func (export "main") (result i32)
- (memory.size))))
- (test-vm "memory.grow within limits"
- 2
- '(module
- (memory 2 3)
- (func (export "main") (result i32)
- (i32.const 1)
- (memory.grow))))
- (test-vm "memory.grow outside limits"
- -1
- '(module
- (memory 1 1)
- (func (export "main") (result i32)
- (i32.const 1)
- (memory.grow))))
- (test-vm "memory.grow no-op"
- 1
- '(module
- (memory 1 1)
- (func (export "main") (result i32)
- (i32.const 0)
- (memory.grow))))
- (test-vm "if"
- 37
- '(module
- (func (export "main") (result i32)
- (if (result i32)
- (i32.eq (i32.const 42) (i32.const 47))
- (then (i32.const 13))
- (else (i32.const 37))))))
- (test-vm "branching in a block"
- 42
- '(module
- (func (export "main") (result i32)
- (block $foo
- (br $foo)
- (unreachable))
- (i32.const 42))))
- (test-vm "return"
- 42
- '(module
- (func (export "main") (result i32)
- (block $foo (result i32)
- (i32.const 42)
- (return)
- (unreachable)))))
- (test-vm "return via br"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (br 0)
- (unreachable))))
- (test-vm "return_call"
- 42
- '(module
- (func $count (param $i i32) (param $k i32) (result i32)
- (if (result i32)
- (i32.eq (local.get $i) (local.get $k))
- (then (local.get $k))
- (else (return_call $count
- (i32.add (local.get $i) (i32.const 1))
- (local.get $k)))))
- (func $main (export "main") (param $k i32) (result i32)
- (call $count (i32.const 0) (local.get $k))))
- #:args '(42))
- (test-vm "return with extra values on stack"
- 42
- '(module
- (func (export "main") (result i32)
- (block $foo (result i32)
- (i32.const 13)
- (i32.const 42)
- (return)))))
- (test-vm/error "fallthrough with too many values on stack"
- '(module
- (func (export "main") (result i32)
- (i32.const 1)
- (i32.const 2))))
- (test-vm/error "fallthrough with too many values on invalid stack"
- '(module
- (func (export "main") (result i32)
- (i32.const 1)
- (return) ; stack is invalid after this
- (i32.const 2)
- (i32.const 3))))
- (test-vm "branching in a loop"
- 24
- '(module
- ;; Iterative factorial.
- (func (export "main") (param $n i32) (result i32)
- (local $result i32)
- (local.set $result (i32.const 1))
- (loop $loop (result i32)
- (if (result i32)
- (i32.eq (local.get $n) (i32.const 1))
- (then (local.get $result))
- (else (local.set $result (i32.mul (local.get $n)
- (local.get $result)))
- (local.set $n (i32.sub (local.get $n) (i32.const 1)))
- (br $loop))))))
- #:args '(4))
- (test-vm "blocks with params and results"
- 24
- '(module
- (func (export "main") (param $n i32) (result i32)
- (local.get $n)
- (block $block (param i32) (result i32)
- (loop $loop (param i32) (result i32)
- (i32.eq (local.get $n) (i32.const 1))
- (br_if $block)
- (local.tee $n (i32.sub (local.get $n) (i32.const 1)))
- (i32.mul)
- (br $loop)))))
- #:args '(4))
- (test-vm "br_table"
- 42
- '(module
- (func (export "main") (result i32)
- (block $foo (result i32)
- (block $bar (result i32)
- (i32.const 21)
- (i32.const 0)
- (br_table $foo $bar))
- (unreachable))
- (i32.const 21)
- (i32.add))))
- (test-vm "br_table with negative i"
- 42
- '(module
- (func (export "main") (result i32)
- (block $foo (result i32)
- (block $bar (result i32)
- (i32.const 21)
- (i32.const -1)
- (br_table $bar $foo))
- (unreachable))
- (i32.const 21)
- (i32.add))))
- (test-vm "inner function call"
- 11
- '(module
- (func $y (param $m i32) (param $x i32) (param $b i32) (result i32)
- (i32.add (i32.mul (local.get $m) (local.get $x)) (local.get $b)))
- (func (export "main") (param $x i32) (result i32)
- (call $y (i32.const 2) (local.get $x) (i32.const 3))))
- #:args '(4))
- (test-vm "imported function call"
- 80
- '(module
- (func $add42 (import "lib" "add42")
- (param i32) (result i32))
- (func (export "main") (param $x i32) (result i32)
- (call $add42 (local.get $x))))
- #:imports `(("lib" . (("add42" . ,(lambda (x) (+ x 42))))))
- #:args '(38)
- #:d8? #f)
- (test-vm "mutable globals"
- 42
- '(module
- (global $foo (mut i32) (i32.const 30))
- (func (export "main") (param $n i32) (result i32)
- (global.set $foo (i32.add (local.get $n) (global.get $foo)))
- (global.get $foo)))
- #:args '(12))
- (test-vm "imported globals"
- 80
- '(module
- (global $foo i32 (i32.const 42))
- (global $bar (import "globals" "bar") i32)
- (func (export "main") (result i32)
- (i32.add (global.get $foo) (global.get $bar))))
- #:imports `(("globals" . (("bar" . ,(make-wasm-global 38 #f)))))
- #:d8? #f)
- (test-vm "immutable global reference in constant expression"
- 42
- '(module
- (global $foo i32 (i32.const 42))
- (global $bar i32 (global.get $foo))
- (func (export "main") (result i32)
- (global.get $bar))))
- (test-vm/error "reference to mutable global in constant expression"
- '(module
- (global $foo (mut i32) (i32.const 42))
- (global $bar i32 (global.get $foo))
- (func (export "main") (result i32)
- (global.get $bar))))
- (test-vm/error "reference to subsequent global in constant expression"
- '(module
- (global $bar i32 (global.get $foo))
- (global $foo i32 (i32.const 42))
- (func (export "main") (result i32)
- (global.get $bar))))
- (test-vm "drop"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (i32.const 13)
- (drop))))
- (test-vm "drop in unreachable code"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (return)
- (drop))))
- (test-vm "select first"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (i32.const 13)
- (i32.const 1)
- (select))))
- (test-vm "select second"
- 13
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (i32.const 13)
- (i32.const 0)
- (select))))
- (test-vm "select in unreachable code"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (return)
- (select))))
- (test-vm "select in unreachable code with i32 on top"
- 42
- '(module
- (func (export "main") (result i32)
- (i32.const 42)
- (return)
- (i32.const 0)
- (select))))
- (test-vm "start function"
- 42
- '(module
- (global $foo (mut i32) (i32.const 13))
- (func $init
- (global.set $foo (i32.const 42)))
- (start $init)
- (func (export "main") (result i32)
- (global.get $foo))))
- (test-vm "table.size"
- 2
- '(module
- (table $funcs 2 funcref)
- (func (export "main") (result i32)
- (table.size $funcs))))
- (test-vm "table.grow within limits"
- 2
- '(module
- (table $funcs 2 3 funcref)
- (func $main (export "main") (result i32)
- (ref.func $main)
- (i32.const 1)
- (table.grow $funcs))))
- (test-vm "table.grow outside limits"
- -1
- '(module
- (table $funcs 1 1 funcref)
- (func $main (export "main") (result i32)
- (ref.func $main)
- (i32.const 1)
- (table.grow $funcs))))
- (test-vm "table.grow no-op"
- 1
- '(module
- (table $funcs 1 1 funcref)
- (func $main (export "main") (result i32)
- (ref.func $main)
- (i32.const 0)
- (table.grow $funcs))))
- (test-vm "table.init with passive element segment"
- 1
- '(module
- (table $a 1 funcref)
- (elem $funcs funcref (ref.null func))
- (func $main (export "main") (result i32)
- (table.init $a $funcs
- (i32.const 0)
- (i32.const 0)
- (i32.const 1))
- (ref.is_null (table.get $a (i32.const 0))))))
- (test-vm "table.fill"
- 1
- '(module
- (table $funcs 3 funcref)
- (elem $funcs (i32.const 0) $main)
- (func $main (export "main") (result i32)
- (i32.const 1)
- (ref.func $main)
- (i32.const 2)
- (table.fill $funcs)
- (i32.const 1))))
- (test-vm "table.copy"
- 1
- '(module
- (table $a 3 funcref)
- (table $b 3 funcref)
- (elem $funcs (i32.const 0) $main $main $main)
- (func $main (export "main") (result i32)
- (i32.const 3)
- (i32.const 0)
- (i32.const 0)
- (table.copy $b $a)
- (i32.const 1))))
- (test-vm "elem.drop"
- 1
- '(module
- (table $funcs 1 funcref)
- (elem $foo (i32.const 0) $main)
- (func $main (export "main") (result i32)
- (elem.drop $foo)
- (i32.const 1))))
- (test-vm "call_indirect"
- 42
- '(module
- (table $funcs 1 funcref)
- (type $i32->i32 (func (param i32) (result i32)))
- (func $inc (param $a i32) (result i32)
- (i32.add (local.get $a) (i32.const 1)))
- (elem $funcs (i32.const 0) $inc)
- (func (export "main") (result i32)
- (call_indirect $funcs (type $i32->i32)
- (i32.const 41) (i32.const 0)))))
- (test-vm "call_ref"
- 42
- '(module
- (type $i32->i32 (func (param i32) (result i32)))
- (func $sum-41 (param $x i32) (result i32)
- (i32.add (local.get $x) (i32.const 41)))
- (func (export "main") (result i32)
- (call_ref $i32->i32 (i32.const 1) (ref.func $sum-41)))))
- (test-vm "ref.null + ref.is_null"
- 1
- '(module
- (func (export "main") (result i32)
- (ref.null func)
- (ref.is_null))))
- (test-vm "ref.test true"
- 1
- '(module
- (type $foo (struct (field $bar (ref eq))))
- (func (export "main") (result i32)
- (ref.test $foo (struct.new $foo (ref.i31 (i32.const 42)))))))
- (test-vm "ref.test false"
- 0
- '(module
- (type $foo (struct (field $bar (ref eq))))
- (func (export "main") (result i32)
- (ref.test $foo (ref.null $foo)))))
- (test-vm "ref.as_non_null"
- 42
- '(module
- (type $foo (struct (field $bar i32)))
- (func (export "main") (result i32)
- (struct.get $foo $bar
- (ref.as_non_null
- (struct.new $foo (i32.const 42)))))))
- (test-vm "ref.cast identity non-null"
- 42
- '(module
- (func (export "main") (result i32)
- (ref.i31 (i32.const 42))
- (ref.cast i31)
- (i31.get_s))))
- (test-vm "ref.cast identity null"
- 42
- '(module
- (func (export "main") (result i32)
- (ref.null i31)
- (ref.cast null i31)
- (drop)
- (i32.const 42))))
- (test-vm/error "ref.cast null"
- '(module
- (func (export "main") (result i32)
- (ref.null i31)
- (ref.cast i31)
- (i31.get_s))))
- (test-vm "external reference passthrough"
- '(opaque to wasm)
- '(module
- (func (export "main") (param $foo externref) (result externref)
- (local.get $foo)))
- #:args '((opaque to wasm))
- #:d8? #f)
- (test-vm "i31.get_s"
- -42
- '(module
- (func (export "main") (result i32)
- (i31.get_s (ref.i31 (i32.const -42))))))
- (test-vm "i31.get_u"
- 2147483606
- '(module
- (func (export "main") (result i32)
- (i31.get_u (ref.i31 (i32.const -42))))))
- (test-vm "struct.get"
- 5.0
- '(module
- (type $vec2 (struct (field $x f32) (field $y f32)))
- (func (export "main") (result f32) (local $v (ref $vec2))
- (local.set $v (struct.new $vec2 (f32.const 3.0) (f32.const 4.0)))
- ;; Calculate vector magnitude, for fun.
- (f32.sqrt
- (f32.add (f32.mul (struct.get $vec2 $x (local.get $v))
- (struct.get $vec2 $x (local.get $v)))
- (f32.mul (struct.get $vec2 $y (local.get $v))
- (struct.get $vec2 $y (local.get $v))))))))
- (test-vm "struct.get_s"
- -42
- '(module
- (type $foo (struct (field $bar i8)))
- (func (export "main") (result i32)
- (struct.get_s $foo $bar (struct.new $foo (i32.const -42))))))
- (test-vm "struct.get_u"
- 214
- '(module
- (type $foo (struct (field $bar i8)))
- (func (export "main") (result i32)
- (struct.get_u $foo $bar (struct.new $foo (i32.const -42))))))
- (test-vm "struct.set"
- 42
- '(module
- (type $foo (struct (field $bar (mut i32))))
- (func (export "main") (result i32) (local $a (ref $foo))
- (local.set $a (struct.new $foo (i32.const 0)))
- (struct.set $foo $bar (local.get $a) (i32.const 42))
- (struct.get $foo $bar (local.get $a)))))
- (test-vm "struct subtyping"
- 42
- '(module
- (type $heap-object
- (sub
- (struct
- (field $hash (mut i32)))))
- (type $pair
- (sub $heap-object
- (struct
- (field $hash (mut i32))
- (field $car (mut (ref eq)))
- (field $cdr (mut (ref eq))))))
- (func (export "main") (result i32) (local $a (ref $pair))
- (local.set $a (struct.new $pair (i32.const 1)
- (ref.i31 (i32.const 21))
- (ref.i31 (i32.const 21))))
- (i32.add (i31.get_s (ref.cast i31 (struct.get $pair $car (local.get $a))))
- (i31.get_s (ref.cast i31 (struct.get $pair $cdr (local.get $a))))))))
- (test-vm "struct.new_default"
- 0
- '(module
- (type $foo (struct (field $bar i32)))
- (func (export "main") (result i32)
- (struct.get $foo $bar (struct.new_default $foo)))))
- (test-vm "array.len"
- 3
- '(module
- (type $foo (array i32))
- (func (export "main") (result i32)
- (array.len (array.new $foo (i32.const 0) (i32.const 3))))))
- (test-vm "array.get"
- 42
- '(module
- (type $foo (array i32))
- (func (export "main") (result i32)
- (array.get $foo (array.new $foo (i32.const 42) (i32.const 1)) (i32.const 0)))))
- (test-vm "array.get_s"
- -42
- '(module
- (type $foo (array i8))
- (func (export "main") (result i32)
- (array.get_s $foo (array.new_fixed $foo 1 (i32.const -42)) (i32.const 0)))))
- (test-vm "array.get_u"
- 214
- '(module
- (type $foo (array i8))
- (func (export "main") (result i32)
- (array.get_u $foo (array.new_fixed $foo 1 (i32.const -42)) (i32.const 0)))))
- (test-vm "array.set"
- 42
- '(module
- (type $foo (array (mut i32)))
- (func (export "main") (result i32) (local $a (ref $foo))
- (local.set $a (array.new $foo (i32.const 0) (i32.const 1)))
- (array.set $foo (local.get $a) (i32.const 0) (i32.const 42))
- (array.get $foo (local.get $a) (i32.const 0)))))
- (test-vm "array.new_fixed"
- 42
- '(module
- (type $foo (array i32))
- (func (export "main") (result i32)
- (array.get $foo (array.new_fixed $foo 1 (i32.const 42)) (i32.const 0)))))
- (test-vm "array.new_default"
- 0
- '(module
- (type $foo (array i32))
- (func (export "main") (result i32)
- (array.get $foo (array.new_default $foo (i32.const 1)) (i32.const 0)))))
- (test-vm "array.new_data"
- 4
- '(module
- (type $foo (array i32))
- (data $init #s32(1 2 3 4))
- (func (export "main") (result i32)
- (array.get $foo (array.new_data $foo $init
- (i32.const 0)
- (i32.const 4))
- (i32.const 3)))))
- (test-vm "array.new_elem"
- 4
- '(module
- (type $foo (array (ref i31)))
- (elem $init (ref i31)
- (item (ref.i31 (i32.const 1)))
- (item (ref.i31 (i32.const 2)))
- (item (ref.i31 (i32.const 3)))
- (item (ref.i31 (i32.const 4))))
- (func (export "main") (result i32)
- (i31.get_s
- (array.get $foo (array.new_elem $foo $init
- (i32.const 0)
- (i32.const 4))
- (i32.const 3))))))
- (test-vm "array.init_data"
- 4
- '(module
- (type $foo (array (mut i32)))
- (data $init #s32(1 2 3 4))
- (func (export "main") (result i32)
- (local $a (ref $foo))
- (local.set $a (array.new $foo
- (i32.const 0)
- (i32.const 4)))
- (array.init_data $foo $init
- (local.get $a)
- (i32.const 0)
- (i32.const 0)
- (i32.const 4))
- (array.get $foo (local.get $a) (i32.const 3)))))
- (test-vm "array.init_elem"
- 4
- '(module
- (type $foo (array (mut (ref i31))))
- (elem $init (ref i31)
- (item (ref.i31 (i32.const 1)))
- (item (ref.i31 (i32.const 2)))
- (item (ref.i31 (i32.const 3)))
- (item (ref.i31 (i32.const 4))))
- (func (export "main") (result i32)
- (local $a (ref $foo))
- (local.set $a (array.new $foo
- (ref.i31 (i32.const 0))
- (i32.const 4)))
- (array.init_elem $foo $init
- (local.get $a)
- (i32.const 0)
- (i32.const 0)
- (i32.const 4))
- (i31.get_s
- (array.get $foo (local.get $a) (i32.const 3))))))
- (test-vm "array.fill"
- 42
- '(module
- (type $foo (array (mut i32)))
- (func (export "main") (result i32) (local $a (ref $foo))
- (local.set $a (array.new_default $foo (i32.const 1)))
- (array.fill $foo
- (local.get $a)
- (i32.const 0)
- (i32.const 42)
- (i32.const 1))
- (array.get $foo (local.get $a) (i32.const 0)))))
- (test-vm "array.copy"
- 42
- '(module
- (type $foo (array (mut i32)))
- (func (export "main") (result i32) (local $a (ref $foo))
- (local.set $a (array.new_default $foo (i32.const 1)))
- (array.copy $foo $foo
- (local.get $a)
- (i32.const 0)
- (array.new_fixed $foo 1 (i32.const 42))
- (i32.const 0)
- (i32.const 1))
- (array.get $foo (local.get $a) (i32.const 0)))))
- (test-vm "reference type constants"
- 42
- '(module
- (type $foo (array (ref i31)))
- (global $bar (ref $foo)
- (array.new $foo
- (ref.i31 (i32.const 42))
- (i32.const 1)))
- (func (export "main") (result i32)
- (i31.get_s
- (array.get $foo
- (global.get $bar)
- (i32.const 0))))))
- (test-vm "string.const"
- "Hello, world!"
- '(module
- (func (export "main") (result (ref string))
- (string.const "Hello, world!")))
- #:d8-read get-line)
- (test-vm "string.new_lossy_utf8_array"
- "HELLO"
- '(module
- (type $utf8 (array (mut i8)))
- (func (export "main") (result (ref string))
- (string.new_lossy_utf8_array (array.new_fixed $utf8 5
- (i32.const 72)
- (i32.const 69)
- (i32.const 76)
- (i32.const 76)
- (i32.const 79))
- (i32.const 0)
- (i32.const 5))))
- #:d8-read get-line)
- (test-vm "string.encode_wtf8_array"
- 5
- '(module
- (type $utf8 (array (mut i8)))
- (func (export "main") (result i32)
- (string.encode_wtf8_array (string.const "HELLO")
- (array.new $utf8
- (i32.const 0)
- (i32.const 5))
- (i32.const 0)))))
- (test-vm "string.measure_utf8"
- 5
- '(module
- (func (export "main") (result i32)
- (string.measure_utf8 (string.const "HELLO")))))
- (test-vm "string.measure_wtf8"
- 5
- '(module
- (func (export "main") (result i32)
- (string.measure_wtf8 (string.const "HELLO")))))
- (test-equal "inter-instance function calls"
- 17
- (let* ((wat-a '(module
- (func (export "square") (param $x i32) (result i32)
- (i32.mul (local.get $x) (local.get $x)))))
- (wat-b '(module
- (func $square (import "wasm" "square") (param i32) (result i32))
- (func (export "main") (param $x i32) (result i32)
- (i32.add (call $square (local.get $x)) (i32.const 1)))))
- (wasm-a (wat->wasm* wat-a))
- (wasm-b (wat->wasm* wat-b))
- (inst-a (instantiate-wasm (validate-wasm wasm-a)))
- (square (wasm-instance-export-ref inst-a "square"))
- (inst-b (instantiate-wasm (validate-wasm wasm-b)
- #:imports `(("wasm" .
- (("square" . ,square)))))))
- ((wasm-instance-export-ref inst-b "main") 4)))
- (test-vm "try"
- 111
- '(module
- (tag $foo (param i32))
- (func (export "main") (result i32)
- (try (result i32)
- (do (i32.const 42)
- (throw $foo))
- (catch $foo
- (i32.const 69)
- (i32.add))
- (catch_all
- (unreachable))))))
- (test-vm "try_delegate"
- 111
- '(module
- (tag $foo (param i32))
- (func (export "main") (result i32)
- (try $bloop (result i32)
- (do (try
- (do (i32.const 69)
- (throw $foo))
- (delegate $bloop))
- (unreachable))
- (catch $foo
- (i32.const 42)
- (i32.add))
- (catch_all (i32.const 77))))))
- (test-vm "rethrow"
- 42
- '(module
- (tag $foo)
- (func (export "main") (result i32)
- (try $l1 (result i32)
- (do (try $l2 (result i32)
- (do (throw $foo))
- (catch $foo
- (rethrow $l2))
- (catch_all (unreachable))))
- (catch $foo
- (i32.const 42))
- (catch_all (unreachable))))))
- (test-equal "throw across instances"
- 111
- (let* ((wat-a '(module
- (tag $err (export "err") (param i32))
- (func (export "foo") (param $x i32)
- (throw $err (local.get $x)))))
- (wat-b '(module
- (tag $err (import "other" "err") (param i32))
- (func $foo (import "other" "foo") (param i32))
- (func (export "main") (param $x i32) (result i32)
- (try (result i32)
- (do (call $foo (local.get $x))
- (unreachable))
- (catch $err
- (i32.const 69)
- (i32.add))
- (catch_all (unreachable))))))
- (wasm-a (wat->wasm* wat-a))
- (wasm-b (wat->wasm* wat-b))
- (inst-a (instantiate-wasm (validate-wasm wasm-a)))
- (err (wasm-instance-export-ref inst-a "err"))
- (foo (wasm-instance-export-ref inst-a "foo"))
- (inst-b (instantiate-wasm (validate-wasm wasm-b)
- #:imports `(("other" .
- (("err" . ,err)
- ("foo" . ,foo)))))))
- ((wasm-instance-export-ref inst-b "main") 42)))
- (test-end* "test-vm")
|