Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 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 #ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
      6 #define V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
      7 
      8 #include <deque>
      9 #include <set>
     10 
     11 #include "src/base/utils/random-number-generator.h"
     12 #include "src/compiler/instruction-selector.h"
     13 #include "src/compiler/raw-machine-assembler.h"
     14 #include "src/macro-assembler.h"
     15 #include "test/unittests/test-utils.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 namespace compiler {
     20 
     21 class InstructionSelectorTest : public TestWithContext,
     22                                 public TestWithIsolateAndZone {
     23  public:
     24   InstructionSelectorTest();
     25   ~InstructionSelectorTest() override;
     26 
     27   base::RandomNumberGenerator* rng() { return &rng_; }
     28 
     29   class Stream;
     30 
     31   enum StreamBuilderMode {
     32     kAllInstructions,
     33     kTargetInstructions,
     34     kAllExceptNopInstructions
     35   };
     36 
     37   class StreamBuilder final : public RawMachineAssembler {
     38    public:
     39     StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
     40         : RawMachineAssembler(test->isolate(),
     41                               new (test->zone()) Graph(test->zone()),
     42                               MakeCallDescriptor(test->zone(), return_type),
     43                               MachineType::PointerRepresentation(),
     44                               MachineOperatorBuilder::kAllOptionalOps),
     45           test_(test) {}
     46     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     47                   MachineType parameter0_type)
     48         : RawMachineAssembler(
     49               test->isolate(), new (test->zone()) Graph(test->zone()),
     50               MakeCallDescriptor(test->zone(), return_type, parameter0_type),
     51               MachineType::PointerRepresentation(),
     52               MachineOperatorBuilder::kAllOptionalOps),
     53           test_(test) {}
     54     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     55                   MachineType parameter0_type, MachineType parameter1_type)
     56         : RawMachineAssembler(
     57               test->isolate(), new (test->zone()) Graph(test->zone()),
     58               MakeCallDescriptor(test->zone(), return_type, parameter0_type,
     59                                  parameter1_type),
     60               MachineType::PointerRepresentation(),
     61               MachineOperatorBuilder::kAllOptionalOps),
     62           test_(test) {}
     63     StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
     64                   MachineType parameter0_type, MachineType parameter1_type,
     65                   MachineType parameter2_type)
     66         : RawMachineAssembler(
     67               test->isolate(), new (test->zone()) Graph(test->zone()),
     68               MakeCallDescriptor(test->zone(), return_type, parameter0_type,
     69                                  parameter1_type, parameter2_type),
     70               MachineType::PointerRepresentation(),
     71               MachineOperatorBuilder::kAllOptionalOps),
     72           test_(test) {}
     73 
     74     Stream Build(CpuFeature feature) {
     75       return Build(InstructionSelector::Features(feature));
     76     }
     77     Stream Build(CpuFeature feature1, CpuFeature feature2) {
     78       return Build(InstructionSelector::Features(feature1, feature2));
     79     }
     80     Stream Build(StreamBuilderMode mode = kTargetInstructions) {
     81       return Build(InstructionSelector::Features(), mode);
     82     }
     83     Stream Build(InstructionSelector::Features features,
     84                  StreamBuilderMode mode = kTargetInstructions,
     85                  InstructionSelector::SourcePositionMode source_position_mode =
     86                      InstructionSelector::kAllSourcePositions);
     87 
     88     const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
     89                                                             int local_count);
     90 
     91    private:
     92     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
     93       MachineSignature::Builder builder(zone, 1, 0);
     94       builder.AddReturn(return_type);
     95       return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
     96     }
     97 
     98     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
     99                                        MachineType parameter0_type) {
    100       MachineSignature::Builder builder(zone, 1, 1);
    101       builder.AddReturn(return_type);
    102       builder.AddParam(parameter0_type);
    103       return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
    104     }
    105 
    106     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
    107                                        MachineType parameter0_type,
    108                                        MachineType parameter1_type) {
    109       MachineSignature::Builder builder(zone, 1, 2);
    110       builder.AddReturn(return_type);
    111       builder.AddParam(parameter0_type);
    112       builder.AddParam(parameter1_type);
    113       return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
    114     }
    115 
    116     CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
    117                                        MachineType parameter0_type,
    118                                        MachineType parameter1_type,
    119                                        MachineType parameter2_type) {
    120       MachineSignature::Builder builder(zone, 1, 3);
    121       builder.AddReturn(return_type);
    122       builder.AddParam(parameter0_type);
    123       builder.AddParam(parameter1_type);
    124       builder.AddParam(parameter2_type);
    125       return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
    126     }
    127 
    128    private:
    129     InstructionSelectorTest* test_;
    130   };
    131 
    132   class Stream final {
    133    public:
    134     size_t size() const { return instructions_.size(); }
    135     const Instruction* operator[](size_t index) const {
    136       EXPECT_LT(index, size());
    137       return instructions_[index];
    138     }
    139 
    140     bool IsDouble(const InstructionOperand* operand) const {
    141       return IsDouble(ToVreg(operand));
    142     }
    143 
    144     bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
    145 
    146     bool IsInteger(const InstructionOperand* operand) const {
    147       return IsInteger(ToVreg(operand));
    148     }
    149 
    150     bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
    151 
    152     bool IsReference(const InstructionOperand* operand) const {
    153       return IsReference(ToVreg(operand));
    154     }
    155 
    156     bool IsReference(const Node* node) const {
    157       return IsReference(ToVreg(node));
    158     }
    159 
    160     float ToFloat32(const InstructionOperand* operand) const {
    161       return ToConstant(operand).ToFloat32();
    162     }
    163 
    164     double ToFloat64(const InstructionOperand* operand) const {
    165       return ToConstant(operand).ToFloat64();
    166     }
    167 
    168     int32_t ToInt32(const InstructionOperand* operand) const {
    169       return ToConstant(operand).ToInt32();
    170     }
    171 
    172     int64_t ToInt64(const InstructionOperand* operand) const {
    173       return ToConstant(operand).ToInt64();
    174     }
    175 
    176     Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
    177       return ToConstant(operand).ToHeapObject();
    178     }
    179 
    180     int ToVreg(const InstructionOperand* operand) const {
    181       if (operand->IsConstant()) {
    182         return ConstantOperand::cast(operand)->virtual_register();
    183       }
    184       EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
    185       return UnallocatedOperand::cast(operand)->virtual_register();
    186     }
    187 
    188     int ToVreg(const Node* node) const;
    189 
    190     bool IsFixed(const InstructionOperand* operand, Register reg) const;
    191     bool IsSameAsFirst(const InstructionOperand* operand) const;
    192     bool IsUsedAtStart(const InstructionOperand* operand) const;
    193 
    194     FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
    195       EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
    196       return deoptimization_entries_[deoptimization_id];
    197     }
    198 
    199     int GetFrameStateDescriptorCount() {
    200       return static_cast<int>(deoptimization_entries_.size());
    201     }
    202 
    203    private:
    204     bool IsDouble(int virtual_register) const {
    205       return doubles_.find(virtual_register) != doubles_.end();
    206     }
    207 
    208     bool IsInteger(int virtual_register) const {
    209       return !IsDouble(virtual_register) && !IsReference(virtual_register);
    210     }
    211 
    212     bool IsReference(int virtual_register) const {
    213       return references_.find(virtual_register) != references_.end();
    214     }
    215 
    216     Constant ToConstant(const InstructionOperand* operand) const {
    217       ConstantMap::const_iterator i;
    218       if (operand->IsConstant()) {
    219         i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
    220         EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
    221         EXPECT_FALSE(constants_.end() == i);
    222       } else {
    223         EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
    224         auto imm = ImmediateOperand::cast(operand);
    225         if (imm->type() == ImmediateOperand::INLINE) {
    226           return Constant(imm->inline_value());
    227         }
    228         i = immediates_.find(imm->indexed_value());
    229         EXPECT_EQ(imm->indexed_value(), i->first);
    230         EXPECT_FALSE(immediates_.end() == i);
    231       }
    232       return i->second;
    233     }
    234 
    235     friend class StreamBuilder;
    236 
    237     typedef std::map<int, Constant> ConstantMap;
    238     typedef std::map<NodeId, int> VirtualRegisters;
    239 
    240     ConstantMap constants_;
    241     ConstantMap immediates_;
    242     std::deque<Instruction*> instructions_;
    243     std::set<int> doubles_;
    244     std::set<int> references_;
    245     VirtualRegisters virtual_registers_;
    246     std::deque<FrameStateDescriptor*> deoptimization_entries_;
    247   };
    248 
    249   base::RandomNumberGenerator rng_;
    250 };
    251 
    252 
    253 template <typename T>
    254 class InstructionSelectorTestWithParam
    255     : public InstructionSelectorTest,
    256       public ::testing::WithParamInterface<T> {};
    257 
    258 }  // namespace compiler
    259 }  // namespace internal
    260 }  // namespace v8
    261 
    262 #endif  // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
    263