blob: 02bf960e189a3048c190d34fd83a3f677bee3150 [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) \
Artem Serov02109dd2016-09-23 17:17:54 +0100108 M(And) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100109 M(ArrayLength) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100110 M(Below) \
111 M(BelowOrEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100112 M(ClearException) \
113 M(ClinitCheck) \
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100114 M(Compare) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100115 M(CurrentMethod) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100116 M(Div) \
117 M(DivZeroCheck) \
Alexandre Ramesb45fbaa52016-10-17 14:57:13 +0100118 M(DoubleConstant) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100119 M(Equal) \
120 M(Exit) \
Alexandre Ramesb45fbaa52016-10-17 14:57:13 +0100121 M(FloatConstant) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100122 M(Goto) \
123 M(GreaterThan) \
124 M(GreaterThanOrEqual) \
125 M(If) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100126 M(InstanceFieldGet) \
127 M(InstanceFieldSet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100128 M(IntConstant) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100129 M(InvokeStaticOrDirect) \
130 M(InvokeVirtual) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100131 M(LessThan) \
132 M(LessThanOrEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100133 M(LoadClass) \
134 M(LoadException) \
135 M(LoadString) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100136 M(LongConstant) \
137 M(MemoryBarrier) \
138 M(Mul) \
Artem Serov02109dd2016-09-23 17:17:54 +0100139 M(Neg) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100140 M(NewArray) \
141 M(NewInstance) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100142 M(Not) \
143 M(NotEqual) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100144 M(NullCheck) \
145 M(NullConstant) \
Artem Serov02109dd2016-09-23 17:17:54 +0100146 M(Or) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100147 M(ParallelMove) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100148 M(ParameterValue) \
149 M(Phi) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100150 M(Return) \
151 M(ReturnVoid) \
Artem Serov02109dd2016-09-23 17:17:54 +0100152 M(Ror) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100153 M(Select) \
Artem Serov02109dd2016-09-23 17:17:54 +0100154 M(Shl) \
155 M(Shr) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100156 M(StaticFieldGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100157 M(Sub) \
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100158 M(SuspendCheck) \
159 M(Throw) \
160 M(TryBoundary) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100161 M(TypeConversion) \
Artem Serov02109dd2016-09-23 17:17:54 +0100162 M(UShr) \
163 M(Xor) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100164
165// TODO: Remove once the VIXL32 backend is implemented completely.
166#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100167 M(ArrayGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100168 M(ArraySet) \
169 M(BooleanNot) \
170 M(BoundsCheck) \
171 M(BoundType) \
172 M(CheckCast) \
173 M(ClassTableGet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100174 M(Deoptimize) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100175 M(InstanceOf) \
176 M(InvokeInterface) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100177 M(InvokeUnresolved) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100178 M(MonitorOperation) \
179 M(NativeDebugInfo) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100180 M(PackedSwitch) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100181 M(Rem) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100182 M(StaticFieldSet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100183 M(UnresolvedInstanceFieldGet) \
184 M(UnresolvedInstanceFieldSet) \
185 M(UnresolvedStaticFieldGet) \
186 M(UnresolvedStaticFieldSet) \
Scott Wakelingfe885462016-09-22 10:24:38 +0100187
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);
Artem Serov02109dd2016-09-23 17:17:54 +0100279 void HandleBitwiseOperation(HBinaryOperation* operation, Opcode opcode);
Scott Wakelingfe885462016-09-22 10:24:38 +0100280 void HandleCondition(HCondition* condition);
Artem Serov02109dd2016-09-23 17:17:54 +0100281 void HandleIntegerRotate(LocationSummary* locations);
282 void HandleLongRotate(LocationSummary* locations);
283 void HandleShift(HBinaryOperation* operation);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100284 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
285 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
Scott Wakelingfe885462016-09-22 10:24:38 +0100286
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100287 Location ArithmeticZeroOrFpuRegister(HInstruction* input);
Artem Serov02109dd2016-09-23 17:17:54 +0100288 Location ArmEncodableConstantOrRegister(HInstruction* constant, Opcode opcode);
289 bool CanEncodeConstantAsImmediate(HConstant* input_cst, Opcode opcode);
290 bool CanEncodeConstantAsImmediate(uint32_t value, Opcode opcode, SetCc set_cc = kCcDontCare);
Alexandre Rames9c19bd62016-10-24 11:50:32 +0100291
Scott Wakelingfe885462016-09-22 10:24:38 +0100292 CodeGeneratorARMVIXL* const codegen_;
293 InvokeDexCallingConventionVisitorARM parameter_visitor_;
294
295 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARMVIXL);
296};
297
298class InstructionCodeGeneratorARMVIXL : public InstructionCodeGenerator {
299 public:
300 InstructionCodeGeneratorARMVIXL(HGraph* graph, CodeGeneratorARMVIXL* codegen);
301
302 FOR_EACH_IMPLEMENTED_INSTRUCTION(DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR)
303
304 FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR)
305
306 ArmVIXLAssembler* GetAssembler() const { return assembler_; }
307 vixl::aarch32::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
308
309 private:
310 void VisitUnimplemementedInstruction(HInstruction* instruction) {
311 LOG(FATAL) << "Unimplemented Instruction: " << instruction->DebugName();
312 }
313
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100314 // Generate code for the given suspend check. If not null, `successor`
315 // is the block to branch to if the suspend check is not needed, and after
316 // the suspend call.
Scott Wakelingfe885462016-09-22 10:24:38 +0100317 void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100318 void GenerateClassInitializationCheck(LoadClassSlowPathARMVIXL* slow_path,
319 vixl32::Register class_reg);
Scott Wakelingfe885462016-09-22 10:24:38 +0100320 void HandleGoto(HInstruction* got, HBasicBlock* successor);
Artem Serov02109dd2016-09-23 17:17:54 +0100321 void GenerateAndConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
322 void GenerateOrrConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
323 void GenerateEorConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value);
324 void HandleBitwiseOperation(HBinaryOperation* operation);
Scott Wakelingfe885462016-09-22 10:24:38 +0100325 void HandleCondition(HCondition* condition);
Artem Serov02109dd2016-09-23 17:17:54 +0100326 void HandleIntegerRotate(HRor* ror);
327 void HandleLongRotate(HRor* ror);
328 void HandleShift(HBinaryOperation* operation);
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100329
330 void GenerateWideAtomicStore(vixl::aarch32::Register addr,
331 uint32_t offset,
332 vixl::aarch32::Register value_lo,
333 vixl::aarch32::Register value_hi,
334 vixl::aarch32::Register temp1,
335 vixl::aarch32::Register temp2,
336 HInstruction* instruction);
337 void GenerateWideAtomicLoad(vixl::aarch32::Register addr,
338 uint32_t offset,
339 vixl::aarch32::Register out_lo,
340 vixl::aarch32::Register out_hi);
341
342 void HandleFieldSet(HInstruction* instruction,
343 const FieldInfo& field_info,
344 bool value_can_be_null);
345 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
346
347 // Generate a GC root reference load:
348 //
349 // root <- *(obj + offset)
350 //
351 // while honoring read barriers if `requires_read_barrier` is true.
352 void GenerateGcRootFieldLoad(HInstruction* instruction,
353 Location root,
354 vixl::aarch32::Register obj,
355 uint32_t offset,
Roland Levillain00468f32016-10-27 18:02:48 +0100356 bool requires_read_barrier);
Scott Wakelingfe885462016-09-22 10:24:38 +0100357 void GenerateTestAndBranch(HInstruction* instruction,
358 size_t condition_input_index,
359 vixl::aarch32::Label* true_target,
360 vixl::aarch32::Label* false_target);
361 void GenerateCompareTestAndBranch(HCondition* condition,
362 vixl::aarch32::Label* true_target,
363 vixl::aarch32::Label* false_target);
364 void GenerateVcmp(HInstruction* instruction);
365 void GenerateFPJumps(HCondition* cond,
366 vixl::aarch32::Label* true_label,
367 vixl::aarch32::Label* false_label);
368 void GenerateLongComparesAndJumps(HCondition* cond,
369 vixl::aarch32::Label* true_label,
370 vixl::aarch32::Label* false_label);
371 void DivRemOneOrMinusOne(HBinaryOperation* instruction);
372 void DivRemByPowerOfTwo(HBinaryOperation* instruction);
373 void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
374 void GenerateDivRemConstantIntegral(HBinaryOperation* instruction);
375
376 ArmVIXLAssembler* const assembler_;
377 CodeGeneratorARMVIXL* const codegen_;
378
379 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARMVIXL);
380};
381
382class CodeGeneratorARMVIXL : public CodeGenerator {
383 public:
384 CodeGeneratorARMVIXL(HGraph* graph,
385 const ArmInstructionSetFeatures& isa_features,
386 const CompilerOptions& compiler_options,
387 OptimizingCompilerStats* stats = nullptr);
388
389 virtual ~CodeGeneratorARMVIXL() {}
390
391 void Initialize() OVERRIDE {
392 block_labels_.resize(GetGraph()->GetBlocks().size());
393 }
394
395 void GenerateFrameEntry() OVERRIDE;
396 void GenerateFrameExit() OVERRIDE;
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100397
Scott Wakelingfe885462016-09-22 10:24:38 +0100398 void Bind(HBasicBlock* block) OVERRIDE;
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100399
400 vixl::aarch32::Label* GetLabelOf(HBasicBlock* block) {
401 block = FirstNonEmptyBlock(block);
402 return &(block_labels_[block->GetBlockId()]);
403 }
404
Scott Wakelingfe885462016-09-22 10:24:38 +0100405 void MoveConstant(Location destination, int32_t value) OVERRIDE;
406 void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
407 void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
408
409 ArmVIXLAssembler* GetAssembler() OVERRIDE { return &assembler_; }
410
411 const ArmVIXLAssembler& GetAssembler() const OVERRIDE { return assembler_; }
412
413 vixl::aarch32::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
414
415 size_t GetWordSize() const OVERRIDE { return kArmWordSize; }
416
417 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return vixl::aarch32::kRegSizeInBytes; }
418
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100419 uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE {
420 vixl::aarch32::Label* block_entry_label = GetLabelOf(block);
421 DCHECK(block_entry_label->IsBound());
422 return block_entry_label->GetLocation();
423 }
424
Scott Wakelingfe885462016-09-22 10:24:38 +0100425 HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
426
427 HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
428
Scott Wakelingfe885462016-09-22 10:24:38 +0100429 void GenerateMemoryBarrier(MemBarrierKind kind);
430 void Finalize(CodeAllocator* allocator) OVERRIDE;
431 void SetupBlockedRegisters() const OVERRIDE;
432
Scott Wakelingfe885462016-09-22 10:24:38 +0100433 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
434 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
435
436 InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kThumb2; }
437
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100438 // Helper method to move a 32-bit value between two locations.
439 void Move32(Location destination, Location source);
440
Scott Wakelingfe885462016-09-22 10:24:38 +0100441 const ArmInstructionSetFeatures& GetInstructionSetFeatures() const { return isa_features_; }
442
443 vixl::aarch32::Label* GetFrameEntryLabel() { return &frame_entry_label_; }
444
445 // Saves the register in the stack. Returns the size taken on stack.
446 size_t SaveCoreRegister(size_t stack_index ATTRIBUTE_UNUSED,
447 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
448 UNIMPLEMENTED(INFO) << "TODO: SaveCoreRegister";
449 return 0;
450 }
451
452 // Restores the register from the stack. Returns the size taken on stack.
453 size_t RestoreCoreRegister(size_t stack_index ATTRIBUTE_UNUSED,
454 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
455 UNIMPLEMENTED(INFO) << "TODO: RestoreCoreRegister";
456 return 0;
457 }
458
459 size_t SaveFloatingPointRegister(size_t stack_index ATTRIBUTE_UNUSED,
460 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
461 UNIMPLEMENTED(INFO) << "TODO: SaveFloatingPointRegister";
462 return 0;
463 }
464
465 size_t RestoreFloatingPointRegister(size_t stack_index ATTRIBUTE_UNUSED,
466 uint32_t reg_id ATTRIBUTE_UNUSED) OVERRIDE {
467 UNIMPLEMENTED(INFO) << "TODO: RestoreFloatingPointRegister";
468 return 0;
469 }
470
471 bool NeedsTwoRegisters(Primitive::Type type) const OVERRIDE {
472 return type == Primitive::kPrimDouble || type == Primitive::kPrimLong;
473 }
474
475 void ComputeSpillMask() OVERRIDE;
476
477 void GenerateImplicitNullCheck(HNullCheck* null_check) OVERRIDE;
478 void GenerateExplicitNullCheck(HNullCheck* null_check) OVERRIDE;
479
480 ParallelMoveResolver* GetMoveResolver() OVERRIDE {
481 return &move_resolver_;
482 }
483
484 // Generate code to invoke a runtime entry point.
485 void InvokeRuntime(QuickEntrypointEnum entrypoint,
486 HInstruction* instruction,
487 uint32_t dex_pc,
488 SlowPathCode* slow_path = nullptr) OVERRIDE;
489
490 // Generate code to invoke a runtime entry point, but do not record
491 // PC-related information in a stack map.
492 void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
493 HInstruction* instruction,
494 SlowPathCode* slow_path);
495
496 void GenerateInvokeRuntime(int32_t entry_point_offset);
497
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100498 // Emit a write barrier.
499 void MarkGCCard(vixl::aarch32::Register temp,
500 vixl::aarch32::Register card,
501 vixl::aarch32::Register object,
502 vixl::aarch32::Register value,
503 bool can_be_null);
504
505 // If read barriers are enabled, generate a read barrier for a heap
506 // reference using a slow path. If heap poisoning is enabled, also
507 // unpoison the reference in `out`.
508 void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
509 Location out,
510 Location ref,
511 Location obj,
512 uint32_t offset,
513 Location index = Location::NoLocation());
514
Scott Wakelingfe885462016-09-22 10:24:38 +0100515 // Check if the desired_string_load_kind is supported. If it is, return it,
516 // otherwise return a fall-back kind that should be used instead.
517 HLoadString::LoadKind GetSupportedLoadStringKind(
518 HLoadString::LoadKind desired_string_load_kind) OVERRIDE;
519
520 // Check if the desired_class_load_kind is supported. If it is, return it,
521 // otherwise return a fall-back kind that should be used instead.
522 HLoadClass::LoadKind GetSupportedLoadClassKind(
523 HLoadClass::LoadKind desired_class_load_kind) OVERRIDE;
524
525 // Check if the desired_dispatch_info is supported. If it is, return it,
526 // otherwise return a fall-back info that should be used instead.
527 HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
528 const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
Nicolas Geoffray5e4e11e2016-09-22 13:17:41 +0100529 HInvokeStaticOrDirect* invoke) OVERRIDE;
Scott Wakelingfe885462016-09-22 10:24:38 +0100530
531 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
532 void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
533
534 void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE;
535
536 void GenerateNop() OVERRIDE;
537
Scott Wakelingfe885462016-09-22 10:24:38 +0100538 private:
Scott Wakelinga7812ae2016-10-17 10:03:36 +0100539 vixl::aarch32::Register GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
540 vixl::aarch32::Register temp);
541
Scott Wakelingfe885462016-09-22 10:24:38 +0100542 // Labels for each block that will be compiled.
543 // We use a deque so that the `vixl::aarch32::Label` objects do not move in memory.
544 ArenaDeque<vixl::aarch32::Label> block_labels_; // Indexed by block id.
545 vixl::aarch32::Label frame_entry_label_;
546
547 LocationsBuilderARMVIXL location_builder_;
548 InstructionCodeGeneratorARMVIXL instruction_visitor_;
549 ParallelMoveResolverARMVIXL move_resolver_;
550
551 ArmVIXLAssembler assembler_;
552 const ArmInstructionSetFeatures& isa_features_;
553
554 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARMVIXL);
555};
556
557#undef FOR_EACH_IMPLEMENTED_INSTRUCTION
558#undef FOR_EACH_UNIMPLEMENTED_INSTRUCTION
559#undef DEFINE_IMPLEMENTED_INSTRUCTION_VISITOR
560#undef DEFINE_UNIMPLEMENTED_INSTRUCTION_VISITOR
561
562
563} // namespace arm
564} // namespace art
565
566#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM_VIXL_H_