1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Flags: --expose-wasm 6 7 load("test/mjsunit/wasm/wasm-constants.js"); 8 load("test/mjsunit/wasm/wasm-module-builder.js"); 9 10 function testCallImport(func, check) { 11 var builder = new WasmModuleBuilder(); 12 13 var sig_index = builder.addType(kSig_i_dd); 14 builder.addImport("func", sig_index); 15 builder.addFunction("main", sig_index) 16 .addBody([ 17 kExprGetLocal, 0, // -- 18 kExprGetLocal, 1, // -- 19 kExprCallImport, 2, 0]) // -- 20 .exportAs("main"); 21 22 var main = builder.instantiate({func: func}).exports.main; 23 24 for (var i = 0; i < 100000; i += 10003) { 25 var a = 22.5 + i, b = 10.5 + i; 26 var r = main(a, b); 27 check(r, a, b); 28 } 29 } 30 31 var global = (function() { return this; })(); 32 var params = [-99, -99, -99, -99]; 33 var was_called = false; 34 var length = -1; 35 36 function FOREIGN_SUB(a, b) { 37 print("FOREIGN_SUB(" + a + ", " + b + ")"); 38 was_called = true; 39 params[0] = this; 40 params[1] = a; 41 params[2] = b; 42 return (a - b) | 0; 43 } 44 45 function check_FOREIGN_SUB(r, a, b) { 46 assertEquals(a - b | 0, r); 47 assertTrue(was_called); 48 // assertEquals(global, params[0]); // sloppy mode 49 assertEquals(a, params[1]); 50 assertEquals(b, params[2]); 51 was_called = false; 52 } 53 54 testCallImport(FOREIGN_SUB, check_FOREIGN_SUB); 55 56 57 function FOREIGN_ABCD(a, b, c, d) { 58 print("FOREIGN_ABCD(" + a + ", " + b + ", " + c + ", " + d + ")"); 59 was_called = true; 60 params[0] = this; 61 params[1] = a; 62 params[2] = b; 63 params[3] = c; 64 params[4] = d; 65 return (a * b * 6) | 0; 66 } 67 68 function check_FOREIGN_ABCD(r, a, b) { 69 assertEquals((a * b * 6) | 0, r); 70 assertTrue(was_called); 71 // assertEquals(global, params[0]); // sloppy mode. 72 assertEquals(a, params[1]); 73 assertEquals(b, params[2]); 74 assertEquals(undefined, params[3]); 75 assertEquals(undefined, params[4]); 76 was_called = false; 77 } 78 79 testCallImport(FOREIGN_ABCD, check_FOREIGN_ABCD); 80 81 function FOREIGN_ARGUMENTS0() { 82 print("FOREIGN_ARGUMENTS0"); 83 was_called = true; 84 length = arguments.length; 85 for (var i = 0; i < arguments.length; i++) { 86 params[i] = arguments[i]; 87 } 88 return (arguments[0] * arguments[1] * 7) | 0; 89 } 90 91 function FOREIGN_ARGUMENTS1(a) { 92 print("FOREIGN_ARGUMENTS1", a); 93 was_called = true; 94 length = arguments.length; 95 for (var i = 0; i < arguments.length; i++) { 96 params[i] = arguments[i]; 97 } 98 return (arguments[0] * arguments[1] * 7) | 0; 99 } 100 101 function FOREIGN_ARGUMENTS2(a, b) { 102 print("FOREIGN_ARGUMENTS2", a, b); 103 was_called = true; 104 length = arguments.length; 105 for (var i = 0; i < arguments.length; i++) { 106 params[i] = arguments[i]; 107 } 108 return (a * b * 7) | 0; 109 } 110 111 function FOREIGN_ARGUMENTS3(a, b, c) { 112 print("FOREIGN_ARGUMENTS3", a, b, c); 113 was_called = true; 114 length = arguments.length; 115 for (var i = 0; i < arguments.length; i++) { 116 params[i] = arguments[i]; 117 } 118 return (a * b * 7) | 0; 119 } 120 121 function FOREIGN_ARGUMENTS4(a, b, c, d) { 122 print("FOREIGN_ARGUMENTS4", a, b, c, d); 123 was_called = true; 124 length = arguments.length; 125 for (var i = 0; i < arguments.length; i++) { 126 params[i] = arguments[i]; 127 } 128 return (a * b * 7) | 0; 129 } 130 131 function check_FOREIGN_ARGUMENTS(r, a, b) { 132 assertEquals((a * b * 7) | 0, r); 133 assertTrue(was_called); 134 assertEquals(2, length); 135 assertEquals(a, params[0]); 136 assertEquals(b, params[1]); 137 was_called = false; 138 } 139 140 // Check a bunch of uses of the arguments object. 141 testCallImport(FOREIGN_ARGUMENTS0, check_FOREIGN_ARGUMENTS); 142 testCallImport(FOREIGN_ARGUMENTS1, check_FOREIGN_ARGUMENTS); 143 testCallImport(FOREIGN_ARGUMENTS2, check_FOREIGN_ARGUMENTS); 144 testCallImport(FOREIGN_ARGUMENTS3, check_FOREIGN_ARGUMENTS); 145 testCallImport(FOREIGN_ARGUMENTS4, check_FOREIGN_ARGUMENTS); 146 147 function returnValue(val) { 148 return function(a, b) { 149 print("RETURN_VALUE ", val); 150 return val; 151 } 152 } 153 154 155 function checkReturn(expected) { 156 return function(r, a, b) { assertEquals(expected, r); } 157 } 158 159 // Check that returning weird values doesn't crash 160 testCallImport(returnValue(undefined), checkReturn(0)); 161 testCallImport(returnValue(null), checkReturn(0)); 162 testCallImport(returnValue("0"), checkReturn(0)); 163 testCallImport(returnValue("-77"), checkReturn(-77)); 164 165 var objWithValueOf = {valueOf: function() { return 198; }} 166 167 testCallImport(returnValue(objWithValueOf), checkReturn(198)); 168 169 170 function testCallBinopVoid(type, func, check) { 171 var ffi = new Object(); 172 173 var passed_length = -1; 174 var passed_a = -1; 175 var passed_b = -1; 176 var args_a = -1; 177 var args_b = -1; 178 179 ffi.func = function(a, b) { 180 passed_length = arguments.length; 181 passed_a = a; 182 passed_b = b; 183 args_a = arguments[0]; 184 args_b = arguments[1]; 185 } 186 187 var builder = new WasmModuleBuilder(); 188 189 builder.addImport("func", makeSig_v_xx(type)); 190 builder.addFunction("main", makeSig_r_xx(kAstI32, type)) 191 .addBody([ 192 kExprGetLocal, 0, // -- 193 kExprGetLocal, 1, // -- 194 kExprCallImport, 2, 0, // -- 195 kExprI8Const, 99, // -- 196 ]) 197 .exportFunc("main"); 198 199 var main = builder.instantiate(ffi).exports.main; 200 201 print("testCallBinopVoid", type); 202 203 for (var i = 0; i < 100000; i += 10003.1) { 204 var a = 22.5 + i, b = 10.5 + i; 205 var r = main(a, b); 206 assertEquals(99, r); 207 assertEquals(2, passed_length); 208 var expected_a, expected_b; 209 switch (type) { 210 case kAstI32: { 211 expected_a = a | 0; 212 expected_b = b | 0; 213 break; 214 } 215 case kAstF32: { 216 expected_a = Math.fround(a); 217 expected_b = Math.fround(b); 218 break; 219 } 220 case kAstF64: { 221 expected_a = a; 222 expected_b = b; 223 break; 224 } 225 } 226 227 assertEquals(expected_a, args_a); 228 assertEquals(expected_b, args_b); 229 assertEquals(expected_a, passed_a); 230 assertEquals(expected_b, passed_b); 231 } 232 } 233 234 235 testCallBinopVoid(kAstI32); 236 // TODO testCallBinopVoid(kAstI64); 237 testCallBinopVoid(kAstF32); 238 testCallBinopVoid(kAstF64); 239 240 241 242 function testCallPrint() { 243 var builder = new WasmModuleBuilder(); 244 builder.addImport("print", makeSig_v_x(kAstI32)); 245 builder.addImport("print", makeSig_r_x(kAstF64, kAstF64)); 246 builder.addFunction("main", makeSig_r_x(kAstF64, kAstF64)) 247 .addBody([ 248 kExprI8Const, 97, // -- 249 kExprCallImport, kArity1, 0, // -- 250 kExprGetLocal, 0, // -- 251 kExprCallImport, kArity1, 1 // -- 252 ]) 253 .exportFunc(); 254 255 var main = builder.instantiate({print: print}).exports.main; 256 257 for (var i = -9; i < 900; i += 16.125) { 258 main(i); 259 } 260 } 261 262 testCallPrint(); 263 testCallPrint(); 264 265 266 function testCallImport2(foo, bar, expected) { 267 var builder = new WasmModuleBuilder(); 268 269 builder.addImport("foo", kSig_i); 270 builder.addImport("bar", kSig_i); 271 builder.addFunction("main", kSig_i) 272 .addBody([ 273 kExprCallImport, kArity0, 0, // -- 274 kExprCallImport, kArity0, 1, // -- 275 kExprI32Add, // -- 276 ]) // -- 277 .exportFunc(); 278 279 var main = builder.instantiate({foo: foo, bar: bar}).exports.main; 280 assertEquals(expected, main()); 281 } 282 283 testCallImport2(function() { return 33; }, function () { return 44; }, 77); 284