blob: 534154f0d47ea796d614a8ec4d05e42edbdbcfd5 [file] [log] [blame]
Alexey Frunze4dda3372015-06-01 18:31:49 -07001/*
2 * Copyright (C) 2015 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_MIPS64_H_
18#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_
19
20#include "code_generator.h"
21#include "dex/compiler_enums.h"
22#include "driver/compiler_options.h"
23#include "nodes.h"
24#include "parallel_move_resolver.h"
25#include "utils/mips64/assembler_mips64.h"
26
27namespace art {
28namespace mips64 {
29
30// Use a local definition to prevent copying mistakes.
31static constexpr size_t kMips64WordSize = kMips64PointerSize;
32
33
34// InvokeDexCallingConvention registers
35
36static constexpr GpuRegister kParameterCoreRegisters[] =
37 { A1, A2, A3, A4, A5, A6, A7 };
38static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
39
40static constexpr FpuRegister kParameterFpuRegisters[] =
41 { F13, F14, F15, F16, F17, F18, F19 };
42static constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters);
43
44
45// InvokeRuntimeCallingConvention registers
46
47static constexpr GpuRegister kRuntimeParameterCoreRegisters[] =
48 { A0, A1, A2, A3, A4, A5, A6, A7 };
49static constexpr size_t kRuntimeParameterCoreRegistersLength =
50 arraysize(kRuntimeParameterCoreRegisters);
51
52static constexpr FpuRegister kRuntimeParameterFpuRegisters[] =
53 { F12, F13, F14, F15, F16, F17, F18, F19 };
54static constexpr size_t kRuntimeParameterFpuRegistersLength =
55 arraysize(kRuntimeParameterFpuRegisters);
56
57
58static constexpr GpuRegister kCoreCalleeSaves[] =
59 { S0, S1, S2, S3, S4, S5, S6, S7, GP, S8, RA }; // TODO: review
60static constexpr FpuRegister kFpuCalleeSaves[] =
61 { F24, F25, F26, F27, F28, F29, F30, F31 };
62
63
64class CodeGeneratorMIPS64;
65
66class InvokeDexCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
67 public:
68 InvokeDexCallingConvention()
69 : CallingConvention(kParameterCoreRegisters,
70 kParameterCoreRegistersLength,
71 kParameterFpuRegisters,
72 kParameterFpuRegistersLength,
73 kMips64PointerSize) {}
74
75 private:
76 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
77};
78
79class InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventionVisitor {
80 public:
81 InvokeDexCallingConventionVisitorMIPS64() {}
82 virtual ~InvokeDexCallingConventionVisitorMIPS64() {}
83
84 Location GetNextLocation(Primitive::Type type) OVERRIDE;
85 Location GetReturnLocation(Primitive::Type type) const OVERRIDE;
86 Location GetMethodLocation() const OVERRIDE;
87
88 private:
89 InvokeDexCallingConvention calling_convention;
90
91 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorMIPS64);
92};
93
94class InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, FpuRegister> {
95 public:
96 InvokeRuntimeCallingConvention()
97 : CallingConvention(kRuntimeParameterCoreRegisters,
98 kRuntimeParameterCoreRegistersLength,
99 kRuntimeParameterFpuRegisters,
100 kRuntimeParameterFpuRegistersLength,
101 kMips64PointerSize) {}
102
103 Location GetReturnLocation(Primitive::Type return_type);
104
105 private:
106 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
107};
108
109class ParallelMoveResolverMIPS64 : public ParallelMoveResolverWithSwap {
110 public:
111 ParallelMoveResolverMIPS64(ArenaAllocator* allocator, CodeGeneratorMIPS64* codegen)
112 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {}
113
114 void EmitMove(size_t index) OVERRIDE;
115 void EmitSwap(size_t index) OVERRIDE;
116 void SpillScratch(int reg) OVERRIDE;
117 void RestoreScratch(int reg) OVERRIDE;
118
119 void Exchange(int index1, int index2, bool double_slot);
120
121 Mips64Assembler* GetAssembler() const;
122
123 private:
124 CodeGeneratorMIPS64* const codegen_;
125
126 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverMIPS64);
127};
128
129class SlowPathCodeMIPS64 : public SlowPathCode {
130 public:
131 SlowPathCodeMIPS64() : entry_label_(), exit_label_() {}
132
133 Label* GetEntryLabel() { return &entry_label_; }
134 Label* GetExitLabel() { return &exit_label_; }
135
136 private:
137 Label entry_label_;
138 Label exit_label_;
139
140 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeMIPS64);
141};
142
143class LocationsBuilderMIPS64 : public HGraphVisitor {
144 public:
145 LocationsBuilderMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen)
146 : HGraphVisitor(graph), codegen_(codegen) {}
147
148#define DECLARE_VISIT_INSTRUCTION(name, super) \
149 void Visit##name(H##name* instr);
150
151 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
152
153#undef DECLARE_VISIT_INSTRUCTION
154
155 private:
156 void HandleInvoke(HInvoke* invoke);
157 void HandleBinaryOp(HBinaryOperation* operation);
158 void HandleShift(HBinaryOperation* operation);
159 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
160 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
161
162 InvokeDexCallingConventionVisitorMIPS64 parameter_visitor_;
163
164 CodeGeneratorMIPS64* const codegen_;
165
166 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderMIPS64);
167};
168
169class InstructionCodeGeneratorMIPS64 : public HGraphVisitor {
170 public:
171 InstructionCodeGeneratorMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen);
172
173#define DECLARE_VISIT_INSTRUCTION(name, super) \
174 void Visit##name(H##name* instr);
175
176 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
177
178#undef DECLARE_VISIT_INSTRUCTION
179
180 Mips64Assembler* GetAssembler() const { return assembler_; }
181
182 private:
183 // Generate code for the given suspend check. If not null, `successor`
184 // is the block to branch to if the suspend check is not needed, and after
185 // the suspend call.
186 void GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path, GpuRegister class_reg);
187 void GenerateMemoryBarrier(MemBarrierKind kind);
188 void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
189 void HandleBinaryOp(HBinaryOperation* operation);
190 void HandleShift(HBinaryOperation* operation);
191 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
192 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
193 void GenerateImplicitNullCheck(HNullCheck* instruction);
194 void GenerateExplicitNullCheck(HNullCheck* instruction);
195 void GenerateTestAndBranch(HInstruction* instruction,
196 Label* true_target,
197 Label* false_target,
198 Label* always_true_target);
199
200 Mips64Assembler* const assembler_;
201 CodeGeneratorMIPS64* const codegen_;
202
203 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorMIPS64);
204};
205
206class CodeGeneratorMIPS64 : public CodeGenerator {
207 public:
208 CodeGeneratorMIPS64(HGraph* graph,
209 const Mips64InstructionSetFeatures& isa_features,
210 const CompilerOptions& compiler_options);
211 virtual ~CodeGeneratorMIPS64() {}
212
213 void GenerateFrameEntry() OVERRIDE;
214 void GenerateFrameExit() OVERRIDE;
215
216 void Bind(HBasicBlock* block) OVERRIDE;
217
218 void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
219
220 size_t GetWordSize() const OVERRIDE { return kMips64WordSize; }
221
222 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64WordSize; }
223
224 uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE {
225 return GetLabelOf(block)->Position();
226 }
227
228 HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
229 HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
230 Mips64Assembler* GetAssembler() OVERRIDE { return &assembler_; }
231
232 void MarkGCCard(GpuRegister object, GpuRegister value);
233
234 // Register allocation.
235
236 void SetupBlockedRegisters(bool is_baseline) const OVERRIDE;
237 // AllocateFreeRegister() is only used when allocating registers locally
238 // during CompileBaseline().
239 Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE;
240
241 Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
242
243 size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id);
244 size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id);
245 size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id);
246 size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id);
247
248 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
249 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
250
251 InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; }
252
253 const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const {
254 return isa_features_;
255 }
256
257 Label* GetLabelOf(HBasicBlock* block) const {
258 return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block);
259 }
260
261 void Initialize() OVERRIDE {
262 block_labels_.SetSize(GetGraph()->GetBlocks().Size());
263 }
264
265 void Finalize(CodeAllocator* allocator) OVERRIDE;
266
267 // Code generation helpers.
268
269 void MoveLocation(Location destination, Location source, Primitive::Type type);
270
271 void SwapLocations(Location loc1, Location loc2, Primitive::Type type);
272
273 // Generate code to invoke a runtime entry point.
274 void InvokeRuntime(int32_t offset,
275 HInstruction* instruction,
276 uint32_t dex_pc,
277 SlowPathCode* slow_path);
278
279 ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; }
280
281 bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const { return false; }
282
283 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
284
285 private:
286 // Labels for each block that will be compiled.
287 GrowableArray<Label> block_labels_;
288 Label frame_entry_label_;
289 LocationsBuilderMIPS64 location_builder_;
290 InstructionCodeGeneratorMIPS64 instruction_visitor_;
291 ParallelMoveResolverMIPS64 move_resolver_;
292 Mips64Assembler assembler_;
293 const Mips64InstructionSetFeatures& isa_features_;
294
295 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorMIPS64);
296};
297
298} // namespace mips64
299} // namespace art
300
301#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_