blob: b0fa03899b8fb645be2452b8e8b17ab7af04fd4d [file] [log] [blame]
Scott Wakelingfe885462016-09-22 10:24:38 +01001/*
2 * Copyright (C) 2016 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_VIXL_H_
18#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_VIXL_H_
19
20#include "code_generator_arm.h"
21#include "utils/arm/assembler_arm_vixl.h"
22
23// TODO(VIXL): make vixl clean wrt -Wshadow.
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wshadow"
26#include "aarch32/constants-aarch32.h"
27#include "aarch32/instructions-aarch32.h"
28#include "aarch32/macro-assembler-aarch32.h"
29#pragma GCC diagnostic pop
30
31// True if VIXL32 should be used for codegen on ARM.
Scott Wakelinga7812ae2016-10-17 10:03:36 +010032#ifdef ART_USE_VIXL_ARM_BACKEND
Scott Wakelingfe885462016-09-22 10:24:38 +010033static constexpr bool kArmUseVIXL32 = true;
34#else
35static constexpr bool kArmUseVIXL32 = false;
36#endif
37
38namespace art {
39namespace arm {
40
Scott Wakelinga7812ae2016-10-17 10:03:36 +010041static const vixl::aarch32::Register kParameterCoreRegistersVIXL[] = {
42 vixl::aarch32::r1,
43 vixl::aarch32::r2,
44 vixl::aarch32::r3
45};
46static const size_t kParameterCoreRegistersLengthVIXL = arraysize(kParameterCoreRegisters);
47static const vixl::aarch32::SRegister kParameterFpuRegistersVIXL[] = {
48 vixl::aarch32::s0,
49 vixl::aarch32::s1,
50 vixl::aarch32::s2,
51 vixl::aarch32::s3,
52 vixl::aarch32::s4,
53 vixl::aarch32::s5,
54 vixl::aarch32::s6,
55 vixl::aarch32::s7,
56 vixl::aarch32::s8,
57 vixl::aarch32::s9,
58 vixl::aarch32::s10,
59 vixl::aarch32::s11,
60 vixl::aarch32::s12,
61 vixl::aarch32::s13,
62 vixl::aarch32::s14,
63 vixl::aarch32::s15
64};
65static const size_t kParameterFpuRegistersLengthVIXL = arraysize(kParameterFpuRegisters);
66
Scott Wakelingfe885462016-09-22 10:24:38 +010067static const vixl::aarch32::Register kMethodRegister = vixl::aarch32::r0;
Scott Wakelinga7812ae2016-10-17 10:03:36 +010068
Scott Wakelingfe885462016-09-22 10:24:38 +010069static const vixl::aarch32::Register kCoreAlwaysSpillRegister = vixl::aarch32::r5;
Scott Wakelinga7812ae2016-10-17 10:03:36 +010070
71// Callee saves core registers r5, r6, r7, r8, r10, r11, and lr.
72static const vixl::aarch32::RegisterList kCoreCalleeSaves = vixl::aarch32::RegisterList::Union(
73 vixl::aarch32::RegisterList(vixl::aarch32::r5,
74 vixl::aarch32::r6,
75 vixl::aarch32::r7,
76 vixl::aarch32::r8),
77 vixl::aarch32::RegisterList(vixl::aarch32::r10,
78 vixl::aarch32::r11,
79 vixl::aarch32::lr));
80
81// Callee saves FP registers s16 to s31 inclusive.
Scott Wakelingfe885462016-09-22 10:24:38 +010082static const vixl::aarch32::SRegisterList kFpuCalleeSaves =
83 vixl::aarch32::SRegisterList(vixl::aarch32::s16, 16);
84
Scott Wakelinga7812ae2016-10-17 10:03:36 +010085static const vixl::aarch32::Register kRuntimeParameterCoreRegistersVIXL[] = {
86 vixl::aarch32::r0,
87 vixl::aarch32::r1,
88 vixl::aarch32::r2,
89 vixl::aarch32::r3
90};
91static const size_t kRuntimeParameterCoreRegistersLengthVIXL =
92 arraysize(kRuntimeParameterCoreRegisters);
93static const vixl::aarch32::SRegister kRuntimeParameterFpuRegistersVIXL[] = {
94 vixl::aarch32::s0,
95 vixl::aarch32::s1,
96 vixl::aarch32::s2,
97 vixl::aarch32::s3
98};
99static const size_t kRuntimeParameterFpuRegistersLengthVIXL =
100 arraysize(kRuntimeParameterFpuRegisters);
101
102class LoadClassSlowPathARMVIXL;
103
Scott Wakelingfe885462016-09-22 10:24:38 +0100104#define FOR_EACH_IMPLEMENTED_INSTRUCTION(M) \
105 M(Above) \
106 M(AboveOrEqual) \
107 M(Add) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100108 M(ArrayLength) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100109 M(Below) \
110 M(BelowOrEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100111 M(ClearException) \
112 M(ClinitCheck) \
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100113 M(Compare) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100114 M(CurrentMethod) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100115 M(Div) \
116 M(DivZeroCheck) \
Alexandre Ramesb45fbaa52016-10-17 14:57:13 +0100117 M(DoubleConstant) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100118 M(Equal) \
119 M(Exit) \
Alexandre Ramesb45fbaa52016-10-17 14:57:13 +0100120 M(FloatConstant) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100121 M(Goto) \
122 M(GreaterThan) \
123 M(GreaterThanOrEqual) \
124 M(If) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100125 M(InstanceFieldGet) \
126 M(InstanceFieldSet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100127 M(IntConstant) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100128 M(InvokeStaticOrDirect) \
129 M(InvokeVirtual) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100130 M(LessThan) \
131 M(LessThanOrEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100132 M(LoadClass) \
133 M(LoadException) \
134 M(LoadString) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100135 M(LongConstant) \
136 M(MemoryBarrier) \
137 M(Mul) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100138 M(NewArray) \
139 M(NewInstance) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100140 M(Not) \
141 M(NotEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100142 M(NullCheck) \
143 M(NullConstant) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100144 M(ParallelMove) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100145 M(ParameterValue) \
146 M(Phi) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100147 M(Return) \
148 M(ReturnVoid) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100149 M(Select) \
150 M(StaticFieldGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100151 M(Sub) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100152 M(SuspendCheck) \
153 M(Throw) \
154 M(TryBoundary) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100155 M(TypeConversion) \
156
157// TODO: Remove once the VIXL32 backend is implemented completely.
158#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
159 M(And) \
160 M(ArrayGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100161 M(ArraySet) \
162 M(BooleanNot) \
163 M(BoundsCheck) \
164 M(BoundType) \
165 M(CheckCast) \
166 M(ClassTableGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100167 M(Deoptimize) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100168 M(InstanceOf) \
169 M(InvokeInterface) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100170 M(InvokeUnresolved) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100171 M(MonitorOperation) \
172 M(NativeDebugInfo) \
173 M(Neg) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100174 M(Or) \
175 M(PackedSwitch) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100176 M(Rem) \
177 M(Ror) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100178 M(Shl) \
179 M(Shr) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100180 M(StaticFieldSet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100181 M(UnresolvedInstanceFieldGet) \
182 M(UnresolvedInstanceFieldSet) \
183 M(UnresolvedStaticFieldGet) \
184 M(UnresolvedStaticFieldSet) \
185 M(UShr) \
186 M(Xor) \
187
188class CodeGeneratorARMVIXL;
189
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100190class InvokeRuntimeCallingConventionARMVIXL
191 : public CallingConvention<vixl::aarch32::Register, vixl::aarch32::SRegister> {
192 public:
193 InvokeRuntimeCallingConventionARMVIXL()
194 : CallingConvention(kRuntimeParameterCoreRegistersVIXL,
195 kRuntimeParameterCoreRegistersLengthVIXL,
196 kRuntimeParameterFpuRegistersVIXL,
197 kRuntimeParameterFpuRegistersLengthVIXL,
198 kArmPointerSize) {}
199
200 private:
201 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConventionARMVIXL);
202};
203
204class InvokeDexCallingConventionARMVIXL
205 : public CallingConvention<vixl::aarch32::Register, vixl::aarch32::SRegister> {
206 public:
207 InvokeDexCallingConventionARMVIXL()
208 : CallingConvention(kParameterCoreRegistersVIXL,
209 kParameterCoreRegistersLengthVIXL,
210 kParameterFpuRegistersVIXL,
211 kParameterFpuRegistersLengthVIXL,
212 kArmPointerSize) {}
213
214 private:
215 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionARMVIXL);
216};
217
Scott Wakelingfe885462016-09-22 10:24:38 +0100218class SlowPathCodeARMVIXL : public SlowPathCode {
219 public:
220 explicit SlowPathCodeARMVIXL(HInstruction* instruction)
221 : SlowPathCode(instruction), entry_label_(), exit_label_() {}
222
223 vixl::aarch32::Label* GetEntryLabel() { return &entry_label_; }
224 vixl::aarch32::Label* GetExitLabel() { return &exit_label_; }
225
226 void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
227 void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
228
229 private:
230 vixl::aarch32::Label entry_label_;
231 vixl::aarch32::Label exit_label_;
232
233 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeARMVIXL);
234};
235
236class ParallelMoveResolverARMVIXL : public ParallelMoveResolverWithSwap {
237 public:
238 ParallelMoveResolverARMVIXL(ArenaAllocator* allocator, CodeGeneratorARMVIXL* codegen)
239 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {}
240
241 void EmitMove(size_t index) OVERRIDE;
242 void EmitSwap(size_t index) OVERRIDE;
243 void SpillScratch(int reg) OVERRIDE;
244 void RestoreScratch(int reg) OVERRIDE;
245
246 ArmVIXLAssembler* GetAssembler() const;
247
248 private:
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100249 void Exchange(vixl32::Register reg, int mem);
Scott Wakelingfe885462016-09-22 10:24:38 +0100250 void Exchange(int mem1, int mem2);
251
252 CodeGeneratorARMVIXL* const codegen_;
253
254 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARMVIXL);
255};
256
257#define DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR(Name) \
258 void Visit##Name(H##Name*) OVERRIDE;
259
260#define DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR(Name) \
261 void Visit##Name(H##Name* instr) OVERRIDE { \
262 VisitUnimplemementedInstruction(instr); }
263
264class LocationsBuilderARMVIXL : public HGraphVisitor {
265 public:
266 LocationsBuilderARMVIXL(HGraph* graph, CodeGeneratorARMVIXL* codegen)
267 : HGraphVisitor(graph), codegen_(codegen) {}
268
269 FOR_EACH_IMPLEMENTED_INSTRUCTION(DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR)
270
271 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR)
272
273 private:
274 void VisitUnimplemementedInstruction(HInstruction* instruction) {
275 LOG(FATAL) << "Unimplemented Instruction: " << instruction->DebugName();
276 }
277
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100278 void HandleInvoke(HInvoke* invoke);
Scott Wakelingfe885462016-09-22 10:24:38 +0100279 void HandleCondition(HCondition* condition);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100280 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
281 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
Scott Wakelingfe885462016-09-22 10:24:38 +0100282
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100283 Location ArithmeticZeroOrFpuRegister(HInstruction* input);
284
Scott Wakelingfe885462016-09-22 10:24:38 +0100285 CodeGeneratorARMVIXL* const codegen_;
286 InvokeDexCallingConventionVisitorARM parameter_visitor_;
287
288 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARMVIXL);
289};
290
291class InstructionCodeGeneratorARMVIXL : public InstructionCodeGenerator {
292 public:
293 InstructionCodeGeneratorARMVIXL(HGraph* graph, CodeGeneratorARMVIXL* codegen);
294
295 FOR_EACH_IMPLEMENTED_INSTRUCTION(DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR)
296
297 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR)
298
299 ArmVIXLAssembler* GetAssembler() const { return assembler_; }
300 vixl::aarch32::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
301
302 private:
303 void VisitUnimplemementedInstruction(HInstruction* instruction) {
304 LOG(FATAL) << "Unimplemented Instruction: " << instruction->DebugName();
305 }
306
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100307 // Generate code for the given suspend check. If not null, `successor`
308 // is the block to branch to if the suspend check is not needed, and after
309 // the suspend call.
Scott Wakelingfe885462016-09-22 10:24:38 +0100310 void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100311 void GenerateClassInitializationCheck(LoadClassSlowPathARMVIXL* slow_path,
312 vixl32::Register class_reg);
Scott Wakelingfe885462016-09-22 10:24:38 +0100313 void HandleGoto(HInstruction* got, HBasicBlock* successor);
314 void HandleCondition(HCondition* condition);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100315
316 void GenerateWideAtomicStore(vixl::aarch32::Register addr,
317 uint32_t offset,
318 vixl::aarch32::Register value_lo,
319 vixl::aarch32::Register value_hi,
320 vixl::aarch32::Register temp1,
321 vixl::aarch32::Register temp2,
322 HInstruction* instruction);
323 void GenerateWideAtomicLoad(vixl::aarch32::Register addr,
324 uint32_t offset,
325 vixl::aarch32::Register out_lo,
326 vixl::aarch32::Register out_hi);
327
328 void HandleFieldSet(HInstruction* instruction,
329 const FieldInfo& field_info,
330 bool value_can_be_null);
331 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
332
333 // Generate a GC root reference load:
334 //
335 // root <- *(obj + offset)
336 //
337 // while honoring read barriers if `requires_read_barrier` is true.
338 void GenerateGcRootFieldLoad(HInstruction* instruction,
339 Location root,
340 vixl::aarch32::Register obj,
341 uint32_t offset,
Roland Levillain00468f32016-10-27 18:02:48 +0100342 bool requires_read_barrier);
Scott Wakelingfe885462016-09-22 10:24:38 +0100343 void GenerateTestAndBranch(HInstruction* instruction,
344 size_t condition_input_index,
345 vixl::aarch32::Label* true_target,
346 vixl::aarch32::Label* false_target);
347 void GenerateCompareTestAndBranch(HCondition* condition,
348 vixl::aarch32::Label* true_target,
349 vixl::aarch32::Label* false_target);
350 void GenerateVcmp(HInstruction* instruction);
351 void GenerateFPJumps(HCondition* cond,
352 vixl::aarch32::Label* true_label,
353 vixl::aarch32::Label* false_label);
354 void GenerateLongComparesAndJumps(HCondition* cond,
355 vixl::aarch32::Label* true_label,
356 vixl::aarch32::Label* false_label);
357 void DivRemOneOrMinusOne(HBinaryOperation* instruction);
358 void DivRemByPowerOfTwo(HBinaryOperation* instruction);
359 void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
360 void GenerateDivRemConstantIntegral(HBinaryOperation* instruction);
361
362 ArmVIXLAssembler* const assembler_;
363 CodeGeneratorARMVIXL* const codegen_;
364
365 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARMVIXL);
366};
367
368class CodeGeneratorARMVIXL : public CodeGenerator {
369 public:
370 CodeGeneratorARMVIXL(HGraph* graph,
371 const ArmInstructionSetFeatures& isa_features,
372 const CompilerOptions& compiler_options,
373 OptimizingCompilerStats* stats = nullptr);
374
375 virtual ~CodeGeneratorARMVIXL() {}
376
377 void Initialize() OVERRIDE {
378 block_labels_.resize(GetGraph()->GetBlocks().size());
379 }
380
381 void GenerateFrameEntry() OVERRIDE;
382 void GenerateFrameExit() OVERRIDE;
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100383
Scott Wakelingfe885462016-09-22 10:24:38 +0100384 void Bind(HBasicBlock* block) OVERRIDE;
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100385
386 vixl::aarch32::Label* GetLabelOf(HBasicBlock* block) {
387 block = FirstNonEmptyBlock(block);
388 return &(block_labels_[block->GetBlockId()]);
389 }
390
Scott Wakelingfe885462016-09-22 10:24:38 +0100391 void MoveConstant(Location destination, int32_t value) OVERRIDE;
392 void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
393 void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
394
395 ArmVIXLAssembler* GetAssembler() OVERRIDE { return &assembler_; }
396
397 const ArmVIXLAssembler& GetAssembler() const OVERRIDE { return assembler_; }
398
399 vixl::aarch32::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
400
401 size_t GetWordSize() const OVERRIDE { return kArmWordSize; }
402
403 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return vixl::aarch32::kRegSizeInBytes; }
404
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100405 uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE {
406 vixl::aarch32::Label* block_entry_label = GetLabelOf(block);
407 DCHECK(block_entry_label->IsBound());
408 return block_entry_label->GetLocation();
409 }
410
Scott Wakelingfe885462016-09-22 10:24:38 +0100411 HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
412
413 HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
414
Scott Wakelingfe885462016-09-22 10:24:38 +0100415 void GenerateMemoryBarrier(MemBarrierKind kind);
416 void Finalize(CodeAllocator* allocator) OVERRIDE;
417 void SetupBlockedRegisters() const OVERRIDE;
418
Scott Wakelingfe885462016-09-22 10:24:38 +0100419 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
420 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
421
422 InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kThumb2; }
423
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100424 // Helper method to move a 32-bit value between two locations.
425 void Move32(Location destination, Location source);
426
Scott Wakelingfe885462016-09-22 10:24:38 +0100427 const ArmInstructionSetFeatures& GetInstructionSetFeatures() const { return isa_features_; }
428
429 vixl::aarch32::Label* GetFrameEntryLabel() { return &frame_entry_label_; }
430
431 // Saves the register in the stack. Returns the size taken on stack.
432 size_t SaveCoreRegister(size_t stack_index ATTRIBUTE_UNUSED,
433 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
434 UNIMPLEMENTED(INFO) << "TODO: SaveCoreRegister";
435 return 0;
436 }
437
438 // Restores the register from the stack. Returns the size taken on stack.
439 size_t RestoreCoreRegister(size_t stack_index ATTRIBUTE_UNUSED,
440 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
441 UNIMPLEMENTED(INFO) << "TODO: RestoreCoreRegister";
442 return 0;
443 }
444
445 size_t SaveFloatingPointRegister(size_t stack_index ATTRIBUTE_UNUSED,
446 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
447 UNIMPLEMENTED(INFO) << "TODO: SaveFloatingPointRegister";
448 return 0;
449 }
450
451 size_t RestoreFloatingPointRegister(size_t stack_index ATTRIBUTE_UNUSED,
452 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
453 UNIMPLEMENTED(INFO) << "TODO: RestoreFloatingPointRegister";
454 return 0;
455 }
456
457 bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE {
458 return type == Primitive::kPrimDouble || type == Primitive::kPrimLong;
459 }
460
461 void ComputeSpillMask() OVERRIDE;
462
463 void GenerateImplicitNullCheck(HNullCheck* null_check) OVERRIDE;
464 void GenerateExplicitNullCheck(HNullCheck* null_check) OVERRIDE;
465
466 ParallelMoveResolver* GetMoveResolver() OVERRIDE {
467 return &move_resolver_;
468 }
469
470 // Generate code to invoke a runtime entry point.
471 void InvokeRuntime(QuickEntrypointEnum entrypoint,
472 HInstruction* instruction,
473 uint32_t dex_pc,
474 SlowPathCode* slow_path = nullptr) OVERRIDE;
475
476 // Generate code to invoke a runtime entry point, but do not record
477 // PC-related information in a stack map.
478 void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
479 HInstruction* instruction,
480 SlowPathCode* slow_path);
481
482 void GenerateInvokeRuntime(int32_t entry_point_offset);
483
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100484 // Emit a write barrier.
485 void MarkGCCard(vixl::aarch32::Register temp,
486 vixl::aarch32::Register card,
487 vixl::aarch32::Register object,
488 vixl::aarch32::Register value,
489 bool can_be_null);
490
491 // If read barriers are enabled, generate a read barrier for a heap
492 // reference using a slow path. If heap poisoning is enabled, also
493 // unpoison the reference in `out`.
494 void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
495 Location out,
496 Location ref,
497 Location obj,
498 uint32_t offset,
499 Location index = Location::NoLocation());
500
Scott Wakelingfe885462016-09-22 10:24:38 +0100501 // Check if the desired_string_load_kind is supported. If it is, return it,
502 // otherwise return a fall-back kind that should be used instead.
503 HLoadString::LoadKind GetSupportedLoadStringKind(
504 HLoadString::LoadKind desired_string_load_kind) OVERRIDE;
505
506 // Check if the desired_class_load_kind is supported. If it is, return it,
507 // otherwise return a fall-back kind that should be used instead.
508 HLoadClass::LoadKind GetSupportedLoadClassKind(
509 HLoadClass::LoadKind desired_class_load_kind) OVERRIDE;
510
511 // Check if the desired_dispatch_info is supported. If it is, return it,
512 // otherwise return a fall-back info that should be used instead.
513 HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
514 const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
Nicolas Geoffray5e4e11e2016-09-22 13:17:41 +0100515 HInvokeStaticOrDirect* invoke) OVERRIDE;
Scott Wakelingfe885462016-09-22 10:24:38 +0100516
517 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
518 void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
519
520 void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
521
522 void GenerateNop() OVERRIDE;
523
Scott Wakelingfe885462016-09-22 10:24:38 +0100524 private:
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100525 vixl::aarch32::Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
526 vixl::aarch32::Register temp);
527
Scott Wakelingfe885462016-09-22 10:24:38 +0100528 // Labels for each block that will be compiled.
529 // We use a deque so that the `vixl::aarch32::Label` objects do not move in memory.
530 ArenaDeque<vixl::aarch32::Label> block_labels_; // Indexed by block id.
531 vixl::aarch32::Label frame_entry_label_;
532
533 LocationsBuilderARMVIXL location_builder_;
534 InstructionCodeGeneratorARMVIXL instruction_visitor_;
535 ParallelMoveResolverARMVIXL move_resolver_;
536
537 ArmVIXLAssembler assembler_;
538 const ArmInstructionSetFeatures& isa_features_;
539
540 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARMVIXL);
541};
542
543#undef FOR_EACH_IMPLEMENTED_INSTRUCTION
544#undef FOR_EACH_UNIMPLEMENTED_INSTRUCTION
545#undef DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR
546#undef DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR
547
548
549} // namespace arm
550} // namespace art
551
552#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_VIXL_H_