blob: 9c67fd523fb57e3a824fb3a44584174f9fede372 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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#include "src/assembler.h"
6#include "src/codegen.h"
7#include "src/compiler/linkage.h"
8#include "src/compiler/raw-machine-assembler.h"
9#include "src/machine-type.h"
10#include "src/register-configuration.h"
11
12#include "test/cctest/cctest.h"
13#include "test/cctest/compiler/codegen-tester.h"
14#include "test/cctest/compiler/graph-builder-tester.h"
15#include "test/cctest/compiler/value-helper.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
Ben Murdoch61f157c2016-09-16 13:49:30 +010021const auto GetRegConfig = RegisterConfiguration::Turbofan;
22
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023namespace {
24typedef float float32;
25typedef double float64;
26
27// Picks a representative pair of integers from the given range.
28// If there are less than {max_pairs} possible pairs, do them all, otherwise try
29// to select a representative set.
30class Pairs {
31 public:
32 Pairs(int max_pairs, int range, const int* codes)
33 : range_(range),
34 codes_(codes),
35 max_pairs_(std::min(max_pairs, range_ * range_)),
36 counter_(0) {}
37
38 bool More() { return counter_ < max_pairs_; }
39
40 void Next(int* r0, int* r1, bool same_is_ok) {
41 do {
42 // Find the next pair.
43 if (exhaustive()) {
44 *r0 = codes_[counter_ % range_];
45 *r1 = codes_[counter_ / range_];
46 } else {
47 // Try each integer at least once for both r0 and r1.
48 int index = counter_ / 2;
49 if (counter_ & 1) {
50 *r0 = codes_[index % range_];
51 *r1 = codes_[index / range_];
52 } else {
53 *r1 = codes_[index % range_];
54 *r0 = codes_[index / range_];
55 }
56 }
57 counter_++;
58 if ((same_is_ok) || (*r0 != *r1)) break;
59 if (counter_ == max_pairs_) {
60 // For the last hurrah, reg#0 with reg#n-1
61 *r0 = codes_[0];
62 *r1 = codes_[range_ - 1];
63 break;
64 }
65 } while (true);
66 }
67
68 private:
69 int range_;
70 const int* codes_;
71 int max_pairs_;
72 int counter_;
73 bool exhaustive() { return max_pairs_ == (range_ * range_); }
74};
75
76
77// Pairs of general purpose registers.
78class RegisterPairs : public Pairs {
79 public:
80 RegisterPairs()
Ben Murdoch61f157c2016-09-16 13:49:30 +010081 : Pairs(100, GetRegConfig()->num_allocatable_general_registers(),
82 GetRegConfig()->allocatable_general_codes()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083};
84
85
86// Pairs of double registers.
87class Float32RegisterPairs : public Pairs {
88 public:
89 Float32RegisterPairs()
90 : Pairs(
91 100,
Ben Murdoch61f157c2016-09-16 13:49:30 +010092#if V8_TARGET_ARCH_ARM
93 // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
94 GetRegConfig()->num_allocatable_double_registers() / 2 - 2,
95#else
96 GetRegConfig()->num_allocatable_double_registers(),
97#endif
98 GetRegConfig()->allocatable_double_codes()) {
99 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100};
101
102
103// Pairs of double registers.
104class Float64RegisterPairs : public Pairs {
105 public:
106 Float64RegisterPairs()
Ben Murdoch61f157c2016-09-16 13:49:30 +0100107 : Pairs(100, GetRegConfig()->num_allocatable_double_registers(),
108 GetRegConfig()->allocatable_double_codes()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109};
110
111
112// Helper for allocating either an GP or FP reg, or the next stack slot.
113struct Allocator {
114 Allocator(int* gp, int gpc, int* fp, int fpc)
115 : gp_count(gpc),
116 gp_offset(0),
117 gp_regs(gp),
118 fp_count(fpc),
119 fp_offset(0),
120 fp_regs(fp),
121 stack_offset(0) {}
122
123 int gp_count;
124 int gp_offset;
125 int* gp_regs;
126
127 int fp_count;
128 int fp_offset;
129 int* fp_regs;
130
131 int stack_offset;
132
133 LinkageLocation Next(MachineType type) {
134 if (IsFloatingPoint(type.representation())) {
135 // Allocate a floating point register/stack location.
136 if (fp_offset < fp_count) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100137 int code = fp_regs[fp_offset++];
138#if V8_TARGET_ARCH_ARM
139 // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
140 if (type.representation() == MachineRepresentation::kFloat32) code *= 2;
141#endif
142 return LinkageLocation::ForRegister(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 } else {
144 int offset = -1 - stack_offset;
145 stack_offset += StackWords(type);
146 return LinkageLocation::ForCallerFrameSlot(offset);
147 }
148 } else {
149 // Allocate a general purpose register/stack location.
150 if (gp_offset < gp_count) {
151 return LinkageLocation::ForRegister(gp_regs[gp_offset++]);
152 } else {
153 int offset = -1 - stack_offset;
154 stack_offset += StackWords(type);
155 return LinkageLocation::ForCallerFrameSlot(offset);
156 }
157 }
158 }
159 int StackWords(MachineType type) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100160 int size = 1 << ElementSizeLog2Of(type.representation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 return size <= kPointerSize ? 1 : size / kPointerSize;
162 }
163 void Reset() {
164 fp_offset = 0;
165 gp_offset = 0;
166 stack_offset = 0;
167 }
168};
169
170
171class RegisterConfig {
172 public:
173 RegisterConfig(Allocator& p, Allocator& r) : params(p), rets(r) {}
174
175 CallDescriptor* Create(Zone* zone, MachineSignature* msig) {
176 rets.Reset();
177 params.Reset();
178
179 LocationSignature::Builder locations(zone, msig->return_count(),
180 msig->parameter_count());
181 // Add return location(s).
182 const int return_count = static_cast<int>(locations.return_count_);
183 for (int i = 0; i < return_count; i++) {
184 locations.AddReturn(rets.Next(msig->GetReturn(i)));
185 }
186
187 // Add register and/or stack parameter(s).
188 const int parameter_count = static_cast<int>(msig->parameter_count());
189 for (int i = 0; i < parameter_count; i++) {
190 locations.AddParam(params.Next(msig->GetParam(i)));
191 }
192
193 const RegList kCalleeSaveRegisters = 0;
194 const RegList kCalleeSaveFPRegisters = 0;
195
196 MachineType target_type = MachineType::AnyTagged();
197 LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
198 int stack_param_count = params.stack_offset;
199 return new (zone) CallDescriptor( // --
200 CallDescriptor::kCallCodeObject, // kind
201 target_type, // target MachineType
202 target_loc, // target location
203 msig, // machine_sig
204 locations.Build(), // location_sig
205 stack_param_count, // stack_parameter_count
206 compiler::Operator::kNoProperties, // properties
207 kCalleeSaveRegisters, // callee-saved registers
208 kCalleeSaveFPRegisters, // callee-saved fp regs
209 CallDescriptor::kUseNativeStack, // flags
210 "c-call");
211 }
212
213 private:
214 Allocator& params;
215 Allocator& rets;
216};
217
218const int kMaxParamCount = 64;
219
220MachineType kIntTypes[kMaxParamCount + 1] = {
221 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
222 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
223 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
224 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
225 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
226 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
227 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
228 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
229 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
230 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
231 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
232 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
233 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
234 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
235 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
236 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
237 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
238 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
239 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
240 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
241 MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
242 MachineType::Int32(), MachineType::Int32()};
243
244
245// For making uniform int32 signatures shorter.
246class Int32Signature : public MachineSignature {
247 public:
248 explicit Int32Signature(int param_count)
249 : MachineSignature(1, param_count, kIntTypes) {
250 CHECK(param_count <= kMaxParamCount);
251 }
252};
253
254
255Handle<Code> CompileGraph(const char* name, CallDescriptor* desc, Graph* graph,
256 Schedule* schedule = nullptr) {
257 Isolate* isolate = CcTest::InitIsolateOnce();
Ben Murdochc5610432016-08-08 18:44:38 +0100258 CompilationInfo info(ArrayVector("testing"), isolate, graph->zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 Handle<Code> code =
260 Pipeline::GenerateCodeForTesting(&info, desc, graph, schedule);
261 CHECK(!code.is_null());
262#ifdef ENABLE_DISASSEMBLER
263 if (FLAG_print_opt_code) {
264 OFStream os(stdout);
265 code->Disassemble(name, os);
266 }
267#endif
268 return code;
269}
270
271
272Handle<Code> WrapWithCFunction(Handle<Code> inner, CallDescriptor* desc) {
Ben Murdochda12d292016-06-02 14:46:10 +0100273 Zone zone(inner->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 MachineSignature* msig =
275 const_cast<MachineSignature*>(desc->GetMachineSignature());
276 int param_count = static_cast<int>(msig->parameter_count());
277 GraphAndBuilders caller(&zone);
278 {
279 GraphAndBuilders& b = caller;
280 Node* start = b.graph()->NewNode(b.common()->Start(param_count + 3));
281 b.graph()->SetStart(start);
282 Node* target = b.graph()->NewNode(b.common()->HeapConstant(inner));
283
284 // Add arguments to the call.
285 Node** args = zone.NewArray<Node*>(param_count + 3);
286 int index = 0;
287 args[index++] = target;
288 for (int i = 0; i < param_count; i++) {
289 args[index] = b.graph()->NewNode(b.common()->Parameter(i), start);
290 index++;
291 }
292 args[index++] = start; // effect.
293 args[index++] = start; // control.
294
295 // Build the call and return nodes.
296 Node* call =
297 b.graph()->NewNode(b.common()->Call(desc), param_count + 3, args);
298 Node* ret = b.graph()->NewNode(b.common()->Return(), call, call, start);
299 b.graph()->SetEnd(ret);
300 }
301
302 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, msig);
303
304 return CompileGraph("wrapper", cdesc, caller.graph());
305}
306
307
308template <typename CType>
309class ArgsBuffer {
310 public:
311 static const int kMaxParamCount = 64;
312
313 explicit ArgsBuffer(int count, int seed = 1) : count_(count), seed_(seed) {
314 // initialize the buffer with "seed 0"
315 seed_ = 0;
316 Mutate();
317 seed_ = seed;
318 }
319
320 class Sig : public MachineSignature {
321 public:
322 explicit Sig(int param_count)
323 : MachineSignature(1, param_count, MachTypes()) {
324 CHECK(param_count <= kMaxParamCount);
325 }
326 };
327
328 static MachineType* MachTypes() {
329 MachineType t = MachineTypeForC<CType>();
330 static MachineType kTypes[kMaxParamCount + 1] = {
331 t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
332 t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
333 t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t};
334 return kTypes;
335 }
336
337 Node* MakeConstant(RawMachineAssembler& raw, int32_t value) {
338 return raw.Int32Constant(value);
339 }
340
341 Node* MakeConstant(RawMachineAssembler& raw, int64_t value) {
342 return raw.Int64Constant(value);
343 }
344
345 Node* MakeConstant(RawMachineAssembler& raw, float32 value) {
346 return raw.Float32Constant(value);
347 }
348
349 Node* MakeConstant(RawMachineAssembler& raw, float64 value) {
350 return raw.Float64Constant(value);
351 }
352
353 Node* LoadInput(RawMachineAssembler& raw, Node* base, int index) {
354 Node* offset = raw.Int32Constant(index * sizeof(CType));
355 return raw.Load(MachineTypeForC<CType>(), base, offset);
356 }
357
358 Node* StoreOutput(RawMachineAssembler& raw, Node* value) {
359 Node* base = raw.PointerConstant(&output);
360 Node* offset = raw.Int32Constant(0);
361 return raw.Store(MachineTypeForC<CType>().representation(), base, offset,
362 value, kNoWriteBarrier);
363 }
364
365 // Computes the next set of inputs by updating the {input} array.
366 void Mutate();
367
368 void Reset() { memset(input, 0, sizeof(input)); }
369
370 int count_;
371 int seed_;
372 CType input[kMaxParamCount];
373 CType output;
374};
375
376
377template <>
378void ArgsBuffer<int32_t>::Mutate() {
379 uint32_t base = 1111111111u * seed_;
380 for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
381 input[j] = static_cast<int32_t>(256 + base + j + seed_ * 13);
382 }
383 output = -1;
384 seed_++;
385}
386
387
388template <>
389void ArgsBuffer<int64_t>::Mutate() {
390 uint64_t base = 11111111111111111ull * seed_;
391 for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
392 input[j] = static_cast<int64_t>(256 + base + j + seed_ * 13);
393 }
394 output = -1;
395 seed_++;
396}
397
398
399template <>
400void ArgsBuffer<float32>::Mutate() {
401 float64 base = -33.25 * seed_;
402 for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
403 input[j] = 256 + base + j + seed_ * 13;
404 }
405 output = std::numeric_limits<float32>::quiet_NaN();
406 seed_++;
407}
408
409
410template <>
411void ArgsBuffer<float64>::Mutate() {
412 float64 base = -111.25 * seed_;
413 for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
414 input[j] = 256 + base + j + seed_ * 13;
415 }
416 output = std::numeric_limits<float64>::quiet_NaN();
417 seed_++;
418}
419
420
421int ParamCount(CallDescriptor* desc) {
422 return static_cast<int>(desc->GetMachineSignature()->parameter_count());
423}
424
425
426template <typename CType>
427class Computer {
428 public:
429 static void Run(CallDescriptor* desc,
430 void (*build)(CallDescriptor*, RawMachineAssembler&),
431 CType (*compute)(CallDescriptor*, CType* inputs),
432 int seed = 1) {
433 int num_params = ParamCount(desc);
434 CHECK_LE(num_params, kMaxParamCount);
435 Isolate* isolate = CcTest::InitIsolateOnce();
436 HandleScope scope(isolate);
437 Handle<Code> inner = Handle<Code>::null();
438 {
439 // Build the graph for the computation.
Ben Murdochda12d292016-06-02 14:46:10 +0100440 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 Graph graph(&zone);
442 RawMachineAssembler raw(isolate, &graph, desc);
443 build(desc, raw);
444 inner = CompileGraph("Compute", desc, &graph, raw.Export());
445 }
446
447 CSignature0<int32_t> csig;
448 ArgsBuffer<CType> io(num_params, seed);
449
450 {
451 // constant mode.
452 Handle<Code> wrapper = Handle<Code>::null();
453 {
454 // Wrap the above code with a callable function that passes constants.
Ben Murdochda12d292016-06-02 14:46:10 +0100455 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 Graph graph(&zone);
457 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
458 RawMachineAssembler raw(isolate, &graph, cdesc);
459 Node* target = raw.HeapConstant(inner);
460 Node** args = zone.NewArray<Node*>(num_params);
461 for (int i = 0; i < num_params; i++) {
462 args[i] = io.MakeConstant(raw, io.input[i]);
463 }
464
465 Node* call = raw.CallN(desc, target, args);
466 Node* store = io.StoreOutput(raw, call);
467 USE(store);
468 raw.Return(raw.Int32Constant(seed));
469 wrapper =
470 CompileGraph("Compute-wrapper-const", cdesc, &graph, raw.Export());
471 }
472
473 CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
474
475 // Run the code, checking it against the reference.
476 CType expected = compute(desc, io.input);
477 int32_t check_seed = runnable.Call();
478 CHECK_EQ(seed, check_seed);
479 CHECK_EQ(expected, io.output);
480 }
481
482 {
483 // buffer mode.
484 Handle<Code> wrapper = Handle<Code>::null();
485 {
486 // Wrap the above code with a callable function that loads from {input}.
Ben Murdochda12d292016-06-02 14:46:10 +0100487 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 Graph graph(&zone);
489 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
490 RawMachineAssembler raw(isolate, &graph, cdesc);
491 Node* base = raw.PointerConstant(io.input);
492 Node* target = raw.HeapConstant(inner);
493 Node** args = zone.NewArray<Node*>(kMaxParamCount);
494 for (int i = 0; i < num_params; i++) {
495 args[i] = io.LoadInput(raw, base, i);
496 }
497
498 Node* call = raw.CallN(desc, target, args);
499 Node* store = io.StoreOutput(raw, call);
500 USE(store);
501 raw.Return(raw.Int32Constant(seed));
502 wrapper = CompileGraph("Compute-wrapper", cdesc, &graph, raw.Export());
503 }
504
505 CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
506
507 // Run the code, checking it against the reference.
508 for (int i = 0; i < 5; i++) {
509 CType expected = compute(desc, io.input);
510 int32_t check_seed = runnable.Call();
511 CHECK_EQ(seed, check_seed);
512 CHECK_EQ(expected, io.output);
513 io.Mutate();
514 }
515 }
516 }
517};
518
519} // namespace
520
521
522static void TestInt32Sub(CallDescriptor* desc) {
523 Isolate* isolate = CcTest::InitIsolateOnce();
524 HandleScope scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +0100525 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 GraphAndBuilders inner(&zone);
527 {
528 // Build the add function.
529 GraphAndBuilders& b = inner;
530 Node* start = b.graph()->NewNode(b.common()->Start(5));
531 b.graph()->SetStart(start);
532 Node* p0 = b.graph()->NewNode(b.common()->Parameter(0), start);
533 Node* p1 = b.graph()->NewNode(b.common()->Parameter(1), start);
534 Node* add = b.graph()->NewNode(b.machine()->Int32Sub(), p0, p1);
535 Node* ret = b.graph()->NewNode(b.common()->Return(), add, start, start);
536 b.graph()->SetEnd(ret);
537 }
538
539 Handle<Code> inner_code = CompileGraph("Int32Sub", desc, inner.graph());
540 Handle<Code> wrapper = WrapWithCFunction(inner_code, desc);
541 MachineSignature* msig =
542 const_cast<MachineSignature*>(desc->GetMachineSignature());
543 CodeRunner<int32_t> runnable(isolate, wrapper,
544 CSignature::FromMachine(&zone, msig));
545
546 FOR_INT32_INPUTS(i) {
547 FOR_INT32_INPUTS(j) {
548 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) -
549 static_cast<uint32_t>(*j));
550 int32_t result = runnable.Call(*i, *j);
551 CHECK_EQ(expected, result);
552 }
553 }
554}
555
556
557static void CopyTwentyInt32(CallDescriptor* desc) {
558 const int kNumParams = 20;
559 int32_t input[kNumParams];
560 int32_t output[kNumParams];
561 Isolate* isolate = CcTest::InitIsolateOnce();
562 HandleScope scope(isolate);
563 Handle<Code> inner = Handle<Code>::null();
564 {
565 // Writes all parameters into the output buffer.
Ben Murdochda12d292016-06-02 14:46:10 +0100566 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 Graph graph(&zone);
568 RawMachineAssembler raw(isolate, &graph, desc);
569 Node* base = raw.PointerConstant(output);
570 for (int i = 0; i < kNumParams; i++) {
571 Node* offset = raw.Int32Constant(i * sizeof(int32_t));
572 raw.Store(MachineRepresentation::kWord32, base, offset, raw.Parameter(i),
573 kNoWriteBarrier);
574 }
575 raw.Return(raw.Int32Constant(42));
576 inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
577 }
578
579 CSignature0<int32_t> csig;
580 Handle<Code> wrapper = Handle<Code>::null();
581 {
582 // Loads parameters from the input buffer and calls the above code.
Ben Murdochda12d292016-06-02 14:46:10 +0100583 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 Graph graph(&zone);
585 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
586 RawMachineAssembler raw(isolate, &graph, cdesc);
587 Node* base = raw.PointerConstant(input);
588 Node* target = raw.HeapConstant(inner);
589 Node** args = zone.NewArray<Node*>(kNumParams);
590 for (int i = 0; i < kNumParams; i++) {
591 Node* offset = raw.Int32Constant(i * sizeof(int32_t));
592 args[i] = raw.Load(MachineType::Int32(), base, offset);
593 }
594
595 Node* call = raw.CallN(desc, target, args);
596 raw.Return(call);
597 wrapper =
598 CompileGraph("CopyTwentyInt32-wrapper", cdesc, &graph, raw.Export());
599 }
600
601 CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
602
603 // Run the code, checking it correctly implements the memcpy.
604 for (int i = 0; i < 5; i++) {
605 uint32_t base = 1111111111u * i;
606 for (int j = 0; j < kNumParams; j++) {
607 input[j] = static_cast<int32_t>(base + 13 * j);
608 }
609
610 memset(output, 0, sizeof(output));
611 CHECK_EQ(42, runnable.Call());
612
613 for (int j = 0; j < kNumParams; j++) {
614 CHECK_EQ(input[j], output[j]);
615 }
616 }
617}
618
619
620static void Test_RunInt32SubWithRet(int retreg) {
621 Int32Signature sig(2);
Ben Murdochda12d292016-06-02 14:46:10 +0100622 base::AccountingAllocator allocator;
623 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 RegisterPairs pairs;
625 while (pairs.More()) {
626 int parray[2];
627 int rarray[] = {retreg};
628 pairs.Next(&parray[0], &parray[1], false);
629 Allocator params(parray, 2, nullptr, 0);
630 Allocator rets(rarray, 1, nullptr, 0);
631 RegisterConfig config(params, rets);
632 CallDescriptor* desc = config.Create(&zone, &sig);
633 TestInt32Sub(desc);
634 }
635}
636
637
638// Separate tests for parallelization.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100639#define TEST_INT32_SUB_WITH_RET(x) \
640 TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \
641 if (x < Register::kNumRegisters && \
642 GetRegConfig()->IsAllocatableGeneralCode(x)) { \
643 Test_RunInt32SubWithRet(x); \
644 } \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 }
646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647TEST_INT32_SUB_WITH_RET(0)
648TEST_INT32_SUB_WITH_RET(1)
649TEST_INT32_SUB_WITH_RET(2)
650TEST_INT32_SUB_WITH_RET(3)
651TEST_INT32_SUB_WITH_RET(4)
652TEST_INT32_SUB_WITH_RET(5)
653TEST_INT32_SUB_WITH_RET(6)
654TEST_INT32_SUB_WITH_RET(7)
655TEST_INT32_SUB_WITH_RET(8)
656TEST_INT32_SUB_WITH_RET(9)
657TEST_INT32_SUB_WITH_RET(10)
658TEST_INT32_SUB_WITH_RET(11)
659TEST_INT32_SUB_WITH_RET(12)
660TEST_INT32_SUB_WITH_RET(13)
661TEST_INT32_SUB_WITH_RET(14)
662TEST_INT32_SUB_WITH_RET(15)
663TEST_INT32_SUB_WITH_RET(16)
664TEST_INT32_SUB_WITH_RET(17)
665TEST_INT32_SUB_WITH_RET(18)
666TEST_INT32_SUB_WITH_RET(19)
667
668
669TEST(Run_Int32Sub_all_allocatable_single) {
670 Int32Signature sig(2);
671 RegisterPairs pairs;
672 while (pairs.More()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100673 base::AccountingAllocator allocator;
674 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 int parray[1];
676 int rarray[1];
677 pairs.Next(&rarray[0], &parray[0], true);
678 Allocator params(parray, 1, nullptr, 0);
679 Allocator rets(rarray, 1, nullptr, 0);
680 RegisterConfig config(params, rets);
681 CallDescriptor* desc = config.Create(&zone, &sig);
682 TestInt32Sub(desc);
683 }
684}
685
686
687TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
688 Int32Signature sig(20);
689 RegisterPairs pairs;
690 while (pairs.More()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100691 base::AccountingAllocator allocator;
692 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 int parray[2];
Ben Murdoch61f157c2016-09-16 13:49:30 +0100694 int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 pairs.Next(&parray[0], &parray[1], false);
696 Allocator params(parray, 2, nullptr, 0);
697 Allocator rets(rarray, 1, nullptr, 0);
698 RegisterConfig config(params, rets);
699 CallDescriptor* desc = config.Create(&zone, &sig);
700 CopyTwentyInt32(desc);
701 }
702}
703
704
705template <typename CType>
706static void Run_Computation(
707 CallDescriptor* desc, void (*build)(CallDescriptor*, RawMachineAssembler&),
708 CType (*compute)(CallDescriptor*, CType* inputs), int seed = 1) {
709 Computer<CType>::Run(desc, build, compute, seed);
710}
711
712
713static uint32_t coeff[] = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
714 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
715 79, 83, 89, 97, 101, 103, 107, 109, 113};
716
717
718static void Build_Int32_WeightedSum(CallDescriptor* desc,
719 RawMachineAssembler& raw) {
720 Node* result = raw.Int32Constant(0);
721 for (int i = 0; i < ParamCount(desc); i++) {
722 Node* term = raw.Int32Mul(raw.Parameter(i), raw.Int32Constant(coeff[i]));
723 result = raw.Int32Add(result, term);
724 }
725 raw.Return(result);
726}
727
728
729static int32_t Compute_Int32_WeightedSum(CallDescriptor* desc, int32_t* input) {
730 uint32_t result = 0;
731 for (int i = 0; i < ParamCount(desc); i++) {
732 result += static_cast<uint32_t>(input[i]) * coeff[i];
733 }
734 return static_cast<int32_t>(result);
735}
736
737
738static void Test_Int32_WeightedSum_of_size(int count) {
739 Int32Signature sig(count);
740 for (int p0 = 0; p0 < Register::kNumRegisters; p0++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100741 if (GetRegConfig()->IsAllocatableGeneralCode(p0)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100742 base::AccountingAllocator allocator;
743 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000744
745 int parray[] = {p0};
Ben Murdoch61f157c2016-09-16 13:49:30 +0100746 int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 Allocator params(parray, 1, nullptr, 0);
748 Allocator rets(rarray, 1, nullptr, 0);
749 RegisterConfig config(params, rets);
750 CallDescriptor* desc = config.Create(&zone, &sig);
751 Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
752 Compute_Int32_WeightedSum, 257 + count);
753 }
754 }
755}
756
757
758// Separate tests for parallelization.
759#define TEST_INT32_WEIGHTEDSUM(x) \
760 TEST(Run_Int32_WeightedSum_##x) { Test_Int32_WeightedSum_of_size(x); }
761
762
763TEST_INT32_WEIGHTEDSUM(1)
764TEST_INT32_WEIGHTEDSUM(2)
765TEST_INT32_WEIGHTEDSUM(3)
766TEST_INT32_WEIGHTEDSUM(4)
767TEST_INT32_WEIGHTEDSUM(5)
768TEST_INT32_WEIGHTEDSUM(7)
769TEST_INT32_WEIGHTEDSUM(9)
770TEST_INT32_WEIGHTEDSUM(11)
771TEST_INT32_WEIGHTEDSUM(17)
772TEST_INT32_WEIGHTEDSUM(19)
773
774
775template <int which>
776static void Build_Select(CallDescriptor* desc, RawMachineAssembler& raw) {
777 raw.Return(raw.Parameter(which));
778}
779
780
781template <typename CType, int which>
782static CType Compute_Select(CallDescriptor* desc, CType* inputs) {
783 return inputs[which];
784}
785
786
787template <typename CType, int which>
788static void RunSelect(CallDescriptor* desc) {
789 int count = ParamCount(desc);
790 if (count <= which) return;
791 Run_Computation<CType>(desc, Build_Select<which>,
792 Compute_Select<CType, which>,
793 1044 + which + 3 * sizeof(CType));
794}
795
796
797template <int which>
798void Test_Int32_Select() {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100799 int parray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
800 int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000801 Allocator params(parray, 1, nullptr, 0);
802 Allocator rets(rarray, 1, nullptr, 0);
803 RegisterConfig config(params, rets);
804
Ben Murdochda12d292016-06-02 14:46:10 +0100805 base::AccountingAllocator allocator;
806 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807
808 for (int i = which + 1; i <= 64; i++) {
809 Int32Signature sig(i);
810 CallDescriptor* desc = config.Create(&zone, &sig);
811 RunSelect<int32_t, which>(desc);
812 }
813}
814
815
816// Separate tests for parallelization.
817#define TEST_INT32_SELECT(x) \
818 TEST(Run_Int32_Select_##x) { Test_Int32_Select<x>(); }
819
820
821TEST_INT32_SELECT(0)
822TEST_INT32_SELECT(1)
823TEST_INT32_SELECT(2)
824TEST_INT32_SELECT(3)
825TEST_INT32_SELECT(4)
826TEST_INT32_SELECT(5)
827TEST_INT32_SELECT(6)
828TEST_INT32_SELECT(11)
829TEST_INT32_SELECT(15)
830TEST_INT32_SELECT(19)
831TEST_INT32_SELECT(45)
832TEST_INT32_SELECT(62)
833TEST_INT32_SELECT(63)
834
835
836TEST(Int64Select_registers) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100837 if (GetRegConfig()->num_allocatable_general_registers() < 2) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms
839
Ben Murdoch61f157c2016-09-16 13:49:30 +0100840 int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 ArgsBuffer<int64_t>::Sig sig(2);
842
843 RegisterPairs pairs;
Ben Murdochda12d292016-06-02 14:46:10 +0100844 base::AccountingAllocator allocator;
845 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 while (pairs.More()) {
847 int parray[2];
848 pairs.Next(&parray[0], &parray[1], false);
849 Allocator params(parray, 2, nullptr, 0);
850 Allocator rets(rarray, 1, nullptr, 0);
851 RegisterConfig config(params, rets);
852
853 CallDescriptor* desc = config.Create(&zone, &sig);
854 RunSelect<int64_t, 0>(desc);
855 RunSelect<int64_t, 1>(desc);
856 }
857}
858
859
860TEST(Float32Select_registers) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100861 if (GetRegConfig()->num_allocatable_double_registers() < 2) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 return;
863 }
864
Ben Murdoch61f157c2016-09-16 13:49:30 +0100865 int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 ArgsBuffer<float32>::Sig sig(2);
867
868 Float32RegisterPairs pairs;
Ben Murdochda12d292016-06-02 14:46:10 +0100869 base::AccountingAllocator allocator;
870 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871 while (pairs.More()) {
872 int parray[2];
873 pairs.Next(&parray[0], &parray[1], false);
874 Allocator params(nullptr, 0, parray, 2);
875 Allocator rets(nullptr, 0, rarray, 1);
876 RegisterConfig config(params, rets);
877
878 CallDescriptor* desc = config.Create(&zone, &sig);
879 RunSelect<float32, 0>(desc);
880 RunSelect<float32, 1>(desc);
881 }
882}
883
884
885TEST(Float64Select_registers) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100886 if (GetRegConfig()->num_allocatable_double_registers() < 2) return;
887 if (GetRegConfig()->num_allocatable_general_registers() < 2) return;
888 int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 ArgsBuffer<float64>::Sig sig(2);
890
891 Float64RegisterPairs pairs;
Ben Murdochda12d292016-06-02 14:46:10 +0100892 base::AccountingAllocator allocator;
893 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 while (pairs.More()) {
895 int parray[2];
896 pairs.Next(&parray[0], &parray[1], false);
897 Allocator params(nullptr, 0, parray, 2);
898 Allocator rets(nullptr, 0, rarray, 1);
899 RegisterConfig config(params, rets);
900
901 CallDescriptor* desc = config.Create(&zone, &sig);
902 RunSelect<float64, 0>(desc);
903 RunSelect<float64, 1>(desc);
904 }
905}
906
907
908TEST(Float32Select_stack_params_return_reg) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100909 int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 Allocator params(nullptr, 0, nullptr, 0);
911 Allocator rets(nullptr, 0, rarray, 1);
912 RegisterConfig config(params, rets);
913
Ben Murdochda12d292016-06-02 14:46:10 +0100914 base::AccountingAllocator allocator;
915 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 for (int count = 1; count < 6; count++) {
917 ArgsBuffer<float32>::Sig sig(count);
918 CallDescriptor* desc = config.Create(&zone, &sig);
919 RunSelect<float32, 0>(desc);
920 RunSelect<float32, 1>(desc);
921 RunSelect<float32, 2>(desc);
922 RunSelect<float32, 3>(desc);
923 RunSelect<float32, 4>(desc);
924 RunSelect<float32, 5>(desc);
925 }
926}
927
928
929TEST(Float64Select_stack_params_return_reg) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100930 int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 Allocator params(nullptr, 0, nullptr, 0);
932 Allocator rets(nullptr, 0, rarray, 1);
933 RegisterConfig config(params, rets);
934
Ben Murdochda12d292016-06-02 14:46:10 +0100935 base::AccountingAllocator allocator;
936 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 for (int count = 1; count < 6; count++) {
938 ArgsBuffer<float64>::Sig sig(count);
939 CallDescriptor* desc = config.Create(&zone, &sig);
940 RunSelect<float64, 0>(desc);
941 RunSelect<float64, 1>(desc);
942 RunSelect<float64, 2>(desc);
943 RunSelect<float64, 3>(desc);
944 RunSelect<float64, 4>(desc);
945 RunSelect<float64, 5>(desc);
946 }
947}
948
949
950template <typename CType, int which>
951static void Build_Select_With_Call(CallDescriptor* desc,
952 RawMachineAssembler& raw) {
953 Handle<Code> inner = Handle<Code>::null();
954 int num_params = ParamCount(desc);
955 CHECK_LE(num_params, kMaxParamCount);
956 {
957 Isolate* isolate = CcTest::InitIsolateOnce();
958 // Build the actual select.
Ben Murdochda12d292016-06-02 14:46:10 +0100959 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 Graph graph(&zone);
961 RawMachineAssembler raw(isolate, &graph, desc);
962 raw.Return(raw.Parameter(which));
963 inner = CompileGraph("Select-indirection", desc, &graph, raw.Export());
964 CHECK(!inner.is_null());
965 CHECK(inner->IsCode());
966 }
967
968 {
969 // Build a call to the function that does the select.
970 Node* target = raw.HeapConstant(inner);
971 Node** args = raw.zone()->NewArray<Node*>(num_params);
972 for (int i = 0; i < num_params; i++) {
973 args[i] = raw.Parameter(i);
974 }
975
976 Node* call = raw.CallN(desc, target, args);
977 raw.Return(call);
978 }
979}
980
981
982TEST(Float64StackParamsToStackParams) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100983 int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000984 Allocator params(nullptr, 0, nullptr, 0);
985 Allocator rets(nullptr, 0, rarray, 1);
986
Ben Murdochda12d292016-06-02 14:46:10 +0100987 base::AccountingAllocator allocator;
988 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 ArgsBuffer<float64>::Sig sig(2);
990 RegisterConfig config(params, rets);
991 CallDescriptor* desc = config.Create(&zone, &sig);
992
993 Run_Computation<float64>(desc, Build_Select_With_Call<float64, 0>,
994 Compute_Select<float64, 0>, 1098);
995
996 Run_Computation<float64>(desc, Build_Select_With_Call<float64, 1>,
997 Compute_Select<float64, 1>, 1099);
998}
999
1000
1001void MixedParamTest(int start) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001002 if (GetRegConfig()->num_double_registers() < 2) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003
1004// TODO(titzer): mix in 64-bit types on all platforms when supported.
1005#if V8_TARGET_ARCH_32_BIT
1006 static MachineType types[] = {
1007 MachineType::Int32(), MachineType::Float32(), MachineType::Float64(),
1008 MachineType::Int32(), MachineType::Float64(), MachineType::Float32(),
1009 MachineType::Float32(), MachineType::Float64(), MachineType::Int32(),
1010 MachineType::Float32(), MachineType::Int32(), MachineType::Float64(),
1011 MachineType::Float64(), MachineType::Float32(), MachineType::Int32(),
1012 MachineType::Float64(), MachineType::Int32(), MachineType::Float32()};
1013#else
1014 static MachineType types[] = {
1015 MachineType::Int32(), MachineType::Int64(), MachineType::Float32(),
1016 MachineType::Float64(), MachineType::Int32(), MachineType::Float64(),
1017 MachineType::Float32(), MachineType::Int64(), MachineType::Int64(),
1018 MachineType::Float32(), MachineType::Float32(), MachineType::Int32(),
1019 MachineType::Float64(), MachineType::Float64(), MachineType::Int64(),
1020 MachineType::Int32(), MachineType::Float64(), MachineType::Int32(),
1021 MachineType::Float32()};
1022#endif
1023
1024 Isolate* isolate = CcTest::InitIsolateOnce();
1025
1026 // Build machine signature
1027 MachineType* params = &types[start];
1028 const int num_params = static_cast<int>(arraysize(types) - start);
1029
1030 // Build call descriptor
Ben Murdoch61f157c2016-09-16 13:49:30 +01001031 int parray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0),
1032 GetRegConfig()->GetAllocatableGeneralCode(1)};
1033 int rarray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
1034 int parray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0),
1035 GetRegConfig()->GetAllocatableDoubleCode(1)};
1036 int rarray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 Allocator palloc(parray_gp, 2, parray_fp, 2);
1038 Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
1039 RegisterConfig config(palloc, ralloc);
1040
1041 for (int which = 0; which < num_params; which++) {
Ben Murdochda12d292016-06-02 14:46:10 +01001042 base::AccountingAllocator allocator;
1043 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001044 HandleScope scope(isolate);
1045 MachineSignature::Builder builder(&zone, 1, num_params);
1046 builder.AddReturn(params[which]);
1047 for (int j = 0; j < num_params; j++) builder.AddParam(params[j]);
1048 MachineSignature* sig = builder.Build();
1049 CallDescriptor* desc = config.Create(&zone, sig);
1050
1051 Handle<Code> select;
1052 {
1053 // build the select.
Ben Murdochda12d292016-06-02 14:46:10 +01001054 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 Graph graph(&zone);
1056 RawMachineAssembler raw(isolate, &graph, desc);
1057 raw.Return(raw.Parameter(which));
1058 select = CompileGraph("Compute", desc, &graph, raw.Export());
1059 }
1060
1061 {
1062 // call the select.
1063 Handle<Code> wrapper = Handle<Code>::null();
1064 int32_t expected_ret;
1065 char bytes[kDoubleSize];
1066 V8_ALIGNED(8) char output[kDoubleSize];
1067 int expected_size = 0;
1068 CSignature0<int32_t> csig;
1069 {
1070 // Wrap the select code with a callable function that passes constants.
Ben Murdochda12d292016-06-02 14:46:10 +01001071 Zone zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 Graph graph(&zone);
1073 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
1074 RawMachineAssembler raw(isolate, &graph, cdesc);
1075 Node* target = raw.HeapConstant(select);
1076 Node** args = zone.NewArray<Node*>(num_params);
1077 int64_t constant = 0x0102030405060708;
1078 for (int i = 0; i < num_params; i++) {
1079 MachineType param_type = sig->GetParam(i);
1080 Node* konst = nullptr;
1081 if (param_type == MachineType::Int32()) {
1082 int32_t value[] = {static_cast<int32_t>(constant)};
1083 konst = raw.Int32Constant(value[0]);
1084 if (i == which) memcpy(bytes, value, expected_size = 4);
1085 }
1086 if (param_type == MachineType::Int64()) {
1087 int64_t value[] = {static_cast<int64_t>(constant)};
1088 konst = raw.Int64Constant(value[0]);
1089 if (i == which) memcpy(bytes, value, expected_size = 8);
1090 }
1091 if (param_type == MachineType::Float32()) {
1092 float32 value[] = {static_cast<float32>(constant)};
1093 konst = raw.Float32Constant(value[0]);
1094 if (i == which) memcpy(bytes, value, expected_size = 4);
1095 }
1096 if (param_type == MachineType::Float64()) {
1097 float64 value[] = {static_cast<float64>(constant)};
1098 konst = raw.Float64Constant(value[0]);
1099 if (i == which) memcpy(bytes, value, expected_size = 8);
1100 }
1101 CHECK_NOT_NULL(konst);
1102
1103 args[i] = konst;
1104 constant += 0x1010101010101010;
1105 }
1106
1107 Node* call = raw.CallN(desc, target, args);
1108 Node* store =
1109 raw.StoreToPointer(output, sig->GetReturn().representation(), call);
1110 USE(store);
1111 expected_ret = static_cast<int32_t>(constant);
1112 raw.Return(raw.Int32Constant(expected_ret));
1113 wrapper = CompileGraph("Select-mixed-wrapper-const", cdesc, &graph,
1114 raw.Export());
1115 }
1116
1117 CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
1118 CHECK_EQ(expected_ret, runnable.Call());
1119 for (int i = 0; i < expected_size; i++) {
1120 CHECK_EQ(static_cast<int>(bytes[i]), static_cast<int>(output[i]));
1121 }
1122 }
1123 }
1124}
1125
1126
1127TEST(MixedParams_0) { MixedParamTest(0); }
1128TEST(MixedParams_1) { MixedParamTest(1); }
1129TEST(MixedParams_2) { MixedParamTest(2); }
1130TEST(MixedParams_3) { MixedParamTest(3); }
1131
Ben Murdoch097c5b22016-05-18 11:27:45 +01001132template <typename T>
1133void TestStackSlot(MachineType slot_type, T expected) {
1134 // Test: Generate with a function f which reserves a stack slot, call an inner
1135 // function g from f which writes into the stack slot of f.
1136
Ben Murdoch61f157c2016-09-16 13:49:30 +01001137 if (GetRegConfig()->num_allocatable_double_registers() < 2) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001138
1139 Isolate* isolate = CcTest::InitIsolateOnce();
1140
1141 // Lots of code to generate the build descriptor for the inner function.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001142 int parray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0),
1143 GetRegConfig()->GetAllocatableGeneralCode(1)};
1144 int rarray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
1145 int parray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0),
1146 GetRegConfig()->GetAllocatableDoubleCode(1)};
1147 int rarray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
Ben Murdoch097c5b22016-05-18 11:27:45 +01001148 Allocator palloc(parray_gp, 2, parray_fp, 2);
1149 Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
1150 RegisterConfig config(palloc, ralloc);
1151
Ben Murdochda12d292016-06-02 14:46:10 +01001152 Zone zone(isolate->allocator());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001153 HandleScope scope(isolate);
1154 MachineSignature::Builder builder(&zone, 1, 12);
1155 builder.AddReturn(MachineType::Int32());
1156 for (int i = 0; i < 10; i++) {
1157 builder.AddParam(MachineType::Int32());
1158 }
1159 builder.AddParam(slot_type);
1160 builder.AddParam(MachineType::Pointer());
1161 MachineSignature* sig = builder.Build();
1162 CallDescriptor* desc = config.Create(&zone, sig);
1163
1164 // Create inner function g. g has lots of parameters so that they are passed
1165 // over the stack.
1166 Handle<Code> inner;
1167 Graph graph(&zone);
1168 RawMachineAssembler g(isolate, &graph, desc);
1169
1170 g.Store(slot_type.representation(), g.Parameter(11), g.Parameter(10),
1171 WriteBarrierKind::kNoWriteBarrier);
1172 g.Return(g.Parameter(9));
1173 inner = CompileGraph("Compute", desc, &graph, g.Export());
1174
1175 // Create function f with a stack slot which calls the inner function g.
1176 BufferedRawMachineAssemblerTester<T> f(slot_type);
1177 Node* target = f.HeapConstant(inner);
1178 Node* stack_slot = f.StackSlot(slot_type.representation());
1179 Node* args[12];
1180 for (int i = 0; i < 10; i++) {
1181 args[i] = f.Int32Constant(i);
1182 }
1183 args[10] = f.Parameter(0);
1184 args[11] = stack_slot;
1185
1186 f.CallN(desc, target, args);
1187 f.Return(f.Load(slot_type, stack_slot, f.IntPtrConstant(0)));
1188
1189 CHECK_EQ(expected, f.Call(expected));
1190}
1191
1192TEST(RunStackSlotInt32) {
1193 int32_t magic = 0x12345678;
1194 TestStackSlot(MachineType::Int32(), magic);
1195}
1196
1197#if !V8_TARGET_ARCH_32_BIT
1198TEST(RunStackSlotInt64) {
1199 int64_t magic = 0x123456789abcdef0;
1200 TestStackSlot(MachineType::Int64(), magic);
1201}
1202#endif
1203
1204TEST(RunStackSlotFloat32) {
1205 float magic = 1234.125f;
1206 TestStackSlot(MachineType::Float32(), magic);
1207}
1208
1209TEST(RunStackSlotFloat64) {
1210 double magic = 3456.375;
1211 TestStackSlot(MachineType::Float64(), magic);
1212}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213} // namespace compiler
1214} // namespace internal
1215} // namespace v8