|
| 1 | +;; No type immediate. |
| 2 | +(assert_malformed |
| 3 | + (module quote |
| 4 | + "(module" |
| 5 | + "(func (drop (cont.new)))" |
| 6 | + ")" |
| 7 | + ) |
| 8 | + "unexpected token" |
| 9 | +) |
| 10 | + |
| 11 | +(assert_malformed |
| 12 | + (module binary |
| 13 | + "\00asm\01\00\00\00" |
| 14 | + "\01\04\01\60\00\00" ;; Type section: 1 type |
| 15 | + "\03\02\01\00" ;; Function section: 1 function |
| 16 | + "\0a\04\01" ;; Code section: 1 function |
| 17 | + ;; function 0 |
| 18 | + "\02\00" ;; Function size and local type count |
| 19 | + "\e0" ;; cont.new (missing type immediate) |
| 20 | + ) |
| 21 | + "unexpected end" |
| 22 | +) |
| 23 | + |
| 24 | +;; Valid binary module parsing, validating, and executing correctly |
| 25 | +(module binary |
| 26 | + "\00\61\73\6d\01\00\00\00" ;; Magic header and version |
| 27 | + "\01\8b\80\80\80\00\03" ;; Type section: 3 types |
| 28 | + "\60\00\00" ;; type 0: func [] -> [] |
| 29 | + "\5d\00" ;; type 1: cont 0 |
| 30 | + "\60\00\01\64\01" ;; type 2: func [] -> [ref 1] |
| 31 | + "\03\83\80\80\80\00\02" ;; Function section: 2 functions |
| 32 | + "\00\02" ;; func 0: type 0, func 1: type 2 |
| 33 | + "\07\88\80\80\80\00\01" ;; Export section: 1 export |
| 34 | + "\04\74\65\73\74\00\01" ;; "test" -> func 1 |
| 35 | + "\09\85\80\80\80\00\01" ;; Element section: 1 segment |
| 36 | + "\03\00\01\00" ;; declarative, elem kind func, 1 func, func index 0 |
| 37 | + "\0a\93\80\80\80\00\02" ;; Code section: 2 functions |
| 38 | + ;; function 0 |
| 39 | + "\82\80\80\80\00\00\0b" ;; size 2, 0 locals, end |
| 40 | + ;; function 1 |
| 41 | + "\86\80\80\80\00\00" ;; size 6, 0 locals |
| 42 | + "\d2\00" ;; ref.func 0 |
| 43 | + "\e0\01" ;; cont.new 1 |
| 44 | + "\0b" ;; end |
| 45 | +) |
| 46 | +(assert_return (invoke "test") (ref.cont)) |
| 47 | + |
| 48 | +;; Out-of-bounds type immediate. |
| 49 | +(assert_invalid |
| 50 | + (module |
| 51 | + (func (drop (cont.new 0 (unreachable)))) |
| 52 | + ) |
| 53 | + "non-continuation type" |
| 54 | +) |
| 55 | + |
| 56 | +;; Non-continuation type. |
| 57 | +(assert_invalid |
| 58 | + (module |
| 59 | + (type $f (func)) |
| 60 | + (func (drop (cont.new $f (unreachable)))) |
| 61 | + ) |
| 62 | + "non-continuation type" |
| 63 | +) |
| 64 | + |
| 65 | +;; Defined function ref.func operand. |
| 66 | +(module |
| 67 | + (type $f (func)) |
| 68 | + (type $k (cont $f)) |
| 69 | + (elem declare func $f) |
| 70 | + (func $f (type $f)) |
| 71 | + (func (export "test") (result (ref $k)) (cont.new $k (ref.func $f))) |
| 72 | +) |
| 73 | +(assert_return (invoke "test") (ref.cont)) |
| 74 | + |
| 75 | +;; Imported function ref.func operand. |
| 76 | +(module definition |
| 77 | + (type $f (func)) |
| 78 | + (type $k (cont $f)) |
| 79 | + (elem declare func $f) |
| 80 | + (import "" "" (func $f (type $f))) |
| 81 | + (func (result (ref $k)) (cont.new $k (ref.func $f))) |
| 82 | +) |
| 83 | + |
| 84 | +;; Defined global operand. |
| 85 | +(module |
| 86 | + (type $f (func)) |
| 87 | + (type $k (cont $f)) |
| 88 | + (global $g (ref null $f) (ref.null nofunc)) |
| 89 | + (func (export "test") (result (ref $k)) (cont.new $k (global.get $g))) |
| 90 | +) |
| 91 | +(assert_trap (invoke "test") "null function reference") |
| 92 | + |
| 93 | +;; Defined global operand (non-null at runtime). |
| 94 | +(module |
| 95 | + (type $f (func)) |
| 96 | + (type $k (cont $f)) |
| 97 | + (elem declare func $f) |
| 98 | + (func $f (type $f)) |
| 99 | + (global $g (ref null $f) (ref.func $f)) |
| 100 | + (func (export "test") (result (ref $k)) (cont.new $k (global.get $g))) |
| 101 | +) |
| 102 | +(assert_return (invoke "test") (ref.cont)) |
| 103 | + |
| 104 | +;; Imported global operand. |
| 105 | +(module definition |
| 106 | + (type $f (func)) |
| 107 | + (type $k (cont $f)) |
| 108 | + (import "" "" (global $g (ref null $f))) |
| 109 | + (func (result (ref $k)) (cont.new $k (global.get $g))) |
| 110 | +) |
| 111 | + |
| 112 | +;; Param operand. |
| 113 | +(module |
| 114 | + (type $f (func)) |
| 115 | + (type $k (cont $f)) |
| 116 | + (func (export "test") (param (ref null $f)) (result (ref $k)) |
| 117 | + (cont.new $k (local.get 0)) |
| 118 | + ) |
| 119 | +) |
| 120 | +(assert_trap (invoke "test" (ref.null nofunc)) "null function reference") |
| 121 | + |
| 122 | +;; Stack-polymorphic (unreachable) input. |
| 123 | +(module |
| 124 | + (type $f (func)) |
| 125 | + (type $k (cont $f)) |
| 126 | + (func (export "test") (result (ref $k)) (cont.new $k (unreachable))) |
| 127 | +) |
| 128 | +(assert_trap (invoke "test") "unreachable") |
| 129 | + |
| 130 | +;; Stack-polymorphic (unreachable) input due to branch. |
| 131 | +(module |
| 132 | + (type $f (func)) |
| 133 | + (type $k (cont $f)) |
| 134 | + (func (export "test") |
| 135 | + (drop |
| 136 | + (block $l (result (ref $k)) |
| 137 | + (cont.new $k (return)) |
| 138 | + ) |
| 139 | + ) |
| 140 | + ) |
| 141 | +) |
| 142 | +(assert_return (invoke "test")) |
| 143 | + |
| 144 | +;; Uninhabitable bottom input. |
| 145 | +(module |
| 146 | + (type $f (func)) |
| 147 | + (type $k (cont $f)) |
| 148 | + (func (param (ref nofunc)) (result (ref $k)) (cont.new $k (local.get 0))) |
| 149 | +) |
| 150 | + |
| 151 | +;; Null constant input. |
| 152 | +(module |
| 153 | + (type $f (func)) |
| 154 | + (type $k (cont $f)) |
| 155 | + (func (export "test") (result (ref $k)) (cont.new $k (ref.null $f))) |
| 156 | +) |
| 157 | +(assert_trap (invoke "test") "null function reference") |
| 158 | + |
| 159 | +;; Bottom null constant input. |
| 160 | +(module |
| 161 | + (type $f (func)) |
| 162 | + (type $k (cont $f)) |
| 163 | + (func (export "test") (result (ref $k)) (cont.new $k (ref.null nofunc))) |
| 164 | +) |
| 165 | +(assert_trap (invoke "test") "null function reference") |
| 166 | + |
| 167 | +;; Top null constant input. |
| 168 | +(assert_invalid |
| 169 | + (module |
| 170 | + (type $f (func)) |
| 171 | + (type $k (cont $f)) |
| 172 | + (func (result (ref $k)) (cont.new $k (ref.null func))) |
| 173 | + ) |
| 174 | + "type mismatch" |
| 175 | +) |
| 176 | + |
| 177 | +;; Any hierarchy null constant input. |
| 178 | +(assert_invalid |
| 179 | + (module |
| 180 | + (type $f (func)) |
| 181 | + (type $k (cont $f)) |
| 182 | + (func (result (ref $k)) (cont.new $k (ref.null none))) |
| 183 | + ) |
| 184 | + "type mismatch" |
| 185 | +) |
| 186 | + |
| 187 | +;; Cont hierarchy null constant input. |
| 188 | +(assert_invalid |
| 189 | + (module |
| 190 | + (type $f (func)) |
| 191 | + (type $k (cont $f)) |
| 192 | + (func (result (ref $k)) (cont.new $k (ref.null nocont))) |
| 193 | + ) |
| 194 | + "type mismatch" |
| 195 | +) |
| 196 | + |
| 197 | +;; Top reference input. |
| 198 | +(assert_invalid |
| 199 | + (module |
| 200 | + (type $f (func)) |
| 201 | + (type $k (cont $f)) |
| 202 | + (func (param funcref) (result (ref $k)) (cont.new $k (local.get 0))) |
| 203 | + ) |
| 204 | + "type mismatch" |
| 205 | +) |
| 206 | + |
| 207 | +;; Declared subtype input. |
| 208 | +(module |
| 209 | + (type $super (sub (func))) |
| 210 | + (type $sub (sub $super (func))) |
| 211 | + (type $k (cont $super)) |
| 212 | + (elem declare func $sub) |
| 213 | + (func $sub (type $sub)) |
| 214 | + (func (export "test") (result (ref $k)) (cont.new $k (ref.func $sub))) |
| 215 | +) |
| 216 | +(assert_return (invoke "test") (ref.cont)) |
| 217 | + |
| 218 | +;; Declared supertype input. |
| 219 | +(assert_invalid |
| 220 | + (module |
| 221 | + (type $super (sub (func))) |
| 222 | + (type $sub (sub $super (func))) |
| 223 | + (type $k (cont $sub)) |
| 224 | + (func (param (ref null $super)) (result (ref $k)) (cont.new $k (local.get 0))) |
| 225 | + ) |
| 226 | + "type mismatch" |
| 227 | +) |
| 228 | + |
| 229 | +;; Unrelated input. |
| 230 | +(assert_invalid |
| 231 | + (module |
| 232 | + (rec |
| 233 | + (type $f (func)) |
| 234 | + (type $other (func)) |
| 235 | + ) |
| 236 | + (type $k (cont $f)) |
| 237 | + (func (param (ref null $other)) (result (ref $k)) (cont.new $k (local.get 0))) |
| 238 | + ) |
| 239 | + "type mismatch" |
| 240 | +) |
| 241 | + |
| 242 | +;; Missing input. |
| 243 | +(assert_invalid |
| 244 | + (module |
| 245 | + (type $f (func)) |
| 246 | + (type $k (cont $f)) |
| 247 | + (func (result (ref $k)) (cont.new $k)) |
| 248 | + ) |
| 249 | + "type mismatch" |
| 250 | +) |
| 251 | + |
| 252 | +;; Extra input. |
| 253 | +(assert_invalid |
| 254 | + (module |
| 255 | + (type $f (func)) |
| 256 | + (type $k (cont $f)) |
| 257 | + (func (param (ref null $f)) (result (ref $k)) (cont.new $k (i32.const 0) (local.get 0))) |
| 258 | + ) |
| 259 | + "type mismatch" |
| 260 | +) |
| 261 | + |
| 262 | +;; Extra input matching continuation params. |
| 263 | +(assert_invalid |
| 264 | + (module |
| 265 | + (type $f (func (param i32))) |
| 266 | + (type $k (cont $f)) |
| 267 | + (func (param (ref null $f)) (result (ref $k)) (cont.new $k (i32.const 0) (local.get 0))) |
| 268 | + ) |
| 269 | + "type mismatch" |
| 270 | +) |
| 271 | + |
| 272 | +;; Contref output type. |
| 273 | +(module |
| 274 | + (type $f (func)) |
| 275 | + (type $k (cont $f)) |
| 276 | + (func (param (ref null $f)) (result contref) (cont.new $k (local.get 0))) |
| 277 | +) |
| 278 | + |
| 279 | +;; Nullable cont reference output type. |
| 280 | +(module |
| 281 | + (type $f (func)) |
| 282 | + (type $k (cont $f)) |
| 283 | + (func (param (ref null $f)) (result (ref null cont)) (cont.new $k (local.get 0))) |
| 284 | +) |
| 285 | + |
| 286 | +;; Non-nullable cont reference output type. |
| 287 | +(module |
| 288 | + (type $f (func)) |
| 289 | + (type $k (cont $f)) |
| 290 | + (func (param (ref null $f)) (result (ref cont)) (cont.new $k (local.get 0))) |
| 291 | +) |
| 292 | + |
| 293 | +;; Declared supertype output type. |
| 294 | +(module |
| 295 | + (type $f (func)) |
| 296 | + (type $super (sub (cont $f))) |
| 297 | + (type $sub (sub $super (cont $f))) |
| 298 | + (func (param (ref null $f)) (result (ref $super)) (cont.new $sub (local.get 0))) |
| 299 | +) |
| 300 | + |
| 301 | +;; Declared subtype output type. |
| 302 | +(assert_invalid |
| 303 | + (module |
| 304 | + (type $f (func)) |
| 305 | + (type $super (sub (cont $f))) |
| 306 | + (type $sub (sub $super (cont $f))) |
| 307 | + (func (param (ref null $f)) (result (ref $sub)) (cont.new $super (local.get 0))) |
| 308 | + ) |
| 309 | + "type mismatch" |
| 310 | +) |
| 311 | + |
| 312 | +;; Unrelated output. |
| 313 | +(assert_invalid |
| 314 | + (module |
| 315 | + (type $f (func)) |
| 316 | + (rec |
| 317 | + (type $k (cont $f)) |
| 318 | + (type $other (cont $f)) |
| 319 | + ) |
| 320 | + (func (param (ref null $f)) (result (ref $other)) (cont.new $k (local.get 0))) |
| 321 | + ) |
| 322 | + "type mismatch" |
| 323 | +) |
| 324 | + |
| 325 | +;; TODO: Make cont.new constant |
| 326 | +;; https://github.com/WebAssembly/stack-switching/issues/145 |
| 327 | + |
| 328 | +;; ;; Constant expression in global definition. |
| 329 | +;; (module |
| 330 | +;; (type $f (func)) |
| 331 | +;; (type $k (cont $f)) |
| 332 | +;; (global $k (export "k") (ref $k) (cont.new $k (ref.func $f))) |
| 333 | +;; (func $f (type $f)) |
| 334 | +;; ) |
| 335 | +;; (assert_return (get "k") (ref.cont)) |
| 336 | + |
| 337 | +;; ;; Constant expression in element segment definition. |
| 338 | +;; (module |
| 339 | +;; (type $f (func)) |
| 340 | +;; (type $k (cont $f)) |
| 341 | +;; (table $t (ref null $k) (elem (cont.new $k (ref.func $f)))) |
| 342 | +;; (func $f (type $f)) |
| 343 | +;; (func (export "get") (result (ref null $k)) (table.get $t (i32.const 0))) |
| 344 | +;; ) |
| 345 | +;; (assert_return (invoke "get") (ref.cont)) |
0 commit comments