github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/integration_test/spectest/v2/testdata/bulk.wast (about) 1 ;; segment syntax 2 (module 3 (memory 1) 4 (data "foo")) 5 6 (module 7 (table 3 funcref) 8 (elem funcref (ref.func 0) (ref.null func) (ref.func 1)) 9 (func) 10 (func)) 11 12 ;; memory.fill 13 (module 14 (memory 1) 15 16 (func (export "fill") (param i32 i32 i32) 17 (memory.fill 18 (local.get 0) 19 (local.get 1) 20 (local.get 2))) 21 22 (func (export "load8_u") (param i32) (result i32) 23 (i32.load8_u (local.get 0))) 24 ) 25 26 ;; Basic fill test. 27 (invoke "fill" (i32.const 1) (i32.const 0xff) (i32.const 3)) 28 (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0)) 29 (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xff)) 30 (assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0xff)) 31 (assert_return (invoke "load8_u" (i32.const 3)) (i32.const 0xff)) 32 (assert_return (invoke "load8_u" (i32.const 4)) (i32.const 0)) 33 34 ;; Fill value is stored as a byte. 35 (invoke "fill" (i32.const 0) (i32.const 0xbbaa) (i32.const 2)) 36 (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xaa)) 37 (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xaa)) 38 39 ;; Fill all of memory 40 (invoke "fill" (i32.const 0) (i32.const 0) (i32.const 0x10000)) 41 42 ;; Out-of-bounds writes trap, and nothing is written 43 (assert_trap (invoke "fill" (i32.const 0xff00) (i32.const 1) (i32.const 0x101)) 44 "out of bounds memory access") 45 (assert_return (invoke "load8_u" (i32.const 0xff00)) (i32.const 0)) 46 (assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0)) 47 48 ;; Succeed when writing 0 bytes at the end of the region. 49 (invoke "fill" (i32.const 0x10000) (i32.const 0) (i32.const 0)) 50 51 ;; Writing 0 bytes outside the memory traps. 52 (assert_trap (invoke "fill" (i32.const 0x10001) (i32.const 0) (i32.const 0)) 53 "out of bounds memory access") 54 55 56 ;; memory.copy 57 (module 58 (memory (data "\aa\bb\cc\dd")) 59 60 (func (export "copy") (param i32 i32 i32) 61 (memory.copy 62 (local.get 0) 63 (local.get 1) 64 (local.get 2))) 65 66 (func (export "load8_u") (param i32) (result i32) 67 (i32.load8_u (local.get 0))) 68 ) 69 70 ;; Non-overlapping copy. 71 (invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) 72 73 (assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) 74 (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) 75 (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) 76 (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) 77 (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) 78 (assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) 79 80 ;; Overlap, source > dest 81 (invoke "copy" (i32.const 8) (i32.const 10) (i32.const 4)) 82 (assert_return (invoke "load8_u" (i32.const 8)) (i32.const 0xaa)) 83 (assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0xbb)) 84 (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xcc)) 85 (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xdd)) 86 (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) 87 (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) 88 89 ;; Overlap, source < dest 90 (invoke "copy" (i32.const 10) (i32.const 7) (i32.const 6)) 91 (assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0)) 92 (assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa)) 93 (assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb)) 94 (assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc)) 95 (assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd)) 96 (assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc)) 97 (assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0)) 98 99 ;; Copy ending at memory limit is ok. 100 (invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) 101 (invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) 102 103 ;; Succeed when copying 0 bytes at the end of the region. 104 (invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) 105 (invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) 106 107 ;; Copying 0 bytes outside the memory traps. 108 (assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) 109 "out of bounds memory access") 110 (assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) 111 "out of bounds memory access") 112 113 114 ;; memory.init 115 (module 116 (memory 1) 117 (data "\aa\bb\cc\dd") 118 119 (func (export "init") (param i32 i32 i32) 120 (memory.init 0 121 (local.get 0) 122 (local.get 1) 123 (local.get 2))) 124 125 (func (export "load8_u") (param i32) (result i32) 126 (i32.load8_u (local.get 0))) 127 ) 128 129 (invoke "init" (i32.const 0) (i32.const 1) (i32.const 2)) 130 (assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xbb)) 131 (assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xcc)) 132 (assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0)) 133 134 ;; Init ending at memory limit and segment limit is ok. 135 (invoke "init" (i32.const 0xfffc) (i32.const 0) (i32.const 4)) 136 137 ;; Out-of-bounds writes trap, and nothing is written. 138 (assert_trap (invoke "init" (i32.const 0xfffe) (i32.const 0) (i32.const 3)) 139 "out of bounds memory access") 140 (assert_return (invoke "load8_u" (i32.const 0xfffe)) (i32.const 0xcc)) 141 (assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0xdd)) 142 143 ;; Succeed when writing 0 bytes at the end of either region. 144 (invoke "init" (i32.const 0x10000) (i32.const 0) (i32.const 0)) 145 (invoke "init" (i32.const 0) (i32.const 4) (i32.const 0)) 146 147 ;; Writing 0 bytes outside the memory traps. 148 (assert_trap (invoke "init" (i32.const 0x10001) (i32.const 0) (i32.const 0)) 149 "out of bounds memory access") 150 (assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0)) 151 "out of bounds memory access") 152 153 ;; data.drop 154 (module 155 (memory 1) 156 (data $p "x") 157 (data $a (memory 0) (i32.const 0) "x") 158 159 (func (export "drop_passive") (data.drop $p)) 160 (func (export "init_passive") (param $len i32) 161 (memory.init $p (i32.const 0) (i32.const 0) (local.get $len))) 162 163 (func (export "drop_active") (data.drop $a)) 164 (func (export "init_active") (param $len i32) 165 (memory.init $a (i32.const 0) (i32.const 0) (local.get $len))) 166 ) 167 168 (invoke "init_passive" (i32.const 1)) 169 (invoke "drop_passive") 170 (invoke "drop_passive") 171 (assert_return (invoke "init_passive" (i32.const 0))) 172 (assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds memory access") 173 (invoke "init_passive" (i32.const 0)) 174 (invoke "drop_active") 175 (assert_return (invoke "init_active" (i32.const 0))) 176 (assert_trap (invoke "init_active" (i32.const 1)) "out of bounds memory access") 177 (invoke "init_active" (i32.const 0)) 178 179 ;; Test that the data segment index is properly encoded as an unsigned (not 180 ;; signed) LEB. 181 (module 182 ;; 65 data segments. 64 is the smallest positive number that is encoded 183 ;; differently as a signed LEB. 184 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 185 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 186 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 187 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 188 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 189 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 190 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 191 (data "") (data "") (data "") (data "") (data "") (data "") (data "") (data "") 192 (data "") 193 (func (data.drop 64))) 194 195 ;; No memory is required for the data.drop instruction. 196 (module (data "goodbye") (func (data.drop 0))) 197 198 ;; table.init 199 (module 200 (table 3 funcref) 201 (elem funcref 202 (ref.func $zero) (ref.func $one) (ref.func $zero) (ref.func $one)) 203 204 (func $zero (result i32) (i32.const 0)) 205 (func $one (result i32) (i32.const 1)) 206 207 (func (export "init") (param i32 i32 i32) 208 (table.init 0 209 (local.get 0) 210 (local.get 1) 211 (local.get 2))) 212 213 (func (export "call") (param i32) (result i32) 214 (call_indirect (result i32) 215 (local.get 0))) 216 ) 217 218 ;; Out-of-bounds stores trap, and nothing is written. 219 (assert_trap (invoke "init" (i32.const 2) (i32.const 0) (i32.const 2)) 220 "out of bounds table access") 221 (assert_trap (invoke "call" (i32.const 2)) 222 "uninitialized element 2") 223 224 (invoke "init" (i32.const 0) (i32.const 1) (i32.const 2)) 225 (assert_return (invoke "call" (i32.const 0)) (i32.const 1)) 226 (assert_return (invoke "call" (i32.const 1)) (i32.const 0)) 227 (assert_trap (invoke "call" (i32.const 2)) "uninitialized element") 228 229 ;; Init ending at table limit and segment limit is ok. 230 (invoke "init" (i32.const 1) (i32.const 2) (i32.const 2)) 231 232 ;; Succeed when storing 0 elements at the end of either region. 233 (invoke "init" (i32.const 3) (i32.const 0) (i32.const 0)) 234 (invoke "init" (i32.const 0) (i32.const 4) (i32.const 0)) 235 236 ;; Writing 0 elements outside the table traps. 237 (assert_trap (invoke "init" (i32.const 4) (i32.const 0) (i32.const 0)) 238 "out of bounds table access") 239 (assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0)) 240 "out of bounds table access") 241 242 243 ;; elem.drop 244 (module 245 (table 1 funcref) 246 (func $f) 247 (elem $p funcref (ref.func $f)) 248 (elem $a (table 0) (i32.const 0) func $f) 249 250 (func (export "drop_passive") (elem.drop $p)) 251 (func (export "init_passive") (param $len i32) 252 (table.init $p (i32.const 0) (i32.const 0) (local.get $len)) 253 ) 254 255 (func (export "drop_active") (elem.drop $a)) 256 (func (export "init_active") (param $len i32) 257 (table.init $a (i32.const 0) (i32.const 0) (local.get $len)) 258 ) 259 ) 260 261 (invoke "init_passive" (i32.const 1)) 262 (invoke "drop_passive") 263 (invoke "drop_passive") 264 (assert_return (invoke "init_passive" (i32.const 0))) 265 (assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds table access") 266 (invoke "init_passive" (i32.const 0)) 267 (invoke "drop_active") 268 (assert_return (invoke "init_active" (i32.const 0))) 269 (assert_trap (invoke "init_active" (i32.const 1)) "out of bounds table access") 270 (invoke "init_active" (i32.const 0)) 271 272 ;; Test that the elem segment index is properly encoded as an unsigned (not 273 ;; signed) LEB. 274 (module 275 ;; 65 elem segments. 64 is the smallest positive number that is encoded 276 ;; differently as a signed LEB. 277 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 278 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 279 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 280 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 281 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 282 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 283 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 284 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 285 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 286 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 287 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 288 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 289 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 290 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 291 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 292 (elem funcref) (elem funcref) (elem funcref) (elem funcref) 293 (elem funcref) 294 (func (elem.drop 64))) 295 296 ;; No table is required for the elem.drop instruction. 297 (module (elem funcref (ref.func 0)) (func (elem.drop 0))) 298 299 ;; table.copy 300 (module 301 (table 10 funcref) 302 (elem (i32.const 0) $zero $one $two) 303 (func $zero (result i32) (i32.const 0)) 304 (func $one (result i32) (i32.const 1)) 305 (func $two (result i32) (i32.const 2)) 306 307 (func (export "copy") (param i32 i32 i32) 308 (table.copy 309 (local.get 0) 310 (local.get 1) 311 (local.get 2))) 312 313 (func (export "call") (param i32) (result i32) 314 (call_indirect (result i32) 315 (local.get 0))) 316 ) 317 318 ;; Non-overlapping copy. 319 (invoke "copy" (i32.const 3) (i32.const 0) (i32.const 3)) 320 ;; Now [$zero, $one, $two, $zero, $one, $two, ...] 321 (assert_return (invoke "call" (i32.const 3)) (i32.const 0)) 322 (assert_return (invoke "call" (i32.const 4)) (i32.const 1)) 323 (assert_return (invoke "call" (i32.const 5)) (i32.const 2)) 324 325 ;; Overlap, source > dest 326 (invoke "copy" (i32.const 0) (i32.const 1) (i32.const 3)) 327 ;; Now [$one, $two, $zero, $zero, $one, $two, ...] 328 (assert_return (invoke "call" (i32.const 0)) (i32.const 1)) 329 (assert_return (invoke "call" (i32.const 1)) (i32.const 2)) 330 (assert_return (invoke "call" (i32.const 2)) (i32.const 0)) 331 332 ;; Overlap, source < dest 333 (invoke "copy" (i32.const 2) (i32.const 0) (i32.const 3)) 334 ;; Now [$one, $two, $one, $two, $zero, $two, ...] 335 (assert_return (invoke "call" (i32.const 2)) (i32.const 1)) 336 (assert_return (invoke "call" (i32.const 3)) (i32.const 2)) 337 (assert_return (invoke "call" (i32.const 4)) (i32.const 0)) 338 339 ;; Copy ending at table limit is ok. 340 (invoke "copy" (i32.const 6) (i32.const 8) (i32.const 2)) 341 (invoke "copy" (i32.const 8) (i32.const 6) (i32.const 2)) 342 343 ;; Succeed when copying 0 elements at the end of the region. 344 (invoke "copy" (i32.const 10) (i32.const 0) (i32.const 0)) 345 (invoke "copy" (i32.const 0) (i32.const 10) (i32.const 0)) 346 347 ;; Fail on out-of-bounds when copying 0 elements outside of table. 348 (assert_trap (invoke "copy" (i32.const 11) (i32.const 0) (i32.const 0)) 349 "out of bounds table access") 350 (assert_trap (invoke "copy" (i32.const 0) (i32.const 11) (i32.const 0)) 351 "out of bounds table access")