/test/unittests/compiler/instruction-selector-unittest.h
C Header | 300 lines | 244 code | 50 blank | 6 comment | 12 complexity | d7948b5323f33ecc44d2f933e0f6ac6a MD5 | raw file
- // Copyright 2014 the V8 project authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
- #define V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
- #include <deque>
- #include <set>
- #include "src/base/utils/random-number-generator.h"
- #include "src/compiler/instruction-selector.h"
- #include "src/compiler/raw-machine-assembler.h"
- #include "src/macro-assembler.h"
- #include "test/unittests/test-utils.h"
- namespace v8 {
- namespace internal {
- namespace compiler {
- class InstructionSelectorTest : public TestWithContext,
- public TestWithIsolateAndZone {
- public:
- InstructionSelectorTest();
- ~InstructionSelectorTest() override;
- base::RandomNumberGenerator* rng() { return &rng_; }
- class Stream;
- enum StreamBuilderMode {
- kAllInstructions,
- kTargetInstructions,
- kAllExceptNopInstructions
- };
- class StreamBuilder final : public RawMachineAssembler {
- public:
- StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
- : RawMachineAssembler(test->isolate(),
- new (test->zone()) Graph(test->zone()),
- MakeCallDescriptor(test->zone(), return_type),
- MachineType::PointerRepresentation(),
- MachineOperatorBuilder::kAllOptionalOps),
- test_(test) {}
- StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
- MachineType parameter0_type)
- : RawMachineAssembler(
- test->isolate(), new (test->zone()) Graph(test->zone()),
- MakeCallDescriptor(test->zone(), return_type, parameter0_type),
- MachineType::PointerRepresentation(),
- MachineOperatorBuilder::kAllOptionalOps),
- test_(test) {}
- StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
- MachineType parameter0_type, MachineType parameter1_type)
- : RawMachineAssembler(
- test->isolate(), new (test->zone()) Graph(test->zone()),
- MakeCallDescriptor(test->zone(), return_type, parameter0_type,
- parameter1_type),
- MachineType::PointerRepresentation(),
- MachineOperatorBuilder::kAllOptionalOps),
- test_(test) {}
- StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
- MachineType parameter0_type, MachineType parameter1_type,
- MachineType parameter2_type)
- : RawMachineAssembler(
- test->isolate(), new (test->zone()) Graph(test->zone()),
- MakeCallDescriptor(test->zone(), return_type, parameter0_type,
- parameter1_type, parameter2_type),
- MachineType::PointerRepresentation(),
- MachineOperatorBuilder::kAllOptionalOps),
- test_(test) {}
- Stream Build(CpuFeature feature) {
- return Build(InstructionSelector::Features(feature));
- }
- Stream Build(CpuFeature feature1, CpuFeature feature2) {
- return Build(InstructionSelector::Features(feature1, feature2));
- }
- Stream Build(StreamBuilderMode mode = kTargetInstructions) {
- return Build(InstructionSelector::Features(), mode);
- }
- Stream Build(InstructionSelector::Features features,
- StreamBuilderMode mode = kTargetInstructions,
- InstructionSelector::SourcePositionMode source_position_mode =
- InstructionSelector::kAllSourcePositions);
- const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
- int local_count);
- private:
- CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
- MachineSignature::Builder builder(zone, 1, 0);
- builder.AddReturn(return_type);
- return MakeSimpleCallDescriptor(zone, builder.Build());
- }
- CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
- MachineType parameter0_type) {
- MachineSignature::Builder builder(zone, 1, 1);
- builder.AddReturn(return_type);
- builder.AddParam(parameter0_type);
- return MakeSimpleCallDescriptor(zone, builder.Build());
- }
- CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
- MachineType parameter0_type,
- MachineType parameter1_type) {
- MachineSignature::Builder builder(zone, 1, 2);
- builder.AddReturn(return_type);
- builder.AddParam(parameter0_type);
- builder.AddParam(parameter1_type);
- return MakeSimpleCallDescriptor(zone, builder.Build());
- }
- CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
- MachineType parameter0_type,
- MachineType parameter1_type,
- MachineType parameter2_type) {
- MachineSignature::Builder builder(zone, 1, 3);
- builder.AddReturn(return_type);
- builder.AddParam(parameter0_type);
- builder.AddParam(parameter1_type);
- builder.AddParam(parameter2_type);
- return MakeSimpleCallDescriptor(zone, builder.Build());
- }
- private:
- InstructionSelectorTest* test_;
- // Create a simple call descriptor for testing.
- CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
- MachineSignature* msig) {
- LocationSignature::Builder locations(zone, msig->return_count(),
- msig->parameter_count());
- // Add return location(s).
- const int return_count = static_cast<int>(msig->return_count());
- for (int i = 0; i < return_count; i++) {
- locations.AddReturn(
- LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetReturn(i)));
- }
- // Just put all parameters on the stack.
- const int parameter_count = static_cast<int>(msig->parameter_count());
- for (int i = 0; i < parameter_count; i++) {
- locations.AddParam(
- LinkageLocation::ForCallerFrameSlot(-1 - i, msig->GetParam(i)));
- }
- const RegList kCalleeSaveRegisters = 0;
- const RegList kCalleeSaveFPRegisters = 0;
- MachineType target_type = MachineType::Pointer();
- LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
- return new (zone) CallDescriptor( // --
- CallDescriptor::kCallAddress, // kind
- target_type, // target MachineType
- target_loc, // target location
- locations.Build(), // location_sig
- 0, // stack_parameter_count
- Operator::kNoProperties, // properties
- kCalleeSaveRegisters, // callee-saved registers
- kCalleeSaveFPRegisters, // callee-saved fp regs
- CallDescriptor::kNoFlags, // flags
- "iselect-test-call");
- }
- };
- class Stream final {
- public:
- size_t size() const { return instructions_.size(); }
- const Instruction* operator[](size_t index) const {
- EXPECT_LT(index, size());
- return instructions_[index];
- }
- bool IsDouble(const InstructionOperand* operand) const {
- return IsDouble(ToVreg(operand));
- }
- bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
- bool IsInteger(const InstructionOperand* operand) const {
- return IsInteger(ToVreg(operand));
- }
- bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
- bool IsReference(const InstructionOperand* operand) const {
- return IsReference(ToVreg(operand));
- }
- bool IsReference(const Node* node) const {
- return IsReference(ToVreg(node));
- }
- float ToFloat32(const InstructionOperand* operand) const {
- return ToConstant(operand).ToFloat32();
- }
- double ToFloat64(const InstructionOperand* operand) const {
- return ToConstant(operand).ToFloat64();
- }
- int32_t ToInt32(const InstructionOperand* operand) const {
- return ToConstant(operand).ToInt32();
- }
- int64_t ToInt64(const InstructionOperand* operand) const {
- return ToConstant(operand).ToInt64();
- }
- Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
- return ToConstant(operand).ToHeapObject();
- }
- int ToVreg(const InstructionOperand* operand) const {
- if (operand->IsConstant()) {
- return ConstantOperand::cast(operand)->virtual_register();
- }
- EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
- return UnallocatedOperand::cast(operand)->virtual_register();
- }
- int ToVreg(const Node* node) const;
- bool IsFixed(const InstructionOperand* operand, Register reg) const;
- bool IsSameAsFirst(const InstructionOperand* operand) const;
- bool IsUsedAtStart(const InstructionOperand* operand) const;
- FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
- EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
- return deoptimization_entries_[deoptimization_id];
- }
- int GetFrameStateDescriptorCount() {
- return static_cast<int>(deoptimization_entries_.size());
- }
- private:
- bool IsDouble(int virtual_register) const {
- return doubles_.find(virtual_register) != doubles_.end();
- }
- bool IsInteger(int virtual_register) const {
- return !IsDouble(virtual_register) && !IsReference(virtual_register);
- }
- bool IsReference(int virtual_register) const {
- return references_.find(virtual_register) != references_.end();
- }
- Constant ToConstant(const InstructionOperand* operand) const {
- ConstantMap::const_iterator i;
- if (operand->IsConstant()) {
- i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
- EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
- EXPECT_FALSE(constants_.end() == i);
- } else {
- EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
- auto imm = ImmediateOperand::cast(operand);
- if (imm->type() == ImmediateOperand::INLINE) {
- return Constant(imm->inline_value());
- }
- i = immediates_.find(imm->indexed_value());
- EXPECT_EQ(imm->indexed_value(), i->first);
- EXPECT_FALSE(immediates_.end() == i);
- }
- return i->second;
- }
- friend class StreamBuilder;
- typedef std::map<int, Constant> ConstantMap;
- typedef std::map<NodeId, int> VirtualRegisters;
- ConstantMap constants_;
- ConstantMap immediates_;
- std::deque<Instruction*> instructions_;
- std::set<int> doubles_;
- std::set<int> references_;
- VirtualRegisters virtual_registers_;
- std::deque<FrameStateDescriptor*> deoptimization_entries_;
- };
- base::RandomNumberGenerator rng_;
- };
- template <typename T>
- class InstructionSelectorTestWithParam
- : public InstructionSelectorTest,
- public ::testing::WithParamInterface<T> {};
- } // namespace compiler
- } // namespace internal
- } // namespace v8
- #endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_