Home | History | Annotate | Download | only in wasm
      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