From a5218f1f118aeae63ccb788043e5de61c36874c5 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 16:31:19 +0200 Subject: [PATCH 001/181] Initial overview --- README.md | 13 +++++++- document/core/index.rst | 2 +- document/core/util/macros.def | 8 ++--- proposals/multi-memory/Overview.md | 52 ++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 proposals/multi-memory/Overview.md diff --git a/README.md b/README.md index 26d58a3a5..d8e89bedb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ -[![Build Status](https://travis-ci.org/WebAssembly/spec.svg?branch=master)](https://travis-ci.org/WebAssembly/spec) +[![Build Status](https://travis-ci.org/WebAssembly/multi-memory.svg?branch=master)](https://travis-ci.org/WebAssembly/multi-memory) + +# Multi Memory Proposal for WebAssembly + +This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). +It is meant for discussion, prototype specification and implementation of a proposal to add support for returning multiple values to WebAssembly. + +* See the [overview](proposals/multi-memory/Overview.md) for a summary of the proposal. + +* See the [modified spec](https://webassembly.github.io/multi-memory/) for details. + +Original `README` from upstream repository follows… # spec diff --git a/document/core/index.rst b/document/core/index.rst index 1d8d6a4aa..2371eedc8 100644 --- a/document/core/index.rst +++ b/document/core/index.rst @@ -3,7 +3,7 @@ WebAssembly Specification .. only:: html - | Release |release| (Draft, |today|) + | Release |release| + multi-memory (WIP Draft, |today|) | Editor: Andreas Rossberg diff --git a/document/core/util/macros.def b/document/core/util/macros.def index 0354e12a0..a1f28e451 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -3,11 +3,11 @@ .. External Standards .. ------------------ -.. |WasmDraft| replace:: http://webassembly.github.io/spec/core/ -.. _WasmDraft: http://webassembly.github.io/spec/core/ +.. |WasmDraft| replace:: http://webassembly.github.io/multi-memory/core/ +.. _WasmDraft: http://webassembly.github.io/multi-memory/core/ -.. |WasmIssues| replace:: http://github.com/webassembly/spec/issues/ -.. _WasmIssues: http://github.com/webassembly/spec/issues/ +.. |WasmIssues| replace:: http://github.com/webassembly/multi-memory/issues/ +.. _WasmIssues: http://github.com/webassembly/multi-memory/issues/ .. |IEEE754| replace:: IEEE 754-2019 .. _IEEE754: https://ieeexplore.ieee.org/document/8766229 diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md new file mode 100644 index 000000000..958de53f8 --- /dev/null +++ b/proposals/multi-memory/Overview.md @@ -0,0 +1,52 @@ +# Multiple Memories for Wasm + +## Summary + +This proposal adds the ability to use multiple memories within a single Wasm module. +In the current version of Wasm, an application can already create multiple memories, but only by splitting things up into multiple modules. +A single module or function cannot refer to multiple memories at the same time. +Consequently, it is not possible to e.g. efficiently transfer data from one memory to another, since that necessarily involves an individual function call into a different module per value. + +## Motivation + +There are a number of use case scenarios for using multiple memories in a single application: + +* *Security.* A module may want to separate public memory that is shared with the outside to exchange data, from private memory that is kept encapsulated inside the module. + +* *Persistence.* An application may want to keep some of its memory state persistent between runs, e.g., by storing it in a file. But it may not want to do that for all its memory, so separating lifetimes via multiple memories is a natural setup. + +* *Linking.* There are a number of tools out there that can merge multiple Wasm modules into one, as a form of static linking. This is possible in almost all cases, except when the set of modules defines more than one memory. Allowing multiple memories in a single module closes this unfortunate gap. + +* *Scaling.* As long as Wasm memories are limited to 32 bit address space, there is no way to scale out of 4 GB memory efficiently. Multiple memories at least provide an efficient workaround until 64 bit memories become available (which may still take a while). + +* *Polyfilling.* Some proposals, e.g., [garbage collection](https://github.com/WebAssembly/gc) or [interface types](https://github.com/WebAssembly/interface-types) could be emulated in current Wasm if they had the ability to add an auxiliary memory that is distinct from the module's own address space. + + +## Overview + +The original Wasm design already anticipated the ability to define and reference multiple memories. In particular, there already is the notion of an index space for memories (which currently can contain at most one entry), and most memory constructs already leave space in the binary encoding for it. +This proposal fills in the holes accordingly. + +This generalisation is fully symmetric to the extension to multiple tables in the [reference types](https://github.com/WebAssembly/reference-types) proposal. + +The design of this extension is almost entirely canonical. Concretely: + +* Allow multiple memory imports and definitions in a single module. + +* Add a memory index to all memory-related instructions. + - Loads and stores have the memop field, in which we can allocate a bit indicating a memory index immediate. + - All other memory instruction already have a memory index immediate (which currently has to be 0). + +* Data segments and exports already have a memory index as well. + +* Extend the validation and execution semantics in the obvious manner. + + +## Implementation + +Engines already have to deal with multiple memories, but any given code so far can only address one. +Hence, in current engines, reserving one register for the base address is a common technique. +Multiple memories will typically require an extra indirection (which some engines already have). + +Engines could conservatively continue to optimise access to memory index 0 via a dedicated register. +PResumably, we could also eventually add a future custom section with optimisation hints, which could e.g. mark the index of the "main" memory. From 8e9cc32408d5bda8a64f2be555a8e86ede760d46 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 16:57:25 +0200 Subject: [PATCH 002/181] Setup travis --- .travis.yml | 2 +- deploy_key.enc | Bin 3248 -> 3360 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6ecbdb356..6eee34bc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,5 +26,5 @@ os: linux env: global: - - ENCRYPTION_LABEL: "304454be9d6c" + - ENCRYPTION_LABEL: "85778253acbe" - COMMIT_AUTHOR_EMAIL: "noreply@webassembly.org" diff --git a/deploy_key.enc b/deploy_key.enc index b6d3e2f19771652a9711760b1712a77fe1b4e579..dc3ad153e8943f59fb98a0f94d7f85d97f5eab96 100644 GIT binary patch literal 3360 zcmV+*4d3z$D!3Vmwp4z-x@9IK*9e9PXH&el(bN`5Pn8 zr4axI&Q_MtP}l^q(haZ4VgBz*<~XC;dtVXW`xxb?dkUFsF`#${ygCrc7=lJbiU(A7 zL4DoQELT^SzL)_eJmvS(6!FOEGr!#hWO3+K#EAV>>4MSfrK@;5NsM-a9DrLV03g^7Fp*TyUz3n(ddutm5@2MYK=$YM7& zqWd^*Ak)2_a#tFtlLu5r&k_i zl%+%d#|wl-r0;abU%ud;EWQrmN-;?IowKQURUFq%E;UYnUZ;VqYN-X*ip8TpioNl9 zR5R$A8lH`LQ+lzq7So!84>81noZULH+ykF9xhnByNA{fyGR^2r? zSnsUBH|hO=XWE3Z*{m!dAGAdEGTBssS%A2HysZWUX=WjDsim@r?QTw*-oF7GG$vB0 zTIqtWI-JT&VhE^LDF|%cSEAcVAZ0T^hyKBdIw9Eal(}EQSb!qA(+@{J|CsT|?L5a9 zc7!>C-9&b`mC7|sm!H_Jg{S5x(tQG<7~wKhBiCN+O%IhU68VT5FAi=Ggz203*@wKr z&V|E5bSaqx*)pxoRVY+w-{n=jngM+$`ql`K4TGrzE9 zUpcfILHw=gD8)xLwpi$X1ZK* zC0-z^ycAeV1IB=4%R*;|bVQz?T6Dk^d4qbtW<9dDr5cPd4W|)CyWD9ab+r6k8u*KOqY_Pm#H~4c9!IMW*N~`i z5HtzppsP&IVaR3lAE@K<FxI4jR= z!b-WRef-W?$|NuqZm5) zCIw#HlrQzXZVX)`dj1N{R`cC^tt+sM`>1rhk0NOA!(Snx!lspOXogcjkam2xJ zif=HL*H$iz==QlE_V81O+E&mY82V~;>P=$1`gxU<9A2Apg57~0hnAMFZHIrK5a!!_ zxm5&ph|0QA5h)zul)Elphgmuw78>uiLfvpaX}#x04`qtwplQ6OJ=qS=l?OCvVRK71 z!hPBFX!?&Yv23QJMi&>uN&JJwuD`2M=k^>xT{D=dQwVo_>xl-${DbrB6!$7VXsh~ zA`mPKEv@u%m*g7g)*w8UfG1$*JRBcSW;aN7!y8}(SX9DI4u7DN_U7tC>aOr4_PLhi zxCwzQU;Q%o^=fBLJPNsNr=O597kdouek)th$48v@1qTq*w%D!I#iZqni+67rcB7IY zGy_)Dn5uUVu6s<-&Al>e0RCXdsl9<8b)j+%v}YKB1~R3!z0Z{HznBZ*vB8|F+)E2X z4Qp$;zS%_T`{%zxe$xKJnm)9Zg=ayV74j}Qc7feZSQRVU?A0YMY zscE=cB7rmsSD{WK#!Y;G5O_`)p8uVgjLSU#2YkM8Ne8UT5a&2d8~>YuvtyFa>WK{B%p}ly`7ygLXlEr>>5QwkQ z%zxl#lrZfc?F2l=|8A*%vMaIs;a`W5%0SMm;FVBotQmW#{lIRyf6j!f;q~w;sac=K z)IWoAq!VDy{b5$9&4HV{L8ztZ7q0k-^9&P3hmT_|ISMC0G%YVya{{hH^_+c($o$}- z#q2>nUz@a@d-@VGq_p3E+8kfX@-YFa006r>;|qVQ3f91A{$E$;Cfr#u@);m=;dXC%9W zr29RQY1S=6Z=Sw1_cm;dUA(P+Tf%|z|B>c=MygG*S%T;QwkpK5oki5HU^Uwm!a}68 zSo(H_+Y_(958E^e^DXO?vzyDI&H&?Hhb~plX-=NYTst%Rubt|Kc5{ESiTJBeW%3W) zoT|LvVI;{~j_k_7x6B})oa!a!aIkeCy%Vl};it4c6|r|#vv_uCK>A{KZ5*|aREVDL zK&Jtm0-^p;9EoN9f4aAA^*5Al*ueFQGfE+zPei$2)}2>RwTb|fMrWP^yhCQu6=+-- z|4mObZ}#(YVK7K!7*0eECt;kV+JkPh=2mfNY^t7y$2i$NH)ejhGtYAnV~l572^d%6 z3<=S49=+|Q+jvqDi;5q0!xFFkRj+X-d@$7@uE}AXQYFABBvxQBsLbUM0px!ALnSWD zDq68T$lJY_Uj;r~(Ik-UM#HzQxtYK&13gf&D1^u~kTt&CWP5eO%H7O_s0j3(Re zJ9wy@2sPmARLyE&H0ncRPAz1$4H{|Hsw$n>B7@ka>Xd`U7woi6CtWTWJ5REzpVcJp zjYDH$$ULy$1(=Dvq;puI!NwJpwFd<`BNY;m+92(Fzl7CwFXV{!5$Hsm%->bT9451FHPj2!perd713-Zo&DhoV zo@yYF(kFc+?bTnGz2QKg?akp!StQYF*I-J#F`ltc{`?vBNi{ab1NB$>=HKl%8%Vd+ zlRj%hD);F2Px+=)^J{lA)CmEn3IMtQ+PKc?U}(b{m*R0>;1!Dl>qFXCFK^7o66l*I zLifPC;B~8Y7gB2$co39m`u@fsvysssJ|ERjZTSf+QV)bj7IxpC!gJibNHyPSO#Su; z6;qwLr>l>Jbs7~&Sc>@7Jl8+#`F;VaFQWtrPLAGuLMZF$e&~Bhc2!GE2 literal 3248 zcmV;h3{UeoaMr!6kTNmX>{8Y#<|(CVbO6TJr-;79Ag-eBM!B~g(FTQ5ldW}>C6w#F z7?FSyFeYZ$v_V^lQFEF>+7k9B7m`7vS_SQ$;wWv|QOclL{NpaXb;g5ti(%WUt|3;5 z3CA#OrS)XS){2AUta7q}MSmhTJq zo{c?28()!ibPsqvTfOAA!4zOONU^F*gLcD(DrJbnNphXRZ3yC#LaPJi{CC$C(2A_7 zNaF$Iwo+ftMAzTpRFW1@B>=0mk{V^}DS!4rt3&v*?r8!}EfiTzY#jX?%ckauU9h@W zx(fD`Pk=~T7D1zi5Xgo-F3df<=bCbjU0(ZD&z`12ST)Xxn<2-%!cB^F0IoG~-*{lROB{l$8;> zQYD6uvZB!WjR97=Gm5k(nd?fS-skc&EK?_V8WnS+v(_4N1NbVfWy{T9c3+w+eKW@y z`gzb1V%Tr>ul(ay+I}7y2o4<>nNeC`_9<4dQwbaZcv=lR5j&@)QY$OIg__IEl?CzP zj*w)N-7!X;zax-wu2%HYpX17nK^l2cLppXhM>Q8<9AmF4V+?wF~S-rGWRU;<& zEfi}`>wt%Un_w@H!oNoZ>x+M|o6OWL0ZWAvCDS3ci~T8hKI0BHLyhmaX>a@YdQNK^9SJORstB zfvrm3TfM$`MMQQXp+4m=U~?Y#8>LXJEJKe+QT3ai?lI{90Zbd!SJdk4H(U1tebkQS zElH@QyluL-tMcF~ED_;l>!0Ijv*4gtnDwmLYV{a3@tjZ`D zFgG=OkZ90lfbv6>Fy&2v?b=c~Y_N9G zUi9};vfpk;9dPn4FMkaR{o~nn&h!a-?Sdb%SZ)!fI~GWnk~X{F~0*MZTR*=jmm-h1@t zDL!$f-TC0j9#3k6yGm=yVm`^%@wfi3bq#*03KSe>$d+&xjHOcMc8uJt8)hN2{SBal z4ob$b$`dj=o#p1YnW?UI^yZ;rkMjLI{F#<8G09bp2NC-f7?!MtUZ(JwIdFlSzu%EdX7u+as(dHl z58QQZ`uk&2UcuOD{=l^SW7lbUC)YQxLZoD(4yfjbALj)ocgYIM0ZYz?(TpdH^*N^lP&fD?>5S3l5d9vDe0MYX}=L@v0ac*d^h zMC3X&i8_TGc*nis1+Hbb@FGCYM0^b7+Ks%np4Yi`?%nMjTjK}kiD^peA^u+*e>(aKEP(B~>~mZq#KO^e z%~M*@SsY^h6(tY`GdMou`@})%F*bIbRNZ>mC~Kmlo-i?%UtfW#dT*z*RcdL zpk60TCgJqxKBvX~s$%Shh(AI%*I`@P2!X_@lhC_lv0_yIg6%&*TKAQRPZQNW>=_H-#1pBvjD+m{Zb}zcH8nbpNqr9whn4 zA=y)BHKQ-DrD~ATW$s5sLj-tJ#cf~=mO{+4YNwZc;4(}zeG0i5iXTW*#VVOL90%~C zVKMQHgk?j=XH43>K+-CeY3%JXI)VIB$Ad;DSsk-VJs=GfjP+|s{r){_ozCKbFDNi| zfEk3yUlIo}(x+SiFz(8%;%1%!B5`O|M9Tgg3bui&lu)v`(ydUn{aib=ktlW8MU&;r zQ+2LIr_4e3%GTLQ5?58orh7HmWd&Z&T0Uz!9~Ha`K^gp=fQ`FR=0~z|>MuzT4#e%& zBXJPHh`^tE;|zIgNiR(*kU@PB&}J%3Coh;M^QnC8vP7h%*_Gozd?$RZWr_#dXYF>u zT>^8L;b}KO+gPONfMBv1ae%Hy6R+;S^w+Ng{zo&nGB`o<^fxC>{v`=!WnoSACN9e? z!P}dgK-N^z=5p%- zjAkKdA-dFrZxs{<7wntcycPzJOC})W{%YX>7&0{p8S%XXI0{sJi2me-X!z#kb@^(L zIrTxbTFMXTi!+maqh2OdhC54A&#rQ{4~>UL|6E*af1FP^b#OX~#=VRt;}}z+FhX7& z(?0)PAKjGZ*g(dZNg81514!QK;bQWS0-qDq&xgnv8vdcEkLzW9YdU7Q`jSwWHd*~b zqQ?O;jM%iLY>Zw*$r*lZ~?dz)vtCi6GqzmKd+b z!(zZgpXf?*+wbzsxQ&XJ3)2p#3|IEa$pe0b>QbH=rr|j)yS-i=SFADE7tJ`oCmN@} zL{UA^mr)_ZWdcbz>BGLSKFnFY^oV4EXulUCv6iQUG?d~nuNbxQiWI`F1pbLxAfG^h iY#Pu|2q&8>`3}#6q-2Cz`ZEbT?K&=q;2asiqpF?e?>4gl From 0cce8a7a4ad3a6cdc5e77cc1352fe0329a2a1a3c Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 17:20:37 +0200 Subject: [PATCH 003/181] Fill in some structure --- proposals/multi-memory/Overview.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 958de53f8..09b9abfb4 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -42,6 +42,32 @@ The design of this extension is almost entirely canonical. Concretely: * Extend the validation and execution semantics in the obvious manner. +### Instructions + +#### Loads and Stores + +TODO + +#### Other Memory Instructions + +TODO + + +### Modules + +#### Data Segments + +TODO + +#### Exports + +TODO + +#### Modules + +TODO + + ## Implementation Engines already have to deal with multiple memories, but any given code so far can only address one. From c37e5d70c6d60e25803224d33247712af57af34a Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 17:22:38 +0200 Subject: [PATCH 004/181] Test Travis --- proposals/multi-memory/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 09b9abfb4..38327ed54 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -34,7 +34,7 @@ The design of this extension is almost entirely canonical. Concretely: * Allow multiple memory imports and definitions in a single module. * Add a memory index to all memory-related instructions. - - Loads and stores have the memop field, in which we can allocate a bit indicating a memory index immediate. + - Loads and stores have the memop field, in which we can allocate a bit indicating a memory index immediate in the binary format. - All other memory instruction already have a memory index immediate (which currently has to be 0). * Data segments and exports already have a memory index as well. From 233b4730b12b2551ca7c04ac898b2747ac3c3a68 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 18:04:35 +0200 Subject: [PATCH 005/181] Try deploy key with more permissions --- deploy_key.enc | Bin 3360 -> 3360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deploy_key.enc b/deploy_key.enc index dc3ad153e8943f59fb98a0f94d7f85d97f5eab96..459fa4223409a8bac3d3557708467d106ec5860e 100644 GIT binary patch literal 3360 zcmV+*4d3#$4d}#%IVVLeUQ!`I9(NCRY135DZVMn3YA(9GWD|xTPk=b84JxzuZ1Po; zQExO%uZ-;_#Ov~m3m=JBXR{wSLoWuv?M?#~;ajNF7Y8I;SK4!+&Ii+Px?xGPCZ+Zi zSy$2iymb_+azOGiTxIbzWj~?q=QDz!W$Ne9Bq@E{H*X2W6v>+Z=W)#D?b@(8&&~qU zu}2Mj0?Il+oBV_YowOS5GBr8vE7gfDDp|-1)&30MCR&cZ5H~+*VkuFKGV4&!-ii2X zsK~7yExt+S0pGUh%yyNdF2wJ#%+u2#V%iREP|+kW|H!fs!SS7|40J$C+j}W%{j|Da z%&n00R?%lx*zamqldL6Fg~1q-m^yZm>M%cy{d{fMXiwgWjBQW|@X?d2h3`?$TV`9!KbBsEfXvK7BHmG8Vo(ffg@|Zp`0z@Zkw6hmcEIg2i4jzqcOivMKz{5=QSj@xqh;`<1%<+_L|p%}NIr)CBcwR1Qm_=hU5G0XERK;!?&OUf z`&q^74P_^Blq9cST2h_o>Dc-tOpu|T{~Yur#S87SxE&e+w;F_s#0(iqOrqD-{Y~ls z^f%`@ya(!;%A2?3P@I2t&yvk7SzBI)Le+((UhIoWL%Ij)Ej%NAw8XhNEr{n{gdf4( ziI>@3Sfgu5v-FcZ9{*Wlz5w!O%yr zSQ3<08H(eE?1BU(u*Z1{k3B3*00z@>XgS+jq{rZruHr0H51P`ggLI16sCk*=;%Z!t zQPg+X#)~Y;c2RCxuZYZ16+iYqmvFhzlFNxybx}~?KV1`!AP3AwBo-}RCcMy)*{z0V zP8SqCT!mF;VZNTp6AnjP{{A_Hm7St|tfhUGS-~P<&PeEbB&yDIiL#6mPy%z-D|;X0 zFKWThYG}^PvOA74>nmIo>~D8Zjfp#2woM!c@B9DE<4=~E15p|JUQiLopzq$vw|fJ^ zia;4#ghifkYYQGV|D^T=UcP6L!1{}1Uh?n{vi zr{2&M(&Lu^M&u|SBhp&`kV3#$8Lu#PEMg6^uVQC;$QfuLWNOqjV>^2xb_%@l3Q)0g zYm$R9((?n1eKV-W=m=3u;_LqK?*E0Kj$eg;^gg~(R!0#1U~lZM5;;tbk} zp$1!Ho%Ae=p4Eo(W(_Jc`?%Kdb8q!^1wJoj!ydU|>JRBbn}%P3J{OVn4R22dclYP;|tRAx0)woklq^+r%}0 z#uUA;i7s`(C3ZbFJR&Rp^*nkNW~cq_It|3~O`I2avtb06k@@NfPqgrK_~@1+9y@|VL0A`TBC{010 zkra!qC}Yo%2R>f%>7qE)?d=vc(uUo7D35(qHS2jUTM0&? zbFdUS0c}$UsUxgWCj?`)DG&nT@$g(!`!GP=CYPZEB&?+TcYK%K`n3RaH=NnmAw3fZ&elSUI!m!sIFv(N^ut7!a(Xbq zJ#L%P$395$yFdS60t?cHX|gxvR@mcd%vBQRVNuM%`ldJ)LkitBLY7i1O{w9v67UX= znI_QGUy2m{E+|@_6K?>h8Iaj31~WiV$w%k>HQ4p}v$mEoWuTElJ~BQRJaE@96#2<3 zSq+dI2%xgbl0t6*r#TT;{e z>0%8tqJQZ}h)8on!1S$=xJigP!df_WBK%#>#`;8x`S3w_(+zOr!Vkl&mc$^c&@-$= zVAXP0-Rk5{k{ReeoQq;D5tRxJ(H6w1zax#(+a`T=0((r!OmNc0SFa(|o0=@%y@YvK zd@wTPf-0M4m464cFi!l)hGAJRq^bix zE;ciXqKzwMZ!{j1^oJP}YtFnPA}kZgK!P&yK;RkG8q!danb602gi^}phu%HRnq zoC)oDEDiYRSC+B%oyK%)LM029Q}50}|7jbkWJIN$2l{rQgueZB#L=vD}h)5z$6vC(D4{TnV8eJMp-MY8y^|s_=ljz~B z6vsxm8hPtYsR~u~79dvskR!Ca~y_~)!7q({O9>SJ5qgv-5 zE)a5$dk}?DW_joCB7gw?Y*9{|y=69=;<6&jt0-wS)^@zYdJ?wx0nC_=13w5z3G^M% zfQIyZS-$(U+&Yk%4?1r-Vd&DWemgd57RTT%-O}ANSFg_Zm8W#Sxm2=D+bumST%!K% z{7!%HF!2=~qj;sccigfK^-6MyaE60ex+SDaTSVnEkDpy@SS-GVK6sWsvyJFYPHS7u zf+!){J{lwG_4HU%s>*AU6CG2(u}JYFigapjfZx^XG91_x=GD`dTd8K0gpI#DgU!LndPai%N zOT9Jt%8_+<<ksGu(|?H5bp(=_Z3LV_LmIrA98@c3jGa z0Gsu#%T2mIni(<5LP=VuDyVl9w#x{SEzTW%QK3cP!FXZ37l^$pMRv=QXmA)xqo+~b z@DW=v?8UyuIp<)Lwp>z=1076kz&2EmD- zf9{_$;a2;#ke0)uhRTF&8FWC!tP;q|u8WYW;P1zi8EN;YuR7R`yq`+vvH&3?jV0j^ zUH%RC^e!8)ZYU*l5CeWhdg44V7i3GBX5V_6<65`^t_kH8$xsNo9K8}sJ)4_2n@T<8 zKcdcc-54l4ziXj-r=G3gNJU@(O`VQ&u0Z-e_&yOs6f8f#J{G5z9YRHp#dP+J+18u% zaoOcOel=IRD>`*|N5E^S321azf}%Jh>eQ? literal 3360 zcmV+*4d3z$D!3Vmwp4z-x@9IK*9e9PXH&el(bN`5Pn8 zr4axI&Q_MtP}l^q(haZ4VgBz*<~XC;dtVXW`xxb?dkUFsF`#${ygCrc7=lJbiU(A7 zL4DoQELT^SzL)_eJmvS(6!FOEGr!#hWO3+K#EAV>>4MSfrK@;5NsM-a9DrLV03g^7Fp*TyUz3n(ddutm5@2MYK=$YM7& zqWd^*Ak)2_a#tFtlLu5r&k_i zl%+%d#|wl-r0;abU%ud;EWQrmN-;?IowKQURUFq%E;UYnUZ;VqYN-X*ip8TpioNl9 zR5R$A8lH`LQ+lzq7So!84>81noZULH+ykF9xhnByNA{fyGR^2r? zSnsUBH|hO=XWE3Z*{m!dAGAdEGTBssS%A2HysZWUX=WjDsim@r?QTw*-oF7GG$vB0 zTIqtWI-JT&VhE^LDF|%cSEAcVAZ0T^hyKBdIw9Eal(}EQSb!qA(+@{J|CsT|?L5a9 zc7!>C-9&b`mC7|sm!H_Jg{S5x(tQG<7~wKhBiCN+O%IhU68VT5FAi=Ggz203*@wKr z&V|E5bSaqx*)pxoRVY+w-{n=jngM+$`ql`K4TGrzE9 zUpcfILHw=gD8)xLwpi$X1ZK* zC0-z^ycAeV1IB=4%R*;|bVQz?T6Dk^d4qbtW<9dDr5cPd4W|)CyWD9ab+r6k8u*KOqY_Pm#H~4c9!IMW*N~`i z5HtzppsP&IVaR3lAE@K<FxI4jR= z!b-WRef-W?$|NuqZm5) zCIw#HlrQzXZVX)`dj1N{R`cC^tt+sM`>1rhk0NOA!(Snx!lspOXogcjkam2xJ zif=HL*H$iz==QlE_V81O+E&mY82V~;>P=$1`gxU<9A2Apg57~0hnAMFZHIrK5a!!_ zxm5&ph|0QA5h)zul)Elphgmuw78>uiLfvpaX}#x04`qtwplQ6OJ=qS=l?OCvVRK71 z!hPBFX!?&Yv23QJMi&>uN&JJwuD`2M=k^>xT{D=dQwVo_>xl-${DbrB6!$7VXsh~ zA`mPKEv@u%m*g7g)*w8UfG1$*JRBcSW;aN7!y8}(SX9DI4u7DN_U7tC>aOr4_PLhi zxCwzQU;Q%o^=fBLJPNsNr=O597kdouek)th$48v@1qTq*w%D!I#iZqni+67rcB7IY zGy_)Dn5uUVu6s<-&Al>e0RCXdsl9<8b)j+%v}YKB1~R3!z0Z{HznBZ*vB8|F+)E2X z4Qp$;zS%_T`{%zxe$xKJnm)9Zg=ayV74j}Qc7feZSQRVU?A0YMY zscE=cB7rmsSD{WK#!Y;G5O_`)p8uVgjLSU#2YkM8Ne8UT5a&2d8~>YuvtyFa>WK{B%p}ly`7ygLXlEr>>5QwkQ z%zxl#lrZfc?F2l=|8A*%vMaIs;a`W5%0SMm;FVBotQmW#{lIRyf6j!f;q~w;sac=K z)IWoAq!VDy{b5$9&4HV{L8ztZ7q0k-^9&P3hmT_|ISMC0G%YVya{{hH^_+c($o$}- z#q2>nUz@a@d-@VGq_p3E+8kfX@-YFa006r>;|qVQ3f91A{$E$;Cfr#u@);m=;dXC%9W zr29RQY1S=6Z=Sw1_cm;dUA(P+Tf%|z|B>c=MygG*S%T;QwkpK5oki5HU^Uwm!a}68 zSo(H_+Y_(958E^e^DXO?vzyDI&H&?Hhb~plX-=NYTst%Rubt|Kc5{ESiTJBeW%3W) zoT|LvVI;{~j_k_7x6B})oa!a!aIkeCy%Vl};it4c6|r|#vv_uCK>A{KZ5*|aREVDL zK&Jtm0-^p;9EoN9f4aAA^*5Al*ueFQGfE+zPei$2)}2>RwTb|fMrWP^yhCQu6=+-- z|4mObZ}#(YVK7K!7*0eECt;kV+JkPh=2mfNY^t7y$2i$NH)ejhGtYAnV~l572^d%6 z3<=S49=+|Q+jvqDi;5q0!xFFkRj+X-d@$7@uE}AXQYFABBvxQBsLbUM0px!ALnSWD zDq68T$lJY_Uj;r~(Ik-UM#HzQxtYK&13gf&D1^u~kTt&CWP5eO%H7O_s0j3(Re zJ9wy@2sPmARLyE&H0ncRPAz1$4H{|Hsw$n>B7@ka>Xd`U7woi6CtWTWJ5REzpVcJp zjYDH$$ULy$1(=Dvq;puI!NwJpwFd<`BNY;m+92(Fzl7CwFXV{!5$Hsm%->bT9451FHPj2!perd713-Zo&DhoV zo@yYF(kFc+?bTnGz2QKg?akp!StQYF*I-J#F`ltc{`?vBNi{ab1NB$>=HKl%8%Vd+ zlRj%hD);F2Px+=)^J{lA)CmEn3IMtQ+PKc?U}(b{m*R0>;1!Dl>qFXCFK^7o66l*I zLifPC;B~8Y7gB2$co39m`u@fsvysssJ|ERjZTSf+QV)bj7IxpC!gJibNHyPSO#Su; z6;qwLr>l>Jbs7~&Sc>@7Jl8+#`F;VaFQWtrPLAGuLMZF$e&~Bhc2!GE2 From 0aa07c0144cd56e0c6f3d50ed75e9a74049ecf76 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 19:08:12 +0200 Subject: [PATCH 006/181] Try deploy key with yet more permissions --- deploy_key.enc | Bin 3360 -> 3360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deploy_key.enc b/deploy_key.enc index 459fa4223409a8bac3d3557708467d106ec5860e..7e298a8dd5740856b098f5bc8a5cce77de02aab8 100644 GIT binary patch literal 3360 zcmV+*4d3$m@E7;{ul`0gL%fe7Va{|PUo&!dbKKDj40i<^O7^m6ehi=7EEi0;8pXryuzgphD*(%h>*>Y4m= z*vYG!1?QxR-9K~zVe8D=rjkGQiuKM$<}K*{`?7^_i-Qs{X2HQor1?#-OGNze;dvHu zxltyOj#Ez|Ufepr93rD@f#cHxbcvbo(0_etpFqaGPbWpcT-!|$6jg%XFI1Un9kH`5 z(1SPrcj)m#4?;`PwEVx<RVV53n3gaXC0iQb%PZ`<1@~G$0b6p20KhsFd(j? zjW09P!SSe$_?0xO8XcA!lxX*vhiFl5r-{XZWpLb^;e@f zI5nS74e#ZI`pzE8H~ea+onsq({H_5u|&M2$iq=pj847S2s@}ZJ0UHq7;F4`q$M<0OL5GDAJdtu zHm!MWs*Khl2FHYe!U=eUks5p2V)OzZoy|SR`L-ID980f50!?{395Md%#Q0)it?dw; zsTqY!{HM!>xg;oiQ3ON!Kt?MInYlSgr&gS*XF;#?1-R!a4LKE%X1YjjX3>E9Vvpxo z!5{odVbrN3l_@>1R$XD-g=|#kGsr?!v!BAZ8+|vciE{^tCL0x3sKP0ld;#x;U)@6L zhyTOUdRp8oeK%OKXX{t{*~REhqvX_Ba*v28)tbd60?%b6Cot<7Xz?*ve7g$#>Z0Cf zwn9w#t0-lV8f3W_&FlZ8)`XAptnikd;mh2B5|6z)FmNZ4j5bgu564m{&`&uk+OE7P ze6lssLQOVln)qC&JJ!gB_o|4av*+;r)vQHjFbWU~b_vUnL6(Z5Sz|aaEp!EqK~NS| zmgHn#q1XTR5HJI9$PfnG{M|x{59^osyP#Lu4!O75+dILXT!MJn-WR=c(PChG52;aH zQW?4CK!2;;|06GU|H(pU^Iaifa?L^uVXm$hq-e|u&G&yqu^%6o*vdx=cY{$eYxsIx z>jV>0R@oQy5gC4br_|!j{WJVbgPpt*B$h$bBxJql0&I|*a%1wA+wGxHMJb5%1f+E{ zlNq15jW0-aj4M!R`n^#lh{jK?d`1t8Z@VTB!eZ?)rWKZcr^SDIGX1*g0<{r#VP$mg zh#Th)8f8x~6ZdprlFy3vSb|mYfx)%Z$QAcRP4kt}(^Pi0GK+@-s#_wdw}b^OfV}A# z%}L;&)rpnS0;Slb(BsHdYcSFBx2So$J6rYb0r!7f1detw>e2HAZo8#nqzsH{)al;F z#=0Ny!{2u?Sb+>yFLGI2qIIVG9H}9qqhl7%$RQT|xN-MV37Ug{*$i6vAth04yjbNO z42M74^slMvxEz43Jw9+cV2lI?qf@+xy|Q{~-|ZCQFSwXwB?S%53GZmFQJ|czJd?de z`8Z}dd~JyLVpd*gqhId(lj8xO+ojZnS-{P2p1lL$mK2f@4cf#qLP$Gpx zx%X>PE`u{Y+#+B@0CjAz71uw_aWWX-X_&a}(FRm*p`leYBi&)FKFlXrCyTI=+%9*b{S_PR)`^C zpj8GBNYuHtb{(5@cmf1hw)K$;@)hhcqDAeL|Cf~6e$NnQy2urv7S~gWniVQwy*Zmh zJg3!QRcLXX);N|C?50Z<-$KUg@@tYWS-D~_s<7X}oo*9Xq5ZxJ%P@izO;aU0AtGyp zt5<4A`Oz*#kG{mU4<)gUPBBf92ES^^A5Kx-p0syzOCe{s2$IaX{HeT8c%r$rI>74Y zhL6*U)u9CfWw?2^KD9J?qw%oRnptsi^D2uAWg3Ced&GR8WG@ z3>JMI-L5`^#~1+fMLg(k>vY1EFIwJk8uV;9e5YnvwV4UAJ0NGi3}Yj;qzMyRoF@ zW0k&s8S26i_hzFrse5klgEWM=@(}18`c)>9cUr`eBxVCVdUz8?te2(-5{h%E{3`F~ zM?A5Olv9!5D3Y(2HR;9q(f*q`bzFQ?lxsNZ80*#yyJNLoZ4V=u|-)@3gJTS^Z(l7mm>CX?(bJUlMKL^aqi5H z;dw1T*mgL>OtmBGg41`sua-|)WXWat?8A->vaq16EKknh_1W?Z81W87m|x|G_l%Dm zZARSLl55SQs`h90}cFu)Uieg=jqks16TST30Y|os7Z%B z&`p0my*;>Fnrr9l>=Bu;%Q)#Rqd)}&KxBv{P%`@aW=1JNk=0iF);0A_ z*XJA)M~!1#Cd-S*0>7S_@Z1?>=LcO?ipnQAiy8sSg$t8JU01o|99ER)fb#NwUmKip zWSV)BfKl&%aHS&zOyu@yzJ$M$tQzcGClZA-vl74UF}yEGgCP3-^*BY}J&pM4$gf&J z3ZSYoGlDJ0HZ_QyQvWohEp~Ybku-M8_n$Fj|J^?L(T}lXV$qMZhV`$v3?B_u-IV^u zt|B{uJ?e4rBWstfc*}7z?sQcoT6*Ytc3cp?=H9=I4aTfxBE$V#G&DoghuX=mcn0Kb zZo%`Cqp$SrNl{<#sa{8guDlm26F;3W4)R{_lG%gVPLSoWnQOJGUp#A+Vv8>+K4zSe z6`yRk*86e`&dpVEHUrI6rW=V)s=edQVG)t0Gt-lDJE4PXhSmrZ^gw=Q<9iYYOD;US`OG!ScC~R`+OA9ct(r+G0BRU4-Z6561X%b zd~w`9w=wcf2g7VEf2HrHpwYr^P#Qm4J;r002hAF7W+l3F7yDdmdmrpvSv3B-QFVlF zhqD9h^h4i3h~gz^O|h`8LY}dH2;`hJZv}^pqCYJD)W4YyJ#AIu4X{6+fZv$fAVqL_ z1N7RqnH~$sg=Ti5jtKaKcHesIP?o&t5Z_)g}QF1rqL+LoiVD2|-~ literal 3360 zcmV+*4d3#$4d}#%IVVLeUQ!`I9(NCRY135DZVMn3YA(9GWD|xTPk=b84JxzuZ1Po; zQExO%uZ-;_#Ov~m3m=JBXR{wSLoWuv?M?#~;ajNF7Y8I;SK4!+&Ii+Px?xGPCZ+Zi zSy$2iymb_+azOGiTxIbzWj~?q=QDz!W$Ne9Bq@E{H*X2W6v>+Z=W)#D?b@(8&&~qU zu}2Mj0?Il+oBV_YowOS5GBr8vE7gfDDp|-1)&30MCR&cZ5H~+*VkuFKGV4&!-ii2X zsK~7yExt+S0pGUh%yyNdF2wJ#%+u2#V%iREP|+kW|H!fs!SS7|40J$C+j}W%{j|Da z%&n00R?%lx*zamqldL6Fg~1q-m^yZm>M%cy{d{fMXiwgWjBQW|@X?d2h3`?$TV`9!KbBsEfXvK7BHmG8Vo(ffg@|Zp`0z@Zkw6hmcEIg2i4jzqcOivMKz{5=QSj@xqh;`<1%<+_L|p%}NIr)CBcwR1Qm_=hU5G0XERK;!?&OUf z`&q^74P_^Blq9cST2h_o>Dc-tOpu|T{~Yur#S87SxE&e+w;F_s#0(iqOrqD-{Y~ls z^f%`@ya(!;%A2?3P@I2t&yvk7SzBI)Le+((UhIoWL%Ij)Ej%NAw8XhNEr{n{gdf4( ziI>@3Sfgu5v-FcZ9{*Wlz5w!O%yr zSQ3<08H(eE?1BU(u*Z1{k3B3*00z@>XgS+jq{rZruHr0H51P`ggLI16sCk*=;%Z!t zQPg+X#)~Y;c2RCxuZYZ16+iYqmvFhzlFNxybx}~?KV1`!AP3AwBo-}RCcMy)*{z0V zP8SqCT!mF;VZNTp6AnjP{{A_Hm7St|tfhUGS-~P<&PeEbB&yDIiL#6mPy%z-D|;X0 zFKWThYG}^PvOA74>nmIo>~D8Zjfp#2woM!c@B9DE<4=~E15p|JUQiLopzq$vw|fJ^ zia;4#ghifkYYQGV|D^T=UcP6L!1{}1Uh?n{vi zr{2&M(&Lu^M&u|SBhp&`kV3#$8Lu#PEMg6^uVQC;$QfuLWNOqjV>^2xb_%@l3Q)0g zYm$R9((?n1eKV-W=m=3u;_LqK?*E0Kj$eg;^gg~(R!0#1U~lZM5;;tbk} zp$1!Ho%Ae=p4Eo(W(_Jc`?%Kdb8q!^1wJoj!ydU|>JRBbn}%P3J{OVn4R22dclYP;|tRAx0)woklq^+r%}0 z#uUA;i7s`(C3ZbFJR&Rp^*nkNW~cq_It|3~O`I2avtb06k@@NfPqgrK_~@1+9y@|VL0A`TBC{010 zkra!qC}Yo%2R>f%>7qE)?d=vc(uUo7D35(qHS2jUTM0&? zbFdUS0c}$UsUxgWCj?`)DG&nT@$g(!`!GP=CYPZEB&?+TcYK%K`n3RaH=NnmAw3fZ&elSUI!m!sIFv(N^ut7!a(Xbq zJ#L%P$395$yFdS60t?cHX|gxvR@mcd%vBQRVNuM%`ldJ)LkitBLY7i1O{w9v67UX= znI_QGUy2m{E+|@_6K?>h8Iaj31~WiV$w%k>HQ4p}v$mEoWuTElJ~BQRJaE@96#2<3 zSq+dI2%xgbl0t6*r#TT;{e z>0%8tqJQZ}h)8on!1S$=xJigP!df_WBK%#>#`;8x`S3w_(+zOr!Vkl&mc$^c&@-$= zVAXP0-Rk5{k{ReeoQq;D5tRxJ(H6w1zax#(+a`T=0((r!OmNc0SFa(|o0=@%y@YvK zd@wTPf-0M4m464cFi!l)hGAJRq^bix zE;ciXqKzwMZ!{j1^oJP}YtFnPA}kZgK!P&yK;RkG8q!danb602gi^}phu%HRnq zoC)oDEDiYRSC+B%oyK%)LM029Q}50}|7jbkWJIN$2l{rQgueZB#L=vD}h)5z$6vC(D4{TnV8eJMp-MY8y^|s_=ljz~B z6vsxm8hPtYsR~u~79dvskR!Ca~y_~)!7q({O9>SJ5qgv-5 zE)a5$dk}?DW_joCB7gw?Y*9{|y=69=;<6&jt0-wS)^@zYdJ?wx0nC_=13w5z3G^M% zfQIyZS-$(U+&Yk%4?1r-Vd&DWemgd57RTT%-O}ANSFg_Zm8W#Sxm2=D+bumST%!K% z{7!%HF!2=~qj;sccigfK^-6MyaE60ex+SDaTSVnEkDpy@SS-GVK6sWsvyJFYPHS7u zf+!){J{lwG_4HU%s>*AU6CG2(u}JYFigapjfZx^XG91_x=GD`dTd8K0gpI#DgU!LndPai%N zOT9Jt%8_+<<ksGu(|?H5bp(=_Z3LV_LmIrA98@c3jGa z0Gsu#%T2mIni(<5LP=VuDyVl9w#x{SEzTW%QK3cP!FXZ37l^$pMRv=QXmA)xqo+~b z@DW=v?8UyuIp<)Lwp>z=1076kz&2EmD- zf9{_$;a2;#ke0)uhRTF&8FWC!tP;q|u8WYW;P1zi8EN;YuR7R`yq`+vvH&3?jV0j^ zUH%RC^e!8)ZYU*l5CeWhdg44V7i3GBX5V_6<65`^t_kH8$xsNo9K8}sJ)4_2n@T<8 zKcdcc-54l4ziXj-r=G3gNJU@(O`VQ&u0Z-e_&yOs6f8f#J{G5z9YRHp#dP+J+18u% zaoOcOel=IRD>`*|N5E^S321azf}%Jh>eQ? From a93a04dfec381ce332eb63de839922803883cc54 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 19:32:12 +0200 Subject: [PATCH 007/181] Try deploy key with yet more permissions --- deploy_key.enc | Bin 3360 -> 3360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deploy_key.enc b/deploy_key.enc index 7e298a8dd5740856b098f5bc8a5cce77de02aab8..cf789956a32c1834557af4112c88fddff236c387 100644 GIT binary patch literal 3360 zcmV+*4d3$BOiBk0J_3>vcV1nx#~rgDOu*ign*ZPNO9*zHcyYbh<%u*B< z3FZ2DvjLzzOGK#AIO54EsFyKA(mGL=#GRO;j_KU5^^04X=~cQnAm?$JoL1z-?6<_r0XmonQJc&wSk6-MUjDE!+sz|$YK_!n9R41Nv5+yJ`VyDk1lC^#{ z;~fxc>3Sg?YXbijmmiuR9IXT%qLlz48G{b6<05BO^0sGTgJ9xJ9D}MaQe7LprXgw2 zans!Nq_+vGOUV5)-m3h3hFP32%|fF)k6;GeC~|Uv$zh0L%YNrou3_+QSxT3L{k^Cd zNal%ko0zKZ3It2DS%)t$2Oi+Bb%bB+(XzB$adK}Z27o3DImS`L?@b>qk@&9ZRwzGN z1H}X`aFJSRTNTETHwY8>M0bFRT9~}lo=qvzv6Yl7yKrf~opT`0ho$?1jcPynd zIvHE6*~s|_m^U&byg2r|1M_K_nQT%>aw?sll`D*TOWp>QCEyCSCv{4dr4B_$nA{_HD zz%v5M0%QTq(zBr+NK(X@{&bZvCq|wJLKzlj2U>|BgC`QtY&vK;J&yL+`dBA0jG|oo zrD)ESY+;fX+I_gUJ;uO3jHs^N>ft)4+x-aM`V7P+3A~&L5_HH`Nn8)y18=ovJST^O z7uvYz1I8U^|9o-J)h9q((Dxgley^T*x#O$UX$CQn{rLeZeij#)?T|XnE!HKTIA#mJ zUUiZV!$ipA9e%gm?BKXpJP@h>ez^BJQp1`iA_j($XGIqWoAsFt&eXSr^!pX*mb)MO zNYFWhJoo?HoWeM?j8-K1T2D;&Lk9Vj?%4aGa&>i;!A!b-A?;MncYSb$jASZvFynwM z4Ie%Y_m`Ii+pSN@k9EVnHN&5VR6pAEw-iEBosr}w^xGS7sQ`9}c-VYW>nd<>@m?=R zINMyS#ehmUc2eW$cKRCEP0Y*b|wD$#E?daln;JLH6LI7XK=f98^{)?XD z)P~FNIcxAE%db&*V|ECc)LCM^Jp-Hl6QB+ER|I;X61DTqhg|bKp2!HKVxw$n8J93; zeh?MURNP4b?OuT)n4FTMee4eN30<-y=eLYcS&XvCWOqLJM;D#yk@VT(8ZXQsV;s?P zgqXmB6oI?PT($HYSMzSwQsGy@N(&FfQ-FwpD)jSe`33o|7cC1(%|Izg!x#>^8$Nj# zk%fiQo&9m+5uqcJhR;6YFfcf&vBtBFa6Bebkgfmj{ zP8fZ79< zE12N-Lqt{P_O8Xsx*%f?do&E0wdfZ~g>HqeasWJBCfU{S|1No56H_gpoCEJGftw8H z*kNQ_R4Z7|zmMJ5XkEhCoEoa8e}m6l0QNQzE!Ie>fS0)BYI)RdO@&3>uSfJU;m@kW z2PEGma0}gm2=-jhG1?u54a#5-PV<-!kY~$?OPJF!;mUop&TC~$TE z$NwAQ80Mw{;!BXcdp=f^dAu=mT@Nt%?!y4i=?A-Y;R zvRc5AUQh4f4Jt-Au><+LL@F=i7f_B$TVSzfQ>mFO+ltf`q{pTj7MC5oZ?|8AJ-LWqc`9z{GF0}A60k^h$%C@8J#)~Ds1e^(Z9?K8fFjDf46GTPzJCh7dih9| zRJ+|Rns0sI({a5*i*)LLdZa$91HyZsCfs5Qd_w8M(XB_fZ^O%bdUYum^wRu;4|Eg~dxg}s;iwyGToDu%OnAA*sltXY4M z9tLX&FT0g6mXp$ZsmB}rXS`1WiCAO3PT3r8JJRbv*3l*dE3Nvw(+6ZRM6W5;sCub^ zM?MufcYUuEQyu|DC;?apLfw6)j3aXjtab#?<1r4|^~G!M$Pqf-xni^BDn12u(La#( zk9Fu5n1paVQUzyx4w>KP8{Y_*mlBB1fnyDLvdH{ynBQYTCsc4I$6A^8p6Z;hx!aqO z9o=tgK&o&fQ z)x5n)RIb!F4;Lsn+ApWk3i@!BaLaSke81elw2eg$&~q5Ej3pt;A{nP#x9%v{tI6{O%Te1M`?2n2>#&LoBYe}!yKP~gg^6trg@j+ ziG=GsD5MHHKE;1x%d?p;u)X7zk4-8|F{5un2tYm7bR>aB5-u*L;C#6Frl;@}mYXG9 zuBFmn=b{jGf>+`pG%i-EJMq^o5>q@rD8>Nse)Tj^FNF{ccguT>K<4TW&dx3PME7F` z>lj<48-&>F1=i5s%WBrEWIAGI$*jot&?Mycz>!l2vkQ@(KwCr|bUCM*mvpSpMaA(i zQ~x86lHd>c3{2vhF3-WU+*Z+_EI$f1S^nzap;QX1cAw%4g+$9x{fh7Qz3@TLdA{Dp`fJ?41KA6TH)m%4V%yeFQMg=y@#Lp3izDSM@_dYKqPu5@2g4`t2?@p%RgQ!*5@Hz>NgyEX~=NR^bJCN>*OCM(`09 zXX3NCw>!!eHG+{KhA1=Ea3*i8Xf3qhTx6w%SN}%EnWGd;&YT#zl@zPMgJi%3SIH>< zs!XC<0=Da)Po$b>@x}F7M=NCts zqAJAXOfeLUoQ`tdP{%-WWE5N^9@w?Sp{JumEtf|Q5+*u;R|L^I3tpxT@m(&-#!W>u z;p2(b_kLepgtbKaus$=g(b|I?-mWC9Tm*ErD(Y^+yZgBk#b3-#z1^M)_O8+#H7it7 qWuc!*-Z1YB4jNk_F?Y?hF9pe1B`Y7Coi;mfnIoo?q*aR$?FPMSGlG}^ literal 3360 zcmV+*4d3$m@E7;{ul`0gL%fe7Va{|PUo&!dbKKDj40i<^O7^m6ehi=7EEi0;8pXryuzgphD*(%h>*>Y4m= z*vYG!1?QxR-9K~zVe8D=rjkGQiuKM$<}K*{`?7^_i-Qs{X2HQor1?#-OGNze;dvHu zxltyOj#Ez|Ufepr93rD@f#cHxbcvbo(0_etpFqaGPbWpcT-!|$6jg%XFI1Un9kH`5 z(1SPrcj)m#4?;`PwEVx<RVV53n3gaXC0iQb%PZ`<1@~G$0b6p20KhsFd(j? zjW09P!SSe$_?0xO8XcA!lxX*vhiFl5r-{XZWpLb^;e@f zI5nS74e#ZI`pzE8H~ea+onsq({H_5u|&M2$iq=pj847S2s@}ZJ0UHq7;F4`q$M<0OL5GDAJdtu zHm!MWs*Khl2FHYe!U=eUks5p2V)OzZoy|SR`L-ID980f50!?{395Md%#Q0)it?dw; zsTqY!{HM!>xg;oiQ3ON!Kt?MInYlSgr&gS*XF;#?1-R!a4LKE%X1YjjX3>E9Vvpxo z!5{odVbrN3l_@>1R$XD-g=|#kGsr?!v!BAZ8+|vciE{^tCL0x3sKP0ld;#x;U)@6L zhyTOUdRp8oeK%OKXX{t{*~REhqvX_Ba*v28)tbd60?%b6Cot<7Xz?*ve7g$#>Z0Cf zwn9w#t0-lV8f3W_&FlZ8)`XAptnikd;mh2B5|6z)FmNZ4j5bgu564m{&`&uk+OE7P ze6lssLQOVln)qC&JJ!gB_o|4av*+;r)vQHjFbWU~b_vUnL6(Z5Sz|aaEp!EqK~NS| zmgHn#q1XTR5HJI9$PfnG{M|x{59^osyP#Lu4!O75+dILXT!MJn-WR=c(PChG52;aH zQW?4CK!2;;|06GU|H(pU^Iaifa?L^uVXm$hq-e|u&G&yqu^%6o*vdx=cY{$eYxsIx z>jV>0R@oQy5gC4br_|!j{WJVbgPpt*B$h$bBxJql0&I|*a%1wA+wGxHMJb5%1f+E{ zlNq15jW0-aj4M!R`n^#lh{jK?d`1t8Z@VTB!eZ?)rWKZcr^SDIGX1*g0<{r#VP$mg zh#Th)8f8x~6ZdprlFy3vSb|mYfx)%Z$QAcRP4kt}(^Pi0GK+@-s#_wdw}b^OfV}A# z%}L;&)rpnS0;Slb(BsHdYcSFBx2So$J6rYb0r!7f1detw>e2HAZo8#nqzsH{)al;F z#=0Ny!{2u?Sb+>yFLGI2qIIVG9H}9qqhl7%$RQT|xN-MV37Ug{*$i6vAth04yjbNO z42M74^slMvxEz43Jw9+cV2lI?qf@+xy|Q{~-|ZCQFSwXwB?S%53GZmFQJ|czJd?de z`8Z}dd~JyLVpd*gqhId(lj8xO+ojZnS-{P2p1lL$mK2f@4cf#qLP$Gpx zx%X>PE`u{Y+#+B@0CjAz71uw_aWWX-X_&a}(FRm*p`leYBi&)FKFlXrCyTI=+%9*b{S_PR)`^C zpj8GBNYuHtb{(5@cmf1hw)K$;@)hhcqDAeL|Cf~6e$NnQy2urv7S~gWniVQwy*Zmh zJg3!QRcLXX);N|C?50Z<-$KUg@@tYWS-D~_s<7X}oo*9Xq5ZxJ%P@izO;aU0AtGyp zt5<4A`Oz*#kG{mU4<)gUPBBf92ES^^A5Kx-p0syzOCe{s2$IaX{HeT8c%r$rI>74Y zhL6*U)u9CfWw?2^KD9J?qw%oRnptsi^D2uAWg3Ced&GR8WG@ z3>JMI-L5`^#~1+fMLg(k>vY1EFIwJk8uV;9e5YnvwV4UAJ0NGi3}Yj;qzMyRoF@ zW0k&s8S26i_hzFrse5klgEWM=@(}18`c)>9cUr`eBxVCVdUz8?te2(-5{h%E{3`F~ zM?A5Olv9!5D3Y(2HR;9q(f*q`bzFQ?lxsNZ80*#yyJNLoZ4V=u|-)@3gJTS^Z(l7mm>CX?(bJUlMKL^aqi5H z;dw1T*mgL>OtmBGg41`sua-|)WXWat?8A->vaq16EKknh_1W?Z81W87m|x|G_l%Dm zZARSLl55SQs`h90}cFu)Uieg=jqks16TST30Y|os7Z%B z&`p0my*;>Fnrr9l>=Bu;%Q)#Rqd)}&KxBv{P%`@aW=1JNk=0iF);0A_ z*XJA)M~!1#Cd-S*0>7S_@Z1?>=LcO?ipnQAiy8sSg$t8JU01o|99ER)fb#NwUmKip zWSV)BfKl&%aHS&zOyu@yzJ$M$tQzcGClZA-vl74UF}yEGgCP3-^*BY}J&pM4$gf&J z3ZSYoGlDJ0HZ_QyQvWohEp~Ybku-M8_n$Fj|J^?L(T}lXV$qMZhV`$v3?B_u-IV^u zt|B{uJ?e4rBWstfc*}7z?sQcoT6*Ytc3cp?=H9=I4aTfxBE$V#G&DoghuX=mcn0Kb zZo%`Cqp$SrNl{<#sa{8guDlm26F;3W4)R{_lG%gVPLSoWnQOJGUp#A+Vv8>+K4zSe z6`yRk*86e`&dpVEHUrI6rW=V)s=edQVG)t0Gt-lDJE4PXhSmrZ^gw=Q<9iYYOD;US`OG!ScC~R`+OA9ct(r+G0BRU4-Z6561X%b zd~w`9w=wcf2g7VEf2HrHpwYr^P#Qm4J;r002hAF7W+l3F7yDdmdmrpvSv3B-QFVlF zhqD9h^h4i3h~gz^O|h`8LY}dH2;`hJZv}^pqCYJD)W4YyJ#AIu4X{6+fZv$fAVqL_ z1N7RqnH~$sg=Ti5jtKaKcHesIP?o&t5Z_)g}QF1rqL+LoiVD2|-~ From bdc2f61028fa8e2627059d81ab081ae5700c287e Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 20:01:10 +0200 Subject: [PATCH 008/181] Try deploy key with yet more permissions --- deploy_key.enc | Bin 3360 -> 3360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deploy_key.enc b/deploy_key.enc index cf789956a32c1834557af4112c88fddff236c387..0f549de34c399d7f098084cca6c9d098e6a2a3a5 100644 GIT binary patch literal 3360 zcmV+*4d3!}icpykOdpFRidI0Xi~N(@r|2t6J>&RU3Y1CobHLm0;@QGQ8m12~^cR5d z>B-33jyK;$LnC(r8c}3?5A2`w(jjw^MOq0{${(^C&#u_2WW#1vlWOkNiJOR>Kp$pq zBZon&Z&~uE}yFshEdH`=MnDaZFwy8AVf^T0g>%B5fB}yeb6!JJ`7ZdDJvySAv%DpjdowUDGMn zF$EZRc;_-rYOEoZKuNO?IwT>N!jb;^WqWfGg}gg4mDeFutHg$;4&ry*mxv*eDJoo+ zvx$yS^p-&UqokO8TnEdsvc=ti7y2%UX#uUUNB}Qa)&w9@54*waWAH0w+DL1C$5-dh z(_-NQ@pvcbxM*s7t-+!nh7p%ZAe#n)nOU$z6T^gi?(7)*i6ivDG{I`TM|1C)ah}Cu zH{?a>0Nx}{aT5WeoJ*0?0ri&^?b9~pRLJ-%muwlRH>5HTZpMajH! zusQ1LzQv3U$B>rE=qt~b^P6Fnr%EuNf$w7AcSBiOnk({_bOcJtG5 zc*f6eAQ8C~;n*(TvG&Q;96XLv>3~!=8&bkqCq3^3W^cP}-_dWaR zkoVh}?-lnEgE%Cv7oAFvIbz=v70Br$wo@wDc;`BRss}Kl+<9&Q%=mzAZw0FltdRg> zHt9=7v3ze5BuE1t${+3@Gg3j?R^taeP_6GX_7VVL_PtcJC4UV1+bvQ_z!RJ521DWN znB~7TU1Yo>NvsDHf|25KaG&ym=#*=AgzK9=Wp_vS*K$|ncY+;KZo|`Eblb$oi9eY8 z9siZ=#@A`}t08%lWDjhfMidgR9-~otY8V3rkaAsaEMkW55`=A2Je#uRr`;s`eyGuv zms{Af>W^{<^+{|KZVv_j#!qy_?b^}5?Gnr+vp?=$GPDQ8i-yepl2uEGGILqpC5y!z zr?*T4oM;G3FHKBq6Lg_qoYckEa{5AYwrA~b&6T=#nD+UDs=%}y-HFu?UYY&UY|~U;MnMC%HUsiH|C2;t3DtvEfB#)e2<>oq}31 z7Xy%ehiYEU=>>8I{c3q_MHG?@6Nr@t!IYG(5)Ws}+P}Z&e7_9S8Kr$Jue5?8lni7A zBduNa-e-EEX`9`l#t9}OX{63BfvAc;-_JEvLUg{j`dKbwlm4_0#KVx6Yc26eI6Q0K z6aT|l%L6PfoQ|0kF zbp{?YZUza~IVXO$?53L7b{pPSehiQ4Ov?SN6GDgwtX+kHii9#uygR?%tPcU|0qJ|) zAMV*x4`@CXhi_tSqxnX@(S`EtlR)Q&e4(=Jp@mV9SCZss*8mKy1}%%UogLSx!b_S0 z>*V>o8k_;{eo1a%0QV6pAdVPpF&{;d8fQDaMIr91q`CZmnpU_yp_OBv;gvS$OJRY` z&xtCD*KcmTXCMq7u*{;{`Nj_|Q?j2=Rx^0#{oi3e+zQj@Z5(Vg^_^xyqb#n`ipdWO zW^-WPSXCVqK`MKYnq;!3Z>G*=%HJ*1&#=*0OhEs0NyS=P7SO*@t~{9=GbL|VvH zaZ_;rgm0PfzYyf$fOT#s8P@e5SAJsOU9(dRRdf}9XJJ?jnVd#~X7EUJo~>CRdvUTz z9HE)|17Y#rUM9)ksXwZgrT)UvX6S2fFgFm%Ai3ODtVaBpbdhL|CH?PCaT4kP*KK-^ zvkstATW+rfe1{3U9KN<0?U@6oza2v(643 z-HSEJ+**lHkodm23COkSR!&IizyhVdL;NJL0~_q6s079TcG{a9VAa-_S#rYKQDbXC z+p`Dt7I$+rNMH4^9mi%-Dat4PoQvaidx=w5<>nO0VbBNLjo8mA7G z_F!5GJFEd*%Ewf-Z8G`2M|aPRB*Jz1CxRVk!x*F;_=cnU z7(4pZv@PsHg@`UwkQoy8uas?{l#Yi_)F*QGa$hwdPtKo`PE(b!jgWFBSqa|07b3!Ky)?Cca|JI8;)Jd}0k` zwqUY!|8D?QvYplyj{$}hJfXsZ4W)2Y=WY`0gCDY5k6C!0)^DgyCH>EP>onjc4M9k^~*5GTKCorhNv@DL``hF0vF3kb2ZT zd~1Q8an64%;&A3#8cZjUia2h2TI`RVirkE**Ec2Y+C;~3D2#B$c=BE4?%1NqFHBsF25naQ^wKJ^1=KXVjnt7x3-&%XS5%F|oCXDVI{D|pJzY)fcYdFr zmq7gGRb^uh&@mYlmduj{VrSH#YB2VV(YW>Ja0AP|-!f)EiY%nss@@<?x zXS|a9Igp^0xJO;VTE;^5kC(f=G)T(WAgF6yV*NsZNhaBP|2!*6div=m7Qgtx!?(v9 z4by4ME=ZrG{(``i3h^M4plifZ+YWdC)~a%MKAB@|Gy@}b+qgtwRgNC&$d0wf$dwAf zyMtN&gy)r{VYJThui8rj$vz)!BP+6E!kbf^4KZ2gu%vId>S-3I%}oF()lz-SqVCMI zmxJXqjpm{%_w-Dq8t6siNgx?0-dEOui-G;v^-cd5;0Hnv_t}&ByNcy4EdAa&ESrhV zG>70ch^F&7to{2uva}c55ONa>b}^mA^cW<1?6sNWkNKW@YbS{glgT-cN*)nYkXa+=?5ch`(U!yQnD6OjqHQQ z5n!n?ta?IvmBW?XRC?HNf!K#jILVGyxM&AFYH1)-E&0!-gJ1f$CA-qXLGM>KRa!=RJb8Mxx6Ip$PqmXs~9i7J6U9;Q@Rqe7FZGA3Eu(p zGv-&J;dXCaWBxk^cU#sxDK;@=W`kh<{sHn9xpvk5G@KjdQL7fjWz8_TRX*57P+|W&B~)s@ z{m8GBr-a3q3K%CK;Ko^wx8kO7pJA%OKd_6?BFC)Y0DyJ8UObV5?kJS~b3}wgnqSKt qkm3aCFGDgV1vD2h7ESLWorE87k+ieSe1;y)iWH_P1OQ$?g0jlX`hTSW literal 3360 zcmV+*4d3$BOiBk0J_3>vcV1nx#~rgDOu*ign*ZPNO9*zHcyYbh<%u*B< z3FZ2DvjLzzOGK#AIO54EsFyKA(mGL=#GRO;j_KU5^^04X=~cQnAm?$JoL1z-?6<_r0XmonQJc&wSk6-MUjDE!+sz|$YK_!n9R41Nv5+yJ`VyDk1lC^#{ z;~fxc>3Sg?YXbijmmiuR9IXT%qLlz48G{b6<05BO^0sGTgJ9xJ9D}MaQe7LprXgw2 zans!Nq_+vGOUV5)-m3h3hFP32%|fF)k6;GeC~|Uv$zh0L%YNrou3_+QSxT3L{k^Cd zNal%ko0zKZ3It2DS%)t$2Oi+Bb%bB+(XzB$adK}Z27o3DImS`L?@b>qk@&9ZRwzGN z1H}X`aFJSRTNTETHwY8>M0bFRT9~}lo=qvzv6Yl7yKrf~opT`0ho$?1jcPynd zIvHE6*~s|_m^U&byg2r|1M_K_nQT%>aw?sll`D*TOWp>QCEyCSCv{4dr4B_$nA{_HD zz%v5M0%QTq(zBr+NK(X@{&bZvCq|wJLKzlj2U>|BgC`QtY&vK;J&yL+`dBA0jG|oo zrD)ESY+;fX+I_gUJ;uO3jHs^N>ft)4+x-aM`V7P+3A~&L5_HH`Nn8)y18=ovJST^O z7uvYz1I8U^|9o-J)h9q((Dxgley^T*x#O$UX$CQn{rLeZeij#)?T|XnE!HKTIA#mJ zUUiZV!$ipA9e%gm?BKXpJP@h>ez^BJQp1`iA_j($XGIqWoAsFt&eXSr^!pX*mb)MO zNYFWhJoo?HoWeM?j8-K1T2D;&Lk9Vj?%4aGa&>i;!A!b-A?;MncYSb$jASZvFynwM z4Ie%Y_m`Ii+pSN@k9EVnHN&5VR6pAEw-iEBosr}w^xGS7sQ`9}c-VYW>nd<>@m?=R zINMyS#ehmUc2eW$cKRCEP0Y*b|wD$#E?daln;JLH6LI7XK=f98^{)?XD z)P~FNIcxAE%db&*V|ECc)LCM^Jp-Hl6QB+ER|I;X61DTqhg|bKp2!HKVxw$n8J93; zeh?MURNP4b?OuT)n4FTMee4eN30<-y=eLYcS&XvCWOqLJM;D#yk@VT(8ZXQsV;s?P zgqXmB6oI?PT($HYSMzSwQsGy@N(&FfQ-FwpD)jSe`33o|7cC1(%|Izg!x#>^8$Nj# zk%fiQo&9m+5uqcJhR;6YFfcf&vBtBFa6Bebkgfmj{ zP8fZ79< zE12N-Lqt{P_O8Xsx*%f?do&E0wdfZ~g>HqeasWJBCfU{S|1No56H_gpoCEJGftw8H z*kNQ_R4Z7|zmMJ5XkEhCoEoa8e}m6l0QNQzE!Ie>fS0)BYI)RdO@&3>uSfJU;m@kW z2PEGma0}gm2=-jhG1?u54a#5-PV<-!kY~$?OPJF!;mUop&TC~$TE z$NwAQ80Mw{;!BXcdp=f^dAu=mT@Nt%?!y4i=?A-Y;R zvRc5AUQh4f4Jt-Au><+LL@F=i7f_B$TVSzfQ>mFO+ltf`q{pTj7MC5oZ?|8AJ-LWqc`9z{GF0}A60k^h$%C@8J#)~Ds1e^(Z9?K8fFjDf46GTPzJCh7dih9| zRJ+|Rns0sI({a5*i*)LLdZa$91HyZsCfs5Qd_w8M(XB_fZ^O%bdUYum^wRu;4|Eg~dxg}s;iwyGToDu%OnAA*sltXY4M z9tLX&FT0g6mXp$ZsmB}rXS`1WiCAO3PT3r8JJRbv*3l*dE3Nvw(+6ZRM6W5;sCub^ zM?MufcYUuEQyu|DC;?apLfw6)j3aXjtab#?<1r4|^~G!M$Pqf-xni^BDn12u(La#( zk9Fu5n1paVQUzyx4w>KP8{Y_*mlBB1fnyDLvdH{ynBQYTCsc4I$6A^8p6Z;hx!aqO z9o=tgK&o&fQ z)x5n)RIb!F4;Lsn+ApWk3i@!BaLaSke81elw2eg$&~q5Ej3pt;A{nP#x9%v{tI6{O%Te1M`?2n2>#&LoBYe}!yKP~gg^6trg@j+ ziG=GsD5MHHKE;1x%d?p;u)X7zk4-8|F{5un2tYm7bR>aB5-u*L;C#6Frl;@}mYXG9 zuBFmn=b{jGf>+`pG%i-EJMq^o5>q@rD8>Nse)Tj^FNF{ccguT>K<4TW&dx3PME7F` z>lj<48-&>F1=i5s%WBrEWIAGI$*jot&?Mycz>!l2vkQ@(KwCr|bUCM*mvpSpMaA(i zQ~x86lHd>c3{2vhF3-WU+*Z+_EI$f1S^nzap;QX1cAw%4g+$9x{fh7Qz3@TLdA{Dp`fJ?41KA6TH)m%4V%yeFQMg=y@#Lp3izDSM@_dYKqPu5@2g4`t2?@p%RgQ!*5@Hz>NgyEX~=NR^bJCN>*OCM(`09 zXX3NCw>!!eHG+{KhA1=Ea3*i8Xf3qhTx6w%SN}%EnWGd;&YT#zl@zPMgJi%3SIH>< zs!XC<0=Da)Po$b>@x}F7M=NCts zqAJAXOfeLUoQ`tdP{%-WWE5N^9@w?Sp{JumEtf|Q5+*u;R|L^I3tpxT@m(&-#!W>u z;p2(b_kLepgtbKaus$=g(b|I?-mWC9Tm*ErD(Y^+yZgBk#b3-#z1^M)_O8+#H7it7 qWuc!*-Z1YB4jNk_F?Y?hF9pe1B`Y7Coi;mfnIoo?q*aR$?FPMSGlG}^ From 79c9aa36860a6c24c1b8dbac43cbc56c58853578 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 1 Oct 2019 21:28:32 +0200 Subject: [PATCH 009/181] Reset deploy key --- deploy_key.enc | Bin 3360 -> 3360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deploy_key.enc b/deploy_key.enc index 0f549de34c399d7f098084cca6c9d098e6a2a3a5..b1495761095e6f39839056bdd4a07303f13946c6 100644 GIT binary patch literal 3360 zcmV+*4d3#(PTlAH?3XC{aDin@h(!+2WSjm&tUo)G=xtJXYuq|qzGjC?;0`(1G=0TM zYlPMYzS2H5riW-D*S_l8uD|SPHEV#kv_OM%BaQzMl_)T?*t|Bd8S^RpDjIC?pNa5) zPf~KdR~@U09s*Dz!b)huy|P1JCduA8@XDtl+(+WN@I*H|`xRm{I*fqjbcvleRfQ}z z)7#sR8?(9?-+|zda}PJ*?@2Uu03p}E{9&`H@&L1T_OWrMQ-EdV$}j_1BU5WYTu89c zN`?xV7hst;9)P)`Q&z4%U|}bxvQu`~b62JUzx>#)SnT|Ctvm($R`7m%xcGcIa)0?P~z&VP*{c?!yz+J#{+fG&|T zE^?`{wnMlelh$z^9)jsj27BiyvPsHOgoIG;Qn2k$Iv}6Y_wc0aHiHOPW}HQ84|o=+ z<6$y0QqKK^`*b^nDNAcu#;FywRD;Ps5_5m zQro3HA3>OVy*#l8kEhzkpZSH<)yNw$Xey&2wBbHNT#u|9jp z$E8HkbJQtq2c5IKr00dR-P1R*VgDA5%=p5^(YK#9LEfRBMB4XrVDUh=BBL zcewP8d$VYOw|eqO77j%;9AYnq4?C&r;oFsIx!cC$4_*S(kzu}T#GrW?)q|n*k%>&- zOLlb_U^zBYH-w2VLx$6|GlszX0a_yvmq%M~fky(DxQz-5o^$FLZEX3P74($$ZUO6$ zf7`8gmMjIR;W7|i1d)(0v+?A0Zml$jpZt-70)J+7Ry}JIOUEnuS;vHbM?rQg2_8Xy zN%b#zd8<|FrD=(O^ccGce#d7AerfL-8KK016t>!NPsIT*^mIet2^YtbDYo2YB!L{6 z#u(4+WQG|e=^zg-TC&zw3aIg}2h2XnUcc?}6(S%H?5;Pqjr#I>)Ct6fnUd6Zcxwa80FS!u{6plbMp_TH;#BDHd}e)sl@MdS?n& z93BX3T}3aOpSSh<+c`@N4*V~4`P% zIrH1`7IJEkle#2%r1EpZ{P(`tY1WMfOx}Fp z!_>VYfBsFU*%&1@B;{kGntyvA7>m5%~SF(+AhFA=9jnOgN{Dw4 zn49l+E;j`Zl6L6?;QZ1g3tv$h$Dl&XpWfeUz|?yu5rpL$bgukqUu>jAC&>z#g$pCg zbpfEvKyZ`}aU14tC$<#rD^?@>bP7^;u_y)fh*&TSH$jUC&oGe?1&c94C%WxiexGLu6@O{2|e>MdcefiXK}p1r?CmEjRACWf@#g!{WwboQ-gN%F?7 zW?>$uJ1)~BoeJtnP9dMX!O-=+cAmpoeA$lTm(QKVhcKR)%;u#Ro_Godc7JpV7}+6P zx+j}N3JuXHH}oaGVeZ-m%LfU*Db0^ zumcG`UC<}Bw+|~xG-0ytdT{Z25=1sXPhe*u5^S%n6;Bu#lEY6~2{tOji{6ZB>e2m%EH%FwP|t?$F}}qR^f+-q ze#W>;LlGj8YNj^RdH)(T@-DI{3Dz5r&oRIf^gGwv#AMym-2gP|Djv~h2SQ&Krqcwv z+FqT3%T`Z=Jtodw$-7726n>);MNm*uP!=gvD>~zQg;x)Wo@N1<`n-XO-Cq+aM@$Hm z^Ahl>I9YAG>ovK!%=~Q#1|xmxb^Acs!Vcc7sN5qJFv|-@q)8~B(hrX3f!*YbU}$G` zhN3;hh_Z-QL@Psx)s`R@bJsFt$v7Y?9VN^@=#-j1J@Seo=1!H6C5%|H;vFi3k;`vniNmY?7iNESGq>|5{Nwa#a;r^x6Lx&}I(TitwjkkQkfF_~b=kxE zcKdg^1*UGNRZi>W&a(l?8PrhWT*zU#3i)!>2Oo2*77aiH3j_8Pb=I`tfbUi}E$AEqg0|!?~ z)v91%jlW45{|ljvt?*q;snkhDO=$VZFqx(M&~g2RRk02Y&r%k-vHIQWeOdNYtYh>A zsQc23ovO135!CtLda3-7x}e#6ou67e#>ML!jW;rdc$&1Cy}Hwq?2pdI2bl&<{Tc)p*U@k=B`5NfJqZnUsOA*u zFqrmVaL@Ju@lpEOygv)oNpD`R`_Ng-+}K?VU1VWs<~Rc34`(5N|C;4(IBdk{rkIzz zcFyqrbRk)=a!N>vQkXwa1*b%1DK=ZT6eZNU&5!@b$cNBrqYF}Ad1ZN207Jxy= zZU|;o?pFuDqgs@BG88-8f}TunxT&U1dgIB#3juCKMKmXmlEXDzR=!*=Ee!z3W{O{G zcXqA|XjCy1F=?g?GsgAJ-ZDS@tFEgf zHXSEo%WNm7FGoZj+0_IW#@_uTR8buIO~lL!N9!~v1jWp@Kf!=(}_-7u1j zE^pHN`Qcp5K-f*4YkYGn>8Hi9dS_A6M22;t85|=~PW7$O0A6r5pX8Mhd<`roc45Xx zrSLqkK>YBIvqlF=!XD5ZMeqEyF(l&$JF-kT+*h@CZi%sijOVmow=R6J8`=cp2VK3w zS_9AMdFD(QKWAFA37%JNxe{?~TlZJH>b^{`G<)A}cq4~0IdOH0pl@Hd6R4cI0o_g= zH4uRF{2KEQlikE{@&{rym|6>4T0w#RKoj`4R1+2{1fsu5-VlBEsFuLIOfOC7OH)Eb zi6px)`fcn=Oq}`0HBlR+*6_LL5h27sizpQc4rG?>IMC&>5AT`^nkLZtkx?j> zaP#Xk4JyBislo43X`_(RQFed7RPgT_NsgcqGdPS}Qd^?BJvLRpB)rhiFaxD8tN7a_ z#?uNYps&`}a{EX)39da>qMom2a!sH2^;$hgWBXGC? literal 3360 zcmV+*4d3!}icpykOdpFRidI0Xi~N(@r|2t6J>&RU3Y1CobHLm0;@QGQ8m12~^cR5d z>B-33jyK;$LnC(r8c}3?5A2`w(jjw^MOq0{${(^C&#u_2WW#1vlWOkNiJOR>Kp$pq zBZon&Z&~uE}yFshEdH`=MnDaZFwy8AVf^T0g>%B5fB}yeb6!JJ`7ZdDJvySAv%DpjdowUDGMn zF$EZRc;_-rYOEoZKuNO?IwT>N!jb;^WqWfGg}gg4mDeFutHg$;4&ry*mxv*eDJoo+ zvx$yS^p-&UqokO8TnEdsvc=ti7y2%UX#uUUNB}Qa)&w9@54*waWAH0w+DL1C$5-dh z(_-NQ@pvcbxM*s7t-+!nh7p%ZAe#n)nOU$z6T^gi?(7)*i6ivDG{I`TM|1C)ah}Cu zH{?a>0Nx}{aT5WeoJ*0?0ri&^?b9~pRLJ-%muwlRH>5HTZpMajH! zusQ1LzQv3U$B>rE=qt~b^P6Fnr%EuNf$w7AcSBiOnk({_bOcJtG5 zc*f6eAQ8C~;n*(TvG&Q;96XLv>3~!=8&bkqCq3^3W^cP}-_dWaR zkoVh}?-lnEgE%Cv7oAFvIbz=v70Br$wo@wDc;`BRss}Kl+<9&Q%=mzAZw0FltdRg> zHt9=7v3ze5BuE1t${+3@Gg3j?R^taeP_6GX_7VVL_PtcJC4UV1+bvQ_z!RJ521DWN znB~7TU1Yo>NvsDHf|25KaG&ym=#*=AgzK9=Wp_vS*K$|ncY+;KZo|`Eblb$oi9eY8 z9siZ=#@A`}t08%lWDjhfMidgR9-~otY8V3rkaAsaEMkW55`=A2Je#uRr`;s`eyGuv zms{Af>W^{<^+{|KZVv_j#!qy_?b^}5?Gnr+vp?=$GPDQ8i-yepl2uEGGILqpC5y!z zr?*T4oM;G3FHKBq6Lg_qoYckEa{5AYwrA~b&6T=#nD+UDs=%}y-HFu?UYY&UY|~U;MnMC%HUsiH|C2;t3DtvEfB#)e2<>oq}31 z7Xy%ehiYEU=>>8I{c3q_MHG?@6Nr@t!IYG(5)Ws}+P}Z&e7_9S8Kr$Jue5?8lni7A zBduNa-e-EEX`9`l#t9}OX{63BfvAc;-_JEvLUg{j`dKbwlm4_0#KVx6Yc26eI6Q0K z6aT|l%L6PfoQ|0kF zbp{?YZUza~IVXO$?53L7b{pPSehiQ4Ov?SN6GDgwtX+kHii9#uygR?%tPcU|0qJ|) zAMV*x4`@CXhi_tSqxnX@(S`EtlR)Q&e4(=Jp@mV9SCZss*8mKy1}%%UogLSx!b_S0 z>*V>o8k_;{eo1a%0QV6pAdVPpF&{;d8fQDaMIr91q`CZmnpU_yp_OBv;gvS$OJRY` z&xtCD*KcmTXCMq7u*{;{`Nj_|Q?j2=Rx^0#{oi3e+zQj@Z5(Vg^_^xyqb#n`ipdWO zW^-WPSXCVqK`MKYnq;!3Z>G*=%HJ*1&#=*0OhEs0NyS=P7SO*@t~{9=GbL|VvH zaZ_;rgm0PfzYyf$fOT#s8P@e5SAJsOU9(dRRdf}9XJJ?jnVd#~X7EUJo~>CRdvUTz z9HE)|17Y#rUM9)ksXwZgrT)UvX6S2fFgFm%Ai3ODtVaBpbdhL|CH?PCaT4kP*KK-^ zvkstATW+rfe1{3U9KN<0?U@6oza2v(643 z-HSEJ+**lHkodm23COkSR!&IizyhVdL;NJL0~_q6s079TcG{a9VAa-_S#rYKQDbXC z+p`Dt7I$+rNMH4^9mi%-Dat4PoQvaidx=w5<>nO0VbBNLjo8mA7G z_F!5GJFEd*%Ewf-Z8G`2M|aPRB*Jz1CxRVk!x*F;_=cnU z7(4pZv@PsHg@`UwkQoy8uas?{l#Yi_)F*QGa$hwdPtKo`PE(b!jgWFBSqa|07b3!Ky)?Cca|JI8;)Jd}0k` zwqUY!|8D?QvYplyj{$}hJfXsZ4W)2Y=WY`0gCDY5k6C!0)^DgyCH>EP>onjc4M9k^~*5GTKCorhNv@DL``hF0vF3kb2ZT zd~1Q8an64%;&A3#8cZjUia2h2TI`RVirkE**Ec2Y+C;~3D2#B$c=BE4?%1NqFHBsF25naQ^wKJ^1=KXVjnt7x3-&%XS5%F|oCXDVI{D|pJzY)fcYdFr zmq7gGRb^uh&@mYlmduj{VrSH#YB2VV(YW>Ja0AP|-!f)EiY%nss@@<?x zXS|a9Igp^0xJO;VTE;^5kC(f=G)T(WAgF6yV*NsZNhaBP|2!*6div=m7Qgtx!?(v9 z4by4ME=ZrG{(``i3h^M4plifZ+YWdC)~a%MKAB@|Gy@}b+qgtwRgNC&$d0wf$dwAf zyMtN&gy)r{VYJThui8rj$vz)!BP+6E!kbf^4KZ2gu%vId>S-3I%}oF()lz-SqVCMI zmxJXqjpm{%_w-Dq8t6siNgx?0-dEOui-G;v^-cd5;0Hnv_t}&ByNcy4EdAa&ESrhV zG>70ch^F&7to{2uva}c55ONa>b}^mA^cW<1?6sNWkNKW@YbS{glgT-cN*)nYkXa+=?5ch`(U!yQnD6OjqHQQ z5n!n?ta?IvmBW?XRC?HNf!K#jILVGyxM&AFYH1)-E&0!-gJ1f$CA-qXLGM>KRa!=RJb8Mxx6Ip$PqmXs~9i7J6U9;Q@Rqe7FZGA3Eu(p zGv-&J;dXCaWBxk^cU#sxDK;@=W`kh<{sHn9xpvk5G@KjdQL7fjWz8_TRX*57P+|W&B~)s@ z{m8GBr-a3q3K%CK;Ko^wx8kO7pJA%OKd_6?BFC)Y0DyJ8UObV5?kJS~b3}wgnqSKt qkm3aCFGDgV1vD2h7ESLWorE87k+ieSe1;y)iWH_P1OQ$?g0jlX`hTSW From 4477d0489c0aacf3019ab9e7fc15f8e4afbabfc1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 11:29:13 +0200 Subject: [PATCH 010/181] Fill in overview todos --- proposals/multi-memory/Overview.md | 33 ++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 38327ed54..66b36eb53 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -44,28 +44,43 @@ The design of this extension is almost entirely canonical. Concretely: ### Instructions -#### Loads and Stores +Except where noted, the following changes apply to each `load` and `store` instruction as well as to `memory.size` and `memory.grow`. Corresponding changes will be necessary for the new instructions introduced by the bulk memory proposal.instructions. -TODO +Abstract syntax: -#### Other Memory Instructions +* Add a memory index immediate. -TODO +Validation: + +* Check the memory index immediate instead of index 0. + +Execution: + +* Access the memory according to their index immediate instead of memory 0. + +Binary format: + +* For loads and stores: Reinterpret the alignment value in the `memarg` as a bitfield; if bit 6 (the MSB of the first LEB byte) is set, then an `i32` memory index follows after the offset immediate (even with SIMD, alignment must not currently be larger than 4 in the logarithmic encoding, i.e., taking up the lower 3 bits, so this is more than safe). + +* For other memory instructions: Replace the hard-coded `0x00` bytes with an `i32` memory index. + +Text format: + +* Add an optional `memidx` immediate that defaults to 0 if absent (for backwards compatibility). In the case of loads and stores, this index must occur before the optional alignment and offset immediates. ### Modules -#### Data Segments +#### Data Segments and Memory Exports -TODO +The abstract syntax for data segments and memory exports already carry a memory index that is checked and used accordingly (even though it currently is known to be 0). Binary and text format also already have the corresponding index parameter (which is optional and defaults to 0 in the case of data segments). -#### Exports +So technically, no spec change is necessary, though implementations now need to deal with the possibility that the index is not 0. -TODO #### Modules -TODO +* Validation for modules no longer checks that there is at most 1 memory defined or imported. ## Implementation From c63325e50de810e7771403764e956834bef7c4d2 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 12:17:26 +0200 Subject: [PATCH 011/181] Spec changes --- document/core/binary/instructions.rst | 16 +++--- document/core/exec/instructions.rst | 70 ++++++++++++------------ document/core/syntax/instructions.rst | 33 +++++------ document/core/syntax/modules.rst | 5 -- document/core/text/instructions.rst | 79 ++++++++++++++++++--------- document/core/valid/instructions.rst | 60 ++++++++++---------- document/core/valid/modules.rst | 4 +- 7 files changed, 142 insertions(+), 125 deletions(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 1d4a8af8a..dc5faee1c 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -117,7 +117,7 @@ Variable Instructions Memory Instructions ~~~~~~~~~~~~~~~~~~~ -Each variant of :ref:`memory instruction ` is encoded with a different byte code. Loads and stores are followed by the encoding of their |memarg| immediate. +Each variant of :ref:`memory instruction ` is encoded with a different byte code. Loads and stores are followed by the encoding of their |memarg| immediate, which includes the :ref:`memory index ` if bit 6 of the flags field containing alignemnt is set; the memory index defaults to 0 otherwise. .. _binary-memarg: .. _binary-load: @@ -128,9 +128,12 @@ Each variant of :ref:`memory instruction ` is encoded with .. _binary-memory.grow: .. math:: - \begin{array}{llclll} + \begin{array}{llcllll} \production{memory argument} & \Bmemarg &::=& - a{:}\Bu32~~o{:}\Bu32 &\Rightarrow& \{ \ALIGN~a,~\OFFSET~o \} \\ + a{:}\Bu32~~o{:}\Bu32 &\Rightarrow& 0~\{ \ALIGN~a,~\OFFSET~o \} + & (\iff a < 2^6) \\ &&|& + a{:}\Bu32~~o{:}\Bu32~~x{:}\memidx &\Rightarrow& x~\{ \ALIGN~(a - 2^6),~\OFFSET~o \} + & (\otherwise) \\ \production{instruction} & \Binstr &::=& \dots \\ &&|& \hex{28}~~m{:}\Bmemarg &\Rightarrow& \I32.\LOAD~m \\ &&|& \hex{29}~~m{:}\Bmemarg &\Rightarrow& \I64.\LOAD~m \\ &&|& @@ -155,13 +158,10 @@ Each variant of :ref:`memory instruction ` is encoded with \hex{3C}~~m{:}\Bmemarg &\Rightarrow& \I64.\STORE\K{8}~m \\ &&|& \hex{3D}~~m{:}\Bmemarg &\Rightarrow& \I64.\STORE\K{16}~m \\ &&|& \hex{3E}~~m{:}\Bmemarg &\Rightarrow& \I64.\STORE\K{32}~m \\ &&|& - \hex{3F}~~\hex{00} &\Rightarrow& \MEMORYSIZE \\ &&|& - \hex{40}~~\hex{00} &\Rightarrow& \MEMORYGROW \\ + \hex{3F}~~x{:}\Bmemidx &\Rightarrow& \MEMORYSIZE~x \\ &&|& + \hex{40}~~x{:}\Bmemidx &\Rightarrow& \MEMORYGROW~x \\ \end{array} -.. note:: - In future versions of WebAssembly, the additional zero bytes occurring in the encoding of the |MEMORYSIZE| and |MEMORYGROW| instructions may be used to index additional memories. - .. index:: numeric instruction pair: binary format; instruction diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index 8c9d012f2..db332ce04 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -391,14 +391,14 @@ Memory Instructions .. _exec-load: .. _exec-loadn: -:math:`t\K{.}\LOAD~\memarg` and :math:`t\K{.}\LOAD{N}\K{\_}\sx~\memarg` -....................................................................... +:math:`t\K{.}\LOAD~x~\memarg` and :math:`t\K{.}\LOAD{N}\K{\_}\sx~x~\memarg` +........................................................................... 1. Let :math:`F` be the :ref:`current ` :ref:`frame `. -2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[0]` exists. +2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[x]` exists. -3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[0]`. +3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[x]`. 4. Assert: due to :ref:`validation `, :math:`S.\SMEMS[a]` exists. @@ -436,28 +436,28 @@ Memory Instructions ~\\[-1ex] \begin{array}{l} \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~i)~(t.\LOAD~\memarg) &\stepto& S; F; (t.\CONST~c) + S; F; (\I32.\CONST~i)~(t.\LOAD~x~\memarg) &\stepto& S; F; (t.\CONST~c) \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & \X{ea} = i + \memarg.\OFFSET \\ - \wedge & \X{ea} + |t|/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA| \\ - \wedge & \bytes_t(c) = S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA[\X{ea} \slice |t|/8]) + \wedge & \X{ea} + |t|/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ + \wedge & \bytes_t(c) = S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice |t|/8]) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~i)~(t.\LOAD{N}\K{\_}\sx~\memarg) &\stepto& + S; F; (\I32.\CONST~i)~(t.\LOAD{N}\K{\_}\sx~x~\memarg) &\stepto& S; F; (t.\CONST~\extend\F{\_}\sx_{N,|t|}(n)) \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & \X{ea} = i + \memarg.\OFFSET \\ - \wedge & \X{ea} + N/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA| \\ - \wedge & \bytes_{\iN}(n) = S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA[\X{ea} \slice N/8]) + \wedge & \X{ea} + N/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ + \wedge & \bytes_{\iN}(n) = S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice N/8]) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~k)~(t.\LOAD({N}\K{\_}\sx)^?~\memarg) &\stepto& S; F; \TRAP + S; F; (\I32.\CONST~k)~(t.\LOAD({N}\K{\_}\sx)^?~x~\memarg) &\stepto& S; F; \TRAP \end{array} \\ \qquad (\otherwise) \\ @@ -467,14 +467,14 @@ Memory Instructions .. _exec-store: .. _exec-storen: -:math:`t\K{.}\STORE~\memarg` and :math:`t\K{.}\STORE{N}~\memarg` -................................................................ +:math:`t\K{.}\STORE~x~\memarg` and :math:`t\K{.}\STORE{N}~x~\memarg` +.................................................................... 1. Let :math:`F` be the :ref:`current ` :ref:`frame `. -2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[0]` exists. +2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[x]` exists. -3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[0]`. +3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[x]`. 4. Assert: due to :ref:`validation `, :math:`S.\SMEMS[a]` exists. @@ -514,27 +514,27 @@ Memory Instructions ~\\[-1ex] \begin{array}{l} \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~i)~(t.\CONST~c)~(t.\STORE~\memarg) &\stepto& S'; F; \epsilon + S; F; (\I32.\CONST~i)~(t.\CONST~c)~(t.\STORE~x~\memarg) &\stepto& S'; F; \epsilon \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & \X{ea} = i + \memarg.\OFFSET \\ - \wedge & \X{ea} + |t|/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA| \\ - \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA[\X{ea} \slice |t|/8] = \bytes_t(c) + \wedge & \X{ea} + |t|/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ + \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice |t|/8] = \bytes_t(c) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~i)~(t.\CONST~c)~(t.\STORE{N}~\memarg) &\stepto& S'; F; \epsilon + S; F; (\I32.\CONST~i)~(t.\CONST~c)~(t.\STORE{N}~x~\memarg) &\stepto& S'; F; \epsilon \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & \X{ea} = i + \memarg.\OFFSET \\ - \wedge & \X{ea} + N/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA| \\ - \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA[\X{ea} \slice N/8] = \bytes_{\iN}(\wrap_{|t|,N}(c)) + \wedge & \X{ea} + N/8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ + \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice N/8] = \bytes_{\iN}(\wrap_{|t|,N}(c)) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~k)~(t.\CONST~c)~(t.\STORE{N}^?~\memarg) &\stepto& S; F; \TRAP + S; F; (\I32.\CONST~k)~(t.\CONST~c)~(t.\STORE{N}^?~x~\memarg) &\stepto& S; F; \TRAP \end{array} \\ \qquad (\otherwise) \\ @@ -543,14 +543,14 @@ Memory Instructions .. _exec-memory.size: -:math:`\MEMORYSIZE` -................... +:math:`\MEMORYSIZE~x` +..................... 1. Let :math:`F` be the :ref:`current ` :ref:`frame `. -2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[0]` exists. +2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[x]` exists. -3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[0]`. +3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[x]`. 4. Assert: due to :ref:`validation `, :math:`S.\SMEMS[a]` exists. @@ -563,23 +563,23 @@ Memory Instructions .. math:: \begin{array}{l} \begin{array}{lcl@{\qquad}l} - S; F; \MEMORYSIZE &\stepto& S; F; (\I32.\CONST~\X{sz}) + S; F; (\MEMORYSIZE~x) &\stepto& S; F; (\I32.\CONST~\X{sz}) \end{array} \\ \qquad - (\iff |S.\SMEMS[F.\AMODULE.\MIMEMS[0]].\MIDATA| = \X{sz}\cdot64\,\F{Ki}) \\ + (\iff |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| = \X{sz}\cdot64\,\F{Ki}) \\ \end{array} .. _exec-memory.grow: -:math:`\MEMORYGROW` -................... +:math:`\MEMORYGROW~x` +..................... 1. Let :math:`F` be the :ref:`current ` :ref:`frame `. -2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[0]` exists. +2. Assert: due to :ref:`validation `, :math:`F.\AMODULE.\MIMEMS[x]` exists. -3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[0]`. +3. Let :math:`a` be the :ref:`memory address ` :math:`F.\AMODULE.\MIMEMS[x]`. 4. Assert: due to :ref:`validation `, :math:`S.\SMEMS[a]` exists. @@ -603,17 +603,17 @@ Memory Instructions ~\\[-1ex] \begin{array}{l} \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~n)~\MEMORYGROW &\stepto& S'; F; (\I32.\CONST~\X{sz}) + S; F; (\I32.\CONST~n)~(\MEMORYGROW~x) &\stepto& S'; F; (\I32.\CONST~\X{sz}) \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & F.\AMODULE.\MIMEMS[0] = a \\ + (\iff & F.\AMODULE.\MIMEMS[x] = a \\ \wedge & \X{sz} = |S.\SMEMS[a].\MIDATA|/64\,\F{Ki} \\ \wedge & S' = S \with \SMEMS[a] = \growmem(S.\SMEMS[a], n)) \\ \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} - S; F; (\I32.\CONST~n)~\MEMORYGROW &\stepto& S; F; (\I32.\CONST~{-1}) + S; F; (\I32.\CONST~n)~(\MEMORYGROW~x) &\stepto& S; F; (\I32.\CONST~{-1}) \end{array} \end{array} diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index 4f6d613c4..31b2e3605 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -231,22 +231,22 @@ Instructions in this group are concerned with linear :ref:`memory `. \{ \OFFSET~\u32, \ALIGN~\u32 \} \\ \production{instruction} & \instr &::=& \dots \\&&|& - \K{i}\X{nn}\K{.}\LOAD~\memarg ~|~ - \K{f}\X{nn}\K{.}\LOAD~\memarg \\&&|& - \K{i}\X{nn}\K{.}\STORE~\memarg ~|~ - \K{f}\X{nn}\K{.}\STORE~\memarg \\&&|& - \K{i}\X{nn}\K{.}\LOAD\K{8\_}\sx~\memarg ~|~ - \K{i}\X{nn}\K{.}\LOAD\K{16\_}\sx~\memarg ~|~ - \K{i64.}\LOAD\K{32\_}\sx~\memarg \\&&|& - \K{i}\X{nn}\K{.}\STORE\K{8}~\memarg ~|~ - \K{i}\X{nn}\K{.}\STORE\K{16}~\memarg ~|~ - \K{i64.}\STORE\K{32}~\memarg \\&&|& - \MEMORYSIZE \\&&|& - \MEMORYGROW \\ + \K{i}\X{nn}\K{.}\LOAD~\memidx~\memarg ~|~ + \K{f}\X{nn}\K{.}\LOAD~\memidx~\memarg \\&&|& + \K{i}\X{nn}\K{.}\STORE~\memidx~\memarg ~|~ + \K{f}\X{nn}\K{.}\STORE~\memidx~\memarg \\&&|& + \K{i}\X{nn}\K{.}\LOAD\K{8\_}\sx~\memidx~\memarg ~|~ + \K{i}\X{nn}\K{.}\LOAD\K{16\_}\sx~\memidx~\memarg ~|~ + \K{i64.}\LOAD\K{32\_}\sx~\memidx~\memarg \\&&|& + \K{i}\X{nn}\K{.}\STORE\K{8}~\memidx~\memarg ~|~ + \K{i}\X{nn}\K{.}\STORE\K{16}~\memidx~\memarg ~|~ + \K{i64.}\STORE\K{32}~\memidx~\memarg \\&&|& + \MEMORYSIZE~\memidx \\&&|& + \MEMORYGROW~\memidx \\ \end{array} Memory is accessed with |LOAD| and |STORE| instructions for the different :ref:`value types `. -They all take a *memory immediate* |memarg| that contains an address *offset* and the expected *alignment* (expressed as the exponent of a power of 2). +They all take a :ref:`memory index ` and a *memory immediate* |memarg| that contains an address *offset* and the expected *alignment* (expressed as the exponent of a power of 2). Integer loads and stores can optionally specify a *storage size* that is smaller than the :ref:`bit width ` of the respective value type. In the case of loads, a sign extension mode |sx| is then required to select appropriate behavior. @@ -258,14 +258,9 @@ A :ref:`trap ` results if any of the accessed memory bytes lies outside th Future version of WebAssembly might provide memory instructions with 64 bit address ranges. The |MEMORYSIZE| instruction returns the current size of a memory. -The |MEMORYGROW| instruction grows memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. +The |MEMORYGROW| instruction grows a memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. Both instructions operate in units of :ref:`page size `. -.. note:: - In the current version of WebAssembly, - all memory instructions implicitly operate on :ref:`memory ` :ref:`index ` :math:`0`. - This restriction may be lifted in future versions. - .. index:: ! control instruction, ! structured control, ! label, ! block, ! branch, ! unwinding, result type, label index, function index, type index, vector, trap, function, table, function type pair: abstract syntax; instruction diff --git a/document/core/syntax/modules.rst b/document/core/syntax/modules.rst index 7935fcae6..b01e7d573 100644 --- a/document/core/syntax/modules.rst +++ b/document/core/syntax/modules.rst @@ -187,11 +187,6 @@ Memories are referenced through :ref:`memory indices `, starting with the smallest index not referencing a memory :ref:`import `. Most constructs implicitly reference memory index :math:`0`. -.. note:: - In the current version of WebAssembly, at most one memory may be defined or imported in a single module, - and *all* constructs implicitly reference this memory :math:`0`. - This restriction may be lifted in future versions. - .. index:: ! global, global index, global type, mutability, expression, constant, value, import pair: abstract syntax; global diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index 11182070b..2f6e825f8 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -191,31 +191,60 @@ Lexically, an |Toffset| or |Talign| phrase is considered a single :ref:`keyword \text{align{=}}a{:}\Tu32 &\Rightarrow& a \\ &&|& \epsilon &\Rightarrow& N \\ \production{instruction} & \Tplaininstr_I &::=& \dots \\ &&|& - \text{i32.load}~~m{:}\Tmemarg_4 &\Rightarrow& \I32.\LOAD~m \\ &&|& - \text{i64.load}~~m{:}\Tmemarg_8 &\Rightarrow& \I64.\LOAD~m \\ &&|& - \text{f32.load}~~m{:}\Tmemarg_4 &\Rightarrow& \F32.\LOAD~m \\ &&|& - \text{f64.load}~~m{:}\Tmemarg_8 &\Rightarrow& \F64.\LOAD~m \\ &&|& - \text{i32.load8\_s}~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\LOAD\K{8\_s}~m \\ &&|& - \text{i32.load8\_u}~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\LOAD\K{8\_u}~m \\ &&|& - \text{i32.load16\_s}~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\LOAD\K{16\_s}~m \\ &&|& - \text{i32.load16\_u}~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\LOAD\K{16\_u}~m \\ &&|& - \text{i64.load8\_s}~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\LOAD\K{8\_s}~m \\ &&|& - \text{i64.load8\_u}~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\LOAD\K{8\_u}~m \\ &&|& - \text{i64.load16\_s}~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\LOAD\K{16\_s}~m \\ &&|& - \text{i64.load16\_u}~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\LOAD\K{16\_u}~m \\ &&|& - \text{i64.load32\_s}~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\LOAD\K{32\_s}~m \\ &&|& - \text{i64.load32\_u}~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\LOAD\K{32\_u}~m \\ &&|& - \text{i32.store}~~m{:}\Tmemarg_4 &\Rightarrow& \I32.\STORE~m \\ &&|& - \text{i64.store}~~m{:}\Tmemarg_8 &\Rightarrow& \I64.\STORE~m \\ &&|& - \text{f32.store}~~m{:}\Tmemarg_4 &\Rightarrow& \F32.\STORE~m \\ &&|& - \text{f64.store}~~m{:}\Tmemarg_8 &\Rightarrow& \F64.\STORE~m \\ &&|& - \text{i32.store8}~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\STORE\K{8}~m \\ &&|& - \text{i32.store16}~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\STORE\K{16}~m \\ &&|& - \text{i64.store8}~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\STORE\K{8}~m \\ &&|& - \text{i64.store16}~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\STORE\K{16}~m \\ &&|& - \text{i64.store32}~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\STORE\K{32}~m \\ &&|& - \text{memory.size} &\Rightarrow& \MEMORYSIZE \\ &&|& - \text{memory.grow} &\Rightarrow& \MEMORYGROW \\ + \text{i32.load}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \I32.\LOAD~x~m \\ &&|& + \text{i64.load}~~x{:}\Tmemidx~~m{:}\Tmemarg_8 &\Rightarrow& \I64.\LOAD~x~m \\ &&|& + \text{f32.load}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \F32.\LOAD~x~m \\ &&|& + \text{f64.load}~~x{:}\Tmemidx~~m{:}\Tmemarg_8 &\Rightarrow& \F64.\LOAD~x~m \\ &&|& + \text{i32.load8\_s}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\LOAD\K{8\_s}~x~m \\ &&|& + \text{i32.load8\_u}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\LOAD\K{8\_u}~x~m \\ &&|& + \text{i32.load16\_s}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\LOAD\K{16\_s}~x~m \\ &&|& + \text{i32.load16\_u}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\LOAD\K{16\_u}~x~m \\ &&|& + \text{i64.load8\_s}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\LOAD\K{8\_s}~x~m \\ &&|& + \text{i64.load8\_u}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\LOAD\K{8\_u}~x~m \\ &&|& + \text{i64.load16\_s}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\LOAD\K{16\_s}~x~m \\ &&|& + \text{i64.load16\_u}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\LOAD\K{16\_u}~x~m \\ &&|& + \text{i64.load32\_s}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\LOAD\K{32\_s}~x~m \\ &&|& + \text{i64.load32\_u}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\LOAD\K{32\_u}~x~m \\ &&|& + \text{i32.store}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \I32.\STORE~x~m \\ &&|& + \text{i64.store}~~x{:}\Tmemidx~~m{:}\Tmemarg_8 &\Rightarrow& \I64.\STORE~x~m \\ &&|& + \text{f32.store}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \F32.\STORE~x~m \\ &&|& + \text{f64.store}~~x{:}\Tmemidx~~m{:}\Tmemarg_8 &\Rightarrow& \F64.\STORE~x~m \\ &&|& + \text{i32.store8}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I32.\STORE\K{8}~x~m \\ &&|& + \text{i32.store16}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I32.\STORE\K{16}~x~m \\ &&|& + \text{i64.store8}~~x{:}\Tmemidx~~m{:}\Tmemarg_1 &\Rightarrow& \I64.\STORE\K{8}~x~m \\ &&|& + \text{i64.store16}~~x{:}\Tmemidx~~m{:}\Tmemarg_2 &\Rightarrow& \I64.\STORE\K{16}~x~m \\ &&|& + \text{i64.store32}~~x{:}\Tmemidx~~m{:}\Tmemarg_4 &\Rightarrow& \I64.\STORE\K{32}~x~m \\ &&|& + \text{memory.size}~~x{:}\Tmemidx &\Rightarrow& \MEMORYSIZE~x \\ &&|& + \text{memory.grow}~~x{:}\Tmemidx &\Rightarrow& \MEMORYGROW~x \\ + \end{array} + + +Abbreviations +............. + +As an abbreviation, the memory index can be omitted in all memory instructions, defaulting to :math:`\T{0}`. + +.. math:: + \begin{array}{llclll} + \production{instruction} & + \Tvaltype\text{.load}~~\Tmemarg + &\equiv& + \Tvaltype\text{.load}~~\text{0}~~\Tmemarg \\& + \Tvaltype\text{.load}N\text{\_}X~~\Tmemarg + &\equiv& + \Tvaltype\text{.load}N\text{\_}X~~\text{0}~~\Tmemarg \\& + \Tvaltype\text{.store}~~\Tmemarg + &\equiv& + \Tvaltype\text{.store}~~\text{0}~~\Tmemarg \\& + \Tvaltype\text{.store}N~~\Tmemarg + &\equiv& + \Tvaltype\text{.store}N~~\text{0}~~\Tmemarg \\& + \text{memory.size} + &\equiv& + \text{memory.size}~~\text{0} \\& + \text{memory.grow} + &\equiv& + \text{memory.grow}~~\text{0} \\ \end{array} diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 3d4aecf0a..c28867820 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -309,10 +309,10 @@ Memory Instructions .. _valid-load: -:math:`t\K{.}\LOAD~\memarg` -........................... +:math:`t\K{.}\LOAD~x~\memarg` +............................. -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * The alignment :math:`2^{\memarg.\ALIGN}` must not be larger than the :ref:`bit width ` of :math:`t` divided by :math:`8`. @@ -320,20 +320,20 @@ Memory Instructions .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype \qquad 2^{\memarg.\ALIGN} \leq |t|/8 }{ - C \vdashinstr t\K{.load}~\memarg : [\I32] \to [t] + C \vdashinstr t\K{.load}~x~\memarg : [\I32] \to [t] } .. _valid-loadn: -:math:`t\K{.}\LOAD{N}\K{\_}\sx~\memarg` -....................................... +:math:`t\K{.}\LOAD{N}\K{\_}\sx~x~\memarg` +......................................... -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * The alignment :math:`2^{\memarg.\ALIGN}` must not be larger than :math:`N/8`. @@ -341,18 +341,18 @@ Memory Instructions .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype \qquad 2^{\memarg.\ALIGN} \leq N/8 }{ - C \vdashinstr t\K{.load}N\K{\_}\sx~\memarg : [\I32] \to [t] + C \vdashinstr t\K{.load}N\K{\_}\sx~x~\memarg : [\I32] \to [t] } -:math:`t\K{.}\STORE~\memarg` -............................ +:math:`t\K{.}\STORE~x~\memarg` +.............................. -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * The alignment :math:`2^{\memarg.\ALIGN}` must not be larger than the :ref:`bit width ` of :math:`t` divided by :math:`8`. @@ -360,20 +360,20 @@ Memory Instructions .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype \qquad 2^{\memarg.\ALIGN} \leq |t|/8 }{ - C \vdashinstr t\K{.store}~\memarg : [\I32~t] \to [] + C \vdashinstr t\K{.store}~x~\memarg : [\I32~t] \to [] } .. _valid-storen: -:math:`t\K{.}\STORE{N}~\memarg` -............................... +:math:`t\K{.}\STORE{N}~x~\memarg` +................................. -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * The alignment :math:`2^{\memarg.\ALIGN}` must not be larger than :math:`N/8`. @@ -381,45 +381,45 @@ Memory Instructions .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype \qquad 2^{\memarg.\ALIGN} \leq N/8 }{ - C \vdashinstr t\K{.store}N~\memarg : [\I32~t] \to [] + C \vdashinstr t\K{.store}N~x~\memarg : [\I32~t] \to [] } .. _valid-memory.size: -:math:`\MEMORYSIZE` -................... +:math:`\MEMORYSIZE~x` +..................... -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * Then the instruction is valid with type :math:`[] \to [\I32]`. .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype }{ - C \vdashinstr \MEMORYSIZE : [] \to [\I32] + C \vdashinstr \MEMORYSIZE~x : [] \to [\I32] } .. _valid-memory.grow: -:math:`\MEMORYGROW` -................... +:math:`\MEMORYGROW~x` +..................... -* The memory :math:`C.\CMEMS[0]` must be defined in the context. +* The memory :math:`C.\CMEMS[x]` must be defined in the context. * Then the instruction is valid with type :math:`[\I32] \to [\I32]`. .. math:: \frac{ - C.\CMEMS[0] = \memtype + C.\CMEMS[x] = \memtype }{ - C \vdashinstr \MEMORYGROW : [\I32] \to [\I32] + C \vdashinstr \MEMORYGROW~x : [\I32] \to [\I32] } diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst index a7c93c418..570bc7ac7 100644 --- a/document/core/valid/modules.rst +++ b/document/core/valid/modules.rst @@ -552,8 +552,6 @@ Instead, the context :math:`C` for validation of the module's content is constru \qquad |C.\CTABLES| \leq 1 \qquad - |C.\CMEMS| \leq 1 - \qquad (\export.\ENAME)^\ast ~\F{disjoint} \end{array} }{ @@ -584,4 +582,4 @@ Instead, the context :math:`C` for validation of the module's content is constru The effect of defining the limited context :math:`C'` for validating the module's globals is that their initialization expressions can only access imported globals and nothing else. .. note:: - The restriction on the number of tables and memories may be lifted in future versions of WebAssembly. + The restriction on the number of tables may be lifted in future versions of WebAssembly. From c52086f99717829644feb1948ddeb780039e5be0 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 15:32:24 +0200 Subject: [PATCH 012/181] Typo --- document/core/binary/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index dc5faee1c..6d9608833 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -117,7 +117,7 @@ Variable Instructions Memory Instructions ~~~~~~~~~~~~~~~~~~~ -Each variant of :ref:`memory instruction ` is encoded with a different byte code. Loads and stores are followed by the encoding of their |memarg| immediate, which includes the :ref:`memory index ` if bit 6 of the flags field containing alignemnt is set; the memory index defaults to 0 otherwise. +Each variant of :ref:`memory instruction ` is encoded with a different byte code. Loads and stores are followed by the encoding of their |memarg| immediate, which includes the :ref:`memory index ` if bit 6 of the flags field containing alignment is set; the memory index defaults to 0 otherwise. .. _binary-memarg: .. _binary-load: From 6f50abe631d70884c062bde2952b56e524794dd1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 15:36:45 +0200 Subject: [PATCH 013/181] Eps --- document/core/text/instructions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index 2f6e825f8..a2c3dc502 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -230,9 +230,9 @@ As an abbreviation, the memory index can be omitted in all memory instructions, \Tvaltype\text{.load}~~\Tmemarg &\equiv& \Tvaltype\text{.load}~~\text{0}~~\Tmemarg \\& - \Tvaltype\text{.load}N\text{\_}X~~\Tmemarg + \Tvaltype\text{.load}N\text{\_}\sx~~\Tmemarg &\equiv& - \Tvaltype\text{.load}N\text{\_}X~~\text{0}~~\Tmemarg \\& + \Tvaltype\text{.load}N\text{\_}\sx~~\text{0}~~\Tmemarg \\& \Tvaltype\text{.store}~~\Tmemarg &\equiv& \Tvaltype\text{.store}~~\text{0}~~\Tmemarg \\& From 717177c7c0d980b9eeaaa09d9bfc5b791982af21 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 11:07:47 +0200 Subject: [PATCH 014/181] Interpreter changes --- interpreter/binary/decode.ml | 65 ++++++----- interpreter/binary/encode.ml | 103 ++++++++++------- interpreter/exec/eval.ml | 16 +-- interpreter/syntax/ast.ml | 8 +- interpreter/syntax/operators.ml | 89 ++++++++------- interpreter/text/arrange.ml | 38 +++---- interpreter/text/lexer.mll | 36 +++--- interpreter/text/parser.mly | 20 +++- interpreter/util/lib.ml | 1 + interpreter/util/lib.mli | 1 + interpreter/valid/valid.ml | 21 ++-- test/core/binary.wast | 191 -------------------------------- test/core/imports.wast | 13 --- test/core/memory.wast | 3 - 14 files changed, 216 insertions(+), 389 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index cff17feaa..6a8590cfc 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -195,10 +195,13 @@ let op s = u8 s let end_ s = expect 0x0b s "END opcode expected" let memop s = - let align = vu32 s in + let flags = vu32 s in + let has_var = (Int32.logand flags 0x40l = 0l) in + let align = Int32.(logand flags (lognot 0x40l)) in require (I32.le_u align 32l) s (pos s - 1) "invalid memop flags"; let offset = vu32 s in - Int32.to_int align, offset + let x = if has_var then Source.(0l @@ no_region) else at var s in + x, Int32.to_int align, offset let rec instr s = let pos = pos s in @@ -262,37 +265,33 @@ let rec instr s = | 0x25 | 0x26 | 0x27 as b -> illegal s pos b - | 0x28 -> let a, o = memop s in i32_load a o - | 0x29 -> let a, o = memop s in i64_load a o - | 0x2a -> let a, o = memop s in f32_load a o - | 0x2b -> let a, o = memop s in f64_load a o - | 0x2c -> let a, o = memop s in i32_load8_s a o - | 0x2d -> let a, o = memop s in i32_load8_u a o - | 0x2e -> let a, o = memop s in i32_load16_s a o - | 0x2f -> let a, o = memop s in i32_load16_u a o - | 0x30 -> let a, o = memop s in i64_load8_s a o - | 0x31 -> let a, o = memop s in i64_load8_u a o - | 0x32 -> let a, o = memop s in i64_load16_s a o - | 0x33 -> let a, o = memop s in i64_load16_u a o - | 0x34 -> let a, o = memop s in i64_load32_s a o - | 0x35 -> let a, o = memop s in i64_load32_u a o - - | 0x36 -> let a, o = memop s in i32_store a o - | 0x37 -> let a, o = memop s in i64_store a o - | 0x38 -> let a, o = memop s in f32_store a o - | 0x39 -> let a, o = memop s in f64_store a o - | 0x3a -> let a, o = memop s in i32_store8 a o - | 0x3b -> let a, o = memop s in i32_store16 a o - | 0x3c -> let a, o = memop s in i64_store8 a o - | 0x3d -> let a, o = memop s in i64_store16 a o - | 0x3e -> let a, o = memop s in i64_store32 a o - - | 0x3f -> - expect 0x00 s "zero flag expected"; - memory_size - | 0x40 -> - expect 0x00 s "zero flag expected"; - memory_grow + | 0x28 -> let x, a, o = memop s in i32_load x a o + | 0x29 -> let x, a, o = memop s in i64_load x a o + | 0x2a -> let x, a, o = memop s in f32_load x a o + | 0x2b -> let x, a, o = memop s in f64_load x a o + | 0x2c -> let x, a, o = memop s in i32_load8_s x a o + | 0x2d -> let x, a, o = memop s in i32_load8_u x a o + | 0x2e -> let x, a, o = memop s in i32_load16_s x a o + | 0x2f -> let x, a, o = memop s in i32_load16_u x a o + | 0x30 -> let x, a, o = memop s in i64_load8_s x a o + | 0x31 -> let x, a, o = memop s in i64_load8_u x a o + | 0x32 -> let x, a, o = memop s in i64_load16_s x a o + | 0x33 -> let x, a, o = memop s in i64_load16_u x a o + | 0x34 -> let x, a, o = memop s in i64_load32_s x a o + | 0x35 -> let x, a, o = memop s in i64_load32_u x a o + + | 0x36 -> let x, a, o = memop s in i32_store x a o + | 0x37 -> let x, a, o = memop s in i64_store x a o + | 0x38 -> let x, a, o = memop s in f32_store x a o + | 0x39 -> let x, a, o = memop s in f64_store x a o + | 0x3a -> let x, a, o = memop s in i32_store8 x a o + | 0x3b -> let x, a, o = memop s in i32_store16 x a o + | 0x3c -> let x, a, o = memop s in i64_store8 x a o + | 0x3d -> let x, a, o = memop s in i64_store16 x a o + | 0x3e -> let x, a, o = memop s in i64_store32 x a o + + | 0x3f -> memory_size (at var s) + | 0x40 -> memory_grow (at var s) | 0x41 -> i32_const (at vs32 s) | 0x42 -> i64_const (at vs64 s) diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index e6f327567..0d4c2b5b3 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -135,10 +135,14 @@ let encode m = let op n = u8 n let end_ () = op 0x0b - let memop {align; offset; _} = vu32 (Int32.of_int align); vu32 offset - let var x = vu32 x.it + let memop x {align; offset; _} = + let flags = if x.it = 0l then align else align + 0x40 in + vu32 (Int32.of_int flags); + vu32 offset; + if x.it <> 0l then var x + let rec instr e = match e.it with | Unreachable -> op 0x00 @@ -167,49 +171,64 @@ let encode m = | GlobalGet x -> op 0x23; var x | GlobalSet x -> op 0x24; var x - | Load ({ty = I32Type; sz = None; _} as mo) -> op 0x28; memop mo - | Load ({ty = I64Type; sz = None; _} as mo) -> op 0x29; memop mo - | Load ({ty = F32Type; sz = None; _} as mo) -> op 0x2a; memop mo - | Load ({ty = F64Type; sz = None; _} as mo) -> op 0x2b; memop mo - | Load ({ty = I32Type; sz = Some (Pack8, SX); _} as mo) -> - op 0x2c; memop mo - | Load ({ty = I32Type; sz = Some (Pack8, ZX); _} as mo) -> - op 0x2d; memop mo - | Load ({ty = I32Type; sz = Some (Pack16, SX); _} as mo) -> - op 0x2e; memop mo - | Load ({ty = I32Type; sz = Some (Pack16, ZX); _} as mo) -> - op 0x2f; memop mo - | Load {ty = I32Type; sz = Some (Pack32, _); _} -> + | Load (x, ({ty = I32Type; sz = None; _} as mo)) -> + op 0x28; memop x mo + | Load (x, ({ty = I64Type; sz = None; _} as mo)) -> + op 0x29; memop x mo + | Load (x, ({ty = F32Type; sz = None; _} as mo)) -> + op 0x2a; memop x mo + | Load (x, ({ty = F64Type; sz = None; _} as mo)) -> + op 0x2b; memop x mo + | Load (x, ({ty = I32Type; sz = Some (Pack8, SX); _} as mo)) -> + op 0x2c; memop x mo + | Load (x, ({ty = I32Type; sz = Some (Pack8, ZX); _} as mo)) -> + op 0x2d; memop x mo + | Load (x, ({ty = I32Type; sz = Some (Pack16, SX); _} as mo)) -> + op 0x2e; memop x mo + | Load (x, ({ty = I32Type; sz = Some (Pack16, ZX); _} as mo)) -> + op 0x2f; memop x mo + | Load (x, {ty = I32Type; sz = Some (Pack32, _); _}) -> + assert false + | Load (x, ({ty = I64Type; sz = Some (Pack8, SX); _} as mo)) -> + op 0x30; memop x mo + | Load (x, ({ty = I64Type; sz = Some (Pack8, ZX); _} as mo)) -> + op 0x31; memop x mo + | Load (x, ({ty = I64Type; sz = Some (Pack16, SX); _} as mo)) -> + op 0x32; memop x mo + | Load (x, ({ty = I64Type; sz = Some (Pack16, ZX); _} as mo)) -> + op 0x33; memop x mo + | Load (x, ({ty = I64Type; sz = Some (Pack32, SX); _} as mo)) -> + op 0x34; memop x mo + | Load (x, ({ty = I64Type; sz = Some (Pack32, ZX); _} as mo)) -> + op 0x35; memop x mo + | Load (x, {ty = F32Type | F64Type; sz = Some _; _}) -> + assert false + + | Store (x, ({ty = I32Type; sz = None; _} as mo)) -> + op 0x36; memop x mo + | Store (x, ({ty = I64Type; sz = None; _} as mo)) -> + op 0x37; memop x mo + | Store (x, ({ty = F32Type; sz = None; _} as mo)) -> + op 0x38; memop x mo + | Store (x, ({ty = F64Type; sz = None; _} as mo)) -> + op 0x39; memop x mo + | Store (x, ({ty = I32Type; sz = Some Pack8; _} as mo)) -> + op 0x3a; memop x mo + | Store (x, ({ty = I32Type; sz = Some Pack16; _} as mo)) -> + op 0x3b; memop x mo + | Store (x, {ty = I32Type; sz = Some Pack32; _}) -> assert false - | Load ({ty = I64Type; sz = Some (Pack8, SX); _} as mo) -> - op 0x30; memop mo - | Load ({ty = I64Type; sz = Some (Pack8, ZX); _} as mo) -> - op 0x31; memop mo - | Load ({ty = I64Type; sz = Some (Pack16, SX); _} as mo) -> - op 0x32; memop mo - | Load ({ty = I64Type; sz = Some (Pack16, ZX); _} as mo) -> - op 0x33; memop mo - | Load ({ty = I64Type; sz = Some (Pack32, SX); _} as mo) -> - op 0x34; memop mo - | Load ({ty = I64Type; sz = Some (Pack32, ZX); _} as mo) -> - op 0x35; memop mo - | Load {ty = F32Type | F64Type; sz = Some _; _} -> + | Store (x, ({ty = I64Type; sz = Some Pack8; _} as mo)) -> + op 0x3c; memop x mo + | Store (x, ({ty = I64Type; sz = Some Pack16; _} as mo)) -> + op 0x3d; memop x mo + | Store (x, ({ty = I64Type; sz = Some Pack32; _} as mo)) -> + op 0x3e; memop x mo + | Store (x, {ty = F32Type | F64Type; sz = Some _; _}) -> assert false - | Store ({ty = I32Type; sz = None; _} as mo) -> op 0x36; memop mo - | Store ({ty = I64Type; sz = None; _} as mo) -> op 0x37; memop mo - | Store ({ty = F32Type; sz = None; _} as mo) -> op 0x38; memop mo - | Store ({ty = F64Type; sz = None; _} as mo) -> op 0x39; memop mo - | Store ({ty = I32Type; sz = Some Pack8; _} as mo) -> op 0x3a; memop mo - | Store ({ty = I32Type; sz = Some Pack16; _} as mo) -> op 0x3b; memop mo - | Store {ty = I32Type; sz = Some Pack32; _} -> assert false - | Store ({ty = I64Type; sz = Some Pack8; _} as mo) -> op 0x3c; memop mo - | Store ({ty = I64Type; sz = Some Pack16; _} as mo) -> op 0x3d; memop mo - | Store ({ty = I64Type; sz = Some Pack32; _} as mo) -> op 0x3e; memop mo - | Store {ty = F32Type | F64Type; sz = Some _; _} -> assert false - - | MemorySize -> op 0x3f; u8 0x00 - | MemoryGrow -> op 0x40; u8 0x00 + | MemorySize x -> op 0x3f; var x + | MemoryGrow x -> op 0x40; var x | Const {it = I32 c; _} -> op 0x41; vs32 c | Const {it = I64 c; _} -> op 0x42; vs64 c diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 452d9425c..7efe82afd 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -192,8 +192,8 @@ let rec step (c : config) : config = with Global.NotMutable -> Crash.error e.at "write to immutable global" | Global.Type -> Crash.error e.at "type mismatch at global write") - | Load {offset; ty; sz; _}, I32 i :: vs' -> - let mem = memory frame.inst (0l @@ e.at) in + | Load (x, {offset; ty; sz; _}), I32 i :: vs' -> + let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try let v = @@ -203,8 +203,8 @@ let rec step (c : config) : config = in v :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) - | Store {offset; sz; _}, v :: I32 i :: vs' -> - let mem = memory frame.inst (0l @@ e.at) in + | Store (x, {offset; sz; _}), v :: I32 i :: vs' -> + let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try (match sz with @@ -214,12 +214,12 @@ let rec step (c : config) : config = vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]); - | MemorySize, vs -> - let mem = memory frame.inst (0l @@ e.at) in + | MemorySize x, vs -> + let mem = memory frame.inst x in I32 (Memory.size mem) :: vs, [] - | MemoryGrow, I32 delta :: vs' -> - let mem = memory frame.inst (0l @@ e.at) in + | MemoryGrow x, I32 delta :: vs' -> + let mem = memory frame.inst x in let old_size = Memory.size mem in let result = try Memory.grow mem delta; old_size diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 089023fc1..fdd98829c 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -87,10 +87,10 @@ and instr' = | LocalTee of var (* write local variable and keep value *) | GlobalGet of var (* read global variable *) | GlobalSet of var (* write global variable *) - | Load of loadop (* read memory at address *) - | Store of storeop (* write memory at address *) - | MemorySize (* size of linear memory *) - | MemoryGrow (* grow linear memory *) + | Load of var * loadop (* read memory at address *) + | Store of var * storeop (* write memory at address *) + | MemorySize of var (* size of linear memory *) + | MemoryGrow of var (* grow linear memory *) | Const of literal (* constant *) | Test of testop (* numeric test *) | Compare of relop (* numeric comparison *) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index ff7588fa0..e5096fdf9 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -31,45 +31,53 @@ let local_tee x = LocalTee x let global_get x = GlobalGet x let global_set x = GlobalSet x -let i32_load align offset = Load {ty = I32Type; align; offset; sz = None} -let i64_load align offset = Load {ty = I64Type; align; offset; sz = None} -let f32_load align offset = Load {ty = F32Type; align; offset; sz = None} -let f64_load align offset = Load {ty = F64Type; align; offset; sz = None} -let i32_load8_s align offset = - Load {ty = I32Type; align; offset; sz = Some (Pack8, SX)} -let i32_load8_u align offset = - Load {ty = I32Type; align; offset; sz = Some (Pack8, ZX)} -let i32_load16_s align offset = - Load {ty = I32Type; align; offset; sz = Some (Pack16, SX)} -let i32_load16_u align offset = - Load {ty = I32Type; align; offset; sz = Some (Pack16, ZX)} -let i64_load8_s align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack8, SX)} -let i64_load8_u align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack8, ZX)} -let i64_load16_s align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack16, SX)} -let i64_load16_u align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack16, ZX)} -let i64_load32_s align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack32, SX)} -let i64_load32_u align offset = - Load {ty = I64Type; align; offset; sz = Some (Pack32, ZX)} +let i32_load x align offset = + Load (x, {ty = I32Type; align; offset; sz = None}) +let i64_load x align offset = + Load (x, {ty = I64Type; align; offset; sz = None}) +let f32_load x align offset = + Load (x, {ty = F32Type; align; offset; sz = None}) +let f64_load x align offset = + Load (x, {ty = F64Type; align; offset; sz = None}) +let i32_load8_s x align offset = + Load (x, {ty = I32Type; align; offset; sz = Some (Pack8, SX)}) +let i32_load8_u x align offset = + Load (x, {ty = I32Type; align; offset; sz = Some (Pack8, ZX)}) +let i32_load16_s x align offset = + Load (x, {ty = I32Type; align; offset; sz = Some (Pack16, SX)}) +let i32_load16_u x align offset = + Load (x, {ty = I32Type; align; offset; sz = Some (Pack16, ZX)}) +let i64_load8_s x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack8, SX)}) +let i64_load8_u x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack8, ZX)}) +let i64_load16_s x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack16, SX)}) +let i64_load16_u x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack16, ZX)}) +let i64_load32_s x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack32, SX)}) +let i64_load32_u x align offset = + Load (x, {ty = I64Type; align; offset; sz = Some (Pack32, ZX)}) -let i32_store align offset = Store {ty = I32Type; align; offset; sz = None} -let i64_store align offset = Store {ty = I64Type; align; offset; sz = None} -let f32_store align offset = Store {ty = F32Type; align; offset; sz = None} -let f64_store align offset = Store {ty = F64Type; align; offset; sz = None} -let i32_store8 align offset = - Store {ty = I32Type; align; offset; sz = Some Pack8} -let i32_store16 align offset = - Store {ty = I32Type; align; offset; sz = Some Pack16} -let i64_store8 align offset = - Store {ty = I64Type; align; offset; sz = Some Pack8} -let i64_store16 align offset = - Store {ty = I64Type; align; offset; sz = Some Pack16} -let i64_store32 align offset = - Store {ty = I64Type; align; offset; sz = Some Pack32} +let i32_store x align offset = + Store (x, {ty = I32Type; align; offset; sz = None}) +let i64_store x align offset = + Store (x, {ty = I64Type; align; offset; sz = None}) +let f32_store x align offset = + Store (x, {ty = F32Type; align; offset; sz = None}) +let f64_store x align offset = + Store (x, {ty = F64Type; align; offset; sz = None}) +let i32_store8 x align offset = + Store (x, {ty = I32Type; align; offset; sz = Some Pack8}) +let i32_store16 x align offset = + Store (x, {ty = I32Type; align; offset; sz = Some Pack16}) +let i64_store8 x align offset = + Store (x, {ty = I64Type; align; offset; sz = Some Pack8}) +let i64_store16 x align offset = + Store (x, {ty = I64Type; align; offset; sz = Some Pack16}) +let i64_store32 x align offset = + Store (x, {ty = I64Type; align; offset; sz = Some Pack32}) let i32_clz = Unary (I32 I32Op.Clz) let i32_ctz = Unary (I32 I32Op.Ctz) @@ -199,6 +207,5 @@ let i64_reinterpret_f64 = Convert (I64 I64Op.ReinterpretFloat) let f32_reinterpret_i32 = Convert (F32 F32Op.ReinterpretInt) let f64_reinterpret_i64 = Convert (F64 F64Op.ReinterpretInt) -let memory_size = MemorySize -let memory_grow = MemoryGrow - +let memory_size x = MemorySize x +let memory_grow x = MemoryGrow x diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index f764d34ce..d9ad6e5a7 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -187,6 +187,13 @@ let testop = oper (IntOp.testop, FloatOp.testop) let relop = oper (IntOp.relop, FloatOp.relop) let cvtop = oper (IntOp.cvtop, FloatOp.cvtop) + +(* Expressions *) + +let var x = nat32 x.it +let value v = string_of_value v.it +let constop v = value_type (type_of v.it) ^ ".const" + let pack_size = function | Memory.Pack8 -> "8" | Memory.Pack16 -> "16" @@ -196,28 +203,21 @@ let extension = function | Memory.SX -> "_s" | Memory.ZX -> "_u" -let memop name {ty; align; offset; _} sz = - value_type ty ^ "." ^ name ^ +let memop name x {ty; align; offset; _} sz = + value_type ty ^ "." ^ name ^ " " ^ var x ^ (if offset = 0l then "" else " offset=" ^ nat32 offset) ^ (if 1 lsl align = sz then "" else " align=" ^ nat (1 lsl align)) -let loadop op = +let loadop x op = match op.sz with - | None -> memop "load" op (size op.ty) + | None -> memop "load" x op (size op.ty) | Some (sz, ext) -> - memop ("load" ^ pack_size sz ^ extension ext) op (Memory.packed_size sz) + memop ("load" ^ pack_size sz ^ extension ext) x op (Memory.packed_size sz) -let storeop op = +let storeop x op = match op.sz with - | None -> memop "store" op (size op.ty) - | Some sz -> memop ("store" ^ pack_size sz) op (Memory.packed_size sz) - - -(* Expressions *) - -let var x = nat32 x.it -let value v = string_of_value v.it -let constop v = value_type (type_of v.it) ^ ".const" + | None -> memop "store" x op (size op.ty) + | Some sz -> memop ("store" ^ pack_size sz) x op (Memory.packed_size sz) let rec instr e = let head, inner = @@ -243,10 +243,10 @@ let rec instr e = | LocalTee x -> "local.tee " ^ var x, [] | GlobalGet x -> "global.get " ^ var x, [] | GlobalSet x -> "global.set " ^ var x, [] - | Load op -> loadop op, [] - | Store op -> storeop op, [] - | MemorySize -> "memory.size", [] - | MemoryGrow -> "memory.grow", [] + | Load (x, op) -> loadop x op, [] + | Store (x, op) -> storeop x op, [] + | MemorySize x -> "memory.size " ^ var x, [] + | MemoryGrow x -> "memory.grow " ^ var x, [] | Const lit -> constop lit ^ " " ^ value lit, [] | Test op -> testop op, [] | Compare op -> relop op, [] diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index dab48e045..9c50d82d3 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -200,37 +200,37 @@ rule token = parse | "global.set" { GLOBAL_SET } | (nxx as t)".load" - { LOAD (fun a o -> - numop t (i32_load (opt a 2)) (i64_load (opt a 3)) - (f32_load (opt a 2)) (f64_load (opt a 3)) o) } + { LOAD (fun x a o -> + numop t (i32_load x (opt a 2)) (i64_load x (opt a 3)) + (f32_load x (opt a 2)) (f64_load x (opt a 3)) o) } | (nxx as t)".store" - { STORE (fun a o -> - numop t (i32_store (opt a 2)) (i64_store (opt a 3)) - (f32_store (opt a 2)) (f64_store (opt a 3)) o) } + { STORE (fun x a o -> + numop t (i32_store x (opt a 2)) (i64_store x (opt a 3)) + (f32_store x (opt a 2)) (f64_store x (opt a 3)) o) } | (ixx as t)".load"(mem_size as sz)"_"(sign as s) { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; - LOAD (fun a o -> + LOAD (fun x a o -> intop t (memsz sz - (ext s i32_load8_s i32_load8_u (opt a 0)) - (ext s i32_load16_s i32_load16_u (opt a 1)) + (ext s i32_load8_s i32_load8_u x (opt a 0)) + (ext s i32_load16_s i32_load16_u x (opt a 1)) (fun _ -> unreachable) o) (memsz sz - (ext s i64_load8_s i64_load8_u (opt a 0)) - (ext s i64_load16_s i64_load16_u (opt a 1)) - (ext s i64_load32_s i64_load32_u (opt a 2)) o)) } + (ext s i64_load8_s i64_load8_u x (opt a 0)) + (ext s i64_load16_s i64_load16_u x (opt a 1)) + (ext s i64_load32_s i64_load32_u x (opt a 2)) o)) } | (ixx as t)".store"(mem_size as sz) { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; - STORE (fun a o -> + STORE (fun x a o -> intop t (memsz sz - (i32_store8 (opt a 0)) - (i32_store16 (opt a 1)) + (i32_store8 x (opt a 0)) + (i32_store16 x (opt a 1)) (fun _ -> unreachable) o) (memsz sz - (i64_store8 (opt a 0)) - (i64_store16 (opt a 1)) - (i64_store32 (opt a 2)) o)) } + (i64_store8 x (opt a 0)) + (i64_store16 x (opt a 1)) + (i64_store32 x (opt a 2)) o)) } | "offset="(nat as s) { OFFSET_EQ_NAT s } | "align="(nat as s) { ALIGN_EQ_NAT s } diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index 670afd6ba..976328d59 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -173,8 +173,8 @@ let inline_type_explicit (c : context) x ft at = %token TEST %token COMPARE %token CONVERT -%token Memory.offset -> Ast.instr'> LOAD -%token Memory.offset -> Ast.instr'> STORE +%token int option -> Memory.offset -> Ast.instr'> LOAD +%token int option -> Memory.offset -> Ast.instr'> STORE %token OFFSET_EQ_NAT %token ALIGN_EQ_NAT @@ -251,6 +251,10 @@ var : | NAT { let at = at () in fun c lookup -> nat32 $1 at @@ at } | VAR { let at = at () in fun c lookup -> lookup c ($1 @@ at) @@ at } +var_opt : + | /* empty */ { fun c lookup at -> 0l @@ at } + | var { fun c lookup at -> $1 c lookup } + var_list : | /* empty */ { fun c lookup -> [] } | var var_list { fun c lookup -> $1 c lookup :: $2 c lookup } @@ -315,10 +319,14 @@ plain_instr : | LOCAL_TEE var { fun c -> local_tee ($2 c local) } | GLOBAL_GET var { fun c -> global_get ($2 c global) } | GLOBAL_SET var { fun c -> global_set ($2 c global) } - | LOAD offset_opt align_opt { fun c -> $1 $3 $2 } - | STORE offset_opt align_opt { fun c -> $1 $3 $2 } - | MEMORY_SIZE { fun c -> memory_size } - | MEMORY_GROW { fun c -> memory_grow } + | LOAD var_opt offset_opt align_opt + { let at1 = ati 1 in fun c -> $1 ($2 c memory at1) $4 $3 } + | STORE var_opt offset_opt align_opt + { let at1 = ati 1 in fun c -> $1 ($2 c memory at1) $4 $3 } + | MEMORY_SIZE var_opt + { let at1 = ati 1 in fun c -> memory_size ($2 c memory at1) } + | MEMORY_GROW var_opt + { let at1 = ati 1 in fun c -> memory_grow ($2 c memory at1) } | CONST literal { fun c -> fst (literal $1 $2) } | TEST { fun c -> $1 } | COMPARE { fun c -> $1 } diff --git a/interpreter/util/lib.ml b/interpreter/util/lib.ml index a2919e00e..a7de53bc6 100644 --- a/interpreter/util/lib.ml +++ b/interpreter/util/lib.ml @@ -1,5 +1,6 @@ module Fun = struct + let id x = x let curry f x y = f (x, y) let uncurry f (x, y) = f x y diff --git a/interpreter/util/lib.mli b/interpreter/util/lib.mli index 3ab141c40..9e1de07d2 100644 --- a/interpreter/util/lib.mli +++ b/interpreter/util/lib.mli @@ -2,6 +2,7 @@ module Fun : sig + val id : 'a -> 'a val curry : ('a * 'b -> 'c) -> ('a -> 'b -> 'c) val uncurry : ('a -> 'b -> 'c) -> ('a * 'b -> 'c) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index ea78d1784..d70f175f1 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -138,7 +138,6 @@ let type_cvtop at = function (* Expressions *) let check_memop (c : context) (memop : 'a memop) get_sz at = - ignore (memory c (0l @@ at)); let size = match get_sz memop.sz with | None -> size memop.ty @@ -248,20 +247,22 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = require (mut = Mutable) x.at "global is immutable"; [t] --> [] - | Load memop -> + | Load (x, memop) -> + ignore (memory c x); check_memop c memop (Lib.Option.map fst) e.at; [I32Type] --> [memop.ty] - | Store memop -> - check_memop c memop (fun sz -> sz) e.at; + | Store (x, memop) -> + ignore (memory c x); + check_memop c memop Lib.Fun.id e.at; [I32Type; memop.ty] --> [] - | MemorySize -> - ignore (memory c (0l @@ e.at)); + | MemorySize x -> + ignore (memory c x); [] --> [I32Type] - | MemoryGrow -> - ignore (memory c (0l @@ e.at)); + | MemoryGrow x -> + ignore (memory c x); [I32Type] --> [I32Type] | Const v -> @@ -469,6 +470,4 @@ let check_module (m : module_) = check_start c start; ignore (List.fold_left (check_export c) NameSet.empty exports); require (List.length c.tables <= 1) m.at - "multiple tables are not allowed (yet)"; - require (List.length c.memories <= 1) m.at - "multiple memories are not allowed (yet)" + "multiple tables are not allowed (yet)" diff --git a/test/core/binary.wast b/test/core/binary.wast index f800348b9..a60495b48 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -138,197 +138,6 @@ "zero flag expected" ) -;; memory.grow reserved byte equal to zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\09\01" ;; Code section - - ;; function 0 - "\07\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\01" ;; memory.grow reserved byte is not equal to zero! - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.grow reserved byte should not be a "long" LEB128 zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0a\01" ;; Code section - - ;; function 0 - "\08\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; Same as above for 3, 4, and 5-byte zero encodings. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0b\01" ;; Code section - - ;; function 0 - "\09\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0c\01" ;; Code section - - ;; function 0 - "\0a\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0d\01" ;; Code section - - ;; function 0 - "\0b\00" - "\41\00" ;; i32.const 0 - "\40" ;; memory.grow - "\80\80\80\80\00" ;; memory.grow reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.size reserved byte equal to zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\07\01" ;; Code section - - ;; function 0 - "\05\00" - "\3f" ;; memory.size - "\01" ;; memory.size reserved byte is not equal to zero! - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; memory.size reserved byte should not be a "long" LEB128 zero. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\08\01" ;; Code section - - ;; function 0 - "\06\00" - "\3f" ;; memory.size - "\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -;; Same as above for 3, 4, and 5-byte zero encodings. -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\09\01" ;; Code section - - ;; function 0 - "\07\00" - "\3f" ;; memory.size - "\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0a\01" ;; Code section - - ;; function 0 - "\08\00" - "\3f" ;; memory.size - "\80\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - -(assert_malformed - (module binary - "\00asm" "\01\00\00\00" - "\01\04\01\60\00\00" ;; Type section - "\03\02\01\00" ;; Function section - "\05\03\01\00\00" ;; Memory section - "\0a\0b\01" ;; Code section - - ;; function 0 - "\09\00" - "\3f" ;; memory.size - "\80\80\80\80\00" ;; memory.size reserved byte - "\1a" ;; drop - "\0b" ;; end - ) - "zero flag expected" -) - ;; No more than 2^32 locals. (assert_malformed (module binary diff --git a/test/core/imports.wast b/test/core/imports.wast index 2f0200dc3..cdfc8c58b 100644 --- a/test/core/imports.wast +++ b/test/core/imports.wast @@ -401,19 +401,6 @@ (assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) (assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") -(assert_invalid - (module (import "" "" (memory 1)) (import "" "" (memory 1))) - "multiple memories" -) -(assert_invalid - (module (import "" "" (memory 1)) (memory 0)) - "multiple memories" -) -(assert_invalid - (module (memory 0) (memory 0)) - "multiple memories" -) - (module (import "test" "memory-2-inf" (memory 2))) (module (import "test" "memory-2-inf" (memory 1))) (module (import "test" "memory-2-inf" (memory 0))) diff --git a/test/core/memory.wast b/test/core/memory.wast index 3c426450a..c4e932b0e 100644 --- a/test/core/memory.wast +++ b/test/core/memory.wast @@ -5,9 +5,6 @@ (module (memory 1 256)) (module (memory 0 65536)) -(assert_invalid (module (memory 0) (memory 0)) "multiple memories") -(assert_invalid (module (memory (import "spectest" "memory") 0) (memory 0)) "multiple memories") - (module (memory (data)) (func (export "memsize") (result i32) (memory.size))) (assert_return (invoke "memsize") (i32.const 0)) (module (memory (data "")) (func (export "memsize") (result i32) (memory.size))) From 828bec9928544c40a89490f12cbca37393debf9e Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 4 Oct 2019 16:29:19 +0200 Subject: [PATCH 015/181] Tests --- document/js-api/index.bs | 4 +- test/core/load.wast | 35 +++++++ test/core/memory_grow.wast | 201 +++++++++++++++++++++++++++++-------- test/core/memory_size.wast | 26 +++++ test/core/store.wast | 69 +++++++++++++ 5 files changed, 290 insertions(+), 45 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 188375ce6..646719918 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -1125,10 +1125,10 @@ In practice, an implementation may run out of resources for valid modules below
  • The maximum number of globals defined in a module is 1000000.
  • The maximum number of data segments defined in a module is 100000.
  • -
  • The maximum number of tables, including declared or imported tables, is 1.
  • +
  • The maximum number of tables, including defined and imported tables, is 1.
  • The maximum size of a table is 10000000.
  • The maximum number of table entries in any table initialization is 10000000.
  • -
  • The maximum number of memories, including declared or imported memories, is 1.
  • +
  • The maximum number of memories, including defined and imported memories, is 1.
  • The initial or maximum number of pages for any memory, declared or imported, is at most 32767.
  • The maximum number of parameters to any function is 1000.
  • diff --git a/test/core/load.wast b/test/core/load.wast index ef5ec7c42..2821cfa36 100644 --- a/test/core/load.wast +++ b/test/core/load.wast @@ -1,3 +1,38 @@ +;; Multiple memories + +(module + (memory (export "mem") 2) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data $mem1 (i32.const 20) "\01\02\03\04\05") + (data $mem2 (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) +) + +(assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read1" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read1" (i32.const 23)) (i32.const 4)) +(assert_return (invoke "read1" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read2" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read2" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read2" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read2" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read2" (i32.const 54)) (i32.const 14)) + + ;; Load operator as the argument of control constructs and instructions (module diff --git a/test/core/memory_grow.wast b/test/core/memory_grow.wast index 8a87c77c6..d5419fc85 100644 --- a/test/core/memory_grow.wast +++ b/test/core/memory_grow.wast @@ -1,38 +1,3 @@ -(module - (memory 0) - - (func (export "load_at_zero") (result i32) (i32.load (i32.const 0))) - (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2))) - - (func (export "load_at_page_size") (result i32) (i32.load (i32.const 0x10000))) - (func (export "store_at_page_size") (i32.store (i32.const 0x10000) (i32.const 3))) - - (func (export "grow") (param $sz i32) (result i32) (memory.grow (local.get $sz))) - (func (export "size") (result i32) (memory.size)) -) - -(assert_return (invoke "size") (i32.const 0)) -(assert_trap (invoke "store_at_zero") "out of bounds memory access") -(assert_trap (invoke "load_at_zero") "out of bounds memory access") -(assert_trap (invoke "store_at_page_size") "out of bounds memory access") -(assert_trap (invoke "load_at_page_size") "out of bounds memory access") -(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) -(assert_return (invoke "size") (i32.const 1)) -(assert_return (invoke "load_at_zero") (i32.const 0)) -(assert_return (invoke "store_at_zero")) -(assert_return (invoke "load_at_zero") (i32.const 2)) -(assert_trap (invoke "store_at_page_size") "out of bounds memory access") -(assert_trap (invoke "load_at_page_size") "out of bounds memory access") -(assert_return (invoke "grow" (i32.const 4)) (i32.const 1)) -(assert_return (invoke "size") (i32.const 5)) -(assert_return (invoke "load_at_zero") (i32.const 2)) -(assert_return (invoke "store_at_zero")) -(assert_return (invoke "load_at_zero") (i32.const 2)) -(assert_return (invoke "load_at_page_size") (i32.const 0)) -(assert_return (invoke "store_at_page_size")) -(assert_return (invoke "load_at_page_size") (i32.const 3)) - - (module (memory 0) (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) @@ -61,6 +26,7 @@ (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) (assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1)) + ;; Test that newly allocated memory (program start and memory.grow) is zeroed (module @@ -96,6 +62,130 @@ (assert_return (invoke "grow" (i32.const 1)) (i32.const 5)) (assert_return (invoke "check-memory-zero" (i32.const 0x50000) (i32.const 0x5_ffff)) (i32.const 0)) + +;; Memory access at boundary + +(module + (memory 0) + + (func (export "load_at_zero") (result i32) (i32.load (i32.const 0))) + (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2))) + + (func (export "load_at_page_size") (result i32) + (i32.load (i32.const 0x10000)) + ) + (func (export "store_at_page_size") + (i32.store (i32.const 0x10000) (i32.const 3)) + ) + + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) + (func (export "size") (result i32) (memory.size)) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_trap (invoke "store_at_zero") "out of bounds memory access") +(assert_trap (invoke "load_at_zero") "out of bounds memory access") +(assert_trap (invoke "store_at_page_size") "out of bounds memory access") +(assert_trap (invoke "load_at_page_size") "out of bounds memory access") +(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "load_at_zero") (i32.const 0)) +(assert_return (invoke "store_at_zero")) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_trap (invoke "store_at_page_size") "out of bounds memory access") +(assert_trap (invoke "load_at_page_size") "out of bounds memory access") +(assert_return (invoke "grow" (i32.const 4)) (i32.const 1)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_return (invoke "store_at_zero")) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_return (invoke "load_at_page_size") (i32.const 0)) +(assert_return (invoke "store_at_page_size")) +(assert_return (invoke "load_at_page_size") (i32.const 3)) + + +;; Multiple memories + +(module + (memory (export "mem1") 2 5) + (memory (export "mem2") 0) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem1") 1 6) + (memory $mem2 (import "M" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) + (func (export "size3") (result i32) (memory.size $mem3)) + (func (export "size4") (result i32) (memory.size $mem4)) + + (func (export "grow1") (param i32) (result i32) + (memory.grow $mem1 (local.get 0)) + ) + (func (export "grow2") (param i32) (result i32) + (memory.grow $mem2 (local.get 0)) + ) + (func (export "grow3") (param i32) (result i32) + (memory.grow $mem3 (local.get 0)) + ) + (func (export "grow4") (param i32) (result i32) + (memory.grow $mem4 (local.get 0)) + ) +) + +(assert_return (invoke "size1") (i32.const 2)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "size1") (i32.const 3)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 2)) (i32.const 3)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow2" (i32.const 10)) (i32.const 0)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow3" (i32.const 0x1000_0000)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow3" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 6)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow4" (i32.const 1)) (i32.const 4)) +(assert_return (invoke "grow4" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 6)) +(assert_return (invoke "size4") (i32.const 5)) + + ;; As the argument of control constructs and instructions (module @@ -309,10 +399,21 @@ (assert_return (invoke "as-memory.grow-size") (i32.const 1)) +;; Type mismatches + +(assert_invalid + (module + (memory 1) + (func $type-i32-vs-f32 (result i32) + (memory.grow (f32.const 0)) + ) + ) + "type mismatch" +) (assert_invalid (module (memory 0) - (func $type-size-empty + (func $type-size-i32-vs-empty (memory.grow) (drop) ) ) @@ -321,7 +422,7 @@ (assert_invalid (module (memory 0) - (func $type-size-empty-in-block + (func $type-size-i32-vs-empty-in-block (i32.const 0) (block (memory.grow) (drop)) ) @@ -331,7 +432,7 @@ (assert_invalid (module (memory 0) - (func $type-size-empty-in-loop + (func $type-size-i32-vs-empty-in-loop (i32.const 0) (loop (memory.grow) (drop)) ) @@ -341,7 +442,7 @@ (assert_invalid (module (memory 0) - (func $type-size-empty-in-then + (func $type-size-i32-vs-empty-in-then (i32.const 0) (i32.const 0) (if (then (memory.grow) (drop))) ) @@ -349,7 +450,21 @@ "type mismatch" ) - -;; Type check - -(assert_invalid (module (memory 1) (func (result i32) (memory.grow (f32.const 0)))) "type mismatch") +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-empty + (memory.grow (i32.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-f32 (result f32) + (memory.grow (i32.const 1)) + ) + ) + "type mismatch" +) diff --git a/test/core/memory_size.wast b/test/core/memory_size.wast index 239e66d8f..a1d6ea2dd 100644 --- a/test/core/memory_size.wast +++ b/test/core/memory_size.wast @@ -63,6 +63,32 @@ (assert_return (invoke "size") (i32.const 8)) +;; Multiple memories + +(module + (memory (export "mem1") 2 4) + (memory (export "mem2") 0) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem1") 1 5) + (memory $mem2 (import "M" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) + (func (export "size3") (result i32) (memory.size $mem3)) + (func (export "size4") (result i32) (memory.size $mem4)) +) + +(assert_return (invoke "size1") (i32.const 2)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + + ;; Type errors (assert_invalid diff --git a/test/core/store.wast b/test/core/store.wast index 01c3a2dd6..fa4b284c1 100644 --- a/test/core/store.wast +++ b/test/core/store.wast @@ -1,3 +1,72 @@ +;; Multiple memories + +(module + (memory (export "mem") 2) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data $mem1 (i32.const 20) "\01\02\03\04\05") + (data $mem2 (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) + + (func (export "copy-1-to-2") + (local $i i32) + (local.set $i (i32.const 20)) + (loop $cont + (br_if 1 (i32.eq (local.get $i) (i32.const 23))) + (i32.store8 $mem2 (local.get $i) (i32.load8_u $mem1 (local.get $i))) + (local.set $i (i32.add (local.get $i) (i32.const 1))) + (br 0) + ) + ) + + (func (export "copy-2-to-1") + (local $i i32) + (local.set $i (i32.const 50)) + (loop $cont + (br_if 1 (i32.eq (local.get $i) (i32.const 54))) + (i32.store8 $mem1 (local.get $i) (i32.load8_u $mem2 (local.get $i))) + (local.set $i (i32.add (local.get $i) (i32.const 1))) + (br 0) + ) + ) +) + +(assert_return (invoke "read2" (i32.const 20)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 21)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 22)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 23)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 24)) (i32.const 0)) +(invoke "copy-1-to-2") +(assert_return (invoke "read2" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read2" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read2" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read2" (i32.const 23)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 24)) (i32.const 0)) + +(assert_return (invoke "read1" (i32.const 50)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 51)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 52)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 53)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 54)) (i32.const 0)) +(invoke "copy-2-to-1") +(assert_return (invoke "read1" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read1" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read1" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read1" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read1" (i32.const 54)) (i32.const 0)) + + ;; Store operator as the argument of control constructs and instructions (module From 945062d16c540d85c9c5addf1311e6a08cca08ec Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 14 Oct 2019 14:26:03 +0200 Subject: [PATCH 016/181] Comments --- interpreter/binary/decode.ml | 15 ++++++++++----- interpreter/binary/encode.ml | 11 +++++++++-- test/core/store.wast | 4 ++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 6a8590cfc..b05a234c3 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -126,6 +126,12 @@ let sized f s = require (pos s = start + size) s start "section size mismatch"; x +let bits i j flags = + Int32.(to_int + (logand (shift_right flags i) (lognot (shift_left (-1l) (j + 1))))) + +let bit i flags = bits i i flags = 1 + (* Types *) @@ -196,12 +202,11 @@ let end_ s = expect 0x0b s "END opcode expected" let memop s = let flags = vu32 s in - let has_var = (Int32.logand flags 0x40l = 0l) in - let align = Int32.(logand flags (lognot 0x40l)) in - require (I32.le_u align 32l) s (pos s - 1) "invalid memop flags"; + let align = bits 0 5 flags in + require (bits 7 31 flags = 0) s (pos s - 1) "invalid memop flags"; let offset = vu32 s in - let x = if has_var then Source.(0l @@ no_region) else at var s in - x, Int32.to_int align, offset + let x = if bit 6 flags then at var s else Source.(0l @@ no_region) in + x, align, offset let rec instr s = let pos = pos s in diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 0d4c2b5b3..7a7ddcd34 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -86,6 +86,13 @@ let encode m = patch s (p + 3) (lsb ((n lsr 21) lor 0x80)); patch s (p + 4) (lsb (n lsr 28)) + let bits i j n flags = + let w = Int32.(shift_left (of_int n) i) in + assert (Int32.(logand flags (shift_left (-1l) (j + 1))) = 0l); + Int32.logor w flags + + let bit i b flags = bits i i (if b then 1 else 0) flags + (* Types *) open Types @@ -138,8 +145,8 @@ let encode m = let var x = vu32 x.it let memop x {align; offset; _} = - let flags = if x.it = 0l then align else align + 0x40 in - vu32 (Int32.of_int flags); + let flags = bit 6 (x.it <> 0l) (bits 0 5 align 0l) in + vu32 flags; vu32 offset; if x.it <> 0l then var x diff --git a/test/core/store.wast b/test/core/store.wast index fa4b284c1..935232760 100644 --- a/test/core/store.wast +++ b/test/core/store.wast @@ -26,7 +26,7 @@ (br_if 1 (i32.eq (local.get $i) (i32.const 23))) (i32.store8 $mem2 (local.get $i) (i32.load8_u $mem1 (local.get $i))) (local.set $i (i32.add (local.get $i) (i32.const 1))) - (br 0) + (br $cont) ) ) @@ -37,7 +37,7 @@ (br_if 1 (i32.eq (local.get $i) (i32.const 54))) (i32.store8 $mem1 (local.get $i) (i32.load8_u $mem2 (local.get $i))) (local.set $i (i32.add (local.get $i) (i32.const 1))) - (br 0) + (br $cont) ) ) ) From b02d9d4b33f7e699007391513b9642a282661730 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 16 Oct 2019 07:39:02 +0200 Subject: [PATCH 017/181] Remove bits again --- document/core/binary/instructions.rst | 2 +- interpreter/binary/decode.ml | 14 +++++--------- interpreter/binary/encode.ml | 13 ++++--------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 6d9608833..0416dc275 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -133,7 +133,7 @@ Each variant of :ref:`memory instruction ` is encoded with a{:}\Bu32~~o{:}\Bu32 &\Rightarrow& 0~\{ \ALIGN~a,~\OFFSET~o \} & (\iff a < 2^6) \\ &&|& a{:}\Bu32~~o{:}\Bu32~~x{:}\memidx &\Rightarrow& x~\{ \ALIGN~(a - 2^6),~\OFFSET~o \} - & (\otherwise) \\ + & (\iff 2^6 \leq a < 2^7) \\ \production{instruction} & \Binstr &::=& \dots \\ &&|& \hex{28}~~m{:}\Bmemarg &\Rightarrow& \I32.\LOAD~m \\ &&|& \hex{29}~~m{:}\Bmemarg &\Rightarrow& \I64.\LOAD~m \\ &&|& diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index b05a234c3..6af221cf9 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -126,12 +126,6 @@ let sized f s = require (pos s = start + size) s start "section size mismatch"; x -let bits i j flags = - Int32.(to_int - (logand (shift_right flags i) (lognot (shift_left (-1l) (j + 1))))) - -let bit i flags = bits i i flags = 1 - (* Types *) @@ -201,11 +195,13 @@ let op s = u8 s let end_ s = expect 0x0b s "END opcode expected" let memop s = + let pos = pos s in let flags = vu32 s in - let align = bits 0 5 flags in - require (bits 7 31 flags = 0) s (pos s - 1) "invalid memop flags"; + let has_var = Int32.logand flags 0x40l <> 0l in + let align = Int32.(to_int (logand flags 0x3fl)) in + require (I32.lt_u flags 0x80l) s pos "invalid memop flags"; let offset = vu32 s in - let x = if bit 6 flags then at var s else Source.(0l @@ no_region) in + let x = if has_var then at var s else Source.(0l @@ no_region) in x, align, offset let rec instr s = diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 7a7ddcd34..78e2eecff 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -86,13 +86,6 @@ let encode m = patch s (p + 3) (lsb ((n lsr 21) lor 0x80)); patch s (p + 4) (lsb (n lsr 28)) - let bits i j n flags = - let w = Int32.(shift_left (of_int n) i) in - assert (Int32.(logand flags (shift_left (-1l) (j + 1))) = 0l); - Int32.logor w flags - - let bit i b flags = bits i i (if b then 1 else 0) flags - (* Types *) open Types @@ -145,10 +138,12 @@ let encode m = let var x = vu32 x.it let memop x {align; offset; _} = - let flags = bit 6 (x.it <> 0l) (bits 0 5 align 0l) in + let has_var = x.it <> 0l in + let flags = + Int32.(logor (of_int align) (if has_var then 0x40l else 0x00l)) in vu32 flags; vu32 offset; - if x.it <> 0l then var x + if has_var then var x let rec instr e = match e.it with From e810a177246c592d30fd99319199d00faa6560f5 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 11 Nov 2019 07:10:23 +0100 Subject: [PATCH 018/181] Adjust README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8e89bedb..d1d982ed8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Multi Memory Proposal for WebAssembly This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). -It is meant for discussion, prototype specification and implementation of a proposal to add support for returning multiple values to WebAssembly. +It is meant for discussion, prototype specification and implementation of a proposal to add support for multiple memories to WebAssembly. * See the [overview](proposals/multi-memory/Overview.md) for a summary of the proposal. From 307d9ef35f3aeae2191763ff3546097c7fd63288 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 3 Feb 2020 13:34:13 +0100 Subject: [PATCH 019/181] Isolation --- proposals/multi-memory/Overview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 66b36eb53..56e67892b 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -13,6 +13,8 @@ There are a number of use case scenarios for using multiple memories in a single * *Security.* A module may want to separate public memory that is shared with the outside to exchange data, from private memory that is kept encapsulated inside the module. +* *Isolation.* Even internal to a single module it is beneficial to have both and be able separate memory that is shared between multiple threads from memory used in a single-threaded manner. + * *Persistence.* An application may want to keep some of its memory state persistent between runs, e.g., by storing it in a file. But it may not want to do that for all its memory, so separating lifetimes via multiple memories is a natural setup. * *Linking.* There are a number of tools out there that can merge multiple Wasm modules into one, as a form of static linking. This is possible in almost all cases, except when the set of modules defines more than one memory. Allowing multiple memories in a single module closes this unfortunate gap. From 768400e8c25141357f3efa750d940ac8684b1b22 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 17 Jun 2020 09:33:28 +0200 Subject: [PATCH 020/181] Update syntax for elem/data to match bulk proposal (#12) --- interpreter/text/arrange.ml | 8 ++++---- interpreter/text/parser.mly | 8 ++++---- test/core/data.wast | 16 ++++++++-------- test/core/elem.wast | 16 ++++++++-------- test/core/imports.wast | 8 ++++---- test/core/load.wast | 4 ++-- test/core/store.wast | 4 ++-- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index d9ad6e5a7..eda7d2f5f 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -290,15 +290,15 @@ let memory off i mem = let {mtype = MemoryType lim} = mem.it in Node ("memory $" ^ nat (off + i) ^ " " ^ limits nat32 lim, []) -let segment head dat seg = +let segment head category dat seg = let {index; offset; init} = seg.it in - Node (head, atom var index :: Node ("offset", const offset) :: dat init) + Node (head, Node (category, [atom var index]) :: Node ("offset", const offset) :: dat init) let elems seg = - segment "elem" (list (atom var)) seg + segment "elem" "table" (list (atom var)) seg let data seg = - segment "data" break_bytes seg + segment "data" "memory" break_bytes seg (* Modules *) diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index 976328d59..72ad55207 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -558,9 +558,9 @@ offset : | expr { let at = at () in fun c -> $1 c @@ at } /* Sugar */ elem : - | LPAR ELEM var offset var_list RPAR + | LPAR ELEM LPAR TABLE var RPAR offset var_list RPAR { let at = at () in - fun c -> {index = $3 c table; offset = $4 c; init = $5 c func} @@ at } + fun c -> {index = $5 c table; offset = $7 c; init = $8 c func} @@ at } | LPAR ELEM offset var_list RPAR /* Sugar */ { let at = at () in fun c -> {index = 0l @@ at; offset = $3 c; init = $4 c func} @@ at } @@ -590,9 +590,9 @@ table_fields : [], [] } data : - | LPAR DATA var offset string_list RPAR + | LPAR DATA LPAR MEMORY var RPAR offset string_list RPAR { let at = at () in - fun c -> {index = $3 c memory; offset = $4 c; init = $5} @@ at } + fun c -> {index = $5 c memory; offset = $7 c; init = $8} @@ at } | LPAR DATA offset string_list RPAR /* Sugar */ { let at = at () in fun c -> {index = 0l @@ at; offset = $3 c; init = $4} @@ at } diff --git a/test/core/data.wast b/test/core/data.wast index 32d05f5e8..a651c1178 100644 --- a/test/core/data.wast +++ b/test/core/data.wast @@ -8,14 +8,14 @@ (data (i32.const 1) "a" "" "bcd") (data (offset (i32.const 0))) (data (offset (i32.const 0)) "" "a" "bc" "") - (data 0 (i32.const 0)) - (data 0x0 (i32.const 1) "a" "" "bcd") - (data 0x000 (offset (i32.const 0))) - (data 0 (offset (i32.const 0)) "" "a" "bc" "") - (data $m (i32.const 0)) - (data $m (i32.const 1) "a" "" "bcd") - (data $m (offset (i32.const 0))) - (data $m (offset (i32.const 0)) "" "a" "bc" "") + (data (memory 0) (i32.const 0)) + (data (memory 0x0) (i32.const 1) "a" "" "bcd") + (data (memory 0x000) (offset (i32.const 0))) + (data (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data (memory $m) (i32.const 0)) + (data (memory $m) (i32.const 1) "a" "" "bcd") + (data (memory $m) (offset (i32.const 0))) + (data (memory $m) (offset (i32.const 0)) "" "a" "bc" "") ) ;; Basic use diff --git a/test/core/elem.wast b/test/core/elem.wast index 261f6bb0b..c39030f21 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast @@ -8,14 +8,14 @@ (elem (i32.const 0) $f $f) (elem (offset (i32.const 0))) (elem (offset (i32.const 0)) $f $f) - (elem 0 (i32.const 0)) - (elem 0x0 (i32.const 0) $f $f) - (elem 0x000 (offset (i32.const 0))) - (elem 0 (offset (i32.const 0)) $f $f) - (elem $t (i32.const 0)) - (elem $t (i32.const 0) $f $f) - (elem $t (offset (i32.const 0))) - (elem $t (offset (i32.const 0)) $f $f) + (elem (table 0) (i32.const 0)) + (elem (table 0x0) (i32.const 0) $f $f) + (elem (table 0x000) (offset (i32.const 0))) + (elem (table 0) (offset (i32.const 0)) $f $f) + (elem (table $t) (i32.const 0)) + (elem (table $t) (i32.const 0) $f $f) + (elem (table $t) (offset (i32.const 0))) + (elem (table $t) (offset (i32.const 0)) $f $f) ) ;; Basic use diff --git a/test/core/imports.wast b/test/core/imports.wast index cdfc8c58b..abd03e88c 100644 --- a/test/core/imports.wast +++ b/test/core/imports.wast @@ -271,7 +271,7 @@ (module (type (func (result i32))) (import "spectest" "table" (table 10 20 funcref)) - (elem 0 (i32.const 1) $f $g) + (elem (table 0) (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) (call_indirect (type 0) (local.get 0)) @@ -290,7 +290,7 @@ (module (type (func (result i32))) (table (import "spectest" "table") 10 20 funcref) - (elem 0 (i32.const 1) $f $g) + (elem (table 0) (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) (call_indirect (type 0) (local.get 0)) @@ -380,7 +380,7 @@ (module (import "spectest" "memory" (memory 1 2)) - (data 0 (i32.const 10) "\10") + (data (memory 0) (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) @@ -392,7 +392,7 @@ (module (memory (import "spectest" "memory") 1 2) - (data 0 (i32.const 10) "\10") + (data (memory 0) (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) diff --git a/test/core/load.wast b/test/core/load.wast index 2821cfa36..c8f1a2491 100644 --- a/test/core/load.wast +++ b/test/core/load.wast @@ -9,8 +9,8 @@ (memory $mem1 (import "M" "mem") 2) (memory $mem2 3) - (data $mem1 (i32.const 20) "\01\02\03\04\05") - (data $mem2 (i32.const 50) "\0A\0B\0C\0D\0E") + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") (func (export "read1") (param i32) (result i32) (i32.load8_u $mem1 (local.get 0)) diff --git a/test/core/store.wast b/test/core/store.wast index 935232760..5bdd0c660 100644 --- a/test/core/store.wast +++ b/test/core/store.wast @@ -9,8 +9,8 @@ (memory $mem1 (import "M" "mem") 2) (memory $mem2 3) - (data $mem1 (i32.const 20) "\01\02\03\04\05") - (data $mem2 (i32.const 50) "\0A\0B\0C\0D\0E") + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") (func (export "read1") (param i32) (result i32) (i32.load8_u $mem1 (local.get 0)) From f806a562bbbc64f6fbc51b0c505a3ed0ebf01483 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 5 Aug 2020 17:27:48 +0200 Subject: [PATCH 021/181] [spec] Cherry-pick text format change from bulk-ops proposal (#14) --- document/core/text/modules.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/document/core/text/modules.rst b/document/core/text/modules.rst index 12c8e309d..dae550c0e 100644 --- a/document/core/text/modules.rst +++ b/document/core/text/modules.rst @@ -475,7 +475,7 @@ Element segments allow for an optional :ref:`table index ` to ide .. math:: \begin{array}{llclll} \production{element segment} & \Telem_I &::=& - \text{(}~\text{elem}~~x{:}\Ttableidx_I~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~y^\ast{:}\Tvec(\Tfuncidx_I)~\text{)} \\ &&& \qquad + \text{(}~\text{elem}~~\text{(}~table~~x{:}\Ttableidx_I~\text{)}~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~y^\ast{:}\Tvec(\Tfuncidx_I)~\text{)} \\ &&& \qquad \Rightarrow\quad \{ \ETABLE~x, \EOFFSET~e, \EINIT~y^\ast \} \\ \end{array} @@ -503,7 +503,7 @@ Also, the table index can be omitted, defaulting to :math:`\T{0}`. \production{element segment} & \text{(}~\text{elem}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} &\equiv& - \text{(}~\text{elem}~~0~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} + \text{(}~\text{elem}~~\text{(}~table~~0~\text{)}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} \end{array} As another abbreviation, element segments may also be specified inline with :ref:`table ` definitions; see the respective section. @@ -525,7 +525,7 @@ The data is written as a :ref:`string `, which may be split up into .. math:: \begin{array}{llclll} \production{data segment} & \Tdata_I &::=& - \text{(}~\text{data}~~x{:}\Tmemidx_I~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~b^\ast{:}\Tdatastring~\text{)} \\ &&& \qquad + \text{(}~\text{data}~~\text{(}~\text{memory}~~x{:}\Tmemidx_I~\text{)}~~\text{(}~\text{offset}~~e{:}\Texpr_I~\text{)}~~b^\ast{:}\Tdatastring~\text{)} \\ &&& \qquad \Rightarrow\quad \{ \DMEM~x', \DOFFSET~e, \DINIT~b^\ast \} \\[1ex] \production{data string} & \Tdatastring &::=& (b^\ast{:}\Tstring)^\ast \quad\Rightarrow\quad \concat((b^\ast)^\ast) \\ @@ -555,7 +555,7 @@ Also, the memory index can be omitted, defaulting to :math:`\T{0}`. \production{data segment} & \text{(}~\text{data}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} &\equiv& - \text{(}~\text{data}~~0~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} + \text{(}~\text{data}~~\text{(}~\text{memory}~0~\text{)}~~\text{(}~\text{offset}~~\Texpr_I~\text{)}~~\dots~\text{)} \end{array} As another abbreviation, data segments may also be specified inline with :ref:`memory ` definitions; see the respective section. From c5e1773ad07cc8143aa6c8e4fd814f3d53a09d7a Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 16 Feb 2021 16:45:29 -0800 Subject: [PATCH 022/181] Add initial overview (#1) --- README.md | 13 ++++++- proposals/extended-const/Overview.md | 52 ++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 proposals/extended-const/Overview.md diff --git a/README.md b/README.md index 83cdc4da6..8d0e88791 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ -[![Build Status](https://travis-ci.org/WebAssembly/spec.svg?branch=master)](https://travis-ci.org/WebAssembly/spec) +[![Build Status](https://travis-ci.org/WebAssembly/extended-const.svg?branch=master)](https://travis-ci.org/WebAssembly/extended-const) + +# Extented Const Expressesions Proposal for WebAssembly + +This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). +It is meant for discussion, prototype specification and implementation of a proposal to add tail call support to WebAssembly. + +* See the [overview](proposals/extended-const/Overview.md) for a summary of the proposal. + +* See the [modified spec](https://webassembly.github.io/extended-const/core/) for details. + +Original `README` from upstream repository follows... # spec diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md new file mode 100644 index 000000000..b38330314 --- /dev/null +++ b/proposals/extended-const/Overview.md @@ -0,0 +1,52 @@ +# Extended Constant Expressions + +## Introduction + +This page describes a proposal for extending constant expressions in +WebAssembly. The current [spec][] for constant expressions is fairly limited, +and was always intended to be extended. + +This proposal adds new instructions to the list of *constant instructions* that +can be used in *constant expressions*. + +An overview of this proposal was presented at the 01-19-20 CG meeting along with +a brief [presentation][]. This issue was originally discusses in +https://github.com/WebAssembly/design/issues/1392. + +### Motivation + +The primay/initial motivation comes from LLVM where we could benefit from using +integer addition in both global initializers and in segment initializers. Both +of these use cases stem from dynamic linking, which is currently +[experimental][abi]. + +1. With dynamic linking the data segments are relative to a global import called + `__memory_base` which is supplied by the dynamic linker. We currently have + to have [combine][] all our memory segments into one because there is no way + to do `__memory_base + CONST_OFFSET` in a segment initilizer. + +2. The linker currently has to generate [dynamic relocations][reloc] for certain + WebAssembly globals because its currently not possible to initialize a global + with a value of `__memory_base + CONST_OFFSET`. Specifically, this happens + when the static linker decides that a given symbol is local to the currently + module. In this case, rather than importing a global it creates a new + global which points insides the a data segment (i.e. it's value is an offset + from `__memory_base` or `__table_base` which are themselves imported). + +## New Instructions + +This proposal adds the following new instructions to the list of valid constant +instruction: + + - `i32.add` + - `i32.sub` + - `i64.add` + - `i64.sub` + - `i32.mul` + - `i64.mul` + +[spec]: https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions +[presentation]: https://docs.google.com/presentation/d/1sM9mJJ6iM7D8324ipYxot91hSKnWCtB8jX4Kh3bde5E +[abi]: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md +[combine]: https://github.com/llvm/llvm-project/blob/5f9be2c3e37c0428ba56876dd84af04b8d9d8915/lld/wasm/Writer.cpp#L868 +[reloc]: https://github.com/llvm/llvm-project/blob/5f9be2c3e37c0428ba56876dd84af04b8d9d8915/lld/wasm/SyntheticSections.cpp#L311 From 5c4f381d7d59d71ea57d67ff89d5e574466f215e Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 17 Feb 2021 11:03:31 -0800 Subject: [PATCH 023/181] Add initial tests and interpreter implementation (#2) --- interpreter/valid/valid.ml | 2 + proposals/extended-const/Overview.md | 2 +- test/core/data.wast | 34 +++++++++++++++- test/core/global.wast | 61 +++++++++++++++++++--------- 4 files changed, 78 insertions(+), 21 deletions(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 7dd573b54..25a65f599 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -382,6 +382,8 @@ let check_func (c : context) (f : func) = let is_const (c : context) (e : instr) = match e.it with | Const _ -> true + | Binary (Values.I32 I32Op.(Add | Sub | Mul)) -> true + | Binary (Values.I64 I64Op.(Add | Sub | Mul)) -> true | GlobalGet x -> let GlobalType (_, mut) = global c x in mut = Immutable | _ -> false diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md index b38330314..107779093 100644 --- a/proposals/extended-const/Overview.md +++ b/proposals/extended-const/Overview.md @@ -40,9 +40,9 @@ instruction: - `i32.add` - `i32.sub` + - `i32.mul` - `i64.add` - `i64.sub` - - `i32.mul` - `i64.mul` [spec]: https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions diff --git a/test/core/data.wast b/test/core/data.wast index e840a9467..15f37e371 100644 --- a/test/core/data.wast +++ b/test/core/data.wast @@ -156,6 +156,38 @@ (data (i32.const 1) "a") ) +;; Extended contant expressions + +(module + (memory 1) + (data (i32.add (i32.const 0) (i32.const 42))) +) + +(module + (memory 1) + (data (i32.sub (i32.const 42) (i32.const 0))) +) + +(module + (memory 1) + (data (i32.mul (i32.const 1) (i32.const 2))) +) + +;; Combining add, sub, mul and global.get + +(module + (global (import "spectest" "global_i32") i32) + (memory 1) + (data (i32.mul + (i32.const 2) + (i32.add + (i32.sub (global.get 0) (i32.const 1)) + (i32.const 2) + ) + ) + ) +) + ;; Invalid bounds for data (assert_unlinkable @@ -455,4 +487,4 @@ (data (global.get 0)) ) "constant expression required" -) \ No newline at end of file +) diff --git a/test/core/global.wast b/test/core/global.wast index 55d7447b1..4f36df71e 100644 --- a/test/core/global.wast +++ b/test/core/global.wast @@ -1,29 +1,46 @@ ;; Test globals (module + (global (import "spectest" "global_i32") i32) + (global (import "spectest" "global_i64") i64) + (global $a i32 (i32.const -2)) - (global (;1;) f32 (f32.const -3)) - (global (;2;) f64 (f64.const -4)) + (global (;3;) f32 (f32.const -3)) + (global (;4;) f64 (f64.const -4)) (global $b i64 (i64.const -5)) (global $x (mut i32) (i32.const -12)) - (global (;5;) (mut f32) (f32.const -13)) - (global (;6;) (mut f64) (f64.const -14)) + (global (;7;) (mut f32) (f32.const -13)) + (global (;8;) (mut f64) (f64.const -14)) (global $y (mut i64) (i64.const -15)) + (global $z1 i32 (global.get 0)) + (global $z2 i64 (global.get 1)) + (global $z3 i32 (i32.add (i32.sub (i32.mul (i32.const 20) (i32.const 2)) (i32.const 2)) (i32.const 4))) + (global $z4 i64 (i64.add (i64.sub (i64.mul (i64.const 20) (i64.const 2)) (i64.const 2)) (i64.const 5))) + (global $z5 i32 (i32.add (global.get 0) (i32.const 42))) + (global $z6 i64 (i64.add (global.get 1) (i64.const 42))) + + (func (export "get-a") (result i32) (global.get $a)) (func (export "get-b") (result i64) (global.get $b)) (func (export "get-x") (result i32) (global.get $x)) (func (export "get-y") (result i64) (global.get $y)) + (func (export "get-z1") (result i32) (global.get $z1)) + (func (export "get-z2") (result i64) (global.get $z2)) + (func (export "get-z3") (result i32) (global.get $z3)) + (func (export "get-z4") (result i64) (global.get $z4)) + (func (export "get-z5") (result i32) (global.get $z5)) + (func (export "get-z6") (result i64) (global.get $z6)) (func (export "set-x") (param i32) (global.set $x (local.get 0))) (func (export "set-y") (param i64) (global.set $y (local.get 0))) - (func (export "get-1") (result f32) (global.get 1)) - (func (export "get-2") (result f64) (global.get 2)) - (func (export "get-5") (result f32) (global.get 5)) - (func (export "get-6") (result f64) (global.get 6)) - (func (export "set-5") (param f32) (global.set 5 (local.get 0))) - (func (export "set-6") (param f64) (global.set 6 (local.get 0))) + (func (export "get-3") (result f32) (global.get 3)) + (func (export "get-4") (result f64) (global.get 4)) + (func (export "get-7") (result f32) (global.get 7)) + (func (export "get-8") (result f64) (global.get 8)) + (func (export "set-7") (param f32) (global.set 7 (local.get 0))) + (func (export "set-8") (param f64) (global.set 8 (local.get 0))) ;; As the argument of control constructs and instructions @@ -182,21 +199,27 @@ (assert_return (invoke "get-b") (i64.const -5)) (assert_return (invoke "get-x") (i32.const -12)) (assert_return (invoke "get-y") (i64.const -15)) - -(assert_return (invoke "get-1") (f32.const -3)) -(assert_return (invoke "get-2") (f64.const -4)) -(assert_return (invoke "get-5") (f32.const -13)) -(assert_return (invoke "get-6") (f64.const -14)) +(assert_return (invoke "get-z1") (i32.const 666)) +(assert_return (invoke "get-z2") (i64.const 666)) +(assert_return (invoke "get-z3") (i32.const 42)) +(assert_return (invoke "get-z4") (i64.const 43)) +(assert_return (invoke "get-z5") (i32.const 708)) +(assert_return (invoke "get-z6") (i64.const 708)) + +(assert_return (invoke "get-3") (f32.const -3)) +(assert_return (invoke "get-4") (f64.const -4)) +(assert_return (invoke "get-7") (f32.const -13)) +(assert_return (invoke "get-8") (f64.const -14)) (assert_return (invoke "set-x" (i32.const 6))) (assert_return (invoke "set-y" (i64.const 7))) -(assert_return (invoke "set-5" (f32.const 8))) -(assert_return (invoke "set-6" (f64.const 9))) +(assert_return (invoke "set-7" (f32.const 8))) +(assert_return (invoke "set-8" (f64.const 9))) (assert_return (invoke "get-x") (i32.const 6)) (assert_return (invoke "get-y") (i64.const 7)) -(assert_return (invoke "get-5") (f32.const 8)) -(assert_return (invoke "get-6") (f64.const 9)) +(assert_return (invoke "get-7") (f32.const 8)) +(assert_return (invoke "get-8") (f64.const 9)) (assert_return (invoke "as-select-first") (i32.const 6)) (assert_return (invoke "as-select-mid") (i32.const 2)) From da162d878b591155dd37c537b0eeee00b87edce8 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 18 Feb 2021 08:28:26 -0800 Subject: [PATCH 024/181] Feedback from #2 (#3) --- interpreter/valid/valid.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 25a65f599..213db23ac 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -381,8 +381,8 @@ let check_func (c : context) (f : func) = let is_const (c : context) (e : instr) = match e.it with - | Const _ -> true - | Binary (Values.I32 I32Op.(Add | Sub | Mul)) -> true + | Const _ + | Binary (Values.I32 I32Op.(Add | Sub | Mul)) | Binary (Values.I64 I64Op.(Add | Sub | Mul)) -> true | GlobalGet x -> let GlobalType (_, mut) = global c x in mut = Immutable | _ -> false From 6876ee803d266adee2f7a703147427d77f518656 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 28 Jun 2021 09:15:37 +0200 Subject: [PATCH 025/181] Fix merge artefact --- README.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.md b/README.md index ecf80ff30..652d63639 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD [![Build Status](https://travis-ci.org/WebAssembly/multi-memory.svg?branch=master)](https://travis-ci.org/WebAssembly/multi-memory) # Multi Memory Proposal for WebAssembly @@ -11,22 +10,6 @@ It is meant for discussion, prototype specification and implementation of a prop * See the [modified spec](https://webassembly.github.io/multi-memory/) for details. Original `README` from upstream repository follows… -======= -[![Build Status](https://travis-ci.org/WebAssembly/reference-types.svg?branch=master)](https://travis-ci.org/WebAssembly/reference-types) - -# Reference Types Proposal for WebAssembly - -This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). -It is meant for discussion, prototype specification and implementation of a proposal to add support for basic reference types to WebAssembly. - -* See the [overview](proposals/reference-types/Overview.md) for a summary of the proposal. - -* See the [modified spec](https://webassembly.github.io/reference-types/core/) for details. - -The repository is now based on the [bulk operations proposal](proposals/bulk-memory-operations/Overview.md) and includes all respective changes. - -Original README from upstream repository follows... ->>>>>>> reftype/master # spec From 0ea57799110ef3df3ced4626ad07e1b18b59b452 Mon Sep 17 00:00:00 2001 From: Yuhan Deng <31569419+yhdengh@users.noreply.github.com> Date: Wed, 13 Oct 2021 06:02:16 -0700 Subject: [PATCH 026/181] Import wasmtime multi-memory test (#22) --- test/core/multimemory.wast | 163 +++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 test/core/multimemory.wast diff --git a/test/core/multimemory.wast b/test/core/multimemory.wast new file mode 100644 index 000000000..6fef86abd --- /dev/null +++ b/test/core/multimemory.wast @@ -0,0 +1,163 @@ +;; From wasmtime misc_testsuite/multi-memory/simple.wast + +(module + (memory $m1 1) + (memory $m2 1) + + (func (export "store1") (param i32 i64) + local.get 0 + local.get 1 + i64.store (memory $m1)) + + (func (export "store2") (param i32 i64) + local.get 0 + local.get 1 + i64.store (memory $m2)) + + (func (export "load1") (param i32) (result i64) + local.get 0 + i64.load (memory $m1)) + + (func (export "load2") (param i32) (result i64) + local.get 0 + i64.load (memory $m2)) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + +(module $a + (memory (export "mem") 1) + + (func (export "store") (param i32 i64) + local.get 0 + local.get 1 + i64.store) + + (func (export "load") (param i32) (result i64) + local.get 0 + i64.load) +) + +(module $b + (memory (export "mem") 1) + + (func (export "store") (param i32 i64) + local.get 0 + local.get 1 + i64.store) + + (func (export "load") (param i32) (result i64) + local.get 0 + i64.load) +) + +(invoke $a "store" (i32.const 0) (i64.const 1)) +(invoke $b "store" (i32.const 0) (i64.const 2)) +(assert_return (invoke $a "load" (i32.const 0)) (i64.const 1)) +(assert_return (invoke $b "load" (i32.const 0)) (i64.const 2)) + +(module $c + (import "a" "mem" (memory $m1 1)) + (import "b" "mem" (memory $m2 1)) + + (func (export "store1") (param i32 i64) + local.get 0 + local.get 1 + i64.store (memory $m1)) + + (func (export "store2") (param i32 i64) + local.get 0 + local.get 1 + i64.store (memory $m2)) + + (func (export "load1") (param i32) (result i64) + local.get 0 + i64.load (memory $m1)) + + (func (export "load2") (param i32) (result i64) + local.get 0 + i64.load (memory $m2)) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) + +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + +(module + (memory $m1 1) + (memory $m2 2) + + (func (export "grow1") (param i32) (result i32) + local.get 0 + memory.grow (memory $m1)) + + (func (export "grow2") (param i32) (result i32) + local.get 0 + memory.grow (memory $m2)) + + (func (export "size1") (result i32) memory.size $m1) + (func (export "size2") (result i32) memory.size $m2) +) + +(assert_return (invoke "size1") (i32.const 1)) +(assert_return (invoke "size2") (i32.const 2)) +(assert_return (invoke "grow1" (i32.const 3)) (i32.const 1)) +(assert_return (invoke "grow1" (i32.const 4)) (i32.const 4)) +(assert_return (invoke "grow1" (i32.const 1)) (i32.const 8)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 3)) + +(module + (memory $m1 1) + (memory $m2 1) + + (func (export "init1") (result i32) + i32.const 1 + i32.const 0 + i32.const 4 + memory.init $d $m1 + i32.const 1 + i32.load) + + (func (export "init2") (result i32) + i32.const 1 + i32.const 4 + i32.const 4 + memory.init $d $m2 + i32.const 1 + i32.load (memory $m2)) + + (data $d "\01\00\00\00" "\02\00\00\00") +) + +(assert_return (invoke "init1") (i32.const 1)) +(assert_return (invoke "init2") (i32.const 2)) + +(module + (memory $m1 1) + (memory $m2 1) + + (func (export "fill1") (result i32) + i32.const 1 + i32.const 0x01 + i32.const 4 + memory.fill $m1 + i32.const 1 + i32.load) + + (func (export "fill2") (result i32) + i32.const 1 + i32.const 0x02 + i32.const 2 + memory.fill $m2 + i32.const 1 + i32.load (memory $m2)) +) + +(assert_return (invoke "fill1") (i32.const 0x01010101)) +(assert_return (invoke "fill2") (i32.const 0x0202)) From 7af14f8752b1f57eabd2ab32be625b3d60e41983 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 13 Oct 2021 15:41:28 +0200 Subject: [PATCH 027/181] Fix test (#23) --- test/core/load.wast | 29 +++++++ test/core/memory-multi.wast | 42 ++++++++++ test/core/memory_grow.wast | 26 ++++++ test/core/multimemory.wast | 163 ------------------------------------ test/core/store.wast | 79 +++++++++++++++++ 5 files changed, 176 insertions(+), 163 deletions(-) create mode 100644 test/core/memory-multi.wast delete mode 100644 test/core/multimemory.wast diff --git a/test/core/load.wast b/test/core/load.wast index c8f1a2491..9fe48e2b4 100644 --- a/test/core/load.wast +++ b/test/core/load.wast @@ -1,7 +1,30 @@ ;; Multiple memories (module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (data (memory $mem1) (i32.const 0) "\01") + (data (memory $mem2) (i32.const 0) "\02") +) + +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + +(module $M (memory (export "mem") 2) + + (func (export "read") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) ) (register "M") @@ -20,6 +43,12 @@ ) ) +(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) + (assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) (assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) (assert_return (invoke "read1" (i32.const 22)) (i32.const 3)) diff --git a/test/core/memory-multi.wast b/test/core/memory-multi.wast new file mode 100644 index 000000000..b5b71fd9e --- /dev/null +++ b/test/core/memory-multi.wast @@ -0,0 +1,42 @@ +;; From wasmtime misc_testsuite/multi-memory/simple.wast + +;; Should be replaced with suitable extensions to ../meta/generate_memory_*.js + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "init1") (result i32) + (memory.init $mem1 $d (i32.const 1) (i32.const 0) (i32.const 4)) + (i32.load $mem1 (i32.const 1)) + ) + + (func (export "init2") (result i32) + (memory.init $mem2 $d (i32.const 1) (i32.const 4) (i32.const 4)) + (i32.load $mem2 (i32.const 1)) + ) + + (data $d "\01\00\00\00" "\02\00\00\00") +) + +(assert_return (invoke "init1") (i32.const 1)) +(assert_return (invoke "init2") (i32.const 2)) + + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "fill1") (result i32) + (memory.fill $mem1 (i32.const 1) (i32.const 0x01) (i32.const 4)) + (i32.load $mem1 (i32.const 1)) + ) + + (func (export "fill2") (result i32) + (memory.fill $mem2 (i32.const 1) (i32.const 0x02) (i32.const 2)) + (i32.load $mem2 (i32.const 1)) + ) +) + +(assert_return (invoke "fill1") (i32.const 0x01010101)) +(assert_return (invoke "fill2") (i32.const 0x0202)) diff --git a/test/core/memory_grow.wast b/test/core/memory_grow.wast index 5a409b2de..4b6dbc838 100644 --- a/test/core/memory_grow.wast +++ b/test/core/memory_grow.wast @@ -399,6 +399,32 @@ (assert_return (invoke "as-memory.grow-size") (i32.const 1)) +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 2) + + (func (export "grow1") (param i32) (result i32) + (memory.grow $mem1 (local.get 0)) + ) + (func (export "grow2") (param i32) (result i32) + (memory.grow $mem2 (local.get 0)) + ) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) +) + +(assert_return (invoke "size1") (i32.const 1)) +(assert_return (invoke "size2") (i32.const 2)) +(assert_return (invoke "grow1" (i32.const 3)) (i32.const 1)) +(assert_return (invoke "grow1" (i32.const 4)) (i32.const 4)) +(assert_return (invoke "grow1" (i32.const 1)) (i32.const 8)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 3)) + + ;; Type mismatches (assert_invalid diff --git a/test/core/multimemory.wast b/test/core/multimemory.wast deleted file mode 100644 index 6fef86abd..000000000 --- a/test/core/multimemory.wast +++ /dev/null @@ -1,163 +0,0 @@ -;; From wasmtime misc_testsuite/multi-memory/simple.wast - -(module - (memory $m1 1) - (memory $m2 1) - - (func (export "store1") (param i32 i64) - local.get 0 - local.get 1 - i64.store (memory $m1)) - - (func (export "store2") (param i32 i64) - local.get 0 - local.get 1 - i64.store (memory $m2)) - - (func (export "load1") (param i32) (result i64) - local.get 0 - i64.load (memory $m1)) - - (func (export "load2") (param i32) (result i64) - local.get 0 - i64.load (memory $m2)) -) - -(invoke "store1" (i32.const 0) (i64.const 1)) -(invoke "store2" (i32.const 0) (i64.const 2)) -(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) -(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) - -(module $a - (memory (export "mem") 1) - - (func (export "store") (param i32 i64) - local.get 0 - local.get 1 - i64.store) - - (func (export "load") (param i32) (result i64) - local.get 0 - i64.load) -) - -(module $b - (memory (export "mem") 1) - - (func (export "store") (param i32 i64) - local.get 0 - local.get 1 - i64.store) - - (func (export "load") (param i32) (result i64) - local.get 0 - i64.load) -) - -(invoke $a "store" (i32.const 0) (i64.const 1)) -(invoke $b "store" (i32.const 0) (i64.const 2)) -(assert_return (invoke $a "load" (i32.const 0)) (i64.const 1)) -(assert_return (invoke $b "load" (i32.const 0)) (i64.const 2)) - -(module $c - (import "a" "mem" (memory $m1 1)) - (import "b" "mem" (memory $m2 1)) - - (func (export "store1") (param i32 i64) - local.get 0 - local.get 1 - i64.store (memory $m1)) - - (func (export "store2") (param i32 i64) - local.get 0 - local.get 1 - i64.store (memory $m2)) - - (func (export "load1") (param i32) (result i64) - local.get 0 - i64.load (memory $m1)) - - (func (export "load2") (param i32) (result i64) - local.get 0 - i64.load (memory $m2)) -) - -(invoke "store1" (i32.const 0) (i64.const 1)) -(invoke "store2" (i32.const 0) (i64.const 2)) -(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) - -(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) - -(module - (memory $m1 1) - (memory $m2 2) - - (func (export "grow1") (param i32) (result i32) - local.get 0 - memory.grow (memory $m1)) - - (func (export "grow2") (param i32) (result i32) - local.get 0 - memory.grow (memory $m2)) - - (func (export "size1") (result i32) memory.size $m1) - (func (export "size2") (result i32) memory.size $m2) -) - -(assert_return (invoke "size1") (i32.const 1)) -(assert_return (invoke "size2") (i32.const 2)) -(assert_return (invoke "grow1" (i32.const 3)) (i32.const 1)) -(assert_return (invoke "grow1" (i32.const 4)) (i32.const 4)) -(assert_return (invoke "grow1" (i32.const 1)) (i32.const 8)) -(assert_return (invoke "grow2" (i32.const 1)) (i32.const 2)) -(assert_return (invoke "grow2" (i32.const 1)) (i32.const 3)) - -(module - (memory $m1 1) - (memory $m2 1) - - (func (export "init1") (result i32) - i32.const 1 - i32.const 0 - i32.const 4 - memory.init $d $m1 - i32.const 1 - i32.load) - - (func (export "init2") (result i32) - i32.const 1 - i32.const 4 - i32.const 4 - memory.init $d $m2 - i32.const 1 - i32.load (memory $m2)) - - (data $d "\01\00\00\00" "\02\00\00\00") -) - -(assert_return (invoke "init1") (i32.const 1)) -(assert_return (invoke "init2") (i32.const 2)) - -(module - (memory $m1 1) - (memory $m2 1) - - (func (export "fill1") (result i32) - i32.const 1 - i32.const 0x01 - i32.const 4 - memory.fill $m1 - i32.const 1 - i32.load) - - (func (export "fill2") (result i32) - i32.const 1 - i32.const 0x02 - i32.const 2 - memory.fill $m2 - i32.const 1 - i32.load (memory $m2)) -) - -(assert_return (invoke "fill1") (i32.const 0x01010101)) -(assert_return (invoke "fill2") (i32.const 0x0202)) diff --git a/test/core/store.wast b/test/core/store.wast index 5bdd0c660..86f6263af 100644 --- a/test/core/store.wast +++ b/test/core/store.wast @@ -1,5 +1,84 @@ ;; Multiple memories +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + +(module $M1 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M1") + +(module $M2 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M2") + +(invoke $M1 "store" (i32.const 0) (i64.const 1)) +(invoke $M2 "store" (i32.const 0) (i64.const 2)) +(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) + +(module + (memory $mem1 (import "M1" "mem") 1) + (memory $mem2 (import "M2" "mem") 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + (module (memory (export "mem") 2) ) From 5527fd97956f42615a2405b073d0f06f087953bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Fri, 29 Oct 2021 12:25:25 +0300 Subject: [PATCH 028/181] Fix typo in multi-memory/Overview.md (#24) --- proposals/multi-memory/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 56e67892b..6d3171d40 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -92,4 +92,4 @@ Hence, in current engines, reserving one register for the base address is a comm Multiple memories will typically require an extra indirection (which some engines already have). Engines could conservatively continue to optimise access to memory index 0 via a dedicated register. -PResumably, we could also eventually add a future custom section with optimisation hints, which could e.g. mark the index of the "main" memory. +Presumably, we could also eventually add a future custom section with optimisation hints, which could e.g. mark the index of the "main" memory. From 21326c56b00cfd44c9b0c9869b57e3a751ecf7b8 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 22 Nov 2021 14:17:58 +0100 Subject: [PATCH 029/181] Fix merge artefact --- document/js-api/index.bs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 6f2913eac..80704c428 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -1219,14 +1219,10 @@ In practice, an implementation may run out of resources for valid modules below
  • The maximum number of globals defined in a module is 1000000.
  • The maximum number of data segments defined in a module is 100000.
  • -<<<<<<< HEAD -
  • The maximum number of tables, including defined and imported tables, is 1.
  • -=======
  • The maximum number of tables, including declared or imported tables, is 100000.
  • The maximum size of a table is 10000000.
  • ->>>>>>> reftype/master
  • The maximum number of table entries in any table initialization is 10000000.
  • -
  • The maximum number of memories, including defined and imported memories, is 10000000.
  • +
  • The maximum number of memories, including defined and imported memories, is 1.
  • The maximum number of parameters to any function or block is 1000.
  • The maximum number of return values for any function or block is 1000.
  • From 170c9e3d999f84228584bb2e2e9410ac49cce21b Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 22 Nov 2021 14:18:54 +0100 Subject: [PATCH 030/181] Raise memory limit to 100 --- document/js-api/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 80704c428..ec2f1928e 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -1207,7 +1207,7 @@ Note: ECMAScript doesn't specify any sort of behavior on out-of-memory condition The WebAssembly core specification allows an implementation to define limits on the syntactic structure of the module. While each embedding of WebAssembly may choose to define its own limits, for predictability the standard WebAssembly JavaScript Interface described in this document defines the following exact limits. -An implementation must reject a module that exceeds one of the following limits with a {{CompileError}}: +An implementation must reject a module that exceeds one of the following limits with a {{CompileError}}. In practice, an implementation may run out of resources for valid modules below these limits.
      @@ -1222,7 +1222,7 @@ In practice, an implementation may run out of resources for valid modules below
    • The maximum number of tables, including declared or imported tables, is 100000.
    • The maximum size of a table is 10000000.
    • The maximum number of table entries in any table initialization is 10000000.
    • -
    • The maximum number of memories, including defined and imported memories, is 1.
    • +
    • The maximum number of memories, including defined and imported memories, is 100.
    • The maximum number of parameters to any function or block is 1000.
    • The maximum number of return values for any function or block is 1000.
    • From c5021190bab2080ae9771188f6e928fa207d5df3 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 25 Feb 2022 09:53:09 -0800 Subject: [PATCH 031/181] Add implementation status --- proposals/extended-const/Overview.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md index 107779093..1af0bb5e2 100644 --- a/proposals/extended-const/Overview.md +++ b/proposals/extended-const/Overview.md @@ -45,6 +45,13 @@ instruction: - `i64.sub` - `i64.mul` +## Implementation Status + +- spec interpreter: Done +- wabt: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) +- Firefox: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) +- v8: [WIP](https://bugs.chromium.org/p/v8/issues/detail?id=12089) + [spec]: https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions [presentation]: https://docs.google.com/presentation/d/1sM9mJJ6iM7D8324ipYxot91hSKnWCtB8jX4Kh3bde5E [abi]: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md From f7900e502aedc304ea4d59d09e1f6d27140ffed1 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 4 Mar 2022 09:43:31 -0800 Subject: [PATCH 032/181] Update v8 implementation status --- proposals/extended-const/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md index 1af0bb5e2..02933eab7 100644 --- a/proposals/extended-const/Overview.md +++ b/proposals/extended-const/Overview.md @@ -50,7 +50,7 @@ instruction: - spec interpreter: Done - wabt: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) - Firefox: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) -- v8: [WIP](https://bugs.chromium.org/p/v8/issues/detail?id=12089) +- v8: [Done](https://chromium.googlesource.com/v8/v8/+/bf1565d7081cabc510e39c42eaea67ea6e79484e) [spec]: https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions [presentation]: https://docs.google.com/presentation/d/1sM9mJJ6iM7D8324ipYxot91hSKnWCtB8jX4Kh3bde5E From f572e42a1757a416d7352550aab9dab9effb945d Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 27 Jun 2022 19:56:04 +0200 Subject: [PATCH 033/181] Switch order of load/store immediates in binary format --- interpreter/binary/decode.ml | 4 ++-- interpreter/binary/encode.ml | 4 ++-- proposals/multi-memory/Overview.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 5964b492a..3f72c57b5 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -210,11 +210,11 @@ let end_ s = expect 0x0b s "END opcode expected" let memop s = let pos = pos s in let flags = vu32 s in + require (I32.lt_u flags 0x80l) s pos "malformed memop flags"; let has_var = Int32.logand flags 0x40l <> 0l in + let x = if has_var then at var s else Source.(0l @@ no_region) in let align = Int32.(to_int (logand flags 0x3fl)) in - require (I32.lt_u flags 0x80l) s pos "malformed memop flags"; let offset = vu32 s in - let x = if has_var then at var s else Source.(0l @@ no_region) in x, align, offset let block_type s = diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 113b4ed50..5daa9c78a 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -148,8 +148,8 @@ struct let flags = Int32.(logor (of_int align) (if has_var then 0x40l else 0x00l)) in vu32 flags; - vu32 offset; - if has_var then var x + if has_var then var x; + vu32 offset let block_type = function | VarBlockType x -> vs33 x.it diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 6d3171d40..5829c0905 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -62,7 +62,7 @@ Execution: Binary format: -* For loads and stores: Reinterpret the alignment value in the `memarg` as a bitfield; if bit 6 (the MSB of the first LEB byte) is set, then an `i32` memory index follows after the offset immediate (even with SIMD, alignment must not currently be larger than 4 in the logarithmic encoding, i.e., taking up the lower 3 bits, so this is more than safe). +* For loads and stores: Reinterpret the alignment value in the `memarg` as a bitfield; if bit 6 (the MSB of the first LEB byte) is set, then an `i32` memory index follows after the alignment bitfield (even with SIMD, alignment must not currently be larger than 4 in the logarithmic encoding, i.e., taking up the lower 3 bits, so this is more than safe). * For other memory instructions: Replace the hard-coded `0x00` bytes with an `i32` memory index. From 8d42a7bfeb3383a618de18932beca96e401098bd Mon Sep 17 00:00:00 2001 From: Ashley Nelson Date: Mon, 25 Jul 2022 12:12:35 -0700 Subject: [PATCH 034/181] Specify Memory Copy changes The memory copy instruction is a bit of a special case because it can contain two indexes, representing the source memory index and destination memory index. The goal of this change is to explicitly name the rules for encoding and decoding memory copy, particularly for the text format. --- proposals/multi-memory/Overview.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 5829c0905..db7b19fa7 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -64,12 +64,16 @@ Binary format: * For loads and stores: Reinterpret the alignment value in the `memarg` as a bitfield; if bit 6 (the MSB of the first LEB byte) is set, then an `i32` memory index follows after the alignment bitfield (even with SIMD, alignment must not currently be larger than 4 in the logarithmic encoding, i.e., taking up the lower 3 bits, so this is more than safe). +* For copy, replace the two hard-coded `0x00` bytes with two `i32` memory indexes, representing the source memory index and destination memory index respectively. + * For other memory instructions: Replace the hard-coded `0x00` bytes with an `i32` memory index. Text format: * Add an optional `memidx` immediate that defaults to 0 if absent (for backwards compatibility). In the case of loads and stores, this index must occur before the optional alignment and offset immediates. +* In the case of copy, two optional `memidx` immediates are added, representing the source memory index and destination memory index respectively. These optional indexes must both be present to specify a source and destintaion memory, or both be absent to default to 0. + ### Modules From 43ab171fcd8201567bc2dfbdb3c0cf662bfc4971 Mon Sep 17 00:00:00 2001 From: Ashley Nelson Date: Mon, 25 Jul 2022 15:27:08 -0700 Subject: [PATCH 035/181] Update proposals/multi-memory/Overview.md Co-authored-by: Andreas Rossberg --- proposals/multi-memory/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index db7b19fa7..3d0522ca7 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -64,7 +64,7 @@ Binary format: * For loads and stores: Reinterpret the alignment value in the `memarg` as a bitfield; if bit 6 (the MSB of the first LEB byte) is set, then an `i32` memory index follows after the alignment bitfield (even with SIMD, alignment must not currently be larger than 4 in the logarithmic encoding, i.e., taking up the lower 3 bits, so this is more than safe). -* For copy, replace the two hard-coded `0x00` bytes with two `i32` memory indexes, representing the source memory index and destination memory index respectively. +* For copy, replace the two hard-coded `0x00` bytes with two `i32` memory indexes, denoting the destination and source memory, respectively. * For other memory instructions: Replace the hard-coded `0x00` bytes with an `i32` memory index. From 8bae4d847bf5ba608745cdcf08c82c312bafb898 Mon Sep 17 00:00:00 2001 From: Ashley Nelson Date: Mon, 25 Jul 2022 15:27:13 -0700 Subject: [PATCH 036/181] Update proposals/multi-memory/Overview.md Co-authored-by: Andreas Rossberg --- proposals/multi-memory/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/multi-memory/Overview.md b/proposals/multi-memory/Overview.md index 3d0522ca7..abf7c12bc 100644 --- a/proposals/multi-memory/Overview.md +++ b/proposals/multi-memory/Overview.md @@ -72,7 +72,7 @@ Text format: * Add an optional `memidx` immediate that defaults to 0 if absent (for backwards compatibility). In the case of loads and stores, this index must occur before the optional alignment and offset immediates. -* In the case of copy, two optional `memidx` immediates are added, representing the source memory index and destination memory index respectively. These optional indexes must both be present to specify a source and destintaion memory, or both be absent to default to 0. +* In the case of copy, two optional `memidx` immediates are added, denoting the destination and source memory, respectively. These optional indexes must both be present to specify a source and destintaion memory, or both be absent to default to 0. ### Modules From 406efbc6dbead3dc123ae881796ba67cb6b2a456 Mon Sep 17 00:00:00 2001 From: YiYing He Date: Fri, 12 Aug 2022 02:37:44 +0800 Subject: [PATCH 037/181] Update spec for the load/store immediates binary format change. Signed-off-by: YiYing He --- document/core/binary/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 05f04ba3d..151e7e591 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -198,7 +198,7 @@ Each variant of :ref:`memory instruction ` is encoded with \production{memory argument} & \Bmemarg &::=& a{:}\Bu32~~o{:}\Bu32 &\Rightarrow& 0~\{ \ALIGN~a,~\OFFSET~o \} & (\iff a < 2^6) \\ &&|& - a{:}\Bu32~~o{:}\Bu32~~x{:}\memidx &\Rightarrow& x~\{ \ALIGN~(a - 2^6),~\OFFSET~o \} + a{:}\Bu32~~x{:}\memidx~~o{:}\Bu32 &\Rightarrow& x~\{ \ALIGN~(a - 2^6),~\OFFSET~o \} & (\iff 2^6 \leq a < 2^7) \\ \production{instruction} & \Binstr &::=& \dots \\ &&|& \hex{28}~~m{:}\Bmemarg &\Rightarrow& \I32.\LOAD~m \\ &&|& From 0493e50be45301c703af9b1926b81c3f2eced81e Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 24 Oct 2022 16:30:08 -0700 Subject: [PATCH 038/181] Update implementation status (#10) --- proposals/extended-const/Overview.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md index 02933eab7..920c3cde9 100644 --- a/proposals/extended-const/Overview.md +++ b/proposals/extended-const/Overview.md @@ -48,9 +48,13 @@ instruction: ## Implementation Status - spec interpreter: Done -- wabt: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) - Firefox: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) -- v8: [Done](https://chromium.googlesource.com/v8/v8/+/bf1565d7081cabc510e39c42eaea67ea6e79484e) +- Chrome/v8: [Done](https://chromium.googlesource.com/v8/v8/+/bf1565d7081cabc510e39c42eaea67ea6e79484e) +- Safari: ? +- wabt: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) +- llvm: Done +- binaryen: Done +- emscripten: Done [spec]: https://webassembly.github.io/spec/core/valid/instructions.html#constant-expressions [presentation]: https://docs.google.com/presentation/d/1sM9mJJ6iM7D8324ipYxot91hSKnWCtB8jX4Kh3bde5E From 11f60455d4d94ce0655c90da686b3d413c610070 Mon Sep 17 00:00:00 2001 From: tyingq <45127417+tyingq@users.noreply.github.com> Date: Mon, 28 Nov 2022 16:01:22 -0600 Subject: [PATCH 039/181] fix typo in README.md (#8) fix typo of "Extended" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b4ca868f..8ac515b72 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Build Status](https://github.com/WebAssembly/extended-const/actions/workflows/main.yml/badge.svg) -# Extented Const Expressesions Proposal for WebAssembly +# Extended Const Expressesions Proposal for WebAssembly This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). It is meant for discussion, prototype specification and implementation of a proposal to add tail call support to WebAssembly. From fb4683b5935d970337e68cce295ed8ab027753c4 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 9 Feb 2023 08:49:26 +0900 Subject: [PATCH 040/181] Remove wabt "Done" link (#14) It seems like a wrong copy-and-paste from Firefox. --- proposals/extended-const/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/extended-const/Overview.md b/proposals/extended-const/Overview.md index 920c3cde9..864749a63 100644 --- a/proposals/extended-const/Overview.md +++ b/proposals/extended-const/Overview.md @@ -51,7 +51,7 @@ instruction: - Firefox: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) - Chrome/v8: [Done](https://chromium.googlesource.com/v8/v8/+/bf1565d7081cabc510e39c42eaea67ea6e79484e) - Safari: ? -- wabt: [Done](https://github.com/WebAssembly/debugging/issues/17#issuecomment-1041130743) +- wabt: Done - llvm: Done - binaryen: Done - emscripten: Done From 0ebc3052fc681c134af4a49dd3c7b5e5cdf03ef3 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Fri, 10 Feb 2023 23:21:00 +0900 Subject: [PATCH 041/181] Separate simd tests to a separate file There are engines which don't have simd support but have multi-memory support. eg. toywasm Even for engines which support both of features, it seems common to have options to enable/disable features separately. This commit makes it easier for them to run only non-simd part of multi-memory tests. --- test/core/memory-multi.wast | 42 --------------------------- test/core/simd/simd_memory-multi.wast | 42 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 42 deletions(-) create mode 100644 test/core/simd/simd_memory-multi.wast diff --git a/test/core/memory-multi.wast b/test/core/memory-multi.wast index b9ba4a045..b5b71fd9e 100644 --- a/test/core/memory-multi.wast +++ b/test/core/memory-multi.wast @@ -40,45 +40,3 @@ (assert_return (invoke "fill1") (i32.const 0x01010101)) (assert_return (invoke "fill2") (i32.const 0x0202)) - - -;; Test syntax for load/store_lane immediates - -(module - (memory 1) - (memory $m 1) - - (func - (local $v v128) - - (drop (v128.load8_lane 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) - - (drop (v128.load8_lane $m 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane $m offset=0 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane $m align=1 1 (i32.const 0) (local.get $v))) - - (drop (v128.load8_lane 1 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) - (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) - - (v128.store8_lane 1 (i32.const 0) (local.get $v)) - (v128.store8_lane offset=0 1 (i32.const 0) (local.get $v)) - (v128.store8_lane offset=0 align=1 1 (i32.const 0) (local.get $v)) - (v128.store8_lane align=1 1 (i32.const 0) (local.get $v)) - - (v128.store8_lane $m 1 (i32.const 0) (local.get $v)) - (v128.store8_lane $m offset=0 1 (i32.const 0) (local.get $v)) - (v128.store8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v)) - (v128.store8_lane $m align=1 1 (i32.const 0) (local.get $v)) - - (v128.store8_lane 1 1 (i32.const 0) (local.get $v)) - (v128.store8_lane 1 offset=0 1 (i32.const 0) (local.get $v)) - (v128.store8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v)) - (v128.store8_lane 1 align=1 1 (i32.const 0) (local.get $v)) - ) -) diff --git a/test/core/simd/simd_memory-multi.wast b/test/core/simd/simd_memory-multi.wast new file mode 100644 index 000000000..202f2cd8d --- /dev/null +++ b/test/core/simd/simd_memory-multi.wast @@ -0,0 +1,42 @@ +;; From wasmtime misc_testsuite/multi-memory/simple.wast + +;; Test syntax for load/store_lane immediates + +(module + (memory 1) + (memory $m 1) + + (func + (local $v v128) + + (drop (v128.load8_lane 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) + + (drop (v128.load8_lane $m 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m align=1 1 (i32.const 0) (local.get $v))) + + (drop (v128.load8_lane 1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) + + (v128.store8_lane 1 (i32.const 0) (local.get $v)) + (v128.store8_lane offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane align=1 1 (i32.const 0) (local.get $v)) + + (v128.store8_lane $m 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m align=1 1 (i32.const 0) (local.get $v)) + + (v128.store8_lane 1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 align=1 1 (i32.const 0) (local.get $v)) + ) +) From 890f941fd81410430549ebd656af528ff1cc5e24 Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Thu, 16 Feb 2023 15:15:56 -0500 Subject: [PATCH 042/181] [test] Add more tests for multi-memory --- test/core/multi-memory/address0.wast | 212 +++++++++++++++ test/core/multi-memory/address1.wast | 295 +++++++++++++++++++++ test/core/multi-memory/align0.wast | 43 +++ test/core/multi-memory/binary0.wast | 67 +++++ test/core/multi-memory/block0.wast | 18 ++ test/core/multi-memory/br0.wast | 15 ++ test/core/multi-memory/br_if0.wast | 15 ++ test/core/multi-memory/br_table0.wast | 15 ++ test/core/multi-memory/call0.wast | 21 ++ test/core/multi-memory/call_indirect0.wast | 22 ++ test/core/multi-memory/data0.wast | 73 +++++ test/core/multi-memory/data1.wast | 146 ++++++++++ test/core/multi-memory/data_drop0.wast | 28 ++ test/core/multi-memory/exports0.wast | 51 ++++ test/core/multi-memory/float_exprs0.wast | 38 +++ test/core/multi-memory/float_exprs1.wast | 105 ++++++++ test/core/multi-memory/float_memory0.wast | 60 +++++ test/core/multi-memory/global0.wast | 21 ++ test/core/multi-memory/if0.wast | 29 ++ test/core/multi-memory/imports0.wast | 45 ++++ test/core/multi-memory/imports1.wast | 16 ++ test/core/multi-memory/imports2.wast | 73 +++++ test/core/multi-memory/imports3.wast | 75 ++++++ test/core/multi-memory/imports4.wast | 47 ++++ test/core/multi-memory/linking0.wast | 42 +++ test/core/multi-memory/linking1.wast | 65 +++++ test/core/multi-memory/linking2.wast | 30 +++ test/core/multi-memory/linking3.wast | 83 ++++++ test/core/multi-memory/load0.wast | 19 ++ test/core/multi-memory/load1.wast | 41 +++ test/core/multi-memory/load2.wast | 213 +++++++++++++++ test/core/multi-memory/local_tee0.wast | 19 ++ test/core/multi-memory/loop0.wast | 19 ++ test/core/multi-memory/memory_copy0.wast | 60 +++++ test/core/multi-memory/memory_copy1.wast | 1 + test/core/multi-memory/memory_fill0.wast | 46 ++++ test/core/multi-memory/memory_init0.wast | 42 +++ test/core/multi-memory/memory_size0.wast | 19 ++ test/core/multi-memory/memory_size1.wast | 29 ++ test/core/multi-memory/memory_size2.wast | 34 +++ test/core/multi-memory/memory_size3.wast | 25 ++ test/core/multi-memory/memory_trap0.wast | 36 +++ test/core/multi-memory/memory_trap1.wast | 250 +++++++++++++++++ test/core/multi-memory/return0.wast | 19 ++ test/core/multi-memory/select0.wast | 24 ++ test/core/multi-memory/start0.wast | 42 +++ test/core/multi-memory/store0.wast | 25 ++ test/core/multi-memory/store1.wast | 52 ++++ test/core/multi-memory/traps.wast | 35 +++ test/core/run.py | 3 +- 50 files changed, 2802 insertions(+), 1 deletion(-) create mode 100644 test/core/multi-memory/address0.wast create mode 100644 test/core/multi-memory/address1.wast create mode 100644 test/core/multi-memory/align0.wast create mode 100644 test/core/multi-memory/binary0.wast create mode 100644 test/core/multi-memory/block0.wast create mode 100644 test/core/multi-memory/br0.wast create mode 100644 test/core/multi-memory/br_if0.wast create mode 100644 test/core/multi-memory/br_table0.wast create mode 100644 test/core/multi-memory/call0.wast create mode 100644 test/core/multi-memory/call_indirect0.wast create mode 100644 test/core/multi-memory/data0.wast create mode 100644 test/core/multi-memory/data1.wast create mode 100644 test/core/multi-memory/data_drop0.wast create mode 100644 test/core/multi-memory/exports0.wast create mode 100644 test/core/multi-memory/float_exprs0.wast create mode 100644 test/core/multi-memory/float_exprs1.wast create mode 100644 test/core/multi-memory/float_memory0.wast create mode 100644 test/core/multi-memory/global0.wast create mode 100644 test/core/multi-memory/if0.wast create mode 100644 test/core/multi-memory/imports0.wast create mode 100644 test/core/multi-memory/imports1.wast create mode 100644 test/core/multi-memory/imports2.wast create mode 100644 test/core/multi-memory/imports3.wast create mode 100644 test/core/multi-memory/imports4.wast create mode 100644 test/core/multi-memory/linking0.wast create mode 100644 test/core/multi-memory/linking1.wast create mode 100644 test/core/multi-memory/linking2.wast create mode 100644 test/core/multi-memory/linking3.wast create mode 100644 test/core/multi-memory/load0.wast create mode 100644 test/core/multi-memory/load1.wast create mode 100644 test/core/multi-memory/load2.wast create mode 100644 test/core/multi-memory/local_tee0.wast create mode 100644 test/core/multi-memory/loop0.wast create mode 100644 test/core/multi-memory/memory_copy0.wast create mode 100644 test/core/multi-memory/memory_copy1.wast create mode 100644 test/core/multi-memory/memory_fill0.wast create mode 100644 test/core/multi-memory/memory_init0.wast create mode 100644 test/core/multi-memory/memory_size0.wast create mode 100644 test/core/multi-memory/memory_size1.wast create mode 100644 test/core/multi-memory/memory_size2.wast create mode 100644 test/core/multi-memory/memory_size3.wast create mode 100644 test/core/multi-memory/memory_trap0.wast create mode 100644 test/core/multi-memory/memory_trap1.wast create mode 100644 test/core/multi-memory/return0.wast create mode 100644 test/core/multi-memory/select0.wast create mode 100644 test/core/multi-memory/start0.wast create mode 100644 test/core/multi-memory/store0.wast create mode 100644 test/core/multi-memory/store1.wast create mode 100644 test/core/multi-memory/traps.wast diff --git a/test/core/multi-memory/address0.wast b/test/core/multi-memory/address0.wast new file mode 100644 index 000000000..a02236520 --- /dev/null +++ b/test/core/multi-memory/address0.wast @@ -0,0 +1,212 @@ +;; Load i32 data with different offset/align arguments + +(module + (memory $mem0 0) + (memory $mem1 1) + (data (memory $mem1) (i32.const 0) "abcdefghijklmnopqrstuvwxyz") + + (func (export "8u_good1") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good2") (param $i i32) (result i32) + (i32.load8_u $mem1 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good3") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8u_good4") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8u_good5") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "8s_good1") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good2") (param $i i32) (result i32) + (i32.load8_s $mem1 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good3") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8s_good4") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8s_good5") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "16u_good1") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good2") (param $i i32) (result i32) + (i32.load16_u $mem1 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good3") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16u_good4") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16u_good5") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "16s_good1") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good2") (param $i i32) (result i32) + (i32.load16_s $mem1 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good3") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16s_good4") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16s_good5") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "32_good1") (param $i i32) (result i32) + (i32.load $mem1 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32_good2") (param $i i32) (result i32) + (i32.load $mem1 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32_good3") (param $i i32) (result i32) + (i32.load $mem1 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32_good4") (param $i i32) (result i32) + (i32.load $mem1 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32_good5") (param $i i32) (result i32) + (i32.load $mem1 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "8u_bad") (param $i i32) + (drop (i32.load8_u $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "8s_bad") (param $i i32) + (drop (i32.load8_s $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "16u_bad") (param $i i32) + (drop (i32.load16_u $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "16s_bad") (param $i i32) + (drop (i32.load16_s $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "32_bad") (param $i i32) + (drop (i32.load $mem1 offset=4294967295 (local.get $i))) + ) +) + +(assert_return (invoke "8u_good1" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8u_good2" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8u_good3" (i32.const 0)) (i32.const 98)) +(assert_return (invoke "8u_good4" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "8u_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "8s_good1" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8s_good2" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8s_good3" (i32.const 0)) (i32.const 98)) +(assert_return (invoke "8s_good4" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "8s_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "16u_good1" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16u_good2" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16u_good3" (i32.const 0)) (i32.const 25442)) +(assert_return (invoke "16u_good4" (i32.const 0)) (i32.const 25699)) +(assert_return (invoke "16u_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "16s_good1" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16s_good2" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16s_good3" (i32.const 0)) (i32.const 25442)) +(assert_return (invoke "16s_good4" (i32.const 0)) (i32.const 25699)) +(assert_return (invoke "16s_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "32_good1" (i32.const 0)) (i32.const 1684234849)) +(assert_return (invoke "32_good2" (i32.const 0)) (i32.const 1684234849)) +(assert_return (invoke "32_good3" (i32.const 0)) (i32.const 1701077858)) +(assert_return (invoke "32_good4" (i32.const 0)) (i32.const 1717920867)) +(assert_return (invoke "32_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "8u_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "32_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "8u_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "32_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good4" (i32.const 65508)) (i32.const 0)) +(assert_trap (invoke "32_good5" (i32.const 65508)) "out of bounds memory access") + +(assert_trap (invoke "8u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "8s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32_good3" (i32.const -1)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32_bad" (i32.const 0)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "32_bad" (i32.const 1)) "out of bounds memory access") diff --git a/test/core/multi-memory/address1.wast b/test/core/multi-memory/address1.wast new file mode 100644 index 000000000..d43d6475c --- /dev/null +++ b/test/core/multi-memory/address1.wast @@ -0,0 +1,295 @@ +;; Load i64 data with different offset/align arguments + +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 0) + (memory $mem3 0) + (memory $mem4 1) + (data (memory $mem4) (i32.const 0) "abcdefghijklmnopqrstuvwxyz") + + (func (export "8u_good1") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good2") (param $i i32) (result i64) + (i64.load8_u $mem4 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good3") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8u_good4") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8u_good5") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "8s_good1") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good2") (param $i i32) (result i64) + (i64.load8_s $mem4 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good3") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8s_good4") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8s_good5") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "16u_good1") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good2") (param $i i32) (result i64) + (i64.load16_u $mem4 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good3") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16u_good4") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16u_good5") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "16s_good1") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good2") (param $i i32) (result i64) + (i64.load16_s $mem4 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good3") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16s_good4") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16s_good5") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "32u_good1") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32u_good2") (param $i i32) (result i64) + (i64.load32_u $mem4 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32u_good3") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32u_good4") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32u_good5") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "32s_good1") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32s_good2") (param $i i32) (result i64) + (i64.load32_s $mem4 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32s_good3") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32s_good4") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32s_good5") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "64_good1") (param $i i32) (result i64) + (i64.load $mem4 offset=0 (local.get $i)) ;; 0x6867666564636261 'abcdefgh' + ) + (func (export "64_good2") (param $i i32) (result i64) + (i64.load $mem4 align=1 (local.get $i)) ;; 0x6867666564636261 'abcdefgh' + ) + (func (export "64_good3") (param $i i32) (result i64) + (i64.load $mem4 offset=1 align=1 (local.get $i)) ;; 0x6968676665646362 'bcdefghi' + ) + (func (export "64_good4") (param $i i32) (result i64) + (i64.load $mem4 offset=2 align=2 (local.get $i)) ;; 0x6a69686766656463 'cdefghij' + ) + (func (export "64_good5") (param $i i32) (result i64) + (i64.load $mem4 offset=25 align=8 (local.get $i)) ;; 122 'z\0\0\0\0\0\0\0' + ) + + (func (export "8u_bad") (param $i i32) + (drop (i64.load8_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "8s_bad") (param $i i32) + (drop (i64.load8_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "16u_bad") (param $i i32) + (drop (i64.load16_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "16s_bad") (param $i i32) + (drop (i64.load16_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "32u_bad") (param $i i32) + (drop (i64.load32_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "32s_bad") (param $i i32) + (drop (i64.load32_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "64_bad") (param $i i32) + (drop (i64.load $mem4 offset=4294967295 (local.get $i))) + ) +) + +(assert_return (invoke "8u_good1" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8u_good2" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8u_good3" (i32.const 0)) (i64.const 98)) +(assert_return (invoke "8u_good4" (i32.const 0)) (i64.const 99)) +(assert_return (invoke "8u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "8s_good1" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8s_good2" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8s_good3" (i32.const 0)) (i64.const 98)) +(assert_return (invoke "8s_good4" (i32.const 0)) (i64.const 99)) +(assert_return (invoke "8s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "16u_good1" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16u_good2" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16u_good3" (i32.const 0)) (i64.const 25442)) +(assert_return (invoke "16u_good4" (i32.const 0)) (i64.const 25699)) +(assert_return (invoke "16u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "16s_good1" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16s_good2" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16s_good3" (i32.const 0)) (i64.const 25442)) +(assert_return (invoke "16s_good4" (i32.const 0)) (i64.const 25699)) +(assert_return (invoke "16s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "32u_good1" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32u_good2" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32u_good3" (i32.const 0)) (i64.const 1701077858)) +(assert_return (invoke "32u_good4" (i32.const 0)) (i64.const 1717920867)) +(assert_return (invoke "32u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "32s_good1" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32s_good2" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32s_good3" (i32.const 0)) (i64.const 1701077858)) +(assert_return (invoke "32s_good4" (i32.const 0)) (i64.const 1717920867)) +(assert_return (invoke "32s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "64_good1" (i32.const 0)) (i64.const 0x6867666564636261)) +(assert_return (invoke "64_good2" (i32.const 0)) (i64.const 0x6867666564636261)) +(assert_return (invoke "64_good3" (i32.const 0)) (i64.const 0x6968676665646362)) +(assert_return (invoke "64_good4" (i32.const 0)) (i64.const 0x6a69686766656463)) +(assert_return (invoke "64_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "8u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "32u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "32s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "64_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "8u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "32u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "32s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "64_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good4" (i32.const 65504)) (i64.const 0)) +(assert_trap (invoke "64_good5" (i32.const 65504)) "out of bounds memory access") + +(assert_trap (invoke "8u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "8s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "64_good3" (i32.const -1)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "64_bad" (i32.const 0)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "64_bad" (i32.const 1)) "out of bounds memory access") + diff --git a/test/core/multi-memory/align0.wast b/test/core/multi-memory/align0.wast new file mode 100644 index 000000000..f1507087f --- /dev/null +++ b/test/core/multi-memory/align0.wast @@ -0,0 +1,43 @@ +;; Test aligned and unaligned read/write + +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 0) + + ;; $default: natural alignment, $1: align=1, $2: align=2, $4: align=4, $8: align=8 + + (func (export "f32_align_switch") (param i32) (result f32) + (local f32 f32) + (local.set 1 (f32.const 10.0)) + (block $4 + (block $2 + (block $1 + (block $default + (block $0 + (br_table $0 $default $1 $2 $4 (local.get 0)) + ) ;; 0 + (f32.store $mem1 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 (i32.const 0))) + (br $4) + ) ;; default + (f32.store $mem1 align=1 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=1 (i32.const 0))) + (br $4) + ) ;; 1 + (f32.store $mem1 align=2 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=2 (i32.const 0))) + (br $4) + ) ;; 2 + (f32.store $mem1 align=4 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=4 (i32.const 0))) + ) ;; 4 + (local.get 2) + ) +) + +(assert_return (invoke "f32_align_switch" (i32.const 0)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 1)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 2)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 3)) (f32.const 10.0)) + diff --git a/test/core/multi-memory/binary0.wast b/test/core/multi-memory/binary0.wast new file mode 100644 index 000000000..ff441120f --- /dev/null +++ b/test/core/multi-memory/binary0.wast @@ -0,0 +1,67 @@ +;; Unsigned LEB128 can have non-minimal length +(module binary + "\00asm" "\01\00\00\00" + "\05\07\02" ;; Memory section with 2 entries + "\00\82\00" ;; no max, minimum 2 + "\00\82\00" ;; no max, minimum 2 +) +(module binary + "\00asm" "\01\00\00\00" + "\05\13\03" ;; Memory section with 3 entries + "\00\83\80\80\80\00" ;; no max, minimum 3 + "\00\84\80\80\80\00" ;; no max, minimum 4 + "\00\85\80\80\80\00" ;; no max, minimum 5 +) + +(module binary + "\00asm" "\01\00\00\00" + "\05\05\02" ;; Memory section with 2 entries + "\00\00" ;; no max, minimum 0 + "\00\00" ;; no max, minimum 0 + "\0b\06\01" ;; Data section with 1 entry + "\00" ;; Memory index 0 + "\41\00\0b\00" ;; (i32.const 0) with contents "" +) + +(module binary + "\00asm" "\01\00\00\00" + "\05\05\02" ;; Memory section with 2 entries + "\00\00" ;; no max, minimum 0 + "\00\01" ;; no max, minimum 1 + "\0b\07\01" ;; Data section with 1 entry + "\02\01" ;; Memory index 1 + "\41\00\0b\00" ;; (i32.const 0) with contents "" +) + +(module binary + "\00asm" "\01\00\00\00" + "\05\05\02" ;; Memory section with 2 entries + "\00\00" ;; no max, minimum 0 + "\00\01" ;; no max, minimum 1 + "\0b\0a\01" ;; Data section with 1 entry + "\02\81\80\80\00" ;; Memory index 1 + "\41\00\0b\00" ;; (i32.const 0) with contents "" +) + +;; Unsigned LEB128 must not be overlong +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\05\0a\02" ;; Memory section with 2 entries + "\00\01" ;; no max, minimum 1 + "\00\82\80\80\80\80\00" ;; no max, minimum 2 with one byte too many + ) + "integer representation too long" +) + +;; 2 memories declared, 1 given +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\05\03\02" ;; memory section with inconsistent count (1 declared, 0 given) + "\00\00" ;; memory 0 (missed) + ;; "\00\00" ;; memory 1 (missing) + ) + "unexpected end of section or function" +) + diff --git a/test/core/multi-memory/block0.wast b/test/core/multi-memory/block0.wast new file mode 100644 index 000000000..a012ebc8a --- /dev/null +++ b/test/core/multi-memory/block0.wast @@ -0,0 +1,18 @@ +;; Test `block` operator + +(module + ;; Auxiliary definition + (memory $mem0 1) + (memory $mem1 1) + + (func (export "as-memory.grow-value1") (result i32) + (memory.grow $mem0 (block (result i32) (i32.const 1))) + ) + + (func (export "as-memory.grow-value2") (result i32) + (memory.grow $mem1 (block (result i32) (i32.const 1))) + ) +) + +(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) +(assert_return (invoke "as-memory.grow-value2") (i32.const 1)) diff --git a/test/core/multi-memory/br0.wast b/test/core/multi-memory/br0.wast new file mode 100644 index 000000000..509e7b068 --- /dev/null +++ b/test/core/multi-memory/br0.wast @@ -0,0 +1,15 @@ +(module + (memory $mem0 1) + (memory $mem1 1) + + (func (export "as-memory.grow-size0") (result i32) + (block (result i32) (memory.grow $mem0 (br 0 (i32.const 40)))) + ) + + (func (export "as-memory.grow-size1") (result i32) + (block (result i32) (memory.grow $mem1 (br 0 (i32.const 40)))) + ) +) + +(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) +(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) diff --git a/test/core/multi-memory/br_if0.wast b/test/core/multi-memory/br_if0.wast new file mode 100644 index 000000000..2b7a32b40 --- /dev/null +++ b/test/core/multi-memory/br_if0.wast @@ -0,0 +1,15 @@ +(module + (memory $mem0 1) + (memory $mem1 1) + + (func (export "as-memory.grow-size0") (result i32) + (block (result i32) (memory.grow $mem0 (br_if 0 (i32.const 1) (i32.const 1)))) + ) + + (func (export "as-memory.grow-size1") (result i32) + (block (result i32) (memory.grow $mem1 (br_if 0 (i32.const 1) (i32.const 1)))) + ) +) + +(assert_return (invoke "as-memory.grow-size0") (i32.const 1)) +(assert_return (invoke "as-memory.grow-size1") (i32.const 1)) diff --git a/test/core/multi-memory/br_table0.wast b/test/core/multi-memory/br_table0.wast new file mode 100644 index 000000000..0cb89b395 --- /dev/null +++ b/test/core/multi-memory/br_table0.wast @@ -0,0 +1,15 @@ +(module + (memory $mem0 1) + (memory $mem1 1) + + (func (export "as-memory.grow-size0") (result i32) + (block (result i32) (memory.grow $mem0 (br_table 0 (i32.const 40) (i32.const 0)))) + ) + + (func (export "as-memory.grow-size1") (result i32) + (block (result i32) (memory.grow $mem1 (br_table 0 (i32.const 40) (i32.const 0)))) + ) +) + +(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) +(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) diff --git a/test/core/multi-memory/call0.wast b/test/core/multi-memory/call0.wast new file mode 100644 index 000000000..4d48fcfa3 --- /dev/null +++ b/test/core/multi-memory/call0.wast @@ -0,0 +1,21 @@ +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 2) + + (func $const-i32 (result i32) (i32.const 0x12)) + + (func (export "as-memory.grow-value0") (result i32) + (memory.grow $mem0 (call $const-i32)) + ) + (func (export "as-memory.grow-value1") (result i32) + (memory.grow $mem1 (call $const-i32)) + ) + (func (export "as-memory.grow-value2") (result i32) + (memory.grow $mem2 (call $const-i32)) + ) +) + +(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) +(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) +(assert_return (invoke "as-memory.grow-value2") (i32.const 2)) diff --git a/test/core/multi-memory/call_indirect0.wast b/test/core/multi-memory/call_indirect0.wast new file mode 100644 index 000000000..11cbdf4e4 --- /dev/null +++ b/test/core/multi-memory/call_indirect0.wast @@ -0,0 +1,22 @@ +(module + (memory $mem0 0) + (memory $mem1 1) + + (type $out-i32 (func (result i32))) + + (table funcref + (elem + $const-i32 )) + + (func $const-i32 (type $out-i32) (i32.const 0x132)) + + (func (export "as-memory.grow-value0") (result i32) + (memory.grow $mem0 (call_indirect (type $out-i32) (i32.const 0))) + ) + (func (export "as-memory.grow-value1") (result i32) + (memory.grow $mem1 (call_indirect (type $out-i32) (i32.const 0))) + ) +) + +(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) +(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) diff --git a/test/core/multi-memory/data0.wast b/test/core/multi-memory/data0.wast new file mode 100644 index 000000000..2cb95851c --- /dev/null +++ b/test/core/multi-memory/data0.wast @@ -0,0 +1,73 @@ +;; Test the data section + +;; Syntax + +(module + (memory $mem0 1) + (memory $mem1 1) + (memory $mem2 1) + + (data (i32.const 0)) + (data (i32.const 1) "a" "" "bcd") + (data (offset (i32.const 0))) + (data (offset (i32.const 0)) "" "a" "bc" "") + (data (memory 0) (i32.const 0)) + (data (memory 0x0) (i32.const 1) "a" "" "bcd") + (data (memory 0x000) (offset (i32.const 0))) + (data (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data (memory $mem0) (i32.const 0)) + (data (memory $mem1) (i32.const 1) "a" "" "bcd") + (data (memory $mem2) (offset (i32.const 0))) + (data (memory $mem0) (offset (i32.const 0)) "" "a" "bc" "") + + (data $d1 (i32.const 0)) + (data $d2 (i32.const 1) "a" "" "bcd") + (data $d3 (offset (i32.const 0))) + (data $d4 (offset (i32.const 0)) "" "a" "bc" "") + (data $d5 (memory 0) (i32.const 0)) + (data $d6 (memory 0x0) (i32.const 1) "a" "" "bcd") + (data $d7 (memory 0x000) (offset (i32.const 0))) + (data $d8 (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data $d9 (memory $mem0) (i32.const 0)) + (data $d10 (memory $mem1) (i32.const 1) "a" "" "bcd") + (data $d11 (memory $mem2) (offset (i32.const 0))) + (data $d12 (memory $mem0) (offset (i32.const 0)) "" "a" "bc" "") +) + +;; Basic use + +(module + (memory 1) + (data (i32.const 0) "a") +) +(module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 0) (i32.const 0) "a") + (data (memory 1) (i32.const 0) "a") + (data (memory 2) (i32.const 0) "a") +) + +(module + (global (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get 0) "a") +) +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get 0) "a") +) + +(module + (global $g (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get $g) "a") +) +(module + (global $g (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get $g) "a") +) + diff --git a/test/core/multi-memory/data1.wast b/test/core/multi-memory/data1.wast new file mode 100644 index 000000000..8348d5c58 --- /dev/null +++ b/test/core/multi-memory/data1.wast @@ -0,0 +1,146 @@ +;; Invalid bounds for data + +(assert_trap + (module + (memory 1) + (memory 0) + (memory 2) + (data (memory 1) (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1 1) + (memory 1 1) + (memory 0 0) + (data (memory 2) (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1 1) + (memory 0 1) + (memory 1 1) + (data (memory 1) (i32.const 0) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 1) + (memory 1) + (memory 0) + (data (memory 2) (i32.const 1)) + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 1 1) + (memory 1 1) + (memory 0 1) + (data (memory 2) (i32.const 1)) + ) + "out of bounds memory access" +) + +;; This seems to cause a time-out on Travis. +(;assert_unlinkable + (module + (memory 0x10000) + (data (i32.const 0xffffffff) "ab") + ) + "" ;; either out of memory or out of bounds +;) + +(assert_trap + (module + (global (import "spectest" "global_i32") i32) + (memory 3) + (memory 0) + (memory 3) + (data (memory 1) (global.get 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2 2) + (memory 1 2) + (memory 2 2) + (data (memory 1) (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 3) + (memory 3) + (memory 2) + (data (memory 2) (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 3 3) + (memory 2 3) + (memory 3 3) + (data (memory 1) (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 0) + (memory 0) + (memory 1) + (data (memory 2) (i32.const -1) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 2) (i32.const -1) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2) + (memory 2) + (memory 2) + (data (memory 2) (i32.const -100) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 3) (i32.const -100) "a") + ) + "out of bounds memory access" +) + diff --git a/test/core/multi-memory/data_drop0.wast b/test/core/multi-memory/data_drop0.wast new file mode 100644 index 000000000..b617b10ea --- /dev/null +++ b/test/core/multi-memory/data_drop0.wast @@ -0,0 +1,28 @@ +;; data.drop +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 0) + (data $p "x") + (data $a (memory 1) (i32.const 0) "x") + + (func (export "drop_passive") (data.drop $p)) + (func (export "init_passive") (param $len i32) + (memory.init $mem1 $p (i32.const 0) (i32.const 0) (local.get $len))) + + (func (export "drop_active") (data.drop $a)) + (func (export "init_active") (param $len i32) + (memory.init $mem1 $a (i32.const 0) (i32.const 0) (local.get $len))) +) + +(invoke "init_passive" (i32.const 1)) +(invoke "drop_passive") +(invoke "drop_passive") +(assert_return (invoke "init_passive" (i32.const 0))) +(assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds memory access") +(invoke "init_passive" (i32.const 0)) +(invoke "drop_active") +(assert_return (invoke "init_active" (i32.const 0))) +(assert_trap (invoke "init_active" (i32.const 1)) "out of bounds memory access") +(invoke "init_active" (i32.const 0)) + diff --git a/test/core/multi-memory/exports0.wast b/test/core/multi-memory/exports0.wast new file mode 100644 index 000000000..6eb94d13b --- /dev/null +++ b/test/core/multi-memory/exports0.wast @@ -0,0 +1,51 @@ +;; Memories + +(module (memory 0) (export "a" (memory 0))) +(module (memory 0) (export "a" (memory 0)) (export "b" (memory 0))) +(module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1))) +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 0) + (memory $mem3 0) + (memory $mem4 0) + (memory $mem5 0) + (memory $mem6 0) + + (export "a" (memory $mem0)) + (export "b" (memory $mem1)) + (export "ac" (memory $mem2)) + (export "bc" (memory $mem3)) + (export "ad" (memory $mem4)) + (export "bd" (memory $mem5)) + (export "be" (memory $mem6)) + + (export "za" (memory $mem0)) + (export "zb" (memory $mem1)) + (export "zac" (memory $mem2)) + (export "zbc" (memory $mem3)) + (export "zad" (memory $mem4)) + (export "zbd" (memory $mem5)) + (export "zbe" (memory $mem6)) +) + +(module + (export "a" (memory 0)) + (memory 6) + + (export "b" (memory 1)) + (memory 3) +) + +(module + (export "a" (memory 0)) + (memory 0 1) + (memory 0 1) + (memory 0 1) + (memory 0 1) + + (export "b" (memory 3)) +) +(module (export "a" (memory $a)) (memory $a 0)) +(module (export "a" (memory $a)) (memory $a 0 1)) + diff --git a/test/core/multi-memory/float_exprs0.wast b/test/core/multi-memory/float_exprs0.wast new file mode 100644 index 000000000..8b40b349d --- /dev/null +++ b/test/core/multi-memory/float_exprs0.wast @@ -0,0 +1,38 @@ +(module + (memory 0 0) + (memory $m 1 1) + (memory 0 0) + (func (export "init") (param $i i32) (param $x f64) + (f64.store $m (local.get $i) (local.get $x))) + + (func (export "run") (param $n i32) (param $z f64) + (local $i i32) + (block $exit + (loop $cont + (f64.store $m + (local.get $i) + (f64.div (f64.load $m (local.get $i)) (local.get $z)) + ) + (local.set $i (i32.add (local.get $i) (i32.const 8))) + (br_if $cont (i32.lt_u (local.get $i) (local.get $n))) + ) + ) + ) + + (func (export "check") (param $i i32) (result f64) (f64.load $m (local.get $i))) +) + +(invoke "init" (i32.const 0) (f64.const 15.1)) +(invoke "init" (i32.const 8) (f64.const 15.2)) +(invoke "init" (i32.const 16) (f64.const 15.3)) +(invoke "init" (i32.const 24) (f64.const 15.4)) +(assert_return (invoke "check" (i32.const 0)) (f64.const 15.1)) +(assert_return (invoke "check" (i32.const 8)) (f64.const 15.2)) +(assert_return (invoke "check" (i32.const 16)) (f64.const 15.3)) +(assert_return (invoke "check" (i32.const 24)) (f64.const 15.4)) +(invoke "run" (i32.const 32) (f64.const 3.0)) +(assert_return (invoke "check" (i32.const 0)) (f64.const 0x1.4222222222222p+2)) +(assert_return (invoke "check" (i32.const 8)) (f64.const 0x1.4444444444444p+2)) +(assert_return (invoke "check" (i32.const 16)) (f64.const 0x1.4666666666667p+2)) +(assert_return (invoke "check" (i32.const 24)) (f64.const 0x1.4888888888889p+2)) + diff --git a/test/core/multi-memory/float_exprs1.wast b/test/core/multi-memory/float_exprs1.wast new file mode 100644 index 000000000..834696acd --- /dev/null +++ b/test/core/multi-memory/float_exprs1.wast @@ -0,0 +1,105 @@ +;; Test that plain summation is not reassociated, and that Kahan summation +;; isn't optimized into plain summation. + +(module + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory $m (data + "\c4\c5\57\24\a5\84\c8\0b\6d\b8\4b\2e\f2\76\17\1c\ca\4a\56\1e\1b\6e\71\22" + "\5d\17\1e\6e\bf\cd\14\5c\c7\21\55\51\39\9c\1f\b2\51\f0\a3\93\d7\c1\2c\ae" + "\7e\a8\28\3a\01\21\f4\0a\58\93\f8\42\77\9f\83\39\6a\5f\ba\f7\0a\d8\51\6a" + "\34\ca\ad\c6\34\0e\d8\26\dc\4c\33\1c\ed\29\90\a8\78\0f\d1\ce\76\31\23\83" + "\b8\35\e8\f2\44\b0\d3\a1\fc\bb\32\e1\b0\ba\69\44\09\d6\d9\7d\ff\2e\c0\5a" + "\36\14\33\14\3e\a9\fa\87\6d\8b\bc\ce\9d\a7\fd\c4\e9\85\3f\dd\d7\e1\18\a6" + "\50\26\72\6e\3f\73\0f\f8\12\93\23\34\61\76\12\48\c0\9b\05\93\eb\ac\86\de" + "\94\3e\55\e8\8c\e8\dd\e4\fc\95\47\be\56\03\21\20\4c\e6\bf\7b\f6\7f\d5\ba" + "\73\1c\c1\14\8f\c4\27\96\b3\bd\33\ff\78\41\5f\c0\5a\ce\f6\67\6e\73\9a\17" + "\66\70\03\f8\ce\27\a3\52\b2\9f\3b\bf\fb\ae\ed\d3\5a\f8\37\57\f0\f5\6e\ef" + "\b1\4d\70\3d\54\a7\01\9a\85\08\48\91\f5\9d\0c\60\87\5b\d9\54\1e\51\6d\88" + "\8e\08\8c\a5\71\3a\56\08\67\46\8f\8f\13\2a\2c\ec\2c\1f\b4\62\2b\6f\41\0a" + "\c4\65\42\a2\31\6b\2c\7d\3e\bb\75\ac\86\97\30\d9\48\cd\9a\1f\56\c4\c6\e4" + "\12\c0\9d\fb\ee\02\8c\ce\1c\f2\1e\a1\78\23\db\c4\1e\49\03\d3\71\cc\08\50" + "\c5\d8\5c\ed\d5\b5\65\ac\b5\c9\21\d2\c9\29\76\de\f0\30\1a\5b\3c\f2\3b\db" + "\3a\39\82\3a\16\08\6f\a8\f1\be\69\69\99\71\a6\05\d3\14\93\2a\16\f2\2f\11" + "\c7\7e\20\bb\91\44\ee\f8\e4\01\53\c0\b9\7f\f0\bf\f0\03\9c\6d\b1\df\a2\44" + "\01\6d\6b\71\2b\5c\b3\21\19\46\5e\8f\db\91\d3\7c\78\6b\b7\12\00\8f\eb\bd" + "\8a\f5\d4\2e\c4\c1\1e\df\73\63\59\47\49\03\0a\b7\cf\24\cf\9c\0e\44\7a\9e" + "\14\fb\42\bf\9d\39\30\9e\a0\ab\2f\d1\ae\9e\6a\83\43\e3\55\7d\85\bf\63\8a" + "\f8\96\10\1f\fe\6d\e7\22\1b\e1\69\46\8a\44\c8\c8\f9\0c\2b\19\07\a5\02\3e" + "\f2\30\10\9a\85\8a\5f\ef\81\45\a0\77\b1\03\10\73\4b\ae\98\9d\47\bf\9a\2d" + "\3a\d5\0f\03\66\e3\3d\53\d9\40\ce\1f\6f\32\2f\21\2b\23\21\6c\62\d4\a7\3e" + "\a8\ce\28\31\2d\00\3d\67\5e\af\a0\cf\2e\d2\b9\6b\84\eb\69\08\3c\62\36\be" + "\12\fd\36\7f\88\3e\ad\bc\0b\c0\41\c4\50\b6\e3\50\31\e8\ce\e2\96\65\55\9c" + "\16\46\e6\b0\2d\3a\e8\81\05\b0\bf\34\f7\bc\10\1c\fb\cc\3c\f1\85\97\42\9f" + "\eb\14\8d\3c\bf\d7\17\88\49\9d\8b\2b\b2\3a\83\d1\4f\04\9e\a1\0f\ad\08\9d" + "\54\af\d1\82\c3\ec\32\2f\02\8f\05\21\2d\a2\b7\e4\f4\6f\2e\81\2b\0b\9c\fc" + "\cb\fe\74\02\f9\db\f4\f3\ea\00\a8\ec\d1\99\74\26\dd\d6\34\d5\25\b1\46\dd" + "\9c\aa\71\f5\60\b0\88\c8\e0\0b\59\5a\25\4f\29\66\f9\e3\2e\fe\e9\da\e5\18" + "\4f\27\62\f4\ce\a4\21\95\74\c7\57\64\27\9a\4c\fd\54\7d\61\ce\c3\ac\87\46" + "\9c\fa\ff\09\ca\79\97\67\24\74\ca\d4\21\83\26\25\19\12\37\64\19\e5\65\e0" + "\74\75\8e\dd\c8\ef\74\c7\d8\21\2b\79\04\51\46\65\60\03\5d\fa\d8\f4\65\a4" + "\9e\5d\23\da\d7\8a\92\80\a4\de\78\3c\f1\57\42\6d\cd\c9\2f\d5\a4\9e\ab\40" + "\f4\cb\1b\d7\a3\ca\fc\eb\a7\01\b2\9a\69\4e\46\9b\18\4e\dd\79\a7\aa\a6\52" + "\39\1e\ef\30\cc\9b\bd\5b\ee\4c\21\6d\30\00\72\b0\46\5f\08\cf\c5\b9\e0\3e" + "\c2\b3\0c\dc\8e\64\de\19\42\79\cf\43\ea\43\5d\8e\88\f7\ab\15\dc\3f\c8\67" + "\20\db\b8\64\b1\47\1f\de\f2\cb\3f\59\9f\d8\46\90\dc\ae\2f\22\f9\e2\31\89" + "\d9\9c\1c\4c\d3\a9\4a\57\84\9c\9f\ea\2c\3c\ae\3c\c3\1e\8b\e5\4e\17\01\25" + "\db\34\46\5f\15\ea\05\0c\7c\d9\45\8c\19\d0\73\8a\96\16\dd\44\f9\05\b7\5b" + "\71\b0\e6\21\36\5f\75\89\91\73\75\ab\7d\ae\d3\73\ec\37\c6\ea\55\75\ef\ea" + "\ab\8b\7b\11\dc\6d\1a\b2\6a\c4\25\cf\aa\e3\9f\49\49\89\cb\37\9b\0a\a7\01" + "\60\70\dc\b7\c8\83\e1\42\f5\be\ad\62\94\ad\8d\a1" + )) + (memory 0 0) + (memory 0 0) + (memory 0 0) + + (func (export "f32.kahan_sum") (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (local $c f32) + (local $t f32) + (block $exit + (loop $top + (local.set $t + (f32.sub + (f32.sub + (local.tee $sum + (f32.add + (local.get $c) + (local.tee $t + (f32.sub (f32.load $m (local.get $p)) (local.get $t)) + ) + ) + ) + (local.get $c) + ) + (local.get $t) + ) + ) + (local.set $p (i32.add (local.get $p) (i32.const 4))) + (local.set $c (local.get $sum)) + (br_if $top (local.tee $n (i32.add (local.get $n) (i32.const -1)))) + ) + ) + (local.get $sum) + ) + + (func (export "f32.plain_sum") (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (block $exit + (loop $top + (local.set $sum (f32.add (local.get $sum) (f32.load $m (local.get $p)))) + (local.set $p (i32.add (local.get $p) (i32.const 4))) + (local.set $n (i32.add (local.get $n) (i32.const -1))) + (br_if $top (local.get $n)) + ) + ) + (local.get $sum) + ) +) + +(assert_return (invoke "f32.kahan_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.101a1ap+104)) +(assert_return (invoke "f32.plain_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.a0343ap+103)) + diff --git a/test/core/multi-memory/float_memory0.wast b/test/core/multi-memory/float_memory0.wast new file mode 100644 index 000000000..00e22dfb0 --- /dev/null +++ b/test/core/multi-memory/float_memory0.wast @@ -0,0 +1,60 @@ +;; Test that floating-point load and store are bit-preserving. + +;; Test that load and store do not canonicalize NaNs as x87 does. + +(module + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory $m (data "\00\00\a0\7f")) + (memory 0 0) + (memory 0 0) + + (func (export "f32.load") (result f32) (f32.load $m (i32.const 0))) + (func (export "i32.load") (result i32) (i32.load $m (i32.const 0))) + (func (export "f32.store") (f32.store $m (i32.const 0) (f32.const nan:0x200000))) + (func (export "i32.store") (i32.store $m (i32.const 0) (i32.const 0x7fa00000))) + (func (export "reset") (i32.store $m (i32.const 0) (i32.const 0))) +) + +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "f32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "i32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) + +(module + (memory 0 0) + (memory $m (data "\00\00\00\00\00\00\f4\7f")) + + (func (export "f64.load") (result f64) (f64.load $m (i32.const 0))) + (func (export "i64.load") (result i64) (i64.load $m (i32.const 0))) + (func (export "f64.store") (f64.store $m (i32.const 0) (f64.const nan:0x4000000000000))) + (func (export "i64.store") (i64.store $m (i32.const 0) (i64.const 0x7ff4000000000000))) + (func (export "reset") (i64.store $m (i32.const 0) (i64.const 0))) +) + +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "f64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "i64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) + diff --git a/test/core/multi-memory/global0.wast b/test/core/multi-memory/global0.wast new file mode 100644 index 000000000..00d99d5cd --- /dev/null +++ b/test/core/multi-memory/global0.wast @@ -0,0 +1,21 @@ +(module + (memory $mem0 3) + (memory $mem1 4) + (memory $mem2 9) + + (global $x (mut i32) (i32.const 3)) + + (func (export "as-memory.grow-value0") (result i32) + (memory.grow $mem0 (global.get $x)) + ) + (func (export "as-memory.grow-value1") (result i32) + (memory.grow $mem1 (global.get $x)) + ) + (func (export "as-memory.grow-value2") (result i32) + (memory.grow $mem2 (global.get $x)) + ) +) + +(assert_return (invoke "as-memory.grow-value0") (i32.const 3)) +(assert_return (invoke "as-memory.grow-value1") (i32.const 4)) +(assert_return (invoke "as-memory.grow-value2") (i32.const 9)) diff --git a/test/core/multi-memory/if0.wast b/test/core/multi-memory/if0.wast new file mode 100644 index 000000000..1a82abd79 --- /dev/null +++ b/test/core/multi-memory/if0.wast @@ -0,0 +1,29 @@ +(module + (memory $mem0 1) + (memory $mem1 4) + + (func (export "as-memory.grow-value0") (param i32) (result i32) + (memory.grow $mem0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + + (func (export "as-memory.grow-value1") (param i32) (result i32) + (memory.grow $mem1 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) +) + +(assert_return (invoke "as-memory.grow-value0" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-memory.grow-value0" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-memory.grow-value1" (i32.const 0)) (i32.const 4)) +(assert_return (invoke "as-memory.grow-value1" (i32.const 1)) (i32.const 4)) + diff --git a/test/core/multi-memory/imports0.wast b/test/core/multi-memory/imports0.wast new file mode 100644 index 000000000..ce827a2d2 --- /dev/null +++ b/test/core/multi-memory/imports0.wast @@ -0,0 +1,45 @@ +(module + (func (export "func")) + (func (export "func-i32") (param i32)) + (func (export "func-f32") (param f32)) + (func (export "func->i32") (result i32) (i32.const 22)) + (func (export "func->f32") (result f32) (f32.const 11)) + (func (export "func-i32->i32") (param i32) (result i32) (local.get 0)) + (func (export "func-i64->i64") (param i64) (result i64) (local.get 0)) + (global (export "global-i32") i32 (i32.const 55)) + (global (export "global-f32") f32 (f32.const 44)) + (global (export "global-mut-i64") (mut i64) (i64.const 66)) + (table (export "table-10-inf") 10 funcref) + (table (export "table-10-20") 10 20 funcref) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(assert_unlinkable + (module (import "test" "memory-2-inf" (func))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (func))) + "incompatible import type" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (global i32))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (global i32))) + "incompatible import type" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (table 10 funcref))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (table 10 funcref))) + "incompatible import type" +) diff --git a/test/core/multi-memory/imports1.wast b/test/core/multi-memory/imports1.wast new file mode 100644 index 000000000..bae0f8008 --- /dev/null +++ b/test/core/multi-memory/imports1.wast @@ -0,0 +1,16 @@ +(module + (import "spectest" "memory" (memory 1 2)) + (import "spectest" "memory" (memory 1 2)) + (memory $m (import "spectest" "memory") 1 2) + (import "spectest" "memory" (memory 1 2)) + + (data (memory 2) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load $m (local.get 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + diff --git a/test/core/multi-memory/imports2.wast b/test/core/multi-memory/imports2.wast new file mode 100644 index 000000000..314bc131d --- /dev/null +++ b/test/core/multi-memory/imports2.wast @@ -0,0 +1,73 @@ +(module + (memory (export "z") 0 0) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(module + (import "test" "z" (memory 0)) + (memory $m (import "spectest" "memory") 1 2) + (data (memory 1) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load $m (local.get 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + +(module + (memory (import "spectest" "memory") 1 2) + (data (memory 0) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) +) +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + +(module + (import "test" "memory-2-inf" (memory 2)) + (import "test" "memory-2-inf" (memory 1)) + (import "test" "memory-2-inf" (memory 0)) +) + +(module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 0)) + (import "spectest" "memory" (memory 1 2)) + (import "spectest" "memory" (memory 0 2)) + (import "spectest" "memory" (memory 1 3)) + (import "spectest" "memory" (memory 0 3)) +) + +(assert_unlinkable + (module (import "test" "unknown" (memory 1))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "unknown" (memory 1))) + "unknown import" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (memory 3))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-inf" (memory 2 3))) + "incompatible import type" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 2))) + "incompatible import type" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 1 1))) + "incompatible import type" +) + diff --git a/test/core/multi-memory/imports3.wast b/test/core/multi-memory/imports3.wast new file mode 100644 index 000000000..37cc4eb87 --- /dev/null +++ b/test/core/multi-memory/imports3.wast @@ -0,0 +1,75 @@ +(module + (func (export "func")) + (func (export "func-i32") (param i32)) + (func (export "func-f32") (param f32)) + (func (export "func->i32") (result i32) (i32.const 22)) + (func (export "func->f32") (result f32) (f32.const 11)) + (func (export "func-i32->i32") (param i32) (result i32) (local.get 0)) + (func (export "func-i64->i64") (param i64) (result i64) (local.get 0)) + (global (export "global-i32") i32 (i32.const 55)) + (global (export "global-f32") f32 (f32.const 44)) + (global (export "global-mut-i64") (mut i64) (i64.const 66)) + (table (export "table-10-inf") 10 funcref) + (table (export "table-10-20") 10 20 funcref) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "func-i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "global-i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "table-10-inf" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "print_i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "global_i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "table" (memory 1)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "memory" (memory 2)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "memory" (memory 1 1)) + ) + "incompatible import type" +) diff --git a/test/core/multi-memory/imports4.wast b/test/core/multi-memory/imports4.wast new file mode 100644 index 000000000..411b1c0f4 --- /dev/null +++ b/test/core/multi-memory/imports4.wast @@ -0,0 +1,47 @@ +(module + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(module + (import "test" "memory-2-4" (memory 1)) + (memory $m (import "spectest" "memory") 0 3) ;; actual has max size 2 + (func (export "grow") (param i32) (result i32) (memory.grow $m (local.get 0))) +) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) + +(module $Mgm + (memory 0) + (memory 0) + (memory $m (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow $m (i32.const 1))) +) +(register "grown-memory" $Mgm) +(assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 + +(module $Mgim1 + ;; imported memory limits should match, because external memory size is 2 now + (import "test" "memory-2-4" (memory 1)) + (memory $m (export "memory") (import "grown-memory" "memory") 2) + (memory 0) + (memory 0) + (func (export "grow") (result i32) (memory.grow $m (i32.const 1))) +) +(register "grown-imported-memory" $Mgim1) +(assert_return (invoke $Mgim1 "grow") (i32.const 2)) ;; now size is 3 + +(module $Mgim2 + ;; imported memory limits should match, because external memory size is 3 now + (import "test" "memory-2-4" (memory 1)) + (memory $m (import "grown-imported-memory" "memory") 3) + (memory 0) + (memory 0) + (func (export "size") (result i32) (memory.size $m)) +) +(assert_return (invoke $Mgim2 "size") (i32.const 3)) diff --git a/test/core/multi-memory/linking0.wast b/test/core/multi-memory/linking0.wast new file mode 100644 index 000000000..b09c69f6a --- /dev/null +++ b/test/core/multi-memory/linking0.wast @@ -0,0 +1,42 @@ +(module $Mt + (type (func (result i32))) + (type (func)) + + (table (export "tab") 10 funcref) + (elem (i32.const 2) $g $g $g $g) + (func $g (result i32) (i32.const 4)) + (func (export "h") (result i32) (i32.const -4)) + + (func (export "call") (param i32) (result i32) + (call_indirect (type 0) (local.get 0)) + ) +) +(register "Mt" $Mt) + +(assert_unlinkable + (module + (table (import "Mt" "tab") 10 funcref) + (memory (import "spectest" "memory") 1) + (memory (import "Mt" "mem") 1) ;; does not exist + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (elem (i32.const 9) $f) + ) + "unknown import" +) +(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") + + +(assert_trap + (module + (table (import "Mt" "tab") 10 funcref) + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (memory 0) + (memory $m 1) + (memory 0) + (data $m (i32.const 0x10000) "d") ;; out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) diff --git a/test/core/multi-memory/linking1.wast b/test/core/multi-memory/linking1.wast new file mode 100644 index 000000000..39eabb00b --- /dev/null +++ b/test/core/multi-memory/linking1.wast @@ -0,0 +1,65 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(module $Nm + (func $loadM (import "Mm" "load") (param i32) (result i32)) + (memory (import "Mm" "mem0") 0) + + (memory $m 1) + (data (memory 1) (i32.const 10) "\f0\f1\f2\f3\f4\f5") + + (export "Mm.load" (func $loadM)) + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $m (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) + +(module $Om + (memory (import "Mm" "mem1") 1) + (data (i32.const 5) "\a0\a1\a2\a3\a4\a5\a6\a7") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) +(assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) + +(module + (memory (import "Mm" "mem1") 0) + (data (i32.const 0xffff) "a") +) + +(assert_trap + (module + (memory (import "Mm" "mem0") 0) + (data (i32.const 0xffff) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory (import "Mm" "mem1") 0) + (data (i32.const 0x10000) "a") + ) + "out of bounds memory access" +) + diff --git a/test/core/multi-memory/linking2.wast b/test/core/multi-memory/linking2.wast new file mode 100644 index 000000000..26bf3cca2 --- /dev/null +++ b/test/core/multi-memory/linking2.wast @@ -0,0 +1,30 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(module $Pm + (memory (import "Mm" "mem1") 1 8) + + (func (export "grow") (param $a i32) (result i32) + (memory.grow (local.get 0)) + ) +) + +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 4)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) + diff --git a/test/core/multi-memory/linking3.wast b/test/core/multi-memory/linking3.wast new file mode 100644 index 000000000..e23fbe4e6 --- /dev/null +++ b/test/core/multi-memory/linking3.wast @@ -0,0 +1,83 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 5 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(assert_unlinkable + (module + (func $host (import "spectest" "print")) + (memory (import "Mm" "mem1") 1) + (table (import "Mm" "tab") 0 funcref) ;; does not exist + (data (i32.const 0) "abc") + ) + "unknown import" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0)) + +;; Unlike in v1 spec, active data segments written before an +;; out-of-bounds access persist after the instantiation failure. +(assert_trap + (module + ;; Note: the memory is 5 pages large by the time we get here. + (memory (import "Mm" "mem1") 1) + (data (i32.const 0) "abc") + (data (i32.const 327670) "zzzzzzzzzzzzzzzzzz") ;; (partially) out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) +(assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) + +(assert_trap + (module + (memory (import "Mm" "mem1") 1) + (data (i32.const 0) "abc") + (table 0 funcref) + (func) + (elem (i32.const 0) 0) ;; out of bounds + ) + "out of bounds table access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + +;; Store is modified if the start function traps. +(module $Ms + (type $t (func (result i32))) + (memory (export "memory") 1) + (table (export "table") 1 funcref) + (func (export "get memory[0]") (type $t) + (i32.load8_u (i32.const 0)) + ) + (func (export "get table[0]") (type $t) + (call_indirect (type $t) (i32.const 0)) + ) +) +(register "Ms" $Ms) + +(assert_trap + (module + (import "Ms" "memory" (memory 1)) + (import "Ms" "table" (table 1 funcref)) + (data (i32.const 0) "hello") + (elem (i32.const 0) $f) + (func $f (result i32) + (i32.const 0xdead) + ) + (func $main + (unreachable) + ) + (start $main) + ) + "unreachable" +) + +(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' +(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) diff --git a/test/core/multi-memory/load0.wast b/test/core/multi-memory/load0.wast new file mode 100644 index 000000000..2332a2008 --- /dev/null +++ b/test/core/multi-memory/load0.wast @@ -0,0 +1,19 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (data (memory $mem1) (i32.const 0) "\01") + (data (memory $mem2) (i32.const 0) "\02") +) + +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/test/core/multi-memory/load1.wast b/test/core/multi-memory/load1.wast new file mode 100644 index 000000000..be309c39c --- /dev/null +++ b/test/core/multi-memory/load1.wast @@ -0,0 +1,41 @@ +(module $M + (memory (export "mem") 2) + + (func (export "read") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) +) + +(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read1" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read1" (i32.const 23)) (i32.const 4)) +(assert_return (invoke "read1" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read2" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read2" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read2" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read2" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read2" (i32.const 54)) (i32.const 14)) diff --git a/test/core/multi-memory/load2.wast b/test/core/multi-memory/load2.wast new file mode 100644 index 000000000..dfe6fed76 --- /dev/null +++ b/test/core/multi-memory/load2.wast @@ -0,0 +1,213 @@ +(module + (memory 0) + (memory 0) + (memory 0) + (memory $m 1) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (i32.load $m (i32.const 0)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (i32.load $m (i32.const 0)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (i32.load $m (i32.const 0)) (i32.const 1))) (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (i32.load $m (i32.const 0)))) (i32.const 7) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (i32.load $m (i32.const 0)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (i32.load $m (i32.const 0)) (i32.const 1)) (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (i32.load $m (i32.const 0))) (i32.const 7) + ) + ) + + (func (export "as-return-value") (result i32) + (return (i32.load $m (i32.const 0))) + ) + + (func (export "as-if-cond") (result i32) + (if (result i32) (i32.load $m (i32.const 0)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (i32.load $m (i32.const 0))) (else (i32.const 0)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 0)) (else (i32.load $m (i32.const 0))) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (select (i32.load $m (i32.const 0)) (local.get 0) (local.get 1)) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (select (local.get 0) (i32.load $m (i32.const 0)) (local.get 1)) + ) + (func (export "as-select-cond") (result i32) + (select (i32.const 0) (i32.const 1) (i32.load $m (i32.const 0))) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (call $f (i32.load $m (i32.const 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (result i32) + (call $f (i32.const 1) (i32.load $m (i32.const 0)) (i32.const 3)) + ) + (func (export "as-call-last") (result i32) + (call $f (i32.const 1) (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (result i32) + (call_indirect (type $sig) + (i32.load $m (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.load $m (i32.const 0)) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.load $m (i32.const 0)) (i32.const 0) + ) + ) + (func (export "as-call_indirect-index") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.const 3) (i32.load $m (i32.const 0)) + ) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (i32.load $m (i32.const 0))) + ) + (func (export "as-local.tee-value") (result i32) (local i32) + (local.tee 0 (i32.load $m (i32.const 0))) + ) + (global $g (mut i32) (i32.const 0)) + (func (export "as-global.set-value") (local i32) + (global.set $g (i32.load $m (i32.const 0))) + ) + + (func (export "as-load-address") (result i32) + (i32.load $m (i32.load $m (i32.const 0))) + ) + (func (export "as-loadN-address") (result i32) + (i32.load8_s $m (i32.load $m (i32.const 0))) + ) + + (func (export "as-store-address") + (i32.store $m (i32.load $m (i32.const 0)) (i32.const 7)) + ) + (func (export "as-store-value") + (i32.store $m (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (func (export "as-storeN-address") + (i32.store8 $m (i32.load8_s $m (i32.const 0)) (i32.const 7)) + ) + (func (export "as-storeN-value") + (i32.store16 $m (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (func (export "as-unary-operand") (result i32) + (i32.clz (i32.load $m (i32.const 100))) + ) + + (func (export "as-binary-left") (result i32) + (i32.add (i32.load $m (i32.const 100)) (i32.const 10)) + ) + (func (export "as-binary-right") (result i32) + (i32.sub (i32.const 10) (i32.load $m (i32.const 100))) + ) + + (func (export "as-test-operand") (result i32) + (i32.eqz (i32.load $m (i32.const 100))) + ) + + (func (export "as-compare-left") (result i32) + (i32.le_s (i32.load $m (i32.const 100)) (i32.const 10)) + ) + (func (export "as-compare-right") (result i32) + (i32.ne (i32.const 10) (i32.load $m (i32.const 100))) + ) + + (func (export "as-memory.grow-size") (result i32) + (memory.grow $m (i32.load $m (i32.const 100))) + ) +) + +(assert_return (invoke "as-br-value") (i32.const 0)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 0)) +(assert_return (invoke "as-br_if-value-cond") (i32.const 7)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 0)) +(assert_return (invoke "as-br_table-value-index") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 0)) + +(assert_return (invoke "as-if-cond") (i32.const 1)) +(assert_return (invoke "as-if-then") (i32.const 0)) +(assert_return (invoke "as-if-else") (i32.const 0)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-select-cond") (i32.const 1)) + +(assert_return (invoke "as-call-first") (i32.const -1)) +(assert_return (invoke "as-call-mid") (i32.const -1)) +(assert_return (invoke "as-call-last") (i32.const -1)) + +(assert_return (invoke "as-call_indirect-first") (i32.const -1)) +(assert_return (invoke "as-call_indirect-mid") (i32.const -1)) +(assert_return (invoke "as-call_indirect-last") (i32.const -1)) +(assert_return (invoke "as-call_indirect-index") (i32.const -1)) + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value") (i32.const 0)) +(assert_return (invoke "as-global.set-value")) + +(assert_return (invoke "as-load-address") (i32.const 0)) +(assert_return (invoke "as-loadN-address") (i32.const 0)) +(assert_return (invoke "as-store-address")) +(assert_return (invoke "as-store-value")) +(assert_return (invoke "as-storeN-address")) +(assert_return (invoke "as-storeN-value")) + +(assert_return (invoke "as-unary-operand") (i32.const 32)) + +(assert_return (invoke "as-binary-left") (i32.const 10)) +(assert_return (invoke "as-binary-right") (i32.const 10)) + +(assert_return (invoke "as-test-operand") (i32.const 1)) + +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) + +(assert_return (invoke "as-memory.grow-size") (i32.const 1)) + diff --git a/test/core/multi-memory/local_tee0.wast b/test/core/multi-memory/local_tee0.wast new file mode 100644 index 000000000..6594ecc72 --- /dev/null +++ b/test/core/multi-memory/local_tee0.wast @@ -0,0 +1,19 @@ +(module + (memory $mem0 0) + (memory $mem1 2) + (memory $mem2 5) + + (func (export "as-memory.grow-size0") (param i32) (result i32) + (memory.grow $mem0 (local.tee 0 (i32.const 40))) + ) + (func (export "as-memory.grow-size1") (param i32) (result i32) + (memory.grow $mem1 (local.tee 0 (i32.const 40))) + ) + (func (export "as-memory.grow-size2") (param i32) (result i32) + (memory.grow $mem2 (local.tee 0 (i32.const 40))) + ) +) + +(assert_return (invoke "as-memory.grow-size0" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-memory.grow-size1" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-memory.grow-size2" (i32.const 0)) (i32.const 5)) diff --git a/test/core/multi-memory/loop0.wast b/test/core/multi-memory/loop0.wast new file mode 100644 index 000000000..9e5cbc59b --- /dev/null +++ b/test/core/multi-memory/loop0.wast @@ -0,0 +1,19 @@ +(module + (memory $mem0 0) + (memory $mem1 4) + (memory $mem2 9) + + (func (export "as-memory.grow-value0") (result i32) + (memory.grow $mem0 (loop (result i32) (i32.const 1))) + ) + (func (export "as-memory.grow-value1") (result i32) + (memory.grow $mem1 (loop (result i32) (i32.const 1))) + ) + (func (export "as-memory.grow-value2") (result i32) + (memory.grow $mem2 (loop (result i32) (i32.const 1))) + ) +) + +(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) +(assert_return (invoke "as-memory.grow-value1") (i32.const 4)) +(assert_return (invoke "as-memory.grow-value2") (i32.const 9)) diff --git a/test/core/multi-memory/memory_copy0.wast b/test/core/multi-memory/memory_copy0.wast new file mode 100644 index 000000000..5a5d910e7 --- /dev/null +++ b/test/core/multi-memory/memory_copy0.wast @@ -0,0 +1,60 @@ +;; memory.copy +(module + (memory $mem0 (data "\ff\11\44\ee")) + (memory $mem1 (data "\ee\22\55\ff")) + (memory $mem2 (data "\dd\33\66\00")) + (memory $mem3 (data "\aa\bb\cc\dd")) + + (func (export "copy") (param i32 i32 i32) + (memory.copy $mem3 $mem3 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem3 (local.get 0))) +) + +;; Non-overlapping copy. +(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) + +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) + +;; Overlap, source > dest +(invoke "copy" (i32.const 8) (i32.const 10) (i32.const 4)) +(assert_return (invoke "load8_u" (i32.const 8)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) + +;; Overlap, source < dest +(invoke "copy" (i32.const 10) (i32.const 7) (i32.const 6)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0)) + +;; Copy ending at memory limit is ok. +(invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) +(invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) + +;; Succeed when copying 0 bytes at the end of the region. +(invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) + +;; Copying 0 bytes outside the memory traps. +(assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) + "out of bounds memory access") + diff --git a/test/core/multi-memory/memory_copy1.wast b/test/core/multi-memory/memory_copy1.wast new file mode 100644 index 000000000..b224bfe20 --- /dev/null +++ b/test/core/multi-memory/memory_copy1.wast @@ -0,0 +1 @@ +;; TODO: test copy across different memories. diff --git a/test/core/multi-memory/memory_fill0.wast b/test/core/multi-memory/memory_fill0.wast new file mode 100644 index 000000000..eaf15bf5a --- /dev/null +++ b/test/core/multi-memory/memory_fill0.wast @@ -0,0 +1,46 @@ +;; memory.fill +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 1) + + (func (export "fill") (param i32 i32 i32) + (memory.fill $mem2 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0))) +) + +;; Basic fill test. +(invoke "fill" (i32.const 1) (i32.const 0xff) (i32.const 3)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 3)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 4)) (i32.const 0)) + +;; Fill value is stored as a byte. +(invoke "fill" (i32.const 0) (i32.const 0xbbaa) (i32.const 2)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xaa)) + +;; Fill all of memory +(invoke "fill" (i32.const 0) (i32.const 0) (i32.const 0x10000)) + +;; Out-of-bounds writes trap, and nothing is written +(assert_trap (invoke "fill" (i32.const 0xff00) (i32.const 1) (i32.const 0x101)) + "out of bounds memory access") +(assert_return (invoke "load8_u" (i32.const 0xff00)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0)) + +;; Succeed when writing 0 bytes at the end of the region. +(invoke "fill" (i32.const 0x10000) (i32.const 0) (i32.const 0)) + +;; Writing 0 bytes outside the memory traps. +(assert_trap (invoke "fill" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") + + diff --git a/test/core/multi-memory/memory_init0.wast b/test/core/multi-memory/memory_init0.wast new file mode 100644 index 000000000..190da6b9d --- /dev/null +++ b/test/core/multi-memory/memory_init0.wast @@ -0,0 +1,42 @@ +;; memory.init +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 1) + (memory $mem3 0) + (data $mem2 "\aa\bb\cc\dd") + + (func (export "init") (param i32 i32 i32) + (memory.init $mem2 0 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0))) +) + +(invoke "init" (i32.const 0) (i32.const 1) (i32.const 2)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0)) + +;; Init ending at memory limit and segment limit is ok. +(invoke "init" (i32.const 0xfffc) (i32.const 0) (i32.const 4)) + +;; Out-of-bounds writes trap, and nothing is written. +(assert_trap (invoke "init" (i32.const 0xfffe) (i32.const 0) (i32.const 3)) + "out of bounds memory access") +(assert_return (invoke "load8_u" (i32.const 0xfffe)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0xdd)) + +;; Succeed when writing 0 bytes at the end of either region. +(invoke "init" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "init" (i32.const 0) (i32.const 4) (i32.const 0)) + +;; Writing 0 bytes outside the memory traps. +(assert_trap (invoke "init" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0)) + "out of bounds memory access") + diff --git a/test/core/multi-memory/memory_size0.wast b/test/core/multi-memory/memory_size0.wast new file mode 100644 index 000000000..47ad9ec4b --- /dev/null +++ b/test/core/multi-memory/memory_size0.wast @@ -0,0 +1,19 @@ +(module + (memory 0) + (memory 0) + (memory 0) + (memory 0) + (memory $m 0) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 5)) + diff --git a/test/core/multi-memory/memory_size1.wast b/test/core/multi-memory/memory_size1.wast new file mode 100644 index 000000000..69026a650 --- /dev/null +++ b/test/core/multi-memory/memory_size1.wast @@ -0,0 +1,29 @@ +(module + (memory 0) + (memory 0) + (memory $n 0) + (memory 0) + (memory $m 0) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) + + (func (export "sizen") (result i32) (memory.size $n)) + (func (export "grown") (param $sz i32) (drop (memory.grow $n (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 0)) + +(assert_return (invoke "grown" (i32.const 1))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 1)) diff --git a/test/core/multi-memory/memory_size2.wast b/test/core/multi-memory/memory_size2.wast new file mode 100644 index 000000000..e59917e37 --- /dev/null +++ b/test/core/multi-memory/memory_size2.wast @@ -0,0 +1,34 @@ +(module + (memory 0 0) + (memory 0 0) + (memory $n 0 0) + (memory $m 0 2) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) + + (func (export "sizen") (result i32) (memory.size $n)) + (func (export "grown") (param $sz i32) (drop (memory.grow $n (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 3))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 2)) + +(assert_return (invoke "grown" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 2)) diff --git a/test/core/multi-memory/memory_size3.wast b/test/core/multi-memory/memory_size3.wast new file mode 100644 index 000000000..834aa1c36 --- /dev/null +++ b/test/core/multi-memory/memory_size3.wast @@ -0,0 +1,25 @@ +;; Type errors + +(assert_invalid + (module + (memory 0) + (memory $m 1) + (memory 0) + (func $type-result-i32-vs-empty + (memory.size $m) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (memory 0) + (memory 0) + (memory $m 1) + (func $type-result-i32-vs-f32 (result f32) + (memory.size $m) + ) + ) + "type mismatch" +) diff --git a/test/core/multi-memory/memory_trap0.wast b/test/core/multi-memory/memory_trap0.wast new file mode 100644 index 000000000..26ecdf844 --- /dev/null +++ b/test/core/multi-memory/memory_trap0.wast @@ -0,0 +1,36 @@ +(module + (memory 0) + (memory 0) + (memory $m 1) + + (func $addr_limit (result i32) + (i32.mul (memory.size $m) (i32.const 0x10000)) + ) + + (func (export "store") (param $i i32) (param $v i32) + (i32.store $m (i32.add (call $addr_limit) (local.get $i)) (local.get $v)) + ) + + (func (export "load") (param $i i32) (result i32) + (i32.load $m (i32.add (call $addr_limit) (local.get $i))) + ) + + (func (export "memory.grow") (param i32) (result i32) + (memory.grow $m (local.get 0)) + ) +) + +(assert_return (invoke "store" (i32.const -4) (i32.const 42))) +(assert_return (invoke "load" (i32.const -4)) (i32.const 42)) +(assert_trap (invoke "store" (i32.const -3) (i32.const 0x12345678)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const -2) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const -1) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const 0) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const 0x80000000) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const 0x80000000)) "out of bounds memory access") +(assert_return (invoke "memory.grow" (i32.const 0x10001)) (i32.const -1)) + diff --git a/test/core/multi-memory/memory_trap1.wast b/test/core/multi-memory/memory_trap1.wast new file mode 100644 index 000000000..bd692d04c --- /dev/null +++ b/test/core/multi-memory/memory_trap1.wast @@ -0,0 +1,250 @@ +(module + (memory 0) + (memory 0) + (memory $m 1) + (data (memory 2) (i32.const 0) "abcdefgh") + (data (memory 2) (i32.const 0xfff8) "abcdefgh") + + (func (export "i32.load") (param $a i32) (result i32) + (i32.load $m (local.get $a)) + ) + (func (export "i64.load") (param $a i32) (result i64) + (i64.load $m (local.get $a)) + ) + (func (export "f32.load") (param $a i32) (result f32) + (f32.load $m (local.get $a)) + ) + (func (export "f64.load") (param $a i32) (result f64) + (f64.load $m (local.get $a)) + ) + (func (export "i32.load8_s") (param $a i32) (result i32) + (i32.load8_s $m (local.get $a)) + ) + (func (export "i32.load8_u") (param $a i32) (result i32) + (i32.load8_u $m (local.get $a)) + ) + (func (export "i32.load16_s") (param $a i32) (result i32) + (i32.load16_s $m (local.get $a)) + ) + (func (export "i32.load16_u") (param $a i32) (result i32) + (i32.load16_u $m (local.get $a)) + ) + (func (export "i64.load8_s") (param $a i32) (result i64) + (i64.load8_s $m (local.get $a)) + ) + (func (export "i64.load8_u") (param $a i32) (result i64) + (i64.load8_u $m (local.get $a)) + ) + (func (export "i64.load16_s") (param $a i32) (result i64) + (i64.load16_s $m (local.get $a)) + ) + (func (export "i64.load16_u") (param $a i32) (result i64) + (i64.load16_u $m (local.get $a)) + ) + (func (export "i64.load32_s") (param $a i32) (result i64) + (i64.load32_s $m (local.get $a)) + ) + (func (export "i64.load32_u") (param $a i32) (result i64) + (i64.load32_u $m (local.get $a)) + ) + (func (export "i32.store") (param $a i32) (param $v i32) + (i32.store $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store") (param $a i32) (param $v i64) + (i64.store $m (local.get $a) (local.get $v)) + ) + (func (export "f32.store") (param $a i32) (param $v f32) + (f32.store $m (local.get $a) (local.get $v)) + ) + (func (export "f64.store") (param $a i32) (param $v f64) + (f64.store $m (local.get $a) (local.get $v)) + ) + (func (export "i32.store8") (param $a i32) (param $v i32) + (i32.store8 $m (local.get $a) (local.get $v)) + ) + (func (export "i32.store16") (param $a i32) (param $v i32) + (i32.store16 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store8") (param $a i32) (param $v i64) + (i64.store8 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store16") (param $a i32) (param $v i64) + (i64.store16 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store32") (param $a i32) (param $v i64) + (i64.store32 $m (local.get $a) (local.get $v)) + ) +) + +(assert_trap (invoke "i32.store" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xfffe) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -2) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -3) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -4) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffc) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffb) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffa) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -3) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -4) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -5) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -6) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -7) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -8) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0x10000) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xffff) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xfffe) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -1) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -2) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -3) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -4) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0x10000) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xffff) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffe) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffd) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffc) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffb) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffa) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -1) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -2) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -3) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -4) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -5) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -6) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -7) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -8) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store8" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store8" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const -2) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store8" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store8" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -3) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -4) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffc)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffb)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffa)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfff9)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -5)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -6)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -7)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -8)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffc)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffb)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffa)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfff9)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -5)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -6)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -7)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -8)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -4)) "out of bounds memory access") + +;; No memory was changed +(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0x6867666564636261)) +(assert_return (invoke "i64.load" (i32.const 0)) (i64.const 0x6867666564636261)) + +;; Check that out of bounds store do not store partial data. +;; Zero last 8 bytes. +(assert_return (invoke "i64.store" (i32.const 0xfff8) (i64.const 0))) +(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0x12345678)) "out of bounds memory access") +(assert_return (invoke "i32.load" (i32.const 0xfffc)) (i32.const 0)) +(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0x1234567890abcdef)) "out of bounds memory access") +(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0)) +(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0x12345678)) "out of bounds memory access") +(assert_return (invoke "f32.load" (i32.const 0xfffc)) (f32.const 0)) +(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0x1234567890abcdef)) "out of bounds memory access") +(assert_return (invoke "f64.load" (i32.const 0xfff8)) (f64.const 0)) diff --git a/test/core/multi-memory/return0.wast b/test/core/multi-memory/return0.wast new file mode 100644 index 000000000..9c3c0193f --- /dev/null +++ b/test/core/multi-memory/return0.wast @@ -0,0 +1,19 @@ +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 4) + + (func (export "as-memory.grow-size0") (result i32) + (memory.grow $mem0 (return (i32.const 40))) + ) + (func (export "as-memory.grow-size1") (result i32) + (memory.grow $mem1 (return (i32.const 40))) + ) + (func (export "as-memory.grow-size2") (result i32) + (memory.grow $mem2 (return (i32.const 40))) + ) +) + +(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) +(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) +(assert_return (invoke "as-memory.grow-size2") (i32.const 40)) diff --git a/test/core/multi-memory/select0.wast b/test/core/multi-memory/select0.wast new file mode 100644 index 000000000..87f46bf3d --- /dev/null +++ b/test/core/multi-memory/select0.wast @@ -0,0 +1,24 @@ +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 7) + + (func (export "as-memory.grow-value0") (param i32) (result i32) + (memory.grow $mem0 (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + (func (export "as-memory.grow-value1") (param i32) (result i32) + (memory.grow $mem1 (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + (func (export "as-memory.grow-value2") (param i32) (result i32) + (memory.grow $mem2 (select (i32.const 1) (i32.const 2) (local.get 0))) + ) +) + +(assert_return (invoke "as-memory.grow-value0" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-memory.grow-value0" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-memory.grow-value1" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-memory.grow-value1" (i32.const 1)) (i32.const 3)) + +(assert_return (invoke "as-memory.grow-value2" (i32.const 0)) (i32.const 7)) +(assert_return (invoke "as-memory.grow-value2" (i32.const 1)) (i32.const 9)) diff --git a/test/core/multi-memory/start0.wast b/test/core/multi-memory/start0.wast new file mode 100644 index 000000000..677279ed6 --- /dev/null +++ b/test/core/multi-memory/start0.wast @@ -0,0 +1,42 @@ +(module + (memory 0) + (memory $m (data "A")) + (memory $n 1) + + (func $inc + (i32.store8 $m + (i32.const 0) + (i32.add + (i32.load8_u $m (i32.const 0)) + (i32.const 1) + ) + ) + ) + (func $get (result i32) + (return (i32.load8_u $m (i32.const 0))) + ) + (func $getn (result i32) + (return (i32.load8_u $n (i32.const 0))) + ) + (func $main + (call $inc) + (call $inc) + (call $inc) + ) + + (start $main) + (export "inc" (func $inc)) + (export "get" (func $get)) + (export "getn" (func $getn)) +) +(assert_return (invoke "get") (i32.const 68)) +(assert_return (invoke "getn") (i32.const 0)) + +(invoke "inc") +(assert_return (invoke "get") (i32.const 69)) +(assert_return (invoke "getn") (i32.const 0)) + +(invoke "inc") +(assert_return (invoke "get") (i32.const 70)) +(assert_return (invoke "getn") (i32.const 0)) + diff --git a/test/core/multi-memory/store0.wast b/test/core/multi-memory/store0.wast new file mode 100644 index 000000000..2f217b1f9 --- /dev/null +++ b/test/core/multi-memory/store0.wast @@ -0,0 +1,25 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/test/core/multi-memory/store1.wast b/test/core/multi-memory/store1.wast new file mode 100644 index 000000000..10cf2c426 --- /dev/null +++ b/test/core/multi-memory/store1.wast @@ -0,0 +1,52 @@ +(module $M1 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M1") + +(module $M2 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M2") + +(invoke $M1 "store" (i32.const 0) (i64.const 1)) +(invoke $M2 "store" (i32.const 0) (i64.const 2)) +(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) + +(module + (memory $mem1 (import "M1" "mem") 1) + (memory $mem2 (import "M2" "mem") 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/test/core/multi-memory/traps.wast b/test/core/multi-memory/traps.wast new file mode 100644 index 000000000..fd942e4b6 --- /dev/null +++ b/test/core/multi-memory/traps.wast @@ -0,0 +1,35 @@ +(module + (memory $mem0 1) + (memory $mem1 1) + (memory $mem2 1) + + (func (export "no_dce.i32.load") (param $i i32) (drop (i32.load $mem1 (local.get $i)))) + (func (export "no_dce.i32.load16_s") (param $i i32) (drop (i32.load16_s $mem1 (local.get $i)))) + (func (export "no_dce.i32.load16_u") (param $i i32) (drop (i32.load16_u $mem1 (local.get $i)))) + (func (export "no_dce.i32.load8_s") (param $i i32) (drop (i32.load8_s $mem1 (local.get $i)))) + (func (export "no_dce.i32.load8_u") (param $i i32) (drop (i32.load8_u $mem1 (local.get $i)))) + (func (export "no_dce.i64.load") (param $i i32) (drop (i64.load $mem1 (local.get $i)))) + (func (export "no_dce.i64.load32_s") (param $i i32) (drop (i64.load32_s $mem1 (local.get $i)))) + (func (export "no_dce.i64.load32_u") (param $i i32) (drop (i64.load32_u $mem2 (local.get $i)))) + (func (export "no_dce.i64.load16_s") (param $i i32) (drop (i64.load16_s $mem2 (local.get $i)))) + (func (export "no_dce.i64.load16_u") (param $i i32) (drop (i64.load16_u $mem2 (local.get $i)))) + (func (export "no_dce.i64.load8_s") (param $i i32) (drop (i64.load8_s $mem2 (local.get $i)))) + (func (export "no_dce.i64.load8_u") (param $i i32) (drop (i64.load8_u $mem2 (local.get $i)))) + (func (export "no_dce.f32.load") (param $i i32) (drop (f32.load $mem2 (local.get $i)))) + (func (export "no_dce.f64.load") (param $i i32) (drop (f64.load $mem2 (local.get $i)))) +) + +(assert_trap (invoke "no_dce.i32.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load16_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load16_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load8_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load8_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load32_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load32_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load16_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load16_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load8_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load8_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.f32.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.f64.load" (i32.const 65536)) "out of bounds memory access") diff --git a/test/core/run.py b/test/core/run.py index 924b42c69..cabb6188f 100755 --- a/test/core/run.py +++ b/test/core/run.py @@ -25,11 +25,12 @@ main_test_files = glob.glob(os.path.join(inputDir, "*.wast")) # SIMD test files are in a subdirectory. simd_test_files = glob.glob(os.path.join(inputDir, "simd", "*.wast")) +multi_memory_test_files = glob.glob(os.path.join(inputDir, "multi-memory", "*.wast")) wasmCommand = arguments.wasm jsCommand = arguments.js outputDir = arguments.out -inputFiles = arguments.file if arguments.file else main_test_files + simd_test_files +inputFiles = arguments.file if arguments.file else main_test_files + simd_test_files + multi_memory_test_files if not os.path.exists(wasmCommand): sys.stderr.write("""\ From 078a610f56662e074900b6f8ac0a8577e1344ed8 Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Tue, 28 Feb 2023 13:23:58 -0500 Subject: [PATCH 043/181] Remove incidental usages of multi-memory in new tests --- test/core/multi-memory/block0.wast | 18 -------------- test/core/multi-memory/br0.wast | 15 ----------- test/core/multi-memory/br_if0.wast | 15 ----------- test/core/multi-memory/br_table0.wast | 15 ----------- test/core/multi-memory/call0.wast | 21 ---------------- test/core/multi-memory/call_indirect0.wast | 22 ---------------- test/core/multi-memory/global0.wast | 21 ---------------- test/core/multi-memory/if0.wast | 29 ---------------------- test/core/multi-memory/local_tee0.wast | 19 -------------- test/core/multi-memory/loop0.wast | 19 -------------- test/core/multi-memory/return0.wast | 19 -------------- test/core/multi-memory/select0.wast | 24 ------------------ 12 files changed, 237 deletions(-) delete mode 100644 test/core/multi-memory/block0.wast delete mode 100644 test/core/multi-memory/br0.wast delete mode 100644 test/core/multi-memory/br_if0.wast delete mode 100644 test/core/multi-memory/br_table0.wast delete mode 100644 test/core/multi-memory/call0.wast delete mode 100644 test/core/multi-memory/call_indirect0.wast delete mode 100644 test/core/multi-memory/global0.wast delete mode 100644 test/core/multi-memory/if0.wast delete mode 100644 test/core/multi-memory/local_tee0.wast delete mode 100644 test/core/multi-memory/loop0.wast delete mode 100644 test/core/multi-memory/return0.wast delete mode 100644 test/core/multi-memory/select0.wast diff --git a/test/core/multi-memory/block0.wast b/test/core/multi-memory/block0.wast deleted file mode 100644 index a012ebc8a..000000000 --- a/test/core/multi-memory/block0.wast +++ /dev/null @@ -1,18 +0,0 @@ -;; Test `block` operator - -(module - ;; Auxiliary definition - (memory $mem0 1) - (memory $mem1 1) - - (func (export "as-memory.grow-value1") (result i32) - (memory.grow $mem0 (block (result i32) (i32.const 1))) - ) - - (func (export "as-memory.grow-value2") (result i32) - (memory.grow $mem1 (block (result i32) (i32.const 1))) - ) -) - -(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) -(assert_return (invoke "as-memory.grow-value2") (i32.const 1)) diff --git a/test/core/multi-memory/br0.wast b/test/core/multi-memory/br0.wast deleted file mode 100644 index 509e7b068..000000000 --- a/test/core/multi-memory/br0.wast +++ /dev/null @@ -1,15 +0,0 @@ -(module - (memory $mem0 1) - (memory $mem1 1) - - (func (export "as-memory.grow-size0") (result i32) - (block (result i32) (memory.grow $mem0 (br 0 (i32.const 40)))) - ) - - (func (export "as-memory.grow-size1") (result i32) - (block (result i32) (memory.grow $mem1 (br 0 (i32.const 40)))) - ) -) - -(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) -(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) diff --git a/test/core/multi-memory/br_if0.wast b/test/core/multi-memory/br_if0.wast deleted file mode 100644 index 2b7a32b40..000000000 --- a/test/core/multi-memory/br_if0.wast +++ /dev/null @@ -1,15 +0,0 @@ -(module - (memory $mem0 1) - (memory $mem1 1) - - (func (export "as-memory.grow-size0") (result i32) - (block (result i32) (memory.grow $mem0 (br_if 0 (i32.const 1) (i32.const 1)))) - ) - - (func (export "as-memory.grow-size1") (result i32) - (block (result i32) (memory.grow $mem1 (br_if 0 (i32.const 1) (i32.const 1)))) - ) -) - -(assert_return (invoke "as-memory.grow-size0") (i32.const 1)) -(assert_return (invoke "as-memory.grow-size1") (i32.const 1)) diff --git a/test/core/multi-memory/br_table0.wast b/test/core/multi-memory/br_table0.wast deleted file mode 100644 index 0cb89b395..000000000 --- a/test/core/multi-memory/br_table0.wast +++ /dev/null @@ -1,15 +0,0 @@ -(module - (memory $mem0 1) - (memory $mem1 1) - - (func (export "as-memory.grow-size0") (result i32) - (block (result i32) (memory.grow $mem0 (br_table 0 (i32.const 40) (i32.const 0)))) - ) - - (func (export "as-memory.grow-size1") (result i32) - (block (result i32) (memory.grow $mem1 (br_table 0 (i32.const 40) (i32.const 0)))) - ) -) - -(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) -(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) diff --git a/test/core/multi-memory/call0.wast b/test/core/multi-memory/call0.wast deleted file mode 100644 index 4d48fcfa3..000000000 --- a/test/core/multi-memory/call0.wast +++ /dev/null @@ -1,21 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 1) - (memory $mem2 2) - - (func $const-i32 (result i32) (i32.const 0x12)) - - (func (export "as-memory.grow-value0") (result i32) - (memory.grow $mem0 (call $const-i32)) - ) - (func (export "as-memory.grow-value1") (result i32) - (memory.grow $mem1 (call $const-i32)) - ) - (func (export "as-memory.grow-value2") (result i32) - (memory.grow $mem2 (call $const-i32)) - ) -) - -(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) -(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) -(assert_return (invoke "as-memory.grow-value2") (i32.const 2)) diff --git a/test/core/multi-memory/call_indirect0.wast b/test/core/multi-memory/call_indirect0.wast deleted file mode 100644 index 11cbdf4e4..000000000 --- a/test/core/multi-memory/call_indirect0.wast +++ /dev/null @@ -1,22 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 1) - - (type $out-i32 (func (result i32))) - - (table funcref - (elem - $const-i32 )) - - (func $const-i32 (type $out-i32) (i32.const 0x132)) - - (func (export "as-memory.grow-value0") (result i32) - (memory.grow $mem0 (call_indirect (type $out-i32) (i32.const 0))) - ) - (func (export "as-memory.grow-value1") (result i32) - (memory.grow $mem1 (call_indirect (type $out-i32) (i32.const 0))) - ) -) - -(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) -(assert_return (invoke "as-memory.grow-value1") (i32.const 1)) diff --git a/test/core/multi-memory/global0.wast b/test/core/multi-memory/global0.wast deleted file mode 100644 index 00d99d5cd..000000000 --- a/test/core/multi-memory/global0.wast +++ /dev/null @@ -1,21 +0,0 @@ -(module - (memory $mem0 3) - (memory $mem1 4) - (memory $mem2 9) - - (global $x (mut i32) (i32.const 3)) - - (func (export "as-memory.grow-value0") (result i32) - (memory.grow $mem0 (global.get $x)) - ) - (func (export "as-memory.grow-value1") (result i32) - (memory.grow $mem1 (global.get $x)) - ) - (func (export "as-memory.grow-value2") (result i32) - (memory.grow $mem2 (global.get $x)) - ) -) - -(assert_return (invoke "as-memory.grow-value0") (i32.const 3)) -(assert_return (invoke "as-memory.grow-value1") (i32.const 4)) -(assert_return (invoke "as-memory.grow-value2") (i32.const 9)) diff --git a/test/core/multi-memory/if0.wast b/test/core/multi-memory/if0.wast deleted file mode 100644 index 1a82abd79..000000000 --- a/test/core/multi-memory/if0.wast +++ /dev/null @@ -1,29 +0,0 @@ -(module - (memory $mem0 1) - (memory $mem1 4) - - (func (export "as-memory.grow-value0") (param i32) (result i32) - (memory.grow $mem0 - (if (result i32) (local.get 0) - (then (i32.const 1)) - (else (i32.const 0)) - ) - ) - ) - - (func (export "as-memory.grow-value1") (param i32) (result i32) - (memory.grow $mem1 - (if (result i32) (local.get 0) - (then (i32.const 1)) - (else (i32.const 0)) - ) - ) - ) -) - -(assert_return (invoke "as-memory.grow-value0" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "as-memory.grow-value0" (i32.const 1)) (i32.const 1)) - -(assert_return (invoke "as-memory.grow-value1" (i32.const 0)) (i32.const 4)) -(assert_return (invoke "as-memory.grow-value1" (i32.const 1)) (i32.const 4)) - diff --git a/test/core/multi-memory/local_tee0.wast b/test/core/multi-memory/local_tee0.wast deleted file mode 100644 index 6594ecc72..000000000 --- a/test/core/multi-memory/local_tee0.wast +++ /dev/null @@ -1,19 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 2) - (memory $mem2 5) - - (func (export "as-memory.grow-size0") (param i32) (result i32) - (memory.grow $mem0 (local.tee 0 (i32.const 40))) - ) - (func (export "as-memory.grow-size1") (param i32) (result i32) - (memory.grow $mem1 (local.tee 0 (i32.const 40))) - ) - (func (export "as-memory.grow-size2") (param i32) (result i32) - (memory.grow $mem2 (local.tee 0 (i32.const 40))) - ) -) - -(assert_return (invoke "as-memory.grow-size0" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "as-memory.grow-size1" (i32.const 0)) (i32.const 2)) -(assert_return (invoke "as-memory.grow-size2" (i32.const 0)) (i32.const 5)) diff --git a/test/core/multi-memory/loop0.wast b/test/core/multi-memory/loop0.wast deleted file mode 100644 index 9e5cbc59b..000000000 --- a/test/core/multi-memory/loop0.wast +++ /dev/null @@ -1,19 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 4) - (memory $mem2 9) - - (func (export "as-memory.grow-value0") (result i32) - (memory.grow $mem0 (loop (result i32) (i32.const 1))) - ) - (func (export "as-memory.grow-value1") (result i32) - (memory.grow $mem1 (loop (result i32) (i32.const 1))) - ) - (func (export "as-memory.grow-value2") (result i32) - (memory.grow $mem2 (loop (result i32) (i32.const 1))) - ) -) - -(assert_return (invoke "as-memory.grow-value0") (i32.const 0)) -(assert_return (invoke "as-memory.grow-value1") (i32.const 4)) -(assert_return (invoke "as-memory.grow-value2") (i32.const 9)) diff --git a/test/core/multi-memory/return0.wast b/test/core/multi-memory/return0.wast deleted file mode 100644 index 9c3c0193f..000000000 --- a/test/core/multi-memory/return0.wast +++ /dev/null @@ -1,19 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 1) - (memory $mem2 4) - - (func (export "as-memory.grow-size0") (result i32) - (memory.grow $mem0 (return (i32.const 40))) - ) - (func (export "as-memory.grow-size1") (result i32) - (memory.grow $mem1 (return (i32.const 40))) - ) - (func (export "as-memory.grow-size2") (result i32) - (memory.grow $mem2 (return (i32.const 40))) - ) -) - -(assert_return (invoke "as-memory.grow-size0") (i32.const 40)) -(assert_return (invoke "as-memory.grow-size1") (i32.const 40)) -(assert_return (invoke "as-memory.grow-size2") (i32.const 40)) diff --git a/test/core/multi-memory/select0.wast b/test/core/multi-memory/select0.wast deleted file mode 100644 index 87f46bf3d..000000000 --- a/test/core/multi-memory/select0.wast +++ /dev/null @@ -1,24 +0,0 @@ -(module - (memory $mem0 0) - (memory $mem1 1) - (memory $mem2 7) - - (func (export "as-memory.grow-value0") (param i32) (result i32) - (memory.grow $mem0 (select (i32.const 1) (i32.const 2) (local.get 0))) - ) - (func (export "as-memory.grow-value1") (param i32) (result i32) - (memory.grow $mem1 (select (i32.const 1) (i32.const 2) (local.get 0))) - ) - (func (export "as-memory.grow-value2") (param i32) (result i32) - (memory.grow $mem2 (select (i32.const 1) (i32.const 2) (local.get 0))) - ) -) - -(assert_return (invoke "as-memory.grow-value0" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "as-memory.grow-value0" (i32.const 1)) (i32.const 2)) - -(assert_return (invoke "as-memory.grow-value1" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "as-memory.grow-value1" (i32.const 1)) (i32.const 3)) - -(assert_return (invoke "as-memory.grow-value2" (i32.const 0)) (i32.const 7)) -(assert_return (invoke "as-memory.grow-value2" (i32.const 1)) (i32.const 9)) From 426da5ba3f3fc5c0cba7aea968c2d2942dd69cba Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Mon, 22 Nov 2021 08:43:24 -0800 Subject: [PATCH 044/181] Remove merge conflict marker --- document/js-api/index.bs | 1 - 1 file changed, 1 deletion(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index ec2f1928e..d61213ef3 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -898,7 +898,6 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. If |s| equals "anyfunc", return [=funcref=]. 1. If |s| equals "externref", return [=externref=]. 1. Assert: This step is not reached. ->>>>>>> upstream/master
      From abad1178376674f84bda71c0bbd9fa631e486a43 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Mon, 22 Nov 2021 23:49:26 -0800 Subject: [PATCH 045/181] [spec] Handle v128 in validation algorithm (#1399) --- document/core/appendix/algorithm.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst index fa6fa1110..72c83ea56 100644 --- a/document/core/appendix/algorithm.rst +++ b/document/core/appendix/algorithm.rst @@ -28,7 +28,10 @@ Types are representable as an enumeration. type val_type = I32 | I64 | F32 | F64 | V128 | Funcref | Externref func is_num(t : val_type | Unknown) : bool = - return t = I32 || t = I64 || t = F32 || t = F64 || t = V128 || t = Unknown + return t = I32 || t = I64 || t = F32 || t = F64 || t = Unknown + + func is_vec(t : val_type | Unknown) : bool = + return t = V128 || t = Unknown func is_ref(t : val_type | Unknown) : bool = return t = Funcref || t = Externref || t = Unknown @@ -172,7 +175,7 @@ Other instructions are checked in a similar manner. pop_val(I32) let t1 = pop_val() let t2 = pop_val() - error_if(not (is_num(t1) && is_num(t2))) + error_if(not ((is_num(t1) && is_num(t2)) || (is_vec(t1) && is_vec(t2)))) error_if(t1 =/= t2 && t1 =/= Unknown && t2 =/= Unknown) push_val(if (t1 = Unknown) t2 else t1) From f945c2a43444444ceca383399ca89ba1ec86d7fc Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 13 Dec 2021 10:00:15 -0800 Subject: [PATCH 046/181] Add tests for functions without end marker. NFC (#1405) Inspired by this downstream test in wabt: https://github.com/WebAssembly/wabt/pull/1775 Fixes: #1404 --- test/core/binary.wast | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/core/binary.wast b/test/core/binary.wast index d034e5fec..3008e1e77 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -368,6 +368,62 @@ "integer too large" ) +;; Function with missing end marker (between two functions) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\03\02\00\00" ;; Function section: 2 functions + "\0a\0c\02" ;; Code section: 2 functions + ;; function 0 + "\04\00" ;; Function size and local type count + "\41\01" ;; i32.const 1 + "\1a" ;; drop + ;; Missing end marker here + ;; function 1 + "\05\00" ;; Function size and local type count + "\41\01" ;; i32.const 1 + "\1a" ;; drop + "\0b" ;; end + ) + "END opcode expected" +) + +;; Function with missing end marker (at EOF) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\0a\06\01" ;; Code section: 1 function + ;; function 0 + "\04\00" ;; Function size and local type count + "\41\01" ;; i32.const 1 + "\1a" ;; drop + ;; Missing end marker here + ) + "unexpected end of section or function" +) + +;; Function with missing end marker (at end of code sections) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\0a\06\01" ;; Code section: 1 function + ;; function 0 + "\04\00" ;; Function size and local type count + "\41\01" ;; i32.const 1 + "\1a" ;; drop + ;; Missing end marker here + "\0b\03\01\01\00" ;; Data section + ) + ;; The spec interpreter consumes the `\0b` (data section start) as an + ;; END instruction (also happens to be `\0b`) and reports the code section as + ;; being larger than declared. + "section size mismatch" +) ;; Unsigned LEB128 must not be overlong (assert_malformed From 6ac8a4859dbd172aa2f77a9f945927549ed523a9 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 18 Dec 2021 09:00:25 +0100 Subject: [PATCH 047/181] [interpreter] Fix a typo in README (#1406) --- interpreter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/README.md b/interpreter/README.md index 63900136b..6f55c1f3f 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -449,7 +449,7 @@ When running scripts, the interpreter predefines a simple host module named `"sp (func (export "print_f64_f64") (param f64 f64)) ) ``` -The `print` functions are assumes to print their respective argument values to stdout (followed by a newline) and can be used to produce observable output. +The `print` functions are assumed to print their respective argument values to stdout (followed by a newline) and can be used to produce observable output. Note: This module predates the `register` command and should no longer be needed for new tests. We might remove it in the future, so consider it deprecated. From d6c848098336cec32678e39601f437d58f687301 Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Mon, 17 Jan 2022 21:06:53 -0800 Subject: [PATCH 048/181] Add a link to the proposals repo (#1409) Fixes #1407. --- proposals/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/README.md b/proposals/README.md index 364b7ab4d..170c15123 100644 --- a/proposals/README.md +++ b/proposals/README.md @@ -1,3 +1,4 @@ # Proposals -This directory contains overviews for post-MVP proposals that are included in this repository. +This directory contains overviews for post-MVP proposals that have been finished and merged into the spec. +Proposals that are not yet finished can be found at https://github.com/WebAssembly/proposals. From 8ccc5e01fb16e878d836125e11a0fe59cc7d36a1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 28 Jan 2022 08:35:45 +0100 Subject: [PATCH 049/181] [spec] Add note regarding parameter names (#1412) --- document/core/text/types.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/document/core/text/types.rst b/document/core/text/types.rst index 5e63b7c9c..7705cc575 100644 --- a/document/core/text/types.rst +++ b/document/core/text/types.rst @@ -93,6 +93,10 @@ Function Types &\Rightarrow& t \\ \end{array} +.. note:: + The optional identifier names for parameters in a function type only have documentation purpose. + They cannot be referenced from anywhere. + Abbreviations ............. From f5c240e02c03efebf8d4e708ed6f73036198df8d Mon Sep 17 00:00:00 2001 From: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com> Date: Tue, 15 Feb 2022 16:12:55 +0800 Subject: [PATCH 050/181] [spec] Clarifying note on text format (#1420) Signed-off-by: Adrian Cole Co-authored-by: Andreas Rossberg --- document/core/text/modules.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/document/core/text/modules.rst b/document/core/text/modules.rst index 848f6880b..b85f51328 100644 --- a/document/core/text/modules.rst +++ b/document/core/text/modules.rst @@ -250,7 +250,9 @@ Functions can be defined as :ref:`imports ` or :ref:`exports ` or :ref:`exports ` or :ref:`exports ` or :ref:`exports Date: Tue, 22 Feb 2022 19:44:55 +0100 Subject: [PATCH 051/181] [test] Fix section size in binary test (#1424) --- interpreter/binary/decode.ml | 2 +- test/core/binary.wast | 8 ++++---- test/core/custom.wast | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 3f72c57b5..c46e13edb 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -110,7 +110,7 @@ let v128 s = V128.of_bits (get_string (Types.vec_size Types.V128Type) s) let len32 s = let pos = pos s in let n = vu32 s in - if I32.le_u n (Int32.of_int (len s)) then Int32.to_int n else + if I32.le_u n (Int32.of_int (len s - pos)) then Int32.to_int n else error s pos "length out of bounds" let bool s = (vu1 s = 1) diff --git a/test/core/binary.wast b/test/core/binary.wast index 3008e1e77..d658c24ff 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -1120,7 +1120,7 @@ "\60\00\00" ;; 1st type ;; "\60\00\00" ;; 2nd type (missed) ) - "unexpected end of section or function" + "length out of bounds" ) ;; 1 type declared, 2 given @@ -1409,7 +1409,7 @@ "\02\00\0b" ;; function body 0 "\02\00\0b" ;; function body 1 ) - "unexpected end of section or function" + "length out of bounds" ) ;; 1 export declared, 2 given @@ -1471,7 +1471,7 @@ "\03\02\01\00" ;; func section "\04\04\01" ;; table section "\70\00\01" ;; table 0 - "\09\07\02" ;; elem with inconsistent segment count (2 declared, 1 given) + "\09\0a\02" ;; elem with inconsistent segment count (2 declared, 1 given) "\00\41\00\0b\01\00" ;; elem 0 "\00\41\00" ;; elem 1 (partial) ;; "\0b\01\00" ;; elem 1 (missing part) @@ -1583,7 +1583,7 @@ "\01\04\01" ;; type section "\60\00\00" ;; type 0 "\03\02\01\00" ;; func section - "\0a\12\01" ;; code section + "\0a\13\01" ;; code section "\11\00" ;; func 0 "\02\40" ;; block 0 "\41\01" ;; condition of if 0 diff --git a/test/core/custom.wast b/test/core/custom.wast index b2394f5e3..12b047650 100644 --- a/test/core/custom.wast +++ b/test/core/custom.wast @@ -86,7 +86,7 @@ "\00asm" "\01\00\00\00" "\00\26\10" "a custom section" "this is the payload" ) - "unexpected end" + "length out of bounds" ) (assert_malformed From f4e90b7488dec2669ca251d7a83bdfb06451e1c1 Mon Sep 17 00:00:00 2001 From: Zhi An Ng Date: Tue, 1 Mar 2022 18:21:39 +0000 Subject: [PATCH 052/181] Update document README to install six --- document/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/document/README.md b/document/README.md index caf75430d..a99cb9ffb 100644 --- a/document/README.md +++ b/document/README.md @@ -3,9 +3,9 @@ This directory contains the source code for the WebAssembly spec documents, as served from the [webassembly.github.io/spec](https://webassembly.github.io/spec) pages. It uses [Sphinx](http://www.sphinx-doc.org/) and [Bikeshed](https://github.com/tabatkins/bikeshed). -To install Sphinx: +To install Sphinx (and required library six): ``` -pip install sphinx +pip install sphinx six ``` To install Bikeshed, see the instructions [here](https://tabatkins.github.io/bikeshed/#installing). @@ -42,7 +42,7 @@ pipenv shell Install Python dependencies: ``` -pipenv install Sphinx==4.0.0 +pipenv install Sphinx==4.0.0 six ``` ### Checking out the repository From 714441c46dcc06937470e9a8cf5ed9855481f50d Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Fri, 18 Mar 2022 22:38:03 +0000 Subject: [PATCH 053/181] Add --generate-js-only flag to test runner This will return early right after generating JS from the wast test files. It will not attempt to run the tests, or do the round trip conversion from wasm <-> wast. This is convenient for proposals to add tests without having to update the reference interpreter with implementation, and generate those tests to JS to run in other Wasm engines. Fixes #1430. --- test/core/run.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/core/run.py b/test/core/run.py index cabb6188f..a265c3284 100755 --- a/test/core/run.py +++ b/test/core/run.py @@ -17,6 +17,7 @@ parser = argparse.ArgumentParser() parser.add_argument("--wasm", metavar="", default=os.path.join(os.getcwd(), "wasm")) parser.add_argument("--js", metavar="") +parser.add_argument("--generate-js-only", action='store_true') parser.add_argument("--out", metavar="", default=outputDir) parser.add_argument("file", nargs='*') arguments = parser.parse_args() @@ -29,6 +30,7 @@ wasmCommand = arguments.wasm jsCommand = arguments.js +generateJsOnly = arguments.generate_js_only outputDir = arguments.out inputFiles = arguments.file if arguments.file else main_test_files + simd_test_files + multi_memory_test_files @@ -65,6 +67,14 @@ def _runTestFile(self, inputPath): dir, inputFile = os.path.split(inputPath) outputPath = os.path.join(outputDir, inputFile) + # Generate JS first, then return early if we are only generating JS. + jsPath = self._auxFile(outputPath.replace(".wast", ".js")) + logPath = self._auxFile(jsPath + ".log") + self._runCommand(('%s -d "%s" -o "%s"') % (wasmCommand, inputPath, jsPath), logPath) + + if generateJsOnly: + return + # Run original file expectedExitCode = 1 if ".fail." in inputFile else 0 logPath = self._auxFile(outputPath + ".log") @@ -97,9 +107,6 @@ def _runTestFile(self, inputPath): self._runCommand(('%s -d "%s" -o "%s"') % (wasmCommand, wasm2Path, wast2Path), logPath) self._compareFile(wastPath, wast2Path) - jsPath = self._auxFile(outputPath.replace(".wast", ".js")) - logPath = self._auxFile(jsPath + ".log") - self._runCommand(('%s -d "%s" -o "%s"') % (wasmCommand, inputPath, jsPath), logPath) if jsCommand != None: self._runCommand(('%s "%s"') % (jsCommand, jsPath), logPath) From 76db73e765056bcd1e557daafafd621cba4e8513 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Mon, 4 Apr 2022 04:53:10 -0700 Subject: [PATCH 054/181] [spec] Fix missing mention of vectype (#1436) Fixed #1435. --- document/core/binary/types.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/document/core/binary/types.rst b/document/core/binary/types.rst index f77da6eae..485057354 100644 --- a/document/core/binary/types.rst +++ b/document/core/binary/types.rst @@ -69,12 +69,13 @@ Reference Types Value Types ~~~~~~~~~~~ -:ref:`Value types ` are encoded with their respective encoding as a :ref:`number type ` or :ref:`reference type `. +:ref:`Value types ` are encoded with their respective encoding as a :ref:`number type `, :ref:`vector type `, or :ref:`reference type `. .. math:: \begin{array}{llclll@{\qquad\qquad}l} \production{value type} & \Bvaltype &::=& t{:}\Bnumtype &\Rightarrow& t \\ &&|& + t{:}\Bvectype &\Rightarrow& t \\ &&|& t{:}\Breftype &\Rightarrow& t \\ \end{array} From 45fc5f18779f6981036c616e5ecaec6bc47f4037 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 4 Apr 2022 05:23:36 -0700 Subject: [PATCH 055/181] [spec] Fix single-table limitation in module instantiation (#1434) --- document/core/exec/modules.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index 34f1298ad..a6ed62be7 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -657,19 +657,17 @@ It is up to the :ref:`embedder ` to define how such conditions are rep 14. For each :ref:`element segment ` :math:`\elem_i` in :math:`\module.\MELEMS` whose :ref:`mode ` is of the form :math:`\EACTIVE~\{ \ETABLE~\tableidx_i, \EOFFSET~\X{einstr}^\ast_i~\END \}`, do: - a. Assert: :math:`\tableidx_i` is :math:`0`. + a. Let :math:`n` be the length of the vector :math:`\elem_i.\EINIT`. - b. Let :math:`n` be the length of the vector :math:`\elem_i.\EINIT`. + b. :ref:`Execute ` the instruction sequence :math:`\X{einstr}^\ast_i`. - c. :ref:`Execute ` the instruction sequence :math:`\X{einstr}^\ast_i`. + c. :ref:`Execute ` the instruction :math:`\I32.\CONST~0`. - d. :ref:`Execute ` the instruction :math:`\I32.\CONST~0`. - - e. :ref:`Execute ` the instruction :math:`\I32.\CONST~n`. + d. :ref:`Execute ` the instruction :math:`\I32.\CONST~n`. - f. :ref:`Execute ` the instruction :math:`\TABLEINIT~i`. + e. :ref:`Execute ` the instruction :math:`\TABLEINIT~\tableidx_i~i`. - g. :ref:`Execute ` the instruction :math:`\ELEMDROP~i`. + f. :ref:`Execute ` the instruction :math:`\ELEMDROP~i`. 15. For each :ref:`data segment ` :math:`\data_i` in :math:`\module.\MDATAS` whose :ref:`mode ` is of the form :math:`\DACTIVE~\{ \DMEM~\memidx_i, \DOFFSET~\X{dinstr}^\ast_i~\END \}`, do: From e2073f23d36ce124d5091c3619dca230de19d10c Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 4 Apr 2022 23:49:31 -0700 Subject: [PATCH 056/181] [spec] Fix missing immediate on table.set (#1441) --- document/core/exec/instructions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index 89dabbc0b..ccebf2b8f 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -1191,8 +1191,8 @@ Table Instructions .. _exec-table.set: -:math:`\TABLESET` -................. +:math:`\TABLESET~x` +................... 1. Let :math:`F` be the :ref:`current ` :ref:`frame `. From 1611e624b374c1b9a635bb84ba31f8842fd38d06 Mon Sep 17 00:00:00 2001 From: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com> Date: Thu, 14 Apr 2022 18:53:59 +0800 Subject: [PATCH 057/181] [docs] Update syntax in examples (#1442) --- proposals/multi-value/Overview.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/proposals/multi-value/Overview.md b/proposals/multi-value/Overview.md index b3c0277fe..42952f0e4 100644 --- a/proposals/multi-value/Overview.md +++ b/proposals/multi-value/Overview.md @@ -43,7 +43,7 @@ A simple swap function. ```wasm (func $swap (param i32 i32) (result i32 i32) - (get_local 1) (get_local 0) + (local.get 1) (local.get 0) ) ``` @@ -51,10 +51,10 @@ An addition function returning an additional carry bit. ```wasm (func $add64_u_with_carry (param $i i64) (param $j i64) (param $c i32) (result i64 i32) (local $k i64) - (set_local $k - (i64.add (i64.add (get_local $i) (get_local $j)) (i64.extend_u/i32 (get_local $c))) + (local.set $k + (i64.add (i64.add (local.get $i) (local.get $j)) (i64.extend_i32_u (local.get $c))) ) - (return (get_local $k) (i64.lt_u (get_local $k) (get_local $i))) + (return (local.get $k) (i64.lt_u (local.get $k) (local.get $i))) ) ``` @@ -71,7 +71,7 @@ An addition function returning an additional carry bit. Conditionally manipulating a stack operand without using a local. ```wasm (func $add64_u_saturated (param i64 i64) (result i64) - ($i64.add_u_carry (get_local 0) (get_local 1) (i32.const 0)) + (call $add64_u_with_carry (local.get 0) (local.get 1) (i32.const 0)) (if (param i64) (result i64) (then (drop) (i64.const 0xffff_ffff_ffff_ffff)) ) @@ -80,14 +80,22 @@ Conditionally manipulating a stack operand without using a local. An iterative factorial function whose loop doesn't use locals, but uses arguments like phis. ```wasm +(func $pick0 (param i64) (result i64 i64) + (local.get 0) (local.get 0) +) + +(func $pick1 (param i64 i64) (result i64 i64 i64) + (local.get 0) (local.get 1) (local.get 0) +) + (func $fac (param i64) (result i64) - (i64.const 1) (get_local 0) + (i64.const 1) (local.get 0) (loop $l (param i64 i64) (result i64) - (pick 1) (pick 1) (i64.mul) - (pick 1) (i64.const 1) (i64.sub) - (pick 0) (i64.const 0) (i64.gt_u) + (call $pick1) (call $pick1) (i64.mul) + (call $pick1) (i64.const 1) (i64.sub) + (call $pick0) (i64.const 0) (i64.gt_u) (br_if $l) - (pick 1) (return) + (call $pick1) (return) ) ) ``` From e27dc094e795bfbc9a520f53b1a55ced0b7cfe28 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 14 Apr 2022 13:00:02 +0200 Subject: [PATCH 058/181] Clarification in proposals README --- proposals/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/proposals/README.md b/proposals/README.md index 170c15123..b2aa25965 100644 --- a/proposals/README.md +++ b/proposals/README.md @@ -2,3 +2,6 @@ This directory contains overviews for post-MVP proposals that have been finished and merged into the spec. Proposals that are not yet finished can be found at https://github.com/WebAssembly/proposals. + +**Note:** The design documents in this folder are archived here for historical purposes and are no longer actively maintained. +Consequently, they may be outdated, contain unfixed errors, or provide insufficient context. From 41621441e43dc27eb1663f2b647367d20731e945 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 15 Apr 2022 10:45:12 +0200 Subject: [PATCH 059/181] [interpreter] Tweak start section AST to match spec --- interpreter/binary/decode.ml | 6 +++++- interpreter/binary/encode.ml | 6 +++++- interpreter/exec/eval.ml | 2 +- interpreter/syntax/ast.ml | 8 +++++++- interpreter/syntax/free.ml | 6 +++--- interpreter/syntax/free.mli | 2 +- interpreter/text/arrange.ml | 5 +++-- interpreter/text/parser.mly | 2 +- interpreter/valid/valid.ml | 11 +++++------ 9 files changed, 31 insertions(+), 17 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index c46e13edb..25c82de03 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -904,8 +904,12 @@ let export_section s = (* Start section *) +let start s = + let sfunc = at var s in + {sfunc} + let start_section s = - section `StartSection (opt (at var) true) None s + section `StartSection (opt (at start) true) None s (* Code section *) diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 5daa9c78a..37f658d2a 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -803,8 +803,12 @@ struct section 7 (vec export) exs (exs <> []) (* Start section *) + let start st = + let {sfunc} = st.it in + var sfunc + let start_section xo = - section 8 (opt var) xo (xo <> None) + section 8 (opt start) xo (xo <> None) (* Code section *) let compress ts = diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index ec9d5918d..6cda240e2 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -771,7 +771,7 @@ let run_data i data = | Declarative -> assert false let run_start start = - [Call start @@ start.at] + [Call start.it.sfunc @@ start.at] let init (m : module_) (exts : extern list) : module_inst = let diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 5e7982f65..afe5d264e 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -289,6 +289,12 @@ and import' = idesc : import_desc; } +type start = start' Source.phrase +and start' = +{ + sfunc : var; +} + type module_ = module_' Source.phrase and module_' = { @@ -297,7 +303,7 @@ and module_' = tables : table list; memories : memory list; funcs : func list; - start : var option; + start : start option; elems : elem_segment list; datas : data_segment list; imports : import list; diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml index f35a9c6ac..1fefb6e21 100644 --- a/interpreter/syntax/free.ml +++ b/interpreter/syntax/free.ml @@ -57,6 +57,7 @@ let shift s = Set.map (Int32.add (-1l)) (Set.remove 0l s) let (++) = union let list free xs = List.fold_left union empty (List.map free xs) +let opt free xo = Lib.Option.get (Lib.Option.map free xo) empty let block_type = function | VarBlockType x -> types (var x) @@ -135,8 +136,7 @@ let import_desc (d : import_desc) = let export (e : export) = export_desc e.it.edesc let import (i : import) = import_desc i.it.idesc -let start (s : var option) = - funcs (Lib.Option.get (Lib.Option.map var s) Set.empty) +let start (s : start) = funcs (var s.it.sfunc) let module_ (m : module_) = list type_ m.it.types ++ @@ -144,7 +144,7 @@ let module_ (m : module_) = list table m.it.tables ++ list memory m.it.memories ++ list func m.it.funcs ++ - start m.it.start ++ + opt start m.it.start ++ list elem m.it.elems ++ list data m.it.datas ++ list import m.it.imports ++ diff --git a/interpreter/syntax/free.mli b/interpreter/syntax/free.mli index dc01edc02..32f57b96c 100644 --- a/interpreter/syntax/free.mli +++ b/interpreter/syntax/free.mli @@ -29,7 +29,7 @@ val elem : Ast.elem_segment -> t val data : Ast.data_segment -> t val export : Ast.export -> t val import : Ast.import -> t -val start : Ast.var option -> t +val start : Ast.start -> t val module_ : Ast.module_ -> t diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index f0f66f02a..adec6ad2a 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -526,8 +526,6 @@ let func_with_index off i f = let func f = func_with_name "" f -let start x = Node ("start " ^ var x, []) - (* Tables & memories *) @@ -619,6 +617,9 @@ let global off i g = let {gtype; ginit} = g.it in Node ("global $" ^ nat (off + i), global_type gtype :: list instr ginit.it) +let start s = + Node ("start " ^ var s.it.sfunc, []) + (* Modules *) diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index bcbc890c2..75f580427 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -1039,7 +1039,7 @@ type_def : start : | LPAR START var RPAR - { fun c -> $3 c func } + { let at = at () in fun c -> {sfunc = $3 c func} @@ at } module_fields : | /* empty */ diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index bb328de87..a72fd0755 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -673,11 +673,10 @@ let check_global (c : context) (glob : global) = (* Modules *) -let check_start (c : context) (start : var option) = - Lib.Option.app (fun x -> - require (func c x = FuncType ([], [])) x.at - "start function must not have parameters or results" - ) start +let check_start (c : context) (start : start) = + let {sfunc} = start.it in + require (func c sfunc = FuncType ([], [])) start.at + "start function must not have parameters or results" let check_import (im : import) (c : context) : context = let {module_name = _; item_name = _; idesc} = im.it in @@ -738,5 +737,5 @@ let check_module (m : module_) = List.iter (check_elem c1) elems; List.iter (check_data c1) datas; List.iter (check_func c) funcs; - check_start c start; + Lib.Option.app (check_start c) start; ignore (List.fold_left (check_export c) NameSet.empty exports); From 776ba0fb510106c09930c71ada399baa0f1e6041 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Sat, 16 Apr 2022 02:44:20 +0200 Subject: [PATCH 060/181] [spec] Bump release to 2 (#1443) At yesterday's WG meeting, we decided to make a new release, now switching to the Evergreen model. For administrative and technical reasons having to do with W3C procedure, we decided to bump the release number to 2. From now on, the standard will iterate at version 2 from the W3C's official perspective. We use minor release numbers internally to distinguish different iterations. (@ericprud, I hope I understood correctly that the Bikeshed "level" also needed to be bumped to 2.) --- document/core/appendix/changes.rst | 2 +- document/core/conf.py | 6 +++--- document/core/index.bs | 6 +++--- document/js-api/index.bs | 4 ++-- document/web-api/index.bs | 4 ++-- interpreter/main/main.ml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/document/core/appendix/changes.rst b/document/core/appendix/changes.rst index 66303ba21..339cb25f9 100644 --- a/document/core/appendix/changes.rst +++ b/document/core/appendix/changes.rst @@ -7,7 +7,7 @@ Change History Since the original release 1.0 of the WebAssembly specification, a number of proposals for extensions have been integrated. The following sections provide an overview of what has changed. -Release 1.1 +Release 2.0 ~~~~~~~~~~~ .. index:: instruction, integer diff --git a/document/core/conf.py b/document/core/conf.py index 24ec7b09e..1cb3fa541 100644 --- a/document/core/conf.py +++ b/document/core/conf.py @@ -26,7 +26,7 @@ # If your documentation needs a minimal Sphinx version, state it here. # -needs_sphinx = '1.4' +needs_sphinx = '2.3' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -60,7 +60,7 @@ name = 'WebAssembly' project = u'WebAssembly' title = u'WebAssembly Specification' -copyright = u'2017, WebAssembly Community Group' +copyright = u'2022, WebAssembly Community Group' author = u'WebAssembly Community Group' editor = u'Andreas Rossberg (editor)' logo = 'static/webassembly.png' @@ -79,7 +79,7 @@ # built documents. # # The short X.Y version. -version = u'1.1' +version = u'2.0' # The full version, including alpha/beta/rc tags. release = version + ('' if proposal == '' else ' + ') + proposal + draft diff --git a/document/core/index.bs b/document/core/index.bs index b99aac3e1..ff31b91e3 100644 --- a/document/core/index.bs +++ b/document/core/index.bs @@ -3,13 +3,13 @@ Title: WebAssembly Core Specification Shortname: wasm-core Group: wasm Status: ED -Level: 1 -TR: https://www.w3.org/TR/wasm-core-1/ +Level: 2 +TR: https://www.w3.org/TR/wasm-core-2/ ED: https://webassembly.github.io/spec/core/bikeshed/ Editor: Andreas Rossberg (Dfinity Stiftung) Repository: WebAssembly/spec Markup Shorthands: css no, markdown no, algorithm no, idl no -Abstract: This document describes version 1.1 of the core WebAssembly standard, a safe, portable, low-level code format designed for efficient execution and compact representation. +Abstract: This document describes version 2.0 of the core WebAssembly standard, a safe, portable, low-level code format designed for efficient execution and compact representation. Prepare For TR: true diff --git a/document/js-api/index.bs b/document/js-api/index.bs index d61213ef3..9eb8cac0e 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -3,8 +3,8 @@ Title: WebAssembly JavaScript Interface Shortname: wasm-js-api Group: wasm Status: ED -Level: 1 -TR: https://www.w3.org/TR/wasm-js-api-1/ +Level: 2 +TR: https://www.w3.org/TR/wasm-js-api-2/ ED: https://webassembly.github.io/spec/js-api/ Editor: Ms2ger, Igalia Repository: WebAssembly/spec diff --git a/document/web-api/index.bs b/document/web-api/index.bs index d5999b5fc..51f92a5a7 100644 --- a/document/web-api/index.bs +++ b/document/web-api/index.bs @@ -3,8 +3,8 @@ Title: WebAssembly Web API Shortname: wasm-web-api Group: wasm Status: ED -Level: 1 -TR: https://www.w3.org/TR/wasm-web-api-1/ +Level: 2 +TR: https://www.w3.org/TR/wasm-web-api-2/ ED: https://webassembly.github.io/spec/web-api/ Editor: Ms2ger, Igalia Repository: WebAssembly/spec diff --git a/interpreter/main/main.ml b/interpreter/main/main.ml index 91b91018f..898bdef1d 100644 --- a/interpreter/main/main.ml +++ b/interpreter/main/main.ml @@ -1,5 +1,5 @@ let name = "wasm" -let version = "1.1" +let version = "2.0" let configure () = Import.register (Utf8.decode "spectest") Spectest.lookup; From 59c2a9358dcb942794db4b047f03eac9d1e26ffd Mon Sep 17 00:00:00 2001 From: gahaas Date: Mon, 25 Apr 2022 12:06:17 +0200 Subject: [PATCH 061/181] Sync wpt test (#1449) --- test/js-api/constructor/toStringTag.any.js | 2 +- test/js-api/interface.any.js | 2 +- test/js-api/table/constructor.any.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/js-api/constructor/toStringTag.any.js b/test/js-api/constructor/toStringTag.any.js index 9c0d346bc..c6d2cdaf6 100644 --- a/test/js-api/constructor/toStringTag.any.js +++ b/test/js-api/constructor/toStringTag.any.js @@ -1,7 +1,7 @@ // META: global=window,dedicatedworker,jsshell "use strict"; -// https://heycam.github.io/webidl/#es-namespaces +// https://webidl.spec.whatwg.org/#es-namespaces // https://webassembly.github.io/spec/js-api/#namespacedef-webassembly test(() => { diff --git a/test/js-api/interface.any.js b/test/js-api/interface.any.js index 4551e6e6e..19d29ead0 100644 --- a/test/js-api/interface.any.js +++ b/test/js-api/interface.any.js @@ -143,7 +143,7 @@ test_attributes(WebAssembly.Memory.prototype, "WebAssembly.Memory", [ test_operations(WebAssembly.Table.prototype, "WebAssembly.Table", [ ["grow", 1], ["get", 1], - ["set", 2], + ["set", 1], ]); test_attributes(WebAssembly.Table.prototype, "WebAssembly.Table", [ diff --git a/test/js-api/table/constructor.any.js b/test/js-api/table/constructor.any.js index cf501fbc2..6d38d04e4 100644 --- a/test/js-api/table/constructor.any.js +++ b/test/js-api/table/constructor.any.js @@ -89,7 +89,7 @@ test(() => { test(() => { const argument = { "element": "anyfunc", "initial": 0 }; - const table = new WebAssembly.Table(argument, {}); + const table = new WebAssembly.Table(argument, null, {}); assert_Table(table, { "length": 0 }); }, "Stray argument"); From 0612dd92df8f9fa7df1bbb473113ddd91f62c247 Mon Sep 17 00:00:00 2001 From: r00ster Date: Tue, 26 Apr 2022 10:37:18 +0200 Subject: [PATCH 062/181] [spec] Fix typo (#1448) --- document/core/appendix/custom.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/appendix/custom.rst b/document/core/appendix/custom.rst index bea81d61c..c12ebf183 100644 --- a/document/core/appendix/custom.rst +++ b/document/core/appendix/custom.rst @@ -36,7 +36,7 @@ Each subsection consists of a * a one-byte subsection *id*, * the |U32| *size* of the contents, in bytes, -* the actual *contents*, whose structure is depended on the subsection id. +* the actual *contents*, whose structure is dependent on the subsection id. .. math:: \begin{array}{llcll} From 7c76874624cabfddaacebd00fd79a22f673d3d99 Mon Sep 17 00:00:00 2001 From: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com> Date: Wed, 27 Apr 2022 18:15:43 +0800 Subject: [PATCH 063/181] [proposals] Add missing start to example (#1454) --- proposals/bulk-memory-operations/Overview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/proposals/bulk-memory-operations/Overview.md b/proposals/bulk-memory-operations/Overview.md index 8f9bc6c18..0dfc53264 100644 --- a/proposals/bulk-memory-operations/Overview.md +++ b/proposals/bulk-memory-operations/Overview.md @@ -386,6 +386,7 @@ implemented as follows: ;; be dropped. (data.drop 1)) ) +(start $start) ``` ### Instruction encoding From 4a300c4a95f8b7b28919dd98ab5e45e25ff7a857 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 2 May 2022 10:54:32 +0200 Subject: [PATCH 064/181] [spec] "version 2.0" -> "release 2.0" (#1452) --- document/core/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/index.bs b/document/core/index.bs index ff31b91e3..d27a96999 100644 --- a/document/core/index.bs +++ b/document/core/index.bs @@ -9,7 +9,7 @@ ED: https://webassembly.github.io/spec/core/bikeshed/ Editor: Andreas Rossberg (Dfinity Stiftung) Repository: WebAssembly/spec Markup Shorthands: css no, markdown no, algorithm no, idl no -Abstract: This document describes version 2.0 of the core WebAssembly standard, a safe, portable, low-level code format designed for efficient execution and compact representation. +Abstract: This document describes release 2.0 of the core WebAssembly standard, a safe, portable, low-level code format designed for efficient execution and compact representation. Prepare For TR: true From 4162a7411b16374b70de4626bce36966147415a5 Mon Sep 17 00:00:00 2001 From: Timothy McCallum Date: Mon, 2 May 2022 19:08:28 +1000 Subject: [PATCH 065/181] [spec] Fix typo (#1458) --- document/core/exec/runtime.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 482eea0ad..5bd6de257 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -18,7 +18,7 @@ Runtime Structure Values ~~~~~~ -WebAssembly computations manipulate *values* of either the four basic :ref:`number types `, i.e., :ref:`integers ` and :ref:`floating-point data ` of 32 or 64 bit width each, of :ref:`vectors ` of 128 bit width, or of :ref:`reference type `. +WebAssembly computations manipulate *values* of either the four basic :ref:`number types `, i.e., :ref:`integers ` and :ref:`floating-point data ` of 32 or 64 bit width each, or :ref:`vectors ` of 128 bit width, or of :ref:`reference type `. In most places of the semantics, values of different types can occur. In order to avoid ambiguities, values are therefore represented with an abstract syntax that makes their type explicit. From 1c8eb5c31be2fd65f0bd5c989785348a20d5d4d5 Mon Sep 17 00:00:00 2001 From: "Ben L. Titzer" Date: Wed, 4 May 2022 01:47:33 -0400 Subject: [PATCH 066/181] [test] Add assert_trap for unreached valid case (#1460) --- test/core/unreached-valid.wast | 1 + 1 file changed, 1 insertion(+) diff --git a/test/core/unreached-valid.wast b/test/core/unreached-valid.wast index 00252171a..b7ebabfdb 100644 --- a/test/core/unreached-valid.wast +++ b/test/core/unreached-valid.wast @@ -60,3 +60,4 @@ ) ) +(assert_trap (invoke "meet-bottom") "unreachable") From 84914010d45562987e81c61055fae95aff5cc4a0 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 4 May 2022 09:18:58 +0200 Subject: [PATCH 067/181] [interpreter] Name the type Utf8.unicode --- interpreter/binary/utf8.ml | 3 +++ interpreter/binary/utf8.mli | 7 +++++-- interpreter/syntax/ast.ml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/interpreter/binary/utf8.ml b/interpreter/binary/utf8.ml index 5cf17997e..b92295488 100644 --- a/interpreter/binary/utf8.ml +++ b/interpreter/binary/utf8.ml @@ -1,3 +1,6 @@ +type codepoint = int +type unicode = codepoint list + exception Utf8 let con n = 0x80 lor (n land 0x3f) diff --git a/interpreter/binary/utf8.mli b/interpreter/binary/utf8.mli index 3b5994a34..73a95f487 100644 --- a/interpreter/binary/utf8.mli +++ b/interpreter/binary/utf8.mli @@ -1,4 +1,7 @@ +type codepoint = int +type unicode = codepoint list + exception Utf8 -val decode : string -> int list (* raises Utf8 *) -val encode : int list -> string (* raises Utf8 *) +val decode : string -> unicode (* raises Utf8 *) +val encode : unicode -> string (* raises Utf8 *) diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index afe5d264e..289234dd6 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -130,7 +130,7 @@ type vec_laneop = (vec_type, pack_size) memop type var = int32 Source.phrase type num = Values.num Source.phrase type vec = Values.vec Source.phrase -type name = int list +type name = Utf8.unicode type block_type = VarBlockType of var | ValBlockType of value_type option From 96f33a2340b042dea11f0eb200e829d53b1f56b1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 5 May 2022 10:13:04 +0200 Subject: [PATCH 068/181] [spec] Fix binary format of data/elem tags to allow LEB (#1461) --- document/core/binary/modules.rst | 26 ++++++++-------- test/core/binary.wast | 53 +++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/document/core/binary/modules.rst b/document/core/binary/modules.rst index 9e91f6243..818c19e76 100644 --- a/document/core/binary/modules.rst +++ b/document/core/binary/modules.rst @@ -327,28 +327,28 @@ It decodes into a vector of :ref:`element segments ` that represent \production{element section} & \Belemsec &::=& \X{seg}^\ast{:}\Bsection_9(\Bvec(\Belem)) &\Rightarrow& \X{seg} \\ \production{element segment} & \Belem &::=& - \hex{00}~~e{:}\Bexpr~~y^\ast{:}\Bvec(\Bfuncidx) + 0{:}\Bu32~~e{:}\Bexpr~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad \{ \ETYPE~\FUNCREF, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& - \hex{01}~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) + 1{:}\Bu32~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad \{ \ETYPE~\X{et}, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EPASSIVE \} \\ &&|& - \hex{02}~~x{:}\Btableidx~~e{:}\Bexpr~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) + 2{:}\Bu32~~x{:}\Btableidx~~e{:}\Bexpr~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad \{ \ETYPE~\X{et}, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EACTIVE~\{ \ETABLE~x, \EOFFSET~e \} \} \\ &&|& - \hex{03}~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) + 3{:}\Bu32~~\X{et}:\Belemkind~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad \{ \ETYPE~\X{et}, \EINIT~((\REFFUNC~y)~\END)^\ast, \EMODE~\EDECLARATIVE \} \\ &&|& - \hex{04}~~e{:}\Bexpr~~\X{el}^\ast{:}\Bvec(\Bexpr) + 4{:}\Bu32~~e{:}\Bexpr~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad \{ \ETYPE~\FUNCREF, \EINIT~\X{el}^\ast, \EMODE~\EACTIVE~\{ \ETABLE~0, \EOFFSET~e \} \} \\ &&|& - \hex{05}~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) + 5{:}\Bu32~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad \{ \ETYPE~et, \EINIT~\X{el}^\ast, \EMODE~\EPASSIVE \} \\ &&|& - \hex{06}~~x{:}\Btableidx~~e{:}\Bexpr~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) + 6{:}\Bu32~~x{:}\Btableidx~~e{:}\Bexpr~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad \{ \ETYPE~et, \EINIT~\X{el}^\ast, \EMODE~\EACTIVE~\{ \ETABLE~x, \EOFFSET~e \} \} \\ &&|& - \hex{07}~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) + 7{:}\Bu32~~\X{et}:\Breftype~~\X{el}^\ast{:}\Bvec(\Bexpr) &\Rightarrow& \\&&&\quad \{ \ETYPE~et, \EINIT~\X{el}^\ast, \EMODE~\EDECLARATIVE \} \\ \production{element kind} & \Belemkind &::=& @@ -356,7 +356,7 @@ It decodes into a vector of :ref:`element segments ` that represent \end{array} .. note:: - The initial byte can be interpreted as a bitfield. + The initial integer can be interpreted as a bitfield. Bit 0 indicates a passive or declarative segment, bit 1 indicates the presence of an explicit table index for an active segment and otherwise distinguishes passive from declarative segments, bit 2 indicates the use of element type and element :ref:`expressions ` instead of element kind and element indices. @@ -440,16 +440,16 @@ It decodes into a vector of :ref:`data segments ` that represent th \production{data section} & \Bdatasec &::=& \X{seg}^\ast{:}\Bsection_{11}(\Bvec(\Bdata)) &\Rightarrow& \X{seg} \\ \production{data segment} & \Bdata &::=& - \hex{00}~~e{:}\Bexpr~~b^\ast{:}\Bvec(\Bbyte) + 0{:}\Bu32~~e{:}\Bexpr~~b^\ast{:}\Bvec(\Bbyte) &\Rightarrow& \{ \DINIT~b^\ast, \DMODE~\DACTIVE~\{ \DMEM~0, \DOFFSET~e \} \} \\ &&|& - \hex{01}~~b^\ast{:}\Bvec(\Bbyte) + 1{:}\Bu32~~b^\ast{:}\Bvec(\Bbyte) &\Rightarrow& \{ \DINIT~b^\ast, \DMODE~\DPASSIVE \} \\ &&|& - \hex{02}~~x{:}\Bmemidx~~e{:}\Bexpr~~b^\ast{:}\Bvec(\Bbyte) + 2{:}\Bu32~~x{:}\Bmemidx~~e{:}\Bexpr~~b^\ast{:}\Bvec(\Bbyte) &\Rightarrow& \{ \DINIT~b^\ast, \DMODE~\DACTIVE~\{ \DMEM~x, \DOFFSET~e \} \} \\ \end{array} .. note:: - The initial byte can be interpreted as a bitfield. + The initial integer can be interpreted as a bitfield. Bit 0 indicates a passive segment, bit 1 indicates the presence of an explicit memory index for an active segment. diff --git a/test/core/binary.wast b/test/core/binary.wast index d658c24ff..983da24c1 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -140,23 +140,68 @@ "\41\00\0b\00" ;; (i32.const 0) with no elements ) -;; Data segment memory index can have non-minimal length +;; Data segment tags and memory index can have non-minimal length (module binary "\00asm" "\01\00\00\00" "\05\03\01" ;; Memory section with 1 entry "\00\00" ;; no max, minimum 0 "\0b\07\01" ;; Data section with 1 entry - "\80\00" ;; Memory index 0, encoded with 2 bytes + "\80\00" ;; Active segment, encoded with 2 bytes + "\41\00\0b\00" ;; (i32.const 0) with contents "" +) +(module binary + "\00asm" "\01\00\00\00" + "\05\03\01" ;; Memory section with 1 entry + "\00\00" ;; no max, minimum 0 + "\0b\08\01" ;; Data section with 1 entry + "\82\00" ;; Active segment, encoded with 2 bytes + "\00" ;; explicit memory index + "\41\00\0b\00" ;; (i32.const 0) with contents "" +) +(module binary + "\00asm" "\01\00\00\00" + "\05\03\01" ;; Memory section with 1 entry + "\00\00" ;; no max, minimum 0 + "\0b\09\01" ;; Data section with 1 entry + "\82\00" ;; Active segment, encoded with 2 bytes + "\80\00" ;; explicit memory index, encoded with 2 bytes "\41\00\0b\00" ;; (i32.const 0) with contents "" ) -;; Element segment table index can have non-minimal length +;; Element segment tags and table index can have non-minimal length +(module binary + "\00asm" "\01\00\00\00" + "\04\04\01" ;; Table section with 1 entry + "\70\00\00" ;; no max, minimum 0, funcref + "\09\07\01" ;; Element section with 1 entry + "\80\00" ;; Active segment + "\41\00\0b\00" ;; (i32.const 0) with no elements +) (module binary "\00asm" "\01\00\00\00" "\04\04\01" ;; Table section with 1 entry "\70\00\00" ;; no max, minimum 0, funcref "\09\09\01" ;; Element section with 1 entry - "\02\80\00" ;; Table index 0, encoded with 2 bytes + "\02" ;; Active segment + "\80\00" ;; explicit table index, encoded with 2 bytes + "\41\00\0b\00\00" ;; (i32.const 0) with no elements +) +(module binary + "\00asm" "\01\00\00\00" + "\04\04\01" ;; Table section with 1 entry + "\70\00\00" ;; no max, minimum 0, funcref + "\09\09\01" ;; Element section with 1 entry + "\82\00" ;; Active segment, encoded with 2 bytes + "\00" ;; explicit table index + "\41\00\0b\00\00" ;; (i32.const 0) with no elements +) +(module binary + "\00asm" "\01\00\00\00" + "\04\04\01" ;; Table section with 1 entry + "\70\00\00" ;; no max, minimum 0, funcref + "\09\0a\01" ;; Element section with 1 entry + "\82\00" ;; Active segment, encoded with 2 bytes + "\80\00" ;; explicit table index, encoded with 2 bytes "\41\00\0b\00\00" ;; (i32.const 0) with no elements ) From b17959770f232248dcf38c880c562cf09bfd3608 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 12:14:06 +0200 Subject: [PATCH 069/181] [spec] Fix typos in numeric operations (#1467) --- document/core/exec/instructions.rst | 2 +- document/core/exec/numerics.rst | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index ccebf2b8f..a707b2a71 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -108,7 +108,7 @@ Where the underlying operators are non-deterministic, because they may return on (t\K{.}\CONST~c_1)~(t\K{.}\CONST~c_2)~t\K{.}\binop &\stepto& (t\K{.}\CONST~c) & (\iff c \in \binop_t(c_1,c_2)) \\ (t\K{.}\CONST~c_1)~(t\K{.}\CONST~c_2)~t\K{.}\binop &\stepto& \TRAP - & (\iff \binop_{t}(c_1,c2) = \{\}) + & (\iff \binop_{t}(c_1,c_2) = \{\}) \end{array} diff --git a/document/core/exec/numerics.rst b/document/core/exec/numerics.rst index b60416874..301984447 100644 --- a/document/core/exec/numerics.rst +++ b/document/core/exec/numerics.rst @@ -406,7 +406,7 @@ The integer result of predicates -- i.e., :ref:`tests ` and :ref: .. math:: \begin{array}{@{}lcll} - \iandnot_N(i_1, i_2) &=& \iand_N(i_1, \inot_N(i2)) + \iandnot_N(i_1, i_2) &=& \iand_N(i_1, \inot_N(i_2)) \end{array} .. _op-ior: @@ -793,8 +793,8 @@ The integer result of predicates -- i.e., :ref:`tests ` and :ref: .. math:: \begin{array}{@{}lcll} - \iminu_N(i_1, i_2) &=& i_1 & (\iff \ilts_N(i_1, i_2) = 1)\\ - \iminu_N(i_1, i_2) &=& i_2 & (\otherwise) + \imins_N(i_1, i_2) &=& i_1 & (\iff \ilts_N(i_1, i_2) = 1)\\ + \imins_N(i_1, i_2) &=& i_2 & (\otherwise) \end{array} @@ -807,8 +807,8 @@ The integer result of predicates -- i.e., :ref:`tests ` and :ref: .. math:: \begin{array}{@{}lcll} - \iminu_N(i_1, i_2) &=& i_1 & (\iff \igtu_N(i_1, i_2) = 1)\\ - \iminu_N(i_1, i_2) &=& i_2 & (\otherwise) + \imaxu_N(i_1, i_2) &=& i_1 & (\iff \igtu_N(i_1, i_2) = 1)\\ + \imaxu_N(i_1, i_2) &=& i_2 & (\otherwise) \end{array} @@ -821,8 +821,8 @@ The integer result of predicates -- i.e., :ref:`tests ` and :ref: .. math:: \begin{array}{@{}lcll} - \iminu_N(i_1, i_2) &=& i_1 & (\iff \igts_N(i_1, i_2) = 1)\\ - \iminu_N(i_1, i_2) &=& i_2 & (\otherwise) + \imaxs_N(i_1, i_2) &=& i_1 & (\iff \igts_N(i_1, i_2) = 1)\\ + \imaxs_N(i_1, i_2) &=& i_2 & (\otherwise) \end{array} From 2ba134b51d1f26e71cf15194748c133038c2c708 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 12:33:17 +0200 Subject: [PATCH 070/181] [spec] Fix syntax error in element segments validation rule (#1465) --- document/core/valid/modules.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst index 9a8edf9c8..7c8f57c4c 100644 --- a/document/core/valid/modules.rst +++ b/document/core/valid/modules.rst @@ -149,7 +149,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type `. + * The expression :math:`e_i` must be :ref:`valid ` with some :ref:`result type ` :math:`[t]`. * The expression :math:`e_i` must be :ref:`constant `. @@ -160,7 +160,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type Date: Fri, 6 May 2022 13:07:11 +0200 Subject: [PATCH 071/181] [spec] Fix typo in global instance syntax (#1466) --- document/core/exec/runtime.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 5bd6de257..5faaab458 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -320,7 +320,7 @@ It records its :ref:`type ` and holds an individual :ref:`val .. math:: \begin{array}{llll} \production{(global instance)} & \globalinst &::=& - \{ \GITYPE~\valtype, \GIVALUE~\val \} \\ + \{ \GITYPE~\globaltype, \GIVALUE~\val \} \\ \end{array} The value of mutable globals can be mutated through :ref:`variable instructions ` or by external means provided by the :ref:`embedder `. From 10578eeb13aa2e3612d69a2365de1d86b06ed29d Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 13:13:42 +0200 Subject: [PATCH 072/181] [spec] Fix typos in module instantiation (#1468) --- document/core/exec/modules.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index a6ed62be7..eb2faa05f 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -713,8 +713,8 @@ It is up to the :ref:`embedder ` to define how such conditions are rep &\wedge& \module.\MELEMS = \elem^n \\ &\wedge& \module.\MDATAS = \data^m \\ &\wedge& \module.\MSTART = \start^? \\ - &\wedge& (\expr_{\F{g}} = \global.GINIT)^\ast \\ - &\wedge& (\expr_{\F{e}}^\ast = \elem.EINIT)^n \\[1ex] + &\wedge& (\expr_{\F{g}} = \global.\GINIT)^\ast \\ + &\wedge& (\expr_{\F{e}}^\ast = \elem.\EINIT)^n \\[1ex] &\wedge& S', \moduleinst = \allocmodule(S, \module, \externval^k, \val^\ast, (\reff^\ast)^n) \\ &\wedge& F = \{ \AMODULE~\moduleinst, \ALOCALS~\epsilon \} \\[1ex] &\wedge& (S'; F; \expr_{\F{g}} \stepto^\ast S'; F; \val~\END)^\ast \\ @@ -733,15 +733,15 @@ where: \instr^\ast~(\I32.\CONST~0)~(\I32.\CONST~n)~(\TABLEINIT~i)~(\ELEMDROP~i) \\ \F{runelem}_i(\{\ETYPE~\X{et}, \EINIT~\reff^n, \EMODE~\EDECLARATIVE\}) \quad=\\ \qquad (\ELEMDROP~i) \\[1ex] - \F{rundata}_i(\{\DINIT~b^n, DMODE~\DPASSIVE\}) \quad=\quad \epsilon \\ - \F{rundata}_i(\{\DINIT~b^n, DMODE~\DACTIVE \{\DMEM~0, \DOFFSET~\instr^\ast~\END\}\}) \quad=\\ \qquad + \F{rundata}_i(\{\DINIT~b^n, \DMODE~\DPASSIVE\}) \quad=\quad \epsilon \\ + \F{rundata}_i(\{\DINIT~b^n, \DMODE~\DACTIVE \{\DMEM~0, \DOFFSET~\instr^\ast~\END\}\}) \quad=\\ \qquad \instr^\ast~(\I32.\CONST~0)~(\I32.\CONST~n)~(\MEMORYINIT~i)~(\DATADROP~i) \\ \end{array} .. note:: Module :ref:`allocation ` and the :ref:`evaluation ` of :ref:`global ` initializers and :ref:`element segments ` are mutually recursive because the global initialization :ref:`values ` :math:`\val^\ast` and element segment contents :math:`(\reff^\ast)^\ast` are passed to the module allocator while depending on the module instance :math:`\moduleinst` and store :math:`S'` returned by allocation. However, this recursion is just a specification device. - In practice, the initialization values can :ref:`be determined ` beforehand by staging module allocation such that first, the module's own :math:`function instances ` are pre-allocated in the store, then the initializer expressions are evaluated, then the rest of the module instance is allocated, and finally the new function instances' :math:`\AMODULE` fields are set to that module instance. + In practice, the initialization values can :ref:`be determined ` beforehand by staging module allocation such that first, the module's own :ref:`function instances ` are pre-allocated in the store, then the initializer expressions are evaluated, then the rest of the module instance is allocated, and finally the new function instances' :math:`\AMODULE` fields are set to that module instance. This is possible because :ref:`validation ` ensures that initialization expressions cannot actually call a function, only take their reference. All failure conditions are checked before any observable mutation of the store takes place. From 39bfefc29b4bc55150ed950566dbfe6a910aa475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Kr=C3=BCger?= Date: Fri, 6 May 2022 13:28:09 +0200 Subject: [PATCH 073/181] [interpreter] Turn into a Dune package (#1459) --- interpreter/.merlin | 12 ------------ interpreter/dune | 33 +++++++++++++++++++++++++++++++++ interpreter/dune-project | 1 + 3 files changed, 34 insertions(+), 12 deletions(-) delete mode 100644 interpreter/.merlin create mode 100644 interpreter/dune create mode 100644 interpreter/dune-project diff --git a/interpreter/.merlin b/interpreter/.merlin deleted file mode 100644 index 5af0cf09f..000000000 --- a/interpreter/.merlin +++ /dev/null @@ -1,12 +0,0 @@ -S binary -S exec -S host -S main -S runtime -S script -S syntax -S text -S util -S valid - -B _build/* diff --git a/interpreter/dune b/interpreter/dune new file mode 100644 index 000000000..2b5cd3572 --- /dev/null +++ b/interpreter/dune @@ -0,0 +1,33 @@ +(include_subdirs unqualified) + +(library + (name wasm) + ; The 'main' module shall not be part of the library, as it would start the + ; WASM REPL every time in all the dependencies. + ; We also need to exclude the 'wasm' module as it overlaps with the library + ; name. + (modules :standard \ main wasm)) + +(executable + (name main) + (modules main) + (libraries wasm) + (flags + (-open Wasm))) + +(subdir + text + (rule + (target lexer.ml) + (deps lexer.mll) + (action + (chdir + %{workspace_root} + (run %{bin:ocamllex} -ml -q -o %{target} %{deps})))) + (ocamlyacc + (modules parser))) + +(env + (dev + (flags + (-w +a-4-27-42-44-45 -warn-error +a-3)))) diff --git a/interpreter/dune-project b/interpreter/dune-project new file mode 100644 index 000000000..c994249ac --- /dev/null +++ b/interpreter/dune-project @@ -0,0 +1 @@ +(lang dune 2.9) From 3f88dffc8661ccbb40369d8d774fa376cfa036cd Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 13:29:44 +0200 Subject: [PATCH 074/181] [spec] Fix typos in instruction validation rules (#1462) --- document/core/valid/instructions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 3f45bc543..fa5533219 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -793,7 +793,7 @@ Table Instructions .. math:: \frac{ - C.\CTABLES[x] = t + C.\CTABLES[x] = \limits~t }{ C \vdashinstr \TABLESET~x : [\I32~t] \to [] } @@ -900,7 +900,7 @@ Table Instructions .. math:: \frac{ - C.\CTABLES[x] = \limits_1~t + C.\CTABLES[x] = \limits~t \qquad C.\CELEMS[y] = t }{ From d616d7fda55020000ce75ce96c9fb39256e6cd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A4mes=20M=C3=A9n=C3=A9trey?= Date: Fri, 6 May 2022 13:40:20 +0200 Subject: [PATCH 075/181] [bib] Update latex .bib file for webassembly 2.0 (#1463) --- wasm-specs.bib | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/wasm-specs.bib b/wasm-specs.bib index c116cf114..7c8a40aa7 100644 --- a/wasm-specs.bib +++ b/wasm-specs.bib @@ -1,9 +1,20 @@ -@report{WebAssemblyCoreSpecification, +@report{WebAssemblyCoreSpecification1, title = {{WebAssembly Core Specification}}, + version = {1.0}, editor = {Rossberg, Andreas}, date = {2019-12-05}, institution = {{W3C}}, url = {https://www.w3.org/TR/wasm-core-1/}, + langid = {english} +} + +@report{WebAssemblyCoreSpecification2, + title = {{WebAssembly Core Specification}}, + version = {2.0}, + editor = {Rossberg, Andreas}, + date = {2022-04-19}, + institution = {{W3C}}, + url = {https://www.w3.org/TR/wasm-core-2/}, langid = {english}, note = {https://webassembly.github.io/spec/core/_download/WebAssembly.pdf} } From cf4fabb12c658e24e1913ac9aa259c6fca77e57d Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 13:49:01 +0200 Subject: [PATCH 076/181] [spec] Add missing default for vector types (#1464) --- document/core/exec/runtime.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 5faaab458..e5c97ed78 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -51,11 +51,12 @@ or *external references* pointing to an uninterpreted form of :ref:`extern addre .. _default-val: Each :ref:`value type ` has an associated *default value*; -it is the respective value :math:`0` for :ref:`number types ` and null for :ref:`reference types `. +it is the respective value :math:`0` for :ref:`number types `, :math:`0` for :ref:`vector types `, and null for :ref:`reference types `. .. math:: \begin{array}{lcl@{\qquad}l} \default_t &=& t{.}\CONST~0 & (\iff t = \numtype) \\ + \default_t &=& t{.}\CONST~0 & (\iff t = \vectype) \\ \default_t &=& \REFNULL~t & (\iff t = \reftype) \\ \end{array} From 3560cc05676a7438901f3d38b5146c3ac6b60cb4 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 6 May 2022 16:12:00 +0200 Subject: [PATCH 077/181] [spec] Fix typos in binary and text formats (#1469) --- document/core/binary/instructions.rst | 2 +- document/core/binary/modules.rst | 8 ++++---- document/core/binary/types.rst | 2 +- document/core/binary/values.rst | 2 +- document/core/text/instructions.rst | 18 +++++++++--------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 151e7e591..0e3840cfc 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -510,7 +510,7 @@ The |VCONST| instruction is followed by 16 immediate bytes, which are converted \begin{array}{llclll} \production{instruction} & \Binstr &::=& \dots \\&&|& \hex{FD}~~12{:}\Bu32~~(b{:}\Bbyte)^{16} &\Rightarrow& \V128.\VCONST~ - bytes_{\K{i128}}^{-1}(b_{0}~\dots~b_{15}) \\ + \bytes_{\K{i128}}^{-1}(b_{0}~\dots~b_{15}) \\ \end{array} .. _binary-vternop: diff --git a/document/core/binary/modules.rst b/document/core/binary/modules.rst index 818c19e76..f20bd0749 100644 --- a/document/core/binary/modules.rst +++ b/document/core/binary/modules.rst @@ -325,7 +325,7 @@ It decodes into a vector of :ref:`element segments ` that represent .. math:: \begin{array}{llclll} \production{element section} & \Belemsec &::=& - \X{seg}^\ast{:}\Bsection_9(\Bvec(\Belem)) &\Rightarrow& \X{seg} \\ + \X{seg}^\ast{:}\Bsection_9(\Bvec(\Belem)) &\Rightarrow& \X{seg}^\ast \\ \production{element segment} & \Belem &::=& 0{:}\Bu32~~e{:}\Bexpr~~y^\ast{:}\Bvec(\Bfuncidx) &\Rightarrow& \\&&&\quad @@ -406,7 +406,7 @@ denoting *count* locals of the same value type. &\Rightarrow& \X{code} & (\iff \X{size} = ||\Bfunc||) \\ \production{function} & \Bfunc &::=& (t^\ast)^\ast{:}\Bvec(\Blocals)~~e{:}\Bexpr - &\Rightarrow& \concat((t^\ast)^\ast), e^\ast + &\Rightarrow& \concat((t^\ast)^\ast), e & (\iff |\concat((t^\ast)^\ast)| < 2^{32}) \\ \production{locals} & \Blocals &::=& n{:}\Bu32~~t{:}\Bvaltype &\Rightarrow& t^n \\ @@ -438,7 +438,7 @@ It decodes into a vector of :ref:`data segments ` that represent th .. math:: \begin{array}{llclll} \production{data section} & \Bdatasec &::=& - \X{seg}^\ast{:}\Bsection_{11}(\Bvec(\Bdata)) &\Rightarrow& \X{seg} \\ + \X{seg}^\ast{:}\Bsection_{11}(\Bvec(\Bdata)) &\Rightarrow& \X{seg}^\ast \\ \production{data segment} & \Bdata &::=& 0{:}\Bu32~~e{:}\Bexpr~~b^\ast{:}\Bvec(\Bbyte) &\Rightarrow& \{ \DINIT~b^\ast, \DMODE~\DACTIVE~\{ \DMEM~0, \DOFFSET~e \} \} \\ &&|& @@ -504,7 +504,7 @@ All sections can be empty. The lengths of vectors produced by the (possibly empty) :ref:`function ` and :ref:`code ` section must match up. Similarly, the optional data count must match the length of the :ref:`data segment ` vector. -Furthermore, it must be present if any :math:`data index ` occurs in the code section. +Furthermore, it must be present if any :ref:`data index ` occurs in the code section. .. math:: \begin{array}{llcllll} diff --git a/document/core/binary/types.rst b/document/core/binary/types.rst index 485057354..4df661839 100644 --- a/document/core/binary/types.rst +++ b/document/core/binary/types.rst @@ -91,7 +91,7 @@ Value Types Result Types ~~~~~~~~~~~~ -:ref:`Result types ` are encoded by the respective :ref:`vectors ` of :ref:`value types ``. +:ref:`Result types ` are encoded by the respective :ref:`vectors ` of :ref:`value types `. .. math:: \begin{array}{llclll@{\qquad\qquad}l} diff --git a/document/core/binary/values.rst b/document/core/binary/values.rst index c62686248..93699749b 100644 --- a/document/core/binary/values.rst +++ b/document/core/binary/values.rst @@ -66,7 +66,7 @@ As an additional constraint, the total number of bytes encoding a value of type .. math:: \begin{array}{llclll@{\qquad\qquad}l} \production{uninterpreted integer} & \BiN &::=& - n{:}\BsN &\Rightarrow& i & (\iff n = \signed_{\iN}(i)) + n{:}\BsN &\Rightarrow& i & (\iff n = \signed_N(i)) \end{array} .. note:: diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index ea3b683f2..1081b608c 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -239,17 +239,17 @@ Table Instructions Abbreviations ............. -For backwards compatibility, all :math:`table indices ` may be omitted from table instructions, defaulting to :math:`0`. +For backwards compatibility, all :ref:`table indices ` may be omitted from table instructions, defaulting to :math:`0`. .. math:: - \begin{array}{llclll} + \begin{array}{llcl} \production{instruction} & - \text{table.get} &\equiv& \text{table.get}~~\text{0} \\ &&|& - \text{table.set} &\equiv& \text{table.set}~~\text{0} \\ &&|& - \text{table.size} &\equiv& \text{table.size}~~\text{0} \\ &&|& - \text{table.grow} &\equiv& \text{table.grow}~~\text{0} \\ &&|& - \text{table.fill} &\equiv& \text{table.fill}~~\text{0} \\ &&|& - \text{table.copy} &\equiv& \text{table.copy}~~\text{0}~~\text{0} \\ &&|& + \text{table.get} &\equiv& \text{table.get}~~\text{0} \\ & + \text{table.set} &\equiv& \text{table.set}~~\text{0} \\ & + \text{table.size} &\equiv& \text{table.size}~~\text{0} \\ & + \text{table.grow} &\equiv& \text{table.grow}~~\text{0} \\ & + \text{table.fill} &\equiv& \text{table.fill}~~\text{0} \\ & + \text{table.copy} &\equiv& \text{table.copy}~~\text{0}~~\text{0} \\ & \text{table.init}~~x{:}\Telemidx_I &\equiv& \text{table.init}~~\text{0}~~x{:}\Telemidx_I \\ \end{array} @@ -968,7 +968,7 @@ Such a folded instruction can appear anywhere a regular instruction can. \text{(}~\text{loop}~~\Tlabel~~\Tblocktype~~\Tinstr^\ast~\text{)} &\equiv\quad \text{loop}~~\Tlabel~~\Tblocktype~~\Tinstr^\ast~~\text{end} \\ & \text{(}~\text{if}~~\Tlabel~~\Tblocktype~~\Tfoldedinstr^\ast - &\hspace{-3ex} \text{(}~\text{then}~~\Tinstr_1^\ast~\text{)}~~\text{(}~\text{else}~~\Tinstr_2^\ast~\text{)}^?~~\text{)} + &\hspace{-3ex} \text{(}~\text{then}~~\Tinstr_1^\ast~\text{)}~~(\text{(}~\text{else}~~\Tinstr_2^\ast~\text{)})^?~~\text{)} \quad\equiv \\ &\qquad \Tfoldedinstr^\ast~~\text{if}~~\Tlabel~~\Tblocktype &\hspace{-1ex} \Tinstr_1^\ast~~\text{else}~~(\Tinstr_2^\ast)^?~\text{end} \\ \end{array} From 4534a0391d2fe8d12e7f9e0267bd6698cb6d8cd8 Mon Sep 17 00:00:00 2001 From: Ivan Panchenko <39594356+ivan-pan@users.noreply.github.com> Date: Tue, 10 May 2022 09:25:56 +0200 Subject: [PATCH 078/181] [spec] Fix various typos (#1470) --- document/core/appendix/embedding.rst | 16 ++++++------- document/core/appendix/properties.rst | 4 ++-- document/core/binary/modules.rst | 2 +- document/core/exec/conventions.rst | 2 +- document/core/exec/instructions.rst | 34 +++++++++++++-------------- document/core/exec/modules.rst | 6 ++--- document/core/exec/numerics.rst | 20 ++++++++-------- document/core/intro/overview.rst | 2 +- document/core/syntax/conventions.rst | 4 ++-- document/core/syntax/instructions.rst | 4 ++-- document/core/text/conventions.rst | 2 +- document/core/text/modules.rst | 6 ++--- document/core/valid/conventions.rst | 2 +- document/core/valid/instructions.rst | 4 ++-- document/core/valid/modules.rst | 2 +- document/js-api/index.bs | 8 +++---- document/web-api/index.bs | 6 ++--- 17 files changed, 62 insertions(+), 62 deletions(-) diff --git a/document/core/appendix/embedding.rst b/document/core/appendix/embedding.rst index db83ae26b..b2995f2f1 100644 --- a/document/core/appendix/embedding.rst +++ b/document/core/appendix/embedding.rst @@ -50,7 +50,7 @@ Some operations state *pre-conditions* about their arguments or *post-conditions It is the embedder's responsibility to meet the pre-conditions. If it does, the post conditions are guaranteed by the semantics. -In addition to pre- and post-conditions explicitly stated with each operation, the specification adopts the following conventions for :ref:`runtime objects ` (:math:`store`, :math:`\moduleinst`, :math:`\externval`, :ref:`addresses `): +In addition to pre- and post-conditions explicitly stated with each operation, the specification adopts the following conventions for :ref:`runtime objects ` (:math:`\store`, :math:`\moduleinst`, :math:`\externval`, :ref:`addresses `): * Every runtime object passed as a parameter must be :ref:`valid ` per an implicit pre-condition. @@ -258,7 +258,7 @@ Functions :math:`\F{func\_alloc}(\store, \functype, \hostfunc) : (\store, \funcaddr)` ........................................................................... -1. Pre-condition: :math:`\functype` is :math:`valid `. +1. Pre-condition: :math:`\functype` is :ref:`valid `. 2. Let :math:`\funcaddr` be the result of :ref:`allocating a host function ` in :math:`\store` with :ref:`function type ` :math:`\functype` and host function code :math:`\hostfunc`. @@ -326,7 +326,7 @@ Tables :math:`\F{table\_alloc}(\store, \tabletype) : (\store, \tableaddr, \reff)` .......................................................................... -1. Pre-condition: :math:`\tabletype` is :math:`valid `. +1. Pre-condition: :math:`\tabletype` is :ref:`valid `. 2. Let :math:`\tableaddr` be the result of :ref:`allocating a table ` in :math:`\store` with :ref:`table type ` :math:`\tabletype` and initialization value :math:`\reff`. @@ -345,7 +345,7 @@ Tables 1. Return :math:`S.\STABLES[a].\TITYPE`. -2. Post-condition: the returned :ref:`table type ` is :math:`valid `. +2. Post-condition: the returned :ref:`table type ` is :ref:`valid `. .. math:: \begin{array}{lclll} @@ -438,7 +438,7 @@ Memories :math:`\F{mem\_alloc}(\store, \memtype) : (\store, \memaddr)` ................................................................ -1. Pre-condition: :math:`\memtype` is :math:`valid `. +1. Pre-condition: :math:`\memtype` is :ref:`valid `. 2. Let :math:`\memaddr` be the result of :ref:`allocating a memory ` in :math:`\store` with :ref:`memory type ` :math:`\memtype`. @@ -457,7 +457,7 @@ Memories 1. Return :math:`S.\SMEMS[a].\MITYPE`. -2. Post-condition: the returned :ref:`memory type ` is :math:`valid `. +2. Post-condition: the returned :ref:`memory type ` is :ref:`valid `. .. math:: \begin{array}{lclll} @@ -551,7 +551,7 @@ Globals :math:`\F{global\_alloc}(\store, \globaltype, \val) : (\store, \globaladdr)` ............................................................................ -1. Pre-condition: :math:`\globaltype` is :math:`valid `. +1. Pre-condition: :math:`\globaltype` is :ref:`valid `. 2. Let :math:`\globaladdr` be the result of :ref:`allocating a global ` in :math:`\store` with :ref:`global type ` :math:`\globaltype` and initialization value :math:`\val`. @@ -570,7 +570,7 @@ Globals 1. Return :math:`S.\SGLOBALS[a].\GITYPE`. -2. Post-condition: the returned :ref:`global type ` is :math:`valid `. +2. Post-condition: the returned :ref:`global type ` is :ref:`valid `. .. math:: \begin{array}{lclll} diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst index da3658c8f..72251114e 100644 --- a/document/core/appendix/properties.rst +++ b/document/core/appendix/properties.rst @@ -483,7 +483,7 @@ Finally, :ref:`frames ` are classified with *frame contexts*, whic * Each :ref:`value ` :math:`\val_i` in :math:`\val^\ast` must be :ref:`valid ` with some :ref:`value type ` :math:`t_i`. -* Let :math:`t^\ast` the concatenation of all :math:`t_i` in order. +* Let :math:`t^\ast` be the concatenation of all :math:`t_i` in order. * Let :math:`C'` be the same :ref:`context ` as :math:`C`, but with the :ref:`value types ` :math:`t^\ast` prepended to the |CLOCALS| vector. @@ -543,7 +543,7 @@ To that end, all previous typing judgements :math:`C \vdash \X{prop}` are genera :math:`\REFFUNCADDR~\funcaddr` .............................. -* The :ref:`external function value ` :math:`\EVFUNC~\funcaddr` must be :ref:`valid ` with :ref:`external function type ` :math:`\ETFUNC \functype`. +* The :ref:`external function value ` :math:`\EVFUNC~\funcaddr` must be :ref:`valid ` with :ref:`external function type ` :math:`\ETFUNC~\functype`. * Then the instruction is valid with type :math:`[] \to [\FUNCREF]`. diff --git a/document/core/binary/modules.rst b/document/core/binary/modules.rst index f20bd0749..e9c72b61a 100644 --- a/document/core/binary/modules.rst +++ b/document/core/binary/modules.rst @@ -559,7 +559,7 @@ Furthermore, it must be present if any :ref:`data index ` occurs where for each :math:`t_i^\ast, e_i` in :math:`\X{code}^n`, .. math:: - \func^n[i] = \{ \FTYPE~\typeidx^n[i], \FLOCALS~t_i^\ast, \FBODY~e_i \} ) \\ + \func^n[i] = \{ \FTYPE~\typeidx^n[i], \FLOCALS~t_i^\ast, \FBODY~e_i \} \\ .. note:: The version of the WebAssembly binary format may increase in the future diff --git a/document/core/exec/conventions.rst b/document/core/exec/conventions.rst index 807239b04..d9b998a92 100644 --- a/document/core/exec/conventions.rst +++ b/document/core/exec/conventions.rst @@ -92,7 +92,7 @@ and a sequence of |CONST| instructions can be interpreted as an operand "stack" (\I32.\CONST~n_1)~(\I32.\CONST~n_2)~\I32.\ADD \quad\stepto\quad (\I32.\CONST~(n_1 + n_2) \mod 2^{32}) Per this rule, two |CONST| instructions and the |ADD| instruction itself are removed from the instruction stream and replaced with one new |CONST| instruction. - This can be interpreted as popping two value off the stack and pushing the result. + This can be interpreted as popping two values off the stack and pushing the result. When no result is produced, an instruction reduces to the empty sequence: diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index a707b2a71..efcc5bdce 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -400,7 +400,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \begin{array}[t]{@{}r@{~}l@{}} (\iff & i^\ast = \lanes_{i8x16}(c_2) \\ \wedge & c^\ast = \lanes_{i8x16}(c_1)~0^{240} \\ - \wedge & c' = \lanes^{-1}_{i8x16}(c^\ast[ i^\ast[0] ] \dots c^\ast[ i^\ast[15] ]) + \wedge & c' = \lanes^{-1}_{i8x16}(c^\ast[ i^\ast[0] ] \dots c^\ast[ i^\ast[15] ])) \end{array} \end{array} @@ -436,7 +436,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & i^\ast = \lanes_{i8x16}(c_1)~\lanes_{i8x16}(c_2) \\ - \wedge & c = \lanes^{-1}_{i8x16}(i^\ast[x^\ast[0]] \dots i^\ast[x^\ast[15]]) + \wedge & c = \lanes^{-1}_{i8x16}(i^\ast[x^\ast[0]] \dots i^\ast[x^\ast[15]])) \end{array} \end{array} @@ -494,7 +494,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & t_2 = \unpacked(t_1\K{x}N) \\ - \wedge & c_2 = \extend^{sx^?}_{t_1,t_2}(\lanes_{t_1\K{x}N}(c_1)[x]) + \wedge & c_2 = \extend^{sx^?}_{t_1,t_2}(\lanes_{t_1\K{x}N}(c_1)[x])) \end{array} \end{array} @@ -529,8 +529,8 @@ Most vector instructions are defined in terms of generic numeric operators appli \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & i^\ast = \lanes_{\shape}(c_2)) \\ - \wedge & c = \lanes^{-1}_{\shape}(i^\ast \with [x] = c_1) + (\iff & i^\ast = \lanes_{\shape}(c_2) \\ + \wedge & c = \lanes^{-1}_{\shape}(i^\ast \with [x] = c_1)) \end{array} \end{array} @@ -673,7 +673,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\iff & i_1^\ast = \lanes_{\shape}(c) \\ - \wedge & i = \bool(\bigwedge(i_1 \neq 0)^\ast) + \wedge & i = \bool(\bigwedge(i_1 \neq 0)^\ast)) \end{array} \end{array} @@ -735,7 +735,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \begin{array}[t]{@{}r@{~}l@{}} (\iff & d_1^M = \narrow^{\sx}_{|t_1|,|t_2|}( \lanes_{t_1\K{x}M}(c_1)) \\ \wedge & d_2^M = \narrow^{\sx}_{|t_1|,|t_2|}( \lanes_{t_1\K{x}M}(c_2)) \\ - \wedge & c = \lanes^{-1}_{t_2\K{x}N}(d_1^M~d_2^M) + \wedge & c = \lanes^{-1}_{t_2\K{x}N}(d_1^M~d_2^M)) \end{array} \end{array} @@ -762,7 +762,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1))) + (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1)))) \end{array} \end{array} @@ -795,7 +795,7 @@ Most vector instructions are defined in terms of generic numeric operators appli \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx^?}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1)[\half(0, N) \slice N])) + (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx^?}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1)[\half(0, N) \slice N]))) \end{array} \end{array} @@ -830,7 +830,7 @@ where: \end{array} \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} - (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1))~0^M) + (\iff & c = \lanes^{-1}_{t_2\K{x}N}(\vcvtop^{\sx}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1))~0^M)) \end{array} \end{array} @@ -840,7 +840,7 @@ where: :math:`\K{i32x4.}\DOT\K{\_i16x8\_s}` .................................... -1. Assert: due to :ref:`validation `, two values of :ref:`value type ` |V128| is on the top of the stack. +1. Assert: due to :ref:`validation `, two values of :ref:`value type ` |V128| are on the top of the stack. 2. Pop the value :math:`\V128.\VCONST~c_2` from the stack. @@ -863,7 +863,7 @@ where: \begin{array}[t]{@{}r@{~}l@{}} (\iff & (i_1~i_2)^\ast = \imul_{32}(\extends_{16,32}(\lanes_{\I16X8}(c_1)), \extends_{16,32}(\lanes_{\I16X8}(c_2))) \\ \wedge & j^\ast = \iadd_{32}(i_1, i_2)^\ast \\ - \wedge & c = \lanes^{-1}_{\I32X4}(j^\ast) + \wedge & c = \lanes^{-1}_{\I32X4}(j^\ast)) \end{array} \end{array} @@ -873,7 +873,7 @@ where: :math:`t_2\K{x}N\K{.}\EXTMUL\K{\_}\half\K{\_}t_1\K{x}M\K{\_}\sx` ................................................................ -1. Assert: due to :ref:`validation `, two values of :ref:`value type ` |V128| is on the top of the stack. +1. Assert: due to :ref:`validation `, two values of :ref:`value type ` |V128| are on the top of the stack. 2. Pop the value :math:`\V128.\VCONST~c_2` from the stack. @@ -903,7 +903,7 @@ where: \begin{array}[t]{@{}r@{~}l@{}} (\iff & i^\ast = \lanes_{t_1\K{x}M}(c_1)[\half(0, N) \slice N] \\ \wedge & j^\ast = \lanes_{t_1\K{x}M}(c_2)[\half(0, N) \slice N] \\ - \wedge & c = \lanes^{-1}_{t_2\K{x}N}(\imul_{t_2\K{x}N}(\extend^{\sx}_{|t_1|,|t_2|}(i^\ast), \extend^{\sx}_{|t_1|,|t_2|}(j^\ast))) + \wedge & c = \lanes^{-1}_{t_2\K{x}N}(\imul_{t_2\K{x}N}(\extend^{\sx}_{|t_1|,|t_2|}(i^\ast), \extend^{\sx}_{|t_1|,|t_2|}(j^\ast)))) \end{array} where: @@ -941,7 +941,7 @@ where: \begin{array}[t]{@{}r@{~}l@{}} (\iff & (i_1~i_2)^\ast = \extend^{\sx}_{|t_1|,|t_2|}(\lanes_{t_1\K{x}M}(c_1)) \\ \wedge & j^\ast = \iadd_{N}(i_1, i_2)^\ast \\ - \wedge & c = \lanes^{-1}_{t_2\K{x}N}(j^\ast) + \wedge & c = \lanes^{-1}_{t_2\K{x}N}(j^\ast)) \end{array} \end{array} @@ -1779,7 +1779,7 @@ Memory Instructions \wedge & \X{ea} + M \cdot N / 8 \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ \wedge & \bytes_{\iM}(m_k) = S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} + k \cdot M/8 \slice M/8]) \\ \wedge & W = M \cdot 2 \\ - \wedge & c = \lanes^{-1}_{\X{i}W\K{x}N}(\extend^{\sx}_{M,W}(m_0) \dots \extend^{\sx}_{M,W}(m_{N-1})) + \wedge & c = \lanes^{-1}_{\X{i}W\K{x}N}(\extend^{\sx}_{M,W}(m_0) \dots \extend^{\sx}_{M,W}(m_{N-1}))) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} @@ -2087,7 +2087,7 @@ Memory Instructions (\iff & \X{ea} = i + \memarg.\OFFSET \\ \wedge & \X{ea} + N \leq |S.\SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA| \\ \wedge & L = 128/N \\ - \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice N/8] = \bytes_{\iN}(\lanes_{\K{i}N\K{x}L}(c)[x]) + \wedge & S' = S \with \SMEMS[F.\AMODULE.\MIMEMS[x]].\MIDATA[\X{ea} \slice N/8] = \bytes_{\iN}(\lanes_{\K{i}N\K{x}L}(c)[y]) \end{array} \\[1ex] \begin{array}{lcl@{\qquad}l} diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index eb2faa05f..0e8c9d50a 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -386,7 +386,7 @@ Growing :ref:`tables ` \wedge & \X{len} < 2^{32} \\ \wedge & \limits~t = \tableinst.\TITYPE \\ \wedge & \limits' = \limits \with \LMIN = \X{len} \\ - \wedge & \vdashlimits \limits' \ok \\ + \wedge & \vdashlimits \limits' \ok) \\ \end{array} \\ \end{array} @@ -424,7 +424,7 @@ Growing :ref:`memories ` \wedge & \X{len} \leq 2^{16} \\ \wedge & \limits = \meminst.\MITYPE \\ \wedge & \limits' = \limits \with \LMIN = \X{len} \\ - \wedge & \vdashlimits \limits' \ok \\ + \wedge & \vdashlimits \limits' \ok) \\ \end{array} \\ \end{array} @@ -462,7 +462,7 @@ and list of :ref:`reference ` vectors for the module's :ref:`element 6. For each :ref:`element segment ` :math:`\elem_i` in :math:`\module.\MELEMS`, do: - a. Let :math:`\elemaddr_i` be the :ref:`element address ` resulting from :ref:`allocating ` a :ref:`element instance ` of :ref:`reference type ` :math:`\elem_i.\ETYPE` with contents :math:`(\reff^\ast)^\ast[i]`. + a. Let :math:`\elemaddr_i` be the :ref:`element address ` resulting from :ref:`allocating ` an :ref:`element instance ` of :ref:`reference type ` :math:`\elem_i.\ETYPE` with contents :math:`(\reff^\ast)^\ast[i]`. 7. For each :ref:`data segment ` :math:`\data_i` in :math:`\module.\MDATAS`, do: diff --git a/document/core/exec/numerics.rst b/document/core/exec/numerics.rst index 301984447..c7050b17d 100644 --- a/document/core/exec/numerics.rst +++ b/document/core/exec/numerics.rst @@ -197,7 +197,7 @@ Numeric vectors have the same underlying representation as an |i128|. They can a \\ \qquad \begin{array}[t]{@{}r@{~}l@{}} (\where & B = |t| / 8 \\ - \wedge & b^{16} = bytes_{\i128}(c) \\ + \wedge & b^{16} = \bytes_{\i128}(c) \\ \wedge & c_i = \bytes_{t}^{-1}(b^{16}[i \cdot B \slice B])) \end{array} \end{array} @@ -746,7 +746,7 @@ The integer result of predicates -- i.e., :ref:`tests ` and :ref: * Let :math:`j` be the :ref:`signed interpretation ` of :math:`i`. -* If :math:`j` greater than or equal to :math:`0`, then return :math:`i`. +* If :math:`j` is greater than or equal to :math:`0`, then return :math:`i`. * Else return the negation of `j`, modulo :math:`2^N`. @@ -1060,13 +1060,13 @@ This non-deterministic result is expressed by the following auxiliary function p * Else if both :math:`z_1` and :math:`z_2` are infinities of equal sign, then return that infinity. -* Else if one of :math:`z_1` or :math:`z_2` is an infinity, then return that infinity. +* Else if either :math:`z_1` or :math:`z_2` is an infinity, then return that infinity. * Else if both :math:`z_1` and :math:`z_2` are zeroes of opposite sign, then return positive zero. * Else if both :math:`z_1` and :math:`z_2` are zeroes of equal sign, then return that zero. -* Else if one of :math:`z_1` or :math:`z_2` is a zero, then return the other operand. +* Else if either :math:`z_1` or :math:`z_2` is a zero, then return the other operand. * Else if both :math:`z_1` and :math:`z_2` are values with the same magnitude but opposite signs, then return positive zero. @@ -1149,9 +1149,9 @@ This non-deterministic result is expressed by the following auxiliary function p * Else if both :math:`z_1` and :math:`z_2` are infinities of opposite sign, then return negative infinity. -* Else if one of :math:`z_1` or :math:`z_2` is an infinity and the other a value with equal sign, then return positive infinity. +* Else if either :math:`z_1` or :math:`z_2` is an infinity and the other a value with equal sign, then return positive infinity. -* Else if one of :math:`z_1` or :math:`z_2` is an infinity and the other a value with opposite sign, then return negative infinity. +* Else if either :math:`z_1` or :math:`z_2` is an infinity and the other a value with opposite sign, then return negative infinity. * Else if both :math:`z_1` and :math:`z_2` are zeroes of equal sign, then return positive zero. @@ -1235,9 +1235,9 @@ This non-deterministic result is expressed by the following auxiliary function p * If either :math:`z_1` or :math:`z_2` is a NaN, then return an element of :math:`\nans_N\{z_1, z_2\}`. -* Else if one of :math:`z_1` or :math:`z_2` is a negative infinity, then return negative infinity. +* Else if either :math:`z_1` or :math:`z_2` is a negative infinity, then return negative infinity. -* Else if one of :math:`z_1` or :math:`z_2` is a positive infinity, then return the other value. +* Else if either :math:`z_1` or :math:`z_2` is a positive infinity, then return the other value. * Else if both :math:`z_1` and :math:`z_2` are zeroes of opposite signs, then return negative zero. @@ -1264,9 +1264,9 @@ This non-deterministic result is expressed by the following auxiliary function p * If either :math:`z_1` or :math:`z_2` is a NaN, then return an element of :math:`\nans_N\{z_1, z_2\}`. -* Else if one of :math:`z_1` or :math:`z_2` is a positive infinity, then return positive infinity. +* Else if either :math:`z_1` or :math:`z_2` is a positive infinity, then return positive infinity. -* Else if one of :math:`z_1` or :math:`z_2` is a negative infinity, then return the other value. +* Else if either :math:`z_1` or :math:`z_2` is a negative infinity, then return the other value. * Else if both :math:`z_1` and :math:`z_2` are zeroes of opposite signs, then return positive zero. diff --git a/document/core/intro/overview.rst b/document/core/intro/overview.rst index b9e858ccc..5a4760baf 100644 --- a/document/core/intro/overview.rst +++ b/document/core/intro/overview.rst @@ -26,7 +26,7 @@ This language is structured around the following concepts. In addition to these basic number types, there is a single 128 bit wide vector type representing different types of packed data. The supported representations are 4 32-bit, or 2 64-bit - |IEEE754|_ numbers, or different widths of packed integer values + |IEEE754|_ numbers, or different widths of packed integer values, specifically 2 64-bit integers, 4 32-bit integers, 8 16-bit integers, or 16 8-bit integers. diff --git a/document/core/syntax/conventions.rst b/document/core/syntax/conventions.rst index 979d6bc4e..9e5dca182 100644 --- a/document/core/syntax/conventions.rst +++ b/document/core/syntax/conventions.rst @@ -107,9 +107,9 @@ The following notation is adopted for manipulating such records: The update notation for sequences and records generalizes recursively to nested components accessed by "paths" :math:`\X{pth} ::= ([\dots] \;| \;.\K{field})^+`: -* :math:`s \with [i]\,\X{pth} = A` is short for :math:`s \with [i] = (s[i] \with \X{pth} = A)`. +* :math:`s \with [i]\,\X{pth} = A` is short for :math:`s \with [i] = (s[i] \with \X{pth} = A)`, -* :math:`r \with \K{field}\,\X{pth} = A` is short for :math:`r \with \K{field} = (r.\K{field} \with \X{pth} = A)`. +* :math:`r \with \K{field}\,\X{pth} = A` is short for :math:`r \with \K{field} = (r.\K{field} \with \X{pth} = A)`, where :math:`r \with~.\K{field} = A` is shortened to :math:`r \with \K{field} = A`. diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index c50aa33ab..7692e711f 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -428,7 +428,7 @@ Instructions in this group are concerned with accessing :ref:`references ` results if any of the accessed memory bytes lies outside the address range implied by the memory's current size. .. note:: - Future version of WebAssembly might provide memory instructions with 64 bit address ranges. + Future versions of WebAssembly might provide memory instructions with 64 bit address ranges. The |MEMORYSIZE| instruction returns the current size of a memory. The |MEMORYGROW| instruction grows a memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. diff --git a/document/core/text/conventions.rst b/document/core/text/conventions.rst index ddcd8e780..12c8b7dfc 100644 --- a/document/core/text/conventions.rst +++ b/document/core/text/conventions.rst @@ -110,7 +110,7 @@ Contexts The text format allows the use of symbolic :ref:`identifiers ` in place of :ref:`indices `. To resolve these identifiers into concrete indices, -some grammar production are indexed by an *identifier context* :math:`I` as a synthesized attribute that records the declared identifiers in each :ref:`index space `. +some grammar productions are indexed by an *identifier context* :math:`I` as a synthesized attribute that records the declared identifiers in each :ref:`index space `. In addition, the context records the types defined in the module, so that :ref:`parameter ` indices can be computed for :ref:`functions `. It is convenient to define identifier contexts as :ref:`records ` :math:`I` with abstract syntax as follows: diff --git a/document/core/text/modules.rst b/document/core/text/modules.rst index b85f51328..0964dfdaa 100644 --- a/document/core/text/modules.rst +++ b/document/core/text/modules.rst @@ -120,7 +120,7 @@ The following auxiliary function extracts optional identifiers from parameters: Both productions overlap for the case that the function type is :math:`[] \to []`. However, in that case, they also produce the same results, so that the choice is immaterial. - The :ref:`well-formedness ` condition on :math:`I'` ensures that the parameters do not contain duplicate identifier. + The :ref:`well-formedness ` condition on :math:`I'` ensures that the parameters do not contain duplicate identifiers. .. _text-typeuse-abbrev: @@ -356,7 +356,7 @@ Memory definitions can bind a symbolic :ref:`memory identifier `. Abbreviations ............. -A :ref:`data segment ` can be given inline with a memory definition, in which case its offset is :math:`0` the :ref:`limits ` of the :ref:`memory type ` are inferred from the length of the data, rounded up to :ref:`page size `: +A :ref:`data segment ` can be given inline with a memory definition, in which case its offset is :math:`0` and the :ref:`limits ` of the :ref:`memory type ` are inferred from the length of the data, rounded up to :ref:`page size `: .. math:: \begin{array}{llclll} @@ -365,7 +365,7 @@ A :ref:`data segment ` can be given inline with a memory definition, \text{(}~\text{memory}~~\Tid'~~m~~m~\text{)} \\ & \qquad \text{(}~\text{data}~~\text{(}~\text{memory}~~\Tid'~\text{)}~~\text{(}~\text{i32.const}~~\text{0}~\text{)}~~\Tdatastring~\text{)} \\ & \qquad\qquad - (\iff \Tid^? \neq \epsilon \wedge \Tid' = \Tid^? \vee \Tid^? = \epsilon \wedge \Tid' \idfresh, m = \F{ceil}(n / 64\F{Ki})) \\ + (\iff \Tid^? \neq \epsilon \wedge \Tid' = \Tid^? \vee \Tid^? = \epsilon \wedge \Tid' \idfresh, m = \F{ceil}(n / 64\,\F{Ki})) \\ \end{array} Memories can be defined as :ref:`imports ` or :ref:`exports ` inline: diff --git a/document/core/valid/conventions.rst b/document/core/valid/conventions.rst index b6a49b0cd..ae219e44a 100644 --- a/document/core/valid/conventions.rst +++ b/document/core/valid/conventions.rst @@ -150,7 +150,7 @@ and there is one respective rule for each relevant construct :math:`A` of the ab C \vdash \I32.\ADD : [\I32~\I32] \to [\I32] } - The instruction is always valid with type :math:`[\I32~\I32] \to [\I32`] + The instruction is always valid with type :math:`[\I32~\I32] \to [\I32]` (saying that it consumes two |I32| values and produces one), independent of any side conditions. diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index fa5533219..f565f35c3 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -1033,7 +1033,7 @@ Memory Instructions \qquad 2^{\memarg.\ALIGN} \leq N/8 \cdot M }{ - C \vdashinstr \K{v128.}\K{.}\LOAD{N}\K{x}M\_\sx~x~\memarg : [\I32] \to [\V128] + C \vdashinstr \K{v128.}\LOAD{N}\K{x}M\_\sx~x~\memarg : [\I32] \to [\V128] } @@ -1583,7 +1583,7 @@ Expressions :math:`\expr` are classified by :ref:`result types ` with some :ref:`stack type ` :math:`[] \to [{t'}^\ast]`. -* For each :ref:`operand type ` :math:`t'_i` in :math:`{t'}^\ast` and corresponding :ref:`value type ` type :math:`t_i` in :math:`t^\ast`, :math:`t'_i` :ref:`matches ` :math:`t_i`. +* For each :ref:`operand type ` :math:`t'_i` in :math:`{t'}^\ast` and corresponding :ref:`value type ` :math:`t_i` in :math:`t^\ast`, :math:`t'_i` :ref:`matches ` :math:`t_i`. * Then the expression is valid with :ref:`result type ` :math:`[t^\ast]`. diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst index 7c8f57c4c..96edd4d71 100644 --- a/document/core/valid/modules.rst +++ b/document/core/valid/modules.rst @@ -147,7 +147,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type ` with some :ref:`result type ` :math:`[t]`. diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 9eb8cac0e..59af6515d 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -585,7 +585,7 @@ interface Module {
      - The Module(|bytes|) constructor, when invoked, performs the follwing steps: + The Module(|bytes|) constructor, when invoked, performs the following steps: 1. Let |stableBytes| be a [=get a copy of the buffer source|copy of the bytes held by the buffer=] |bytes|. 1. [=Compile a WebAssembly module|Compile the WebAssembly module=] |stableBytes| and store the result as |module|. @@ -778,7 +778,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. Let |ref| be [=DefaultValue=](|elementType|). 1. Otherwise, 1. Let |ref| be ? [=ToWebAssemblyValue=](|value|, |elementType|). - 1. Let |type| be the [=table type=] {[=table type|min=] |initial|, [=table type|ma𝗑=] |maximum|} |elementType|. + 1. Let |type| be the [=table type=] {[=table type|min=] |initial|, [=table type|max=] |maximum|} |elementType|. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |tableaddr|) be [=table_alloc=](|store|, |type|, |ref|). 1. Set the [=surrounding agent=]'s [=associated store=] to |store|. @@ -1147,7 +1147,7 @@ WebAssembly defines the following Error classes: CompileError When the [=namespace object=] for the {{WebAssembly}} namespace is [=create a namespace object|created=], the following steps must be run: -1. Let |namespaceObject| the [=namespace object=]. +1. Let |namespaceObject| be the [=namespace object=]. 1. [=list/iterate|For each=] |error| of « "CompileError", "LinkError", "RuntimeError" », 1. Let |constructor| be a new object, implementing the [=NativeError Object Structure=], with NativeError set to |error|. 1. ! [$CreateMethodProperty$](|namespaceObject|, |error|, |constructor|). @@ -1241,4 +1241,4 @@ In practice, an implementation may run out of resources for valid modules below

      This section is non-normative.

      -This document defines a host environment for WebAssembly. It enables a WebAssembly instance to [=import=] JavaScript objects and functions from an [=read the imports|import object=], but otherwise provides no access to the embedding environment. Thus a WebAssembly instance is bounds to the same constraints as JavaScript. +This document defines a host environment for WebAssembly. It enables a WebAssembly instance to [=import=] JavaScript objects and functions from an [=read the imports|import object=], but otherwise provides no access to the embedding environment. Thus a WebAssembly instance is bound to the same constraints as JavaScript. diff --git a/document/web-api/index.bs b/document/web-api/index.bs index 51f92a5a7..602222129 100644 --- a/document/web-api/index.bs +++ b/document/web-api/index.bs @@ -125,7 +125,7 @@ Note: This algorithm accepts a {{Response}} object, or a 1. If |response| is not [=CORS-same-origin=], [=reject=] |returnValue| with a {{TypeError}} and abort these substeps. 1. If |response|'s [=response/status=] is not an [=ok status=], [=reject=] |returnValue| with a {{TypeError}} and abort these substeps. - 1. [=Consume body|consume=] |response|'s body as an {{ArrayBuffer}}, and let |bodyPromise| be the result. + 1. [=Consume body|Consume=] |response|'s body as an {{ArrayBuffer}}, and let |bodyPromise| be the result. Note: Although it is specified here that the response is consumed entirely before compilation proceeds, that is purely for ease of specification; implementations are likely to instead perform processing in a streaming fashion. The difference is unobservable, and thus the simpler model is specified. @@ -145,7 +145,7 @@ Web user agents must augment the {{Module}} interface with the [DataCloneError" {{DOMException}} + 1. If |forStorage| is true, throw a "DataCloneError" {{DOMException}}. 1. Set |serialized|.\[[Bytes]] to the [=sub-serialization=] of |value|.\[[Bytes]]. @@ -184,7 +184,7 @@ example) even though the exact format of implementation-dependent stack trace strings does not always match, the locations are easily understandable and the same across browsers. -To achieve the same goal of a common representations for WebAssembly constructs, the +To achieve the same goal of a common representation for WebAssembly constructs, the following conventions are adopted. A WebAssembly location is a reference to a particular instruction in the binary, and may be From 684d625de1014f551b46541cb3bcdd027fe43899 Mon Sep 17 00:00:00 2001 From: gahaas Date: Thu, 12 May 2022 14:31:28 +0200 Subject: [PATCH 079/181] TypeError for Global constructor with v128 At the moment the spec requires a `LinkError` to be thrown when the `WebAssembly.Global` constructor is called for type `v128`. This was introduced in https://github.com/WebAssembly/simd/pull/360, but according to the PR description, actually a `TypeError` should be thrown. The PR refers to https://github.com/WebAssembly/simd/blob/master/proposals/simd/SIMD.md#javascript-api-and-simd-values, and there a `TypeError` is required. --- document/js-api/index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 59af6515d..43c189f22 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -916,7 +916,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Let |mutable| be |descriptor|["mutable"]. 1. Let |valuetype| be [=ToValueType=](|descriptor|["value"]). 1. If |valuetype| is [=v128=], - 1. Throw a {{LinkError}} exception. + 1. Throw a {{TypeError}} exception. 1. If |v| is missing, 1. Let |value| be [=DefaultValue=](|valuetype|). 1. Otherwise, From 23b166ca04bb6342e22bb04673989e36b6acc238 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 16 May 2022 18:36:18 +0200 Subject: [PATCH 080/181] [spec] Fix LEB opcodes in instruction index (#1475) --- .../core/appendix/gen-index-instructions.py | 216 ++-- document/core/appendix/index-instructions.rst | 1028 ++++++++--------- 2 files changed, 618 insertions(+), 626 deletions(-) diff --git a/document/core/appendix/gen-index-instructions.py b/document/core/appendix/gen-index-instructions.py index e3232c5a7..4ab7b64d4 100755 --- a/document/core/appendix/gen-index-instructions.py +++ b/document/core/appendix/gen-index-instructions.py @@ -467,114 +467,114 @@ def Instruction(name, opcode, type=None, validation=None, execution=None, operat Instruction(r'\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_u}', r'\hex{FD}~~\hex{7D}', r'[\V128] \to [\V128]', r'valid-vec-extadd_pairwise', r'exec-vec-extadd_pairwise'), Instruction(r'\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_s}', r'\hex{FD}~~\hex{7E}', r'[\V128] \to [\V128]', r'valid-vec-extadd_pairwise', r'exec-vec-extadd_pairwise'), Instruction(r'\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_u}', r'\hex{FD}~~\hex{7F}', r'[\V128] \to [\V128]', r'valid-vec-extadd_pairwise', r'exec-vec-extadd_pairwise'), - Instruction(r'\I16X8.\VABS', r'\hex{FD}~~\hex{80}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), - Instruction(r'\I16X8.\VNEG', r'\hex{FD}~~\hex{81}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), - Instruction(r'\I16X8.\Q15MULRSAT\K{\_s}', r'\hex{FD}~~\hex{82}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iq15mulrsat_s'), - Instruction(r'\I16X8.\ALLTRUE', r'\hex{FD}~~\hex{83}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), - Instruction(r'\I16X8.\BITMASK', r'\hex{FD}~~\hex{84}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), - Instruction(r'\I16X8.\NARROW\K{\_i32x4\_s}', r'\hex{FD}~~\hex{85}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vec-narrow'), - Instruction(r'\I16X8.\NARROW\K{\_i32x4\_u}', r'\hex{FD}~~\hex{86}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vec-narrow'), - Instruction(r'\I16X8.\VEXTEND\K{\_low\_i8x16\_s}', r'\hex{FD}~~\hex{87}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I16X8.\VEXTEND\K{\_high\_i8x16\_s}', r'\hex{FD}~~\hex{88}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I16X8.\VEXTEND\K{\_low\_i8x16\_u}', r'\hex{FD}~~\hex{89}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I16X8.\VEXTEND\K{\_high\_i8x16\_u}', r'\hex{FD}~~\hex{8A}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I16X8.\VSHL', r'\hex{FD}~~\hex{8B}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), - Instruction(r'\I16X8.\VSHR\K{\_s}', r'\hex{FD}~~\hex{8C}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), - Instruction(r'\I16X8.\VSHR\K{\_u}', r'\hex{FD}~~\hex{8D}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), - Instruction(r'\I16X8.\VADD', r'\hex{FD}~~\hex{8E}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), - Instruction(r'\I16X8.\VADD\K{\_sat\_s}', r'\hex{FD}~~\hex{8F}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd_sat_s'), - Instruction(r'\I16X8.\VADD\K{\_sat\_u}', r'\hex{FD}~~\hex{90}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd_sat_u'), - Instruction(r'\I16X8.\VSUB', r'\hex{FD}~~\hex{91}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), - Instruction(r'\I16X8.\VSUB\K{\_sat\_s}', r'\hex{FD}~~\hex{92}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub_sat_s'), - Instruction(r'\I16X8.\VSUB\K{\_sat\_u}', r'\hex{FD}~~\hex{93}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub_sat_u'), - Instruction(r'\F64X2.\VNEAREST', r'\hex{FD}~~\hex{94}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fnearest'), - Instruction(r'\I16X8.\VMUL', r'\hex{FD}~~\hex{95}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), - Instruction(r'\I16X8.\VMIN\K{\_s}', r'\hex{FD}~~\hex{96}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_s'), - Instruction(r'\I16X8.\VMIN\K{\_u}', r'\hex{FD}~~\hex{97}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_u'), - Instruction(r'\I16X8.\VMAX\K{\_s}', r'\hex{FD}~~\hex{98}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_s'), - Instruction(r'\I16X8.\VMAX\K{\_u}', r'\hex{FD}~~\hex{99}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_u'), - Instruction(r'\I16X8.\AVGR\K{\_u}', r'\hex{FD}~~\hex{9B}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iavgr_u'), - Instruction(r'\I16X8.\EXTMUL\K{\_low\_i8x16\_s}', r'\hex{FD}~~\hex{9C}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I16X8.\EXTMUL\K{\_high\_i8x16\_s}', r'\hex{FD}~~\hex{9D}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I16X8.\EXTMUL\K{\_low\_i8x16\_u}', r'\hex{FD}~~\hex{9E}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I16X8.\EXTMUL\K{\_high\_i8x16\_u}', r'\hex{FD}~~\hex{9F}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I32X4.\VABS', r'\hex{FD}~~\hex{A0}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), - Instruction(r'\I32X4.\VNEG', r'\hex{FD}~~\hex{A1}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), - Instruction(r'\I32X4.\ALLTRUE', r'\hex{FD}~~\hex{A3}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), - Instruction(r'\I32X4.\BITMASK', r'\hex{FD}~~\hex{A4}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), - Instruction(r'\I32X4.\VEXTEND\K{\_low\_i16x8\_s}', r'\hex{FD}~~\hex{A7}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I32X4.\VEXTEND\K{\_high\_i16x8\_s}', r'\hex{FD}~~\hex{A8}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I32X4.\VEXTEND\K{\_low\_i16x8\_u}', r'\hex{FD}~~\hex{A9}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I32X4.\VEXTEND\K{\_high\_i16x8\_u}', r'\hex{FD}~~\hex{AA}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I32X4.\VSHL', r'\hex{FD}~~\hex{AB}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), - Instruction(r'\I32X4.\VSHR\K{\_s}', r'\hex{FD}~~\hex{AC}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), - Instruction(r'\I32X4.\VSHR\K{\_u}', r'\hex{FD}~~\hex{AD}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), - Instruction(r'\I32X4.\VADD', r'\hex{FD}~~\hex{AE}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), - Instruction(r'\I32X4.\VSUB', r'\hex{FD}~~\hex{B1}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), - Instruction(r'\I32X4.\VMUL', r'\hex{FD}~~\hex{B5}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), - Instruction(r'\I32X4.\VMIN\K{\_s}', r'\hex{FD}~~\hex{B6}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_s'), - Instruction(r'\I32X4.\VMIN\K{\_u}', r'\hex{FD}~~\hex{B7}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_u'), - Instruction(r'\I32X4.\VMAX\K{\_s}', r'\hex{FD}~~\hex{B8}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_s'), - Instruction(r'\I32X4.\VMAX\K{\_u}', r'\hex{FD}~~\hex{B9}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_u'), - Instruction(r'\I32X4.\DOT\K{\_i16x8\_s}', r'\hex{FD}~~\hex{BA}', r'[\V128~\V128] \to [\V128]', r'valid-vec-dot', r'exec-vec-dot'), - Instruction(r'\I32X4.\EXTMUL\K{\_low\_i16x8\_s}', r'\hex{FD}~~\hex{BC}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I32X4.\EXTMUL\K{\_high\_i16x8\_s}', r'\hex{FD}~~\hex{BD}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I32X4.\EXTMUL\K{\_low\_i16x8\_u}', r'\hex{FD}~~\hex{BE}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I32X4.\EXTMUL\K{\_high\_i16x8\_u}', r'\hex{FD}~~\hex{BF}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I64X2.\VABS', r'\hex{FD}~~\hex{C0}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), - Instruction(r'\I64X2.\VNEG', r'\hex{FD}~~\hex{C1}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), - Instruction(r'\I64X2.\ALLTRUE', r'\hex{FD}~~\hex{C3}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), - Instruction(r'\I64X2.\BITMASK', r'\hex{FD}~~\hex{C4}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), - Instruction(r'\I64X2.\VEXTEND\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{C7}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I64X2.\VEXTEND\K{\_high\_i32x4\_s}', r'\hex{FD}~~\hex{C8}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I64X2.\VEXTEND\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{C9}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I64X2.\VEXTEND\K{\_high\_i32x4\_u}', r'\hex{FD}~~\hex{CA}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), - Instruction(r'\I64X2.\VSHL', r'\hex{FD}~~\hex{CB}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), - Instruction(r'\I64X2.\VSHR\K{\_s}', r'\hex{FD}~~\hex{CC}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), - Instruction(r'\I64X2.\VSHR\K{\_u}', r'\hex{FD}~~\hex{CD}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), - Instruction(r'\I64X2.\VADD', r'\hex{FD}~~\hex{CE}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), - Instruction(r'\I64X2.\VSUB', r'\hex{FD}~~\hex{D1}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), - Instruction(r'\I64X2.\VMUL', r'\hex{FD}~~\hex{D5}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), - Instruction(r'\I64X2.\VEQ', r'\hex{FD}~~\hex{D6}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ieq'), - Instruction(r'\I64X2.\VNE', r'\hex{FD}~~\hex{D7}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ine'), - Instruction(r'\I64X2.\VLT\K{\_s}', r'\hex{FD}~~\hex{D8}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ilt_s'), - Instruction(r'\I64X2.\VGT\K{\_s}', r'\hex{FD}~~\hex{D9}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-igt_s'), - Instruction(r'\I64X2.\VLE\K{\_s}', r'\hex{FD}~~\hex{DA}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ile_s'), - Instruction(r'\I64X2.\VGE\K{\_s}', r'\hex{FD}~~\hex{DB}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ige_s'), - Instruction(r'\I64X2.\EXTMUL\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{DC}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I64X2.\EXTMUL\K{\_high\_i32x4\_s}', r'\hex{FD}~~\hex{DD}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I64X2.\EXTMUL\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{DE}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\I64X2.\EXTMUL\K{\_high\_i32x4\_u}', r'\hex{FD}~~\hex{DF}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), - Instruction(r'\F32X4.\VABS', r'\hex{FD}~~\hex{E0}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fabs'), - Instruction(r'\F32X4.\VNEG', r'\hex{FD}~~\hex{E1}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fneg'), - Instruction(r'\F32X4.\VSQRT', r'\hex{FD}~~\hex{E3}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fsqrt'), - Instruction(r'\F32X4.\VADD', r'\hex{FD}~~\hex{E4}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fadd'), - Instruction(r'\F32X4.\VSUB', r'\hex{FD}~~\hex{E5}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fsub'), - Instruction(r'\F32X4.\VMUL', r'\hex{FD}~~\hex{E6}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmul'), - Instruction(r'\F32X4.\VDIV', r'\hex{FD}~~\hex{E7}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fdiv'), - Instruction(r'\F32X4.\VMIN', r'\hex{FD}~~\hex{E8}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmin'), - Instruction(r'\F32X4.\VMAX', r'\hex{FD}~~\hex{E9}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmax'), - Instruction(r'\F32X4.\VPMIN', r'\hex{FD}~~\hex{EA}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmin'), - Instruction(r'\F32X4.\VPMAX', r'\hex{FD}~~\hex{EB}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmax'), - Instruction(r'\F64X2.\VABS', r'\hex{FD}~~\hex{EC}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fabs'), - Instruction(r'\F64X2.\VNEG', r'\hex{FD}~~\hex{ED}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fneg'), - Instruction(r'\F64X2.\VSQRT', r'\hex{FD}~~\hex{EF}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fsqrt'), - Instruction(r'\F64X2.\VADD', r'\hex{FD}~~\hex{F0}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fadd'), - Instruction(r'\F64X2.\VSUB', r'\hex{FD}~~\hex{F1}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fsub'), - Instruction(r'\F64X2.\VMUL', r'\hex{FD}~~\hex{F2}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmul'), - Instruction(r'\F64X2.\VDIV', r'\hex{FD}~~\hex{F3}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fdiv'), - Instruction(r'\F64X2.\VMIN', r'\hex{FD}~~\hex{F4}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmin'), - Instruction(r'\F64X2.\VMAX', r'\hex{FD}~~\hex{F5}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmax'), - Instruction(r'\F64X2.\VPMIN', r'\hex{FD}~~\hex{F6}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmin'), - Instruction(r'\F64X2.\VPMAX', r'\hex{FD}~~\hex{F7}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmax'), - Instruction(r'\I32X4.\TRUNC\K{\_sat\_f32x4\_s}', r'\hex{FD}~~\hex{F8}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_s'), - Instruction(r'\I32X4.\TRUNC\K{\_sat\_f32x4\_u}', r'\hex{FD}~~\hex{F9}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_u'), - Instruction(r'\F32X4.\VCONVERT\K{\_i32x4\_s}', r'\hex{FD}~~\hex{FA}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_s'), - Instruction(r'\F32X4.\VCONVERT\K{\_i32x4\_u}', r'\hex{FD}~~\hex{FB}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_u'), - Instruction(r'\I32X4.\VTRUNC\K{\_sat\_f64x2\_s\_zero}', r'\hex{FD}~~\hex{FC}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_s'), - Instruction(r'\I32X4.\VTRUNC\K{\_sat\_f64x2\_u\_zero}', r'\hex{FD}~~\hex{FD}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_u'), - Instruction(r'\F64X2.\VCONVERT\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{FE}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_s'), - Instruction(r'\F64X2.\VCONVERT\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{FF}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_u'), + Instruction(r'\I16X8.\VABS', r'\hex{FD}~~\hex{80}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), + Instruction(r'\I16X8.\VNEG', r'\hex{FD}~~\hex{81}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), + Instruction(r'\I16X8.\Q15MULRSAT\K{\_s}', r'\hex{FD}~~\hex{82}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iq15mulrsat_s'), + Instruction(r'\I16X8.\ALLTRUE', r'\hex{FD}~~\hex{83}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), + Instruction(r'\I16X8.\BITMASK', r'\hex{FD}~~\hex{84}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), + Instruction(r'\I16X8.\NARROW\K{\_i32x4\_s}', r'\hex{FD}~~\hex{85}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vec-narrow'), + Instruction(r'\I16X8.\NARROW\K{\_i32x4\_u}', r'\hex{FD}~~\hex{86}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vec-narrow'), + Instruction(r'\I16X8.\VEXTEND\K{\_low\_i8x16\_s}', r'\hex{FD}~~\hex{87}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I16X8.\VEXTEND\K{\_high\_i8x16\_s}', r'\hex{FD}~~\hex{88}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I16X8.\VEXTEND\K{\_low\_i8x16\_u}', r'\hex{FD}~~\hex{89}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I16X8.\VEXTEND\K{\_high\_i8x16\_u}', r'\hex{FD}~~\hex{8A}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I16X8.\VSHL', r'\hex{FD}~~\hex{8B}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), + Instruction(r'\I16X8.\VSHR\K{\_s}', r'\hex{FD}~~\hex{8C}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), + Instruction(r'\I16X8.\VSHR\K{\_u}', r'\hex{FD}~~\hex{8D}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), + Instruction(r'\I16X8.\VADD', r'\hex{FD}~~\hex{8E}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), + Instruction(r'\I16X8.\VADD\K{\_sat\_s}', r'\hex{FD}~~\hex{8F}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd_sat_s'), + Instruction(r'\I16X8.\VADD\K{\_sat\_u}', r'\hex{FD}~~\hex{90}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd_sat_u'), + Instruction(r'\I16X8.\VSUB', r'\hex{FD}~~\hex{91}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), + Instruction(r'\I16X8.\VSUB\K{\_sat\_s}', r'\hex{FD}~~\hex{92}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub_sat_s'), + Instruction(r'\I16X8.\VSUB\K{\_sat\_u}', r'\hex{FD}~~\hex{93}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub_sat_u'), + Instruction(r'\F64X2.\VNEAREST', r'\hex{FD}~~\hex{94}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fnearest'), + Instruction(r'\I16X8.\VMUL', r'\hex{FD}~~\hex{95}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), + Instruction(r'\I16X8.\VMIN\K{\_s}', r'\hex{FD}~~\hex{96}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_s'), + Instruction(r'\I16X8.\VMIN\K{\_u}', r'\hex{FD}~~\hex{97}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_u'), + Instruction(r'\I16X8.\VMAX\K{\_s}', r'\hex{FD}~~\hex{98}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_s'), + Instruction(r'\I16X8.\VMAX\K{\_u}', r'\hex{FD}~~\hex{99}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_u'), + Instruction(r'\I16X8.\AVGR\K{\_u}', r'\hex{FD}~~\hex{9B}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iavgr_u'), + Instruction(r'\I16X8.\EXTMUL\K{\_low\_i8x16\_s}', r'\hex{FD}~~\hex{9C}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I16X8.\EXTMUL\K{\_high\_i8x16\_s}', r'\hex{FD}~~\hex{9D}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I16X8.\EXTMUL\K{\_low\_i8x16\_u}', r'\hex{FD}~~\hex{9E}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I16X8.\EXTMUL\K{\_high\_i8x16\_u}', r'\hex{FD}~~\hex{9F}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I32X4.\VABS', r'\hex{FD}~~\hex{A0}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), + Instruction(r'\I32X4.\VNEG', r'\hex{FD}~~\hex{A1}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), + Instruction(r'\I32X4.\ALLTRUE', r'\hex{FD}~~\hex{A3}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), + Instruction(r'\I32X4.\BITMASK', r'\hex{FD}~~\hex{A4}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), + Instruction(r'\I32X4.\VEXTEND\K{\_low\_i16x8\_s}', r'\hex{FD}~~\hex{A7}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I32X4.\VEXTEND\K{\_high\_i16x8\_s}', r'\hex{FD}~~\hex{A8}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I32X4.\VEXTEND\K{\_low\_i16x8\_u}', r'\hex{FD}~~\hex{A9}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I32X4.\VEXTEND\K{\_high\_i16x8\_u}', r'\hex{FD}~~\hex{AA}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I32X4.\VSHL', r'\hex{FD}~~\hex{AB}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), + Instruction(r'\I32X4.\VSHR\K{\_s}', r'\hex{FD}~~\hex{AC}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), + Instruction(r'\I32X4.\VSHR\K{\_u}', r'\hex{FD}~~\hex{AD}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), + Instruction(r'\I32X4.\VADD', r'\hex{FD}~~\hex{AE}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), + Instruction(r'\I32X4.\VSUB', r'\hex{FD}~~\hex{B1}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), + Instruction(r'\I32X4.\VMUL', r'\hex{FD}~~\hex{B5}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), + Instruction(r'\I32X4.\VMIN\K{\_s}', r'\hex{FD}~~\hex{B6}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_s'), + Instruction(r'\I32X4.\VMIN\K{\_u}', r'\hex{FD}~~\hex{B7}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imin_u'), + Instruction(r'\I32X4.\VMAX\K{\_s}', r'\hex{FD}~~\hex{B8}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_s'), + Instruction(r'\I32X4.\VMAX\K{\_u}', r'\hex{FD}~~\hex{B9}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imax_u'), + Instruction(r'\I32X4.\DOT\K{\_i16x8\_s}', r'\hex{FD}~~\hex{BA}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-dot', r'exec-vec-dot'), + Instruction(r'\I32X4.\EXTMUL\K{\_low\_i16x8\_s}', r'\hex{FD}~~\hex{BC}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I32X4.\EXTMUL\K{\_high\_i16x8\_s}', r'\hex{FD}~~\hex{BD}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I32X4.\EXTMUL\K{\_low\_i16x8\_u}', r'\hex{FD}~~\hex{BE}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I32X4.\EXTMUL\K{\_high\_i16x8\_u}', r'\hex{FD}~~\hex{BF}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I64X2.\VABS', r'\hex{FD}~~\hex{C0}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-iabs'), + Instruction(r'\I64X2.\VNEG', r'\hex{FD}~~\hex{C1}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-ineg'), + Instruction(r'\I64X2.\ALLTRUE', r'\hex{FD}~~\hex{C3}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vtestop', r'exec-vtestop'), + Instruction(r'\I64X2.\BITMASK', r'\hex{FD}~~\hex{C4}~~\hex{01}', r'[\V128] \to [\I32]', r'valid-vec-bitmask', r'exec-vec-bitmask'), + Instruction(r'\I64X2.\VEXTEND\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{C7}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I64X2.\VEXTEND\K{\_high\_i32x4\_s}', r'\hex{FD}~~\hex{C8}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I64X2.\VEXTEND\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{C9}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I64X2.\VEXTEND\K{\_high\_i32x4\_u}', r'\hex{FD}~~\hex{CA}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vcvtop'), + Instruction(r'\I64X2.\VSHL', r'\hex{FD}~~\hex{CB}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishl'), + Instruction(r'\I64X2.\VSHR\K{\_s}', r'\hex{FD}~~\hex{CC}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_s'), + Instruction(r'\I64X2.\VSHR\K{\_u}', r'\hex{FD}~~\hex{CD}~~\hex{01}', r'[\V128~\I32] \to [\V128]', r'valid-vishiftop', r'exec-vishiftop', r'op-ishr_u'), + Instruction(r'\I64X2.\VADD', r'\hex{FD}~~\hex{CE}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-iadd'), + Instruction(r'\I64X2.\VSUB', r'\hex{FD}~~\hex{D1}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-isub'), + Instruction(r'\I64X2.\VMUL', r'\hex{FD}~~\hex{D5}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-imul'), + Instruction(r'\I64X2.\VEQ', r'\hex{FD}~~\hex{D6}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ieq'), + Instruction(r'\I64X2.\VNE', r'\hex{FD}~~\hex{D7}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ine'), + Instruction(r'\I64X2.\VLT\K{\_s}', r'\hex{FD}~~\hex{D8}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ilt_s'), + Instruction(r'\I64X2.\VGT\K{\_s}', r'\hex{FD}~~\hex{D9}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-igt_s'), + Instruction(r'\I64X2.\VLE\K{\_s}', r'\hex{FD}~~\hex{DA}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ile_s'), + Instruction(r'\I64X2.\VGE\K{\_s}', r'\hex{FD}~~\hex{DB}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-ige_s'), + Instruction(r'\I64X2.\EXTMUL\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{DC}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I64X2.\EXTMUL\K{\_high\_i32x4\_s}', r'\hex{FD}~~\hex{DD}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I64X2.\EXTMUL\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{DE}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\I64X2.\EXTMUL\K{\_high\_i32x4\_u}', r'\hex{FD}~~\hex{DF}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vec-extmul', r'exec-vec-extmul'), + Instruction(r'\F32X4.\VABS', r'\hex{FD}~~\hex{E0}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fabs'), + Instruction(r'\F32X4.\VNEG', r'\hex{FD}~~\hex{E1}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fneg'), + Instruction(r'\F32X4.\VSQRT', r'\hex{FD}~~\hex{E3}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fsqrt'), + Instruction(r'\F32X4.\VADD', r'\hex{FD}~~\hex{E4}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fadd'), + Instruction(r'\F32X4.\VSUB', r'\hex{FD}~~\hex{E5}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fsub'), + Instruction(r'\F32X4.\VMUL', r'\hex{FD}~~\hex{E6}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmul'), + Instruction(r'\F32X4.\VDIV', r'\hex{FD}~~\hex{E7}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fdiv'), + Instruction(r'\F32X4.\VMIN', r'\hex{FD}~~\hex{E8}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmin'), + Instruction(r'\F32X4.\VMAX', r'\hex{FD}~~\hex{E9}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmax'), + Instruction(r'\F32X4.\VPMIN', r'\hex{FD}~~\hex{EA}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmin'), + Instruction(r'\F32X4.\VPMAX', r'\hex{FD}~~\hex{EB}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmax'), + Instruction(r'\F64X2.\VABS', r'\hex{FD}~~\hex{EC}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fabs'), + Instruction(r'\F64X2.\VNEG', r'\hex{FD}~~\hex{ED}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fneg'), + Instruction(r'\F64X2.\VSQRT', r'\hex{FD}~~\hex{EF}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vunop', r'exec-vunop', r'op-fsqrt'), + Instruction(r'\F64X2.\VADD', r'\hex{FD}~~\hex{F0}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fadd'), + Instruction(r'\F64X2.\VSUB', r'\hex{FD}~~\hex{F1}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fsub'), + Instruction(r'\F64X2.\VMUL', r'\hex{FD}~~\hex{F2}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmul'), + Instruction(r'\F64X2.\VDIV', r'\hex{FD}~~\hex{F3}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fdiv'), + Instruction(r'\F64X2.\VMIN', r'\hex{FD}~~\hex{F4}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmin'), + Instruction(r'\F64X2.\VMAX', r'\hex{FD}~~\hex{F5}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fmax'), + Instruction(r'\F64X2.\VPMIN', r'\hex{FD}~~\hex{F6}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmin'), + Instruction(r'\F64X2.\VPMAX', r'\hex{FD}~~\hex{F7}~~\hex{01}', r'[\V128~\V128] \to [\V128]', r'valid-vbinop', r'exec-vbinop', r'op-fpmax'), + Instruction(r'\I32X4.\TRUNC\K{\_sat\_f32x4\_s}', r'\hex{FD}~~\hex{F8}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_s'), + Instruction(r'\I32X4.\TRUNC\K{\_sat\_f32x4\_u}', r'\hex{FD}~~\hex{F9}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_u'), + Instruction(r'\F32X4.\VCONVERT\K{\_i32x4\_s}', r'\hex{FD}~~\hex{FA}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_s'), + Instruction(r'\F32X4.\VCONVERT\K{\_i32x4\_u}', r'\hex{FD}~~\hex{FB}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_u'), + Instruction(r'\I32X4.\VTRUNC\K{\_sat\_f64x2\_s\_zero}', r'\hex{FD}~~\hex{FC}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_s'), + Instruction(r'\I32X4.\VTRUNC\K{\_sat\_f64x2\_u\_zero}', r'\hex{FD}~~\hex{FD}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-trunc_sat_u'), + Instruction(r'\F64X2.\VCONVERT\K{\_low\_i32x4\_s}', r'\hex{FD}~~\hex{FE}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_s'), + Instruction(r'\F64X2.\VCONVERT\K{\_low\_i32x4\_u}', r'\hex{FD}~~\hex{FF}~~\hex{01}', r'[\V128] \to [\V128]', r'valid-vcvtop', r'exec-vcvtop', r'op-convert_u'), ] diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst index 27d3bd0ea..a82fa9a62 100644 --- a/document/core/appendix/index-instructions.rst +++ b/document/core/appendix/index-instructions.rst @@ -6,521 +6,513 @@ Index of Instructions --------------------- -================================================= ========================== ============================================= ============================================= ================================================================== -Instruction Binary Opcode Type Validation Execution -================================================= ========================== ============================================= ============================================= ================================================================== -:math:`\UNREACHABLE` :math:`\hex{00}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\NOP` :math:`\hex{01}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\BLOCK~\X{bt}` :math:`\hex{02}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\LOOP~\X{bt}` :math:`\hex{03}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\IF~\X{bt}` :math:`\hex{04}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\ELSE` :math:`\hex{05}` -(reserved) :math:`\hex{06}` -(reserved) :math:`\hex{07}` -(reserved) :math:`\hex{08}` -(reserved) :math:`\hex{09}` -(reserved) :math:`\hex{0A}` -:math:`\END` :math:`\hex{0B}` -:math:`\BR~l` :math:`\hex{0C}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\BRIF~l` :math:`\hex{0D}` :math:`[t^\ast~\I32] \to [t^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\BRTABLE~l^\ast~l` :math:`\hex{0E}` :math:`[t_1^\ast~t^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\RETURN` :math:`\hex{0F}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\CALL~x` :math:`\hex{10}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\CALLINDIRECT~x~y` :math:`\hex{11}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{12}` -(reserved) :math:`\hex{13}` -(reserved) :math:`\hex{14}` -(reserved) :math:`\hex{15}` -(reserved) :math:`\hex{16}` -(reserved) :math:`\hex{17}` -(reserved) :math:`\hex{18}` -(reserved) :math:`\hex{19}` -:math:`\DROP` :math:`\hex{1A}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\SELECT` :math:`\hex{1B}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\SELECT~t` :math:`\hex{1C}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{1D}` -(reserved) :math:`\hex{1E}` -(reserved) :math:`\hex{1F}` -:math:`\LOCALGET~x` :math:`\hex{20}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\LOCALSET~x` :math:`\hex{21}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\LOCALTEE~x` :math:`\hex{22}` :math:`[t] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\GLOBALGET~x` :math:`\hex{23}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\GLOBALSET~x` :math:`\hex{24}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEGET~x` :math:`\hex{25}` :math:`[\I32] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\TABLESET~x` :math:`\hex{26}` :math:`[\I32~t] \to []` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{27}` -:math:`\I32.\LOAD~x~\memarg` :math:`\hex{28}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD~x~\memarg` :math:`\hex{29}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\F32.\LOAD~x~\memarg` :math:`\hex{2A}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F64.\LOAD~x~\memarg` :math:`\hex{2B}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{8\_s}~x~\memarg` :math:`\hex{2C}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{8\_u}~x~\memarg` :math:`\hex{2D}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{16\_s}~x~\memarg` :math:`\hex{2E}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{16\_u}~x~\memarg` :math:`\hex{2F}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{8\_s}~x~\memarg` :math:`\hex{30}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{8\_u}~x~\memarg` :math:`\hex{31}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{16\_s}~x~\memarg` :math:`\hex{32}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{16\_u}~x~\memarg` :math:`\hex{33}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{32\_s}~x~\memarg` :math:`\hex{34}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{32\_u}~x~\memarg` :math:`\hex{35}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE~x~\memarg` :math:`\hex{36}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE~x~\memarg` :math:`\hex{37}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\F32.\STORE~x~\memarg` :math:`\hex{38}` :math:`[\I32~\F32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\F64.\STORE~x~\memarg` :math:`\hex{39}` :math:`[\I32~\F64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE\K{8}~x~\memarg` :math:`\hex{3A}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE\K{16}~x~\memarg` :math:`\hex{3B}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{8}~x~\memarg` :math:`\hex{3C}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{16}~x~\memarg` :math:`\hex{3D}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{32}~x~\memarg` :math:`\hex{3E}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYSIZE~x` :math:`\hex{3F}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYGROW~x` :math:`\hex{40}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\CONST~\i32` :math:`\hex{41}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\CONST~\i64` :math:`\hex{42}` :math:`[] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\F32.\CONST~\f32` :math:`\hex{43}` :math:`[] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F64.\CONST~\f64` :math:`\hex{44}` :math:`[] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\EQZ` :math:`\hex{45}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EQ` :math:`\hex{46}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\NE` :math:`\hex{47}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LT\K{\_s}` :math:`\hex{48}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LT\K{\_u}` :math:`\hex{49}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GT\K{\_s}` :math:`\hex{4A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GT\K{\_u}` :math:`\hex{4B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LE\K{\_s}` :math:`\hex{4C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LE\K{\_u}` :math:`\hex{4D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GE\K{\_s}` :math:`\hex{4E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GE\K{\_u}` :math:`\hex{4F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EQZ` :math:`\hex{50}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EQ` :math:`\hex{51}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\NE` :math:`\hex{52}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LT\K{\_s}` :math:`\hex{53}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LT\K{\_u}` :math:`\hex{54}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GT\K{\_s}` :math:`\hex{55}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GT\K{\_u}` :math:`\hex{56}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LE\K{\_s}` :math:`\hex{57}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LE\K{\_u}` :math:`\hex{58}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GE\K{\_s}` :math:`\hex{59}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GE\K{\_u}` :math:`\hex{5A}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\EQ` :math:`\hex{5B}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NE` :math:`\hex{5C}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\LT` :math:`\hex{5D}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\GT` :math:`\hex{5E}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\LE` :math:`\hex{5F}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\GE` :math:`\hex{60}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\EQ` :math:`\hex{61}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NE` :math:`\hex{62}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\LT` :math:`\hex{63}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\GT` :math:`\hex{64}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\LE` :math:`\hex{65}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\GE` :math:`\hex{66}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\CLZ` :math:`\hex{67}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\CTZ` :math:`\hex{68}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\POPCNT` :math:`\hex{69}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ADD` :math:`\hex{6A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SUB` :math:`\hex{6B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\MUL` :math:`\hex{6C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\DIV\K{\_s}` :math:`\hex{6D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\DIV\K{\_u}` :math:`\hex{6E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REM\K{\_s}` :math:`\hex{6F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REM\K{\_u}` :math:`\hex{70}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\AND` :math:`\hex{71}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\OR` :math:`\hex{72}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\XOR` :math:`\hex{73}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHL` :math:`\hex{74}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHR\K{\_s}` :math:`\hex{75}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHR\K{\_u}` :math:`\hex{76}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ROTL` :math:`\hex{77}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ROTR` :math:`\hex{78}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\CLZ` :math:`\hex{79}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\CTZ` :math:`\hex{7A}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\POPCNT` :math:`\hex{7B}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ADD` :math:`\hex{7C}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SUB` :math:`\hex{7D}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\MUL` :math:`\hex{7E}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\DIV\K{\_s}` :math:`\hex{7F}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\DIV\K{\_u}` :math:`\hex{80}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REM\K{\_s}` :math:`\hex{81}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REM\K{\_u}` :math:`\hex{82}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\AND` :math:`\hex{83}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\OR` :math:`\hex{84}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\XOR` :math:`\hex{85}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHL` :math:`\hex{86}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHR\K{\_s}` :math:`\hex{87}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHR\K{\_u}` :math:`\hex{88}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ROTL` :math:`\hex{89}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ROTR` :math:`\hex{8A}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\ABS` :math:`\hex{8B}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NEG` :math:`\hex{8C}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CEIL` :math:`\hex{8D}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FLOOR` :math:`\hex{8E}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\TRUNC` :math:`\hex{8F}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NEAREST` :math:`\hex{90}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\SQRT` :math:`\hex{91}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\ADD` :math:`\hex{92}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\SUB` :math:`\hex{93}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\MUL` :math:`\hex{94}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\DIV` :math:`\hex{95}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FMIN` :math:`\hex{96}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FMAX` :math:`\hex{97}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\COPYSIGN` :math:`\hex{98}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\ABS` :math:`\hex{99}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NEG` :math:`\hex{9A}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CEIL` :math:`\hex{9B}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FLOOR` :math:`\hex{9C}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\TRUNC` :math:`\hex{9D}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NEAREST` :math:`\hex{9E}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\SQRT` :math:`\hex{9F}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\ADD` :math:`\hex{A0}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\SUB` :math:`\hex{A1}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\MUL` :math:`\hex{A2}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\DIV` :math:`\hex{A3}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FMIN` :math:`\hex{A4}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FMAX` :math:`\hex{A5}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\COPYSIGN` :math:`\hex{A6}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\WRAP\K{\_}\I64` :math:`\hex{A7}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{A8}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{A9}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{AA}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{AB}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{\_}\I32\K{\_s}` :math:`\hex{AC}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{\_}\I32\K{\_u}` :math:`\hex{AD}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{AE}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{AF}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{B0}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{B1}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B2}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B3}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B4}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{B5}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\DEMOTE\K{\_}\F64` :math:`\hex{B6}` :math:`[\F64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B7}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B8}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B9}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{BA}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\PROMOTE\K{\_}\F32` :math:`\hex{BB}` :math:`[\F32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REINTERPRET\K{\_}\F32` :math:`\hex{BC}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REINTERPRET\K{\_}\F64` :math:`\hex{BD}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\REINTERPRET\K{\_}\I32` :math:`\hex{BE}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\REINTERPRET\K{\_}\I64` :math:`\hex{BF}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EXTEND\K{8\_s}` :math:`\hex{C0}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EXTEND\K{16\_s}` :math:`\hex{C1}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{8\_s}` :math:`\hex{C2}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{16\_s}` :math:`\hex{C3}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{32\_s}` :math:`\hex{C4}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -(reserved) :math:`\hex{C5}` -(reserved) :math:`\hex{C6}` -(reserved) :math:`\hex{C7}` -(reserved) :math:`\hex{C8}` -(reserved) :math:`\hex{C9}` -(reserved) :math:`\hex{CA}` -(reserved) :math:`\hex{CB}` -(reserved) :math:`\hex{CC}` -(reserved) :math:`\hex{CD}` -(reserved) :math:`\hex{CE}` -(reserved) :math:`\hex{CF}` -:math:`\REFNULL~t` :math:`\hex{D0}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\REFISNULL` :math:`\hex{D1}` :math:`[t] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\REFFUNC~x` :math:`\hex{D2}` :math:`[] \to [\FUNCREF]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{D3}` -(reserved) :math:`\hex{D4}` -(reserved) :math:`\hex{D5}` -(reserved) :math:`\hex{D6}` -(reserved) :math:`\hex{D7}` -(reserved) :math:`\hex{D8}` -(reserved) :math:`\hex{D9}` -(reserved) :math:`\hex{DA}` -(reserved) :math:`\hex{DB}` -(reserved) :math:`\hex{DC}` -(reserved) :math:`\hex{DD}` -(reserved) :math:`\hex{DE}` -(reserved) :math:`\hex{DF}` -(reserved) :math:`\hex{E0}` -(reserved) :math:`\hex{E1}` -(reserved) :math:`\hex{E2}` -(reserved) :math:`\hex{E3}` -(reserved) :math:`\hex{E4}` -(reserved) :math:`\hex{E5}` -(reserved) :math:`\hex{E6}` -(reserved) :math:`\hex{E7}` -(reserved) :math:`\hex{E8}` -(reserved) :math:`\hex{E9}` -(reserved) :math:`\hex{EA}` -(reserved) :math:`\hex{EB}` -(reserved) :math:`\hex{EC}` -(reserved) :math:`\hex{ED}` -(reserved) :math:`\hex{EE}` -(reserved) :math:`\hex{EF}` -(reserved) :math:`\hex{F0}` -(reserved) :math:`\hex{F1}` -(reserved) :math:`\hex{F2}` -(reserved) :math:`\hex{F3}` -(reserved) :math:`\hex{F4}` -(reserved) :math:`\hex{F5}` -(reserved) :math:`\hex{F6}` -(reserved) :math:`\hex{F7}` -(reserved) :math:`\hex{F8}` -(reserved) :math:`\hex{F9}` -(reserved) :math:`\hex{FA}` -(reserved) :math:`\hex{FB}` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{00}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{01}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{02}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{03}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{04}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{05}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{06}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{07}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\MEMORYINIT~x~y` :math:`\hex{FC}~\hex{08}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\DATADROP~x` :math:`\hex{FC}~\hex{09}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYCOPY~x~y` :math:`\hex{FC}~\hex{0A}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYFILL~y` :math:`\hex{FC}~\hex{0B}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEINIT~x~y` :math:`\hex{FC}~\hex{0C}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\ELEMDROP~x` :math:`\hex{FC}~\hex{0D}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLECOPY~x~y` :math:`\hex{FC}~\hex{0E}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEGROW~x` :math:`\hex{FC}~\hex{0F}` :math:`[t~\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\TABLESIZE~x` :math:`\hex{FC}~\hex{10}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\TABLEFILL~x` :math:`\hex{FC}~\hex{11}` :math:`[\I32~t~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~~0` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~~1` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~~2` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~~3` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~~4` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~~5` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat}\_\F64\K{\_s}` :math:`\hex{FC}~~6` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~~7` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\LOAD~x~\memarg` :math:`\hex{FD}~~\hex{00}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\LOAD\K{8x8\_s}~x~\memarg` :math:`\hex{FD}~~\hex{01}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\LOAD\K{8x8\_u}~x~\memarg` :math:`\hex{FD}~~\hex{02}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\LOAD\K{16x4\_s}~x~\memarg` :math:`\hex{FD}~~\hex{03}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\LOAD\K{16x4\_u}~x~\memarg` :math:`\hex{FD}~~\hex{04}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\LOAD\K{32x2\_s}~x~\memarg` :math:`\hex{FD}~~\hex{05}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\LOAD\K{32x2\_u}~x~\memarg` :math:`\hex{FD}~~\hex{06}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\LOAD\K{\_splat}~x~\memarg` :math:`\hex{FD}~~\hex{07}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\LOAD\K{\_splat}~x~\memarg` :math:`\hex{FD}~~\hex{08}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\LOAD\K{\_splat}~x~\memarg` :math:`\hex{FD}~~\hex{09}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\LOAD\K{\_splat}~x~\memarg` :math:`\hex{FD}~~\hex{0A}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE~x~\memarg` :math:`\hex{FD}~~\hex{0B}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\VCONST~\i128` :math:`\hex{FD}~~\hex{0C}` :math:`[] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SHUFFLE~\laneidx^{16}` :math:`\hex{FD}~~\hex{0D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SWIZZLE` :math:`\hex{FD}~~\hex{0E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SPLAT` :math:`\hex{FD}~~\hex{0F}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\SPLAT` :math:`\hex{FD}~~\hex{10}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\SPLAT` :math:`\hex{FD}~~\hex{11}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\SPLAT` :math:`\hex{FD}~~\hex{12}` :math:`[\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\SPLAT` :math:`\hex{FD}~~\hex{13}` :math:`[\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\SPLAT` :math:`\hex{FD}~~\hex{14}` :math:`[\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{15}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{16}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{17}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{18}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{19}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1A}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1B}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1D}` :math:`[\V128] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1E}` :math:`[\V128~\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1F}` :math:`[\V128] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{20}` :math:`[\V128~\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{21}` :math:`[\V128] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{22}` :math:`[\V128~\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\VEQ` :math:`\hex{FD}~~\hex{23}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VNE` :math:`\hex{FD}~~\hex{24}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{25}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{26}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{27}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{28}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{29}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{2A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{2B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{2C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VEQ` :math:`\hex{FD}~~\hex{2D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VNE` :math:`\hex{FD}~~\hex{2E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{2F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{30}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{31}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{32}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{33}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{34}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{35}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{36}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VEQ` :math:`\hex{FD}~~\hex{37}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VNE` :math:`\hex{FD}~~\hex{38}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{39}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{3A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{3B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{3C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{3D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{3E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{3F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{40}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VEQ` :math:`\hex{FD}~~\hex{41}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNE` :math:`\hex{FD}~~\hex{42}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VLT` :math:`\hex{FD}~~\hex{43}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VGT` :math:`\hex{FD}~~\hex{44}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VLE` :math:`\hex{FD}~~\hex{45}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VGE` :math:`\hex{FD}~~\hex{46}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VEQ` :math:`\hex{FD}~~\hex{47}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNE` :math:`\hex{FD}~~\hex{48}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VLT` :math:`\hex{FD}~~\hex{49}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VGT` :math:`\hex{FD}~~\hex{4A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VLE` :math:`\hex{FD}~~\hex{4B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VGE` :math:`\hex{FD}~~\hex{4C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VNOT` :math:`\hex{FD}~~\hex{4D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VAND` :math:`\hex{FD}~~\hex{4E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VANDNOT` :math:`\hex{FD}~~\hex{4F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VOR` :math:`\hex{FD}~~\hex{50}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VXOR` :math:`\hex{FD}~~\hex{51}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\BITSELECT` :math:`\hex{FD}~~\hex{52}` :math:`[\V128~\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\ANYTRUE` :math:`\hex{FD}~~\hex{53}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{54}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{55}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{56}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{57}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{58}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{59}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5A}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5B}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5C}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{64\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5D}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VDEMOTE\K{\_f64x2\_zero}` :math:`\hex{FD}~~\hex{5E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPROMOTE\K{\_low\_f32x4}` :math:`\hex{FD}~~\hex{5F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VABS` :math:`\hex{FD}~~\hex{60}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VNEG` :math:`\hex{FD}~~\hex{61}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VPOPCNT` :math:`\hex{FD}~~\hex{62}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\ALLTRUE` :math:`\hex{FD}~~\hex{63}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\BITMASK` :math:`\hex{FD}~~\hex{64}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\NARROW\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{65}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\NARROW\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{66}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VCEIL` :math:`\hex{FD}~~\hex{67}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VFLOOR` :math:`\hex{FD}~~\hex{68}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VTRUNC` :math:`\hex{FD}~~\hex{69}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNEAREST` :math:`\hex{FD}~~\hex{6A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHL` :math:`\hex{FD}~~\hex{6B}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{6C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{6D}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD` :math:`\hex{FD}~~\hex{6E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{6F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{70}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB` :math:`\hex{FD}~~\hex{71}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{72}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{73}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCEIL` :math:`\hex{FD}~~\hex{74}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VFLOOR` :math:`\hex{FD}~~\hex{75}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{76}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{77}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{78}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{79}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VTRUNC` :math:`\hex{FD}~~\hex{7A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{7B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_s}` :math:`\hex{FD}~~\hex{7C}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_u}` :math:`\hex{FD}~~\hex{7D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{7E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{7F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VABS` :math:`\hex{FD}~~\hex{80}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VNEG` :math:`\hex{FD}~~\hex{81}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\Q15MULRSAT\K{\_s}` :math:`\hex{FD}~~\hex{82}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\ALLTRUE` :math:`\hex{FD}~~\hex{83}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\BITMASK` :math:`\hex{FD}~~\hex{84}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\NARROW\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{85}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\NARROW\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{86}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{87}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{88}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{89}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{8A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VSHL` :math:`\hex{FD}~~\hex{8B}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{8C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{8D}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD` :math:`\hex{FD}~~\hex{8E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{8F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{90}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB` :math:`\hex{FD}~~\hex{91}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{92}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{93}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNEAREST` :math:`\hex{FD}~~\hex{94}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMUL` :math:`\hex{FD}~~\hex{95}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{96}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{97}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{98}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{99}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{9B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{9C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{9D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{9E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{9F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VABS` :math:`\hex{FD}~~\hex{A0}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VNEG` :math:`\hex{FD}~~\hex{A1}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\ALLTRUE` :math:`\hex{FD}~~\hex{A3}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\BITMASK` :math:`\hex{FD}~~\hex{A4}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{A7}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{A8}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{A9}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{AA}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VSHL` :math:`\hex{FD}~~\hex{AB}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{AC}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{AD}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VADD` :math:`\hex{FD}~~\hex{AE}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSUB` :math:`\hex{FD}~~\hex{B1}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMUL` :math:`\hex{FD}~~\hex{B5}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{B6}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{B7}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{B8}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{B9}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\DOT\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{BA}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{BC}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{BD}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{BE}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{BF}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VABS` :math:`\hex{FD}~~\hex{C0}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VNEG` :math:`\hex{FD}~~\hex{C1}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\ALLTRUE` :math:`\hex{FD}~~\hex{C3}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\BITMASK` :math:`\hex{FD}~~\hex{C4}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{C7}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{C8}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{C9}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{CA}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VSHL` :math:`\hex{FD}~~\hex{CB}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{CC}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{CD}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VADD` :math:`\hex{FD}~~\hex{CE}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSUB` :math:`\hex{FD}~~\hex{D1}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VMUL` :math:`\hex{FD}~~\hex{D5}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VEQ` :math:`\hex{FD}~~\hex{D6}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VNE` :math:`\hex{FD}~~\hex{D7}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{D8}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{D9}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{DA}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{DB}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{DC}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{DD}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{DE}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{DF}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VABS` :math:`\hex{FD}~~\hex{E0}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNEG` :math:`\hex{FD}~~\hex{E1}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VSQRT` :math:`\hex{FD}~~\hex{E3}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VADD` :math:`\hex{FD}~~\hex{E4}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VSUB` :math:`\hex{FD}~~\hex{E5}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMUL` :math:`\hex{FD}~~\hex{E6}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VDIV` :math:`\hex{FD}~~\hex{E7}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMIN` :math:`\hex{FD}~~\hex{E8}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMAX` :math:`\hex{FD}~~\hex{E9}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VPMIN` :math:`\hex{FD}~~\hex{EA}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VPMAX` :math:`\hex{FD}~~\hex{EB}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VABS` :math:`\hex{FD}~~\hex{EC}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNEG` :math:`\hex{FD}~~\hex{ED}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VSQRT` :math:`\hex{FD}~~\hex{EF}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VADD` :math:`\hex{FD}~~\hex{F0}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VSUB` :math:`\hex{FD}~~\hex{F1}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMUL` :math:`\hex{FD}~~\hex{F2}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VDIV` :math:`\hex{FD}~~\hex{F3}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMIN` :math:`\hex{FD}~~\hex{F4}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMAX` :math:`\hex{FD}~~\hex{F5}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPMIN` :math:`\hex{FD}~~\hex{F6}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPMAX` :math:`\hex{FD}~~\hex{F7}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_s}` :math:`\hex{FD}~~\hex{F8}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_u}` :math:`\hex{FD}~~\hex{F9}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VCONVERT\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{FA}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VCONVERT\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{FB}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_s\_zero}` :math:`\hex{FD}~~\hex{FC}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_u\_zero}` :math:`\hex{FD}~~\hex{FD}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{FE}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{FF}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -================================================= ========================== ============================================= ============================================= ================================================================== +================================================= ==================================== ============================================= ============================================= ================================================================== +Instruction Binary Opcode Type Validation Execution +================================================= ==================================== ============================================= ============================================= ================================================================== +:math:`\UNREACHABLE` :math:`\hex{00}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\NOP` :math:`\hex{01}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` +:math:`\BLOCK~\X{bt}` :math:`\hex{02}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\LOOP~\X{bt}` :math:`\hex{03}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\IF~\X{bt}` :math:`\hex{04}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\ELSE` :math:`\hex{05}` +(reserved) :math:`\hex{06}` +(reserved) :math:`\hex{07}` +(reserved) :math:`\hex{08}` +(reserved) :math:`\hex{09}` +(reserved) :math:`\hex{0A}` +:math:`\END` :math:`\hex{0B}` +:math:`\BR~l` :math:`\hex{0C}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\BRIF~l` :math:`\hex{0D}` :math:`[t^\ast~\I32] \to [t^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\BRTABLE~l^\ast~l` :math:`\hex{0E}` :math:`[t_1^\ast~t^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\RETURN` :math:`\hex{0F}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\CALL~x` :math:`\hex{10}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +:math:`\CALLINDIRECT~x~y` :math:`\hex{11}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` +(reserved) :math:`\hex{12}` +(reserved) :math:`\hex{13}` +(reserved) :math:`\hex{14}` +(reserved) :math:`\hex{15}` +(reserved) :math:`\hex{16}` +(reserved) :math:`\hex{17}` +(reserved) :math:`\hex{18}` +(reserved) :math:`\hex{19}` +:math:`\DROP` :math:`\hex{1A}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` +:math:`\SELECT` :math:`\hex{1B}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\SELECT~t` :math:`\hex{1C}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` +(reserved) :math:`\hex{1D}` +(reserved) :math:`\hex{1E}` +(reserved) :math:`\hex{1F}` +:math:`\LOCALGET~x` :math:`\hex{20}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\LOCALSET~x` :math:`\hex{21}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` +:math:`\LOCALTEE~x` :math:`\hex{22}` :math:`[t] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\GLOBALGET~x` :math:`\hex{23}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\GLOBALSET~x` :math:`\hex{24}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` +:math:`\TABLEGET~x` :math:`\hex{25}` :math:`[\I32] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\TABLESET~x` :math:`\hex{26}` :math:`[\I32~t] \to []` :ref:`validation ` :ref:`execution ` +(reserved) :math:`\hex{27}` +:math:`\I32.\LOAD~\memarg` :math:`\hex{28}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD~\memarg` :math:`\hex{29}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\F32.\LOAD~\memarg` :math:`\hex{2A}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution ` +:math:`\F64.\LOAD~\memarg` :math:`\hex{2B}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\LOAD\K{8\_s}~\memarg` :math:`\hex{2C}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\LOAD\K{8\_u}~\memarg` :math:`\hex{2D}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\LOAD\K{16\_s}~\memarg` :math:`\hex{2E}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\LOAD\K{16\_u}~\memarg` :math:`\hex{2F}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{8\_s}~\memarg` :math:`\hex{30}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{8\_u}~\memarg` :math:`\hex{31}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{16\_s}~\memarg` :math:`\hex{32}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{16\_u}~\memarg` :math:`\hex{33}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{32\_s}~\memarg` :math:`\hex{34}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\LOAD\K{32\_u}~\memarg` :math:`\hex{35}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\STORE~\memarg` :math:`\hex{36}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I64.\STORE~\memarg` :math:`\hex{37}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` +:math:`\F32.\STORE~\memarg` :math:`\hex{38}` :math:`[\I32~\F32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\F64.\STORE~\memarg` :math:`\hex{39}` :math:`[\I32~\F64] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I32.\STORE\K{8}~\memarg` :math:`\hex{3A}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I32.\STORE\K{16}~\memarg` :math:`\hex{3B}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I64.\STORE\K{8}~\memarg` :math:`\hex{3C}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I64.\STORE\K{16}~\memarg` :math:`\hex{3D}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` +:math:`\I64.\STORE\K{32}~\memarg` :math:`\hex{3E}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` +:math:`\MEMORYSIZE` :math:`\hex{3F}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\MEMORYGROW` :math:`\hex{40}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\CONST~\i32` :math:`\hex{41}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I64.\CONST~\i64` :math:`\hex{42}` :math:`[] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\F32.\CONST~\f32` :math:`\hex{43}` :math:`[] \to [\F32]` :ref:`validation ` :ref:`execution ` +:math:`\F64.\CONST~\f64` :math:`\hex{44}` :math:`[] \to [\F64]` :ref:`validation ` :ref:`execution ` +:math:`\I32.\EQZ` :math:`\hex{45}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\EQ` :math:`\hex{46}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\NE` :math:`\hex{47}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\LT\K{\_s}` :math:`\hex{48}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\LT\K{\_u}` :math:`\hex{49}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\GT\K{\_s}` :math:`\hex{4A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\GT\K{\_u}` :math:`\hex{4B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\LE\K{\_s}` :math:`\hex{4C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\LE\K{\_u}` :math:`\hex{4D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\GE\K{\_s}` :math:`\hex{4E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\GE\K{\_u}` :math:`\hex{4F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EQZ` :math:`\hex{50}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EQ` :math:`\hex{51}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\NE` :math:`\hex{52}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\LT\K{\_s}` :math:`\hex{53}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\LT\K{\_u}` :math:`\hex{54}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\GT\K{\_s}` :math:`\hex{55}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\GT\K{\_u}` :math:`\hex{56}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\LE\K{\_s}` :math:`\hex{57}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\LE\K{\_u}` :math:`\hex{58}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\GE\K{\_s}` :math:`\hex{59}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\GE\K{\_u}` :math:`\hex{5A}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\EQ` :math:`\hex{5B}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\NE` :math:`\hex{5C}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\LT` :math:`\hex{5D}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\GT` :math:`\hex{5E}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\LE` :math:`\hex{5F}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\GE` :math:`\hex{60}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\EQ` :math:`\hex{61}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\NE` :math:`\hex{62}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\LT` :math:`\hex{63}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\GT` :math:`\hex{64}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\LE` :math:`\hex{65}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\GE` :math:`\hex{66}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\CLZ` :math:`\hex{67}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\CTZ` :math:`\hex{68}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\POPCNT` :math:`\hex{69}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\ADD` :math:`\hex{6A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\SUB` :math:`\hex{6B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\MUL` :math:`\hex{6C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\DIV\K{\_s}` :math:`\hex{6D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\DIV\K{\_u}` :math:`\hex{6E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\REM\K{\_s}` :math:`\hex{6F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\REM\K{\_u}` :math:`\hex{70}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\AND` :math:`\hex{71}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\OR` :math:`\hex{72}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\XOR` :math:`\hex{73}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\SHL` :math:`\hex{74}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\SHR\K{\_s}` :math:`\hex{75}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\SHR\K{\_u}` :math:`\hex{76}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\ROTL` :math:`\hex{77}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\ROTR` :math:`\hex{78}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\CLZ` :math:`\hex{79}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\CTZ` :math:`\hex{7A}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\POPCNT` :math:`\hex{7B}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\ADD` :math:`\hex{7C}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\SUB` :math:`\hex{7D}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\MUL` :math:`\hex{7E}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\DIV\K{\_s}` :math:`\hex{7F}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\DIV\K{\_u}` :math:`\hex{80}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\REM\K{\_s}` :math:`\hex{81}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\REM\K{\_u}` :math:`\hex{82}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\AND` :math:`\hex{83}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\OR` :math:`\hex{84}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\XOR` :math:`\hex{85}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\SHL` :math:`\hex{86}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\SHR\K{\_s}` :math:`\hex{87}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\SHR\K{\_u}` :math:`\hex{88}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\ROTL` :math:`\hex{89}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\ROTR` :math:`\hex{8A}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\ABS` :math:`\hex{8B}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\NEG` :math:`\hex{8C}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\CEIL` :math:`\hex{8D}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\FLOOR` :math:`\hex{8E}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\TRUNC` :math:`\hex{8F}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\NEAREST` :math:`\hex{90}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\SQRT` :math:`\hex{91}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\ADD` :math:`\hex{92}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\SUB` :math:`\hex{93}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\MUL` :math:`\hex{94}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\DIV` :math:`\hex{95}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\FMIN` :math:`\hex{96}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\FMAX` :math:`\hex{97}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\COPYSIGN` :math:`\hex{98}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\ABS` :math:`\hex{99}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\NEG` :math:`\hex{9A}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\CEIL` :math:`\hex{9B}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\FLOOR` :math:`\hex{9C}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\TRUNC` :math:`\hex{9D}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\NEAREST` :math:`\hex{9E}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\SQRT` :math:`\hex{9F}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\ADD` :math:`\hex{A0}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\SUB` :math:`\hex{A1}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\MUL` :math:`\hex{A2}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\DIV` :math:`\hex{A3}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\FMIN` :math:`\hex{A4}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\FMAX` :math:`\hex{A5}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\COPYSIGN` :math:`\hex{A6}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\WRAP\K{\_}\I64` :math:`\hex{A7}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{A8}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{A9}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{AA}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{AB}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EXTEND\K{\_}\I32\K{\_s}` :math:`\hex{AC}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EXTEND\K{\_}\I32\K{\_u}` :math:`\hex{AD}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{AE}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{AF}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{B0}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{B1}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B2}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B3}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B4}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{B5}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\DEMOTE\K{\_}\F64` :math:`\hex{B6}` :math:`[\F64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B7}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B8}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B9}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{BA}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\PROMOTE\K{\_}\F32` :math:`\hex{BB}` :math:`[\F32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\REINTERPRET\K{\_}\F32` :math:`\hex{BC}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\REINTERPRET\K{\_}\F64` :math:`\hex{BD}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32.\REINTERPRET\K{\_}\I32` :math:`\hex{BE}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64.\REINTERPRET\K{\_}\I64` :math:`\hex{BF}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\EXTEND\K{8\_s}` :math:`\hex{C0}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\EXTEND\K{16\_s}` :math:`\hex{C1}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EXTEND\K{8\_s}` :math:`\hex{C2}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EXTEND\K{16\_s}` :math:`\hex{C3}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\EXTEND\K{32\_s}` :math:`\hex{C4}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +(reserved) :math:`\hex{C5}` +(reserved) :math:`\hex{C6}` +(reserved) :math:`\hex{C7}` +(reserved) :math:`\hex{C8}` +(reserved) :math:`\hex{C9}` +(reserved) :math:`\hex{CA}` +(reserved) :math:`\hex{CB}` +(reserved) :math:`\hex{CC}` +(reserved) :math:`\hex{CD}` +(reserved) :math:`\hex{CE}` +(reserved) :math:`\hex{CF}` +:math:`\REFNULL~t` :math:`\hex{D0}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` +:math:`\REFISNULL` :math:`\hex{D1}` :math:`[t] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\REFFUNC~x` :math:`\hex{D2}` :math:`[] \to [\FUNCREF]` :ref:`validation ` :ref:`execution ` +(reserved) :math:`\hex{D3}` +(reserved) :math:`\hex{D4}` +(reserved) :math:`\hex{D5}` +(reserved) :math:`\hex{D6}` +(reserved) :math:`\hex{D7}` +(reserved) :math:`\hex{D8}` +(reserved) :math:`\hex{D9}` +(reserved) :math:`\hex{DA}` +(reserved) :math:`\hex{DB}` +(reserved) :math:`\hex{DC}` +(reserved) :math:`\hex{DD}` +(reserved) :math:`\hex{DE}` +(reserved) :math:`\hex{DF}` +(reserved) :math:`\hex{E0}` +(reserved) :math:`\hex{E1}` +(reserved) :math:`\hex{E2}` +(reserved) :math:`\hex{E3}` +(reserved) :math:`\hex{E4}` +(reserved) :math:`\hex{E5}` +(reserved) :math:`\hex{E6}` +(reserved) :math:`\hex{E7}` +(reserved) :math:`\hex{E8}` +(reserved) :math:`\hex{E9}` +(reserved) :math:`\hex{EA}` +(reserved) :math:`\hex{EB}` +(reserved) :math:`\hex{EC}` +(reserved) :math:`\hex{ED}` +(reserved) :math:`\hex{EE}` +(reserved) :math:`\hex{EF}` +(reserved) :math:`\hex{F0}` +(reserved) :math:`\hex{F1}` +(reserved) :math:`\hex{F2}` +(reserved) :math:`\hex{F3}` +(reserved) :math:`\hex{F4}` +(reserved) :math:`\hex{F5}` +(reserved) :math:`\hex{F6}` +(reserved) :math:`\hex{F7}` +(reserved) :math:`\hex{F8}` +(reserved) :math:`\hex{F9}` +(reserved) :math:`\hex{FA}` +(reserved) :math:`\hex{FB}` +:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{00}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{01}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{02}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{03}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{04}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{05}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{06}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{07}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\MEMORYINIT~x` :math:`\hex{FC}~\hex{08}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\DATADROP~x` :math:`\hex{FC}~\hex{09}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` +:math:`\MEMORYCOPY` :math:`\hex{FC}~\hex{0A}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\MEMORYFILL` :math:`\hex{FC}~\hex{0B}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\TABLEINIT~x~y` :math:`\hex{FC}~\hex{0C}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\ELEMDROP~x` :math:`\hex{FC}~\hex{0D}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` +:math:`\TABLECOPY~x~y` :math:`\hex{FC}~\hex{0E}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\TABLEGROW~x` :math:`\hex{FC}~\hex{0F}` :math:`[t~\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\TABLESIZE~x` :math:`\hex{FC}~\hex{10}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\TABLEFILL~x` :math:`\hex{FC}~\hex{11}` :math:`[\I32~t~\I32] \to []` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD~\memarg` :math:`\hex{FD}~~\hex{00}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{8x8\_s}~\memarg` :math:`\hex{FD}~~\hex{01}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{8x8\_u}~\memarg` :math:`\hex{FD}~~\hex{02}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{16x4\_s}~\memarg` :math:`\hex{FD}~~\hex{03}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{16x4\_u}~\memarg` :math:`\hex{FD}~~\hex{04}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{32x2\_s}~\memarg` :math:`\hex{FD}~~\hex{05}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{32x2\_u}~\memarg` :math:`\hex{FD}~~\hex{06}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{07}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{08}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{09}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{0A}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\STORE~\memarg` :math:`\hex{FD}~~\hex{0B}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` +:math:`\V128.\VCONST~\i128` :math:`\hex{FD}~~\hex{0C}` :math:`[] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\SHUFFLE~\laneidx^{16}` :math:`\hex{FD}~~\hex{0D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\SWIZZLE` :math:`\hex{FD}~~\hex{0E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\SPLAT` :math:`\hex{FD}~~\hex{0F}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\SPLAT` :math:`\hex{FD}~~\hex{10}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\SPLAT` :math:`\hex{FD}~~\hex{11}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\SPLAT` :math:`\hex{FD}~~\hex{12}` :math:`[\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\SPLAT` :math:`\hex{FD}~~\hex{13}` :math:`[\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F64X2.\SPLAT` :math:`\hex{FD}~~\hex{14}` :math:`[\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{15}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{16}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{17}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{18}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{19}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1A}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1B}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1D}` :math:`[\V128] \to [\I64]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1E}` :math:`[\V128~\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1F}` :math:`[\V128] \to [\F32]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{20}` :math:`[\V128~\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{21}` :math:`[\V128] \to [\F64]` :ref:`validation ` :ref:`execution ` +:math:`\F64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{22}` :math:`[\V128~\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\VEQ` :math:`\hex{FD}~~\hex{23}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VNE` :math:`\hex{FD}~~\hex{24}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{25}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{26}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{27}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{28}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{29}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{2A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{2B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{2C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VEQ` :math:`\hex{FD}~~\hex{2D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VNE` :math:`\hex{FD}~~\hex{2E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{2F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{30}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{31}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{32}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{33}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{34}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{35}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{36}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VEQ` :math:`\hex{FD}~~\hex{37}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VNE` :math:`\hex{FD}~~\hex{38}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{39}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{3A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{3B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{3C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{3D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{3E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{3F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{40}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VEQ` :math:`\hex{FD}~~\hex{41}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VNE` :math:`\hex{FD}~~\hex{42}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VLT` :math:`\hex{FD}~~\hex{43}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VGT` :math:`\hex{FD}~~\hex{44}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VLE` :math:`\hex{FD}~~\hex{45}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VGE` :math:`\hex{FD}~~\hex{46}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VEQ` :math:`\hex{FD}~~\hex{47}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VNE` :math:`\hex{FD}~~\hex{48}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VLT` :math:`\hex{FD}~~\hex{49}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VGT` :math:`\hex{FD}~~\hex{4A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VLE` :math:`\hex{FD}~~\hex{4B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VGE` :math:`\hex{FD}~~\hex{4C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\VNOT` :math:`\hex{FD}~~\hex{4D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\VAND` :math:`\hex{FD}~~\hex{4E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\VANDNOT` :math:`\hex{FD}~~\hex{4F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\VOR` :math:`\hex{FD}~~\hex{50}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\VXOR` :math:`\hex{FD}~~\hex{51}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\BITSELECT` :math:`\hex{FD}~~\hex{52}` :math:`[\V128~\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\V128.\ANYTRUE` :math:`\hex{FD}~~\hex{53}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{54}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{55}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{56}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{57}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\STORE\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{58}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\STORE\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{59}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\STORE\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5A}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\STORE\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5B}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{32\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5C}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{64\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5D}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\VDEMOTE\K{\_f64x2\_zero}` :math:`\hex{FD}~~\hex{5E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VPROMOTE\K{\_low\_f32x4}` :math:`\hex{FD}~~\hex{5F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VABS` :math:`\hex{FD}~~\hex{60}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VNEG` :math:`\hex{FD}~~\hex{61}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VPOPCNT` :math:`\hex{FD}~~\hex{62}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\ALLTRUE` :math:`\hex{FD}~~\hex{63}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\BITMASK` :math:`\hex{FD}~~\hex{64}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\NARROW\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{65}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I8X16.\NARROW\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{66}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\VCEIL` :math:`\hex{FD}~~\hex{67}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VFLOOR` :math:`\hex{FD}~~\hex{68}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VTRUNC` :math:`\hex{FD}~~\hex{69}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VNEAREST` :math:`\hex{FD}~~\hex{6A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSHL` :math:`\hex{FD}~~\hex{6B}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{6C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{6D}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VADD` :math:`\hex{FD}~~\hex{6E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{6F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{70}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSUB` :math:`\hex{FD}~~\hex{71}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{72}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{73}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VCEIL` :math:`\hex{FD}~~\hex{74}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VFLOOR` :math:`\hex{FD}~~\hex{75}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{76}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{77}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{78}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{79}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VTRUNC` :math:`\hex{FD}~~\hex{7A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I8X16.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{7B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_s}` :math:`\hex{FD}~~\hex{7C}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_u}` :math:`\hex{FD}~~\hex{7D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{7E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{7F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VABS` :math:`\hex{FD}~~\hex{80}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VNEG` :math:`\hex{FD}~~\hex{81}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\Q15MULRSAT\K{\_s}` :math:`\hex{FD}~~\hex{82}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\ALLTRUE` :math:`\hex{FD}~~\hex{83}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\BITMASK` :math:`\hex{FD}~~\hex{84}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\NARROW\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{85}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\NARROW\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{86}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{87}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{88}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{89}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{8A}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\VSHL` :math:`\hex{FD}~~\hex{8B}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{8C}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{8D}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VADD` :math:`\hex{FD}~~\hex{8E}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{8F}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{90}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VSUB` :math:`\hex{FD}~~\hex{91}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{92}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{93}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VNEAREST` :math:`\hex{FD}~~\hex{94}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VMUL` :math:`\hex{FD}~~\hex{95}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{96}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{97}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{98}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{99}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{9B}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{9C}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{9D}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{9E}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{9F}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VABS` :math:`\hex{FD}~~\hex{A0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VNEG` :math:`\hex{FD}~~\hex{A1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\ALLTRUE` :math:`\hex{FD}~~\hex{A3}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\BITMASK` :math:`\hex{FD}~~\hex{A4}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{A7}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{A8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{A9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{AA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\VSHL` :math:`\hex{FD}~~\hex{AB}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{AC}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{AD}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VADD` :math:`\hex{FD}~~\hex{AE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VSUB` :math:`\hex{FD}~~\hex{B1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VMUL` :math:`\hex{FD}~~\hex{B5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{B6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{B7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{B8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{B9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\DOT\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{BA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{BC}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{BD}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{BE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{BF}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VABS` :math:`\hex{FD}~~\hex{C0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VNEG` :math:`\hex{FD}~~\hex{C1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\ALLTRUE` :math:`\hex{FD}~~\hex{C3}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\BITMASK` :math:`\hex{FD}~~\hex{C4}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{C7}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{C8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{C9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{CA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\VSHL` :math:`\hex{FD}~~\hex{CB}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{CC}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{CD}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VADD` :math:`\hex{FD}~~\hex{CE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VSUB` :math:`\hex{FD}~~\hex{D1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VMUL` :math:`\hex{FD}~~\hex{D5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VEQ` :math:`\hex{FD}~~\hex{D6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VNE` :math:`\hex{FD}~~\hex{D7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{D8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{D9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{DA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{DB}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{DC}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{DD}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{DE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{DF}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\F32X4.\VABS` :math:`\hex{FD}~~\hex{E0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VNEG` :math:`\hex{FD}~~\hex{E1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VSQRT` :math:`\hex{FD}~~\hex{E3}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VADD` :math:`\hex{FD}~~\hex{E4}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VSUB` :math:`\hex{FD}~~\hex{E5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VMUL` :math:`\hex{FD}~~\hex{E6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VDIV` :math:`\hex{FD}~~\hex{E7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VMIN` :math:`\hex{FD}~~\hex{E8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VMAX` :math:`\hex{FD}~~\hex{E9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VPMIN` :math:`\hex{FD}~~\hex{EA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VPMAX` :math:`\hex{FD}~~\hex{EB}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VABS` :math:`\hex{FD}~~\hex{EC}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VNEG` :math:`\hex{FD}~~\hex{ED}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VSQRT` :math:`\hex{FD}~~\hex{EF}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VADD` :math:`\hex{FD}~~\hex{F0}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VSUB` :math:`\hex{FD}~~\hex{F1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VMUL` :math:`\hex{FD}~~\hex{F2}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VDIV` :math:`\hex{FD}~~\hex{F3}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VMIN` :math:`\hex{FD}~~\hex{F4}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VMAX` :math:`\hex{FD}~~\hex{F5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VPMIN` :math:`\hex{FD}~~\hex{F6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VPMAX` :math:`\hex{FD}~~\hex{F7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_s}` :math:`\hex{FD}~~\hex{F8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_u}` :math:`\hex{FD}~~\hex{F9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VCONVERT\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{FA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F32X4.\VCONVERT\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{FB}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_s\_zero}` :math:`\hex{FD}~~\hex{FC}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_u\_zero}` :math:`\hex{FD}~~\hex{FD}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{FE}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{FF}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` +================================================= ==================================== ============================================= ============================================= ================================================================== From 53e55751ba1ddf2c83819a1e0d4dafd57cb0865d Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Tue, 17 May 2022 08:24:00 +0100 Subject: [PATCH 081/181] [spec] Fix v128.loadX_splat in instruction index (#1477) --- document/core/appendix/gen-index-instructions.py | 8 -------- document/core/appendix/index-instructions.rst | 8 ++++---- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/document/core/appendix/gen-index-instructions.py b/document/core/appendix/gen-index-instructions.py index 4ab7b64d4..d9e6753c4 100755 --- a/document/core/appendix/gen-index-instructions.py +++ b/document/core/appendix/gen-index-instructions.py @@ -331,14 +331,6 @@ def Instruction(name, opcode, type=None, validation=None, execution=None, operat Instruction(r'\TABLEGROW~x', r'\hex{FC}~\hex{0F}', r'[t~\I32] \to [\I32]', r'valid-table.grow', r'exec-table.grow'), Instruction(r'\TABLESIZE~x', r'\hex{FC}~\hex{10}', r'[] \to [\I32]', r'valid-table.size', r'exec-table.size'), Instruction(r'\TABLEFILL~x', r'\hex{FC}~\hex{11}', r'[\I32~t~\I32] \to []', r'valid-table.fill', r'exec-table.fill'), - Instruction(r'\I32.\TRUNC\K{\_sat\_}\F32\K{\_s}', r'\hex{FC}~~0', r'[\F32] \to [\I32]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_s'), - Instruction(r'\I32.\TRUNC\K{\_sat\_}\F32\K{\_u}', r'\hex{FC}~~1', r'[\F32] \to [\I32]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_u'), - Instruction(r'\I32.\TRUNC\K{\_sat\_}\F64\K{\_s}', r'\hex{FC}~~2', r'[\F64] \to [\I32]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_s'), - Instruction(r'\I32.\TRUNC\K{\_sat\_}\F64\K{\_u}', r'\hex{FC}~~3', r'[\F64] \to [\I32]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_u'), - Instruction(r'\I64.\TRUNC\K{\_sat\_}\F32\K{\_s}', r'\hex{FC}~~4', r'[\F32] \to [\I64]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_s'), - Instruction(r'\I64.\TRUNC\K{\_sat\_}\F32\K{\_u}', r'\hex{FC}~~5', r'[\F32] \to [\I64]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_u'), - Instruction(r'\I64.\TRUNC\K{\_sat}\_\F64\K{\_s}', r'\hex{FC}~~6', r'[\F64] \to [\I64]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_s'), - Instruction(r'\I64.\TRUNC\K{\_sat\_}\F64\K{\_u}', r'\hex{FC}~~7', r'[\F64] \to [\I64]', r'valid-cvtop', r'exec-cvtop', r'op-trunc_sat_u'), Instruction(r'\V128.\LOAD~x~\memarg', r'\hex{FD}~~\hex{00}', r'[\I32] \to [\V128]', r'valid-load', r'exec-load'), Instruction(r'\I16X8.\LOAD\K{8x8\_s}~x~\memarg', r'\hex{FD}~~\hex{01}', r'[\I32] \to [\V128]', r'valid-load-extend', r'exec-load-extend'), Instruction(r'\I16X8.\LOAD\K{8x8\_u}~x~\memarg', r'\hex{FD}~~\hex{02}', r'[\I32] \to [\V128]', r'valid-load-extend', r'exec-load-extend'), diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst index a82fa9a62..0636a4266 100644 --- a/document/core/appendix/index-instructions.rst +++ b/document/core/appendix/index-instructions.rst @@ -286,10 +286,10 @@ Instruction Binary Opcode :math:`\V128.\LOAD\K{16x4\_u}~\memarg` :math:`\hex{FD}~~\hex{04}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` :math:`\V128.\LOAD\K{32x2\_s}~\memarg` :math:`\hex{FD}~~\hex{05}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` :math:`\V128.\LOAD\K{32x2\_u}~\memarg` :math:`\hex{FD}~~\hex{06}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{07}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{08}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{09}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{\_splat}~\memarg` :math:`\hex{FD}~~\hex{0A}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{8\_splat}~\memarg` :math:`\hex{FD}~~\hex{07}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{16\_splat}~\memarg` :math:`\hex{FD}~~\hex{08}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{32\_splat}~\memarg` :math:`\hex{FD}~~\hex{09}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` +:math:`\V128.\LOAD\K{64\_splat}~\memarg` :math:`\hex{FD}~~\hex{0A}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` :math:`\V128.\STORE~\memarg` :math:`\hex{FD}~~\hex{0B}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` :math:`\V128.\VCONST~\i128` :math:`\hex{FD}~~\hex{0C}` :math:`[] \to [\V128]` :ref:`validation ` :ref:`execution ` :math:`\I8X16.\SHUFFLE~\laneidx^{16}` :math:`\hex{FD}~~\hex{0D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` From 14f194b25cebc03491697b4807e993814cb5e29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Kr=C3=BCger?= Date: Tue, 17 May 2022 15:58:39 +0100 Subject: [PATCH 082/181] [interpreter] Dune test suite (#1478) --- interpreter/dune-project => dune-project | 0 interpreter/Makefile | 9 ++++++-- interpreter/dune | 27 ++++++++++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) rename interpreter/dune-project => dune-project (100%) diff --git a/interpreter/dune-project b/dune-project similarity index 100% rename from interpreter/dune-project rename to dune-project diff --git a/interpreter/Makefile b/interpreter/Makefile index 4ff333d17..78fce53d8 100644 --- a/interpreter/Makefile +++ b/interpreter/Makefile @@ -27,7 +27,7 @@ JS = # set to JS shell command to run JS tests # Main targets -.PHONY: default opt unopt libopt libunopt jslib all land zip smallint +.PHONY: default opt unopt libopt libunopt jslib all land zip smallint dunebuild default: opt debug: unopt @@ -41,6 +41,8 @@ land: $(WINMAKE) all zip: $(ZIP) smallint: smallint.native +dunebuild: + dune build # Building executable @@ -136,7 +138,7 @@ TESTDIR = ../test/core TESTFILES = $(shell cd $(TESTDIR); ls *.wast; ls [a-z]*/*.wast) TESTS = $(TESTFILES:%.wast=%) -.PHONY: test debugtest partest +.PHONY: test debugtest partest dune-test test: $(OPT) smallint $(TESTDIR)/run.py --wasm `pwd`/$(OPT) $(if $(JS),--js '$(JS)',) @@ -168,6 +170,9 @@ quiettest/%: $(OPT) smallinttest: smallint @./smallint.native +dunetest: + dune test + # Miscellaneous targets .PHONY: clean diff --git a/interpreter/dune b/interpreter/dune index 2b5cd3572..6f6dfff3e 100644 --- a/interpreter/dune +++ b/interpreter/dune @@ -3,10 +3,11 @@ (library (name wasm) ; The 'main' module shall not be part of the library, as it would start the - ; WASM REPL every time in all the dependencies. + ; Wasm REPL every time in all the dependencies. ; We also need to exclude the 'wasm' module as it overlaps with the library ; name. - (modules :standard \ main wasm)) + ; 'smallint' is a separate test module. + (modules :standard \ main wasm smallint)) (executable (name main) @@ -15,6 +16,13 @@ (flags (-open Wasm))) +(executable + (name smallint) + (modules smallint) + (libraries wasm) + (flags + (-open Wasm))) + (subdir text (rule @@ -28,6 +36,17 @@ (modules parser))) (env - (dev + (_ (flags - (-w +a-4-27-42-44-45 -warn-error +a-3)))) + (-w +a-4-27-42-44-45-70 -warn-error +a-3)))) + +(rule + (alias runtest) + (deps + ./main.exe + ./smallint.exe + (source_tree ../test)) + (action + (progn + (run ../test/core/run.py --wasm ./main.exe) + (run ./smallint.exe)))) From 2e9d836d464b60653521035ab70fb0a8649c91fa Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 31 May 2022 18:10:01 +0200 Subject: [PATCH 083/181] [interpreter] Fix warning flags for OCaml 4.13 (#1481) --- interpreter/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/Makefile b/interpreter/Makefile index 78fce53d8..1783a9c4d 100644 --- a/interpreter/Makefile +++ b/interpreter/Makefile @@ -19,7 +19,7 @@ WINMAKE = winmake.bat DIRS = util syntax binary text valid runtime exec script host main tests LIBS = bigarray -FLAGS = -lexflags -ml -cflags '-w +a-4-27-42-44-45 -warn-error +a-3' +FLAGS = -lexflags -ml -cflags '-w +a-4-27-42-44-45-70 -warn-error +a-3' OCBA = ocamlbuild $(FLAGS) $(DIRS:%=-I %) OCB = $(OCBA) $(LIBS:%=-libs %) JS = # set to JS shell command to run JS tests From b7da7923693a3cfaac4c108e1a8f059079b89002 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 1 Jun 2022 09:39:42 +0200 Subject: [PATCH 084/181] [interpreter] Simplify lexer and avoid table overflow on some architectures (#1482) --- interpreter/text/lexer.mll | 1119 ++++++++++++++++++------------------ 1 file changed, 570 insertions(+), 549 deletions(-) diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 9f901909e..161520e0a 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -1,17 +1,18 @@ { open Parser open Operators +open Source let convert_pos pos = - { Source.file = pos.Lexing.pos_fname; - Source.line = pos.Lexing.pos_lnum; - Source.column = pos.Lexing.pos_cnum - pos.Lexing.pos_bol + { file = pos.Lexing.pos_fname; + line = pos.Lexing.pos_lnum; + column = pos.Lexing.pos_cnum - pos.Lexing.pos_bol } let region lexbuf = let left = convert_pos (Lexing.lexeme_start_p lexbuf) in let right = convert_pos (Lexing.lexeme_end_p lexbuf) in - {Source.left = left; Source.right = right} + {left = left; right = right} let error lexbuf msg = raise (Script.Syntax (region lexbuf, msg)) let error_nest start lexbuf msg = @@ -47,92 +48,7 @@ let string s = done; Buffer.contents b -let num_type = function - | "i32" -> Types.I32Type - | "i64" -> Types.I64Type - | "f32" -> Types.F32Type - | "f64" -> Types.F64Type - | _ -> assert false - -let vec_type = function - | "v128" -> Types.V128Type - | _ -> assert false - -let intop t i32 i64 = - match t with - | "i32" -> i32 - | "i64" -> i64 - | _ -> assert false - -let floatop t f32 f64 = - match t with - | "f32" -> f32 - | "f64" -> f64 - | _ -> assert false - -let numop t i32 i64 f32 f64 = - match t with - | "i32" -> i32 - | "i64" -> i64 - | "f32" -> f32 - | "f64" -> f64 - | _ -> assert false - -let v128op s i8x16 i16x8 i32x4 i64x2 f32x4 f64x2 = - match s with - | "i8x16" -> i8x16 - | "i16x8" -> i16x8 - | "i32x4" -> i32x4 - | "i64x2" -> i64x2 - | "f32x4" -> f32x4 - | "f64x2" -> f64x2 - | _ -> assert false - -let v128intop s i8x16 i16x8 i32x4 i64x2 = - match s with - | "i8x16" -> i8x16 - | "i16x8" -> i16x8 - | "i32x4" -> i32x4 - | "i64x2" -> i64x2 - | _ -> assert false - -let v128floatop s f32x4 f64x2 = - match s with - | "f32x4" -> f32x4 - | "f64x2" -> f64x2 - | _ -> assert false - -let memsz sz m8 m16 m32 = - match sz with - | "8" -> m8 - | "16" -> m16 - | "32" -> m32 - | _ -> assert false - -let ext e s u = - match e with - | 's' -> s - | 'u' -> u - | _ -> assert false - let opt = Lib.Option.get - -let v128_shape = function - | "i8x16" -> V128.I8x16 () - | "i16x8" -> V128.I16x8 () - | "i32x4" -> V128.I32x4 () - | "i64x2" -> V128.I64x2 () - | "f32x4" -> V128.F32x4 () - | "f64x2" -> V128.F64x2 () - | _ -> assert false - -let only shapes s lexbuf = - if not (List.mem s shapes) then - unknown lexbuf - -let except shapes s lexbuf = - if (List.mem s shapes) then - unknown lexbuf } let sign = '+' | '-' @@ -181,8 +97,13 @@ let float = | sign? "nan" | sign? "nan:" "0x" hexnum let string = '"' character* '"' -let reserved = (letter | digit | '_' | symbol)+ -let name = '$' reserved + +let idchar = letter | digit | '_' | symbol +let name = idchar+ +let id = '$' name + +let keyword = ['a'-'z'] (letter | digit | '_' | '.' | ':')+ +let reserved = name | ',' | ';' | '[' | ']' | '{' | '}' let ixx = "i" ("32" | "64") let fxx = "f" ("32" | "64") @@ -211,469 +132,569 @@ rule token = parse | '"'character*'\\'_ { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" } - | "extern" { EXTERN } - | "externref" { EXTERNREF } - | "funcref" { FUNCREF } - | nxx as t { NUM_TYPE (num_type t) } - | vxxx as t { VEC_TYPE (vec_type t) } - | "mut" { MUT } - - | v128_shape as s { VEC_SHAPE (v128_shape s) } - - | (nxx as t)".const" - { let open Source in - CONST (numop t - (fun s -> let n = I32.of_string s.it in - i32_const (n @@ s.at), Values.I32 n) - (fun s -> let n = I64.of_string s.it in - i64_const (n @@ s.at), Values.I64 n) - (fun s -> let n = F32.of_string s.it in - f32_const (n @@ s.at), Values.F32 n) - (fun s -> let n = F64.of_string s.it in - f64_const (n @@ s.at), Values.F64 n)) - } - | vxxx".const" - { let open Source in - VEC_CONST - (fun shape ss at -> - let v = V128.of_strings shape (List.map (fun s -> s.it) ss) in - (v128_const (v @@ at), Values.V128 v)) + | keyword as s + { match s with + | "i32" -> NUM_TYPE Types.I32Type + | "i64" -> NUM_TYPE Types.I64Type + | "f32" -> NUM_TYPE Types.F32Type + | "f64" -> NUM_TYPE Types.F64Type + | "v128" -> VEC_TYPE Types.V128Type + | "i8x16" -> VEC_SHAPE (V128.I8x16 ()) + | "i16x8" -> VEC_SHAPE (V128.I16x8 ()) + | "i32x4" -> VEC_SHAPE (V128.I32x4 ()) + | "i64x2" -> VEC_SHAPE (V128.I64x2 ()) + | "f32x4" -> VEC_SHAPE (V128.F32x4 ()) + | "f64x2" -> VEC_SHAPE (V128.F64x2 ()) + + | "extern" -> EXTERN + | "externref" -> EXTERNREF + | "funcref" -> FUNCREF + | "mut" -> MUT + + | "nop" -> NOP + | "unreachable" -> UNREACHABLE + | "drop" -> DROP + | "block" -> BLOCK + | "loop" -> LOOP + | "end" -> END + | "br" -> BR + | "br_if" -> BR_IF + | "br_table" -> BR_TABLE + | "return" -> RETURN + | "if" -> IF + | "then" -> THEN + | "else" -> ELSE + | "select" -> SELECT + | "call" -> CALL + | "call_indirect" -> CALL_INDIRECT + + | "local.get" -> LOCAL_GET + | "local.set" -> LOCAL_SET + | "local.tee" -> LOCAL_TEE + | "global.get" -> GLOBAL_GET + | "global.set" -> GLOBAL_SET + + | "table.get" -> TABLE_GET + | "table.set" -> TABLE_SET + | "table.size" -> TABLE_SIZE + | "table.grow" -> TABLE_GROW + | "table.fill" -> TABLE_FILL + | "table.copy" -> TABLE_COPY + | "table.init" -> TABLE_INIT + | "elem.drop" -> ELEM_DROP + + | "memory.size" -> MEMORY_SIZE + | "memory.grow" -> MEMORY_GROW + | "memory.fill" -> MEMORY_FILL + | "memory.copy" -> MEMORY_COPY + | "memory.init" -> MEMORY_INIT + | "data.drop" -> DATA_DROP + + | "i32.load" -> LOAD (fun a o -> i32_load (opt a 2) o) + | "i64.load" -> LOAD (fun a o -> i64_load (opt a 3) o) + | "f32.load" -> LOAD (fun a o -> f32_load (opt a 2) o) + | "f64.load" -> LOAD (fun a o -> f64_load (opt a 3) o) + | "i32.store" -> STORE (fun a o -> i32_store (opt a 2) o) + | "i64.store" -> STORE (fun a o -> i64_store (opt a 3) o) + | "f32.store" -> STORE (fun a o -> f32_store (opt a 2) o) + | "f64.store" -> STORE (fun a o -> f64_store (opt a 3) o) + + | "i32.load8_u" -> LOAD (fun a o -> i32_load8_u (opt a 0) o) + | "i32.load8_s" -> LOAD (fun a o -> i32_load8_s (opt a 0) o) + | "i32.load16_u" -> LOAD (fun a o -> i32_load16_u (opt a 1) o) + | "i32.load16_s" -> LOAD (fun a o -> i32_load16_s (opt a 1) o) + | "i64.load8_u" -> LOAD (fun a o -> i64_load8_u (opt a 0) o) + | "i64.load8_s" -> LOAD (fun a o -> i64_load8_s (opt a 0) o) + | "i64.load16_u" -> LOAD (fun a o -> i64_load16_u (opt a 1) o) + | "i64.load16_s" -> LOAD (fun a o -> i64_load16_s (opt a 1) o) + | "i64.load32_u" -> LOAD (fun a o -> i64_load32_u (opt a 2) o) + | "i64.load32_s" -> LOAD (fun a o -> i64_load32_s (opt a 2) o) + + | "i32.store8" -> LOAD (fun a o -> i32_store8 (opt a 0) o) + | "i32.store16" -> LOAD (fun a o -> i32_store16 (opt a 1) o) + | "i64.store8" -> LOAD (fun a o -> i64_store8 (opt a 0) o) + | "i64.store16" -> LOAD (fun a o -> i64_store16 (opt a 1) o) + | "i64.store32" -> LOAD (fun a o -> i64_store32 (opt a 2) o) + + | "v128.load" -> VEC_LOAD (fun a o -> v128_load (opt a 4) o) + | "v128.store" -> VEC_STORE (fun a o -> v128_store (opt a 4) o) + | "v128.load8x8_u" -> VEC_LOAD (fun a o -> v128_load8x8_u (opt a 3) o) + | "v128.load8x8_s" -> VEC_LOAD (fun a o -> v128_load8x8_s (opt a 3) o) + | "v128.load16x4_u" -> VEC_LOAD (fun a o -> v128_load16x4_u (opt a 3) o) + | "v128.load16x4_s" -> VEC_LOAD (fun a o -> v128_load16x4_s (opt a 3) o) + | "v128.load32x2_u" -> VEC_LOAD (fun a o -> v128_load32x2_u (opt a 3) o) + | "v128.load32x2_s" -> VEC_LOAD (fun a o -> v128_load32x2_s (opt a 3) o) + | "v128.load8_splat" -> + VEC_LOAD (fun a o -> v128_load8_splat (opt a 0) o) + | "v128.load16_splat" -> + VEC_LOAD (fun a o -> v128_load16_splat (opt a 1) o) + | "v128.load32_splat" -> + VEC_LOAD (fun a o -> v128_load32_splat (opt a 2) o) + | "v128.load64_splat" -> + VEC_LOAD (fun a o -> v128_load64_splat (opt a 3) o) + | "v128.load32_zero" -> + VEC_LOAD (fun a o -> v128_load32_zero (opt a 2) o) + | "v128.load64_zero" -> + VEC_LOAD (fun a o -> v128_load64_zero (opt a 3) o) + | "v128.load8_lane" -> + VEC_LOAD_LANE (fun a o i -> v128_load8_lane (opt a 0) o i) + | "v128.load16_lane" -> + VEC_LOAD_LANE (fun a o i -> v128_load16_lane (opt a 1) o i) + | "v128.load32_lane" -> + VEC_LOAD_LANE (fun a o i -> v128_load32_lane (opt a 2) o i) + | "v128.load64_lane" -> + VEC_LOAD_LANE (fun a o i -> v128_load64_lane (opt a 3) o i) + | "v128.store8_lane" -> + VEC_STORE_LANE (fun a o i -> v128_store8_lane (opt a 0) o i) + | "v128.store16_lane" -> + VEC_STORE_LANE (fun a o i -> v128_store16_lane (opt a 1) o i) + | "v128.store32_lane" -> + VEC_STORE_LANE (fun a o i -> v128_store32_lane (opt a 2) o i) + | "v128.store64_lane" -> + VEC_STORE_LANE (fun a o i -> v128_store64_lane (opt a 3) o i) + + | "i32.const" -> + CONST (fun s -> + let n = I32.of_string s.it in i32_const (n @@ s.at), Values.I32 n) + | "i64.const" -> + CONST (fun s -> + let n = I64.of_string s.it in i64_const (n @@ s.at), Values.I64 n) + | "f32.const" -> + CONST (fun s -> + let n = F32.of_string s.it in f32_const (n @@ s.at), Values.F32 n) + | "f64.const" -> + CONST (fun s -> + let n = F64.of_string s.it in f64_const (n @@ s.at), Values.F64 n) + | "v128.const" -> + VEC_CONST + (fun shape ss at -> + let v = V128.of_strings shape (List.map (fun s -> s.it) ss) in + (v128_const (v @@ at), Values.V128 v)) + + | "ref.null" -> REF_NULL + | "ref.func" -> REF_FUNC + | "ref.extern" -> REF_EXTERN + | "ref.is_null" -> REF_IS_NULL + + | "i32.clz" -> UNARY i32_clz + | "i32.ctz" -> UNARY i32_ctz + | "i32.popcnt" -> UNARY i32_popcnt + | "i32.extend8_s" -> UNARY i32_extend8_s + | "i32.extend16_s" -> UNARY i32_extend16_s + | "i64.clz" -> UNARY i64_clz + | "i64.ctz" -> UNARY i64_ctz + | "i64.popcnt" -> UNARY i64_popcnt + | "i64.extend8_s" -> UNARY i64_extend8_s + | "i64.extend16_s" -> UNARY i64_extend16_s + | "i64.extend32_s" -> UNARY i64_extend32_s + + | "f32.neg" -> UNARY f32_neg + | "f32.abs" -> UNARY f32_abs + | "f32.sqrt" -> UNARY f32_sqrt + | "f32.ceil" -> UNARY f32_ceil + | "f32.floor" -> UNARY f32_floor + | "f32.trunc" -> UNARY f32_trunc + | "f32.nearest" -> UNARY f32_nearest + | "f64.neg" -> UNARY f64_neg + | "f64.abs" -> UNARY f64_abs + | "f64.sqrt" -> UNARY f64_sqrt + | "f64.ceil" -> UNARY f64_ceil + | "f64.floor" -> UNARY f64_floor + | "f64.trunc" -> UNARY f64_trunc + | "f64.nearest" -> UNARY f64_nearest + + | "i32.add" -> BINARY i32_add + | "i32.sub" -> BINARY i32_sub + | "i32.mul" -> BINARY i32_mul + | "i32.div_u" -> BINARY i32_div_u + | "i32.div_s" -> BINARY i32_div_s + | "i32.rem_u" -> BINARY i32_rem_u + | "i32.rem_s" -> BINARY i32_rem_s + | "i32.and" -> BINARY i32_and + | "i32.or" -> BINARY i32_or + | "i32.xor" -> BINARY i32_xor + | "i32.shl" -> BINARY i32_shl + | "i32.shr_u" -> BINARY i32_shr_u + | "i32.shr_s" -> BINARY i32_shr_s + | "i32.rotl" -> BINARY i32_rotl + | "i32.rotr" -> BINARY i32_rotr + | "i64.add" -> BINARY i64_add + | "i64.sub" -> BINARY i64_sub + | "i64.mul" -> BINARY i64_mul + | "i64.div_u" -> BINARY i64_div_u + | "i64.div_s" -> BINARY i64_div_s + | "i64.rem_u" -> BINARY i64_rem_u + | "i64.rem_s" -> BINARY i64_rem_s + | "i64.and" -> BINARY i64_and + | "i64.or" -> BINARY i64_or + | "i64.xor" -> BINARY i64_xor + | "i64.shl" -> BINARY i64_shl + | "i64.shr_u" -> BINARY i64_shr_u + | "i64.shr_s" -> BINARY i64_shr_s + | "i64.rotl" -> BINARY i64_rotl + | "i64.rotr" -> BINARY i64_rotr + + | "f32.add" -> BINARY f32_add + | "f32.sub" -> BINARY f32_sub + | "f32.mul" -> BINARY f32_mul + | "f32.div" -> BINARY f32_div + | "f32.min" -> BINARY f32_min + | "f32.max" -> BINARY f32_max + | "f32.copysign" -> BINARY f32_copysign + | "f64.add" -> BINARY f64_add + | "f64.sub" -> BINARY f64_sub + | "f64.mul" -> BINARY f64_mul + | "f64.div" -> BINARY f64_div + | "f64.min" -> BINARY f64_min + | "f64.max" -> BINARY f64_max + | "f64.copysign" -> BINARY f64_copysign + + | "i32.eqz" -> TEST i32_eqz + | "i64.eqz" -> TEST i64_eqz + + | "i32.eq" -> COMPARE i32_eq + | "i32.ne" -> COMPARE i32_ne + | "i32.lt_u" -> COMPARE i32_lt_u + | "i32.lt_s" -> COMPARE i32_lt_s + | "i32.le_u" -> COMPARE i32_le_u + | "i32.le_s" -> COMPARE i32_le_s + | "i32.gt_u" -> COMPARE i32_gt_u + | "i32.gt_s" -> COMPARE i32_gt_s + | "i32.ge_u" -> COMPARE i32_ge_u + | "i32.ge_s" -> COMPARE i32_ge_s + | "i64.eq" -> COMPARE i64_eq + | "i64.ne" -> COMPARE i64_ne + | "i64.lt_u" -> COMPARE i64_lt_u + | "i64.lt_s" -> COMPARE i64_lt_s + | "i64.le_u" -> COMPARE i64_le_u + | "i64.le_s" -> COMPARE i64_le_s + | "i64.gt_u" -> COMPARE i64_gt_u + | "i64.gt_s" -> COMPARE i64_gt_s + | "i64.ge_u" -> COMPARE i64_ge_u + | "i64.ge_s" -> COMPARE i64_ge_s + + | "f32.eq" -> COMPARE f32_eq + | "f32.ne" -> COMPARE f32_ne + | "f32.lt" -> COMPARE f32_lt + | "f32.le" -> COMPARE f32_le + | "f32.gt" -> COMPARE f32_gt + | "f32.ge" -> COMPARE f32_ge + | "f64.eq" -> COMPARE f64_eq + | "f64.ne" -> COMPARE f64_ne + | "f64.lt" -> COMPARE f64_lt + | "f64.le" -> COMPARE f64_le + | "f64.gt" -> COMPARE f64_gt + | "f64.ge" -> COMPARE f64_ge + + | "i32.wrap_i64" -> CONVERT i32_wrap_i64 + | "i64.extend_i32_s" -> CONVERT i64_extend_i32_s + | "i64.extend_i32_u" -> CONVERT i64_extend_i32_u + | "f32.demote_f64" -> CONVERT f32_demote_f64 + | "f64.promote_f32" -> CONVERT f64_promote_f32 + | "i32.trunc_f32_u" -> CONVERT i32_trunc_f32_u + | "i32.trunc_f32_s" -> CONVERT i32_trunc_f32_s + | "i64.trunc_f32_u" -> CONVERT i64_trunc_f32_u + | "i64.trunc_f32_s" -> CONVERT i64_trunc_f32_s + | "i32.trunc_f64_u" -> CONVERT i32_trunc_f64_u + | "i32.trunc_f64_s" -> CONVERT i32_trunc_f64_s + | "i64.trunc_f64_u" -> CONVERT i64_trunc_f64_u + | "i64.trunc_f64_s" -> CONVERT i64_trunc_f64_s + | "i32.trunc_sat_f32_u" -> CONVERT i32_trunc_sat_f32_u + | "i32.trunc_sat_f32_s" -> CONVERT i32_trunc_sat_f32_s + | "i64.trunc_sat_f32_u" -> CONVERT i64_trunc_sat_f32_u + | "i64.trunc_sat_f32_s" -> CONVERT i64_trunc_sat_f32_s + | "i32.trunc_sat_f64_u" -> CONVERT i32_trunc_sat_f64_u + | "i32.trunc_sat_f64_s" -> CONVERT i32_trunc_sat_f64_s + | "i64.trunc_sat_f64_u" -> CONVERT i64_trunc_sat_f64_u + | "i64.trunc_sat_f64_s" -> CONVERT i64_trunc_sat_f64_s + | "f32.convert_i32_u" -> CONVERT f32_convert_i32_u + | "f32.convert_i32_s" -> CONVERT f32_convert_i32_s + | "f64.convert_i32_u" -> CONVERT f64_convert_i32_u + | "f64.convert_i32_s" -> CONVERT f64_convert_i32_s + | "f32.convert_i64_u" -> CONVERT f32_convert_i64_u + | "f32.convert_i64_s" -> CONVERT f32_convert_i64_s + | "f64.convert_i64_u" -> CONVERT f64_convert_i64_u + | "f64.convert_i64_s" -> CONVERT f64_convert_i64_s + | "f32.reinterpret_i32" -> CONVERT f32_reinterpret_i32 + | "f64.reinterpret_i64" -> CONVERT f64_reinterpret_i64 + | "i32.reinterpret_f32" -> CONVERT i32_reinterpret_f32 + | "i64.reinterpret_f64" -> CONVERT i64_reinterpret_f64 + + | "v128.not" -> VEC_UNARY v128_not + | "v128.and" -> VEC_UNARY v128_and + | "v128.andnot" -> VEC_UNARY v128_andnot + | "v128.or" -> VEC_UNARY v128_or + | "v128.xor" -> VEC_UNARY v128_xor + | "v128.bitselect" -> VEC_TERNARY v128_bitselect + | "v128.any_true" -> VEC_TEST v128_any_true + + | "i8x16.neg" -> VEC_UNARY i8x16_neg + | "i16x8.neg" -> VEC_UNARY i16x8_neg + | "i32x4.neg" -> VEC_UNARY i32x4_neg + | "i64x2.neg" -> VEC_UNARY i64x2_neg + | "i8x16.abs" -> VEC_UNARY i8x16_abs + | "i16x8.abs" -> VEC_UNARY i16x8_abs + | "i32x4.abs" -> VEC_UNARY i32x4_abs + | "i64x2.abs" -> VEC_UNARY i64x2_abs + | "i8x16.popcnt" -> VEC_UNARY i8x16_popcnt + | "i8x16.avgr_u" -> VEC_UNARY i8x16_avgr_u + | "i16x8.avgr_u" -> VEC_UNARY i16x8_avgr_u + + | "f32x4.neg" -> VEC_UNARY f32x4_neg + | "f64x2.neg" -> VEC_UNARY f64x2_neg + | "f32x4.abs" -> VEC_UNARY f32x4_abs + | "f64x2.abs" -> VEC_UNARY f64x2_abs + | "f32x4.sqrt" -> VEC_UNARY f32x4_sqrt + | "f64x2.sqrt" -> VEC_UNARY f64x2_sqrt + | "f32x4.ceil" -> VEC_UNARY f32x4_ceil + | "f64x2.ceil" -> VEC_UNARY f64x2_ceil + | "f32x4.floor" -> VEC_UNARY f32x4_floor + | "f64x2.floor" -> VEC_UNARY f64x2_floor + | "f32x4.trunc" -> VEC_UNARY f32x4_trunc + | "f64x2.trunc" -> VEC_UNARY f64x2_trunc + | "f32x4.nearest" -> VEC_UNARY f32x4_nearest + | "f64x2.nearest" -> VEC_UNARY f64x2_nearest + + | "i32x4.trunc_sat_f32x4_u" -> VEC_UNARY i32x4_trunc_sat_f32x4_u + | "i32x4.trunc_sat_f32x4_s" -> VEC_UNARY i32x4_trunc_sat_f32x4_s + | "i32x4.trunc_sat_f64x2_u_zero" -> + VEC_UNARY i32x4_trunc_sat_f64x2_u_zero + | "i32x4.trunc_sat_f64x2_s_zero" -> + VEC_UNARY i32x4_trunc_sat_f64x2_s_zero + | "f64x2.promote_low_f32x4" -> VEC_UNARY f64x2_promote_low_f32x4 + | "f32x4.demote_f64x2_zero" -> VEC_UNARY f32x4_demote_f64x2_zero + | "f32x4.convert_i32x4_u" -> VEC_UNARY f32x4_convert_i32x4_u + | "f32x4.convert_i32x4_s" -> VEC_UNARY f32x4_convert_i32x4_s + | "f64x2.convert_low_i32x4_u" -> VEC_UNARY f64x2_convert_low_i32x4_u + | "f64x2.convert_low_i32x4_s" -> VEC_UNARY f64x2_convert_low_i32x4_s + | "i16x8.extadd_pairwise_i8x16_u" -> + VEC_UNARY i16x8_extadd_pairwise_i8x16_u + | "i16x8.extadd_pairwise_i8x16_s" -> + VEC_UNARY i16x8_extadd_pairwise_i8x16_s + | "i32x4.extadd_pairwise_i16x8_u" -> + VEC_UNARY i32x4_extadd_pairwise_i16x8_u + | "i32x4.extadd_pairwise_i16x8_s" -> + VEC_UNARY i32x4_extadd_pairwise_i16x8_s + + | "i8x16.eq" -> VEC_BINARY i8x16_eq + | "i16x8.eq" -> VEC_BINARY i16x8_eq + | "i32x4.eq" -> VEC_BINARY i32x4_eq + | "i64x2.eq" -> VEC_BINARY i64x2_eq + | "i8x16.ne" -> VEC_BINARY i8x16_ne + | "i16x8.ne" -> VEC_BINARY i16x8_ne + | "i32x4.ne" -> VEC_BINARY i32x4_ne + | "i64x2.ne" -> VEC_BINARY i64x2_ne + | "i8x16.lt_u" -> VEC_BINARY i8x16_lt_u + | "i8x16.lt_s" -> VEC_BINARY i8x16_lt_s + | "i16x8.lt_u" -> VEC_BINARY i16x8_lt_u + | "i16x8.lt_s" -> VEC_BINARY i16x8_lt_s + | "i32x4.lt_u" -> VEC_BINARY i32x4_lt_u + | "i32x4.lt_s" -> VEC_BINARY i32x4_lt_s + | "i64x2.lt_s" -> VEC_BINARY i64x2_lt_s + | "i8x16.le_u" -> VEC_BINARY i8x16_le_u + | "i8x16.le_s" -> VEC_BINARY i8x16_le_s + | "i16x8.le_u" -> VEC_BINARY i16x8_le_u + | "i16x8.le_s" -> VEC_BINARY i16x8_le_s + | "i32x4.le_u" -> VEC_BINARY i32x4_le_u + | "i32x4.le_s" -> VEC_BINARY i32x4_le_s + | "i64x2.le_s" -> VEC_BINARY i64x2_le_s + | "i8x16.gt_u" -> VEC_BINARY i8x16_gt_u + | "i8x16.gt_s" -> VEC_BINARY i8x16_gt_s + | "i16x8.gt_u" -> VEC_BINARY i16x8_gt_u + | "i16x8.gt_s" -> VEC_BINARY i16x8_gt_s + | "i32x4.gt_u" -> VEC_BINARY i32x4_gt_u + | "i32x4.gt_s" -> VEC_BINARY i32x4_gt_s + | "i64x2.gt_s" -> VEC_BINARY i64x2_gt_s + | "i8x16.ge_u" -> VEC_BINARY i8x16_ge_u + | "i8x16.ge_s" -> VEC_BINARY i8x16_ge_s + | "i16x8.ge_u" -> VEC_BINARY i16x8_ge_u + | "i16x8.ge_s" -> VEC_BINARY i16x8_ge_s + | "i32x4.ge_u" -> VEC_BINARY i32x4_ge_u + | "i32x4.ge_s" -> VEC_BINARY i32x4_ge_s + | "i64x2.ge_s" -> VEC_BINARY i64x2_ge_s + + | "f32x4.eq" -> VEC_BINARY f32x4_eq + | "f64x2.eq" -> VEC_BINARY f64x2_eq + | "f32x4.ne" -> VEC_BINARY f32x4_ne + | "f64x2.ne" -> VEC_BINARY f64x2_ne + | "f32x4.lt" -> VEC_BINARY f32x4_lt + | "f64x2.lt" -> VEC_BINARY f64x2_lt + | "f32x4.le" -> VEC_BINARY f32x4_le + | "f64x2.le" -> VEC_BINARY f64x2_le + | "f32x4.gt" -> VEC_BINARY f32x4_gt + | "f64x2.gt" -> VEC_BINARY f64x2_gt + | "f32x4.ge" -> VEC_BINARY f32x4_ge + | "f64x2.ge" -> VEC_BINARY f64x2_ge + | "i8x16.swizzle" -> VEC_BINARY i8x16_swizzle + + | "i8x16.add" -> VEC_BINARY i8x16_add + | "i16x8.add" -> VEC_BINARY i16x8_add + | "i32x4.add" -> VEC_BINARY i32x4_add + | "i64x2.add" -> VEC_BINARY i64x2_add + | "i8x16.sub" -> VEC_BINARY i8x16_sub + | "i16x8.sub" -> VEC_BINARY i16x8_sub + | "i32x4.sub" -> VEC_BINARY i32x4_sub + | "i64x2.sub" -> VEC_BINARY i64x2_sub + | "i16x8.mul" -> VEC_BINARY i16x8_mul + | "i32x4.mul" -> VEC_BINARY i32x4_mul + | "i64x2.mul" -> VEC_BINARY i64x2_mul + | "i8x16.add_sat_u" -> VEC_BINARY i8x16_add_sat_u + | "i8x16.add_sat_s" -> VEC_BINARY i8x16_add_sat_s + | "i16x8.add_sat_u" -> VEC_BINARY i16x8_add_sat_u + | "i16x8.add_sat_s" -> VEC_BINARY i16x8_add_sat_s + | "i8x16.sub_sat_u" -> VEC_BINARY i8x16_sub_sat_u + | "i8x16.sub_sat_s" -> VEC_BINARY i8x16_sub_sat_s + | "i16x8.sub_sat_u" -> VEC_BINARY i16x8_sub_sat_u + | "i16x8.sub_sat_s" -> VEC_BINARY i16x8_sub_sat_s + | "i32x4.dot_i16x8_s" -> VEC_BINARY i32x4_dot_i16x8_s + + | "i8x16.min_u" -> VEC_BINARY i8x16_min_u + | "i16x8.min_u" -> VEC_BINARY i16x8_min_u + | "i32x4.min_u" -> VEC_BINARY i32x4_min_u + | "i8x16.min_s" -> VEC_BINARY i8x16_min_s + | "i16x8.min_s" -> VEC_BINARY i16x8_min_s + | "i32x4.min_s" -> VEC_BINARY i32x4_min_s + | "i8x16.max_u" -> VEC_BINARY i8x16_max_u + | "i16x8.max_u" -> VEC_BINARY i16x8_max_u + | "i32x4.max_u" -> VEC_BINARY i32x4_max_u + | "i8x16.max_s" -> VEC_BINARY i8x16_max_s + | "i16x8.max_s" -> VEC_BINARY i16x8_max_s + | "i32x4.max_s" -> VEC_BINARY i32x4_max_s + + | "f32x4.add" -> VEC_BINARY f32x4_add + | "f64x2.add" -> VEC_BINARY f64x2_add + | "f32x4.sub" -> VEC_BINARY f32x4_sub + | "f64x2.sub" -> VEC_BINARY f64x2_sub + | "f32x4.mul" -> VEC_BINARY f32x4_mul + | "f64x2.mul" -> VEC_BINARY f64x2_mul + | "f32x4.div" -> VEC_BINARY f32x4_div + | "f64x2.div" -> VEC_BINARY f64x2_div + + | "f32x4.min" -> VEC_BINARY f32x4_min + | "f64x2.min" -> VEC_BINARY f64x2_min + | "f32x4.max" -> VEC_BINARY f32x4_max + | "f64x2.max" -> VEC_BINARY f64x2_max + | "f32x4.pmin" -> VEC_BINARY f32x4_pmin + | "f64x2.pmin" -> VEC_BINARY f64x2_pmin + | "f32x4.pmax" -> VEC_BINARY f32x4_pmax + | "f64x2.pmax" -> VEC_BINARY f64x2_pmax + + | "i16x8.q15mulr_sat_s" -> VEC_BINARY i16x8_q15mulr_sat_s + | "i8x16.narrow_i16x8_u" -> VEC_BINARY i8x16_narrow_i16x8_u + | "i8x16.narrow_i16x8_s" -> VEC_BINARY i8x16_narrow_i16x8_s + | "i16x8.narrow_i32x4_u" -> VEC_BINARY i16x8_narrow_i32x4_u + | "i16x8.narrow_i32x4_s" -> VEC_BINARY i16x8_narrow_i32x4_s + | "i16x8.extend_low_i8x16_u" -> VEC_UNARY i16x8_extend_low_i8x16_u + | "i16x8.extend_low_i8x16_s" -> VEC_UNARY i16x8_extend_low_i8x16_s + | "i16x8.extend_high_i8x16_u" -> VEC_UNARY i16x8_extend_high_i8x16_u + | "i16x8.extend_high_i8x16_s" -> VEC_UNARY i16x8_extend_high_i8x16_s + | "i32x4.extend_low_i16x8_u" -> VEC_UNARY i32x4_extend_low_i16x8_u + | "i32x4.extend_low_i16x8_s" -> VEC_UNARY i32x4_extend_low_i16x8_s + | "i32x4.extend_high_i16x8_u" -> VEC_UNARY i32x4_extend_high_i16x8_u + | "i32x4.extend_high_i16x8_s" -> VEC_UNARY i32x4_extend_high_i16x8_s + | "i64x2.extend_low_i32x4_u" -> VEC_UNARY i64x2_extend_low_i32x4_u + | "i64x2.extend_low_i32x4_s" -> VEC_UNARY i64x2_extend_low_i32x4_s + | "i64x2.extend_high_i32x4_u" -> VEC_UNARY i64x2_extend_high_i32x4_u + | "i64x2.extend_high_i32x4_s" -> VEC_UNARY i64x2_extend_high_i32x4_s + | "i16x8.extmul_low_i8x16_u" -> VEC_UNARY i16x8_extmul_low_i8x16_u + | "i16x8.extmul_low_i8x16_s" -> VEC_UNARY i16x8_extmul_low_i8x16_s + | "i16x8.extmul_high_i8x16_u" -> VEC_UNARY i16x8_extmul_high_i8x16_u + | "i16x8.extmul_high_i8x16_s" -> VEC_UNARY i16x8_extmul_high_i8x16_s + | "i32x4.extmul_low_i16x8_u" -> VEC_UNARY i32x4_extmul_low_i16x8_u + | "i32x4.extmul_low_i16x8_s" -> VEC_UNARY i32x4_extmul_low_i16x8_s + | "i32x4.extmul_high_i16x8_u" -> VEC_UNARY i32x4_extmul_high_i16x8_u + | "i32x4.extmul_high_i16x8_s" -> VEC_UNARY i32x4_extmul_high_i16x8_s + | "i64x2.extmul_low_i32x4_u" -> VEC_UNARY i64x2_extmul_low_i32x4_u + | "i64x2.extmul_low_i32x4_s" -> VEC_UNARY i64x2_extmul_low_i32x4_s + | "i64x2.extmul_high_i32x4_u" -> VEC_UNARY i64x2_extmul_high_i32x4_u + | "i64x2.extmul_high_i32x4_s" -> VEC_UNARY i64x2_extmul_high_i32x4_s + + | "i8x16.all_true" -> VEC_TEST i8x16_all_true + | "i16x8.all_true" -> VEC_TEST i16x8_all_true + | "i32x4.all_true" -> VEC_TEST i32x4_all_true + | "i64x2.all_true" -> VEC_TEST i64x2_all_true + | "i8x16.bitmask" -> VEC_BITMASK i8x16_bitmask + | "i16x8.bitmask" -> VEC_BITMASK i16x8_bitmask + | "i32x4.bitmask" -> VEC_BITMASK i32x4_bitmask + | "i64x2.bitmask" -> VEC_BITMASK i64x2_bitmask + | "i8x16.shl" -> VEC_SHIFT i8x16_shl + | "i16x8.shl" -> VEC_SHIFT i16x8_shl + | "i32x4.shl" -> VEC_SHIFT i32x4_shl + | "i64x2.shl" -> VEC_SHIFT i64x2_shl + | "i8x16.shr_u" -> VEC_SHIFT i8x16_shr_u + | "i8x16.shr_s" -> VEC_SHIFT i8x16_shr_s + | "i16x8.shr_u" -> VEC_SHIFT i16x8_shr_u + | "i16x8.shr_s" -> VEC_SHIFT i16x8_shr_s + | "i32x4.shr_u" -> VEC_SHIFT i32x4_shr_u + | "i32x4.shr_s" -> VEC_SHIFT i32x4_shr_s + | "i64x2.shr_u" -> VEC_SHIFT i64x2_shr_u + | "i64x2.shr_s" -> VEC_SHIFT i64x2_shr_s + | "i8x16.shuffle" -> VEC_SHUFFLE + + | "i8x16.splat" -> VEC_SPLAT i8x16_splat + | "i16x8.splat" -> VEC_SPLAT i16x8_splat + | "i32x4.splat" -> VEC_SPLAT i32x4_splat + | "i64x2.splat" -> VEC_SPLAT i64x2_splat + | "f32x4.splat" -> VEC_SPLAT f32x4_splat + | "f64x2.splat" -> VEC_SPLAT f64x2_splat + | "i8x16.extract_lane_u" -> VEC_EXTRACT i8x16_extract_lane_u + | "i8x16.extract_lane_s" -> VEC_EXTRACT i8x16_extract_lane_s + | "i16x8.extract_lane_u" -> VEC_EXTRACT i16x8_extract_lane_u + | "i16x8.extract_lane_s" -> VEC_EXTRACT i16x8_extract_lane_s + | "i32x4.extract_lane" -> VEC_EXTRACT i32x4_extract_lane + | "i64x2.extract_lane" -> VEC_EXTRACT i64x2_extract_lane + | "f32x4.extract_lane" -> VEC_EXTRACT f32x4_extract_lane + | "f64x2.extract_lane" -> VEC_EXTRACT f64x2_extract_lane + | "i8x16.replace_lane" -> VEC_REPLACE i8x16_replace_lane + | "i16x8.replace_lane" -> VEC_REPLACE i16x8_replace_lane + | "i32x4.replace_lane" -> VEC_REPLACE i32x4_replace_lane + | "i64x2.replace_lane" -> VEC_REPLACE i64x2_replace_lane + | "f32x4.replace_lane" -> VEC_REPLACE f32x4_replace_lane + | "f64x2.replace_lane" -> VEC_REPLACE f64x2_replace_lane + + | "type" -> TYPE + | "func" -> FUNC + | "param" -> PARAM + | "result" -> RESULT + | "start" -> START + | "local" -> LOCAL + | "global" -> GLOBAL + | "table" -> TABLE + | "memory" -> MEMORY + | "elem" -> ELEM + | "data" -> DATA + | "declare" -> DECLARE + | "offset" -> OFFSET + | "item" -> ITEM + | "import" -> IMPORT + | "export" -> EXPORT + + | "module" -> MODULE + | "binary" -> BIN + | "quote" -> QUOTE + + | "script" -> SCRIPT + | "register" -> REGISTER + | "invoke" -> INVOKE + | "get" -> GET + | "assert_malformed" -> ASSERT_MALFORMED + | "assert_invalid" -> ASSERT_INVALID + | "assert_unlinkable" -> ASSERT_UNLINKABLE + | "assert_return" -> ASSERT_RETURN + | "assert_trap" -> ASSERT_TRAP + | "assert_exhaustion" -> ASSERT_EXHAUSTION + | "nan:canonical" -> NAN Script.CanonicalNan + | "nan:arithmetic" -> NAN Script.ArithmeticNan + | "input" -> INPUT + | "output" -> OUTPUT + + | _ -> unknown lexbuf } - | "ref.null" { REF_NULL } - | "ref.func" { REF_FUNC } - | "ref.extern" { REF_EXTERN } - | "ref.is_null" { REF_IS_NULL } - - | "nop" { NOP } - | "unreachable" { UNREACHABLE } - | "drop" { DROP } - | "block" { BLOCK } - | "loop" { LOOP } - | "end" { END } - | "br" { BR } - | "br_if" { BR_IF } - | "br_table" { BR_TABLE } - | "return" { RETURN } - | "if" { IF } - | "then" { THEN } - | "else" { ELSE } - | "select" { SELECT } - | "call" { CALL } - | "call_indirect" { CALL_INDIRECT } - - | "local.get" { LOCAL_GET } - | "local.set" { LOCAL_SET } - | "local.tee" { LOCAL_TEE } - | "global.get" { GLOBAL_GET } - | "global.set" { GLOBAL_SET } - - | "table.get" { TABLE_GET } - | "table.set" { TABLE_SET } - | "table.size" { TABLE_SIZE } - | "table.grow" { TABLE_GROW } - | "table.fill" { TABLE_FILL } - | "table.copy" { TABLE_COPY } - | "table.init" { TABLE_INIT } - | "elem.drop" { ELEM_DROP } - - | "memory.size" { MEMORY_SIZE } - | "memory.grow" { MEMORY_GROW } - | "memory.fill" { MEMORY_FILL } - | "memory.copy" { MEMORY_COPY } - | "memory.init" { MEMORY_INIT } - | "data.drop" { DATA_DROP } - - | (nxx as t)".load" - { LOAD (fun x a o -> - numop t (i32_load x (opt a 2)) (i64_load x (opt a 3)) - (f32_load x (opt a 2)) (f64_load x (opt a 3)) o) } - | (nxx as t)".store" - { STORE (fun x a o -> - numop t (i32_store x (opt a 2)) (i64_store x (opt a 3)) - (f32_store x (opt a 2)) (f64_store x (opt a 3)) o) } - | (ixx as t)".load"(mem_size as sz)"_"(sign as s) - { if t = "i32" && sz = "32" then unknown lexbuf; - LOAD (fun x a o -> - intop t - (memsz sz - (ext s i32_load8_s i32_load8_u x (opt a 0)) - (ext s i32_load16_s i32_load16_u x (opt a 1)) - (fun _ -> unreachable) o) - (memsz sz - (ext s i64_load8_s i64_load8_u x (opt a 0)) - (ext s i64_load16_s i64_load16_u x (opt a 1)) - (ext s i64_load32_s i64_load32_u x (opt a 2)) o)) } - | (ixx as t)".store"(mem_size as sz) - { if t = "i32" && sz = "32" then unknown lexbuf; - STORE (fun x a o -> - intop t - (memsz sz - (i32_store8 x (opt a 0)) - (i32_store16 x (opt a 1)) - (fun _ -> unreachable) o) - (memsz sz - (i64_store8 x (opt a 0)) - (i64_store16 x (opt a 1)) - (i64_store32 x (opt a 2)) o)) } - | "v128.load" - { VEC_LOAD (fun x a o -> (v128_load x (opt a 4)) o) } - | "v128.store" - { VEC_STORE (fun x a o -> (v128_store x (opt a 4)) o) } - | "v128.load8x8_"(sign as s) - { VEC_LOAD (fun x a o -> (ext s v128_load8x8_s v128_load8x8_u x (opt a 3)) o) } - | "v128.load16x4_"(sign as s) - { VEC_LOAD (fun x a o -> (ext s v128_load16x4_s v128_load16x4_u x (opt a 3)) o) } - | "v128.load32x2_"(sign as s) - { VEC_LOAD (fun x a o -> (ext s v128_load32x2_s v128_load32x2_u x (opt a 3)) o) } - | "v128.load8_splat" - { VEC_LOAD (fun x a o -> (v128_load8_splat x (opt a 0)) o) } - | "v128.load16_splat" - { VEC_LOAD (fun x a o -> (v128_load16_splat x (opt a 1)) o) } - | "v128.load32_splat" - { VEC_LOAD (fun x a o -> (v128_load32_splat x (opt a 2)) o) } - | "v128.load64_splat" - { VEC_LOAD (fun x a o -> (v128_load64_splat x (opt a 3)) o) } - | "v128.load32_zero" - { VEC_LOAD (fun x a o -> (v128_load32_zero x (opt a 2)) o) } - | "v128.load64_zero" - { VEC_LOAD (fun x a o -> (v128_load64_zero x (opt a 3)) o) } - | "v128.load8_lane" - { VEC_LOAD_LANE (fun x a o i -> (v128_load8_lane x (opt a 0)) o i) } - | "v128.load16_lane" - { VEC_LOAD_LANE (fun x a o i -> (v128_load16_lane x (opt a 1)) o i) } - | "v128.load32_lane" - { VEC_LOAD_LANE (fun x a o i -> (v128_load32_lane x (opt a 2)) o i) } - | "v128.load64_lane" - { VEC_LOAD_LANE (fun x a o i -> (v128_load64_lane x (opt a 3)) o i) } - | "v128.store8_lane" - { VEC_STORE_LANE (fun x a o i -> (v128_store8_lane x (opt a 0)) o i) } - | "v128.store16_lane" - { VEC_STORE_LANE (fun x a o i -> (v128_store16_lane x (opt a 1)) o i) } - | "v128.store32_lane" - { VEC_STORE_LANE (fun x a o i -> (v128_store32_lane x (opt a 2)) o i) } - | "v128.store64_lane" - { VEC_STORE_LANE (fun x a o i -> (v128_store64_lane x (opt a 3)) o i) } | "offset="(nat as s) { OFFSET_EQ_NAT s } | "align="(nat as s) { ALIGN_EQ_NAT s } - | (ixx as t)".clz" { UNARY (intop t i32_clz i64_clz) } - | (ixx as t)".ctz" { UNARY (intop t i32_ctz i64_ctz) } - | (ixx as t)".popcnt" { UNARY (intop t i32_popcnt i64_popcnt) } - | (ixx as t)".extend8_s" { UNARY (intop t i32_extend8_s i64_extend8_s) } - | (ixx as t)".extend16_s" { UNARY (intop t i32_extend16_s i64_extend16_s) } - | "i64.extend32_s" { UNARY i64_extend32_s } - | (fxx as t)".neg" { UNARY (floatop t f32_neg f64_neg) } - | (fxx as t)".abs" { UNARY (floatop t f32_abs f64_abs) } - | (fxx as t)".sqrt" { UNARY (floatop t f32_sqrt f64_sqrt) } - | (fxx as t)".ceil" { UNARY (floatop t f32_ceil f64_ceil) } - | (fxx as t)".floor" { UNARY (floatop t f32_floor f64_floor) } - | (fxx as t)".trunc" { UNARY (floatop t f32_trunc f64_trunc) } - | (fxx as t)".nearest" { UNARY (floatop t f32_nearest f64_nearest) } - - | (ixx as t)".add" { BINARY (intop t i32_add i64_add) } - | (ixx as t)".sub" { BINARY (intop t i32_sub i64_sub) } - | (ixx as t)".mul" { BINARY (intop t i32_mul i64_mul) } - | (ixx as t)".div_s" { BINARY (intop t i32_div_s i64_div_s) } - | (ixx as t)".div_u" { BINARY (intop t i32_div_u i64_div_u) } - | (ixx as t)".rem_s" { BINARY (intop t i32_rem_s i64_rem_s) } - | (ixx as t)".rem_u" { BINARY (intop t i32_rem_u i64_rem_u) } - | (ixx as t)".and" { BINARY (intop t i32_and i64_and) } - | (ixx as t)".or" { BINARY (intop t i32_or i64_or) } - | (ixx as t)".xor" { BINARY (intop t i32_xor i64_xor) } - | (ixx as t)".shl" { BINARY (intop t i32_shl i64_shl) } - | (ixx as t)".shr_s" { BINARY (intop t i32_shr_s i64_shr_s) } - | (ixx as t)".shr_u" { BINARY (intop t i32_shr_u i64_shr_u) } - | (ixx as t)".rotl" { BINARY (intop t i32_rotl i64_rotl) } - | (ixx as t)".rotr" { BINARY (intop t i32_rotr i64_rotr) } - | (fxx as t)".add" { BINARY (floatop t f32_add f64_add) } - | (fxx as t)".sub" { BINARY (floatop t f32_sub f64_sub) } - | (fxx as t)".mul" { BINARY (floatop t f32_mul f64_mul) } - | (fxx as t)".div" { BINARY (floatop t f32_div f64_div) } - | (fxx as t)".min" { BINARY (floatop t f32_min f64_min) } - | (fxx as t)".max" { BINARY (floatop t f32_max f64_max) } - | (fxx as t)".copysign" { BINARY (floatop t f32_copysign f64_copysign) } - - | (ixx as t)".eqz" { TEST (intop t i32_eqz i64_eqz) } - - | (ixx as t)".eq" { COMPARE (intop t i32_eq i64_eq) } - | (ixx as t)".ne" { COMPARE (intop t i32_ne i64_ne) } - | (ixx as t)".lt_s" { COMPARE (intop t i32_lt_s i64_lt_s) } - | (ixx as t)".lt_u" { COMPARE (intop t i32_lt_u i64_lt_u) } - | (ixx as t)".le_s" { COMPARE (intop t i32_le_s i64_le_s) } - | (ixx as t)".le_u" { COMPARE (intop t i32_le_u i64_le_u) } - | (ixx as t)".gt_s" { COMPARE (intop t i32_gt_s i64_gt_s) } - | (ixx as t)".gt_u" { COMPARE (intop t i32_gt_u i64_gt_u) } - | (ixx as t)".ge_s" { COMPARE (intop t i32_ge_s i64_ge_s) } - | (ixx as t)".ge_u" { COMPARE (intop t i32_ge_u i64_ge_u) } - | (fxx as t)".eq" { COMPARE (floatop t f32_eq f64_eq) } - | (fxx as t)".ne" { COMPARE (floatop t f32_ne f64_ne) } - | (fxx as t)".lt" { COMPARE (floatop t f32_lt f64_lt) } - | (fxx as t)".le" { COMPARE (floatop t f32_le f64_le) } - | (fxx as t)".gt" { COMPARE (floatop t f32_gt f64_gt) } - | (fxx as t)".ge" { COMPARE (floatop t f32_ge f64_ge) } - - | "i32.wrap_i64" { CONVERT i32_wrap_i64 } - | "i64.extend_i32_s" { CONVERT i64_extend_i32_s } - | "i64.extend_i32_u" { CONVERT i64_extend_i32_u } - | "f32.demote_f64" { CONVERT f32_demote_f64 } - | "f64.promote_f32" { CONVERT f64_promote_f32 } - | (ixx as t)".trunc_f32_s" - { CONVERT (intop t i32_trunc_f32_s i64_trunc_f32_s) } - | (ixx as t)".trunc_f32_u" - { CONVERT (intop t i32_trunc_f32_u i64_trunc_f32_u) } - | (ixx as t)".trunc_f64_s" - { CONVERT (intop t i32_trunc_f64_s i64_trunc_f64_s) } - | (ixx as t)".trunc_f64_u" - { CONVERT (intop t i32_trunc_f64_u i64_trunc_f64_u) } - | (ixx as t)".trunc_sat_f32_s" - { CONVERT (intop t i32_trunc_sat_f32_s i64_trunc_sat_f32_s) } - | (ixx as t)".trunc_sat_f32_u" - { CONVERT (intop t i32_trunc_sat_f32_u i64_trunc_sat_f32_u) } - | (ixx as t)".trunc_sat_f64_s" - { CONVERT (intop t i32_trunc_sat_f64_s i64_trunc_sat_f64_s) } - | (ixx as t)".trunc_sat_f64_u" - { CONVERT (intop t i32_trunc_sat_f64_u i64_trunc_sat_f64_u) } - | (fxx as t)".convert_i32_s" - { CONVERT (floatop t f32_convert_i32_s f64_convert_i32_s) } - | (fxx as t)".convert_i32_u" - { CONVERT (floatop t f32_convert_i32_u f64_convert_i32_u) } - | (fxx as t)".convert_i64_s" - { CONVERT (floatop t f32_convert_i64_s f64_convert_i64_s) } - | (fxx as t)".convert_i64_u" - { CONVERT (floatop t f32_convert_i64_u f64_convert_i64_u) } - | "f32.reinterpret_i32" { CONVERT f32_reinterpret_i32 } - | "f64.reinterpret_i64" { CONVERT f64_reinterpret_i64 } - | "i32.reinterpret_f32" { CONVERT i32_reinterpret_f32 } - | "i64.reinterpret_f64" { CONVERT i64_reinterpret_f64 } - - | "type" { TYPE } - | "func" { FUNC } - | "start" { START } - | "param" { PARAM } - | "result" { RESULT } - | "local" { LOCAL } - | "global" { GLOBAL } - | "table" { TABLE } - | "memory" { MEMORY } - | "elem" { ELEM } - | "data" { DATA } - | "declare" { DECLARE } - | "offset" { OFFSET } - | "item" { ITEM } - | "import" { IMPORT } - | "export" { EXPORT } - - | "module" { MODULE } - | "binary" { BIN } - | "quote" { QUOTE } - - | "script" { SCRIPT } - | "register" { REGISTER } - | "invoke" { INVOKE } - | "get" { GET } - | "assert_malformed" { ASSERT_MALFORMED } - | "assert_invalid" { ASSERT_INVALID } - | "assert_unlinkable" { ASSERT_UNLINKABLE } - | "assert_return" { ASSERT_RETURN } - | "assert_trap" { ASSERT_TRAP } - | "assert_exhaustion" { ASSERT_EXHAUSTION } - | "nan:canonical" { NAN Script.CanonicalNan } - | "nan:arithmetic" { NAN Script.ArithmeticNan } - | "input" { INPUT } - | "output" { OUTPUT } - - | vxxx".not" { VEC_UNARY v128_not } - | vxxx".and" { VEC_UNARY v128_and } - | vxxx".andnot" { VEC_UNARY v128_andnot } - | vxxx".or" { VEC_UNARY v128_or } - | vxxx".xor" { VEC_UNARY v128_xor } - | vxxx".bitselect" { VEC_TERNARY v128_bitselect } - | vxxx".any_true" { VEC_TEST (v128_any_true) } - - | (v128_shape as s)".neg" - { VEC_UNARY - (v128op s i8x16_neg i16x8_neg i32x4_neg i64x2_neg f32x4_neg f64x2_neg) } - | (v128_float_shape as s)".sqrt" - { VEC_UNARY (v128floatop s f32x4_sqrt f64x2_sqrt) } - | (v128_float_shape as s)".ceil" - { VEC_UNARY (v128floatop s f32x4_ceil f64x2_ceil) } - | (v128_float_shape as s)".floor" - { VEC_UNARY (v128floatop s f32x4_floor f64x2_floor) } - | (v128_float_shape as s)".trunc" - { VEC_UNARY (v128floatop s f32x4_trunc f64x2_trunc) } - | (v128_float_shape as s)".nearest" - { VEC_UNARY (v128floatop s f32x4_nearest f64x2_nearest) } - | (v128_shape as s)".abs" - { VEC_UNARY - (v128op s i8x16_abs i16x8_abs i32x4_abs i64x2_abs f32x4_abs f64x2_abs) } - | "i8x16.popcnt" { VEC_UNARY i8x16_popcnt } - | (v128_int_shape as s)".avgr_u" - { only ["i8x16"; "i16x8"] s lexbuf; - VEC_UNARY (v128intop s i8x16_avgr_u i16x8_avgr_u unreachable unreachable) } - | "i32x4.trunc_sat_f32x4_"(sign as s) - { VEC_UNARY (ext s i32x4_trunc_sat_f32x4_s i32x4_trunc_sat_f32x4_u) } - | "i32x4.trunc_sat_f64x2_"(sign as s)"_zero" - { VEC_UNARY (ext s i32x4_trunc_sat_f64x2_s_zero i32x4_trunc_sat_f64x2_u_zero) } - | "f64x2.promote_low_f32x4" - { VEC_UNARY f64x2_promote_low_f32x4 } - | "f32x4.demote_f64x2_zero" - { VEC_UNARY f32x4_demote_f64x2_zero } - | "f32x4.convert_i32x4_"(sign as s) - { VEC_UNARY (ext s f32x4_convert_i32x4_s f32x4_convert_i32x4_u) } - | "f64x2.convert_low_i32x4_"(sign as s) - { VEC_UNARY (ext s f64x2_convert_low_i32x4_s f64x2_convert_low_i32x4_u) } - | "i16x8.extadd_pairwise_i8x16_"(sign as s) - { VEC_UNARY (ext s i16x8_extadd_pairwise_i8x16_s i16x8_extadd_pairwise_i8x16_u) } - | "i32x4.extadd_pairwise_i16x8_"(sign as s) - { VEC_UNARY (ext s i32x4_extadd_pairwise_i16x8_s i32x4_extadd_pairwise_i16x8_u) } - - | (v128_shape as s)".eq" - { VEC_BINARY (v128op s i8x16_eq i16x8_eq i32x4_eq i64x2_eq f32x4_eq f64x2_eq) } - | (v128_shape as s)".ne" - { VEC_BINARY (v128op s i8x16_ne i16x8_ne i32x4_ne i64x2_ne f32x4_ne f64x2_ne) } - | (v128_int_shape as s)".lt_s" - { VEC_BINARY (v128intop s i8x16_lt_s i16x8_lt_s i32x4_lt_s i64x2_lt_s) } - | (v128_int_shape as s)".lt_u" - { except ["i64x2"] s lexbuf; - VEC_BINARY (v128intop s i8x16_lt_u i16x8_lt_u i32x4_lt_u unreachable) } - | (v128_int_shape as s)".le_s" - { VEC_BINARY (v128intop s i8x16_le_s i16x8_le_s i32x4_le_s i64x2_le_s) } - | (v128_int_shape as s)".le_u" - { except ["i64x2"] s lexbuf; - VEC_BINARY (v128intop s i8x16_le_u i16x8_le_u i32x4_le_u unreachable) } - | (v128_int_shape as s)".gt_s" - { VEC_BINARY (v128intop s i8x16_gt_s i16x8_gt_s i32x4_gt_s i64x2_gt_s) } - | (v128_int_shape as s)".gt_u" - { except ["i64x2"] s lexbuf; - VEC_BINARY (v128intop s i8x16_gt_u i16x8_gt_u i32x4_gt_u unreachable) } - | (v128_int_shape as s)".ge_s" - { VEC_BINARY (v128intop s i8x16_ge_s i16x8_ge_s i32x4_ge_s i64x2_ge_s) } - | (v128_int_shape as s)".ge_u" - { except ["i64x2"] s lexbuf; - VEC_BINARY (v128intop s i8x16_ge_u i16x8_ge_u i32x4_ge_u unreachable) } - | (v128_float_shape as s)".lt" { VEC_BINARY (v128floatop s f32x4_lt f64x2_lt) } - | (v128_float_shape as s)".le" { VEC_BINARY (v128floatop s f32x4_le f64x2_le) } - | (v128_float_shape as s)".gt" { VEC_BINARY (v128floatop s f32x4_gt f64x2_gt) } - | (v128_float_shape as s)".ge" { VEC_BINARY (v128floatop s f32x4_ge f64x2_ge) } - | "i8x16.swizzle" { VEC_BINARY i8x16_swizzle } - - | (v128_shape as s)".add" - { VEC_BINARY - (v128op s i8x16_add i16x8_add i32x4_add i64x2_add f32x4_add f64x2_add) } - | (v128_shape as s)".sub" - { VEC_BINARY - (v128op s i8x16_sub i16x8_sub i32x4_sub i64x2_sub f32x4_sub f64x2_sub) } - | (v128_shape as s)".min_s" - { only ["i8x16"; "i16x8"; "i32x4"] s lexbuf; - VEC_BINARY - (v128op s i8x16_min_s i16x8_min_s i32x4_min_s unreachable - unreachable unreachable) } - | (v128_shape as s)".min_u" - { only ["i8x16"; "i16x8"; "i32x4"] s lexbuf; - VEC_BINARY - (v128op s i8x16_min_u i16x8_min_u i32x4_min_u unreachable - unreachable unreachable) } - | (v128_shape as s)".max_s" - { only ["i8x16"; "i16x8"; "i32x4"] s lexbuf; - VEC_BINARY - (v128op s i8x16_max_s i16x8_max_s i32x4_max_s unreachable - unreachable unreachable) } - | (v128_shape as s)".max_u" - { only ["i8x16"; "i16x8"; "i32x4"] s lexbuf; - VEC_BINARY - (v128op s i8x16_max_u i16x8_max_u i32x4_max_u unreachable - unreachable unreachable) } - | (v128_shape as s)".mul" - { only ["i16x8"; "i32x4"; "i64x2"; "f32x4"; "f64x2"] s lexbuf; - VEC_BINARY - (v128op s unreachable i16x8_mul i32x4_mul i64x2_mul f32x4_mul f64x2_mul) } - | (v128_float_shape as s)".div" - { VEC_BINARY (v128floatop s f32x4_div f64x2_div) } - | (v128_float_shape as s)".min" - { VEC_BINARY (v128floatop s f32x4_min f64x2_min) } - | (v128_float_shape as s)".max" - { VEC_BINARY (v128floatop s f32x4_max f64x2_max) } - | (v128_float_shape as s)".pmin" - { VEC_BINARY (v128floatop s f32x4_pmin f64x2_pmin) } - | (v128_float_shape as s)".pmax" - { VEC_BINARY (v128floatop s f32x4_pmax f64x2_pmax) } - | "i8x16.add_sat_"(sign as s) - { VEC_BINARY (ext s i8x16_add_sat_s i8x16_add_sat_u) } - | "i8x16.sub_sat_"(sign as s) - { VEC_BINARY (ext s i8x16_sub_sat_s i8x16_sub_sat_u) } - | "i16x8.add_sat_"(sign as s) - { VEC_BINARY (ext s i16x8_add_sat_s i16x8_add_sat_u) } - | "i16x8.sub_sat_"(sign as s) - { VEC_BINARY (ext s i16x8_sub_sat_s i16x8_sub_sat_u) } - | "i32x4.dot_i16x8_s" - { VEC_BINARY i32x4_dot_i16x8_s } - | "i8x16.narrow_i16x8_"(sign as s) - { VEC_BINARY (ext s i8x16_narrow_i16x8_s i8x16_narrow_i16x8_u) } - | "i16x8.narrow_i32x4_"(sign as s) - { VEC_BINARY (ext s i16x8_narrow_i32x4_s i16x8_narrow_i32x4_u) } - | "i16x8.extend_low_i8x16_"(sign as s) - { VEC_UNARY (ext s i16x8_extend_low_i8x16_s i16x8_extend_low_i8x16_u) } - | "i16x8.extend_high_i8x16_"(sign as s) - { VEC_UNARY (ext s i16x8_extend_high_i8x16_s i16x8_extend_high_i8x16_u) } - | "i32x4.extend_low_i16x8_"(sign as s) - { VEC_UNARY (ext s i32x4_extend_low_i16x8_s i32x4_extend_low_i16x8_u) } - | "i32x4.extend_high_i16x8_"(sign as s) - { VEC_UNARY (ext s i32x4_extend_high_i16x8_s i32x4_extend_high_i16x8_u) } - | "i64x2.extend_low_i32x4_"(sign as s) - { VEC_UNARY (ext s i64x2_extend_low_i32x4_s i64x2_extend_low_i32x4_u) } - | "i64x2.extend_high_i32x4_"(sign as s) - { VEC_UNARY (ext s i64x2_extend_high_i32x4_s i64x2_extend_high_i32x4_u) } - | "i16x8.extmul_low_i8x16_"(sign as s) - { VEC_BINARY (ext s i16x8_extmul_low_i8x16_s i16x8_extmul_low_i8x16_u) } - | "i16x8.extmul_high_i8x16_"(sign as s) - { VEC_BINARY (ext s i16x8_extmul_high_i8x16_s i16x8_extmul_high_i8x16_u) } - | "i32x4.extmul_low_i16x8_"(sign as s) - { VEC_BINARY (ext s i32x4_extmul_low_i16x8_s i32x4_extmul_low_i16x8_u) } - | "i32x4.extmul_high_i16x8_"(sign as s) - { VEC_BINARY (ext s i32x4_extmul_high_i16x8_s i32x4_extmul_high_i16x8_u) } - | "i64x2.extmul_low_i32x4_"(sign as s) - { VEC_BINARY (ext s i64x2_extmul_low_i32x4_s i64x2_extmul_low_i32x4_u) } - | "i64x2.extmul_high_i32x4_"(sign as s) - { VEC_BINARY (ext s i64x2_extmul_high_i32x4_s i64x2_extmul_high_i32x4_u) } - | "i16x8.q15mulr_sat_s" - { VEC_BINARY i16x8_q15mulr_sat_s } - - | (v128_int_shape as s)".all_true" - { VEC_TEST - (v128intop s i8x16_all_true i16x8_all_true i32x4_all_true i64x2_all_true) } - | (v128_int_shape as s)".bitmask" - { VEC_BITMASK - (v128intop s i8x16_bitmask i16x8_bitmask i32x4_bitmask i64x2_bitmask) } - | (v128_int_shape as s)".shl" - { VEC_SHIFT (v128intop s i8x16_shl i16x8_shl i32x4_shl i64x2_shl) } - | (v128_int_shape as s)".shr_s" - { VEC_SHIFT (v128intop s i8x16_shr_s i16x8_shr_s i32x4_shr_s i64x2_shr_s) } - | (v128_int_shape as s)".shr_u" - { VEC_SHIFT (v128intop s i8x16_shr_u i16x8_shr_u i32x4_shr_u i64x2_shr_u) } - | "i8x16.shuffle" { VEC_SHUFFLE } - - | (v128_shape as s)".splat" - { VEC_SPLAT (v128op s i8x16_splat i16x8_splat i32x4_splat - i64x2_splat f32x4_splat f64x2_splat) } - | (v128_shape as s)".extract_lane" - { except ["i8x16"; "i16x8"] s lexbuf; - VEC_EXTRACT (fun i -> - v128op s - (fun _ -> unreachable) (fun _ -> unreachable) - i32x4_extract_lane i64x2_extract_lane - f32x4_extract_lane f64x2_extract_lane i) } - | (("i8x16"|"i16x8") as t)".extract_lane_"(sign as s) - { VEC_EXTRACT (fun i -> - if t = "i8x16" - then ext s i8x16_extract_lane_s i8x16_extract_lane_u i - else ext s i16x8_extract_lane_s i16x8_extract_lane_u i )} - | (v128_shape as s)".replace_lane" - { VEC_REPLACE - (v128op s i8x16_replace_lane i16x8_replace_lane i32x4_replace_lane - i64x2_replace_lane f32x4_replace_lane f64x2_replace_lane) } - - | name as s { VAR s } + | id as s { VAR s } | ";;"utf8_no_nl*eof { EOF } | ";;"utf8_no_nl*'\n' { Lexing.new_line lexbuf; token lexbuf } From b49ff52b89d4fb381bec93d5f1ce4b6d2e82c5fa Mon Sep 17 00:00:00 2001 From: aathan Date: Wed, 1 Jun 2022 10:48:13 -0700 Subject: [PATCH 085/181] [spec] Editorial nit (#1484) --- document/core/syntax/values.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/syntax/values.rst b/document/core/syntax/values.rst index c4e7f89c3..564ddc2d6 100644 --- a/document/core/syntax/values.rst +++ b/document/core/syntax/values.rst @@ -61,7 +61,7 @@ Different classes of *integers* with different value ranges are distinguished by \uN \\ \end{array} -The latter class defines *uninterpreted* integers, whose signedness interpretation can vary depending on context. +The class |iN| defines *uninterpreted* integers, whose signedness interpretation can vary depending on context. In the abstract syntax, they are represented as unsigned values. However, some operations :ref:`convert ` them to signed based on a two's complement interpretation. From d69f1d7ab6f2c7b8022c6df1ba6991b708ecd38f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 7 Jun 2022 19:18:46 +0200 Subject: [PATCH 086/181] [interpreter] Produce error messages in encoder (#1488) --- interpreter/binary/decode.ml | 224 ++++++++++---------- interpreter/binary/encode.ml | 382 ++++++++++++++++++++--------------- 2 files changed, 337 insertions(+), 269 deletions(-) diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 25c82de03..ab8f55967 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -14,6 +14,7 @@ let stream name bs = {name; bytes = bs; pos = ref 0} let len s = String.length s.bytes let pos s = !(s.pos) let eos s = (pos s = len s) +let reset s pos = s.pos := pos let check n s = if pos s + n > len s then raise EOS let skip n s = if n < 0 then raise EOS else check n s; s.pos := !(s.pos) + n @@ -26,15 +27,16 @@ let get_string n s = let i = pos s in skip n s; String.sub s.bytes i n (* Errors *) +open Source + module Code = Error.Make () exception Code = Code.Error let string_of_byte b = Printf.sprintf "%02x" b let string_of_multi n = Printf.sprintf "%02lx" n -let position s pos = Source.({file = s.name; line = -1; column = pos}) -let region s left right = - Source.({left = position s left; right = position s right}) +let position s pos = {file = s.name; line = -1; column = pos} +let region s left right = {left = position s left; right = position s right} let error s pos msg = raise (Code (region s pos pos, msg)) let require b s pos msg = if not b then error s pos msg @@ -55,70 +57,76 @@ let at f s = let left = pos s in let x = f s in let right = pos s in - Source.(x @@ region s left right) - + x @@ region s left right (* Generic values *) -let u8 s = +let byte s = get s -let u16 s = - let lo = u8 s in - let hi = u8 s in +let word16 s = + let lo = byte s in + let hi = byte s in hi lsl 8 + lo -let u32 s = - let lo = Int32.of_int (u16 s) in - let hi = Int32.of_int (u16 s) in +let word32 s = + let lo = Int32.of_int (word16 s) in + let hi = Int32.of_int (word16 s) in Int32.(add lo (shift_left hi 16)) -let u64 s = - let lo = I64_convert.extend_i32_u (u32 s) in - let hi = I64_convert.extend_i32_u (u32 s) in +let word64 s = + let lo = I64_convert.extend_i32_u (word32 s) in + let hi = I64_convert.extend_i32_u (word32 s) in Int64.(add lo (shift_left hi 32)) -let rec vuN n s = +let rec uN n s = require (n > 0) s (pos s) "integer representation too long"; - let b = u8 s in + let b = byte s in require (n >= 7 || b land 0x7f < 1 lsl n) s (pos s - 1) "integer too large"; let x = Int64.of_int (b land 0x7f) in - if b land 0x80 = 0 then x else Int64.(logor x (shift_left (vuN (n - 7) s) 7)) + if b land 0x80 = 0 then x else Int64.(logor x (shift_left (uN (n - 7) s) 7)) -let rec vsN n s = +let rec sN n s = require (n > 0) s (pos s) "integer representation too long"; - let b = u8 s in + let b = byte s in let mask = (-1 lsl (n - 1)) land 0x7f in require (n >= 7 || b land mask = 0 || b land mask = mask) s (pos s - 1) "integer too large"; let x = Int64.of_int (b land 0x7f) in if b land 0x80 = 0 then (if b land 0x40 = 0 then x else Int64.(logor x (logxor (-1L) 0x7fL))) - else Int64.(logor x (shift_left (vsN (n - 7) s) 7)) - -let vu1 s = Int64.to_int (vuN 1 s) -let vu32 s = Int64.to_int32 (vuN 32 s) -let vs7 s = Int64.to_int (vsN 7 s) -let vs32 s = Int64.to_int32 (vsN 32 s) -let vs33 s = I32_convert.wrap_i64 (vsN 33 s) -let vs64 s = vsN 64 s -let f32 s = F32.of_bits (u32 s) -let f64 s = F64.of_bits (u64 s) + else Int64.(logor x (shift_left (sN (n - 7) s) 7)) + +let u1 s = Int64.to_int (uN 1 s) +let u32 s = Int64.to_int32 (uN 32 s) +let s7 s = Int64.to_int (sN 7 s) +let s32 s = Int64.to_int32 (sN 32 s) +let s33 s = I32_convert.wrap_i64 (sN 33 s) +let s64 s = sN 64 s +let f32 s = F32.of_bits (word32 s) +let f64 s = F64.of_bits (word64 s) let v128 s = V128.of_bits (get_string (Types.vec_size Types.V128Type) s) let len32 s = let pos = pos s in - let n = vu32 s in + let n = u32 s in if I32.le_u n (Int32.of_int (len s - pos)) then Int32.to_int n else error s pos "length out of bounds" -let bool s = (vu1 s = 1) +let bool s = (u1 s = 1) let string s = let n = len32 s in get_string n s let rec list f n s = if n = 0 then [] else let x = f s in x :: list f (n - 1) s let opt f b s = if b then Some (f s) else None let vec f s = let n = len32 s in list f n s +let rec either fs s = + match fs with + | [] -> assert false + | [f] -> f s + | f::fs' -> + let pos = pos s in try f s with Code _ -> reset s pos; either fs' s + let name s = let pos = pos s in try Utf8.decode (string s) with Utf8.Utf8 -> @@ -137,7 +145,7 @@ let sized f s = open Types let num_type s = - match vs7 s with + match s7 s with | -0x01 -> I32Type | -0x02 -> I64Type | -0x03 -> F32Type @@ -145,48 +153,50 @@ let num_type s = | _ -> error s (pos s - 1) "malformed number type" let vec_type s = - match vs7 s with + match s7 s with | -0x05 -> V128Type | _ -> error s (pos s - 1) "malformed vector type" let ref_type s = - match vs7 s with + match s7 s with | -0x10 -> FuncRefType | -0x11 -> ExternRefType | _ -> error s (pos s - 1) "malformed reference type" let value_type s = - match peek s with - | Some n when n >= ((-0x04) land 0x7f) -> NumType (num_type s) - | Some n when n >= ((-0x0f) land 0x7f) -> VecType (vec_type s) - | _ -> RefType (ref_type s) + either [ + (fun s -> NumType (num_type s)); + (fun s -> VecType (vec_type s)); + (fun s -> RefType (ref_type s)); + ] s let result_type s = vec value_type s + let func_type s = - match vs7 s with + match s7 s with | -0x20 -> - let ins = result_type s in - let out = result_type s in - FuncType (ins, out) + let ts1 = result_type s in + let ts2 = result_type s in + FuncType (ts1, ts2) | _ -> error s (pos s - 1) "malformed function type" -let limits vu s = +let limits uN s = let has_max = bool s in - let min = vu s in - let max = opt vu has_max s in + let min = uN s in + let max = opt uN has_max s in {min; max} let table_type s = let t = ref_type s in - let lim = limits vu32 s in + let lim = limits u32 s in TableType (lim, t) let memory_type s = - let lim = limits vu32 s in + let lim = limits u32 s in MemoryType lim let mutability s = - match u8 s with + match byte s with | 0 -> Immutable | 1 -> Mutable | _ -> error s (pos s - 1) "malformed mutability" @@ -197,31 +207,33 @@ let global_type s = GlobalType (t, mut) -(* Decode instructions *) +(* Instructions *) open Ast open Operators -let var s = vu32 s +let var s = u32 s -let op s = u8 s +let op s = byte s let end_ s = expect 0x0b s "END opcode expected" let memop s = let pos = pos s in - let flags = vu32 s in + let flags = u32 s in require (I32.lt_u flags 0x80l) s pos "malformed memop flags"; let has_var = Int32.logand flags 0x40l <> 0l in let x = if has_var then at var s else Source.(0l @@ no_region) in let align = Int32.(to_int (logand flags 0x3fl)) in - let offset = vu32 s in + let offset = u32 s in x, align, offset let block_type s = - match peek s with - | Some 0x40 -> skip 1 s; ValBlockType None - | Some b when b land 0xc0 = 0x40 -> ValBlockType (Some (value_type s)) - | _ -> VarBlockType (at vs33 s) + let p = pos s in + either [ + (fun s -> let x = at s33 s in require (x.it >= 0l) s p ""; VarBlockType x); + (fun s -> expect 0x40 s ""; ValBlockType None); + (fun s -> ValBlockType (Some (value_type s))); + ] s let rec instr s = let pos = pos s in @@ -316,8 +328,8 @@ let rec instr s = | 0x3f -> memory_size (at var s) | 0x40 -> memory_grow (at var s) - | 0x41 -> i32_const (at vs32 s) - | 0x42 -> i64_const (at vs64 s) + | 0x41 -> i32_const (at s32 s) + | 0x42 -> i64_const (at s64 s) | 0x43 -> f32_const (at f32 s) | 0x44 -> f64_const (at f64 s) @@ -468,7 +480,7 @@ let rec instr s = | 0xd2 -> ref_func (at var s) | 0xfc as b -> - (match vu32 s with + (match u32 s with | 0x00l -> i32_trunc_sat_f32_s | 0x01l -> i32_trunc_sat_f32_u | 0x02l -> i32_trunc_sat_f64_s @@ -506,7 +518,7 @@ let rec instr s = ) | 0xfd -> - (match vu32 s with + (match u32 s with | 0x00l -> let x, a, o = memop s in v128_load x a o | 0x01l -> let x, a, o = memop s in v128_load8x8_s x a o | 0x02l -> let x, a, o = memop s in v128_load8x8_u x a o @@ -520,7 +532,7 @@ let rec instr s = | 0x0al -> let x, a, o = memop s in v128_load64_splat x a o | 0x0bl -> let x, a, o = memop s in v128_store x a o | 0x0cl -> v128_const (at v128 s) - | 0x0dl -> i8x16_shuffle (List.init 16 (fun x -> u8 s)) + | 0x0dl -> i8x16_shuffle (List.init 16 (fun _ -> byte s)) | 0x0el -> i8x16_swizzle | 0x0fl -> i8x16_splat | 0x10l -> i16x8_splat @@ -528,20 +540,20 @@ let rec instr s = | 0x12l -> i64x2_splat | 0x13l -> f32x4_splat | 0x14l -> f64x2_splat - | 0x15l -> let i = u8 s in i8x16_extract_lane_s i - | 0x16l -> let i = u8 s in i8x16_extract_lane_u i - | 0x17l -> let i = u8 s in i8x16_replace_lane i - | 0x18l -> let i = u8 s in i16x8_extract_lane_s i - | 0x19l -> let i = u8 s in i16x8_extract_lane_u i - | 0x1al -> let i = u8 s in i16x8_replace_lane i - | 0x1bl -> let i = u8 s in i32x4_extract_lane i - | 0x1cl -> let i = u8 s in i32x4_replace_lane i - | 0x1dl -> let i = u8 s in i64x2_extract_lane i - | 0x1el -> let i = u8 s in i64x2_replace_lane i - | 0x1fl -> let i = u8 s in f32x4_extract_lane i - | 0x20l -> let i = u8 s in f32x4_replace_lane i - | 0x21l -> let i = u8 s in f64x2_extract_lane i - | 0x22l -> let i = u8 s in f64x2_replace_lane i + | 0x15l -> let i = byte s in i8x16_extract_lane_s i + | 0x16l -> let i = byte s in i8x16_extract_lane_u i + | 0x17l -> let i = byte s in i8x16_replace_lane i + | 0x18l -> let i = byte s in i16x8_extract_lane_s i + | 0x19l -> let i = byte s in i16x8_extract_lane_u i + | 0x1al -> let i = byte s in i16x8_replace_lane i + | 0x1bl -> let i = byte s in i32x4_extract_lane i + | 0x1cl -> let i = byte s in i32x4_replace_lane i + | 0x1dl -> let i = byte s in i64x2_extract_lane i + | 0x1el -> let i = byte s in i64x2_replace_lane i + | 0x1fl -> let i = byte s in f32x4_extract_lane i + | 0x20l -> let i = byte s in f32x4_replace_lane i + | 0x21l -> let i = byte s in f64x2_extract_lane i + | 0x22l -> let i = byte s in f64x2_replace_lane i | 0x23l -> i8x16_eq | 0x24l -> i8x16_ne | 0x25l -> i8x16_lt_s @@ -593,35 +605,35 @@ let rec instr s = | 0x53l -> v128_any_true | 0x54l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load8_lane x a o lane | 0x55l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load16_lane x a o lane | 0x56l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load32_lane x a o lane | 0x57l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_load64_lane x a o lane | 0x58l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store8_lane x a o lane | 0x59l -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store16_lane x a o lane | 0x5al -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store32_lane x a o lane | 0x5bl -> let x, a, o = memop s in - let lane = u8 s in + let lane = byte s in v128_store64_lane x a o lane | 0x5cl -> let x, a, o = memop s in v128_load32_zero x a o | 0x5dl -> let x, a, o = memop s in v128_load64_zero x a o @@ -779,7 +791,7 @@ and instr_block' s es = | _ -> let pos = pos s in let e' = instr s in - instr_block' s (Source.(e' @@ region s pos pos) :: es) + instr_block' s ((e' @@ region s pos pos) :: es) let const s = let c = at instr_block s in @@ -811,7 +823,7 @@ let id s = let section_with_size tag f default s = match id s with - | Some tag' when tag' = tag -> ignore (u8 s); sized f s + | Some tag' when tag' = tag -> skip 1 s; sized f s | _ -> default let section tag f default s = @@ -829,7 +841,7 @@ let type_section s = (* Import section *) let import_desc s = - match u8 s with + match byte s with | 0x00 -> FuncImport (at var s) | 0x01 -> TableImport (table_type s) | 0x02 -> MemoryImport (memory_type s) @@ -886,7 +898,7 @@ let global_section s = (* Export section *) let export_desc s = - match u8 s with + match byte s with | 0x00 -> FuncExport (at var s) | 0x01 -> TableExport (at var s) | 0x02 -> MemoryExport (at var s) @@ -915,20 +927,23 @@ let start_section s = (* Code section *) let local s = - let n = vu32 s in + let n = u32 s in let t = value_type s in n, t -let code _ s = +let locals s = let pos = pos s in let nts = vec local s in let ns = List.map (fun (n, _) -> I64_convert.extend_i32_u n) nts in require (I64.lt_u (List.fold_left I64.add 0L ns) 0x1_0000_0000L) s pos "too many locals"; - let locals = List.flatten (List.map (Lib.Fun.uncurry Lib.List32.make) nts) in + List.flatten (List.map (Lib.Fun.uncurry Lib.List32.make) nts) + +let code _ s = + let locals = locals s in let body = instr_block s in end_ s; - {locals; body; ftype = Source.((-1l) @@ Source.no_region)} + {locals; body; ftype = -1l @@ no_region} let code_section s = section `CodeSection (vec (at (sized code))) [] s @@ -945,7 +960,7 @@ let active s = Active {index; offset} let active_zero s = - let index = Source.(0l @@ Source.no_region) in + let index = 0l @@ no_region in let offset = const s in Active {index; offset} @@ -954,15 +969,15 @@ let declarative s = let elem_index s = let x = at var s in - [Source.(ref_func x @@ x.at)] + [ref_func x @@ x.at] let elem_kind s = - match u8 s with + match byte s with | 0x00 -> FuncRefType | _ -> error s (pos s - 1) "malformed element kind" let elem s = - match vu32 s with + match u32 s with | 0x00l -> let emode = at active_zero s in let einit = vec (at elem_index) s in @@ -1010,7 +1025,7 @@ let elem_section s = (* Data section *) let data s = - match vu32 s with + match u32 s with | 0x00l -> let dmode = at active_zero s in let dinit = string s in @@ -1032,7 +1047,7 @@ let data_section s = (* DataCount section *) let data_count s = - Some (vu32 s) + Some (u32 s) let data_count_section s = section `DataCountSection data_count None s @@ -1062,9 +1077,9 @@ let rec iterate f s = if f s <> None then iterate f s let magic = 0x6d736100l let module_ s = - let header = u32 s in + let header = word32 s in require (header = magic) s 0 "magic header not detected"; - let version = u32 s in + let version = word32 s in require (version = Encode.version) s 4 "unknown binary version"; iterate custom_section s; let types = type_section s in @@ -1100,17 +1115,16 @@ let module_ s = List.for_all Free.(fun f -> (func f).datas = Set.empty) func_bodies) s (len s) "data count section required"; let funcs = - List.map2 Source.(fun t f -> {f.it with ftype = t} @@ f.at) - func_types func_bodies + List.map2 (fun t f -> {f.it with ftype = t} @@ f.at) func_types func_bodies in {types; tables; memories; globals; funcs; imports; exports; elems; datas; start} let decode name bs = at module_ (stream name bs) let all_custom tag s = - let header = u32 s in + let header = word32 s in require (header = magic) s 0 "magic header not detected"; - let version = u32 s in + let version = word32 s in require (version = Encode.version) s 4 "unknown binary version"; let rec collect () = iterate non_custom_section s; diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 37f658d2a..40a4ec022 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -1,4 +1,4 @@ -(* Version *) +(* Binary format version *) let version = 1l @@ -8,6 +8,8 @@ let version = 1l module Code = Error.Make () exception Code = Code.Error +let error = Code.error + (* Encoding stream *) @@ -35,50 +37,50 @@ module E (S : sig val stream : stream end) = struct let s = S.stream + (* Generic values *) - let u8 i = put s (Char.chr (i land 0xff)) - let u16 i = u8 (i land 0xff); u8 (i lsr 8) - let u32 i = - Int32.(u16 (to_int (logand i 0xffffl)); - u16 (to_int (shift_right i 16))) - let u64 i = - Int64.(u32 (to_int32 (logand i 0xffffffffL)); - u32 (to_int32 (shift_right i 32))) + let byte i = put s (Char.chr (i land 0xff)) + let word16 i = byte (i land 0xff); byte (i lsr 8) + let word32 i = + Int32.(word16 (to_int (logand i 0xffffl)); + word16 (to_int (shift_right i 16))) + let word64 i = + Int64.(word32 (to_int32 (logand i 0xffffffffL)); + word32 (to_int32 (shift_right i 32))) - let rec vu64 i = + let rec u64 i = let b = Int64.(to_int (logand i 0x7fL)) in - if 0L <= i && i < 128L then u8 b - else (u8 (b lor 0x80); vu64 (Int64.shift_right_logical i 7)) + if 0L <= i && i < 128L then byte b + else (byte (b lor 0x80); u64 (Int64.shift_right_logical i 7)) - let rec vs64 i = + let rec s64 i = let b = Int64.(to_int (logand i 0x7fL)) in - if -64L <= i && i < 64L then u8 b - else (u8 (b lor 0x80); vs64 (Int64.shift_right i 7)) - - let vu1 i = vu64 Int64.(logand (of_int i) 1L) - let vu32 i = vu64 Int64.(logand (of_int32 i) 0xffffffffL) - let vs7 i = vs64 (Int64.of_int i) - let vs32 i = vs64 (Int64.of_int32 i) - let vs33 i = vs64 (I64_convert.extend_i32_s i) - let f32 x = u32 (F32.to_bits x) - let f64 x = u64 (F64.to_bits x) + if -64L <= i && i < 64L then byte b + else (byte (b lor 0x80); s64 (Int64.shift_right i 7)) + + let u1 i = u64 Int64.(logand (of_int i) 1L) + let u32 i = u64 Int64.(logand (of_int32 i) 0xffffffffL) + let s7 i = s64 (Int64.of_int i) + let s32 i = s64 (Int64.of_int32 i) + let s33 i = s64 (I64_convert.extend_i32_s i) + let f32 x = word32 (F32.to_bits x) + let f64 x = word64 (F64.to_bits x) let v128 v = String.iter (put s) (V128.to_bits v) let len i = if Int32.to_int (Int32.of_int i) <> i then - Code.error Source.no_region - "cannot encode length with more than 32 bit"; - vu32 (Int32.of_int i) + Code.error Source.no_region "length out of bounds"; + u32 (Int32.of_int i) - let bool b = vu1 (if b then 1 else 0) + let bool b = u1 (if b then 1 else 0) let string bs = len (String.length bs); put_string s bs let name n = string (Utf8.encode n) let list f xs = List.iter f xs let opt f xo = Lib.Option.app f xo let vec f xs = len (List.length xs); list f xs - let gap32 () = let p = pos s in u32 0l; u8 0; p + let gap32 () = let p = pos s in word32 0l; byte 0; p let patch_gap32 p n = assert (n <= 0x0fff_ffff); (* Strings cannot excess 2G anyway *) let lsb i = Char.chr (i land 0xff) in @@ -88,22 +90,23 @@ struct patch s (p + 3) (lsb ((n lsr 21) lor 0x80)); patch s (p + 4) (lsb (n lsr 28)) + (* Types *) open Types let num_type = function - | I32Type -> vs7 (-0x01) - | I64Type -> vs7 (-0x02) - | F32Type -> vs7 (-0x03) - | F64Type -> vs7 (-0x04) + | I32Type -> s7 (-0x01) + | I64Type -> s7 (-0x02) + | F32Type -> s7 (-0x03) + | F64Type -> s7 (-0x04) let vec_type = function - | V128Type -> vs7 (-0x05) + | V128Type -> s7 (-0x05) let ref_type = function - | FuncRefType -> vs7 (-0x10) - | ExternRefType -> vs7 (-0x11) + | FuncRefType -> s7 (-0x10) + | ExternRefType -> s7 (-0x11) let value_type = function | NumType t -> num_type t @@ -112,49 +115,51 @@ struct let func_type = function | FuncType (ts1, ts2) -> - vs7 (-0x20); vec value_type ts1; vec value_type ts2 + s7 (-0x20); vec value_type ts1; vec value_type ts2 + let limits vu {min; max} = bool (max <> None); vu min; opt vu max let table_type = function - | TableType (lim, t) -> ref_type t; limits vu32 lim + | TableType (lim, t) -> ref_type t; limits u32 lim let memory_type = function - | MemoryType lim -> limits vu32 lim + | MemoryType lim -> limits u32 lim let mutability = function - | Immutable -> u8 0 - | Mutable -> u8 1 + | Immutable -> byte 0 + | Mutable -> byte 1 let global_type = function | GlobalType (t, mut) -> value_type t; mutability mut - (* Expressions *) + + (* Instructions *) open Source open Ast open Values open V128 - let op n = u8 n - let vecop n = op 0xfd; vu32 n + let op n = byte n + let vecop n = op 0xfd; u32 n let end_ () = op 0x0b - let var x = vu32 x.it + let var x = u32 x.it let memop x {align; offset; _} = let has_var = x.it <> 0l in let flags = Int32.(logor (of_int align) (if has_var then 0x40l else 0x00l)) in - vu32 flags; + u32 flags; if has_var then var x; - vu32 offset + u32 offset let block_type = function - | VarBlockType x -> vs33 x.it - | ValBlockType None -> vs7 (-0x40) + | ValBlockType None -> s33 (-0x40l) | ValBlockType (Some t) -> value_type t + | VarBlockType x -> s33 x.it let rec instr e = match e.it with @@ -187,12 +192,12 @@ struct | TableGet x -> op 0x25; var x | TableSet x -> op 0x26; var x - | TableSize x -> op 0xfc; vu32 0x10l; var x - | TableGrow x -> op 0xfc; vu32 0x0fl; var x - | TableFill x -> op 0xfc; vu32 0x11l; var x - | TableCopy (x, y) -> op 0xfc; vu32 0x0el; var x; var y - | TableInit (x, y) -> op 0xfc; vu32 0x0cl; var y; var x - | ElemDrop x -> op 0xfc; vu32 0x0dl; var x + | TableSize x -> op 0xfc; u32 0x10l; var x + | TableGrow x -> op 0xfc; u32 0x0fl; var x + | TableFill x -> op 0xfc; u32 0x11l; var x + | TableCopy (x, y) -> op 0xfc; u32 0x0el; var x; var y + | TableInit (x, y) -> op 0xfc; u32 0x0cl; var y; var x + | ElemDrop x -> op 0xfc; u32 0x0dl; var x | Load (x, ({ty = I32Type; pack = None; _} as mo)) -> op 0x28; memop x mo @@ -210,8 +215,8 @@ struct op 0x2e; memop x mo | Load (x, ({ty = I32Type; pack = Some (Pack16, ZX); _} as mo)) -> op 0x2f; memop x mo - | Load (x, {ty = I32Type; pack = Some ((Pack32 | Pack64), _); _}) -> - assert false + | Load (x, {ty = I32Type; pack = Some (Pack32, _); _}) -> + error e.at "illegal instruction i32.load32" | Load (x, ({ty = I64Type; pack = Some (Pack8, SX); _} as mo)) -> op 0x30; memop x mo | Load (x, ({ty = I64Type; pack = Some (Pack8, ZX); _} as mo)) -> @@ -224,10 +229,10 @@ struct op 0x34; memop x mo | Load (x, ({ty = I64Type; pack = Some (Pack32, ZX); _} as mo)) -> op 0x35; memop x mo - | Load (x, {ty = I64Type; pack = Some (Pack64, _); _}) -> - assert false + | Load (x, {ty = I32Type | I64Type; pack = Some (Pack64, _); _}) -> + error e.at "illegal instruction ixx.load64" | Load (x, {ty = F32Type | F64Type; pack = Some _; _}) -> - assert false + error e.at "illegal instruction fxx.loadN" | Store (x, ({ty = I32Type; pack = None; _} as mo)) -> op 0x36; memop x mo @@ -242,65 +247,65 @@ struct | Store (x, ({ty = I32Type; pack = Some Pack16; _} as mo)) -> op 0x3b; memop x mo | Store (x, {ty = I32Type; pack = Some (Pack32 | Pack64); _}) -> - assert false + error e.at "illegal instruction i32.store32" | Store (x, ({ty = I64Type; pack = Some Pack8; _} as mo)) -> op 0x3c; memop x mo | Store (x, ({ty = I64Type; pack = Some Pack16; _} as mo)) -> op 0x3d; memop x mo | Store (x, ({ty = I64Type; pack = Some Pack32; _} as mo)) -> op 0x3e; memop x mo - | Store (x, {ty = I64Type; pack = Some Pack64; _}) -> - assert false + | Store (x, {ty = I32Type | I64Type; pack = Some Pack64; _}) -> + error e.at "illegal instruction ixx.store64" | Store (x, {ty = F32Type | F64Type; pack = Some _; _}) -> - assert false + error e.at "illegal instruction fxx.storeN" - | LoadVec (x, ({ty = V128Type; pack = None; _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = None; _} as mo)) -> vecop 0x00l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack8x8, SX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack8x8, SX)); _} as mo)) -> vecop 0x01l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack8x8, ZX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack8x8, ZX)); _} as mo)) -> vecop 0x02l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack16x4, SX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack16x4, SX)); _} as mo)) -> vecop 0x03l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack16x4, ZX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack16x4, ZX)); _} as mo)) -> vecop 0x04l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack32x2, SX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack32x2, SX)); _} as mo)) -> vecop 0x05l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack32x2, ZX)); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtLane (Pack32x2, ZX)); _} as mo)) -> vecop 0x06l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack8, ExtSplat); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack8, ExtSplat); _} as mo)) -> vecop 0x07l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack16, ExtSplat); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack16, ExtSplat); _} as mo)) -> vecop 0x08l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack32, ExtSplat); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack32, ExtSplat); _} as mo)) -> vecop 0x09l; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtSplat); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtSplat); _} as mo)) -> vecop 0x0al; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack32, ExtZero); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack32, ExtZero); _} as mo)) -> vecop 0x5cl; memop x mo - | LoadVec (x, ({ty = V128Type; pack = Some (Pack64, ExtZero); _} as mo)) -> + | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtZero); _} as mo)) -> vecop 0x5dl; memop x mo - | LoadVec _ -> assert false + error e.at "illegal instruction v128.loadNxM_" - | LoadVecLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> + | VecLoadLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> vecop 0x54l; memop x mo; u8 i; - | LoadVecLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> + | VecLoadLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> vecop 0x55l; memop x mo; u8 i; - | LoadVecLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> + | VecLoadLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> vecop 0x56l; memop x mo; u8 i; - | LoadVecLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> + | VecLoadLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> vecop 0x57l; memop x mo; u8 i; - | StoreVec (x, ({ty = V128Type; _} as mo)) -> + | VecStore (x, ({ty = V128Type; _} as mo)) -> vecop 0x0bl; memop x mo - | StoreVecLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> + | VecStoreLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> vecop 0x58l; memop x mo; u8 i; - | StoreVecLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> + | VecStoreLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> vecop 0x59l; memop x mo; u8 i; - | StoreVecLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> + | VecStoreLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> vecop 0x5al; memop x mo; u8 i; - | StoreVecLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> + | VecStoreLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> vecop 0x5bl; memop x mo; u8 i; | MemorySize x -> op 0x3f; var x @@ -314,8 +319,8 @@ struct | RefIsNull -> op 0xd1 | RefFunc x -> op 0xd2; var x - | Const {it = I32 c; _} -> op 0x41; vs32 c - | Const {it = I64 c; _} -> op 0x42; vs64 c + | Const {it = I32 c; _} -> op 0x41; s32 c + | Const {it = I64 c; _} -> op 0x42; s64 c | Const {it = F32 c; _} -> op 0x43; f32 c | Const {it = F64 c; _} -> op 0x44; f64 c @@ -364,7 +369,8 @@ struct | Unary (I32 I32Op.Popcnt) -> op 0x69 | Unary (I32 (I32Op.ExtendS Pack8)) -> op 0xc0 | Unary (I32 (I32Op.ExtendS Pack16)) -> op 0xc1 - | Unary (I32 (I32Op.ExtendS (Pack32 | Pack64))) -> assert false + | Unary (I32 (I32Op.ExtendS (Pack32 | Pack64))) -> + error e.at "illegal instruction i32.extendN_s" | Unary (I64 I64Op.Clz) -> op 0x79 | Unary (I64 I64Op.Ctz) -> op 0x7a @@ -372,7 +378,8 @@ struct | Unary (I64 (I64Op.ExtendS Pack8)) -> op 0xc2 | Unary (I64 (I64Op.ExtendS Pack16)) -> op 0xc3 | Unary (I64 (I64Op.ExtendS Pack32)) -> op 0xc4 - | Unary (I64 (I64Op.ExtendS Pack64)) -> assert false + | Unary (I64 (I64Op.ExtendS Pack64)) -> + error e.at "illegal instruction i64.extend64_s" | Unary (F32 F32Op.Abs) -> op 0x8b | Unary (F32 F32Op.Neg) -> op 0x8c @@ -438,37 +445,41 @@ struct | Binary (F64 F64Op.Max) -> op 0xa5 | Binary (F64 F64Op.CopySign) -> op 0xa6 - | Convert (I32 I32Op.ExtendSI32) -> assert false - | Convert (I32 I32Op.ExtendUI32) -> assert false + | Convert (I32 I32Op.ExtendSI32) -> + error e.at "illegal instruction i32.extend_i32_s" + | Convert (I32 I32Op.ExtendUI32) -> + error e.at "illegal instruction i32.extend_i32_u" | Convert (I32 I32Op.WrapI64) -> op 0xa7 | Convert (I32 I32Op.TruncSF32) -> op 0xa8 | Convert (I32 I32Op.TruncUF32) -> op 0xa9 | Convert (I32 I32Op.TruncSF64) -> op 0xaa | Convert (I32 I32Op.TruncUF64) -> op 0xab - | Convert (I32 I32Op.TruncSatSF32) -> op 0xfc; vu32 0x00l - | Convert (I32 I32Op.TruncSatUF32) -> op 0xfc; vu32 0x01l - | Convert (I32 I32Op.TruncSatSF64) -> op 0xfc; vu32 0x02l - | Convert (I32 I32Op.TruncSatUF64) -> op 0xfc; vu32 0x03l + | Convert (I32 I32Op.TruncSatSF32) -> op 0xfc; u32 0x00l + | Convert (I32 I32Op.TruncSatUF32) -> op 0xfc; u32 0x01l + | Convert (I32 I32Op.TruncSatSF64) -> op 0xfc; u32 0x02l + | Convert (I32 I32Op.TruncSatUF64) -> op 0xfc; u32 0x03l | Convert (I32 I32Op.ReinterpretFloat) -> op 0xbc | Convert (I64 I64Op.ExtendSI32) -> op 0xac | Convert (I64 I64Op.ExtendUI32) -> op 0xad - | Convert (I64 I64Op.WrapI64) -> assert false + | Convert (I64 I64Op.WrapI64) -> + error e.at "illegal instruction i64.wrap_i64" | Convert (I64 I64Op.TruncSF32) -> op 0xae | Convert (I64 I64Op.TruncUF32) -> op 0xaf | Convert (I64 I64Op.TruncSF64) -> op 0xb0 | Convert (I64 I64Op.TruncUF64) -> op 0xb1 - | Convert (I64 I64Op.TruncSatSF32) -> op 0xfc; vu32 0x04l - | Convert (I64 I64Op.TruncSatUF32) -> op 0xfc; vu32 0x05l - | Convert (I64 I64Op.TruncSatSF64) -> op 0xfc; vu32 0x06l - | Convert (I64 I64Op.TruncSatUF64) -> op 0xfc; vu32 0x07l + | Convert (I64 I64Op.TruncSatSF32) -> op 0xfc; u32 0x04l + | Convert (I64 I64Op.TruncSatUF32) -> op 0xfc; u32 0x05l + | Convert (I64 I64Op.TruncSatSF64) -> op 0xfc; u32 0x06l + | Convert (I64 I64Op.TruncSatUF64) -> op 0xfc; u32 0x07l | Convert (I64 I64Op.ReinterpretFloat) -> op 0xbd | Convert (F32 F32Op.ConvertSI32) -> op 0xb2 | Convert (F32 F32Op.ConvertUI32) -> op 0xb3 | Convert (F32 F32Op.ConvertSI64) -> op 0xb4 | Convert (F32 F32Op.ConvertUI64) -> op 0xb5 - | Convert (F32 F32Op.PromoteF32) -> assert false + | Convert (F32 F32Op.PromoteF32) -> + error e.at "illegal instruction f32.promote_f32" | Convert (F32 F32Op.DemoteF64) -> op 0xb6 | Convert (F32 F32Op.ReinterpretInt) -> op 0xbe @@ -477,7 +488,8 @@ struct | Convert (F64 F64Op.ConvertSI64) -> op 0xb9 | Convert (F64 F64Op.ConvertUI64) -> op 0xba | Convert (F64 F64Op.PromoteF32) -> op 0xbb - | Convert (F64 F64Op.DemoteF64) -> assert false + | Convert (F64 F64Op.DemoteF64) -> + error e.at "illegal instruction f64.demote_f64" | Convert (F64 F64Op.ReinterpretInt) -> op 0xbf | VecConst {it = V128 c; _} -> vecop 0x0cl; v128 c @@ -493,13 +505,16 @@ struct | VecUnary (V128 (I8x16 V128Op.Popcnt)) -> vecop 0x62l | VecUnary (V128 (I16x8 V128Op.Abs)) -> vecop 0x80l | VecUnary (V128 (I16x8 V128Op.Neg)) -> vecop 0x81l - | VecUnary (V128 (I16x8 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I16x8 V128Op.Popcnt)) -> + error e.at "illegal instruction i16x8.popcnt" | VecUnary (V128 (I32x4 V128Op.Abs)) -> vecop 0xa0l | VecUnary (V128 (I32x4 V128Op.Neg)) -> vecop 0xa1l - | VecUnary (V128 (I32x4 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I32x4 V128Op.Popcnt)) -> + error e.at "illegal instruction i32x4.popcnt" | VecUnary (V128 (I64x2 V128Op.Abs)) -> vecop 0xc0l | VecUnary (V128 (I64x2 V128Op.Neg)) -> vecop 0xc1l - | VecUnary (V128 (I64x2 V128Op.Popcnt)) -> assert false + | VecUnary (V128 (I64x2 V128Op.Popcnt)) -> + error e.at "illegal instruction i64x2.popcnt" | VecUnary (V128 (F32x4 V128Op.Ceil)) -> vecop 0x67l | VecUnary (V128 (F32x4 V128Op.Floor)) -> vecop 0x68l | VecUnary (V128 (F32x4 V128Op.Trunc)) -> vecop 0x69l @@ -548,13 +563,17 @@ struct | VecCompare (V128 (I64x2 V128Op.Eq)) -> vecop 0xd6l | VecCompare (V128 (I64x2 V128Op.Ne)) -> vecop 0xd7l | VecCompare (V128 (I64x2 V128Op.LtS)) -> vecop 0xd8l - | VecCompare (V128 (I64x2 V128Op.LtU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.LtU)) -> + error e.at "illegal instruction i64x2.lt_u" | VecCompare (V128 (I64x2 V128Op.GtS)) -> vecop 0xd9l - | VecCompare (V128 (I64x2 V128Op.GtU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.GtU)) -> + error e.at "illegal instruction i64x2.gt_u" | VecCompare (V128 (I64x2 V128Op.LeS)) -> vecop 0xdal - | VecCompare (V128 (I64x2 V128Op.LeU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.LeU)) -> + error e.at "illegal instruction i64x2.le_u" | VecCompare (V128 (I64x2 V128Op.GeS)) -> vecop 0xdbl - | VecCompare (V128 (I64x2 V128Op.GeU)) -> assert false + | VecCompare (V128 (I64x2 V128Op.GeU)) -> + error e.at "illegal instruction i64x2.ge_u" | VecCompare (V128 (F32x4 V128Op.Eq)) -> vecop 0x41l | VecCompare (V128 (F32x4 V128Op.Ne)) -> vecop 0x42l | VecCompare (V128 (F32x4 V128Op.Lt)) -> vecop 0x43l @@ -568,7 +587,7 @@ struct | VecCompare (V128 (F64x2 V128Op.Le)) -> vecop 0x4bl | VecCompare (V128 (F64x2 V128Op.Ge)) -> vecop 0x4cl - | VecBinary (V128 (I8x16 (V128Op.Shuffle is))) -> vecop 0x0dl; List.iter u8 is + | VecBinary (V128 (I8x16 (V128Op.Shuffle is))) -> vecop 0x0dl; List.iter byte is | VecBinary (V128 (I8x16 V128Op.Swizzle)) -> vecop 0x0el | VecBinary (V128 (I8x16 V128Op.NarrowS)) -> vecop 0x65l | VecBinary (V128 (I8x16 V128Op.NarrowU)) -> vecop 0x66l @@ -637,16 +656,19 @@ struct | VecBinary (V128 (F64x2 V128Op.Max)) -> vecop 0xf5l | VecBinary (V128 (F64x2 V128Op.Pmin)) -> vecop 0xf6l | VecBinary (V128 (F64x2 V128Op.Pmax)) -> vecop 0xf7l - | VecBinary (V128 _) -> assert false + | VecBinary (V128 _) -> + error e.at "illegal binary vector instruction" - | VecConvert (V128 (I8x16 _)) -> assert false + | VecConvert (V128 (I8x16 _)) -> + error e.at "illegal i8x16 conversion instruction" | VecConvert (V128 (I16x8 V128Op.ExtendLowS)) -> vecop 0x87l | VecConvert (V128 (I16x8 V128Op.ExtendHighS)) -> vecop 0x88l | VecConvert (V128 (I16x8 V128Op.ExtendLowU)) -> vecop 0x89l | VecConvert (V128 (I16x8 V128Op.ExtendHighU)) -> vecop 0x8al | VecConvert (V128 (I16x8 V128Op.ExtAddPairwiseS)) -> vecop 0x7cl | VecConvert (V128 (I16x8 V128Op.ExtAddPairwiseU)) -> vecop 0x7dl - | VecConvert (V128 (I16x8 _)) -> assert false + | VecConvert (V128 (I16x8 _)) -> + error e.at "illegal i16x8 conversion instruction" | VecConvert (V128 (I32x4 V128Op.ExtendLowS)) -> vecop 0xa7l | VecConvert (V128 (I32x4 V128Op.ExtendHighS)) -> vecop 0xa8l | VecConvert (V128 (I32x4 V128Op.ExtendLowU)) -> vecop 0xa9l @@ -661,12 +683,15 @@ struct | VecConvert (V128 (I64x2 V128Op.ExtendHighS)) -> vecop 0xc8l | VecConvert (V128 (I64x2 V128Op.ExtendLowU)) -> vecop 0xc9l | VecConvert (V128 (I64x2 V128Op.ExtendHighU)) -> vecop 0xcal - | VecConvert (V128 (I64x2 _)) -> assert false + | VecConvert (V128 (I64x2 _)) -> + error e.at "illegal i64x2 conversion instruction" | VecConvert (V128 (F32x4 V128Op.DemoteZeroF64x2)) -> vecop 0x5el - | VecConvert (V128 (F32x4 V128Op.PromoteLowF32x4)) -> assert false + | VecConvert (V128 (F32x4 V128Op.PromoteLowF32x4)) -> + error e.at "illegal instruction f32x4.promote_low_f32x4" | VecConvert (V128 (F32x4 V128Op.ConvertSI32x4)) -> vecop 0xfal | VecConvert (V128 (F32x4 V128Op.ConvertUI32x4)) -> vecop 0xfbl - | VecConvert (V128 (F64x2 V128Op.DemoteZeroF64x2)) -> assert false + | VecConvert (V128 (F64x2 V128Op.DemoteZeroF64x2)) -> + error e.at "illegal instruction f64x2.demote_zero_f64x2" | VecConvert (V128 (F64x2 V128Op.PromoteLowF32x4)) -> vecop 0x5fl | VecConvert (V128 (F64x2 V128Op.ConvertSI32x4)) -> vecop 0xfel | VecConvert (V128 (F64x2 V128Op.ConvertUI32x4)) -> vecop 0xffl @@ -706,49 +731,54 @@ struct | VecSplat (V128 ((F32x4 V128Op.Splat))) -> vecop 0x13l | VecSplat (V128 ((F64x2 V128Op.Splat))) -> vecop 0x14l - | VecExtract (V128 (I8x16 (V128Op.Extract (i, SX)))) -> vecop 0x15l; u8 i - | VecExtract (V128 (I8x16 (V128Op.Extract (i, ZX)))) -> vecop 0x16l; u8 i - | VecExtract (V128 (I16x8 (V128Op.Extract (i, SX)))) -> vecop 0x18l; u8 i - | VecExtract (V128 (I16x8 (V128Op.Extract (i, ZX)))) -> vecop 0x19l; u8 i - | VecExtract (V128 (I32x4 (V128Op.Extract (i, ())))) -> vecop 0x1bl; u8 i - | VecExtract (V128 (I64x2 (V128Op.Extract (i, ())))) -> vecop 0x1dl; u8 i - | VecExtract (V128 (F32x4 (V128Op.Extract (i, ())))) -> vecop 0x1fl; u8 i - | VecExtract (V128 (F64x2 (V128Op.Extract (i, ())))) -> vecop 0x21l; u8 i - - | VecReplace (V128 (I8x16 (V128Op.Replace i))) -> vecop 0x17l; u8 i - | VecReplace (V128 (I16x8 (V128Op.Replace i))) -> vecop 0x1al; u8 i - | VecReplace (V128 (I32x4 (V128Op.Replace i))) -> vecop 0x1cl; u8 i - | VecReplace (V128 (I64x2 (V128Op.Replace i))) -> vecop 0x1el; u8 i - | VecReplace (V128 (F32x4 (V128Op.Replace i))) -> vecop 0x20l; u8 i - | VecReplace (V128 (F64x2 (V128Op.Replace i))) -> vecop 0x22l; u8 i + | VecExtract (V128 (I8x16 (V128Op.Extract (i, SX)))) -> vecop 0x15l; byte i + | VecExtract (V128 (I8x16 (V128Op.Extract (i, ZX)))) -> vecop 0x16l; byte i + | VecExtract (V128 (I16x8 (V128Op.Extract (i, SX)))) -> vecop 0x18l; byte i + | VecExtract (V128 (I16x8 (V128Op.Extract (i, ZX)))) -> vecop 0x19l; byte i + | VecExtract (V128 (I32x4 (V128Op.Extract (i, ())))) -> vecop 0x1bl; byte i + | VecExtract (V128 (I64x2 (V128Op.Extract (i, ())))) -> vecop 0x1dl; byte i + | VecExtract (V128 (F32x4 (V128Op.Extract (i, ())))) -> vecop 0x1fl; byte i + | VecExtract (V128 (F64x2 (V128Op.Extract (i, ())))) -> vecop 0x21l; byte i + + | VecReplace (V128 (I8x16 (V128Op.Replace i))) -> vecop 0x17l; byte i + | VecReplace (V128 (I16x8 (V128Op.Replace i))) -> vecop 0x1al; byte i + | VecReplace (V128 (I32x4 (V128Op.Replace i))) -> vecop 0x1cl; byte i + | VecReplace (V128 (I64x2 (V128Op.Replace i))) -> vecop 0x1el; byte i + | VecReplace (V128 (F32x4 (V128Op.Replace i))) -> vecop 0x20l; byte i + | VecReplace (V128 (F64x2 (V128Op.Replace i))) -> vecop 0x22l; byte i let const c = list instr c.it; end_ () + (* Sections *) let section id f x needed = if needed then begin - u8 id; + byte id; let g = gap32 () in let p = pos s in f x; patch_gap32 g (pos s - p) end + (* Type section *) + let type_ t = func_type t.it let type_section ts = section 1 (vec type_) ts (ts <> []) + (* Import section *) + let import_desc d = match d.it with - | FuncImport x -> u8 0x00; var x - | TableImport t -> u8 0x01; table_type t - | MemoryImport t -> u8 0x02; memory_type t - | GlobalImport t -> u8 0x03; global_type t + | FuncImport x -> byte 0x00; var x + | TableImport t -> byte 0x01; table_type t + | MemoryImport t -> byte 0x02; memory_type t + | GlobalImport t -> byte 0x03; global_type t let import im = let {module_name; item_name; idesc} = im.it in @@ -757,13 +787,17 @@ struct let import_section ims = section 2 (vec import) ims (ims <> []) + (* Function section *) + let func f = var f.it.ftype let func_section fs = section 3 (vec func) fs (fs <> []) + (* Table section *) + let table tab = let {ttype} = tab.it in table_type ttype @@ -771,7 +805,9 @@ struct let table_section tabs = section 4 (vec table) tabs (tabs <> []) + (* Memory section *) + let memory mem = let {mtype} = mem.it in memory_type mtype @@ -779,7 +815,9 @@ struct let memory_section mems = section 5 (vec memory) mems (mems <> []) + (* Global section *) + let global g = let {gtype; ginit} = g.it in global_type gtype; const ginit @@ -787,13 +825,15 @@ struct let global_section gs = section 6 (vec global) gs (gs <> []) + (* Export section *) + let export_desc d = match d.it with - | FuncExport x -> u8 0; var x - | TableExport x -> u8 1; var x - | MemoryExport x -> u8 2; var x - | GlobalExport x -> u8 3; var x + | FuncExport x -> byte 0; var x + | TableExport x -> byte 1; var x + | MemoryExport x -> byte 2; var x + | GlobalExport x -> byte 3; var x let export ex = let {name = n; edesc} = ex.it in @@ -802,7 +842,9 @@ struct let export_section exs = section 7 (vec export) exs (exs <> []) + (* Start section *) + let start st = let {sfunc} = st.it in var sfunc @@ -810,20 +852,22 @@ struct let start_section xo = section 8 (opt start) xo (xo <> None) + (* Code section *) - let compress ts = + + let local (t, n) = len n; value_type t + + let locals locs = let combine t = function | (t', n) :: ts when t = t' -> (t, n + 1) :: ts | ts -> (t, 1) :: ts - in List.fold_right combine ts [] - - let local (t, n) = len n; value_type t + in vec local (List.fold_right combine locs []) let code f = - let {locals; body; _} = f.it in + let {locals = locs; body; _} = f.it in let g = gap32 () in let p = pos s in - vec local (compress locals); + locals locs; list instr body; end_ (); patch_gap32 g (pos s - p) @@ -831,13 +875,15 @@ struct let code_section fs = section 10 (vec code) fs (fs <> []) + (* Element section *) + let is_elem_kind = function | FuncRefType -> true | _ -> false let elem_kind = function - | FuncRefType -> u8 0x00 + | FuncRefType -> byte 0x00 | _ -> assert false let is_elem_index e = @@ -855,49 +901,55 @@ struct if is_elem_kind etype && List.for_all is_elem_index einit then match emode.it with | Passive -> - vu32 0x01l; elem_kind etype; vec elem_index einit - | Active {index; offset} when index.it = 0l && etype = FuncRefType -> - vu32 0x00l; const offset; vec elem_index einit + u32 0x01l; elem_kind etype; vec elem_index einit + | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + u32 0x00l; const offset; vec elem_index einit | Active {index; offset} -> - vu32 0x02l; + u32 0x02l; var index; const offset; elem_kind etype; vec elem_index einit | Declarative -> - vu32 0x03l; elem_kind etype; vec elem_index einit + u32 0x03l; elem_kind etype; vec elem_index einit else match emode.it with | Passive -> - vu32 0x05l; ref_type etype; vec const einit - | Active {index; offset} when index.it = 0l && etype = FuncRefType -> - vu32 0x04l; const offset; vec const einit + u32 0x05l; ref_type etype; vec const einit + | Active {index; offset} when index.it = 0l && is_elem_kind etype -> + u32 0x04l; const offset; vec const einit | Active {index; offset} -> - vu32 0x06l; var index; const offset; ref_type etype; vec const einit + u32 0x06l; var index; const offset; ref_type etype; vec const einit | Declarative -> - vu32 0x07l; ref_type etype; vec const einit + u32 0x07l; ref_type etype; vec const einit let elem_section elems = section 9 (vec elem) elems (elems <> []) + (* Data section *) + let data seg = let {dinit; dmode} = seg.it in match dmode.it with | Passive -> - vu32 0x01l; string dinit + u32 0x01l; string dinit | Active {index; offset} when index.it = 0l -> - vu32 0x00l; const offset; string dinit + u32 0x00l; const offset; string dinit | Active {index; offset} -> - vu32 0x02l; var index; const offset; string dinit + u32 0x02l; var index; const offset; string dinit | Declarative -> - assert false + error dmode.at "illegal declarative data segment" let data_section datas = section 11 (vec data) datas (datas <> []) + (* Data count section *) + let data_count_section datas m = section 12 len (List.length datas) Free.((module_ m).datas <> Set.empty) + (* Custom section *) + let custom (n, bs) = name n; put_string s bs @@ -905,10 +957,12 @@ struct let custom_section n bs = section 0 custom (n, bs) true + (* Module *) + let module_ m = - u32 0x6d736100l; - u32 version; + word32 0x6d736100l; + word32 version; type_section m.it.types; import_section m.it.imports; func_section m.it.funcs; From 49ba1d9b5e50e407f6fc57c0bf4c1fd094f25e45 Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:21:14 -0700 Subject: [PATCH 087/181] [spec] Add missing close paren on table abbreviation (#1486) Also remove an unnecessary space in the previous table abbreviation. --- document/core/text/modules.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/core/text/modules.rst b/document/core/text/modules.rst index 0964dfdaa..fde59878a 100644 --- a/document/core/text/modules.rst +++ b/document/core/text/modules.rst @@ -290,7 +290,7 @@ An :ref:`element segment ` can be given inline with a table definitio .. math:: \begin{array}{llclll} \production{module field} & - \text{(}~\text{table}~~\Tid^?~~\Treftype~~\text{(}~\text{elem}~~\expr^n{:}\Tvec(\Telemexpr)~\text{)}~~\text{)} \quad\equiv \\ & \qquad + \text{(}~\text{table}~~\Tid^?~~\Treftype~~\text{(}~\text{elem}~~\expr^n{:}\Tvec(\Telemexpr)~\text{)}~\text{)} \quad\equiv \\ & \qquad \text{(}~\text{table}~~\Tid'~~n~~n~~\Treftype~\text{)} \\ & \qquad \text{(}~\text{elem}~~\text{(}~\text{table}~~\Tid'~\text{)}~~\text{(}~\text{i32.const}~~\text{0}~\text{)}~~\Tvec(\Telemexpr)~\text{)} \\ & \qquad\qquad @@ -300,7 +300,7 @@ An :ref:`element segment ` can be given inline with a table definitio .. math:: \begin{array}{llclll} \production{module field} & - \text{(}~\text{table}~~\Tid^?~~\Treftype~~\text{(}~\text{elem}~~x^n{:}\Tvec(\Tfuncidx)~\text{)} \quad\equiv \\ & \qquad + \text{(}~\text{table}~~\Tid^?~~\Treftype~~\text{(}~\text{elem}~~x^n{:}\Tvec(\Tfuncidx)~\text{)}~\text{)} \quad\equiv \\ & \qquad \text{(}~\text{table}~~\Tid'~~n~~n~~\Treftype~\text{)} \\ & \qquad \text{(}~\text{elem}~~\text{(}~\text{table}~~\Tid'~\text{)}~~\text{(}~\text{i32.const}~~\text{0}~\text{)}~~\Tvec(\Tfuncidx)~\text{)} \\ & \qquad\qquad From 8abd2a544d0ebdace6af6a0f494fe79d0bbdc9b4 Mon Sep 17 00:00:00 2001 From: Alberto Fiori <9143617+fifofefe@users.noreply.github.com> Date: Wed, 8 Jun 2022 15:40:16 +0200 Subject: [PATCH 088/181] [spec] Remove outdated note (#1491) --- document/core/exec/runtime.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index e5c97ed78..149a53a8b 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -84,10 +84,6 @@ It is either a sequence of :ref:`values ` or a :ref:`trap Date: Thu, 9 Jun 2022 12:25:43 +0200 Subject: [PATCH 089/181] [interpreter] Factor data and element segments into abstract types (#1492) --- interpreter/exec/eval.ml | 23 ++++++++++++----------- interpreter/exec/ixx.ml | 4 ++-- interpreter/runtime/data.ml | 7 +++++++ interpreter/runtime/data.mli | 7 +++++++ interpreter/runtime/elem.ml | 7 +++++++ interpreter/runtime/elem.mli | 9 +++++++++ interpreter/runtime/instance.ml | 8 ++++---- 7 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 interpreter/runtime/data.ml create mode 100644 interpreter/runtime/data.mli create mode 100644 interpreter/runtime/elem.ml create mode 100644 interpreter/runtime/elem.mli diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 6cda240e2..943515dfb 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -134,7 +134,7 @@ let mem_oob frame x i n = let data_oob frame x i n = I64.gt_u (I64.add (I64_convert.extend_i32_u i) (I64_convert.extend_i32_u n)) - (I64.of_int_u (String.length !(data frame.inst x))) + (Data.size (data frame.inst x)) let table_oob frame x i n = I64.gt_u (I64.add (I64_convert.extend_i32_u i) (I64_convert.extend_i32_u n)) @@ -142,7 +142,7 @@ let table_oob frame x i n = let elem_oob frame x i n = I64.gt_u (I64.add (I64_convert.extend_i32_u i) (I64_convert.extend_i32_u n)) - (I64.of_int_u (List.length !(elem frame.inst x))) + (I64_convert.extend_i32_u (Elem.size (elem frame.inst x))) let rec step (c : config) : config = let {frame; code = vs, es; _} = c in @@ -302,10 +302,10 @@ let rec step (c : config) : config = else if n = 0l then vs', [] else - let seg = !(elem frame.inst y) in + let seg = elem frame.inst y in vs', List.map (at e.at) [ Plain (Const (I32 d @@ e.at)); - Refer (List.nth seg (Int32.to_int s)); + Refer (Elem.load seg s); Plain (TableSet x); Plain (Const (I32 (I32.add d 1l) @@ e.at)); Plain (Const (I32 (I32.add s 1l) @@ e.at)); @@ -315,7 +315,7 @@ let rec step (c : config) : config = | ElemDrop x, vs -> let seg = elem frame.inst x in - seg := []; + Elem.drop seg; vs, [] | Load (x, {offset; ty; pack; _}), Num (I32 i) :: vs' -> @@ -465,11 +465,12 @@ let rec step (c : config) : config = else if n = 0l then vs', [] else - let seg = !(data frame.inst y) in - let b = Int32.of_int (Char.code seg.[Int32.to_int s]) in + let seg = data frame.inst y in + let a = I64_convert.extend_i32_u s in + let b = Data.load seg a in vs', List.map (at e.at) [ Plain (Const (I32 d @@ e.at)); - Plain (Const (I32 b @@ e.at)); + Plain (Const (I32 (I32.of_int_u (Char.code b)) @@ e.at)); Plain (Store (x, {ty = I32Type; align = 0; offset = 0l; pack = Some Pack8})); Plain (Const (I32 (I32.add d 1l) @@ e.at)); @@ -480,7 +481,7 @@ let rec step (c : config) : config = | DataDrop x, vs -> let seg = data frame.inst x in - seg := ""; + Data.drop seg; vs, [] | RefNull t, vs' -> @@ -715,11 +716,11 @@ let create_export (inst : module_inst) (ex : export) : export_inst = let create_elem (inst : module_inst) (seg : elem_segment) : elem_inst = let {etype; einit; _} = seg.it in - ref (List.map (fun c -> as_ref (eval_const inst c)) einit) + Elem.alloc (List.map (fun c -> as_ref (eval_const inst c)) einit) let create_data (inst : module_inst) (seg : data_segment) : data_inst = let {dinit; _} = seg.it in - ref dinit + Data.alloc dinit let add_import (m : module_) (ext : extern) (im : import) (inst : module_inst) diff --git a/interpreter/exec/ixx.ml b/interpreter/exec/ixx.ml index 18f8b7d06..0a13d22b6 100644 --- a/interpreter/exec/ixx.ml +++ b/interpreter/exec/ixx.ml @@ -30,8 +30,8 @@ sig val of_int : int -> t val to_int : t -> int - val of_int64: int64 -> t - val to_int64: t -> int64 + val of_int64 : int64 -> t + val to_int64 : t -> int64 val to_string : t -> string val to_hex_string : t -> string diff --git a/interpreter/runtime/data.ml b/interpreter/runtime/data.ml new file mode 100644 index 000000000..e73cd2f31 --- /dev/null +++ b/interpreter/runtime/data.ml @@ -0,0 +1,7 @@ +type data = string ref +type t = data + +let alloc bs = ref bs +let size seg = I64.of_int_u (String.length !seg) +let load seg i = (!seg).[Int64.to_int i] +let drop seg = seg := "" diff --git a/interpreter/runtime/data.mli b/interpreter/runtime/data.mli new file mode 100644 index 000000000..498c45149 --- /dev/null +++ b/interpreter/runtime/data.mli @@ -0,0 +1,7 @@ +type data +type t = data + +val alloc : string -> data +val size : data -> Memory.address +val load : data -> Memory.address -> char +val drop : data -> unit diff --git a/interpreter/runtime/elem.ml b/interpreter/runtime/elem.ml new file mode 100644 index 000000000..fe8997482 --- /dev/null +++ b/interpreter/runtime/elem.ml @@ -0,0 +1,7 @@ +type elem = Values.ref_ list ref +type t = elem + +let alloc rs = ref rs +let size seg = Lib.List32.length !seg +let load seg i = Lib.List32.nth !seg i +let drop seg = seg := [] diff --git a/interpreter/runtime/elem.mli b/interpreter/runtime/elem.mli new file mode 100644 index 000000000..5eb0c0e56 --- /dev/null +++ b/interpreter/runtime/elem.mli @@ -0,0 +1,9 @@ +open Values + +type elem +type t = elem + +val alloc : ref_ list -> elem +val size : elem -> Table.size +val load : elem -> Table.index -> ref_ +val drop : elem -> unit diff --git a/interpreter/runtime/instance.ml b/interpreter/runtime/instance.ml index 4d4fece07..0ae878c37 100644 --- a/interpreter/runtime/instance.ml +++ b/interpreter/runtime/instance.ml @@ -7,18 +7,18 @@ type module_inst = tables : table_inst list; memories : memory_inst list; globals : global_inst list; - exports : export_inst list; elems : elem_inst list; datas : data_inst list; + exports : export_inst list; } and func_inst = module_inst ref Func.t and table_inst = Table.t and memory_inst = Memory.t and global_inst = Global.t +and elem_inst = Elem.t +and data_inst = Data.t and export_inst = Ast.name * extern -and elem_inst = Values.ref_ list ref -and data_inst = string ref and extern = | ExternFunc of func_inst @@ -55,7 +55,7 @@ let () = let empty_module_inst = { types = []; funcs = []; tables = []; memories = []; globals = []; - exports = []; elems = []; datas = [] } + elems = []; datas = []; exports = [] } let extern_type_of = function | ExternFunc func -> ExternFuncType (Func.type_of func) From 3358264ad1e7afa277d1c9c4e9eaca19ab76ab2c Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 13 Jun 2022 03:04:08 -0700 Subject: [PATCH 090/181] [spec] Update note on module initialization trapping (#1493) --- document/core/exec/modules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index 0e8c9d50a..99eeb2756 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -596,7 +596,7 @@ Given a :ref:`store ` :math:`S`, a :ref:`module ` : Instantiation checks that the module is :ref:`valid ` and the provided imports :ref:`match ` the declared types, and may *fail* with an error otherwise. -Instantiation can also result in a :ref:`trap ` from executing the start function. +Instantiation can also result in a :ref:`trap ` from initializing a table or memory from an active segment or from executing the start function. It is up to the :ref:`embedder ` to define how such conditions are reported. 1. If :math:`\module` is not :ref:`valid `, then: From b4e714fdb91c2c30588164f6e4b7c4154a6f89fe Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 27 Jun 2022 12:32:27 +0200 Subject: [PATCH 091/181] [spec] Add note about control stack invariant to algorithm (#1498) --- document/core/appendix/algorithm.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst index 72c83ea56..9b2c9a5b8 100644 --- a/document/core/appendix/algorithm.rst +++ b/document/core/appendix/algorithm.rst @@ -140,6 +140,8 @@ The type of the :ref:`label ` associated with a control frame is e Finally, the current frame can be marked as unreachable. In that case, all existing operand types are purged from the value stack, in order to allow for the :ref:`stack-polymorphism ` logic in :code:`pop_val` to take effect. +Because every function has an implicit outermost label that corresponds to an implicit block frame, +it is an invariant of the validation algorithm that there always is at least one frame on the control stack when validating an instruction, and hence, `ctrls[0]` is always defined. .. note:: Even with the unreachable flag set, consecutive operands are still pushed to and popped from the operand stack. From bce1aae2f851b5b93ba75161c2563b26a7d7bb84 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 28 Jun 2022 22:50:26 +0200 Subject: [PATCH 092/181] [spec] Tweak tokenisation for text format (#1499) --- document/core/text/lexical.rst | 8 +- interpreter/text/lexer.mll | 10 +- test/core/tokens.wast | 274 +++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 8 deletions(-) create mode 100644 test/core/tokens.wast diff --git a/document/core/text/lexical.rst b/document/core/text/lexical.rst index a3b4529d3..0c40a58d1 100644 --- a/document/core/text/lexical.rst +++ b/document/core/text/lexical.rst @@ -50,7 +50,7 @@ The character stream in the source text is divided, from left to right, into a s (\text{a} ~|~ \dots ~|~ \text{z})~\Tidchar^\ast \qquad (\mbox{if occurring as a literal terminal in the grammar}) \\ \production{reserved} & \Treserved &::=& - \Tidchar^+ \\ + (\Tidchar ~|~ \Tstring)^+ \\ \end{array} Tokens are formed from the input character stream according to the *longest match* rule. @@ -63,9 +63,9 @@ The set of *keyword* tokens is defined implicitly, by all occurrences of a :ref: Any token that does not fall into any of the other categories is considered *reserved*, and cannot occur in source text. .. note:: - The effect of defining the set of reserved tokens is that all tokens must be separated by either parentheses or :ref:`white space `. - For example, :math:`\text{0\$x}` is a single reserved token. - Consequently, it is not recognized as two separate tokens :math:`\text{0}` and :math:`\text{\$x}`, but instead disallowed. + The effect of defining the set of reserved tokens is that all tokens must be separated by either parentheses, :ref:`white space `, or :ref:`comments `. + For example, :math:`\text{0\$x}` is a single reserved token, as is :math:`\text{"a""b"}`. + Consequently, they are not recognized as two separate tokens :math:`\text{0}` and :math:`\text{\$x}`, or :math:`"a"` and :math:`"b"`, respectively, but instead disallowed. This property of tokenization is not affected by the fact that the definition of reserved tokens overlaps with other token classes. diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 161520e0a..d9a12b5d2 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -62,8 +62,9 @@ let symbol = ['+''-''*''/''\\''^''~''=''<''>''!''?''@''#''$''%''&''|'':''`''.''\''] let space = [' ''\t''\n''\r'] +let control = ['\x00'-'\x1f'] # space let ascii = ['\x00'-'\x7f'] -let ascii_no_nl = ['\x00'-'\x09''\x0b'-'\x7f'] +let ascii_no_nl = ascii # '\x0a' let utf8cont = ['\x80'-'\xbf'] let utf8enc = ['\xc2'-'\xdf'] utf8cont @@ -103,7 +104,7 @@ let name = idchar+ let id = '$' name let keyword = ['a'-'z'] (letter | digit | '_' | '.' | ':')+ -let reserved = name | ',' | ';' | '[' | ']' | '{' | '}' +let reserved = (idchar | string)+ | ',' | ';' | '[' | ']' | '{' | '}' let ixx = "i" ("32" | "64") let fxx = "f" ("32" | "64") @@ -705,13 +706,14 @@ rule token = parse | eof { EOF } | reserved { unknown lexbuf } - | utf8 { error lexbuf "malformed operator" } + | control { error lexbuf "misplaced control character" } + | utf8enc { error lexbuf "misplaced unicode character" } | _ { error lexbuf "malformed UTF-8 encoding" } and comment start = parse | ";)" { () } | "(;" { comment (Lexing.lexeme_start_p lexbuf) lexbuf; comment start lexbuf } | '\n' { Lexing.new_line lexbuf; comment start lexbuf } + | utf8_no_nl { comment start lexbuf } | eof { error_nest start lexbuf "unclosed comment" } - | utf8 { comment start lexbuf } | _ { error lexbuf "malformed UTF-8 encoding" } diff --git a/test/core/tokens.wast b/test/core/tokens.wast new file mode 100644 index 000000000..4e785154e --- /dev/null +++ b/test/core/tokens.wast @@ -0,0 +1,274 @@ +;; Tokens can be delimited by parentheses + +(module + (func(nop)) +) +(module + (func (nop)nop) +) +(module + (func nop(nop)) +) +(module + (func(nop)(nop)) +) +(module + (func $f(nop)) +) +(module + (func br 0(nop)) +) +(module + (table 1 funcref) + (func) + (elem (i32.const 0)0) +) +(module + (table 1 funcref) + (func $f) + (elem (i32.const 0)$f) +) +(module + (memory 1) + (data (i32.const 0)"a") +) +(module + (import "spectest" "print"(func)) +) + + +;; Tokens can be delimited by comments + +(module + (func;;bla + ) +) +(module + (func (nop);;bla + ) +) +(module + (func nop;;bla + ) +) +(module + (func $f;;bla + ) +) +(module + (func br 0;;bla + ) +) +(module + (data "a";;bla + ) +) + + +;; Space required between symbols and non-parenthesis tokens + +(module + (func (block $l (i32.const 0) (br_table 0 $l))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table 0$l)))" + ) + "unknown operator" +) + +(module + (func (block $l (i32.const 0) (br_table $l 0))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $l0)))" + ) + "unknown label" +) + +(module + (func (block $l (i32.const 0) (br_table $l $l))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $l$l)))" + ) + "unknown label" +) + +(module + (func (block $l0 (i32.const 0) (br_table $l0))) +) +(module + (func (block $l$l (i32.const 0) (br_table $l$l))) +) + + +;; Space required between strings and non-parenthesis tokens + +(module + (data "a") +) +(assert_malformed + (module quote + "(data\"a\")" + ) + "unknown operator" +) + +(module + (data $l "a") +) +(assert_malformed + (module quote + "(data $l\"a\")" + ) + "unknown operator" +) + +(module + (data $l " a") +) +(assert_malformed + (module quote + "(data $l\" a\")" + ) + "unknown operator" +) + +(module + (data $l "a ") +) +(assert_malformed + (module quote + "(data $l\"a \")" + ) + "unknown operator" +) + +(module + (data $l "a " "b") +) +(assert_malformed + (module quote + "(data $l\"a \"\"b\")" + ) + "unknown operator" +) + +(module + (data $l "") +) +(assert_malformed + (module quote + "(data $l\"\")" + ) + "unknown operator" +) + +(module + (data $l " ") +) +(assert_malformed + (module quote + "(data $l\" \")" + ) + "unknown operator" +) + +(module + (data $l " ") +) +(assert_malformed + (module quote + "(data $l\" \")" + ) + "unknown operator" +) + +(module + (data "a" "b") +) +(assert_malformed + (module quote + "(data \"a\"\"b\")" + ) + "unknown operator" +) + +(module + (data "a" " b") +) +(assert_malformed + (module quote + "(data \"a\"\" b\")" + ) + "unknown operator" +) + +(module + (data "a " "b") +) +(assert_malformed + (module quote + "(data \"a \"\"b\")" + ) + "unknown operator" +) + +(module + (data "" "") +) +(assert_malformed + (module quote + "(data \"\"\"\")" + ) + "unknown operator" +) + +(module + (data "" " ") +) +(assert_malformed + (module quote + "(data \"\"\" \")" + ) + "unknown operator" +) + +(module + (data " " "") +) +(assert_malformed + (module quote + "(data \" \"\"\")" + ) + "unknown operator" +) + + +(assert_malformed + (module quote + "(func \"a\"x)" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func \"a\"0)" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func 0\"a\")" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func \"a\"$x)" + ) + "unknown operator" +) From 91f3966adf926c832b78fa4ae6ad19a420e176cc Mon Sep 17 00:00:00 2001 From: cosine Date: Mon, 11 Jul 2022 13:39:20 -0400 Subject: [PATCH 093/181] [test] Use still-illegal opcode (func-refs) (#1501) --- test/core/binary.wast | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/core/binary.wast b/test/core/binary.wast index 983da24c1..fb3037ae0 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -1050,7 +1050,7 @@ ) ;; end "data count section required") -;; passive element segment containing opcode other than ref.func or ref.null +;; passive element segment containing illegal opcode (assert_malformed (module binary "\00asm" "\01\00\00\00" @@ -1067,7 +1067,7 @@ "\09\07\01" ;; Element section with one segment "\05\70" ;; Passive, funcref "\01" ;; 1 element - "\d3\00\0b" ;; bad opcode, index 0, end + "\f3\00\0b" ;; bad opcode, index 0, end "\0a\04\01" ;; Code section From ee1e3592352e935f6b1e2ee6071ec4c69c22239f Mon Sep 17 00:00:00 2001 From: ariez-xyz <41232910+ariez-xyz@users.noreply.github.com> Date: Sat, 23 Jul 2022 23:18:33 +0200 Subject: [PATCH 094/181] [spec] Fix typo (#1508) --- document/core/syntax/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index 7692e711f..3dcae64df 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -195,7 +195,7 @@ Occasionally, it is convenient to group operators together according to the foll Vector Instructions ~~~~~~~~~~~~~~~~~~~ -Vector instructions (also known as *SIMD* instructions, single data multiple value) provide basic operations over :ref:`values ` of :ref:`vector type `. +Vector instructions (also known as *SIMD* instructions, single instruction multiple data) provide basic operations over :ref:`values ` of :ref:`vector type `. .. math:: \begin{array}{llcl} From 709f908e33ad395e950c6c6884b57d7778fb6b39 Mon Sep 17 00:00:00 2001 From: cosine Date: Fri, 29 Jul 2022 15:08:44 -0400 Subject: [PATCH 095/181] [spec] Fix table.copy validation typo (#1511) --- document/core/valid/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index f565f35c3..ac4b34a82 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -875,7 +875,7 @@ Table Instructions \frac{ C.\CTABLES[x] = \limits_1~t \qquad - C.\CTABLES[x] = \limits_2~t + C.\CTABLES[y] = \limits_2~t }{ C \vdashinstr \TABLECOPY~x~y : [\I32~\I32~\I32] \to [] } From 8538d6f66855aaeadf0800075944d3e84f9e93f0 Mon Sep 17 00:00:00 2001 From: Surma Date: Tue, 2 Aug 2022 13:13:36 +0100 Subject: [PATCH 096/181] [spec] Minor copy edit (#1512) --- document/core/intro/overview.rst | 2 +- document/core/syntax/modules.rst | 2 +- document/core/valid/instructions.rst | 2 +- document/core/valid/types.rst | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/document/core/intro/overview.rst b/document/core/intro/overview.rst index 5a4760baf..84c375e21 100644 --- a/document/core/intro/overview.rst +++ b/document/core/intro/overview.rst @@ -70,7 +70,7 @@ This language is structured around the following concepts. **Tables** A *table* is an array of opaque values of a particular *element type*. It allows programs to select such values indirectly through a dynamic index operand. - Currently, the only available element type is an untyped function reference. + Currently, the only available element type is an untyped function reference or a reference to an external host value. Thereby, a program can call functions indirectly through a dynamic index into a table. For example, this allows emulating function pointers by way of table indices. diff --git a/document/core/syntax/modules.rst b/document/core/syntax/modules.rst index b1e5c76ce..42aa05cd0 100644 --- a/document/core/syntax/modules.rst +++ b/document/core/syntax/modules.rst @@ -323,7 +323,7 @@ The |MSTART| component of a module declares the :ref:`function index ` a module, :ref:`external values ` must be provided whose :ref:`types ` are *matched* against the respective :ref:`external types ` classifying each import. -In some cases, this allows for a simple form of subtyping, as defined here. +In some cases, this allows for a simple form of subtyping (written ":math:`\matchesexterntype`" formally), as defined here. .. index:: limits @@ -279,7 +279,6 @@ Limits \vdashlimitsmatch \{ \LMIN~n_1, \LMAX~m_1 \} \matcheslimits \{ \LMIN~n_2, \LMAX~m_2 \} } - .. _match-externtype: .. index:: function type From 7fecbd5928de9c1403052bf4c43107000ff9a95b Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 3 Aug 2022 11:04:54 +0200 Subject: [PATCH 097/181] [spec] Trivial editorial fix --- document/core/valid/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index f2c559767..ac4b34a82 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -620,7 +620,7 @@ Parametric Instructions * The length of :math:`t^\ast` must be :math:`1`. - * The instruction is valid with type :math:`[t^\ast~t^\ast~\I32] \to [t^\ast]`. + * Then the instruction is valid with type :math:`[t^\ast~t^\ast~\I32] \to [t^\ast]`. * Else: From 633c69d84be0e93f099e2ffdaee3dc6f2fe82abd Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Thu, 4 Aug 2022 01:32:43 -0700 Subject: [PATCH 098/181] [interpreter] Build wast.js with Js_of_ocaml (#1507) --- .github/workflows/main.yml | 11 ++++ interpreter/Makefile | 24 +++---- interpreter/README.md | 23 ++++++- interpreter/dune | 5 +- interpreter/meta/jslib/bsconfig.json | 6 -- interpreter/meta/jslib/build.sh | 97 ---------------------------- interpreter/meta/jslib/wasm.ml | 9 --- interpreter/meta/jslib/wast.ml | 26 ++++++++ 8 files changed, 72 insertions(+), 129 deletions(-) delete mode 100644 interpreter/meta/jslib/bsconfig.json delete mode 100755 interpreter/meta/jslib/build.sh delete mode 100644 interpreter/meta/jslib/wasm.ml create mode 100644 interpreter/meta/jslib/wast.ml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4a5527ca2..9a7a111a1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,17 @@ jobs: - run: opam install --yes ocamlbuild.0.14.0 - run: cd interpreter && opam exec make all + ref-interpreter-js-library: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Setup OCaml + uses: ocaml/setup-ocaml@v2 + with: + ocaml-compiler: 4.12.x + - run: opam install --yes ocamlbuild.0.14.0 ocamlfind.1.9.5 js_of_ocaml.4.0.0 js_of_ocaml-ppx.4.0.0 + - run: cd interpreter && opam exec make wast.js + build-js-api-spec: runs-on: ubuntu-latest steps: diff --git a/interpreter/Makefile b/interpreter/Makefile index 1783a9c4d..7820e6428 100644 --- a/interpreter/Makefile +++ b/interpreter/Makefile @@ -2,7 +2,7 @@ # package manager to build. However, Opam package management is available # optionally through the check/install/uninstall targets. # -# The $(JSLIB) target requires node.js and BuckleScript. +# The $(JSLIB).js target requires Js_of_ocaml (using ocamlfind). # # See README.me for instructions. @@ -14,7 +14,7 @@ UNOPT = $(NAME).debug OPT = $(NAME) LIB = $(NAME) ZIP = $(NAME).zip -JSLIB = wast.js +JSLIB = wast WINMAKE = winmake.bat DIRS = util syntax binary text valid runtime exec script host main tests @@ -22,6 +22,7 @@ LIBS = bigarray FLAGS = -lexflags -ml -cflags '-w +a-4-27-42-44-45-70 -warn-error +a-3' OCBA = ocamlbuild $(FLAGS) $(DIRS:%=-I %) OCB = $(OCBA) $(LIBS:%=-libs %) +JSO = js_of_ocaml -q --opt 3 JS = # set to JS shell command to run JS tests @@ -35,7 +36,7 @@ opt: $(OPT) unopt: $(UNOPT) libopt: _build/$(LIB).cmx _build/$(LIB).cmxa libunopt: _build/$(LIB).cmo _build/$(LIB).cma -jslib: $(JSLIB) +jslib: $(JSLIB).js all: unopt opt libunopt libopt test land: $(WINMAKE) all zip: $(ZIP) @@ -108,14 +109,15 @@ _build/$(LIB).cmxa: $(FILES) $(LIB).mllib _tags Makefile # Building JavaScript library -.PHONY: $(JSLIB) -$(JSLIB): $(UNOPT) - mkdir -p _build/jslib/src - cp meta/jslib/* _build/jslib - cp $(DIRS:%=_build/%/*.ml*) meta/jslib/*.ml _build/jslib/src - rm _build/jslib/src/*.ml[^i] - (cd _build/jslib; ./build.sh ../../$@) +JSLIB_DIR = meta/jslib +JSLIB_FLAGS = -I $(JSLIB_DIR) -use-ocamlfind -pkg js_of_ocaml -pkg js_of_ocaml-ppx +.INTERMEDIATE: $(JSLIB).byte +$(JSLIB).byte: $(JSLIB_DIR)/$(JSLIB).ml + $(OCBA) $(JSLIB_FLAGS) $@ + +$(JSLIB).js: $(JSLIB).byte + $(JSO) $< # Building Windows build file @@ -181,7 +183,7 @@ $(ZIP): $(WINMAKE) git archive --format=zip --prefix=$(NAME)/ -o $@ HEAD clean: - rm -rf _build/jslib $(LIB).mlpack _tags + rm -rf _build/jslib $(LIB).mlpack _tags $(JSLIB).js $(OCB) -clean diff --git a/interpreter/README.md b/interpreter/README.md index 6f55c1f3f..11258ae62 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -65,7 +65,10 @@ The Makefile also provides a target to compile (parts of) the interpreter into a ``` make wast.js ``` -Building this target requires node.js and BuckleScript. +Building this target requires `js_of_ocaml`, which can be installed with OPAM: +``` +opam install js_of_ocaml js_of_ocaml-ppx +``` ## Synopsis @@ -139,7 +142,7 @@ WebAssemblyText.encode(source) ``` which turns a module in S-expression syntax into a WebAssembly binary, and ``` -WebAssemblyText.decode(binary, width = 80) +WebAssemblyText.decode(binary, width) ``` which pretty-prints a binary back into a canonicalised S-expression string. @@ -151,7 +154,7 @@ let binary = WebAssemblyText.encode(source) (new WebAssembly.Instance(new WebAssembly.Module(binary))).exports.f(3, 4) // => 7 -WebAssemblyText.decode(binary) +WebAssemblyText.decode(binary, 80) // => // (module // (type $0 (func (param i32 i32) (result i32))) @@ -160,6 +163,20 @@ WebAssemblyText.decode(binary) // ) ``` +Depending on how you load the library, the object may be accessed in different ways. For example, using `require` in node.js: + +``` +let wast = require("./wast.js"); +let binary = wast.WebAssemblyText.encode("(module)"); +``` + +Or using `load` from a JavaScript shell: + +``` +load("./wast.js"); +let binary = WebAssemblyText.encode("(module)"); +``` + ## S-Expression Syntax diff --git a/interpreter/dune b/interpreter/dune index 6f6dfff3e..48274aad9 100644 --- a/interpreter/dune +++ b/interpreter/dune @@ -4,10 +4,9 @@ (name wasm) ; The 'main' module shall not be part of the library, as it would start the ; Wasm REPL every time in all the dependencies. - ; We also need to exclude the 'wasm' module as it overlaps with the library - ; name. + ; We exclude the 'wast' module as it is only used for the JS build. ; 'smallint' is a separate test module. - (modules :standard \ main wasm smallint)) + (modules :standard \ main smallint wast)) (executable (name main) diff --git a/interpreter/meta/jslib/bsconfig.json b/interpreter/meta/jslib/bsconfig.json deleted file mode 100644 index d313bf93d..000000000 --- a/interpreter/meta/jslib/bsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "wasm", - "sources": [ - {"dir": "src"}, - ] -} diff --git a/interpreter/meta/jslib/build.sh b/interpreter/meta/jslib/build.sh deleted file mode 100755 index 14471217b..000000000 --- a/interpreter/meta/jslib/build.sh +++ /dev/null @@ -1,97 +0,0 @@ -link () { -echo "// DO NOT EDIT. Generated from WebAssembly spec interpreter" -echo " -let WebAssemblyText = (function() { -  let _registry = {__proto__: null}; - function normalize(file) { - return file.split('/').reverse()[0].split('.')[0]; - } -  function require(file) { -    let name = normalize(file); - if (!(name in _registry)) { - throw new Error('missing module: ' + name) -    } else if (typeof _registry[name] === 'function') { -" -if (($LOG == 1)) -then - echo 1>&2 Logging on - echo " - console.log(name); -" -fi -echo " -      let f = _registry[name]; -      _registry[name] = function() { throw new Error('cyclic module: ' + name) }; -      _registry[name] = f(); -    } -    return _registry[name]; -  } -" - -for file in $* -do - echo 1>&2 Including $file - name=`basename $file | sed s/[.]js//g` - echo " - _registry['$name'] = function() { -    let exports = {}; -//////// start of $name.js ////////" - cat $file - echo "//////// end of $name.js //////// -    return exports; -  }; -" -done - -echo " - function binary(bytes) { - let buffer = new ArrayBuffer(bytes.length); - let view = new Uint8Array(buffer); - for (let i = 0; i < bytes.length; ++i) { - view[i] = bytes.charCodeAt(i); - } - return buffer; - } - function bytes(buffer) { - let string = ''; - let view = new Uint8Array(buffer); - for (let i = 0; i < view.length; ++i) { - string += String.fromCodePoint(view[i]); - } - return string; - } -  let Wasm = require('wasm'); - return { - encode(s) { return binary(Wasm.encode(s)) }, - decode(b, w = 80) { return Wasm.decode(bytes(b), w) } - }; -})(); - -" -} - -echo 1>&2 ==== Preparing ==== -npm link bs-platform - -echo 1>&2 ==== Compiling ==== -bsb || exit 1 - -echo 1>&2 ==== Linking full version ==== -LOG=1 -FILES='node_modules/bs-platform/lib/js/*.js lib/js/src/*.js' -link $FILES >temp.js || exit 1 - -echo 1>&2 ==== Running for dependencies ==== -node temp.js | tee temp.log || exit 1 - -echo 1>&2 ==== Linking stripped version ==== -used='' -for file in `ls $FILES` -do - if grep -q `basename $file | sed s/.js//g` temp.log - then - used="$used $file" - fi -done -LOG=0 -link $used >$1 || exit 1 diff --git a/interpreter/meta/jslib/wasm.ml b/interpreter/meta/jslib/wasm.ml deleted file mode 100644 index 915fdafb0..000000000 --- a/interpreter/meta/jslib/wasm.ml +++ /dev/null @@ -1,9 +0,0 @@ -let encode s = - let def = Parse.string_to_module s in - match def.Source.it with - | Script.Textual m -> Encode.encode m - | Script.Encoded (_, bs) -> bs - -let decode s width = - let m = Decode.decode "(decode)" s in - Sexpr.to_string width (Arrange.module_ m) diff --git a/interpreter/meta/jslib/wast.ml b/interpreter/meta/jslib/wast.ml new file mode 100644 index 000000000..9af04f918 --- /dev/null +++ b/interpreter/meta/jslib/wast.ml @@ -0,0 +1,26 @@ +(* Implements a wrapper library that allows the use of the reference + * interpreter's encode/decode functionality in JavaScript. + *) +open Js_of_ocaml + +let _ = + Js.export "WebAssemblyText" + (object%js (_self) + + method encode (s : Js.js_string Js.t) : (Typed_array.arrayBuffer Js.t) = + let def = Parse.string_to_module (Js.to_string s) in + let bs = + match def.Source.it with + | Script.Textual m -> (Encode.encode m) + | Script.Encoded (_, bs) -> bs + | Script.Quoted (_, _) -> failwith "Unsupported" in + let buf = new%js Typed_array.arrayBuffer (String.length bs) in + let u8arr = new%js Typed_array.uint8Array_fromBuffer buf in + String.iteri (fun i c -> Typed_array.set u8arr i (int_of_char c)) bs; buf + + method decode (buf : Typed_array.arrayBuffer Js.t) width : (Js.js_string Js.t) = + let s = Typed_array.String.of_uint8Array (new%js Typed_array.uint8Array_fromBuffer buf) in + let m = Decode.decode "(decode)" s in + Js.string (Sexpr.to_string width (Arrange.module_ m)) + + end) From fa8267b9a31715f27684dc87253251c570811a5f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 4 Aug 2022 11:27:16 +0200 Subject: [PATCH 099/181] [interpreter] Add flag for controlling call budget --- interpreter/exec/eval.ml | 3 ++- interpreter/main/flags.ml | 1 + interpreter/main/main.ml | 6 ++++-- test/build.py | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 943515dfb..80610a1fb 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -73,7 +73,8 @@ type config = } let frame inst locals = {inst; locals} -let config inst vs es = {frame = frame inst []; code = vs, es; budget = 300} +let config inst vs es = + {frame = frame inst []; code = vs, es; budget = !Flags.budget} let plain e = Plain e.it @@ e.at diff --git a/interpreter/main/flags.ml b/interpreter/main/flags.ml index e3fcc2abf..b92378aa2 100644 --- a/interpreter/main/flags.ml +++ b/interpreter/main/flags.ml @@ -5,3 +5,4 @@ let print_sig = ref false let dry = ref false let width = ref 80 let harness = ref true +let budget = ref 256 diff --git a/interpreter/main/main.ml b/interpreter/main/main.ml index 898bdef1d..beeb98049 100644 --- a/interpreter/main/main.ml +++ b/interpreter/main/main.ml @@ -24,11 +24,13 @@ let argspec = Arg.align " read script from file"; "-o", Arg.String (fun file -> add_arg ("(output " ^ quote file ^ ")")), " write module to file"; + "-b", Arg.Int (fun n -> Flags.budget := n), + " configure call depth budget (default is " ^ string_of_int !Flags.budget ^ ")"; "-w", Arg.Int (fun n -> Flags.width := n), - " configure output width (default is 80)"; + " configure output width (default is " ^ string_of_int !Flags.width ^ ")"; "-s", Arg.Set Flags.print_sig, " show module signatures"; "-u", Arg.Set Flags.unchecked, " unchecked, do not perform validation"; - "-h", Arg.Clear Flags.harness, " exclude harness for JS conversion"; + "-j", Arg.Clear Flags.harness, " exclude harness for JS conversion"; "-d", Arg.Set Flags.dry, " dry, do not run program"; "-t", Arg.Set Flags.trace, " trace execution"; "-v", Arg.Unit banner, " show version" diff --git a/test/build.py b/test/build.py index bfb39727d..69c1b19a2 100755 --- a/test/build.py +++ b/test/build.py @@ -60,7 +60,7 @@ def ensure_wasm_executable(path_to_wasm): def convert_one_wast_file(inputs): wast_file, js_file = inputs print('Compiling {} to JS...'.format(wast_file)) - return run(WASM_EXEC, wast_file, '-h', '-o', js_file) + return run(WASM_EXEC, wast_file, '-j', '-o', js_file) def convert_wast_to_js(out_js_dir): """Compile all the wast files to JS and store the results in the JS dir.""" From 9144234a09017444c6412ecc2d74cebee9932ec5 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 10 Aug 2022 11:34:12 +0200 Subject: [PATCH 100/181] [spec] Simplify exec rule for if (#1517) --- document/core/exec/instructions.rst | 34 ++++++++++------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index efcc5bdce..899735533 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -2595,37 +2595,27 @@ Control Instructions :math:`\IF~\blocktype~\instr_1^\ast~\ELSE~\instr_2^\ast~\END` ............................................................. -1. Assert: due to :ref:`validation `, :math:`\expand_F(\blocktype)` is defined. - -2. Let :math:`[t_1^m] \to [t_2^n]` be the :ref:`function type ` :math:`\expand_F(\blocktype)`. - -3. Let :math:`L` be the label whose arity is :math:`n` and whose continuation is the end of the |IF| instruction. - -4. Assert: due to :ref:`validation `, a value of :ref:`value type ` |I32| is on the top of the stack. - -5. Pop the value :math:`\I32.\CONST~c` from the stack. - -6. Assert: due to :ref:`validation `, there are at least :math:`m` values on the top of the stack. +1. Assert: due to :ref:`validation `, a value of :ref:`value type ` |I32| is on the top of the stack. -7. Pop the values :math:`\val^m` from the stack. +2. Pop the value :math:`\I32.\CONST~c` from the stack. -8. If :math:`c` is non-zero, then: +3. If :math:`c` is non-zero, then: - a. :ref:`Enter ` the block :math:`\val^m~\instr_1^\ast` with label :math:`L`. + a. Execute the block instruction :math:`\BLOCK~\X{bt}~\instr_1^\ast~\END`. -9. Else: +4. Else: - a. :ref:`Enter ` the block :math:`\val^m~\instr_2^\ast` with label :math:`L`. + a. Execute the block instruction :math:`\BLOCK~\X{bt}~\instr_2^\ast~\END`. .. math:: ~\\[-1ex] \begin{array}{lcl} - F; \val^m~(\I32.\CONST~c)~\IF~\X{bt}~\instr_1^\ast~\ELSE~\instr_2^\ast~\END &\stepto& - F; \LABEL_n\{\epsilon\}~\val^m~\instr_1^\ast~\END - \\&&\quad (\iff c \neq 0 \wedge \expand_F(\X{bt}) = [t_1^m] \to [t_2^n]) \\ - F; \val^m~(\I32.\CONST~c)~\IF~\X{bt}~\instr_1^\ast~\ELSE~\instr_2^\ast~\END &\stepto& - F; \LABEL_n\{\epsilon\}~\val^m~\instr_2^\ast~\END - \\&&\quad (\iff c = 0 \wedge \expand_F(\X{bt}) = [t_1^m] \to [t_2^n]) \\ + F; (\I32.\CONST~c)~\IF~\X{bt}~\instr_1^\ast~\ELSE~\instr_2^\ast~\END &\stepto& + F; \BLOCK~\X{bt}~\instr_1^\ast~\END + \\&&\quad (\iff c \neq 0) \\ + F; (\I32.\CONST~c)~\IF~\X{bt}~\instr_1^\ast~\ELSE~\instr_2^\ast~\END &\stepto& + F; \BLOCK~\X{bt}~\instr_2^\ast~\END + \\&&\quad (\iff c = 0) \\ \end{array} From 6ab45681fc445b2ed23554bf2dc12c91f25ffcb7 Mon Sep 17 00:00:00 2001 From: Ian Henderson Date: Wed, 10 Aug 2022 23:17:33 -0700 Subject: [PATCH 101/181] [spec] Formatting tweak (#1519) --- document/core/binary/instructions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 0e3840cfc..d3f4ad0eb 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -613,7 +613,7 @@ All other vector instructions are plain opcodes without any immediates. \hex{FD}~~216{:}\Bu32 &\Rightarrow& \I64X2.\VLT\K{\_s} \\ &&|& \hex{FD}~~217{:}\Bu32 &\Rightarrow& \I64X2.\VGT\K{\_s} \\ &&|& \hex{FD}~~218{:}\Bu32 &\Rightarrow& \I64X2.\VLE\K{\_s} \\ &&|& - \hex{FD}~~219{:}\Bu32 &\Rightarrow& \I64X2.\VGE\K{\_s} \\ &&|& + \hex{FD}~~219{:}\Bu32 &\Rightarrow& \I64X2.\VGE\K{\_s} \\ \end{array} .. _binary-vfrelop: From 5170a4dd88cf1ff77645c3bff571eeb5a8ddc9eb Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 11 Aug 2022 15:33:25 +0200 Subject: [PATCH 102/181] [spec] Fix typing rule in appendix (#1516) --- document/core/appendix/index-rules.rst | 2 +- document/core/appendix/properties.rst | 28 ++++++++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/document/core/appendix/index-rules.rst b/document/core/appendix/index-rules.rst index 0da084123..8fa955d19 100644 --- a/document/core/appendix/index-rules.rst +++ b/document/core/appendix/index-rules.rst @@ -55,7 +55,7 @@ Construct Judgement :ref:`Table instance ` :math:`S \vdashtableinst \tableinst : \tabletype` :ref:`Memory instance ` :math:`S \vdashmeminst \meminst : \memtype` :ref:`Global instance ` :math:`S \vdashglobalinst \globalinst : \globaltype` -:ref:`Element instance ` :math:`S \vdasheleminst \eleminst \ok` +:ref:`Element instance ` :math:`S \vdasheleminst \eleminst : t` :ref:`Data instance ` :math:`S \vdashdatainst \datainst \ok` :ref:`Export instance ` :math:`S \vdashexportinst \exportinst \ok` :ref:`Module instance ` :math:`S \vdashmoduleinst \moduleinst : C` diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst index 72251114e..364b5f04a 100644 --- a/document/core/appendix/properties.rst +++ b/document/core/appendix/properties.rst @@ -87,7 +87,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * Each :ref:`global instance ` :math:`\globalinst_i` in :math:`S.\SGLOBALS` must be :ref:`valid ` with some :ref:`global type ` :math:`\globaltype_i`. -* Each :ref:`element instance ` :math:`\eleminst_i` in :math:`S.\SELEMS` must be :ref:`valid `. +* Each :ref:`element instance ` :math:`\eleminst_i` in :math:`S.\SELEMS` must be :ref:`valid ` with some :ref:`reference type ` :math:`\reftype_i`. * Each :ref:`data instance ` :math:`\datainst_i` in :math:`S.\SDATAS` must be :ref:`valid `. @@ -105,7 +105,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co \qquad (S \vdashglobalinst \globalinst : \globaltype)^\ast \\ - (S \vdasheleminst \eleminst \ok)^\ast + (S \vdasheleminst \eleminst : \reftype)^\ast \qquad (S \vdashdatainst \datainst \ok)^\ast \\ @@ -285,13 +285,13 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with :ref:`reference type ` :math:`t`. -* Then the table instance is valid. +* Then the element instance is valid with :ref:`reference type ` :math:`t`. .. math:: \frac{ (S \vdash \reff : t)^\ast }{ - S \vdasheleminst \{ \EITYPE~t, \EIELEM~\reff^\ast \} \ok + S \vdasheleminst \{ \EITYPE~t, \EIELEM~\reff^\ast \} : t } @@ -344,7 +344,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * For each :ref:`global address ` :math:`\globaladdr_i` in :math:`\moduleinst.\MIGLOBALS`, the :ref:`external value ` :math:`\EVGLOBAL~\globaladdr_i` must be :ref:`valid ` with some :ref:`external type ` :math:`\ETGLOBAL~\globaltype_i`. -* For each :ref:`element address ` :math:`\elemaddr_i` in :math:`\moduleinst.\MIELEMS`, the :ref:`element instance ` :math:`S.\SELEMS[\elemaddr_i]` must be :ref:`valid `. +* For each :ref:`element address ` :math:`\elemaddr_i` in :math:`\moduleinst.\MIELEMS`, the :ref:`element instance ` :math:`S.\SELEMS[\elemaddr_i]` must be :ref:`valid ` with some :ref:`reference type ` :math:`\reftype_i`. * For each :ref:`data address ` :math:`\dataaddr_i` in :math:`\moduleinst.\MIDATAS`, the :ref:`data instance ` :math:`S.\SDATAS[\dataaddr_i]` must be :ref:`valid `. @@ -360,8 +360,12 @@ Module instances are classified by *module contexts*, which are regular :ref:`co * Let :math:`\globaltype^\ast` be the concatenation of all :math:`\globaltype_i` in order. -* | Then the module instance is valid with :ref:`context ` - | :math:`\{\CTYPES~\functype^\ast, \CFUNCS~{\functype'}^\ast, \CTABLES~\tabletype^\ast, \CMEMS~\memtype^\ast, \CGLOBALS~\globaltype^\ast\}`. +* Let :math:`\reftype^\ast` be the concatenation of all :math:`\reftype_i` in order. + +* Let :math:`n` be the length of :math:`\moduleinst.\MIDATAS`. + +* Then the module instance is valid with :ref:`context ` + :math:`\{\CTYPES~\functype^\ast,` :math:`\CFUNCS~{\functype'}^\ast,` :math:`\CTABLES~\tabletype^\ast,` :math:`\CMEMS~\memtype^\ast,` :math:`\CGLOBALS~\globaltype^\ast,` :math:`\CELEMS~\reftype^\ast,` :math:`\CDATAS~{\ok}^n\}`. .. math:: ~\\[-1ex] @@ -377,9 +381,9 @@ Module instances are classified by *module contexts*, which are regular :ref:`co \qquad (S \vdashexternval \EVGLOBAL~\globaladdr : \ETGLOBAL~\globaltype)^\ast \\ - (S \vdasheleminst S.\SELEMS[\elemaddr] \ok)^\ast + (S \vdasheleminst S.\SELEMS[\elemaddr] : \reftype)^\ast \qquad - (S \vdashdatainst S.\SDATAS[\dataaddr] \ok)^\ast + (S \vdashdatainst S.\SDATAS[\dataaddr] \ok)^n \\ (S \vdashexportinst \exportinst \ok)^\ast \qquad @@ -394,14 +398,16 @@ Module instances are classified by *module contexts*, which are regular :ref:`co \MIMEMS & \memaddr^\ast, \\ \MIGLOBALS & \globaladdr^\ast, \\ \MIELEMS & \elemaddr^\ast, \\ - \MIDATAS & \dataaddr^\ast, \\ + \MIDATAS & \dataaddr^n, \\ \MIEXPORTS & \exportinst^\ast ~\} : \{ \begin{array}[t]{@{}l@{~}l@{}} \CTYPES & \functype^\ast, \\ \CFUNCS & {\functype'}^\ast, \\ \CTABLES & \tabletype^\ast, \\ \CMEMS & \memtype^\ast, \\ - \CGLOBALS & \globaltype^\ast ~\} + \CGLOBALS & \globaltype^\ast, \\ + \CELEMS & \reftype^\ast, \\ + \CDATAS & {\ok}^n ~\} \end{array} \end{array} } From 08a6178086ff4d6a6c0956ada79d66e87ad698e2 Mon Sep 17 00:00:00 2001 From: Tom Stuart Date: Tue, 23 Aug 2022 09:55:53 +0100 Subject: [PATCH 103/181] =?UTF-8?q?[spec]=20Fix=20=E2=80=9Cinvertible?= =?UTF-8?q?=E2=80=9D=20typo=20(#1520)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- document/core/exec/numerics.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/exec/numerics.rst b/document/core/exec/numerics.rst index c7050b17d..71dfef6a9 100644 --- a/document/core/exec/numerics.rst +++ b/document/core/exec/numerics.rst @@ -177,7 +177,7 @@ When a number is stored into :ref:`memory `, it is converted into a \littleendian(d^8~{d'}^\ast~) &=& \littleendian({d'}^\ast)~\ibits_8^{-1}(d^8) \\ \end{array} -Again these functions are invertable bijections. +Again these functions are invertible bijections. .. index:: numeric vectors, shape From 78c18fb16daa4d8d12344462f02a2e5c5d668912 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 25 Aug 2022 18:36:53 +0200 Subject: [PATCH 104/181] [spec] Correct use of opdtype and stacktype (#1524) --- document/core/valid/instructions.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index ac4b34a82..384a65137 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -48,7 +48,7 @@ This is extended to stack types in a point-wise manner. consuming two |I32| values and producing one. Typing extends to :ref:`instruction sequences ` :math:`\instr^\ast`. -Such a sequence has a :ref:`function type ` :math:`[t_1^\ast] \to [t_2^\ast]` if the accumulative effect of executing the instructions is consuming values of types :math:`t_1^\ast` off the operand stack and pushing new values of types :math:`t_2^\ast`. +Such a sequence has a :ref:`stack type ` :math:`[t_1^\ast] \to [t_2^\ast]` if the accumulative effect of executing the instructions is consuming values of types :math:`t_1^\ast` off the operand stack and pushing new values of types :math:`t_2^\ast`. .. _polymorphism: @@ -63,7 +63,7 @@ Two degrees of polymorphism can be distinguished: * *stack-polymorphic*: - the entire (or most of the) :ref:`function type ` :math:`[t_1^\ast] \to [t_2^\ast]` of the instruction is unconstrained. + the entire (or most of the) :ref:`stack type ` :math:`[t_1^\ast] \to [t_2^\ast]` of the instruction is unconstrained. That is the case for all :ref:`control instructions ` that perform an *unconditional control transfer*, such as |UNREACHABLE|, |BR|, |BRTABLE|, and |RETURN|. In both cases, the unconstrained types or type sequences can be chosen arbitrarily, as long as they meet the constraints imposed for the surrounding parts of the program. @@ -81,7 +81,7 @@ In both cases, the unconstrained types or type sequences can be chosen arbitrari are valid, with :math:`t` in the typing of |SELECT| being instantiated to |I32| or |F64|, respectively. - The |UNREACHABLE| instruction is valid with type :math:`[t_1^\ast] \to [t_2^\ast]` for any possible sequences of value types :math:`t_1^\ast` and :math:`t_2^\ast`. + The |UNREACHABLE| instruction is valid with type :math:`[t_1^\ast] \to [t_2^\ast]` for any possible sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. Consequently, .. math:: @@ -258,7 +258,7 @@ Reference Instructions Vector Instructions ~~~~~~~~~~~~~~~~~~~ -Vector instructions can have a prefix to describe the :ref:`shape ` of the operand. Packed numeric types, |I8| and |I16|, are not :ref:`value type `, we define an auxiliary function to map such packed types into value types: +Vector instructions can have a prefix to describe the :ref:`shape ` of the operand. Packed numeric types, |I8| and |I16|, are not :ref:`value types `. An auxiliary function maps such packed types to value types: .. math:: \begin{array}{lll@{\qquad}l} @@ -598,7 +598,7 @@ Parametric Instructions :math:`\DROP` ............. -* The instruction is valid with type :math:`[t] \to []`, for any :ref:`value type ` :math:`t`. +* The instruction is valid with type :math:`[t] \to []`, for any :ref:`operand type ` :math:`t`. .. math:: \frac{ @@ -1267,7 +1267,7 @@ Control Instructions :math:`\UNREACHABLE` .................... -* The instruction is valid with type :math:`[t_1^\ast] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. +* The instruction is valid with type :math:`[t_1^\ast] \to [t_2^\ast]`, for any sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. .. math:: \frac{ @@ -1374,7 +1374,7 @@ Control Instructions * Let :math:`[t^\ast]` be the :ref:`result type ` :math:`C.\CLABELS[l]`. -* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. +* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]`, for any sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. .. math:: \frac{ @@ -1422,14 +1422,14 @@ Control Instructions * For all :math:`l_i` in :math:`l^\ast`, the label :math:`C.\CLABELS[l_i]` must be defined in the context. -* There must be a :ref:`result type ` :math:`[t^\ast]`, such that: +* There must be a sequence :math:`t^\ast` of :ref:`operand types `, such that: * For each :ref:`operand type ` :math:`t_j` in :math:`t^\ast` and corresponding type :math:`t'_{Nj}` in :math:`C.\CLABELS[l_N]`, :math:`t_j` :ref:`matches ` :math:`t'_{Nj}`. * For all :math:`l_i` in :math:`l^\ast`, and for each :ref:`operand type ` :math:`t_j` in :math:`t^\ast` and corresponding type :math:`t'_{ij}` in :math:`C.\CLABELS[l_i]`, :math:`t_j` :ref:`matches ` :math:`t'_{ij}`. -* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast~\I32] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. +* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast~\I32] \to [t_2^\ast]`, for any sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. .. math:: \frac{ @@ -1455,7 +1455,7 @@ Control Instructions * Let :math:`[t^\ast]` be the :ref:`result type ` of :math:`C.\CRETURN`. -* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. +* Then the instruction is valid with type :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]`, for any sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. .. math:: \frac{ @@ -1542,12 +1542,12 @@ Non-empty Instruction Sequence: :math:`\instr^\ast~\instr_N` ............................................................ * The instruction sequence :math:`\instr^\ast` must be valid with type :math:`[t_1^\ast] \to [t_2^\ast]`, - for some sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`. + for some sequences of :ref:`operand types ` :math:`t_1^\ast` and :math:`t_2^\ast`. * The instruction :math:`\instr_N` must be valid with type :math:`[t^\ast] \to [t_3^\ast]`, - for some sequences of :ref:`value types ` :math:`t^\ast` and :math:`t_3^\ast`. + for some sequences of :ref:`operand types ` :math:`t^\ast` and :math:`t_3^\ast`. -* There must be a sequence of :ref:`value types ` :math:`t_0^\ast`, +* There must be a sequence of :ref:`operand types ` :math:`t_0^\ast`, such that :math:`t_2^\ast = t_0^\ast~{t'}^\ast` where the type sequence :math:`{t'}^\ast` is as long as :math:`t^\ast`. * For each :ref:`operand type ` :math:`t'_i` in :math:`{t'}^\ast` and corresponding type :math:`t_i` in :math:`t^\ast`, :math:`t'_i` :ref:`matches ` :math:`t_i`. From 8363b5015741d2f7039a33356cd4ee382aa73f2f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 25 Aug 2022 20:53:40 +0200 Subject: [PATCH 105/181] [spec] Add note to instruction index (#1528) --- document/core/appendix/gen-index-instructions.py | 9 +++++++++ document/core/appendix/index-instructions.rst | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/document/core/appendix/gen-index-instructions.py b/document/core/appendix/gen-index-instructions.py index d9e6753c4..7489aae00 100755 --- a/document/core/appendix/gen-index-instructions.py +++ b/document/core/appendix/gen-index-instructions.py @@ -21,6 +21,14 @@ --------------------- """ +FOOTER = """\ + +.. note:: + Multi-byte opcodes are given with the shortest possible encoding in the table. + However, what is following the first byte is actually a :ref:`u32 ` with variable-length encoding + and consequently has multiple possible representations.\ +""" + COLUMNS = [ 'Instruction', 'Binary Opcode', @@ -591,3 +599,4 @@ def Row(columns): print(Row(instr), file=f) print(DIVIDER, file=f) + print(FOOTER, file=f) diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst index 0636a4266..84055a9fa 100644 --- a/document/core/appendix/index-instructions.rst +++ b/document/core/appendix/index-instructions.rst @@ -516,3 +516,8 @@ Instruction Binary Opcode :math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{FE}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` :math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{FF}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` ================================================= ==================================== ============================================= ============================================= ================================================================== + +.. note:: + Multi-byte opcodes are given with the shortest possible encoding in the table. + However, what is following the first byte is actually a :ref:`u32 ` with variable-length encoding + and consequently has multiple possible representations. From cccc38a1d4808710608099c1e23bac62345d2c2b Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 26 Aug 2022 14:59:31 +0200 Subject: [PATCH 106/181] [spec] Tweak wording to avoid first person --- document/core/syntax/modules.rst | 2 +- document/core/valid/conventions.rst | 2 +- document/core/valid/instructions.rst | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/document/core/syntax/modules.rst b/document/core/syntax/modules.rst index 42aa05cd0..1bf39753d 100644 --- a/document/core/syntax/modules.rst +++ b/document/core/syntax/modules.rst @@ -106,7 +106,7 @@ Conventions * The meta variables :math:`x, y` range over indices in any of the other index spaces. -* The notation :math:`\F{idx}(A)` denotes the set of indices from index space :math:`\X{idx}` occurring free in :math:`A`. We sometimes reinterpret this set as the :ref:`vector ` of its elements. +* The notation :math:`\F{idx}(A)` denotes the set of indices from index space :math:`\X{idx}` occurring free in :math:`A`. Sometimes this set is reinterpreted as the :ref:`vector ` of its elements. .. note:: For example, if :math:`\instr^\ast` is :math:`(\DATADROP~x) (\MEMORYINIT~y)`, then :math:`\freedataidx(\instr^\ast) = \{x, y\}`, or equivalently, the vector :math:`x~y`. diff --git a/document/core/valid/conventions.rst b/document/core/valid/conventions.rst index ae219e44a..fbd4f6e20 100644 --- a/document/core/valid/conventions.rst +++ b/document/core/valid/conventions.rst @@ -79,7 +79,7 @@ In addition to field access written :math:`C.\K{field}` the following notation i * :math:`C,\K{field}\,A^\ast` denotes the same context as :math:`C` but with the elements :math:`A^\ast` prepended to its :math:`\K{field}` component sequence. .. note:: - We use :ref:`indexing notation ` like :math:`C.\CLABELS[i]` to look up indices in their respective :ref:`index space ` in the context. + :ref:`Indexing notation ` like :math:`C.\CLABELS[i]` is used to look up indices in their respective :ref:`index space ` in the context. Context extension notation :math:`C,\K{field}\,A` is primarily used to locally extend *relative* index spaces, such as :ref:`label indices `. Accordingly, the notation is defined to append at the *front* of the respective sequence, introducing a new relative index :math:`0` and shifting the existing ones. diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 384a65137..552bd4be7 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -258,7 +258,7 @@ Reference Instructions Vector Instructions ~~~~~~~~~~~~~~~~~~~ -Vector instructions can have a prefix to describe the :ref:`shape ` of the operand. Packed numeric types, |I8| and |I16|, are not :ref:`value types `. An auxiliary function maps such packed types to value types: +Vector instructions can have a prefix to describe the :ref:`shape ` of the operand. Packed numeric types, |I8| and |I16|, are not :ref:`value types `. An auxiliary function maps such packed type shapes to value types: .. math:: \begin{array}{lll@{\qquad}l} @@ -268,7 +268,7 @@ Vector instructions can have a prefix to describe the :ref:`shape Date: Tue, 30 Aug 2022 18:46:38 +0200 Subject: [PATCH 107/181] [spec/test] Fix scoping of non-imported globals (#1525) --- document/core/valid/instructions.rst | 2 +- document/core/valid/modules.rst | 44 ++++++++++++++-------------- test/core/data.wast | 25 +++++++++++----- test/core/elem.wast | 23 +++++++++++---- test/core/global.wast | 9 ++++++ 5 files changed, 67 insertions(+), 36 deletions(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index 552bd4be7..2e2ca4115 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -1646,7 +1646,7 @@ Constant Expressions } .. note:: - Currently, constant expressions occurring as initializers of :ref:`globals ` are further constrained in that contained |GLOBALGET| instructions are only allowed to refer to *imported* globals. + Currently, constant expressions occurring in :ref:`globals `, :ref:`element `, or :ref:`data ` segments are further constrained in that contained |GLOBALGET| instructions are only allowed to refer to *imported* globals. This is enforced in the :ref:`validation rule for modules ` by constraining the context :math:`C` accordingly. The definition of constant expression may be extended in future versions of WebAssembly. diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst index 96edd4d71..72989de3b 100644 --- a/document/core/valid/modules.rst +++ b/document/core/valid/modules.rst @@ -546,24 +546,33 @@ Instead, the context :math:`C` for validation of the module's content is constru * all other fields are empty. -* Under the context :math:`C`: +* For each :math:`\functype_i` in :math:`\module.\MTYPES`, + the :ref:`function type ` :math:`\functype_i` must be :ref:`valid `. - * For each :math:`\functype_i` in :math:`\module.\MTYPES`, - the :ref:`function type ` :math:`\functype_i` must be :ref:`valid `. +* Under the context :math:`C`: * For each :math:`\func_i` in :math:`\module.\MFUNCS`, the definition :math:`\func_i` must be :ref:`valid ` with a :ref:`function type ` :math:`\X{ft}_i`. + * If :math:`\module.\MSTART` is non-empty, + then :math:`\module.\MSTART` must be :ref:`valid `. + + * For each :math:`\import_i` in :math:`\module.\MIMPORTS`, + the segment :math:`\import_i` must be :ref:`valid ` with an :ref:`external type ` :math:`\X{it}_i`. + + * For each :math:`\export_i` in :math:`\module.\MEXPORTS`, + the segment :math:`\export_i` must be :ref:`valid ` with :ref:`external type ` :math:`\X{et}_i`. + +* Under the context :math:`C'`: + * For each :math:`\table_i` in :math:`\module.\MTABLES`, the definition :math:`\table_i` must be :ref:`valid ` with a :ref:`table type ` :math:`\X{tt}_i`. * For each :math:`\mem_i` in :math:`\module.\MMEMS`, the definition :math:`\mem_i` must be :ref:`valid ` with a :ref:`memory type ` :math:`\X{mt}_i`. - * For each :math:`\global_i` in :math:`\module.\MGLOBALS`: - - * Under the context :math:`C'`, - the definition :math:`\global_i` must be :ref:`valid ` with a :ref:`global type ` :math:`\X{gt}_i`. + * For each :math:`\global_i` in :math:`\module.\MGLOBALS`, + the definition :math:`\global_i` must be :ref:`valid ` with a :ref:`global type ` :math:`\X{gt}_i`. * For each :math:`\elem_i` in :math:`\module.\MELEMS`, the segment :math:`\elem_i` must be :ref:`valid ` with :ref:`reference type ` :math:`\X{rt}_i`. @@ -571,15 +580,6 @@ Instead, the context :math:`C` for validation of the module's content is constru * For each :math:`\data_i` in :math:`\module.\MDATAS`, the segment :math:`\data_i` must be :ref:`valid `. - * If :math:`\module.\MSTART` is non-empty, - then :math:`\module.\MSTART` must be :ref:`valid `. - - * For each :math:`\import_i` in :math:`\module.\MIMPORTS`, - the segment :math:`\import_i` must be :ref:`valid ` with an :ref:`external type ` :math:`\X{it}_i`. - - * For each :math:`\export_i` in :math:`\module.\MEXPORTS`, - the segment :math:`\export_i` must be :ref:`valid ` with :ref:`external type ` :math:`\X{et}_i`. - * The length of :math:`C.\CMEMS` must not be larger than :math:`1`. * All export names :math:`\export_i.\ENAME` must be different. @@ -607,15 +607,15 @@ Instead, the context :math:`C` for validation of the module's content is constru \quad (C \vdashfunc \func : \X{ft})^\ast \quad - (C \vdashtable \table : \X{tt})^\ast + (C' \vdashtable \table : \X{tt})^\ast \quad - (C \vdashmem \mem : \X{mt})^\ast + (C' \vdashmem \mem : \X{mt})^\ast \quad (C' \vdashglobal \global : \X{gt})^\ast \\ - (C \vdashelem \elem : \X{rt})^\ast + (C' \vdashelem \elem : \X{rt})^\ast \quad - (C \vdashdata \data \ok)^n + (C' \vdashdata \data \ok)^n \quad (C \vdashstart \start \ok)^? \quad @@ -665,5 +665,5 @@ Instead, the context :math:`C` for validation of the module's content is constru However, this recursion is just a specification device. All types needed to construct :math:`C` can easily be determined from a simple pre-pass over the module that does not perform any actual validation. - Globals, however, are not recursive. - The effect of defining the limited context :math:`C'` for validating the module's globals is that their initialization expressions can only access functions and imported globals and nothing else. + Globals, however, are not recursive and not accessible within :ref:`constant expressions ` when they are defined locally. + The effect of defining the limited context :math:`C'` for validating certain definitions is that they can only access functions and imported globals and nothing else. diff --git a/test/core/data.wast b/test/core/data.wast index e4298bba4..9a83d0eaf 100644 --- a/test/core/data.wast +++ b/test/core/data.wast @@ -82,9 +82,15 @@ (data (global.get $g) "a") ) -;; Use of internal globals in constant expressions is not allowed in MVP. -;; (module (memory 1) (data (global.get 0) "a") (global i32 (i32.const 0))) -;; (module (memory 1) (data (global.get $g) "a") (global $g i32 (i32.const 0))) +(assert_invalid + (module (memory 1) (global i32 (i32.const 0)) (data (global.get 0) "a")) + "unknown global" +) +(assert_invalid + (module (memory 1) (global $g i32 (i32.const 0)) (data (global.get $g) "a")) + "unknown global" +) + ;; Corner cases @@ -457,11 +463,14 @@ "constant expression required" ) -;; Use of internal globals in constant expressions is not allowed in MVP. -;; (assert_invalid -;; (module (memory 1) (data (global.get $g)) (global $g (mut i32) (i32.const 0))) -;; "constant expression required" -;; ) +(assert_invalid + (module + (global $g (import "test" "g") (mut i32)) + (memory 1) + (data (global.get $g)) + ) + "constant expression required" +) (assert_invalid (module diff --git a/test/core/elem.wast b/test/core/elem.wast index 575ecef81..af12fec63 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast @@ -148,6 +148,16 @@ (assert_return (invoke "call-7") (i32.const 65)) (assert_return (invoke "call-9") (i32.const 66)) +(assert_invalid + (module (table 1 funcref) (global i32 (i32.const 0)) (elem (global.get 0) $f) (func $f)) + "unknown global" +) +(assert_invalid + (module (table 1 funcref) (global $g i32 (i32.const 0)) (elem (global.get $g) $f) (func $f)) + "unknown global" +) + + ;; Corner cases (module @@ -425,11 +435,14 @@ "constant expression required" ) -;; Use of internal globals in constant expressions is not allowed in MVP. -;; (assert_invalid -;; (module (table 1 funcref) (elem (global.get $g)) (global $g i32 (i32.const 0))) -;; "constant expression required" -;; ) +(assert_invalid + (module + (global $g (import "test" "g") (mut i32)) + (table 1 funcref) + (elem (global.get $g)) + ) + "constant expression required" +) (assert_invalid (module diff --git a/test/core/global.wast b/test/core/global.wast index 9fa5e2231..e40a305f1 100644 --- a/test/core/global.wast +++ b/test/core/global.wast @@ -348,6 +348,15 @@ "unknown global" ) +(assert_invalid + (module (global i32 (i32.const 0)) (global i32 (global.get 0))) + "unknown global" +) +(assert_invalid + (module (global $g i32 (i32.const 0)) (global i32 (global.get $g))) + "unknown global" +) + (assert_invalid (module (global i32 (global.get 1)) (global i32 (i32.const 0))) "unknown global" From 0f4fd747790c75b1c3615fd4bec63c81adbd29d8 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 1 Sep 2022 19:27:30 +0200 Subject: [PATCH 108/181] [spec] Fix language config --- document/core/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/conf.py b/document/core/conf.py index 1cb3fa541..01747a40a 100644 --- a/document/core/conf.py +++ b/document/core/conf.py @@ -88,7 +88,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: From 66e8467713a2e9d7b45efab108d7ac7d32e5d317 Mon Sep 17 00:00:00 2001 From: whirlicote <78504913+whirlicote@users.noreply.github.com> Date: Tue, 20 Sep 2022 08:26:57 +0200 Subject: [PATCH 109/181] [spec] Fix naming typo (#1532) --- document/core/exec/modules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index 99eeb2756..ed647cc57 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -313,7 +313,7 @@ New instances of :ref:`functions `, :ref:`tables ` in :math:`S`. -3. Let :math:`\eleminst` be the :ref:`element instance ` :math:`\{ \EITYPE~t, \EIELEM~\reff^\ast \}`. +3. Let :math:`\eleminst` be the :ref:`element instance ` :math:`\{ \EITYPE~\reftype, \EIELEM~\reff^\ast \}`. 4. Append :math:`\eleminst` to the |SELEMS| of :math:`S`. From 4534627e5f382f9f55667b7c3e1fcdc4d9f87d26 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 20 Sep 2022 13:51:35 +0200 Subject: [PATCH 110/181] [spec] Add citation for WasmCert (#1533) --- document/core/appendix/properties.rst | 8 ++++++-- document/core/util/macros.def | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst index 364b5f04a..c37823219 100644 --- a/document/core/appendix/properties.rst +++ b/document/core/appendix/properties.rst @@ -807,7 +807,7 @@ Theorems ~~~~~~~~ Given the definition of :ref:`valid configurations `, -the standard soundness theorems hold. [#cite-cpp2018]_ +the standard soundness theorems hold. [#cite-cpp2018]_ [#cite-fm2021]_ **Theorem (Preservation).** If a :ref:`configuration ` :math:`S;T` is :ref:`valid ` with :ref:`result type ` :math:`[t^\ast]` (i.e., :math:`\vdashconfig S;T : [t^\ast]`), @@ -839,5 +839,9 @@ Consequently, given a :ref:`valid store `, no computation defined b Andreas Haas, Andreas Rossberg, Derek Schuff, Ben Titzer, Dan Gohman, Luke Wagner, Alon Zakai, JF Bastien, Michael Holman. |PLDI2017|_. Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2017). ACM 2017. .. [#cite-cpp2018] - A machine-verified version of the formalization and soundness proof is described in the following article: + A machine-verified version of the formalization and soundness proof of the PLDI 2017 paper is described in the following article: Conrad Watt. |CPP2018|_. Proceedings of the 7th ACM SIGPLAN Conference on Certified Programs and Proofs (CPP 2018). ACM 2018. + +.. [#cite-fm2021] + Machine-verified formalizations and soundness proofs of the semantics from the official specification are described in the following article: + Conrad Watt, Xiaojia Rao, Jean Pichon-Pharabod, Martin Bodin, Philippa Gardner. |FM2021|_. Proceedings of the 24th International Symposium on Formal Methods (FM 2021). Springer 2021. diff --git a/document/core/util/macros.def b/document/core/util/macros.def index d66a8d6fe..aaefc4069 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -38,6 +38,7 @@ .. |MediaType| replace:: Media Type .. _MediaType: https://www.iana.org/assignments/media-types/media-types.xhtml + .. Literature .. ---------- @@ -47,6 +48,9 @@ .. |CPP2018| replace:: Mechanising and Verifying the WebAssembly Specification .. _CPP2018: https://dl.acm.org/citation.cfm?id=3167082 +.. |FM2021| replace:: Two Mechanisations of WebAssembly 1.0 +.. _FM2021: https://link.springer.com/chapter/10.1007/978-3-030-90870-6_4 + .. |TAPL| replace:: Types and Programming Languages .. _TAPL: https://www.cis.upenn.edu/~bcpierce/tapl/ From 62a78b5d1c0f99a3c0ff459ecf561be87ae38c6d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 20 Sep 2022 15:36:08 +0200 Subject: [PATCH 111/181] [test] Fix async_index.js --- test/harness/async_index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/harness/async_index.js b/test/harness/async_index.js index c200019ac..6d804bd56 100644 --- a/test/harness/async_index.js +++ b/test/harness/async_index.js @@ -267,6 +267,7 @@ function assert_return(action, ...expected) { .then( values => { uniqueTest(_ => { + let actual = values[0]; if (actual === undefined) { actual = []; } else if (!Array.isArray(actual)) { From fd9693fc7480980cc5958bb1dfdc6e4b0e3be2d6 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 20 Sep 2022 14:44:58 +0200 Subject: [PATCH 112/181] [test] Enable the i64 tests in imports.wast. Fixes #1514. --- test/core/imports.wast | 15 +++++---------- test/harness/async_index.js | 2 ++ test/harness/sync_index.js | 2 ++ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/test/core/imports.wast b/test/core/imports.wast index a1609c813..94c1af5c9 100644 --- a/test/core/imports.wast +++ b/test/core/imports.wast @@ -30,11 +30,9 @@ (type $func_f64 (func (param f64))) (import "spectest" "print_i32" (func (param i32))) - ;; JavaScript can't handle i64 yet. - ;; (func (import "spectest" "print_i64") (param i64)) + (func (import "spectest" "print_i64") (param i64)) (import "spectest" "print_i32" (func $print_i32 (param i32))) - ;; JavaScript can't handle i64 yet. - ;; (import "spectest" "print_i64" (func $print_i64 (param i64))) + (import "spectest" "print_i64" (func $print_i64 (param i64))) (import "spectest" "print_f32" (func $print_f32 (param f32))) (import "spectest" "print_f64" (func $print_f64 (param f64))) (import "spectest" "print_i32_f32" (func $print_i32_f32 (param i32 f32))) @@ -72,14 +70,12 @@ (func (export "print64") (param $i i64) (local $x f64) (local.set $x (f64.convert_i64_s (call $i64->i64 (local.get $i)))) - ;; JavaScript can't handle i64 yet. - ;; (call 1 (local.get $i)) + (call 1 (local.get $i)) (call $print_f64_f64 (f64.add (local.get $x) (f64.const 1)) (f64.const 53) ) - ;; JavaScript can't handle i64 yet. - ;; (call $print_i64 (local.get $i)) + (call $print_i64 (local.get $i)) (call $print_f64 (local.get $x)) (call $print_f64-2 (local.get $x)) (call_indirect (type $func_f64) (local.get $x) (i32.const 1)) @@ -234,8 +230,7 @@ (import "spectest" "global_i32" (global $x i32)) (global $y (import "spectest" "global_i32") i32) - ;; JavaScript can't handle i64 yet. - ;; (import "spectest" "global_i64" (global i64)) + (import "spectest" "global_i64" (global i64)) (import "spectest" "global_f32" (global f32)) (import "spectest" "global_f64" (global f64)) diff --git a/test/harness/async_index.js b/test/harness/async_index.js index 6d804bd56..bb7d4cf5d 100644 --- a/test/harness/async_index.js +++ b/test/harness/async_index.js @@ -93,11 +93,13 @@ function reinitializeRegistry() { eq_funcref: eq_funcref, print: console.log.bind(console), print_i32: console.log.bind(console), + print_i64: console.log.bind(console), print_i32_f32: console.log.bind(console), print_f64_f64: console.log.bind(console), print_f32: console.log.bind(console), print_f64: console.log.bind(console), global_i32: 666, + global_i64: 666n, global_f32: 666, global_f64: 666, table: new WebAssembly.Table({ diff --git a/test/harness/sync_index.js b/test/harness/sync_index.js index 7ed9f2915..79469ee9b 100644 --- a/test/harness/sync_index.js +++ b/test/harness/sync_index.js @@ -103,11 +103,13 @@ function reinitializeRegistry() { eq_funcref: eq_funcref, print: console.log.bind(console), print_i32: console.log.bind(console), + print_i64: console.log.bind(console), print_i32_f32: console.log.bind(console), print_f64_f64: console.log.bind(console), print_f32: console.log.bind(console), print_f64: console.log.bind(console), global_i32: 666, + global_i64: 666n, global_f32: 666, global_f64: 666, table: new WebAssembly.Table({initial: 10, maximum: 20, element: 'anyfunc'}), From 577128068d3896fc27c125568b1bb28f7dc72061 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 27 Sep 2022 13:40:35 +0200 Subject: [PATCH 113/181] [js-api][web-api] Editorial: Fix some minor issues. Fixes #1064. --- document/js-api/index.bs | 47 +++++++++++++++++++++------------------ document/web-api/index.bs | 9 +------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 43c189f22..3201425a9 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -34,6 +34,9 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT text: TypeError; url: sec-native-error-types-used-in-this-standard-typeerror text: RangeError; url: sec-native-error-types-used-in-this-standard-rangeerror type: dfn + url: sec-returnifabrupt-shorthands + text: ! + text: ? text: agent cluster; url: sec-agent-clusters text: agent; url: agent text: data block; url: sec-data-blocks @@ -355,9 +358,9 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje 1. If |module|.[=imports=] [=list/is empty|is not empty=], and |importObject| is undefined, throw a {{TypeError}} exception. 1. Let |imports| be « ». 1. [=list/iterate|For each=] (|moduleName|, |componentName|, |externtype|) of [=module_imports=](|module|), - 1. Let |o| be ? [=Get=](|importObject|, |moduleName|). + 1. Let |o| be [=?=] [=Get=](|importObject|, |moduleName|). 1. If [=Type=](|o|) is not Object, throw a {{TypeError}} exception. - 1. Let |v| be ? [=Get=](|o|, |componentName|). + 1. Let |v| be [=?=] [=Get=](|o|, |componentName|). 1. If |externtype| is of the form [=func=] |functype|, 1. If [=IsCallable=](|v|) is false, throw a {{LinkError}} exception. 1. If |v| has a \[[FunctionAddress]] internal slot, and therefore is an [=Exported Function=], @@ -403,7 +406,7 @@ The verification of WebAssembly type requirements is deferred to the
      To create an exports object from a WebAssembly module |module| and instance |instance|, perform the following steps: - 1. Let |exportsObject| be ! [=ObjectCreate=](null). + 1. Let |exportsObject| be [=!=] [=ObjectCreate=](null). 1. [=list/iterate|For each=] (|name|, |externtype|) of [=module_exports=](|module|), 1. Let |externval| be [=instance_export=](|instance|, |name|). 1. Assert: |externval| is not [=error=]. @@ -427,11 +430,11 @@ The verification of WebAssembly type requirements is deferred to the 1. Let [=external value|table=] |tableaddr| be |externval|. 1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|. 1. Let |value| be |table|. - 1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|). + 1. Let |status| be [=!=] [=CreateDataProperty=](|exportsObject|, |name|, |value|). 1. Assert: |status| is true. Note: the validity and uniqueness checks performed during [=WebAssembly module validation=] ensure that each property name is valid and no properties are defined twice. - 1. Perform ! [=SetIntegrityLevel=](|exportsObject|, `"frozen"`). + 1. Perform [=!=] [=SetIntegrityLevel=](|exportsObject|, `"frozen"`). 1. Return |exportsObject|.
      @@ -687,7 +690,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. Let |map| be the [=surrounding agent=]'s associated [=Memory object cache=]. 1. Assert: |map|[|memaddr|] [=map/exists=]. 1. Let |memory| be |map|[|memaddr|]. - 1. Perform ! [=DetachArrayBuffer=](|memory|.\[[BufferObject]], "WebAssembly.Memory"). + 1. Perform [=!=] [=DetachArrayBuffer=](|memory|.\[[BufferObject]], "WebAssembly.Memory"). 1. Let |buffer| be the result of [=create a memory buffer|creating a memory buffer=] from |memaddr|. 1. Set |memory|.\[[BufferObject]] to |buffer|.
      @@ -777,7 +780,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). 1. Otherwise, - 1. Let |ref| be ? [=ToWebAssemblyValue=](|value|, |elementType|). + 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |type| be the [=table type=] {[=table type|min=] |initial|, [=table type|max=] |maximum|} |elementType|. 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let (|store|, |tableaddr|) be [=table_alloc=](|store|, |type|, |ref|). @@ -794,7 +797,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). 1. Otherwise, - 1. Let |ref| be ? [=ToWebAssemblyValue=](|value|, |elementType|). + 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|, |ref|). 1. If |result| is [=error=], throw a {{RangeError}} exception. @@ -827,7 +830,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address 1. If |value| is missing, 1. Let |ref| be [=DefaultValue=](|elementType|). 1. Otherwise, - 1. Let |ref| be ? [=ToWebAssemblyValue=](|value|, |elementType|). + 1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|). 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let |store| be [=table_write=](|store|, |tableaddr|, |index|, |ref|). 1. If |store| is [=error=], throw a {{RangeError}} exception. @@ -977,7 +980,7 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [ 1. Let |moduleinst| be |funcinst|.module. 1. Assert: |funcaddr| is contained in |moduleinst|.funcaddrs. 1. Let |index| be the index of |moduleinst|.funcaddrs where |funcaddr| is found. - 1. Return ! [=ToString=](|index|). + 1. Return [=!=] [=ToString=](|index|).
      @@ -1004,7 +1007,7 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [ 1. Let |store| be the [=surrounding agent=]'s [=associated store=]. 1. Let |functype| be [=func_type=](|store|, |funcaddr|). - 1. Let [|parameters|] → [results] be |functype|. + 1. Let [|parameters|] → [|results|] be |functype|. 1. If |parameters| or |results| contain [=v128=], throw a {{TypeError}}. Note: the above error is thrown each time the \[[Call]] method is invoked. @@ -1035,19 +1038,19 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
      To run a host function from the JavaScript object |func|, type |functype|, and [=list=] of [=WebAssembly values=] |arguments|, perform the following steps: - 1. Let [parameters] → [|results|] be |functype|. + 1. Let [|parameters|] → [|results|] be |functype|. 1. If |parameters| or |results| contain [=v128=], throw a {{TypeError}}. 1. Let |jsArguments| be « ». 1. [=list/iterate|For each=] |arg| of |arguments|, - 1. [=list/Append=] ! [=ToJSValue=](|arg|) to |jsArguments|. - 1. Let |ret| be ? [=Call=](|func|, undefined, |jsArguments|). + 1. [=list/Append=] [=!=] [=ToJSValue=](|arg|) to |jsArguments|. + 1. Let |ret| be [=?=] [=Call=](|func|, undefined, |jsArguments|). 1. Let |resultsSize| be |results|'s [=list/size=]. 1. If |resultsSize| is 0, return « ». - 1. Otherwise, if |resultsSize| is 1, return « ? [=ToWebAssemblyValue=](|ret|, |results|[0]) ». + 1. Otherwise, if |resultsSize| is 1, return « [=?=] [=ToWebAssemblyValue=](|ret|, |results|[0]) ». 1. Otherwise, - 1. Let |method| be ? [=GetMethod=](|ret|, [=@@iterator=]). + 1. Let |method| be [=?=] [=GetMethod=](|ret|, [=@@iterator=]). 1. If |method| is undefined, [=throw=] a {{TypeError}}. - 1. Let |values| be ? [=IterableToList=](|ret|, |method|). + 1. Let |values| be [=?=] [=IterableToList=](|ret|, |method|). 1. Let |wasmValues| be a new, empty [=list=]. 1. If |values|'s [=list/size=] is not |resultsSize|, throw a {{TypeError}} exception. 1. For each |value| and |resultType| in |values| and |results|, paired linearly, @@ -1109,16 +1112,16 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va 1. Assert: |type| is not [=v128=]. 1. If |type| is [=i64=], - 1. Let |i64| be ? [=ToBigInt64=](|v|). + 1. Let |i64| be [=?=] [=ToBigInt64=](|v|). 1. Return [=i64.const=] |i64|. 1. If |type| is [=i32=], - 1. Let |i32| be ? [=ToInt32=](|v|). + 1. Let |i32| be [=?=] [=ToInt32=](|v|). 1. Return [=i32.const=] |i32|. 1. If |type| is [=f32=], - 1. Let |f32| be ? [=ToNumber=](|v|) rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode. + 1. Let |f32| be [=?=] [=ToNumber=](|v|) rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode. 1. Return [=f32.const=] |f32|. 1. If |type| is [=f64=], - 1. Let |f64| be ? [=ToNumber=](|v|). + 1. Let |f64| be [=?=] [=ToNumber=](|v|). 1. Return [=f64.const=] |f64|. 1. If |type| is [=funcref=], 1. If |v| is null, @@ -1150,7 +1153,7 @@ When the [=namespace object=] for the {{WebAssembly}} namespace is [=create a na 1. Let |namespaceObject| be the [=namespace object=]. 1. [=list/iterate|For each=] |error| of « "CompileError", "LinkError", "RuntimeError" », 1. Let |constructor| be a new object, implementing the [=NativeError Object Structure=], with NativeError set to |error|. - 1. ! [$CreateMethodProperty$](|namespaceObject|, |error|, |constructor|). + 1. [=!=] [$CreateMethodProperty$](|namespaceObject|, |error|, |constructor|).
      diff --git a/document/web-api/index.bs b/document/web-api/index.bs index 602222129..1e74e0941 100644 --- a/document/web-api/index.bs +++ b/document/web-api/index.bs @@ -32,12 +32,6 @@ Prepare For TR: true "title": "WebAssembly JS Integration Specification", "publisher": "W3C WebAssembly Community Group", "status": "Draft" - }, - "SECURECONTEXTS": { - "href": "https://w3c.github.io/webappsec-secure-contexts/", - "title": "Secure Contexts", - "publisher": "WebAppSec WG", - "status": "Candidate Recommendation" } } @@ -71,7 +65,6 @@ urlPrefix: https://webassembly.github.io/spec/js-api/; spec: WASMJS text: Exported Function; url: #exported-function url:https://html.spec.whatwg.org/#cors-same-origin;text:CORS-same-origin;type:dfn;spec:HTML url:https://fetch.spec.whatwg.org/#concept-body-consume-body;text:consume body;type:dfn;spec:FETCH -url:https://w3c.github.io/webappsec-secure-contexts/#environment-settings-object-contextually-secure; text:contextually secure; type: dfn; spec: SECURECONTEXTS
      - To instantiate a WebAssembly module from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps: + To synchronously instantiate a WebAssembly module from a {{Module}} |moduleObject| and imports |importObject|, perform the following steps: 1. Let |module| be |moduleObject|.\[[Module]]. 1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result. 1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result. @@ -499,7 +499,7 @@ The verification of WebAssembly type requirements is deferred to the 1. Let |promise| be [=a new promise=]. 1. [=Upon fulfillment=] of |promiseOfModule| with value |module|: - 1. [=instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, and let |instance| be the result. If this throws an exception, catch it, [=reject=] |promise| with the exception, and abort these substeps. + 1. [=synchronously instantiate a WebAssembly module|Synchronously instantiate the WebAssembly module=] |module| importing |importObject|, and let |instance| be the result. If this throws an exception, catch it, [=reject=] |promise| with the exception, and abort these substeps. 1. Let |result| be the {{WebAssemblyInstantiatedSource}} value «[ "{{WebAssemblyInstantiatedSource/module}}" → |module|, "{{WebAssemblyInstantiatedSource/instance}}" → |instance| ]». 1. [=Resolve=] |promise| with |result|. 1. [=Upon rejection=] of |promiseOfModule| with reason |reason|: From d12e8ff298a05bde8bb2b79281b068accf21749a Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Mon, 18 Mar 2019 10:51:53 +0100 Subject: [PATCH 160/181] Add notes to discourage using synchronous APIs. --- document/js-api/index.bs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 8d7414157..8215da12e 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -604,6 +604,8 @@ interface Module { 1. If |module| is [=error=], throw a {{CompileError}} exception. 1. Set **this**.\[[Module]] to |module|. 1. Set **this**.\[[Bytes]] to |stableBytes|. + +Note: Some implementations enforce a size limitation on |bytes|. Use of this API is discouraged, in favor of asynchronous APIs.

      Instances

      @@ -622,6 +624,8 @@ interface Instance { 1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result. 1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result. 1. [=initialize an instance object|Initialize=] **this** from |module| and |instance|. + +Note: The use of this synchronous API is discouraged, as some implementations sometimes do long-running compilation work when instantiating.
      From f7ac90b08c067a01e103e8da5daee1df92fe254e Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Mon, 18 Mar 2019 10:52:13 +0100 Subject: [PATCH 161/181] [jsapi] Normative: Always queue a task during asynchronous instantiation JSC will have to do asynchronous compilation work during some instantiations. To be consistent, this PR always queues a task to complete instantiation, except through the synchronous Instance(module) API, to ensure consistency across platforms. This patch also cleans up the specification in various surrounding ways: - Include notes about APIs whose use is discouraged/may be limited Closes #741 See also https://github.com/webpack/webpack/issues/6433 --- document/js-api/index.bs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 8215da12e..08754cbc0 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -474,13 +474,15 @@ The verification of WebAssembly type requirements is deferred to the 1. Let |module| be |moduleObject|.\[[Module]]. 1. [=Read the imports=] of |module| with imports |importObject|, and let |imports| be the result. If this operation throws an exception, catch it, [=reject=] |promise| with the exception, and return |promise|. - 1. [=Queue a task=] to perform the following steps: - 1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result. - If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps. - 1. Let |instanceObject| be a [=/new=] {{Instance}}. - 1. [=initialize an instance object|Initialize=] |instanceObject| from |module| and |instance|. - If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps. - 1. [=Resolve=] |promise| with |instanceObject|. + 1. Run the following steps [=in parallel=]: + 1. [=Queue a task=] to perform the following steps: + Note: Implementation-specific work may be performed here. + 1. [=Instantiate the core of a WebAssembly module=] |module| with |imports|, and let |instance| be the result. + If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps. + 1. Let |instanceObject| be a [=/new=] {{Instance}}. + 1. [=initialize an instance object|Initialize=] |instanceObject| from |module| and |instance|. + If this throws an exception, catch it, [=reject=] |promise| with the exception, and terminate these substeps. + 1. [=Resolve=] |promise| with |instanceObject|. 1. Return |promise|.
      @@ -499,14 +501,15 @@ The verification of WebAssembly type requirements is deferred to the 1. Let |promise| be [=a new promise=]. 1. [=Upon fulfillment=] of |promiseOfModule| with value |module|: - 1. [=synchronously instantiate a WebAssembly module|Synchronously instantiate the WebAssembly module=] |module| importing |importObject|, and let |instance| be the result. If this throws an exception, catch it, [=reject=] |promise| with the exception, and abort these substeps. - 1. Let |result| be the {{WebAssemblyInstantiatedSource}} value «[ "{{WebAssemblyInstantiatedSource/module}}" → |module|, "{{WebAssemblyInstantiatedSource/instance}}" → |instance| ]». - 1. [=Resolve=] |promise| with |result|. + 1. [=asynchronously instantiate a WebAssembly module|Instantiate the WebAssembly module=] |module| importing |importObject|, and let |innerPromise| be the result. + 1. [=Upon fulfillment=] of |innerPromise| with value |instance|. + 1. Let |result| be the {{WebAssemblyInstantiatedSource}} value «[ "{{WebAssemblyInstantiatedSource/module}}" → |module|, "{{WebAssemblyInstantiatedSource/instance}}" → |instance| ]». + 1. [=Resolve=] |promise| with |result|. + 1. [=Upon rejection=] of |innerPromise| with reason |reason|: + 1. [=Reject=] |promise| with |reason|. 1. [=Upon rejection=] of |promiseOfModule| with reason |reason|: 1. [=Reject=] |promise| with |reason|. 1. Return |promise|. - - Note: It would be valid to perform certain parts of the instantiation [=in parallel=], but several parts need to happen in the event loop, including JavaScript operations to access the |importObject| and execution of the start function.
      From f7ea587ef83c771ac7a78f5cb7618f396b38271e Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 17 Feb 2023 17:12:31 -0800 Subject: [PATCH 162/181] [test] Exception -> Tag in wasm-module-builder.js The section name has changed to the tag section a few years ago. This adds the corresponding changes added in WebAssembly/exception-handling#252 and WebAssembly/exception-handling#256. --- test/js-api/wasm-module-builder.js | 46 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/test/js-api/wasm-module-builder.js b/test/js-api/wasm-module-builder.js index 7be72f86d..d0f9e78bc 100644 --- a/test/js-api/wasm-module-builder.js +++ b/test/js-api/wasm-module-builder.js @@ -65,7 +65,7 @@ let kElementSectionCode = 9; // Elements section let kCodeSectionCode = 10; // Function code let kDataSectionCode = 11; // Data segments let kDataCountSectionCode = 12; // Data segment count (between Element & Code) -let kExceptionSectionCode = 13; // Exception section (between Global & Export) +let kTagSectionCode = 13; // Tag section (between Memory & Global) // Name section types let kModuleNameCode = 0; @@ -104,13 +104,13 @@ let kExternalFunction = 0; let kExternalTable = 1; let kExternalMemory = 2; let kExternalGlobal = 3; -let kExternalException = 4; +let kExternalTag = 4; let kTableZero = 0; let kMemoryZero = 0; let kSegmentZero = 0; -let kExceptionAttribute = 0; +let kTagAttribute = 0; // Useful signatures let kSig_i_i = makeSig([kWasmI32], [kWasmI32]); @@ -681,7 +681,7 @@ class WasmModuleBuilder { this.exports = []; this.globals = []; this.tables = []; - this.exceptions = []; + this.tags = []; this.functions = []; this.element_segments = []; this.data_segments = []; @@ -689,7 +689,7 @@ class WasmModuleBuilder { this.num_imported_funcs = 0; this.num_imported_globals = 0; this.num_imported_tables = 0; - this.num_imported_exceptions = 0; + this.num_imported_tags = 0; return this; } @@ -752,11 +752,11 @@ class WasmModuleBuilder { return table; } - addException(type) { + addTag(type) { let type_index = (typeof type) == "number" ? type : this.addType(type); - let except_index = this.exceptions.length + this.num_imported_exceptions; - this.exceptions.push(type_index); - return except_index; + let tag_index = this.tags.length + this.num_imported_tags; + this.tags.push(type_index); + return tag_index; } addFunction(name, type) { @@ -804,14 +804,14 @@ class WasmModuleBuilder { return this.num_imported_tables++; } - addImportedException(module, name, type) { - if (this.exceptions.length != 0) { - throw new Error('Imported exceptions must be declared before local ones'); + addImportedTag(module, name, type) { + if (this.tags.length != 0) { + throw new Error('Imported tags must be declared before local ones'); } let type_index = (typeof type) == "number" ? type : this.addType(type); - let o = {module: module, name: name, kind: kExternalException, type: type_index}; + let o = {module: module, name: name, kind: kExternalTag, type: type_index}; this.imports.push(o); - return this.num_imported_exceptions++; + return this.num_imported_tags++; } addExport(name, index) { @@ -938,8 +938,8 @@ class WasmModuleBuilder { section.emit_u8(has_max ? 1 : 0); // flags section.emit_u32v(imp.initial); // initial if (has_max) section.emit_u32v(imp.maximum); // maximum - } else if (imp.kind == kExternalException) { - section.emit_u32v(kExceptionAttribute); + } else if (imp.kind == kExternalTag) { + section.emit_u32v(kTagAttribute); section.emit_u32v(imp.type); } else { throw new Error("unknown/unsupported import kind " + imp.kind); @@ -1036,13 +1036,13 @@ class WasmModuleBuilder { }); } - // Add exceptions. - if (wasm.exceptions.length > 0) { - if (debug) print("emitting exceptions @ " + binary.length); - binary.emit_section(kExceptionSectionCode, section => { - section.emit_u32v(wasm.exceptions.length); - for (let type of wasm.exceptions) { - section.emit_u32v(kExceptionAttribute); + // Add tags. + if (wasm.tags.length > 0) { + if (debug) print("emitting tags @ " + binary.length); + binary.emit_section(kTagSectionCode, section => { + section.emit_u32v(wasm.tags.length); + for (let type of wasm.tags) { + section.emit_u32v(kTagAttribute); section.emit_u32v(type); } }); From 541abcbcf2e10904d8ff34ce6bb9028cc3cc679f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 22 Feb 2023 12:43:02 +0100 Subject: [PATCH 163/181] [spec] Fix reduction rule for label (#1612) Fix #1605. --- document/core/exec/instructions.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index 7056de745..e4d77cdb8 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -2868,22 +2868,20 @@ Exiting :math:`\instr^\ast` with label :math:`L` When the end of a block is reached without a jump or trap aborting it, then the following steps are performed. -1. Let :math:`n` be the number of values on the top of the stack. +1. Pop all values :math:`\val^\ast` from the top of the stack. -2. Pop the values :math:`\val^n` from the stack. +2. Assert: due to :ref:`validation `, the label :math:`L` is now on the top of the stack. -3. Assert: due to :ref:`validation `, the label :math:`L` is now on the top of the stack and has arity :math:`n`. +3. Pop the label from the stack. -4. Pop the label from the stack. +4. Push :math:`\val^\ast` back to the stack. -5. Push :math:`\val^n` back to the stack. - -6. Jump to the position after the |END| of the :ref:`structured control instruction ` associated with the label :math:`L`. +5. Jump to the position after the |END| of the :ref:`structured control instruction ` associated with the label :math:`L`. .. math:: ~\\[-1ex] \begin{array}{lcl@{\qquad}l} - \LABEL_n\{\instr^\ast\}~\val^n~\END &\stepto& \val^n + \LABEL_n\{\instr^\ast\}~\val^\ast~\END &\stepto& \val^\ast \end{array} .. note:: From 218c93e47d6c80759eb14dd742001f42fb27f9c0 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 22 Feb 2023 18:20:55 +0100 Subject: [PATCH 164/181] [spec] Clarifying note about canonical NaNs (#1614) --- document/core/syntax/values.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/document/core/syntax/values.rst b/document/core/syntax/values.rst index 564ddc2d6..1b155df42 100644 --- a/document/core/syntax/values.rst +++ b/document/core/syntax/values.rst @@ -140,6 +140,8 @@ An *arithmetic NaN* is a floating-point value :math:`\pm\NAN(n)` with :math:`n .. note:: In the abstract syntax, subnormals are distinguished by the leading 0 of the significand. The exponent of subnormals has the same value as the smallest possible exponent of a normal number. Only in the :ref:`binary representation ` the exponent of a subnormal is encoded differently than the exponent of any normal number. + The notion of canonical NaN defined here is unrelated to the notion of canonical NaN that the |IEEE754|_ standard (Section 3.5.2) defines for decimal interchange formats. + Conventions ........... From 28846ac5d41b49f4b83e6ffc180c5da59c4fdab1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 22 Feb 2023 21:14:40 +0100 Subject: [PATCH 165/181] [spec] Tweak crossref --- document/core/util/macros.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/document/core/util/macros.def b/document/core/util/macros.def index aaefc4069..3ab6d5480 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -9,7 +9,7 @@ .. |WasmIssues| replace:: |issuelink| .. _WasmIssues: |issuelink| -.. |IEEE754| replace:: IEEE 754-2019 +.. |IEEE754| replace:: IEEE 754 .. _IEEE754: https://ieeexplore.ieee.org/document/8766229 .. |Unicode| replace:: Unicode From be3dc78f1cc6fe2aae63a494288d942c0d9d55f4 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 23 Feb 2023 00:00:44 -0800 Subject: [PATCH 166/181] [test] Fix invalid section ID tests (#1615) --- .github/workflows/main.yml | 2 +- test/core/binary.wast | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b64d31bb3..a158de1ee 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v1 with: - node-version: 18.x + node-version: 19.x - run: cd interpreter && opam exec make JS=node all ref-interpreter-js-library: diff --git a/test/core/binary.wast b/test/core/binary.wast index fb3037ae0..a00bb9b47 100644 --- a/test/core/binary.wast +++ b/test/core/binary.wast @@ -45,11 +45,11 @@ (assert_malformed (module binary "\00asm\00\00\00\01") "unknown binary version") ;; Invalid section id. -(assert_malformed (module binary "\00asm" "\01\00\00\00" "\0d\00") "malformed section id") -(assert_malformed (module binary "\00asm" "\01\00\00\00" "\7f\00") "malformed section id") -(assert_malformed (module binary "\00asm" "\01\00\00\00" "\80\00\01\00") "malformed section id") -(assert_malformed (module binary "\00asm" "\01\00\00\00" "\81\00\01\00") "malformed section id") -(assert_malformed (module binary "\00asm" "\01\00\00\00" "\ff\00\01\00") "malformed section id") +(assert_malformed (module binary "\00asm" "\01\00\00\00" "\0e\01\00") "malformed section id") +(assert_malformed (module binary "\00asm" "\01\00\00\00" "\7f\01\00") "malformed section id") +(assert_malformed (module binary "\00asm" "\01\00\00\00" "\80\01\00\01\01\00") "malformed section id") +(assert_malformed (module binary "\00asm" "\01\00\00\00" "\81\01\00\01\01\00") "malformed section id") +(assert_malformed (module binary "\00asm" "\01\00\00\00" "\ff\01\00\01\01\00") "malformed section id") ;; Unsigned LEB128 can have non-minimal length (module binary From 3c5772d5007dae1bd656e6adbf9afe5dbb7b1d44 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 1 Mar 2023 09:43:47 +0100 Subject: [PATCH 167/181] [spec] Don't check in generated index, to avoid spurious merge conflicts --- document/core/.gitignore | 1 + document/core/Makefile | 1 + document/core/appendix/index-instructions.rst | 523 ------------------ 3 files changed, 2 insertions(+), 523 deletions(-) delete mode 100644 document/core/appendix/index-instructions.rst diff --git a/document/core/.gitignore b/document/core/.gitignore index b932ec283..d21e55e36 100644 --- a/document/core/.gitignore +++ b/document/core/.gitignore @@ -1,3 +1,4 @@ _build _static document/*.pyc +appendix/index-instructions.rst diff --git a/document/core/Makefile b/document/core/Makefile index 3ff1a87cb..bfbf70bfc 100644 --- a/document/core/Makefile +++ b/document/core/Makefile @@ -103,6 +103,7 @@ pdf: index latexpdf clean: rm -rf $(BUILDDIR) rm -rf $(STATICDIR) + rm -f appendix/index-instructions.rst .PHONY: html html: index diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst deleted file mode 100644 index 977c21fb3..000000000 --- a/document/core/appendix/index-instructions.rst +++ /dev/null @@ -1,523 +0,0 @@ -.. DO NOT EDIT: This file is auto-generated by the gen-index-instructions.py script. - -.. index:: instruction -.. _index-instr: - -Index of Instructions ---------------------- - -================================================= ==================================== ============================================= ============================================= ================================================================== -Instruction Binary Opcode Type Validation Execution -================================================= ==================================== ============================================= ============================================= ================================================================== -:math:`\UNREACHABLE` :math:`\hex{00}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\NOP` :math:`\hex{01}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\BLOCK~\X{bt}` :math:`\hex{02}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\LOOP~\X{bt}` :math:`\hex{03}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\IF~\X{bt}` :math:`\hex{04}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\ELSE` :math:`\hex{05}` -(reserved) :math:`\hex{06}` -(reserved) :math:`\hex{07}` -(reserved) :math:`\hex{08}` -(reserved) :math:`\hex{09}` -(reserved) :math:`\hex{0A}` -:math:`\END` :math:`\hex{0B}` -:math:`\BR~l` :math:`\hex{0C}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\BRIF~l` :math:`\hex{0D}` :math:`[t^\ast~\I32] \to [t^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\BRTABLE~l^\ast~l` :math:`\hex{0E}` :math:`[t_1^\ast~t^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\RETURN` :math:`\hex{0F}` :math:`[t_1^\ast~t^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\CALL~x` :math:`\hex{10}` :math:`[t_1^\ast] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -:math:`\CALLINDIRECT~x~y` :math:`\hex{11}` :math:`[t_1^\ast~\I32] \to [t_2^\ast]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{12}` -(reserved) :math:`\hex{13}` -(reserved) :math:`\hex{14}` -(reserved) :math:`\hex{15}` -(reserved) :math:`\hex{16}` -(reserved) :math:`\hex{17}` -(reserved) :math:`\hex{18}` -(reserved) :math:`\hex{19}` -:math:`\DROP` :math:`\hex{1A}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\SELECT` :math:`\hex{1B}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\SELECT~t` :math:`\hex{1C}` :math:`[t~t~\I32] \to [t]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{1D}` -(reserved) :math:`\hex{1E}` -(reserved) :math:`\hex{1F}` -:math:`\LOCALGET~x` :math:`\hex{20}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\LOCALSET~x` :math:`\hex{21}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\LOCALTEE~x` :math:`\hex{22}` :math:`[t] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\GLOBALGET~x` :math:`\hex{23}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\GLOBALSET~x` :math:`\hex{24}` :math:`[t] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEGET~x` :math:`\hex{25}` :math:`[\I32] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\TABLESET~x` :math:`\hex{26}` :math:`[\I32~t] \to []` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{27}` -:math:`\I32.\LOAD~\memarg` :math:`\hex{28}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD~\memarg` :math:`\hex{29}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\F32.\LOAD~\memarg` :math:`\hex{2A}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F64.\LOAD~\memarg` :math:`\hex{2B}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{8\_s}~\memarg` :math:`\hex{2C}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{8\_u}~\memarg` :math:`\hex{2D}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{16\_s}~\memarg` :math:`\hex{2E}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\LOAD\K{16\_u}~\memarg` :math:`\hex{2F}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{8\_s}~\memarg` :math:`\hex{30}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{8\_u}~\memarg` :math:`\hex{31}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{16\_s}~\memarg` :math:`\hex{32}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{16\_u}~\memarg` :math:`\hex{33}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{32\_s}~\memarg` :math:`\hex{34}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\LOAD\K{32\_u}~\memarg` :math:`\hex{35}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE~\memarg` :math:`\hex{36}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE~\memarg` :math:`\hex{37}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\F32.\STORE~\memarg` :math:`\hex{38}` :math:`[\I32~\F32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\F64.\STORE~\memarg` :math:`\hex{39}` :math:`[\I32~\F64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE\K{8}~\memarg` :math:`\hex{3A}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I32.\STORE\K{16}~\memarg` :math:`\hex{3B}` :math:`[\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{8}~\memarg` :math:`\hex{3C}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{16}~\memarg` :math:`\hex{3D}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\I64.\STORE\K{32}~\memarg` :math:`\hex{3E}` :math:`[\I32~\I64] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYSIZE` :math:`\hex{3F}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYGROW` :math:`\hex{40}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\CONST~\i32` :math:`\hex{41}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64.\CONST~\i64` :math:`\hex{42}` :math:`[] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\F32.\CONST~\f32` :math:`\hex{43}` :math:`[] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F64.\CONST~\f64` :math:`\hex{44}` :math:`[] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\I32.\EQZ` :math:`\hex{45}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EQ` :math:`\hex{46}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\NE` :math:`\hex{47}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LT\K{\_s}` :math:`\hex{48}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LT\K{\_u}` :math:`\hex{49}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GT\K{\_s}` :math:`\hex{4A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GT\K{\_u}` :math:`\hex{4B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LE\K{\_s}` :math:`\hex{4C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\LE\K{\_u}` :math:`\hex{4D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GE\K{\_s}` :math:`\hex{4E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\GE\K{\_u}` :math:`\hex{4F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EQZ` :math:`\hex{50}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EQ` :math:`\hex{51}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\NE` :math:`\hex{52}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LT\K{\_s}` :math:`\hex{53}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LT\K{\_u}` :math:`\hex{54}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GT\K{\_s}` :math:`\hex{55}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GT\K{\_u}` :math:`\hex{56}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LE\K{\_s}` :math:`\hex{57}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\LE\K{\_u}` :math:`\hex{58}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GE\K{\_s}` :math:`\hex{59}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\GE\K{\_u}` :math:`\hex{5A}` :math:`[\I64~\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\EQ` :math:`\hex{5B}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NE` :math:`\hex{5C}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\LT` :math:`\hex{5D}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\GT` :math:`\hex{5E}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\LE` :math:`\hex{5F}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\GE` :math:`\hex{60}` :math:`[\F32~\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\EQ` :math:`\hex{61}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NE` :math:`\hex{62}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\LT` :math:`\hex{63}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\GT` :math:`\hex{64}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\LE` :math:`\hex{65}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\GE` :math:`\hex{66}` :math:`[\F64~\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\CLZ` :math:`\hex{67}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\CTZ` :math:`\hex{68}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\POPCNT` :math:`\hex{69}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ADD` :math:`\hex{6A}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SUB` :math:`\hex{6B}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\MUL` :math:`\hex{6C}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\DIV\K{\_s}` :math:`\hex{6D}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\DIV\K{\_u}` :math:`\hex{6E}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REM\K{\_s}` :math:`\hex{6F}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REM\K{\_u}` :math:`\hex{70}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\AND` :math:`\hex{71}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\OR` :math:`\hex{72}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\XOR` :math:`\hex{73}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHL` :math:`\hex{74}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHR\K{\_s}` :math:`\hex{75}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\SHR\K{\_u}` :math:`\hex{76}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ROTL` :math:`\hex{77}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\ROTR` :math:`\hex{78}` :math:`[\I32~\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\CLZ` :math:`\hex{79}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\CTZ` :math:`\hex{7A}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\POPCNT` :math:`\hex{7B}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ADD` :math:`\hex{7C}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SUB` :math:`\hex{7D}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\MUL` :math:`\hex{7E}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\DIV\K{\_s}` :math:`\hex{7F}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\DIV\K{\_u}` :math:`\hex{80}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REM\K{\_s}` :math:`\hex{81}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REM\K{\_u}` :math:`\hex{82}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\AND` :math:`\hex{83}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\OR` :math:`\hex{84}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\XOR` :math:`\hex{85}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHL` :math:`\hex{86}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHR\K{\_s}` :math:`\hex{87}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\SHR\K{\_u}` :math:`\hex{88}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ROTL` :math:`\hex{89}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\ROTR` :math:`\hex{8A}` :math:`[\I64~\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\ABS` :math:`\hex{8B}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NEG` :math:`\hex{8C}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CEIL` :math:`\hex{8D}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FLOOR` :math:`\hex{8E}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\TRUNC` :math:`\hex{8F}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\NEAREST` :math:`\hex{90}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\SQRT` :math:`\hex{91}` :math:`[\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\ADD` :math:`\hex{92}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\SUB` :math:`\hex{93}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\MUL` :math:`\hex{94}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\DIV` :math:`\hex{95}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FMIN` :math:`\hex{96}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\FMAX` :math:`\hex{97}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\COPYSIGN` :math:`\hex{98}` :math:`[\F32~\F32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\ABS` :math:`\hex{99}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NEG` :math:`\hex{9A}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CEIL` :math:`\hex{9B}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FLOOR` :math:`\hex{9C}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\TRUNC` :math:`\hex{9D}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\NEAREST` :math:`\hex{9E}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\SQRT` :math:`\hex{9F}` :math:`[\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\ADD` :math:`\hex{A0}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\SUB` :math:`\hex{A1}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\MUL` :math:`\hex{A2}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\DIV` :math:`\hex{A3}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FMIN` :math:`\hex{A4}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\FMAX` :math:`\hex{A5}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\COPYSIGN` :math:`\hex{A6}` :math:`[\F64~\F64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\WRAP\K{\_}\I64` :math:`\hex{A7}` :math:`[\I64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{A8}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{A9}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{AA}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{AB}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{\_}\I32\K{\_s}` :math:`\hex{AC}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{\_}\I32\K{\_u}` :math:`\hex{AD}` :math:`[\I32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F32\K{\_s}` :math:`\hex{AE}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F32\K{\_u}` :math:`\hex{AF}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F64\K{\_s}` :math:`\hex{B0}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_}\F64\K{\_u}` :math:`\hex{B1}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B2}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B3}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B4}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{B5}` :math:`[\I64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\DEMOTE\K{\_}\F64` :math:`\hex{B6}` :math:`[\F64] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I32\K{\_s}` :math:`\hex{B7}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I32\K{\_u}` :math:`\hex{B8}` :math:`[\I32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I64\K{\_s}` :math:`\hex{B9}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\CONVERT\K{\_}\I64\K{\_u}` :math:`\hex{BA}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\PROMOTE\K{\_}\F32` :math:`\hex{BB}` :math:`[\F32] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\REINTERPRET\K{\_}\F32` :math:`\hex{BC}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\REINTERPRET\K{\_}\F64` :math:`\hex{BD}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32.\REINTERPRET\K{\_}\I32` :math:`\hex{BE}` :math:`[\I32] \to [\F32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64.\REINTERPRET\K{\_}\I64` :math:`\hex{BF}` :math:`[\I64] \to [\F64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EXTEND\K{8\_s}` :math:`\hex{C0}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\EXTEND\K{16\_s}` :math:`\hex{C1}` :math:`[\I32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{8\_s}` :math:`\hex{C2}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{16\_s}` :math:`\hex{C3}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\EXTEND\K{32\_s}` :math:`\hex{C4}` :math:`[\I64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -(reserved) :math:`\hex{C5}` -(reserved) :math:`\hex{C6}` -(reserved) :math:`\hex{C7}` -(reserved) :math:`\hex{C8}` -(reserved) :math:`\hex{C9}` -(reserved) :math:`\hex{CA}` -(reserved) :math:`\hex{CB}` -(reserved) :math:`\hex{CC}` -(reserved) :math:`\hex{CD}` -(reserved) :math:`\hex{CE}` -(reserved) :math:`\hex{CF}` -:math:`\REFNULL~t` :math:`\hex{D0}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` -:math:`\REFISNULL` :math:`\hex{D1}` :math:`[t] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\REFFUNC~x` :math:`\hex{D2}` :math:`[] \to [\FUNCREF]` :ref:`validation ` :ref:`execution ` -(reserved) :math:`\hex{D3}` -(reserved) :math:`\hex{D4}` -(reserved) :math:`\hex{D5}` -(reserved) :math:`\hex{D6}` -(reserved) :math:`\hex{D7}` -(reserved) :math:`\hex{D8}` -(reserved) :math:`\hex{D9}` -(reserved) :math:`\hex{DA}` -(reserved) :math:`\hex{DB}` -(reserved) :math:`\hex{DC}` -(reserved) :math:`\hex{DD}` -(reserved) :math:`\hex{DE}` -(reserved) :math:`\hex{DF}` -(reserved) :math:`\hex{E0}` -(reserved) :math:`\hex{E1}` -(reserved) :math:`\hex{E2}` -(reserved) :math:`\hex{E3}` -(reserved) :math:`\hex{E4}` -(reserved) :math:`\hex{E5}` -(reserved) :math:`\hex{E6}` -(reserved) :math:`\hex{E7}` -(reserved) :math:`\hex{E8}` -(reserved) :math:`\hex{E9}` -(reserved) :math:`\hex{EA}` -(reserved) :math:`\hex{EB}` -(reserved) :math:`\hex{EC}` -(reserved) :math:`\hex{ED}` -(reserved) :math:`\hex{EE}` -(reserved) :math:`\hex{EF}` -(reserved) :math:`\hex{F0}` -(reserved) :math:`\hex{F1}` -(reserved) :math:`\hex{F2}` -(reserved) :math:`\hex{F3}` -(reserved) :math:`\hex{F4}` -(reserved) :math:`\hex{F5}` -(reserved) :math:`\hex{F6}` -(reserved) :math:`\hex{F7}` -(reserved) :math:`\hex{F8}` -(reserved) :math:`\hex{F9}` -(reserved) :math:`\hex{FA}` -(reserved) :math:`\hex{FB}` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{00}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{01}` :math:`[\F32] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{02}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{03}` :math:`[\F64] \to [\I32]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_s}` :math:`\hex{FC}~\hex{04}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F32\K{\_u}` :math:`\hex{FC}~\hex{05}` :math:`[\F32] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_s}` :math:`\hex{FC}~\hex{06}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64.\TRUNC\K{\_sat\_}\F64\K{\_u}` :math:`\hex{FC}~\hex{07}` :math:`[\F64] \to [\I64]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\MEMORYINIT~x` :math:`\hex{FC}~\hex{08}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\DATADROP~x` :math:`\hex{FC}~\hex{09}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYCOPY` :math:`\hex{FC}~\hex{0A}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\MEMORYFILL` :math:`\hex{FC}~\hex{0B}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEINIT~x~y` :math:`\hex{FC}~\hex{0C}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\ELEMDROP~x` :math:`\hex{FC}~\hex{0D}` :math:`[] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLECOPY~x~y` :math:`\hex{FC}~\hex{0E}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\TABLEGROW~x` :math:`\hex{FC}~\hex{0F}` :math:`[t~\I32] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\TABLESIZE~x` :math:`\hex{FC}~\hex{10}` :math:`[] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\TABLEFILL~x` :math:`\hex{FC}~\hex{11}` :math:`[\I32~t~\I32] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD~\memarg` :math:`\hex{FD}~~\hex{00}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{8x8\_s}~\memarg` :math:`\hex{FD}~~\hex{01}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{8x8\_u}~\memarg` :math:`\hex{FD}~~\hex{02}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{16x4\_s}~\memarg` :math:`\hex{FD}~~\hex{03}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{16x4\_u}~\memarg` :math:`\hex{FD}~~\hex{04}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32x2\_s}~\memarg` :math:`\hex{FD}~~\hex{05}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32x2\_u}~\memarg` :math:`\hex{FD}~~\hex{06}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{8\_splat}~\memarg` :math:`\hex{FD}~~\hex{07}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{16\_splat}~\memarg` :math:`\hex{FD}~~\hex{08}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32\_splat}~\memarg` :math:`\hex{FD}~~\hex{09}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{64\_splat}~\memarg` :math:`\hex{FD}~~\hex{0A}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE~\memarg` :math:`\hex{FD}~~\hex{0B}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\VCONST~\i128` :math:`\hex{FD}~~\hex{0C}` :math:`[] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SHUFFLE~\laneidx^{16}` :math:`\hex{FD}~~\hex{0D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SWIZZLE` :math:`\hex{FD}~~\hex{0E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\SPLAT` :math:`\hex{FD}~~\hex{0F}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\SPLAT` :math:`\hex{FD}~~\hex{10}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\SPLAT` :math:`\hex{FD}~~\hex{11}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\SPLAT` :math:`\hex{FD}~~\hex{12}` :math:`[\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\SPLAT` :math:`\hex{FD}~~\hex{13}` :math:`[\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\SPLAT` :math:`\hex{FD}~~\hex{14}` :math:`[\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{15}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{16}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{17}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTRACTLANE\K{\_s}~\laneidx` :math:`\hex{FD}~~\hex{18}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTRACTLANE\K{\_u}~\laneidx` :math:`\hex{FD}~~\hex{19}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1A}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1B}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1D}` :math:`[\V128] \to [\I64]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{1E}` :math:`[\V128~\I64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{1F}` :math:`[\V128] \to [\F32]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{20}` :math:`[\V128~\F32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\EXTRACTLANE~\laneidx` :math:`\hex{FD}~~\hex{21}` :math:`[\V128] \to [\F64]` :ref:`validation ` :ref:`execution ` -:math:`\F64X2.\REPLACELANE~\laneidx` :math:`\hex{FD}~~\hex{22}` :math:`[\V128~\F64] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\VEQ` :math:`\hex{FD}~~\hex{23}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VNE` :math:`\hex{FD}~~\hex{24}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{25}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{26}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{27}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{28}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{29}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{2A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{2B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{2C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VEQ` :math:`\hex{FD}~~\hex{2D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VNE` :math:`\hex{FD}~~\hex{2E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{2F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{30}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{31}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{32}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{33}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{34}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{35}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{36}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VEQ` :math:`\hex{FD}~~\hex{37}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VNE` :math:`\hex{FD}~~\hex{38}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{39}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLT\K{\_u}` :math:`\hex{FD}~~\hex{3A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{3B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGT\K{\_u}` :math:`\hex{FD}~~\hex{3C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{3D}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VLE\K{\_u}` :math:`\hex{FD}~~\hex{3E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{3F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VGE\K{\_u}` :math:`\hex{FD}~~\hex{40}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VEQ` :math:`\hex{FD}~~\hex{41}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNE` :math:`\hex{FD}~~\hex{42}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VLT` :math:`\hex{FD}~~\hex{43}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VGT` :math:`\hex{FD}~~\hex{44}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VLE` :math:`\hex{FD}~~\hex{45}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VGE` :math:`\hex{FD}~~\hex{46}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VEQ` :math:`\hex{FD}~~\hex{47}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNE` :math:`\hex{FD}~~\hex{48}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VLT` :math:`\hex{FD}~~\hex{49}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VGT` :math:`\hex{FD}~~\hex{4A}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VLE` :math:`\hex{FD}~~\hex{4B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VGE` :math:`\hex{FD}~~\hex{4C}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VNOT` :math:`\hex{FD}~~\hex{4D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VAND` :math:`\hex{FD}~~\hex{4E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VANDNOT` :math:`\hex{FD}~~\hex{4F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VOR` :math:`\hex{FD}~~\hex{50}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\VXOR` :math:`\hex{FD}~~\hex{51}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\BITSELECT` :math:`\hex{FD}~~\hex{52}` :math:`[\V128~\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\V128.\ANYTRUE` :math:`\hex{FD}~~\hex{53}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{54}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{55}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{56}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{57}` :math:`[\I32~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{8\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{58}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{16\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{59}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{32\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5A}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\STORE\K{64\_lane}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5B}` :math:`[\I32~\V128] \to []` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{32\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5C}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\V128.\LOAD\K{64\_zero}~\memarg~\laneidx` :math:`\hex{FD}~~\hex{5D}` :math:`[\I32] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VDEMOTE\K{\_f64x2\_zero}` :math:`\hex{FD}~~\hex{5E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPROMOTE\K{\_low\_f32x4}` :math:`\hex{FD}~~\hex{5F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VABS` :math:`\hex{FD}~~\hex{60}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VNEG` :math:`\hex{FD}~~\hex{61}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VPOPCNT` :math:`\hex{FD}~~\hex{62}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\ALLTRUE` :math:`\hex{FD}~~\hex{63}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\BITMASK` :math:`\hex{FD}~~\hex{64}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\NARROW\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{65}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I8X16.\NARROW\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{66}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VCEIL` :math:`\hex{FD}~~\hex{67}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VFLOOR` :math:`\hex{FD}~~\hex{68}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VTRUNC` :math:`\hex{FD}~~\hex{69}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNEAREST` :math:`\hex{FD}~~\hex{6A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHL` :math:`\hex{FD}~~\hex{6B}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{6C}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{6D}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD` :math:`\hex{FD}~~\hex{6E}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{6F}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{70}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB` :math:`\hex{FD}~~\hex{71}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{72}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{73}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCEIL` :math:`\hex{FD}~~\hex{74}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VFLOOR` :math:`\hex{FD}~~\hex{75}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{76}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{77}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{78}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{79}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VTRUNC` :math:`\hex{FD}~~\hex{7A}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I8X16.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{7B}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_s}` :math:`\hex{FD}~~\hex{7C}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTADDPAIRWISE\K{\_i8x16\_u}` :math:`\hex{FD}~~\hex{7D}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{7E}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTADDPAIRWISE\K{\_i16x8\_u}` :math:`\hex{FD}~~\hex{7F}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VABS` :math:`\hex{FD}~~\hex{80}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VNEG` :math:`\hex{FD}~~\hex{81}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\Q15MULRSAT\K{\_s}` :math:`\hex{FD}~~\hex{82}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\ALLTRUE` :math:`\hex{FD}~~\hex{83}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\BITMASK` :math:`\hex{FD}~~\hex{84}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\NARROW\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{85}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\NARROW\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{86}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{87}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{88}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{89}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VEXTEND\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{8A}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\VSHL` :math:`\hex{FD}~~\hex{8B}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{8C}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{8D}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD` :math:`\hex{FD}~~\hex{8E}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD\K{\_sat\_s}` :math:`\hex{FD}~~\hex{8F}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VADD\K{\_sat\_u}` :math:`\hex{FD}~~\hex{90}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB` :math:`\hex{FD}~~\hex{91}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB\K{\_sat\_s}` :math:`\hex{FD}~~\hex{92}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VSUB\K{\_sat\_u}` :math:`\hex{FD}~~\hex{93}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNEAREST` :math:`\hex{FD}~~\hex{94}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMUL` :math:`\hex{FD}~~\hex{95}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{96}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{97}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{98}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{99}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\AVGR\K{\_u}` :math:`\hex{FD}~~\hex{9B}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_s}` :math:`\hex{FD}~~\hex{9C}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_s}` :math:`\hex{FD}~~\hex{9D}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_low\_i8x16\_u}` :math:`\hex{FD}~~\hex{9E}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I16X8.\EXTMUL\K{\_high\_i8x16\_u}` :math:`\hex{FD}~~\hex{9F}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VABS` :math:`\hex{FD}~~\hex{A0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VNEG` :math:`\hex{FD}~~\hex{A1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\ALLTRUE` :math:`\hex{FD}~~\hex{A3}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\BITMASK` :math:`\hex{FD}~~\hex{A4}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{A7}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{A8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{A9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VEXTEND\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{AA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\VSHL` :math:`\hex{FD}~~\hex{AB}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{AC}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{AD}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VADD` :math:`\hex{FD}~~\hex{AE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VSUB` :math:`\hex{FD}~~\hex{B1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMUL` :math:`\hex{FD}~~\hex{B5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMIN\K{\_s}` :math:`\hex{FD}~~\hex{B6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMIN\K{\_u}` :math:`\hex{FD}~~\hex{B7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMAX\K{\_s}` :math:`\hex{FD}~~\hex{B8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VMAX\K{\_u}` :math:`\hex{FD}~~\hex{B9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\DOT\K{\_i16x8\_s}` :math:`\hex{FD}~~\hex{BA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_s}` :math:`\hex{FD}~~\hex{BC}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_s}` :math:`\hex{FD}~~\hex{BD}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_low\_i16x8\_u}` :math:`\hex{FD}~~\hex{BE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I32X4.\EXTMUL\K{\_high\_i16x8\_u}` :math:`\hex{FD}~~\hex{BF}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VABS` :math:`\hex{FD}~~\hex{C0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VNEG` :math:`\hex{FD}~~\hex{C1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\ALLTRUE` :math:`\hex{FD}~~\hex{C3}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\BITMASK` :math:`\hex{FD}~~\hex{C4}~~\hex{01}` :math:`[\V128] \to [\I32]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{C7}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{C8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{C9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VEXTEND\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{CA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\VSHL` :math:`\hex{FD}~~\hex{CB}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSHR\K{\_s}` :math:`\hex{FD}~~\hex{CC}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSHR\K{\_u}` :math:`\hex{FD}~~\hex{CD}~~\hex{01}` :math:`[\V128~\I32] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VADD` :math:`\hex{FD}~~\hex{CE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VSUB` :math:`\hex{FD}~~\hex{D1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VMUL` :math:`\hex{FD}~~\hex{D5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VEQ` :math:`\hex{FD}~~\hex{D6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VNE` :math:`\hex{FD}~~\hex{D7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VLT\K{\_s}` :math:`\hex{FD}~~\hex{D8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VGT\K{\_s}` :math:`\hex{FD}~~\hex{D9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VLE\K{\_s}` :math:`\hex{FD}~~\hex{DA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\VGE\K{\_s}` :math:`\hex{FD}~~\hex{DB}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{DC}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_s}` :math:`\hex{FD}~~\hex{DD}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{DE}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\I64X2.\EXTMUL\K{\_high\_i32x4\_u}` :math:`\hex{FD}~~\hex{DF}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution ` -:math:`\F32X4.\VABS` :math:`\hex{FD}~~\hex{E0}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VNEG` :math:`\hex{FD}~~\hex{E1}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VSQRT` :math:`\hex{FD}~~\hex{E3}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VADD` :math:`\hex{FD}~~\hex{E4}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VSUB` :math:`\hex{FD}~~\hex{E5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMUL` :math:`\hex{FD}~~\hex{E6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VDIV` :math:`\hex{FD}~~\hex{E7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMIN` :math:`\hex{FD}~~\hex{E8}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VMAX` :math:`\hex{FD}~~\hex{E9}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VPMIN` :math:`\hex{FD}~~\hex{EA}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VPMAX` :math:`\hex{FD}~~\hex{EB}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VABS` :math:`\hex{FD}~~\hex{EC}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VNEG` :math:`\hex{FD}~~\hex{ED}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VSQRT` :math:`\hex{FD}~~\hex{EF}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VADD` :math:`\hex{FD}~~\hex{F0}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VSUB` :math:`\hex{FD}~~\hex{F1}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMUL` :math:`\hex{FD}~~\hex{F2}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VDIV` :math:`\hex{FD}~~\hex{F3}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMIN` :math:`\hex{FD}~~\hex{F4}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VMAX` :math:`\hex{FD}~~\hex{F5}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPMIN` :math:`\hex{FD}~~\hex{F6}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VPMAX` :math:`\hex{FD}~~\hex{F7}~~\hex{01}` :math:`[\V128~\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_s}` :math:`\hex{FD}~~\hex{F8}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\TRUNC\K{\_sat\_f32x4\_u}` :math:`\hex{FD}~~\hex{F9}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VCONVERT\K{\_i32x4\_s}` :math:`\hex{FD}~~\hex{FA}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F32X4.\VCONVERT\K{\_i32x4\_u}` :math:`\hex{FD}~~\hex{FB}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_s\_zero}` :math:`\hex{FD}~~\hex{FC}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\I32X4.\VTRUNC\K{\_sat\_f64x2\_u\_zero}` :math:`\hex{FD}~~\hex{FD}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_s}` :math:`\hex{FD}~~\hex{FE}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -:math:`\F64X2.\VCONVERT\K{\_low\_i32x4\_u}` :math:`\hex{FD}~~\hex{FF}~~\hex{01}` :math:`[\V128] \to [\V128]` :ref:`validation ` :ref:`execution `, :ref:`operator ` -================================================= ==================================== ============================================= ============================================= ================================================================== - -.. note:: - Multi-byte opcodes are given with the shortest possible encoding in the table. - However, what is following the first byte is actually a :ref:`u32 ` with variable-length encoding - and consequently has multiple possible representations. From b0d907c542fa2ef30822421ab1f9b2f897c05bee Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 1 Mar 2023 09:50:47 +0100 Subject: [PATCH 168/181] [spec] Rename script --- document/core/Makefile | 2 +- .../{gen-index-instructions.py => index-instructions.py} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename document/core/appendix/{gen-index-instructions.py => index-instructions.py} (99%) diff --git a/document/core/Makefile b/document/core/Makefile index bfbf70bfc..d8b357c73 100644 --- a/document/core/Makefile +++ b/document/core/Makefile @@ -91,7 +91,7 @@ bikeshed-keep: .PHONY: index index: - (cd appendix; ./gen-index-instructions.py) + (cd appendix; ./index-instructions.py) .PHONY: pdf pdf: index latexpdf diff --git a/document/core/appendix/gen-index-instructions.py b/document/core/appendix/index-instructions.py similarity index 99% rename from document/core/appendix/gen-index-instructions.py rename to document/core/appendix/index-instructions.py index 2531dcd10..58e998757 100755 --- a/document/core/appendix/gen-index-instructions.py +++ b/document/core/appendix/index-instructions.py @@ -12,7 +12,7 @@ INDEX_INSTRUCTIONS_RST = os.path.join(SCRIPT_DIR, 'index-instructions.rst') HEADER = """\ -.. DO NOT EDIT: This file is auto-generated by the gen-index-instructions.py script. +.. DO NOT EDIT: This file is auto-generated by the index-instructions.py script. .. index:: instruction .. _index-instr: From 844973cc5ce6507fca89a7c4822bdd6f883a59ed Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 1 Mar 2023 12:11:19 +0100 Subject: [PATCH 169/181] Fix merge bullshit again --- interpreter/binary/encode.ml | 29 +++++----- interpreter/exec/eval.ml | 8 +-- interpreter/syntax/ast.ml | 8 +-- interpreter/syntax/free.ml | 4 +- interpreter/syntax/operators.ml | 44 +++++++-------- interpreter/text/arrange.ml | 8 +-- interpreter/text/lexer.mll | 96 ++++++++++++++++----------------- interpreter/valid/valid.ml | 26 ++++----- 8 files changed, 112 insertions(+), 111 deletions(-) diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 40a4ec022..52a9b98b4 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -246,7 +246,7 @@ struct op 0x3a; memop x mo | Store (x, ({ty = I32Type; pack = Some Pack16; _} as mo)) -> op 0x3b; memop x mo - | Store (x, {ty = I32Type; pack = Some (Pack32 | Pack64); _}) -> + | Store (x, {ty = I32Type; pack = Some Pack32; _}) -> error e.at "illegal instruction i32.store32" | Store (x, ({ty = I64Type; pack = Some Pack8; _} as mo)) -> op 0x3c; memop x mo @@ -285,35 +285,36 @@ struct vecop 0x5cl; memop x mo | VecLoad (x, ({ty = V128Type; pack = Some (Pack64, ExtZero); _} as mo)) -> vecop 0x5dl; memop x mo - error e.at "illegal instruction v128.loadNxM_" + | VecLoad _ -> + error e.at "illegal instruction v128.loadNxM_x" | VecLoadLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> - vecop 0x54l; memop x mo; u8 i; + vecop 0x54l; memop x mo; byte i; | VecLoadLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> - vecop 0x55l; memop x mo; u8 i; + vecop 0x55l; memop x mo; byte i; | VecLoadLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> - vecop 0x56l; memop x mo; u8 i; + vecop 0x56l; memop x mo; byte i; | VecLoadLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> - vecop 0x57l; memop x mo; u8 i; + vecop 0x57l; memop x mo; byte i; | VecStore (x, ({ty = V128Type; _} as mo)) -> vecop 0x0bl; memop x mo | VecStoreLane (x, ({ty = V128Type; pack = Pack8; _} as mo), i) -> - vecop 0x58l; memop x mo; u8 i; + vecop 0x58l; memop x mo; byte i; | VecStoreLane (x, ({ty = V128Type; pack = Pack16; _} as mo), i) -> - vecop 0x59l; memop x mo; u8 i; + vecop 0x59l; memop x mo; byte i; | VecStoreLane (x, ({ty = V128Type; pack = Pack32; _} as mo), i) -> - vecop 0x5al; memop x mo; u8 i; + vecop 0x5al; memop x mo; byte i; | VecStoreLane (x, ({ty = V128Type; pack = Pack64; _} as mo), i) -> - vecop 0x5bl; memop x mo; u8 i; + vecop 0x5bl; memop x mo; byte i; | MemorySize x -> op 0x3f; var x | MemoryGrow x -> op 0x40; var x - | MemoryFill x -> op 0xfc; vu32 0x0bl; var x - | MemoryCopy (x, y) -> op 0xfc; vu32 0x0al; var x; var y - | MemoryInit (x, y) -> op 0xfc; vu32 0x08l; var y; var x - | DataDrop x -> op 0xfc; vu32 0x09l; var x + | MemoryFill x -> op 0xfc; u32 0x0bl; var x + | MemoryCopy (x, y) -> op 0xfc; u32 0x0al; var x; var y + | MemoryInit (x, y) -> op 0xfc; u32 0x08l; var y; var x + | DataDrop x -> op 0xfc; u32 0x09l; var x | RefNull t -> op 0xd0; ref_type t | RefIsNull -> op 0xd1 diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 80610a1fb..6d37aa2cc 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -341,7 +341,7 @@ let rec step (c : config) : config = vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]); - | LoadVec (x, {offset; ty; pack; _}), Num (I32 i) :: vs' -> + | VecLoad (x, {offset; ty; pack; _}), Num (I32 i) :: vs' -> let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try @@ -353,7 +353,7 @@ let rec step (c : config) : config = in Vec v :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) - | StoreVec (x, {offset; _}), Vec v :: Num (I32 i) :: vs' -> + | VecStore (x, {offset; _}), Vec v :: Num (I32 i) :: vs' -> let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try @@ -361,7 +361,7 @@ let rec step (c : config) : config = vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]); - | LoadVecLane (x, {offset; ty; pack; _}, j), Vec (V128 v) :: Num (I32 i) :: vs' -> + | VecLoadLane (x, {offset; ty; pack; _}, j), Vec (V128 v) :: Num (I32 i) :: vs' -> let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try @@ -382,7 +382,7 @@ let rec step (c : config) : config = in Vec (V128 v) :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) - | StoreVecLane (x, {offset; ty; pack; _}, j), Vec (V128 v) :: Num (I32 i) :: vs' -> + | VecStoreLane (x, {offset; ty; pack; _}, j), Vec (V128 v) :: Num (I32 i) :: vs' -> let mem = memory frame.inst x in let addr = I64_convert.extend_i32_u i in (try diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 289234dd6..8d31a0df7 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -163,11 +163,11 @@ and instr' = | TableInit of var * var (* initialize table range from segment *) | ElemDrop of var (* drop passive element segment *) | Load of var * loadop (* read memory at address *) - | LoadVec of var * vec_loadop (* read memory at address *) - | LoadVecLane of var * vec_laneop * int (* read single lane at address *) | Store of var * storeop (* write memory at address *) - | StoreVec of var * vec_storeop (* write memory at address *) - | StoreVecLane of var * vec_laneop * int (* write single lane to address *) + | VecLoad of var * vec_loadop (* read memory at address *) + | VecStore of var * vec_storeop (* write memory at address *) + | VecLoadLane of var * vec_laneop * int (* read single lane at address *) + | VecStoreLane of var * vec_laneop * int (* write single lane to address *) | MemorySize of var (* size of memory *) | MemoryGrow of var (* grow memory *) | MemoryFill of var (* fill memory range with value *) diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml index 1fefb6e21..ae340b098 100644 --- a/interpreter/syntax/free.ml +++ b/interpreter/syntax/free.ml @@ -83,8 +83,8 @@ let rec instr (e : instr) = | TableCopy (x, y) -> tables (var x) ++ tables (var y) | TableInit (x, y) -> tables (var x) ++ elems (var y) | ElemDrop x -> elems (var x) - | Load (x, _) | Store (x, _) | LoadVec (x, _) | StoreVec (x, _) - | LoadVecLane (x, _, _) | StoreVecLane (x, _, _) + | Load (x, _) | Store (x, _) | VecLoad (x, _) | VecStore (x, _) + | VecLoadLane (x, _, _) | VecStoreLane (x, _, _) | MemorySize x | MemoryGrow x | MemoryFill x -> memories (var x) | MemoryCopy (x, y) -> memories (var x) ++ memories (var y) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index f52d452ad..786b8feba 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -92,50 +92,50 @@ let i64_store32 x align offset = Store (x, {ty = I64Type; align; offset; pack = Some Pack32}) let v128_load x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = None}) + VecLoad (x, {ty = V128Type; align; offset; pack = None}) let v128_load8x8_s x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack8x8, SX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack8x8, SX))}) let v128_load8x8_u x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack8x8, ZX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack8x8, ZX))}) let v128_load16x4_s x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack16x4, SX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack16x4, SX))}) let v128_load16x4_u x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack16x4, ZX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack16x4, ZX))}) let v128_load32x2_s x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack32x2, SX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack32x2, SX))}) let v128_load32x2_u x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack32x2, ZX))}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtLane (Pack32x2, ZX))}) let v128_load8_splat x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack8, ExtSplat)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack8, ExtSplat)}) let v128_load16_splat x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack16, ExtSplat)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack16, ExtSplat)}) let v128_load32_splat x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack32, ExtSplat)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack32, ExtSplat)}) let v128_load64_splat x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtSplat)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtSplat)}) let v128_load32_zero x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack32, ExtZero)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack32, ExtZero)}) let v128_load64_zero x align offset = - LoadVec (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtZero)}) + VecLoad (x, {ty = V128Type; align; offset; pack = Some (Pack64, ExtZero)}) let v128_load8_lane x align offset i = - LoadVecLane (x, {ty = V128Type; align; offset; pack = Pack8}, i) + VecLoadLane (x, {ty = V128Type; align; offset; pack = Pack8}, i) let v128_load16_lane x align offset i = - LoadVecLane (x, {ty = V128Type; align; offset; pack = Pack16}, i) + VecLoadLane (x, {ty = V128Type; align; offset; pack = Pack16}, i) let v128_load32_lane x align offset i = - LoadVecLane (x, {ty = V128Type; align; offset; pack = Pack32}, i) + VecLoadLane (x, {ty = V128Type; align; offset; pack = Pack32}, i) let v128_load64_lane x align offset i = - LoadVecLane (x, {ty = V128Type; align; offset; pack = Pack64}, i) + VecLoadLane (x, {ty = V128Type; align; offset; pack = Pack64}, i) let v128_store x align offset = - StoreVec (x, {ty = V128Type; align; offset; pack = ()}) + VecStore (x, {ty = V128Type; align; offset; pack = ()}) let v128_store8_lane x align offset i = - StoreVecLane (x, {ty = V128Type; align; offset; pack = Pack8}, i) + VecStoreLane (x, {ty = V128Type; align; offset; pack = Pack8}, i) let v128_store16_lane x align offset i = - StoreVecLane (x, {ty = V128Type; align; offset; pack = Pack16}, i) + VecStoreLane (x, {ty = V128Type; align; offset; pack = Pack16}, i) let v128_store32_lane x align offset i = - StoreVecLane (x, {ty = V128Type; align; offset; pack = Pack32}, i) + VecStoreLane (x, {ty = V128Type; align; offset; pack = Pack32}, i) let v128_store64_lane x align offset i = - StoreVecLane (x, {ty = V128Type; align; offset; pack = Pack64}, i) + VecStoreLane (x, {ty = V128Type; align; offset; pack = Pack64}, i) let memory_size x = MemorySize x let memory_grow x = MemoryGrow x diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index adec6ad2a..b0421e1be 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -467,11 +467,11 @@ let rec instr e = | TableInit (x, y) -> "table.init " ^ var x ^ " " ^ var y, [] | ElemDrop x -> "elem.drop " ^ var x, [] | Load (x, op) -> loadop x op, [] - | LoadVec (x, op) -> vec_loadop x op, [] - | LoadVecLane (x, op, i) -> vec_laneop "load" x op i, [] | Store (x, op) -> storeop x op, [] - | StoreVec (x, op) -> vec_storeop x op, [] - | StoreVecLane (x, op, i) -> vec_laneop "store" x op i, [] + | VecLoad (x, op) -> vec_loadop x op, [] + | VecStore (x, op) -> vec_storeop x op, [] + | VecLoadLane (x, op, i) -> vec_laneop "load" x op i, [] + | VecStoreLane (x, op, i) -> vec_laneop "store" x op i, [] | MemorySize x -> "memory.size " ^ var x, [] | MemoryGrow x -> "memory.grow " ^ var x, [] | MemoryFill x -> "memory.fill " ^ var x, [] diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index d9a12b5d2..cb0d072c8 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -191,68 +191,68 @@ rule token = parse | "memory.init" -> MEMORY_INIT | "data.drop" -> DATA_DROP - | "i32.load" -> LOAD (fun a o -> i32_load (opt a 2) o) - | "i64.load" -> LOAD (fun a o -> i64_load (opt a 3) o) - | "f32.load" -> LOAD (fun a o -> f32_load (opt a 2) o) - | "f64.load" -> LOAD (fun a o -> f64_load (opt a 3) o) - | "i32.store" -> STORE (fun a o -> i32_store (opt a 2) o) - | "i64.store" -> STORE (fun a o -> i64_store (opt a 3) o) - | "f32.store" -> STORE (fun a o -> f32_store (opt a 2) o) - | "f64.store" -> STORE (fun a o -> f64_store (opt a 3) o) - - | "i32.load8_u" -> LOAD (fun a o -> i32_load8_u (opt a 0) o) - | "i32.load8_s" -> LOAD (fun a o -> i32_load8_s (opt a 0) o) - | "i32.load16_u" -> LOAD (fun a o -> i32_load16_u (opt a 1) o) - | "i32.load16_s" -> LOAD (fun a o -> i32_load16_s (opt a 1) o) - | "i64.load8_u" -> LOAD (fun a o -> i64_load8_u (opt a 0) o) - | "i64.load8_s" -> LOAD (fun a o -> i64_load8_s (opt a 0) o) - | "i64.load16_u" -> LOAD (fun a o -> i64_load16_u (opt a 1) o) - | "i64.load16_s" -> LOAD (fun a o -> i64_load16_s (opt a 1) o) - | "i64.load32_u" -> LOAD (fun a o -> i64_load32_u (opt a 2) o) - | "i64.load32_s" -> LOAD (fun a o -> i64_load32_s (opt a 2) o) - - | "i32.store8" -> LOAD (fun a o -> i32_store8 (opt a 0) o) - | "i32.store16" -> LOAD (fun a o -> i32_store16 (opt a 1) o) - | "i64.store8" -> LOAD (fun a o -> i64_store8 (opt a 0) o) - | "i64.store16" -> LOAD (fun a o -> i64_store16 (opt a 1) o) - | "i64.store32" -> LOAD (fun a o -> i64_store32 (opt a 2) o) - - | "v128.load" -> VEC_LOAD (fun a o -> v128_load (opt a 4) o) - | "v128.store" -> VEC_STORE (fun a o -> v128_store (opt a 4) o) - | "v128.load8x8_u" -> VEC_LOAD (fun a o -> v128_load8x8_u (opt a 3) o) - | "v128.load8x8_s" -> VEC_LOAD (fun a o -> v128_load8x8_s (opt a 3) o) - | "v128.load16x4_u" -> VEC_LOAD (fun a o -> v128_load16x4_u (opt a 3) o) - | "v128.load16x4_s" -> VEC_LOAD (fun a o -> v128_load16x4_s (opt a 3) o) - | "v128.load32x2_u" -> VEC_LOAD (fun a o -> v128_load32x2_u (opt a 3) o) - | "v128.load32x2_s" -> VEC_LOAD (fun a o -> v128_load32x2_s (opt a 3) o) + | "i32.load" -> LOAD (fun x a o -> i32_load x (opt a 2) o) + | "i64.load" -> LOAD (fun x a o -> i64_load x (opt a 3) o) + | "f32.load" -> LOAD (fun x a o -> f32_load x (opt a 2) o) + | "f64.load" -> LOAD (fun x a o -> f64_load x (opt a 3) o) + | "i32.store" -> STORE (fun x a o -> i32_store x (opt a 2) o) + | "i64.store" -> STORE (fun x a o -> i64_store x (opt a 3) o) + | "f32.store" -> STORE (fun x a o -> f32_store x (opt a 2) o) + | "f64.store" -> STORE (fun x a o -> f64_store x (opt a 3) o) + + | "i32.load8_u" -> LOAD (fun x a o -> i32_load8_u x (opt a 0) o) + | "i32.load8_s" -> LOAD (fun x a o -> i32_load8_s x (opt a 0) o) + | "i32.load16_u" -> LOAD (fun x a o -> i32_load16_u x (opt a 1) o) + | "i32.load16_s" -> LOAD (fun x a o -> i32_load16_s x (opt a 1) o) + | "i64.load8_u" -> LOAD (fun x a o -> i64_load8_u x (opt a 0) o) + | "i64.load8_s" -> LOAD (fun x a o -> i64_load8_s x (opt a 0) o) + | "i64.load16_u" -> LOAD (fun x a o -> i64_load16_u x (opt a 1) o) + | "i64.load16_s" -> LOAD (fun x a o -> i64_load16_s x (opt a 1) o) + | "i64.load32_u" -> LOAD (fun x a o -> i64_load32_u x (opt a 2) o) + | "i64.load32_s" -> LOAD (fun x a o -> i64_load32_s x (opt a 2) o) + + | "i32.store8" -> LOAD (fun x a o -> i32_store8 x (opt a 0) o) + | "i32.store16" -> LOAD (fun x a o -> i32_store16 x (opt a 1) o) + | "i64.store8" -> LOAD (fun x a o -> i64_store8 x (opt a 0) o) + | "i64.store16" -> LOAD (fun x a o -> i64_store16 x (opt a 1) o) + | "i64.store32" -> LOAD (fun x a o -> i64_store32 x (opt a 2) o) + + | "v128.load" -> VEC_LOAD (fun x a o -> v128_load x (opt a 4) o) + | "v128.store" -> VEC_STORE (fun x a o -> v128_store x (opt a 4) o) + | "v128.load8x8_u" -> VEC_LOAD (fun x a o -> v128_load8x8_u x (opt a 3) o) + | "v128.load8x8_s" -> VEC_LOAD (fun x a o -> v128_load8x8_s x (opt a 3) o) + | "v128.load16x4_u" -> VEC_LOAD (fun x a o -> v128_load16x4_u x (opt a 3) o) + | "v128.load16x4_s" -> VEC_LOAD (fun x a o -> v128_load16x4_s x (opt a 3) o) + | "v128.load32x2_u" -> VEC_LOAD (fun x a o -> v128_load32x2_u x (opt a 3) o) + | "v128.load32x2_s" -> VEC_LOAD (fun x a o -> v128_load32x2_s x (opt a 3) o) | "v128.load8_splat" -> - VEC_LOAD (fun a o -> v128_load8_splat (opt a 0) o) + VEC_LOAD (fun x a o -> v128_load8_splat x (opt a 0) o) | "v128.load16_splat" -> - VEC_LOAD (fun a o -> v128_load16_splat (opt a 1) o) + VEC_LOAD (fun x a o -> v128_load16_splat x (opt a 1) o) | "v128.load32_splat" -> - VEC_LOAD (fun a o -> v128_load32_splat (opt a 2) o) + VEC_LOAD (fun x a o -> v128_load32_splat x (opt a 2) o) | "v128.load64_splat" -> - VEC_LOAD (fun a o -> v128_load64_splat (opt a 3) o) + VEC_LOAD (fun x a o -> v128_load64_splat x (opt a 3) o) | "v128.load32_zero" -> - VEC_LOAD (fun a o -> v128_load32_zero (opt a 2) o) + VEC_LOAD (fun x a o -> v128_load32_zero x (opt a 2) o) | "v128.load64_zero" -> - VEC_LOAD (fun a o -> v128_load64_zero (opt a 3) o) + VEC_LOAD (fun x a o -> v128_load64_zero x (opt a 3) o) | "v128.load8_lane" -> - VEC_LOAD_LANE (fun a o i -> v128_load8_lane (opt a 0) o i) + VEC_LOAD_LANE (fun x a o i -> v128_load8_lane x (opt a 0) o i) | "v128.load16_lane" -> - VEC_LOAD_LANE (fun a o i -> v128_load16_lane (opt a 1) o i) + VEC_LOAD_LANE (fun x a o i -> v128_load16_lane x (opt a 1) o i) | "v128.load32_lane" -> - VEC_LOAD_LANE (fun a o i -> v128_load32_lane (opt a 2) o i) + VEC_LOAD_LANE (fun x a o i -> v128_load32_lane x (opt a 2) o i) | "v128.load64_lane" -> - VEC_LOAD_LANE (fun a o i -> v128_load64_lane (opt a 3) o i) + VEC_LOAD_LANE (fun x a o i -> v128_load64_lane x (opt a 3) o i) | "v128.store8_lane" -> - VEC_STORE_LANE (fun a o i -> v128_store8_lane (opt a 0) o i) + VEC_STORE_LANE (fun x a o i -> v128_store8_lane x (opt a 0) o i) | "v128.store16_lane" -> - VEC_STORE_LANE (fun a o i -> v128_store16_lane (opt a 1) o i) + VEC_STORE_LANE (fun x a o i -> v128_store16_lane x (opt a 1) o i) | "v128.store32_lane" -> - VEC_STORE_LANE (fun a o i -> v128_store32_lane (opt a 2) o i) + VEC_STORE_LANE (fun x a o i -> v128_store32_lane x (opt a 2) o i) | "v128.store64_lane" -> - VEC_STORE_LANE (fun a o i -> v128_store64_lane (opt a 3) o i) + VEC_STORE_LANE (fun x a o i -> v128_store64_lane x (opt a 3) o i) | "i32.const" -> CONST (fun s -> diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index a72fd0755..6f0822c0b 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -357,29 +357,29 @@ let rec check_instr (c : context) (e : instr) (s : infer_result_type) : op_type check_memop c memop num_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [NumType memop.ty] - | LoadVec (x, memop) -> + | Store (x, memop) -> + let _mt = memory c x in + check_memop c memop num_size (fun sz -> sz) e.at; + [NumType I32Type; NumType memop.ty] --> [] + + | VecLoad (x, memop) -> let _mt = memory c x in check_memop c memop vec_size (Lib.Option.map fst) e.at; [NumType I32Type] --> [VecType memop.ty] - | LoadVecLane (x, memop, i) -> + | VecStore (x, memop) -> + let _mt = memory c x in + check_memop c memop vec_size (fun _ -> None) e.at; + [NumType I32Type; VecType memop.ty] --> [] + + | VecLoadLane (x, memop, i) -> let _mt = memory c x in check_memop c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at "invalid lane index"; [NumType I32Type; VecType memop.ty] --> [VecType memop.ty] - | Store (x, memop) -> - let _mt = memory c x in - check_memop c memop num_size (fun sz -> sz) e.at; - [NumType I32Type; NumType memop.ty] --> [] - - | StoreVec (x, memop) -> - let _mt = memory c x in - check_memop c memop vec_size (fun _ -> None) e.at; - [NumType I32Type; VecType memop.ty] --> [] - - | StoreVecLane (x, memop, i) -> + | VecStoreLane (x, memop, i) -> let _mt = memory c x in check_memop c memop vec_size (fun sz -> Some sz) e.at; require (i < vec_size memop.ty / packed_size memop.pack) e.at From 929163a6fc7ccf25a205896ae6ae0b246bd9a371 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 1 Mar 2023 12:31:13 +0100 Subject: [PATCH 170/181] [ci] Disable node again --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a158de1ee..7cd34fbcd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,9 @@ jobs: uses: actions/setup-node@v1 with: node-version: 19.x - - run: cd interpreter && opam exec make JS=node all + # TODO: disable node.js run until it fully implements proposal + # - run: cd interpreter && opam exec make JS=node all + - run: cd interpreter && opam exec make all ref-interpreter-js-library: runs-on: ubuntu-latest From 00c57f58a58ab5fcf89fd9912a9a92606ed8ca12 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 3 Mar 2023 22:29:15 +0100 Subject: [PATCH 171/181] Fix typo in readme's title (#16) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ac515b72..c4ccd156c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Build Status](https://github.com/WebAssembly/extended-const/actions/workflows/main.yml/badge.svg) -# Extended Const Expressesions Proposal for WebAssembly +# Extended Const Expressions Proposal for WebAssembly This repository is a clone of [github.com/WebAssembly/spec/](https://github.com/WebAssembly/spec/). It is meant for discussion, prototype specification and implementation of a proposal to add tail call support to WebAssembly. From 0882af7393d3deadaee33f6115437ce8a0a03e02 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Wed, 8 Mar 2023 12:46:27 -0800 Subject: [PATCH 172/181] Rename new traps.wast test -> traps0.wast --- test/core/multi-memory/{traps.wast => traps0.wast} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/core/multi-memory/{traps.wast => traps0.wast} (100%) diff --git a/test/core/multi-memory/traps.wast b/test/core/multi-memory/traps0.wast similarity index 100% rename from test/core/multi-memory/traps.wast rename to test/core/multi-memory/traps0.wast From 7612271a72f00e2b385a98a7f79a031f94fb77e6 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 19 Apr 2023 10:10:47 -0700 Subject: [PATCH 173/181] Update constant expression validation rules (#17) These changes a published here: https://webassembly.github.io/extended-const/core/valid/instructions.html#constant-expressions --- document/core/valid/instructions.rst | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index afcda69c0..075721938 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -1604,6 +1604,8 @@ Constant Expressions * either of the form :math:`t.\CONST~c`, + * or of the form :math:`\K{i}\X{nn}\K{.}\ibinop`, where :math:`\ibinop` is limited to :math:`\ADD`, :math:`\SUB`, or :math:`\MUL`. + * or of the form :math:`\REFNULL`, * or of the form :math:`\REFFUNC~x`, @@ -1619,18 +1621,9 @@ Constant Expressions .. math:: \frac{ + \ibinop \in \{\ADD, \SUB, \MUL\} }{ - C \vdashinstrconst t.\CONST~c \const - } - \qquad - \frac{ - }{ - C \vdashinstrconst \REFNULL~t \const - } - \qquad - \frac{ - }{ - C \vdashinstrconst \REFFUNC~x \const + C \vdashinstrconst \K{i}\X{nn}\K{.}\ibinop \const } .. math:: From 15c1f925cf6754d83f08763a6ccb5fbec585e327 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 6 Jun 2023 00:43:23 +0900 Subject: [PATCH 174/181] memory_copy1.wast: add some tests i want to make this this non-empty because wast2json complains on an empty file. --- test/core/multi-memory/memory_copy1.wast | 41 +++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/core/multi-memory/memory_copy1.wast b/test/core/multi-memory/memory_copy1.wast index b224bfe20..df9165f42 100644 --- a/test/core/multi-memory/memory_copy1.wast +++ b/test/core/multi-memory/memory_copy1.wast @@ -1 +1,40 @@ -;; TODO: test copy across different memories. +;; test memory.copy across different memories. +(module + (memory $mem0 (data "\ff\11\44\ee")) + (memory $mem1 (data "\ee\22\55\ff")) + (memory $mem2 (data "\dd\33\66\00")) + (memory $mem3 (data "\aa\bb\cc\dd")) + + (func (export "copy") (param i32 i32 i32) + (memory.copy $mem0 $mem3 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem0 (local.get 0))) +) + +;; Non-overlapping copy. +(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) + +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) + +;; Copy ending at memory limit is ok. +(invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) +(invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) + +;; Succeed when copying 0 bytes at the end of the region. +(invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) + +;; Copying 0 bytes outside the memory traps. +(assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) + "out of bounds memory access") From fbc99efd7a788db300aec3dd62a14577ec404f1b Mon Sep 17 00:00:00 2001 From: Clemens Backes Date: Wed, 12 Jul 2023 18:53:46 +0200 Subject: [PATCH 175/181] Clarify order of the memory.copy immediates Clarify that the destination memory index comes first. There is a single test for that (memory_copy1), but I did not find anything about the order in the spec text. --- document/core/binary/instructions.rst | 8 ++++---- document/core/syntax/instructions.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index d3f4ad0eb..74bdf4715 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -226,10 +226,10 @@ Each variant of :ref:`memory instruction ` is encoded with \hex{3E}~~m{:}\Bmemarg &\Rightarrow& \I64.\STORE\K{32}~m \\ &&|& \hex{3F}~~x{:}\Bmemidx &\Rightarrow& \MEMORYSIZE~x \\ &&|& \hex{40}~~x{:}\Bmemidx &\Rightarrow& \MEMORYGROW~x \\ &&|& - \hex{FC}~~8{:}\Bu32~~y{:}\Bdataidx~x{:}\Bmemidx &\Rightarrow& \MEMORYINIT~x~y \\ &&|& - \hex{FC}~~9{:}\Bu32~~x{:}\Bdataidx &\Rightarrow& \DATADROP~x \\ &&|& - \hex{FC}~~10{:}\Bu32~~x{:}\Bmemidx~~y{:}\Bmemidx &\Rightarrow& \MEMORYCOPY~x~y \\ &&|& - \hex{FC}~~11{:}\Bu32~~x{:}\Bmemidx &\Rightarrow& \MEMORYFILL~x \\ + \hex{FC}~~8{:}\Bu32~~src{:}\Bdataidx~dst{:}\Bmemidx &\Rightarrow& \MEMORYINIT~dst~src \\ &&|& + \hex{FC}~~9{:}\Bu32~~dst{:}\Bdataidx &\Rightarrow& \DATADROP~dst \\ &&|& + \hex{FC}~~10{:}\Bu32~~dst{:}\Bmemidx~~src{:}\Bmemidx &\Rightarrow& \MEMORYCOPY~dst~src \\ &&|& + \hex{FC}~~11{:}\Bu32~~dst{:}\Bmemidx &\Rightarrow& \MEMORYFILL~dst \\ \end{array} .. index:: numeric instruction diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index a1b5aaa9d..18fb026b2 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -601,7 +601,7 @@ The |MEMORYSIZE| instruction returns the current size of a memory. The |MEMORYGROW| instruction grows a memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. Both instructions operate in units of :ref:`page size `. The |MEMORYFILL| instruction sets all values in a region of a memory to a given byte. -The |MEMORYCOPY| instruction copies data from a source memory region to a possibly overlapping destination region in another or the same memory. +The |MEMORYCOPY| instruction copies data from a source memory region (second *immediate* |memarg|) to a possibly overlapping destination region in another or the same memory (first *immediate* |memarg|). The |MEMORYINIT| instruction copies data from a :ref:`passive data segment ` into a memory. The |DATADROP| instruction prevents further use of a passive data segment. This instruction is intended to be used as an optimization hint. After a data segment is dropped its data can no longer be retrieved, so the memory used by this segment may be freed. From b8a9f4addbe8a40b1a09f35356707b13d6619d67 Mon Sep 17 00:00:00 2001 From: Clemens Backes Date: Thu, 13 Jul 2023 11:51:24 +0200 Subject: [PATCH 176/181] Revert most changes, only specify that the first index is the destination --- document/core/binary/instructions.rst | 8 ++++---- document/core/syntax/instructions.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index 74bdf4715..d3f4ad0eb 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -226,10 +226,10 @@ Each variant of :ref:`memory instruction ` is encoded with \hex{3E}~~m{:}\Bmemarg &\Rightarrow& \I64.\STORE\K{32}~m \\ &&|& \hex{3F}~~x{:}\Bmemidx &\Rightarrow& \MEMORYSIZE~x \\ &&|& \hex{40}~~x{:}\Bmemidx &\Rightarrow& \MEMORYGROW~x \\ &&|& - \hex{FC}~~8{:}\Bu32~~src{:}\Bdataidx~dst{:}\Bmemidx &\Rightarrow& \MEMORYINIT~dst~src \\ &&|& - \hex{FC}~~9{:}\Bu32~~dst{:}\Bdataidx &\Rightarrow& \DATADROP~dst \\ &&|& - \hex{FC}~~10{:}\Bu32~~dst{:}\Bmemidx~~src{:}\Bmemidx &\Rightarrow& \MEMORYCOPY~dst~src \\ &&|& - \hex{FC}~~11{:}\Bu32~~dst{:}\Bmemidx &\Rightarrow& \MEMORYFILL~dst \\ + \hex{FC}~~8{:}\Bu32~~y{:}\Bdataidx~x{:}\Bmemidx &\Rightarrow& \MEMORYINIT~x~y \\ &&|& + \hex{FC}~~9{:}\Bu32~~x{:}\Bdataidx &\Rightarrow& \DATADROP~x \\ &&|& + \hex{FC}~~10{:}\Bu32~~x{:}\Bmemidx~~y{:}\Bmemidx &\Rightarrow& \MEMORYCOPY~x~y \\ &&|& + \hex{FC}~~11{:}\Bu32~~x{:}\Bmemidx &\Rightarrow& \MEMORYFILL~x \\ \end{array} .. index:: numeric instruction diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index 18fb026b2..d407eb3a5 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -601,7 +601,7 @@ The |MEMORYSIZE| instruction returns the current size of a memory. The |MEMORYGROW| instruction grows a memory by a given delta and returns the previous size, or :math:`-1` if enough memory cannot be allocated. Both instructions operate in units of :ref:`page size `. The |MEMORYFILL| instruction sets all values in a region of a memory to a given byte. -The |MEMORYCOPY| instruction copies data from a source memory region (second *immediate* |memarg|) to a possibly overlapping destination region in another or the same memory (first *immediate* |memarg|). +The |MEMORYCOPY| instruction copies data from a source memory region to a possibly overlapping destination region in another or the same memory; the first index denotes the destination. The |MEMORYINIT| instruction copies data from a :ref:`passive data segment ` into a memory. The |DATADROP| instruction prevents further use of a passive data segment. This instruction is intended to be used as an optimization hint. After a data segment is dropped its data can no longer be retrieved, so the memory used by this segment may be freed. From 35e435a89a8e5a0de0bbd592fe292bc5d2aac207 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Thu, 14 Dec 2023 09:50:42 -0800 Subject: [PATCH 177/181] [test] Test elem offsets with extended const exprs (#18) --- test/core/elem.wast | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/test/core/elem.wast b/test/core/elem.wast index 6e7a33afa..92dab5250 100644 --- a/test/core/elem.wast +++ b/test/core/elem.wast @@ -699,3 +699,60 @@ ) (assert_return (invoke "call_imported_elem") (i32.const 42)) + +;; Extended contant expressions + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.add (i32.const 1) (i32.const 2))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 3)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.sub (i32.const 2) (i32.const 1))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 1)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.mul (i32.const 2) (i32.const 2))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 4)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +;; Combining add, sub, mul and global.get + +(module + (global (import "spectest" "global_i32") i32) + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) + (offset + (i32.mul + (i32.const 2) + (i32.add + (i32.sub (global.get 0) (i32.const 665)) + (i32.const 2)))) + funcref + (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 6)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") From 1510c7947102b8e3f071d897a96d37a10e353f15 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 7 Mar 2024 08:30:06 +0100 Subject: [PATCH 178/181] Add some missing side conditions --- document/core/valid/instructions.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index f88fe1bf3..2fbb7857c 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -1197,7 +1197,9 @@ Parametric Instructions } \qquad \frac{ - \vdash t \leq \vectype + C \vdashresulttype [t] \ok + \qquad + C \vdash t \leq \vectype }{ C \vdashinstr \SELECT : [t~t~\I32] \to [t] } @@ -2253,6 +2255,8 @@ Control Instructions \expanddt(C.\CFUNCS[x]) = \TFUNC~[t_1^\ast] \toF [t_2^\ast] \qquad C \vdashresulttypematch [t_2^\ast] \matchesresulttype C.\CRETURN + \qquad + C \vdashinstrtype [t_3^\ast~t_1^\ast] \to [t_4^\ast] \ok }{ C \vdashinstr \RETURNCALL~x : [t_3^\ast~t_1^\ast] \to [t_4^\ast] } @@ -2279,6 +2283,8 @@ Control Instructions \expanddt(C.\CTYPES[x]) = \TFUNC~[t_1^\ast] \toF [t_2^\ast] \qquad C \vdashresulttypematch [t_2^\ast] \matchesresulttype C.\CRETURN + \qquad + C \vdashinstrtype [t_3^\ast~t_1^\ast~(\REF~\NULL~x)] \to [t_4^\ast] \ok }{ C \vdashinstr \CALLREF~x : [t_3^\ast~t_1^\ast~(\REF~\NULL~x)] \to [t_4^\ast] } @@ -2317,6 +2323,8 @@ Control Instructions \expanddt(C.\CTYPES[y]) = \TFUNC~[t_1^\ast] \toF [t_2^\ast] \qquad C \vdashresulttypematch [t_2^\ast] \matchesresulttype C.\CRETURN + \qquad + C \vdashinstrtype [t_3^\ast~t_1^\ast~\I32] \to [t_4^\ast] \ok }{ C \vdashinstr \RETURNCALLINDIRECT~x~y : [t_3^\ast~t_1^\ast~\I32] \to [t_4^\ast] } From 031000271e67a8a15002459cc625a8a27863926f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 7 Mar 2024 08:51:10 +0100 Subject: [PATCH 179/181] Fix duplication in Changes --- document/core/appendix/changes.rst | 50 +++++++----------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/document/core/appendix/changes.rst b/document/core/appendix/changes.rst index e9e43f633..a7dd1b2d6 100644 --- a/document/core/appendix/changes.rst +++ b/document/core/appendix/changes.rst @@ -138,9 +138,19 @@ Added vector type and instructions that manipulate multiple numeric values in pa * New injection/projection :ref:`vector instructions `: :math:`\K{i}\!N\!\K{x}\!M\!\K{.splat}`, :math:`\K{f}\!N\!\K{x}\!M\!\K{.splat}`, :math:`\K{i}\!N\!\K{x}\!M\!\K{.bitmask}` -Release 2.? +Release 3.0 ~~~~~~~~~~~ +.. index: instruction, function, call + +Tail calls +.......... + +Added instructions to perform tail calls [#proposal-tailcall]_. + +* New :ref:`control instructions `: :math:`RETURNCALL` and :math:`RETURNCALLINDIRECT` + + .. index:: reference, reference type, heap type, value type, local, local type, instruction, instruction type, table, function, function type, matching, subtyping Typeful References @@ -211,44 +221,6 @@ Added managed reference types [#proposal-gc]_. .. [#proposal-vectype] https://github.com/WebAssembly/spec/tree/main/proposals/simd/ - -Release 3.0 -~~~~~~~~~~~ - -.. index: instruction, function, call - -Tail calls -.......... - -Added instructions to perform tail calls [#proposal-tailcall]_. - -* New :ref:`control instructions `: :math:`RETURNCALL` and :math:`RETURNCALLINDIRECT` - - -.. index:: reference, reference type, heap type, value type, local, local type, instruction, instruction type, table, function, function type, matching, subtyping - -Typeful References -.................. - -Added more precise types for references [#proposal-typedref]_. - -* New generalised form of :ref:`reference types `: :math:`(\REF~\NULL^?~\heaptype)` - -* New class of :ref:`heap types `: |FUNC|, |EXTERN|, :math:`\typeidx` - -* Basic :ref:`subtyping ` on :ref:`reference ` and :ref:`value ` types - -* New :ref:`reference instructions `: |REFASNONNULL|, |BRONNULL|, |BRONNONNULL| - -* New :ref:`control instruction `: |CALLREF| - -* Refined typing of :ref:`reference instruction ` |REFFUNC| with more precise result type - -* Refined typing of :ref:`local instructions ` and :ref:`instruction sequences ` to track the :ref:`initialization status ` of :ref:`locals ` with non-:ref:`defaultable ` type - -* Extended :ref:`table definitions ` with optional initializer expression - - .. [#proposal-tailcall] https://github.com/WebAssembly/spec/tree/main/proposals/tail-call/ From d0919bc3523d60d9cbb32ee551c8347a8679a5d3 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 7 Mar 2024 09:01:29 +0100 Subject: [PATCH 180/181] [spec] Add extended constants to Changes --- document/core/appendix/changes.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/document/core/appendix/changes.rst b/document/core/appendix/changes.rst index a7dd1b2d6..0c0dd9da9 100644 --- a/document/core/appendix/changes.rst +++ b/document/core/appendix/changes.rst @@ -141,6 +141,19 @@ Added vector type and instructions that manipulate multiple numeric values in pa Release 3.0 ~~~~~~~~~~~ +.. index: instruction, expression, constant + +Extended Constant Expressions +............................. + +Allowed basic numeric computations in constant expressions [#proposal-extconst]_. + +* Extended set of :ref:`constant instructions ` with :math:`\K{i}\!N\!\K{.add}`, :math:`\K{i}\!N\!\K{.sub}`, and :math:`\K{i}\!N\!\K{.mul}` + +.. note:: + The :ref:`garbage collection ` added further constant instructions. + + .. index: instruction, function, call Tail calls @@ -176,6 +189,7 @@ Added more precise types for references [#proposal-typedref]_. .. index:: reference, reference type, heap type, field type, storage type, structure type, array type, composite type, sub type, recursive type +.. _extension-gc: Garbage Collection .................. @@ -221,6 +235,9 @@ Added managed reference types [#proposal-gc]_. .. [#proposal-vectype] https://github.com/WebAssembly/spec/tree/main/proposals/simd/ +.. [#proposal-extconst] + https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/ + .. [#proposal-tailcall] https://github.com/WebAssembly/spec/tree/main/proposals/tail-call/ From ba81d7a297c03510688974cb280f4db771f997f4 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 7 Mar 2024 10:53:46 +0100 Subject: [PATCH 181/181] Add multi memories to Changes --- document/core/appendix/changes.rst | 90 ++++++++++++++++++------------ 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/document/core/appendix/changes.rst b/document/core/appendix/changes.rst index 0c0dd9da9..f8e5659e6 100644 --- a/document/core/appendix/changes.rst +++ b/document/core/appendix/changes.rst @@ -15,7 +15,7 @@ Release 2.0 Sign extension instructions ........................... -Added new numeric instructions for performing sign extension within integer representations [#proposal-signext]_. +Added new numeric instructions for performing sign extension within integer representations. [#proposal-signext]_ * New :ref:`numeric instructions `: :math:`\K{i}\X{nn}\K{.}\EXTEND\X{N}\K{\_s}` @@ -25,7 +25,7 @@ Added new numeric instructions for performing sign extension within integer repr Non-trapping float-to-int conversions ..................................... -Added new conversion instructions that avoid trapping when converting a floating-point number to an integer [#proposal-cvtsat]_. +Added new conversion instructions that avoid trapping when converting a floating-point number to an integer. [#proposal-cvtsat]_ * New :ref:`numeric instructions `: :math:`\K{i}\X{nn}\K{.}\TRUNC\K{\_sat\_f}\X{mm}\K{\_}\sx` @@ -35,7 +35,7 @@ Added new conversion instructions that avoid trapping when converting a floating Multiple values ............... -Generalized the result type of blocks and functions to allow for multiple values; in addition, introduced the ability to have block parameters [#proposal-multivalue]_. +Generalized the result type of blocks and functions to allow for multiple values; in addition, introduced the ability to have block parameters. [#proposal-multivalue]_ * :ref:`Function types ` allow more than one result @@ -47,7 +47,7 @@ Generalized the result type of blocks and functions to allow for multiple values Reference types ............... -Added |FUNCREF| and |EXTERNREF| as new value types and respective instructions [#proposal-reftype]_. +Added |FUNCREF| and |EXTERNREF| as new value types and respective instructions. [#proposal-reftype]_ * New :ref:`value types `: :ref:`reference types ` |FUNCREF| and |EXTERNREF| @@ -63,19 +63,19 @@ Added |FUNCREF| and |EXTERNREF| as new value types and respective instructions [ Table instructions .................. -Added instructions to directly access and modify tables [#proposal-reftype]_. +Added instructions to directly access and modify tables. [#proposal-reftype]_ * :ref:`Table types ` allow any :ref:`reference type ` as element type * New :ref:`table instructions `: |TABLEGET|, |TABLESET|, |TABLESIZE|, |TABLEGROW| -.. index:: table, instruction, table index, element segment +.. index:: table, instruction, table index, element segment, import, export Multiple tables ............... -Added the ability to use multiple tables per module [#proposal-reftype]_. +Added the ability to use multiple tables per module. [#proposal-reftype]_ * :ref:`Modules ` may :ref:`define `, :ref:`import `, and :ref:`export ` multiple tables @@ -89,7 +89,7 @@ Added the ability to use multiple tables per module [#proposal-reftype]_. Bulk memory and table instructions .................................. -Added instructions that modify ranges of memory or table entries [#proposal-reftype]_ [#proposal-bulk]_ +Added instructions that modify ranges of memory or table entries. [#proposal-reftype]_ [#proposal-bulk]_ * New :ref:`memory instructions `: |MEMORYFILL|, |MEMORYINIT|, |MEMORYCOPY|, |DATADROP| @@ -138,17 +138,36 @@ Added vector type and instructions that manipulate multiple numeric values in pa * New injection/projection :ref:`vector instructions `: :math:`\K{i}\!N\!\K{x}\!M\!\K{.splat}`, :math:`\K{f}\!N\!\K{x}\!M\!\K{.splat}`, :math:`\K{i}\!N\!\K{x}\!M\!\K{.bitmask}` +.. [#proposal-signext] + https://github.com/WebAssembly/spec/tree/main/proposals/sign-extension-ops/ + +.. [#proposal-cvtsat] + https://github.com/WebAssembly/spec/tree/main/proposals/nontrapping-float-to-int-conversion/ + +.. [#proposal-multivalue] + https://github.com/WebAssembly/spec/tree/main/proposals/multi-value/ + +.. [#proposal-reftype] + https://github.com/WebAssembly/spec/tree/main/proposals/reference-types/ + +.. [#proposal-bulk] + https://github.com/WebAssembly/spec/tree/main/proposals/bulk-memory-operations/ + +.. [#proposal-vectype] + https://github.com/WebAssembly/spec/tree/main/proposals/simd/ + + Release 3.0 ~~~~~~~~~~~ .. index: instruction, expression, constant -Extended Constant Expressions +Extended constant expressions ............................. -Allowed basic numeric computations in constant expressions [#proposal-extconst]_. +Allowed basic numeric computations in constant expressions. [#proposal-extconst]_ -* Extended set of :ref:`constant instructions ` with :math:`\K{i}\!N\!\K{.add}`, :math:`\K{i}\!N\!\K{.sub}`, and :math:`\K{i}\!N\!\K{.mul}` +* Extended set of :ref:`constant instructions ` with :math:`\K{i}\X{nn}\K{.add}`, :math:`\K{i}\X{nn}\K{.sub}`, and :math:`\K{i}\X{nn}\K{.mul}`, and |GLOBALGET| for any previously declared immutable :ref:`global ` .. note:: The :ref:`garbage collection ` added further constant instructions. @@ -159,17 +178,31 @@ Allowed basic numeric computations in constant expressions [#proposal-extconst]_ Tail calls .......... -Added instructions to perform tail calls [#proposal-tailcall]_. +Added instructions to perform tail calls. [#proposal-tailcall]_ + +* New :ref:`control instructions `: |RETURNCALL| and |RETURNCALLINDIRECT| + + +.. index: instruction, memory, memory index, data segment, import, export + +Multiple memories +................. -* New :ref:`control instructions `: :math:`RETURNCALL` and :math:`RETURNCALLINDIRECT` +Added the ability to use multiple memories per module. [#proposal-multimem]_ + +* :ref:`Modules ` may :ref:`define `, :ref:`import `, and :ref:`export ` multiple memories + +* :ref:`Memory instructions ` take a :ref:`memory index ` immediate: |MEMORYSIZE|, |MEMORYGROW|, |MEMORYFILL|, |MEMORYCOPY|, |MEMORYINIT|, :math:`t\K{.load}`, :math:`t\K{.store}`, :math:`t\K{.load}\!N\!\K{\_}\sx`, :math:`t\K{.store}\!N`, :math:`\K{v128.load}\!N\!\K{x}\!M\!\K{\_}\sx`, :math:`\K{v128.load}\!N\!\K{\_zero}`, :math:`\K{v128.load}\!N\!\K{\_splat}`, :math:`\K{v128.load}\!N\!\K{\_lane}`, :math:`\K{v128.store}\!N\!\K{\_lane}` + +* :ref:`Data segments ` take a :ref:`memory index ` .. index:: reference, reference type, heap type, value type, local, local type, instruction, instruction type, table, function, function type, matching, subtyping -Typeful References +Typeful references .................. -Added more precise types for references [#proposal-typedref]_. +Added more precise types for references. [#proposal-typedref]_ * New generalised form of :ref:`reference types `: :math:`(\REF~\NULL^?~\heaptype)` @@ -191,10 +224,10 @@ Added more precise types for references [#proposal-typedref]_. .. index:: reference, reference type, heap type, field type, storage type, structure type, array type, composite type, sub type, recursive type .. _extension-gc: -Garbage Collection +Garbage collection .................. -Added managed reference types [#proposal-gc]_. +Added managed reference types. [#proposal-gc]_ * New forms of :ref:`heap types `: |ANY|, |EQT|, |I31|, |STRUCT|, |ARRAY|, |NONE|, |NOFUNC|, |NOEXTERN| @@ -214,26 +247,8 @@ Added managed reference types [#proposal-gc]_. * New :ref:`reference instructions ` for converting :ref:`host types `: |ANYCONVERTEXTERN|, |EXTERNCONVERTANY| -* Extended set of :ref:`constant instructions ` with |REFI31|, |STRUCTNEW|, |STRUCTNEWDEFAULT|, |ARRAYNEW|, |ARRAYNEWDEFAULT|, |ARRAYNEWFIXED|, |ANYCONVERTEXTERN|, |EXTERNCONVERTANY|, and |GLOBALGET| for any previously declared immutable :ref:`global ` - - -.. [#proposal-signext] - https://github.com/WebAssembly/spec/tree/main/proposals/sign-extension-ops/ - -.. [#proposal-cvtsat] - https://github.com/WebAssembly/spec/tree/main/proposals/nontrapping-float-to-int-conversion/ - -.. [#proposal-multivalue] - https://github.com/WebAssembly/spec/tree/main/proposals/multi-value/ +* Extended set of :ref:`constant instructions ` with |REFI31|, |STRUCTNEW|, |STRUCTNEWDEFAULT|, |ARRAYNEW|, |ARRAYNEWDEFAULT|, |ARRAYNEWFIXED|, |ANYCONVERTEXTERN|, |EXTERNCONVERTANY| -.. [#proposal-reftype] - https://github.com/WebAssembly/spec/tree/main/proposals/reference-types/ - -.. [#proposal-bulk] - https://github.com/WebAssembly/spec/tree/main/proposals/bulk-memory-operations/ - -.. [#proposal-vectype] - https://github.com/WebAssembly/spec/tree/main/proposals/simd/ .. [#proposal-extconst] https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/ @@ -241,6 +256,9 @@ Added managed reference types [#proposal-gc]_. .. [#proposal-tailcall] https://github.com/WebAssembly/spec/tree/main/proposals/tail-call/ +.. [#proposal-multimem] + https://github.com/WebAssembly/multi-memory/blob/main/proposals/multi-memory/ + .. [#proposal-typedref] https://github.com/WebAssembly/spec/tree/main/proposals/function-references/