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 testCallFFI(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, kArity2, 0 // -- 20 ]) // -- 21 .exportFunc(); 22 23 var main = builder.instantiate({func: func}).exports.main; 24 25 for (var i = 0; i < 100000; i += 10003) { 26 var a = 22.5 + i, b = 10.5 + i; 27 var r = main(a, b); 28 check(r, a, b); 29 } 30 } 31 32 var global = (function() { return this; })(); 33 var params = [-99, -99, -99, -99, -99]; 34 var was_called = false; 35 var length = -1; 36 37 function FOREIGN_SUB(a, b) { 38 print("FOREIGN_SUB(" + a + ", " + b + ")"); 39 was_called = true; 40 params[0] = this; 41 params[1] = a; 42 params[2] = b; 43 return (a - b) | 0; 44 } 45 46 function check_FOREIGN_SUB(r, a, b) { 47 assertEquals(a - b | 0, r); 48 assertTrue(was_called); 49 // assertEquals(global, params[0]); // sloppy mode 50 assertEquals(a, params[1]); 51 assertEquals(b, params[2]); 52 was_called = false; 53 } 54 55 testCallFFI(FOREIGN_SUB, check_FOREIGN_SUB); 56 57 58 function FOREIGN_ABCD(a, b, c, d) { 59 print("FOREIGN_ABCD(" + a + ", " + b + ", " + c + ", " + d + ")"); 60 was_called = true; 61 params[0] = this; 62 params[1] = a; 63 params[2] = b; 64 params[3] = c; 65 params[4] = d; 66 return (a * b * 6) | 0; 67 } 68 69 function check_FOREIGN_ABCD(r, a, b) { 70 assertEquals((a * b * 6) | 0, r); 71 assertTrue(was_called); 72 // assertEquals(global, params[0]); // sloppy mode. 73 assertEquals(a, params[1]); 74 assertEquals(b, params[2]); 75 assertEquals(undefined, params[3]); 76 assertEquals(undefined, params[4]); 77 was_called = false; 78 } 79 80 testCallFFI(FOREIGN_ABCD, check_FOREIGN_ABCD); 81 82 function FOREIGN_ARGUMENTS0() { 83 print("FOREIGN_ARGUMENTS0"); 84 was_called = true; 85 length = arguments.length; 86 for (var i = 0; i < arguments.length; i++) { 87 params[i] = arguments[i]; 88 } 89 return (arguments[0] * arguments[1] * 7) | 0; 90 } 91 92 function FOREIGN_ARGUMENTS1(a) { 93 print("FOREIGN_ARGUMENTS1", a); 94 was_called = true; 95 length = arguments.length; 96 for (var i = 0; i < arguments.length; i++) { 97 params[i] = arguments[i]; 98 } 99 return (arguments[0] * arguments[1] * 7) | 0; 100 } 101 102 function FOREIGN_ARGUMENTS2(a, b) { 103 print("FOREIGN_ARGUMENTS2", a, b); 104 was_called = true; 105 length = arguments.length; 106 for (var i = 0; i < arguments.length; i++) { 107 params[i] = arguments[i]; 108 } 109 return (a * b * 7) | 0; 110 } 111 112 function FOREIGN_ARGUMENTS3(a, b, c) { 113 print("FOREIGN_ARGUMENTS3", a, b, c); 114 was_called = true; 115 length = arguments.length; 116 for (var i = 0; i < arguments.length; i++) { 117 params[i] = arguments[i]; 118 } 119 return (a * b * 7) | 0; 120 } 121 122 function FOREIGN_ARGUMENTS4(a, b, c, d) { 123 print("FOREIGN_ARGUMENTS4", a, b, c, d); 124 was_called = true; 125 length = arguments.length; 126 for (var i = 0; i < arguments.length; i++) { 127 params[i] = arguments[i]; 128 } 129 return (a * b * 7) | 0; 130 } 131 132 function check_FOREIGN_ARGUMENTS(r, a, b) { 133 assertEquals((a * b * 7) | 0, r); 134 assertTrue(was_called); 135 assertEquals(2, length); 136 assertEquals(a, params[0]); 137 assertEquals(b, params[1]); 138 was_called = false; 139 } 140 141 // Check a bunch of uses of the arguments object. 142 testCallFFI(FOREIGN_ARGUMENTS0, check_FOREIGN_ARGUMENTS); 143 testCallFFI(FOREIGN_ARGUMENTS1, check_FOREIGN_ARGUMENTS); 144 testCallFFI(FOREIGN_ARGUMENTS2, check_FOREIGN_ARGUMENTS); 145 testCallFFI(FOREIGN_ARGUMENTS3, check_FOREIGN_ARGUMENTS); 146 testCallFFI(FOREIGN_ARGUMENTS4, check_FOREIGN_ARGUMENTS); 147 148 function returnValue(val) { 149 return function(a, b) { 150 print("RETURN_VALUE ", val); 151 return val; 152 } 153 } 154 155 156 function checkReturn(expected) { 157 return function(r, a, b) { assertEquals(expected, r); } 158 } 159 160 // Check that returning weird values doesn't crash 161 testCallFFI(returnValue(undefined), checkReturn(0)); 162 testCallFFI(returnValue(null), checkReturn(0)); 163 testCallFFI(returnValue("0"), checkReturn(0)); 164 testCallFFI(returnValue("-77"), checkReturn(-77)); 165 166 var objWithValueOf = {valueOf: function() { return 198; }} 167 168 testCallFFI(returnValue(objWithValueOf), checkReturn(198)); 169 170 171 function testCallBinopVoid(type, func, check) { 172 var passed_length = -1; 173 var passed_a = -1; 174 var passed_b = -1; 175 var args_a = -1; 176 var args_b = -1; 177 178 ffi = {func: function(a, b) { 179 passed_length = arguments.length; 180 passed_a = a; 181 passed_b = b; 182 args_a = arguments[0]; 183 args_b = arguments[1]; 184 }}; 185 186 var builder = new WasmModuleBuilder(); 187 188 builder.addImport("func", makeSig_v_xx(type)); 189 builder.addFunction("main", makeSig_r_xx(kAstI32, type)) 190 .addBody([ 191 kExprGetLocal, 0, // -- 192 kExprGetLocal, 1, // -- 193 kExprCallImport, kArity2, 0, // -- 194 kExprI8Const, 99 // -- 195 ]) // -- 196 .exportFunc() 197 198 var main = builder.instantiate(ffi).exports.main; 199 200 print("testCallBinopVoid", type); 201 202 for (var i = 0; i < 100000; i += 10003.1) { 203 var a = 22.5 + i, b = 10.5 + i; 204 var r = main(a, b); 205 assertEquals(99, r); 206 assertEquals(2, passed_length); 207 var expected_a, expected_b; 208 switch (type) { 209 case kAstI32: { 210 expected_a = a | 0; 211 expected_b = b | 0; 212 break; 213 } 214 case kAstF32: { 215 expected_a = Math.fround(a); 216 expected_b = Math.fround(b); 217 break; 218 } 219 case kAstF64: { 220 expected_a = a; 221 expected_b = b; 222 break; 223 } 224 } 225 226 assertEquals(expected_a, args_a); 227 assertEquals(expected_b, args_b); 228 assertEquals(expected_a, passed_a); 229 assertEquals(expected_b, passed_b); 230 } 231 } 232 233 234 testCallBinopVoid(kAstI32); 235 // TODO testCallBinopVoid(kAstI64); 236 testCallBinopVoid(kAstF32); 237 testCallBinopVoid(kAstF64); 238 239 240 241 function testCallPrint() { 242 var builder = new WasmModuleBuilder(); 243 244 builder.addImport("print", makeSig_v_x(kAstI32)); 245 builder.addImport("print", makeSig_v_x(kAstF64)); 246 builder.addFunction("main", makeSig_v_x(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 for (var i = -9; i < 900; i += 6.125) main(i); 257 } 258 259 testCallPrint(); 260 testCallPrint(); 261