1// Copyright 2016 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
7const stdlib = {
8  Math: Math,
9  Int8Array: Int8Array,
10  Int16Array: Int16Array,
11  Int32Array: Int32Array,
12  Uint8Array: Uint8Array,
13  Uint16Array: Uint16Array,
14  Uint32Array: Uint32Array,
15  Float32Array: Float32Array,
16  Float64Array: Float64Array,
17};
18
19const buffer = new ArrayBuffer(65536);
20const BASE = 1000000000;
21
22const OOB_INDEXES = [
23  buffer.byteLength,
24  buffer.byteLength + 1,
25  buffer.byteLength + 2,
26  buffer.byteLength + 3,
27  buffer.byteLength + 4,
28  buffer.byteLength + 5,
29  buffer.byteLength + 6,
30  buffer.byteLength + 7,
31  buffer.byteLength + 8,
32  buffer.byteLength + 9,
33  buffer.byteLength + 10,
34  0x80000000,
35  0x80000004,
36  0xF0000000,
37  0xFFFFFFFF,
38  0xFFFFFFFE,
39  -1, -2, -3, -4, -5, -6, -7, -8
40];
41
42function resetBuffer() {
43  var view = new Int32Array(buffer);
44  for (var i = 0; i < view.length; i++) {
45    view[i] = BASE | (i << 2);
46  }
47}
48resetBuffer();
49
50
51function checkView(view, load, shift) {
52  for (var i = 0; i < 300; i++) {
53    assertEquals(view[i >> shift], load(i));
54  }
55}
56
57function RunThreeWayTest(asmfunc, expect) {
58  var asm_source = asmfunc.toString();
59  var nonasm_source = asm_source.replace(new RegExp("use asm"), "");
60
61  var js_module = eval("(" + nonasm_source + ")")(stdlib, {}, buffer);
62  print("Testing " + asmfunc.name + " (js)...");
63  expect(js_module);
64
65  print("Testing " + asmfunc.name + " (asm.js)...");
66  var asm_module = asmfunc(stdlib, {}, buffer);
67  expect(asm_module);
68
69  print("Testing " + asmfunc.name + " (wasm)...");
70  var wasm_module = Wasm.instantiateModuleFromAsm(asm_source, null, buffer);
71  expect(wasm_module);
72}
73
74function LoadAt_i32(stdlib, foreign, buffer) {
75  "use asm";
76  var HEAP32 = new stdlib.Int32Array(buffer);
77  function load(a) {
78    a = a | 0;
79    return HEAP32[a >> 2] | 0;
80  }
81  return {load: load};
82}
83
84RunThreeWayTest(LoadAt_i32, function(module) {
85  var load = module.load;
86  assertEquals(BASE, load(0));
87  assertEquals(BASE | 0x30, load(0x30));
88  assertEquals(BASE | 0x704, load(0x704));
89  assertEquals(BASE | 0x704, load(0x705));
90  assertEquals(BASE | 0x704, load(0x706));
91  assertEquals(BASE | 0x704, load(0x707));
92
93  var length = buffer.byteLength;
94  assertEquals(BASE | (length - 4), load(length - 4));
95  assertEquals(BASE | (length - 4), load(length - 4 + 1));
96  assertEquals(BASE | (length - 4), load(length - 4 + 2));
97  assertEquals(BASE | (length - 4), load(length - 4 + 3));
98
99  for (index of OOB_INDEXES) assertEquals(0, load(index));
100  checkView(new Int32Array(buffer), load, 2);
101});
102
103function LoadAt_i16(stdlib, foreign, buffer) {
104  "use asm";
105  var HEAP16 = new stdlib.Int16Array(buffer);
106  function load(a) {
107    a = a | 0;
108    return HEAP16[a >> 1] | 0;
109  }
110  return {load: load};
111}
112
113RunThreeWayTest(LoadAt_i16, function(module) {
114  var load = module.load;
115  var LOWER = (BASE << 16) >> 16;
116  var UPPER = BASE >> 16;
117  assertEquals(LOWER, load(0));
118  assertEquals(UPPER, load(2));
119
120  assertEquals(LOWER | 0x30, load(0x30));
121  assertEquals(UPPER, load(0x32));
122
123  assertEquals(LOWER | 0x504, load(0x504));
124  assertEquals(LOWER | 0x504, load(0x505));
125
126  assertEquals(UPPER, load(0x706));
127  assertEquals(UPPER, load(0x707));
128
129  var length = buffer.byteLength;
130  assertEquals(LOWER | (length - 4), load(length - 4));
131  assertEquals(LOWER | (length - 4), load(length - 4 + 1));
132  assertEquals(UPPER, load(length - 4 + 2));
133  assertEquals(UPPER, load(length - 4 + 3));
134
135  for (index of OOB_INDEXES) assertEquals(0, load(index));
136  checkView(new Int16Array(buffer), load, 1);
137});
138
139function LoadAt_u16(stdlib, foreign, buffer) {
140  "use asm";
141  var HEAP16 = new stdlib.Uint16Array(buffer);
142  function load(a) {
143    a = a | 0;
144    return HEAP16[a >> 1] | 0;
145  }
146  return {load: load};
147}
148
149RunThreeWayTest(LoadAt_u16, function(module) {
150  var load = module.load;
151  for (index of OOB_INDEXES) assertEquals(0, load(index));
152  checkView(new Uint16Array(buffer), load, 1);
153});
154
155function LoadAt_i8(stdlib, foreign, buffer) {
156  "use asm";
157  var HEAP8 = new stdlib.Int8Array(buffer);
158  function load(a) {
159    a = a | 0;
160    return HEAP8[a >> 0] | 0;
161  }
162  return {load: load};
163}
164
165RunThreeWayTest(LoadAt_i8, function(module) {
166  var load = module.load;
167  for (index of OOB_INDEXES) assertEquals(0, load(index));
168  checkView(new Int8Array(buffer), load, 0);
169});
170
171function LoadAt_u8(stdlib, foreign, buffer) {
172  "use asm";
173  var HEAP8 = new stdlib.Uint8Array(buffer);
174  function load(a) {
175    a = a | 0;
176    return HEAP8[a >> 0] | 0;
177  }
178  return {load: load};
179}
180
181RunThreeWayTest(LoadAt_u8, function(module) {
182  var load = module.load;
183  for (index of OOB_INDEXES) assertEquals(0, load(index));
184  checkView(new Uint8Array(buffer), load, 0);
185});
186
187
188function LoadAt_u32(stdlib, foreign, buffer) {
189  "use asm";
190  var HEAP32 = new stdlib.Uint32Array(buffer);
191  function load(a) {
192    a = a | 0;
193    return +(HEAP32[a >> 2] >>> 0);
194  }
195  return {load: load};
196}
197
198RunThreeWayTest(LoadAt_u32, function(module) {
199  var load = module.load;
200  for (index of OOB_INDEXES) assertEquals(0, load(index));
201  checkView(new Uint32Array(buffer), load, 2);
202});
203
204function LoadAt_f32(stdlib, foreign, buffer) {
205  "use asm";
206  var HEAP32 = new stdlib.Float32Array(buffer);
207  var fround = stdlib.Math.fround;
208  function load(a) {
209    a = a | 0;
210    return fround(HEAP32[a >> 2]);
211  }
212  return {load: load};
213}
214
215RunThreeWayTest(LoadAt_f32, function(module) {
216  var load = module.load;
217  for (index of OOB_INDEXES) assertEquals(NaN, load(index));
218  checkView(new Float32Array(buffer), load, 2);
219});
220
221function LoadAt_f64(stdlib, foreign, buffer) {
222  "use asm";
223  var HEAP64 = new stdlib.Float64Array(buffer);
224  function load(a) {
225    a = a | 0;
226    return +HEAP64[a >> 3];
227  }
228  return {load: load};
229}
230
231RunThreeWayTest(LoadAt_f64, function(module) {
232  var load = module.load;
233  for (index of OOB_INDEXES) assertEquals(NaN, load(index));
234  checkView(new Float64Array(buffer), load, 3);
235});
236
237// TODO(titzer): constant heap indexes
238// TODO(titzer): heap accesses with offsets and arithmetic
239// TODO(titzer): [i >> K] where K is greater than log(size)
240