c885bdde1d
Change-Id: Ica33af158cca53c8e951e4b2582de83660e8a60d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121851 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
235 lines
7.8 KiB
C++
235 lines
7.8 KiB
C++
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/compiler/backend/locations_helpers.h"
|
|
#include "vm/dart_api_impl.h"
|
|
#include "vm/dart_entry.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
#define Reg(index) (static_cast<Register>(index))
|
|
#define Fpu(index) (static_cast<FpuRegister>(index))
|
|
|
|
#define ReqReg Location::RequiresRegister()
|
|
#define ReqFpu Location::RequiresFpuRegister()
|
|
#define RegLoc(index) Location::RegisterLocation(Reg(index))
|
|
#define FpuLoc(index) Location::FpuRegisterLocation(Fpu(index))
|
|
|
|
typedef ZoneGrowableArray<Location> LocationArray;
|
|
|
|
static LocationArray* MakeLocationArray() {
|
|
LocationArray* arr = new LocationArray();
|
|
return arr;
|
|
}
|
|
|
|
static LocationArray* MakeLocationArray(Location loc0) {
|
|
LocationArray* arr = new LocationArray();
|
|
arr->Add(loc0);
|
|
return arr;
|
|
}
|
|
|
|
static LocationArray* MakeLocationArray(Location loc0, Location loc1) {
|
|
LocationArray* arr = new LocationArray();
|
|
arr->Add(loc0);
|
|
arr->Add(loc1);
|
|
return arr;
|
|
}
|
|
|
|
static void ValidateSummary(LocationSummary* locs,
|
|
Location expected_output,
|
|
const LocationArray* expected_inputs,
|
|
const LocationArray* expected_temps) {
|
|
EXPECT(locs->out(0).Equals(expected_output));
|
|
EXPECT_EQ(expected_inputs->length(), locs->input_count());
|
|
for (intptr_t i = 0; i < expected_inputs->length(); i++) {
|
|
EXPECT(locs->in(i).Equals(expected_inputs->At(i)));
|
|
}
|
|
EXPECT_EQ(expected_temps->length(), locs->temp_count());
|
|
for (intptr_t i = 0; i < expected_temps->length(); i++) {
|
|
EXPECT(locs->temp(i).Equals(expected_temps->At(i)));
|
|
}
|
|
}
|
|
|
|
static void FillSummary(LocationSummary* locs,
|
|
Location expected_output,
|
|
const LocationArray* expected_inputs,
|
|
const LocationArray* expected_temps) {
|
|
locs->set_out(0, expected_output);
|
|
for (intptr_t i = 0; i < expected_inputs->length(); i++) {
|
|
locs->set_in(i, expected_inputs->At(i));
|
|
}
|
|
for (intptr_t i = 0; i < expected_temps->length(); i++) {
|
|
locs->set_temp(i, expected_temps->At(i));
|
|
}
|
|
}
|
|
|
|
class MockInstruction : public ZoneAllocated {
|
|
public:
|
|
virtual ~MockInstruction() {}
|
|
|
|
LocationSummary* locs() {
|
|
if (locs_ == NULL) {
|
|
locs_ = MakeLocationSummary(Thread::Current()->zone(), false);
|
|
}
|
|
return locs_;
|
|
}
|
|
|
|
virtual LocationSummary* MakeLocationSummary(Zone* zone, bool opt) const = 0;
|
|
virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
|
|
|
|
private:
|
|
LocationSummary* locs_;
|
|
};
|
|
|
|
#define INSTRUCTION_TEST(Name, Arity, Signature, ExpectedOut, ExpectedIn, \
|
|
ExpectedTemp, AllocatedOut, AllocatedIn, \
|
|
AllocatedTemp) \
|
|
class Name##Instr : public MockInstruction { \
|
|
public: \
|
|
LocationSummary* MakeLocationSummary(Zone* zone, bool opt) const; \
|
|
void EmitNativeCode(FlowGraphCompiler* compiler); \
|
|
virtual intptr_t InputCount() const { return Arity; } \
|
|
}; \
|
|
TEST_CASE(LocationsHelpers_##Name) { \
|
|
const Location expected_out = ExpectedOut; \
|
|
const LocationArray* expected_inputs = MakeLocationArray ExpectedIn; \
|
|
const LocationArray* expected_temps = MakeLocationArray ExpectedTemp; \
|
|
\
|
|
const Location allocated_out = AllocatedOut; \
|
|
const LocationArray* allocated_inputs = MakeLocationArray AllocatedIn; \
|
|
const LocationArray* allocated_temps = MakeLocationArray AllocatedTemp; \
|
|
\
|
|
Name##Instr* instr = new Name##Instr(); \
|
|
LocationSummary* locs = instr->locs(); \
|
|
\
|
|
ValidateSummary(locs, expected_out, expected_inputs, expected_temps); \
|
|
FillSummary(locs, allocated_out, allocated_inputs, allocated_temps); \
|
|
\
|
|
instr->EmitNativeCode(NULL); \
|
|
} \
|
|
DEFINE_BACKEND(Name, Signature)
|
|
|
|
// Reg -> Reg
|
|
INSTRUCTION_TEST(Unary,
|
|
1,
|
|
(Register out, Register in),
|
|
ReqReg,
|
|
(ReqReg),
|
|
(),
|
|
RegLoc(0),
|
|
(RegLoc(1)),
|
|
()) {
|
|
EXPECT_EQ(Reg(0), out);
|
|
EXPECT_EQ(Reg(1), in);
|
|
}
|
|
|
|
// (Reg, Fpu) -> Reg
|
|
INSTRUCTION_TEST(Binary1,
|
|
2,
|
|
(Register out, Register in0, FpuRegister in1),
|
|
ReqReg,
|
|
(ReqReg, Location::RequiresFpuRegister()),
|
|
(),
|
|
RegLoc(0),
|
|
(RegLoc(1), FpuLoc(2)),
|
|
()) {
|
|
EXPECT_EQ(Reg(0), out);
|
|
EXPECT_EQ(Reg(1), in0);
|
|
EXPECT_EQ(Fpu(2), in1);
|
|
}
|
|
|
|
// (Fpu, Reg) -> Reg
|
|
INSTRUCTION_TEST(Binary2,
|
|
2,
|
|
(Register out, FpuRegister in0, Register in1),
|
|
ReqReg,
|
|
(ReqFpu, ReqReg),
|
|
(),
|
|
RegLoc(0),
|
|
(FpuLoc(1), RegLoc(2)),
|
|
()) {
|
|
EXPECT_EQ(Reg(0), out);
|
|
EXPECT_EQ(Fpu(1), in0);
|
|
EXPECT_EQ(Reg(2), in1);
|
|
}
|
|
|
|
// -> Reg(3)
|
|
INSTRUCTION_TEST(FixedOutput,
|
|
0,
|
|
(Fixed<Register, Reg(3)> out),
|
|
RegLoc(3),
|
|
(),
|
|
(),
|
|
RegLoc(3),
|
|
(),
|
|
()) {
|
|
EXPECT_EQ(Reg(3), Reg(out));
|
|
}
|
|
|
|
// Fpu(3) -> Fpu
|
|
INSTRUCTION_TEST(FixedInput,
|
|
1,
|
|
(FpuRegister out, Fixed<FpuRegister, Fpu(3)> in),
|
|
ReqFpu,
|
|
(FpuLoc(3)),
|
|
(),
|
|
FpuLoc(0),
|
|
(FpuLoc(3)),
|
|
()) {
|
|
EXPECT_EQ(Fpu(0), out);
|
|
EXPECT_EQ(Fpu(3), Fpu(in));
|
|
}
|
|
|
|
// Reg -> SameAsFirstInput
|
|
INSTRUCTION_TEST(SameAsFirstInput,
|
|
2,
|
|
(SameAsFirstInput, Register in0, Register in1),
|
|
Location::SameAsFirstInput(),
|
|
(ReqReg, ReqReg),
|
|
(),
|
|
RegLoc(0),
|
|
(RegLoc(0), RegLoc(1)),
|
|
()) {
|
|
EXPECT_EQ(Reg(0), in0);
|
|
EXPECT_EQ(Reg(1), in1);
|
|
}
|
|
|
|
// {Temps: Fpu, Reg} (Reg, Fpu) -> Reg
|
|
INSTRUCTION_TEST(Temps,
|
|
2,
|
|
(Register out,
|
|
Register in0,
|
|
FpuRegister in1,
|
|
Temp<FpuRegister> temp0,
|
|
Temp<Register> temp1),
|
|
ReqReg,
|
|
(ReqReg, ReqFpu),
|
|
(ReqFpu, ReqReg),
|
|
RegLoc(0),
|
|
(RegLoc(1), FpuLoc(2)),
|
|
(FpuLoc(3), RegLoc(4))) {
|
|
EXPECT_EQ(Reg(0), out);
|
|
EXPECT_EQ(Reg(1), in0);
|
|
EXPECT_EQ(Fpu(2), in1);
|
|
EXPECT_EQ(Fpu(3), Fpu(temp0));
|
|
EXPECT_EQ(Reg(4), Reg(temp1));
|
|
}
|
|
|
|
// {Temps: Fpu(3)} -> Fpu
|
|
INSTRUCTION_TEST(FixedTemp,
|
|
0,
|
|
(FpuRegister out, Temp<Fixed<FpuRegister, Fpu(3)> > temp),
|
|
ReqFpu,
|
|
(),
|
|
(FpuLoc(3)),
|
|
FpuLoc(4),
|
|
(),
|
|
(FpuLoc(3))) {
|
|
EXPECT_EQ(Fpu(4), out);
|
|
EXPECT_EQ(Fpu(3), Fpu(temp));
|
|
}
|
|
|
|
} // namespace dart
|