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 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