select.js (6813B)
1 // Test the select instruction 2 3 wasmFailValidateText('(module (func (select (i32.const 0) (i32.const 0) (f32.const 0))))', mismatchError("f32", "i32")); 4 5 wasmFailValidateText('(module (func (select (i32.const 0) (f32.const 0) (i32.const 0))) (export "" (func 0)))', /(select operand types must match)|(type mismatch: expected f32, found i32)/); 6 wasmFailValidateText('(module (func (select (block ) (i32.const 0) (i32.const 0))) (export "" (func 0)))', emptyStackError); 7 wasmFailValidateText('(module (func (select (return) (i32.const 0) (i32.const 0))) (export "" (func 0)))', unusedValuesError); 8 assertEq(wasmEvalText('(module (func (drop (select (return) (i32.const 0) (i32.const 0)))) (export "" (func 0)))').exports[""](), undefined); 9 assertEq(wasmEvalText('(module (func (result i32) (i32.add (i32.const 0) (select (return (i32.const 42)) (i32.const 0) (i32.const 0)))) (export "" (func 0)))').exports[""](), 42); 10 wasmFailValidateText('(module (func (select (if (result i32) (i32.const 1) (then (i32.const 0)) (else (f32.const 0))) (i32.const 0) (i32.const 0))) (export "" (func 0)))', mismatchError("f32", "i32")); 11 wasmFailValidateText('(module (func) (func (select (call 0) (call 0) (i32.const 0))) (export "" (func 0)))', emptyStackError); 12 13 (function testSideEffects() { 14 15 var numT = 0; 16 var numF = 0; 17 18 var imports = {"": { 19 ifTrue: () => 1 + numT++, 20 ifFalse: () => -1 + numF++, 21 }} 22 23 // Test that side-effects are applied on both branches. 24 var f = wasmEvalText(` 25 (module 26 (import "" "ifTrue" (func (result i32))) 27 (import "" "ifFalse" (func (result i32))) 28 (func (param i32) (result i32) 29 (select 30 (call 0) 31 (call 1) 32 (local.get 0) 33 ) 34 ) 35 (export "" (func 2)) 36 ) 37 `, imports).exports[""]; 38 39 assertEq(f(-1), numT); 40 assertEq(numT, 1); 41 assertEq(numF, 1); 42 43 assertEq(f(0), numF - 2); 44 assertEq(numT, 2); 45 assertEq(numF, 2); 46 47 assertEq(f(1), numT); 48 assertEq(numT, 3); 49 assertEq(numF, 3); 50 51 assertEq(f(0), numF - 2); 52 assertEq(numT, 4); 53 assertEq(numF, 4); 54 55 assertEq(f(0), numF - 2); 56 assertEq(numT, 5); 57 assertEq(numF, 5); 58 59 assertEq(f(1), numT); 60 assertEq(numT, 6); 61 assertEq(numF, 6); 62 63 })(); 64 65 function testNumSelect(type, trueVal, falseVal) { 66 var trueJS = jsify(trueVal); 67 var falseJS = jsify(falseVal); 68 69 // Always true condition 70 var alwaysTrue = wasmEvalText(` 71 (module 72 (func (param i32) (result ${type}) 73 (select 74 (${type}.const ${trueVal}) 75 (${type}.const ${falseVal}) 76 (i32.const 1) 77 ) 78 ) 79 (export "" (func 0)) 80 ) 81 `, {}).exports[""]; 82 83 assertEq(alwaysTrue(0), trueJS); 84 assertEq(alwaysTrue(1), trueJS); 85 assertEq(alwaysTrue(-1), trueJS); 86 87 // Always false condition 88 var alwaysFalse = wasmEvalText(` 89 (module 90 (func (param i32) (result ${type}) 91 (select 92 (${type}.const ${trueVal}) 93 (${type}.const ${falseVal}) 94 (i32.const 0) 95 ) 96 ) 97 (export "" (func 0)) 98 ) 99 `, {}).exports[""]; 100 101 assertEq(alwaysFalse(0), falseJS); 102 assertEq(alwaysFalse(1), falseJS); 103 assertEq(alwaysFalse(-1), falseJS); 104 105 // Variable condition 106 var f = wasmEvalText(` 107 (module 108 (func (param i32) (result ${type}) 109 (select 110 (${type}.const ${trueVal}) 111 (${type}.const ${falseVal}) 112 (local.get 0) 113 ) 114 ) 115 (export "" (func 0)) 116 ) 117 `, {}).exports[""]; 118 119 assertEq(f(0), falseJS); 120 assertEq(f(1), trueJS); 121 assertEq(f(-1), trueJS); 122 123 wasmFullPass(` 124 (module 125 (func (param i32) (result ${type}) 126 (select 127 (${type}.const ${trueVal}) 128 (${type}.const ${falseVal}) 129 (local.get 0) 130 ) 131 ) 132 (export "run" (func 0)) 133 )`, 134 trueJS, 135 {}, 136 1); 137 } 138 139 testNumSelect('i32', 13, 37); 140 testNumSelect('i32', Math.pow(2, 31) - 1, -Math.pow(2, 31)); 141 142 testNumSelect('f32', Math.fround(13.37), Math.fround(19.89)); 143 testNumSelect('f32', 'inf', '-0'); 144 testNumSelect('f32', 'nan', Math.pow(2, -31)); 145 146 testNumSelect('f64', 13.37, 19.89); 147 testNumSelect('f64', 'inf', '-0'); 148 testNumSelect('f64', 'nan', Math.pow(2, -31)); 149 150 wasmAssert(` 151 (module 152 (func $f (param i32) (result i64) 153 (select 154 (i64.const 0xc0010ff08badf00d) 155 (i64.const 0x12345678deadc0de) 156 (local.get 0) 157 ) 158 ) 159 (export "" (func 0)) 160 )`, [ 161 { type: 'i64', func: '$f', args: ['i32.const 0'], expected: '0x12345678deadc0de' }, 162 { type: 'i64', func: '$f', args: ['i32.const 1'], expected: '0xc0010ff08badf00d' }, 163 { type: 'i64', func: '$f', args: ['i32.const -1'], expected: '0xc0010ff08badf00d' }, 164 ], {}); 165 166 wasmFailValidateText(`(module 167 (func (param externref) 168 (select (local.get 0) (local.get 0) (i32.const 0)) 169 drop 170 ))`, 171 /(untyped select)|(type mismatch: select only takes integral types)/); 172 173 wasmFailValidateText(`(module 174 (func (param funcref) 175 (select (local.get 0) (local.get 0) (i32.const 0)) 176 drop 177 ))`, 178 /(untyped select)|(type mismatch: select only takes integral types)/); 179 180 function testRefSelect(type, trueVal, falseVal) { 181 // Always true condition 182 var alwaysTrue = wasmEvalText(` 183 (module 184 (func (param i32 ${type} ${type}) (result ${type}) 185 (select (result ${type}) 186 local.get 1 187 local.get 2 188 (i32.const 1) 189 ) 190 ) 191 (export "" (func 0)) 192 ) 193 `, {}).exports[""]; 194 195 assertEq(alwaysTrue(0, trueVal, falseVal), trueVal); 196 assertEq(alwaysTrue(1, trueVal, falseVal), trueVal); 197 assertEq(alwaysTrue(-1, trueVal, falseVal), trueVal); 198 199 // Always false condition 200 var alwaysFalse = wasmEvalText(` 201 (module 202 (func (param i32 ${type} ${type}) (result ${type}) 203 (select (result ${type}) 204 local.get 1 205 local.get 2 206 (i32.const 0) 207 ) 208 ) 209 (export "" (func 0)) 210 ) 211 `, {}).exports[""]; 212 213 assertEq(alwaysFalse(0, trueVal, falseVal), falseVal); 214 assertEq(alwaysFalse(1, trueVal, falseVal), falseVal); 215 assertEq(alwaysFalse(-1, trueVal, falseVal), falseVal); 216 217 // Variable condition 218 var f = wasmEvalText(` 219 (module 220 (func (param i32 ${type} ${type}) (result ${type}) 221 (select (result ${type}) 222 local.get 1 223 local.get 2 224 (local.get 0) 225 ) 226 ) 227 (export "" (func 0)) 228 ) 229 `, {}).exports[""]; 230 231 assertEq(f(0, trueVal, falseVal), falseVal); 232 assertEq(f(1, trueVal, falseVal), trueVal); 233 assertEq(f(-1, trueVal, falseVal), trueVal); 234 235 wasmFullPass(` 236 (module 237 (func (param i32 ${type} ${type}) (result ${type}) 238 (select (result ${type}) 239 local.get 1 240 local.get 2 241 (local.get 0) 242 ) 243 ) 244 (export "run" (func 0)) 245 )`, 246 trueVal, 247 {}, 248 1, 249 trueVal, 250 falseVal); 251 } 252 253 testRefSelect('externref', {}, {}); 254 255 let {export1, export2} = wasmEvalText(`(module 256 (func (export "export1")) 257 (func (export "export2")) 258 )`).exports; 259 260 testRefSelect('funcref', export1, export2);