1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_H_
18 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_H_
19 
20 #include "code_generator.h"
21 #include "nodes.h"
22 #include "parallel_move_resolver.h"
23 #include "utils/arm/assembler_thumb2.h"
24 
25 namespace art {
26 namespace arm {
27 
28 class CodeGeneratorARM;
29 
30 static constexpr size_t kArmWordSize = 4;
31 
32 static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
33 static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 };
34 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
35 
36 class InvokeDexCallingConvention : public CallingConvention<Register> {
37  public:
InvokeDexCallingConvention()38   InvokeDexCallingConvention()
39       : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
40 
GetRegisterPairAt(size_t argument_index)41   RegisterPair GetRegisterPairAt(size_t argument_index) {
42     DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
43     return kParameterCorePairRegisters[argument_index];
44   }
45 
46  private:
47   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
48 };
49 
50 class InvokeDexCallingConventionVisitor {
51  public:
InvokeDexCallingConventionVisitor()52   InvokeDexCallingConventionVisitor() : gp_index_(0) {}
53 
54   Location GetNextLocation(Primitive::Type type);
55 
56  private:
57   InvokeDexCallingConvention calling_convention;
58   uint32_t gp_index_;
59 
60   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
61 };
62 
63 class ParallelMoveResolverARM : public ParallelMoveResolver {
64  public:
ParallelMoveResolverARM(ArenaAllocator * allocator,CodeGeneratorARM * codegen)65   ParallelMoveResolverARM(ArenaAllocator* allocator, CodeGeneratorARM* codegen)
66       : ParallelMoveResolver(allocator), codegen_(codegen) {}
67 
68   virtual void EmitMove(size_t index) OVERRIDE;
69   virtual void EmitSwap(size_t index) OVERRIDE;
70   virtual void SpillScratch(int reg) OVERRIDE;
71   virtual void RestoreScratch(int reg) OVERRIDE;
72 
73   ArmAssembler* GetAssembler() const;
74 
75  private:
76   void Exchange(Register reg, int mem);
77   void Exchange(int mem1, int mem2);
78 
79   CodeGeneratorARM* const codegen_;
80 
81   DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARM);
82 };
83 
84 class LocationsBuilderARM : public HGraphVisitor {
85  public:
LocationsBuilderARM(HGraph * graph,CodeGeneratorARM * codegen)86   explicit LocationsBuilderARM(HGraph* graph, CodeGeneratorARM* codegen)
87       : HGraphVisitor(graph), codegen_(codegen) {}
88 
89 #define DECLARE_VISIT_INSTRUCTION(name)     \
90   virtual void Visit##name(H##name* instr);
91 
92   FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
93 
94 #undef DECLARE_VISIT_INSTRUCTION
95 
96  private:
97   CodeGeneratorARM* const codegen_;
98   InvokeDexCallingConventionVisitor parameter_visitor_;
99 
100   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM);
101 };
102 
103 class InstructionCodeGeneratorARM : public HGraphVisitor {
104  public:
105   InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen);
106 
107 #define DECLARE_VISIT_INSTRUCTION(name)     \
108   virtual void Visit##name(H##name* instr);
109 
FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)110   FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
111 
112 #undef DECLARE_VISIT_INSTRUCTION
113 
114   ArmAssembler* GetAssembler() const { return assembler_; }
115   void LoadCurrentMethod(Register reg);
116 
117  private:
118   ArmAssembler* const assembler_;
119   CodeGeneratorARM* const codegen_;
120 
121   DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARM);
122 };
123 
124 class CodeGeneratorARM : public CodeGenerator {
125  public:
126   explicit CodeGeneratorARM(HGraph* graph);
~CodeGeneratorARM()127   virtual ~CodeGeneratorARM() { }
128 
129   virtual void GenerateFrameEntry() OVERRIDE;
130   virtual void GenerateFrameExit() OVERRIDE;
131   virtual void Bind(Label* label) OVERRIDE;
132   virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
133 
GetWordSize()134   virtual size_t GetWordSize() const OVERRIDE {
135     return kArmWordSize;
136   }
137 
138   virtual size_t FrameEntrySpillSize() const OVERRIDE;
139 
GetLocationBuilder()140   virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
141     return &location_builder_;
142   }
143 
GetInstructionVisitor()144   virtual HGraphVisitor* GetInstructionVisitor() OVERRIDE {
145     return &instruction_visitor_;
146   }
147 
GetAssembler()148   virtual ArmAssembler* GetAssembler() OVERRIDE {
149     return &assembler_;
150   }
151 
152   virtual void SetupBlockedRegisters(bool* blocked_registers) const OVERRIDE;
153   virtual ManagedRegister AllocateFreeRegister(
154       Primitive::Type type, bool* blocked_registers) const OVERRIDE;
155   virtual size_t GetNumberOfRegisters() const OVERRIDE;
156 
157   virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
158 
GetNumberOfCoreRegisters()159   virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
160     return kNumberOfCoreRegisters;
161   }
162 
GetNumberOfFloatingPointRegisters()163   virtual size_t GetNumberOfFloatingPointRegisters() const OVERRIDE {
164     return kNumberOfDRegisters;
165   }
166 
167   virtual void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
168   virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
169 
GetMoveResolver()170   ParallelMoveResolverARM* GetMoveResolver() {
171     return &move_resolver_;
172   }
173 
GetInstructionSet()174   virtual InstructionSet GetInstructionSet() const OVERRIDE {
175     return InstructionSet::kThumb2;
176   }
177 
178   // Helper method to move a 32bits value between two locations.
179   void Move32(Location destination, Location source);
180   // Helper method to move a 64bits value between two locations.
181   void Move64(Location destination, Location source);
182 
183   // Emit a write barrier.
184   void MarkGCCard(Register temp, Register card, Register object, Register value);
185 
186  private:
187   LocationsBuilderARM location_builder_;
188   InstructionCodeGeneratorARM instruction_visitor_;
189   ParallelMoveResolverARM move_resolver_;
190   Thumb2Assembler assembler_;
191 
192   DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM);
193 };
194 
195 }  // namespace arm
196 }  // namespace art
197 
198 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_H_
199