code_generator_arm64.h revision 840e5461a85f8908f51e7f6cd562a9129ff0e7ce
15319defdf502fc4569316473846b83180ec08035Alexandre Rames/*
25319defdf502fc4569316473846b83180ec08035Alexandre Rames * Copyright (C) 2014 The Android Open Source Project
35319defdf502fc4569316473846b83180ec08035Alexandre Rames *
45319defdf502fc4569316473846b83180ec08035Alexandre Rames * Licensed under the Apache License, Version 2.0 (the "License");
55319defdf502fc4569316473846b83180ec08035Alexandre Rames * you may not use this file except in compliance with the License.
65319defdf502fc4569316473846b83180ec08035Alexandre Rames * You may obtain a copy of the License at
75319defdf502fc4569316473846b83180ec08035Alexandre Rames *
85319defdf502fc4569316473846b83180ec08035Alexandre Rames *      http://www.apache.org/licenses/LICENSE-2.0
95319defdf502fc4569316473846b83180ec08035Alexandre Rames *
105319defdf502fc4569316473846b83180ec08035Alexandre Rames * Unless required by applicable law or agreed to in writing, software
115319defdf502fc4569316473846b83180ec08035Alexandre Rames * distributed under the License is distributed on an "AS IS" BASIS,
125319defdf502fc4569316473846b83180ec08035Alexandre Rames * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135319defdf502fc4569316473846b83180ec08035Alexandre Rames * See the License for the specific language governing permissions and
145319defdf502fc4569316473846b83180ec08035Alexandre Rames * limitations under the License.
155319defdf502fc4569316473846b83180ec08035Alexandre Rames */
165319defdf502fc4569316473846b83180ec08035Alexandre Rames
175319defdf502fc4569316473846b83180ec08035Alexandre Rames#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
185319defdf502fc4569316473846b83180ec08035Alexandre Rames#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
195319defdf502fc4569316473846b83180ec08035Alexandre Rames
205319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator.h"
2102d81cc8d162a31f0664249535456775e397b608Serban Constantinescu#include "dex/compiler_enums.h"
225319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "nodes.h"
235319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "parallel_move_resolver.h"
245319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "utils/arm64/assembler_arm64.h"
255319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "a64/disasm-a64.h"
265319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "a64/macro-assembler-a64.h"
275319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "arch/arm64/quick_method_frame_info_arm64.h"
285319defdf502fc4569316473846b83180ec08035Alexandre Rames
295319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace art {
305319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace arm64 {
315319defdf502fc4569316473846b83180ec08035Alexandre Rames
325319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64;
3367555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Ramesclass SlowPathCodeARM64;
345319defdf502fc4569316473846b83180ec08035Alexandre Rames
3586a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray// Use a local definition to prevent copying mistakes.
3686a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffraystatic constexpr size_t kArm64WordSize = kArm64PointerSize;
3786a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray
385319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::Register kParameterCoreRegisters[] = {
395319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::x1, vixl::x2, vixl::x3, vixl::x4, vixl::x5, vixl::x6, vixl::x7
405319defdf502fc4569316473846b83180ec08035Alexandre Rames};
415319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
425319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::FPRegister kParameterFPRegisters[] = {
435319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::d0, vixl::d1, vixl::d2, vixl::d3, vixl::d4, vixl::d5, vixl::d6, vixl::d7
445319defdf502fc4569316473846b83180ec08035Alexandre Rames};
455319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters);
465319defdf502fc4569316473846b83180ec08035Alexandre Rames
475319defdf502fc4569316473846b83180ec08035Alexandre Ramesconst vixl::Register tr = vixl::x18;        // Thread Register
485319defdf502fc4569316473846b83180ec08035Alexandre Rames
495319defdf502fc4569316473846b83180ec08035Alexandre Ramesconst vixl::CPURegList vixl_reserved_core_registers(vixl::ip0, vixl::ip1);
50a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Ramesconst vixl::CPURegList vixl_reserved_fp_registers(vixl::d31);
5102164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescuconst vixl::CPURegList runtime_reserved_core_registers(tr, vixl::lr);
525b4b898ed8725242ee6b7229b94467c3ea3054c8Nicolas Geoffrayconst vixl::CPURegList quick_callee_saved_registers(vixl::CPURegister::kRegister,
535b4b898ed8725242ee6b7229b94467c3ea3054c8Nicolas Geoffray                                                    vixl::kXRegSize,
545b4b898ed8725242ee6b7229b94467c3ea3054c8Nicolas Geoffray                                                    kArm64CalleeSaveRefSpills);
555319defdf502fc4569316473846b83180ec08035Alexandre Rames
56a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre RamesLocation ARM64ReturnLocation(Primitive::Type return_type);
57a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames
585319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InvokeDexCallingConvention : public CallingConvention<vixl::Register, vixl::FPRegister> {
595319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
605319defdf502fc4569316473846b83180ec08035Alexandre Rames  InvokeDexCallingConvention()
615319defdf502fc4569316473846b83180ec08035Alexandre Rames      : CallingConvention(kParameterCoreRegisters,
625319defdf502fc4569316473846b83180ec08035Alexandre Rames                          kParameterCoreRegistersLength,
635319defdf502fc4569316473846b83180ec08035Alexandre Rames                          kParameterFPRegisters,
645319defdf502fc4569316473846b83180ec08035Alexandre Rames                          kParameterFPRegistersLength) {}
655319defdf502fc4569316473846b83180ec08035Alexandre Rames
665319defdf502fc4569316473846b83180ec08035Alexandre Rames  Location GetReturnLocation(Primitive::Type return_type) {
67a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames    return ARM64ReturnLocation(return_type);
685319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
695319defdf502fc4569316473846b83180ec08035Alexandre Rames
705319defdf502fc4569316473846b83180ec08035Alexandre Rames
715319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
725319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
735319defdf502fc4569316473846b83180ec08035Alexandre Rames};
745319defdf502fc4569316473846b83180ec08035Alexandre Rames
755319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InvokeDexCallingConventionVisitor {
765319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
77a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  InvokeDexCallingConventionVisitor() : gp_index_(0), fp_index_(0), stack_index_(0) {}
785319defdf502fc4569316473846b83180ec08035Alexandre Rames
795319defdf502fc4569316473846b83180ec08035Alexandre Rames  Location GetNextLocation(Primitive::Type type);
805319defdf502fc4569316473846b83180ec08035Alexandre Rames  Location GetReturnLocation(Primitive::Type return_type) {
815319defdf502fc4569316473846b83180ec08035Alexandre Rames    return calling_convention.GetReturnLocation(return_type);
825319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
835319defdf502fc4569316473846b83180ec08035Alexandre Rames
845319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
855319defdf502fc4569316473846b83180ec08035Alexandre Rames  InvokeDexCallingConvention calling_convention;
865319defdf502fc4569316473846b83180ec08035Alexandre Rames  // The current index for core registers.
875319defdf502fc4569316473846b83180ec08035Alexandre Rames  uint32_t gp_index_;
88a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  // The current index for floating-point registers.
89a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  uint32_t fp_index_;
905319defdf502fc4569316473846b83180ec08035Alexandre Rames  // The current stack index.
915319defdf502fc4569316473846b83180ec08035Alexandre Rames  uint32_t stack_index_;
925319defdf502fc4569316473846b83180ec08035Alexandre Rames
935319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
945319defdf502fc4569316473846b83180ec08035Alexandre Rames};
955319defdf502fc4569316473846b83180ec08035Alexandre Rames
965319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InstructionCodeGeneratorARM64 : public HGraphVisitor {
975319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
985319defdf502fc4569316473846b83180ec08035Alexandre Rames  InstructionCodeGeneratorARM64(HGraph* graph, CodeGeneratorARM64* codegen);
995319defdf502fc4569316473846b83180ec08035Alexandre Rames
1005319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \
101de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Visit##name(H##name* instr) OVERRIDE;
1025319defdf502fc4569316473846b83180ec08035Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1035319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION
1045319defdf502fc4569316473846b83180ec08035Alexandre Rames
1055319defdf502fc4569316473846b83180ec08035Alexandre Rames  void LoadCurrentMethod(XRegister reg);
1065319defdf502fc4569316473846b83180ec08035Alexandre Rames
1075319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler* GetAssembler() const { return assembler_; }
10867555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; }
1095319defdf502fc4569316473846b83180ec08035Alexandre Rames
1105319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
11167555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path, vixl::Register class_reg);
11202d81cc8d162a31f0664249535456775e397b608Serban Constantinescu  void GenerateMemoryBarrier(MemBarrierKind kind);
11302164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu  void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
11467555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void HandleBinaryOp(HBinaryOperation* instr);
11502164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu  void HandleShift(HBinaryOperation* instr);
1165319defdf502fc4569316473846b83180ec08035Alexandre Rames
1175319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler* const assembler_;
1185319defdf502fc4569316473846b83180ec08035Alexandre Rames  CodeGeneratorARM64* const codegen_;
1195319defdf502fc4569316473846b83180ec08035Alexandre Rames
1205319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARM64);
1215319defdf502fc4569316473846b83180ec08035Alexandre Rames};
1225319defdf502fc4569316473846b83180ec08035Alexandre Rames
1235319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass LocationsBuilderARM64 : public HGraphVisitor {
1245319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
1255319defdf502fc4569316473846b83180ec08035Alexandre Rames  explicit LocationsBuilderARM64(HGraph* graph, CodeGeneratorARM64* codegen)
1265319defdf502fc4569316473846b83180ec08035Alexandre Rames      : HGraphVisitor(graph), codegen_(codegen) {}
1275319defdf502fc4569316473846b83180ec08035Alexandre Rames
1285319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \
129de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Visit##name(H##name* instr) OVERRIDE;
1305319defdf502fc4569316473846b83180ec08035Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1315319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION
1325319defdf502fc4569316473846b83180ec08035Alexandre Rames
1335319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
13467555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void HandleBinaryOp(HBinaryOperation* instr);
13502164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu  void HandleShift(HBinaryOperation* instr);
1365319defdf502fc4569316473846b83180ec08035Alexandre Rames  void HandleInvoke(HInvoke* instr);
1375319defdf502fc4569316473846b83180ec08035Alexandre Rames
1385319defdf502fc4569316473846b83180ec08035Alexandre Rames  CodeGeneratorARM64* const codegen_;
1395319defdf502fc4569316473846b83180ec08035Alexandre Rames  InvokeDexCallingConventionVisitor parameter_visitor_;
1405319defdf502fc4569316473846b83180ec08035Alexandre Rames
1415319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM64);
1425319defdf502fc4569316473846b83180ec08035Alexandre Rames};
1435319defdf502fc4569316473846b83180ec08035Alexandre Rames
1443e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Ramesclass ParallelMoveResolverARM64 : public ParallelMoveResolver {
1453e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames public:
1463e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  ParallelMoveResolverARM64(ArenaAllocator* allocator, CodeGeneratorARM64* codegen)
1473e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames      : ParallelMoveResolver(allocator), codegen_(codegen) {}
1483e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
1493e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void EmitMove(size_t index) OVERRIDE;
1503e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void EmitSwap(size_t index) OVERRIDE;
1513e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void RestoreScratch(int reg) OVERRIDE;
1523e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void SpillScratch(int reg) OVERRIDE;
1533e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
1543e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames private:
1553e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  Arm64Assembler* GetAssembler() const;
1563e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() const {
1573e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    return GetAssembler()->vixl_masm_;
1583e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  }
1593e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
1603e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  CodeGeneratorARM64* const codegen_;
1613e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
1623e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARM64);
1633e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames};
1643e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
1655319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64 : public CodeGenerator {
1665319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
1675319defdf502fc4569316473846b83180ec08035Alexandre Rames  explicit CodeGeneratorARM64(HGraph* graph);
168de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual ~CodeGeneratorARM64() {}
1695319defdf502fc4569316473846b83180ec08035Alexandre Rames
170de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void GenerateFrameEntry() OVERRIDE;
171de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void GenerateFrameExit() OVERRIDE;
1725319defdf502fc4569316473846b83180ec08035Alexandre Rames
1735319defdf502fc4569316473846b83180ec08035Alexandre Rames  static const vixl::CPURegList& GetFramePreservedRegisters() {
1745319defdf502fc4569316473846b83180ec08035Alexandre Rames    static const vixl::CPURegList frame_preserved_regs =
1755319defdf502fc4569316473846b83180ec08035Alexandre Rames        vixl::CPURegList(vixl::CPURegister::kRegister, vixl::kXRegSize, vixl::lr.Bit());
1765319defdf502fc4569316473846b83180ec08035Alexandre Rames    return frame_preserved_regs;
1775319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
1785319defdf502fc4569316473846b83180ec08035Alexandre Rames  static int GetFramePreservedRegistersSize() {
1795319defdf502fc4569316473846b83180ec08035Alexandre Rames    return GetFramePreservedRegisters().TotalSizeInBytes();
1805319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
1815319defdf502fc4569316473846b83180ec08035Alexandre Rames
182de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Bind(HBasicBlock* block) OVERRIDE;
1835319defdf502fc4569316473846b83180ec08035Alexandre Rames
1845319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::Label* GetLabelOf(HBasicBlock* block) const {
1855319defdf502fc4569316473846b83180ec08035Alexandre Rames    return block_labels_ + block->GetBlockId();
1865319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
1875319defdf502fc4569316473846b83180ec08035Alexandre Rames
188de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
1895319defdf502fc4569316473846b83180ec08035Alexandre Rames
190de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  size_t GetWordSize() const OVERRIDE {
1915319defdf502fc4569316473846b83180ec08035Alexandre Rames    return kArm64WordSize;
1925319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
1935319defdf502fc4569316473846b83180ec08035Alexandre Rames
19467555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE {
19567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    vixl::Label* block_entry_label = GetLabelOf(block);
19667555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    DCHECK(block_entry_label->IsBound());
19767555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    return block_entry_label->location();
198de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  }
199de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray
200de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  size_t FrameEntrySpillSize() const OVERRIDE;
2015319defdf502fc4569316473846b83180ec08035Alexandre Rames
202de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
203de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
204de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  Arm64Assembler* GetAssembler() OVERRIDE { return &assembler_; }
20567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; }
2065319defdf502fc4569316473846b83180ec08035Alexandre Rames
2075319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Emit a write barrier.
2085319defdf502fc4569316473846b83180ec08035Alexandre Rames  void MarkGCCard(vixl::Register object, vixl::Register value);
2095319defdf502fc4569316473846b83180ec08035Alexandre Rames
2105319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Register allocation.
2115319defdf502fc4569316473846b83180ec08035Alexandre Rames
212de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void SetupBlockedRegisters() const OVERRIDE;
2135319defdf502fc4569316473846b83180ec08035Alexandre Rames  // AllocateFreeRegister() is only used when allocating registers locally
2145319defdf502fc4569316473846b83180ec08035Alexandre Rames  // during CompileBaseline().
215de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE;
2165319defdf502fc4569316473846b83180ec08035Alexandre Rames
217de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
2185319defdf502fc4569316473846b83180ec08035Alexandre Rames
2193e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id);
2203e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id);
2213e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2223e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id);
2235319defdf502fc4569316473846b83180ec08035Alexandre Rames
2245319defdf502fc4569316473846b83180ec08035Alexandre Rames  // The number of registers that can be allocated. The register allocator may
2255319defdf502fc4569316473846b83180ec08035Alexandre Rames  // decide to reserve and not use a few of them.
2265319defdf502fc4569316473846b83180ec08035Alexandre Rames  // We do not consider registers sp, xzr, wzr. They are either not allocatable
2275319defdf502fc4569316473846b83180ec08035Alexandre Rames  // (xzr, wzr), or make for poor allocatable registers (sp alignment
2285319defdf502fc4569316473846b83180ec08035Alexandre Rames  // requirements, etc.). This also facilitates our task as all other registers
2295319defdf502fc4569316473846b83180ec08035Alexandre Rames  // can easily be mapped via to or from their type and index or code.
230a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  static const int kNumberOfAllocatableRegisters = vixl::kNumberOfRegisters - 1;
231a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  static const int kNumberOfAllocatableFPRegisters = vixl::kNumberOfFPRegisters;
2325319defdf502fc4569316473846b83180ec08035Alexandre Rames  static constexpr int kNumberOfAllocatableRegisterPairs = 0;
2335319defdf502fc4569316473846b83180ec08035Alexandre Rames
234de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
235de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
2365319defdf502fc4569316473846b83180ec08035Alexandre Rames
237de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  InstructionSet GetInstructionSet() const OVERRIDE {
2385319defdf502fc4569316473846b83180ec08035Alexandre Rames    return InstructionSet::kArm64;
2395319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
2405319defdf502fc4569316473846b83180ec08035Alexandre Rames
241de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Initialize() OVERRIDE {
2425319defdf502fc4569316473846b83180ec08035Alexandre Rames    HGraph* graph = GetGraph();
2435319defdf502fc4569316473846b83180ec08035Alexandre Rames    int length = graph->GetBlocks().Size();
2445319defdf502fc4569316473846b83180ec08035Alexandre Rames    block_labels_ = graph->GetArena()->AllocArray<vixl::Label>(length);
2455319defdf502fc4569316473846b83180ec08035Alexandre Rames    for (int i = 0; i < length; ++i) {
2465319defdf502fc4569316473846b83180ec08035Alexandre Rames      new(block_labels_ + i) vixl::Label();
2475319defdf502fc4569316473846b83180ec08035Alexandre Rames    }
2485319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
2495319defdf502fc4569316473846b83180ec08035Alexandre Rames
25032f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  void Finalize(CodeAllocator* allocator) OVERRIDE;
25132f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu
252fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames  // Code generation helpers.
25367555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void MoveConstant(vixl::CPURegister destination, HConstant* constant);
2543e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  // The type is optional. When specified it must be coherent with the
2553e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  // locations, and is used for optimisation and debugging.
2563e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void MoveLocation(Location destination, Location source,
2573e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames                    Primitive::Type type = Primitive::kPrimVoid);
2583e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void SwapLocations(Location loc_1, Location loc_2);
25967555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void Load(Primitive::Type type, vixl::CPURegister dst, const vixl::MemOperand& src);
26067555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void Store(Primitive::Type type, vixl::CPURegister rt, const vixl::MemOperand& dst);
26167555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void LoadCurrentMethod(vixl::Register current_method);
26202d81cc8d162a31f0664249535456775e397b608Serban Constantinescu  void LoadAcquire(Primitive::Type type, vixl::CPURegister dst, const vixl::MemOperand& src);
26302d81cc8d162a31f0664249535456775e397b608Serban Constantinescu  void StoreRelease(Primitive::Type type, vixl::CPURegister rt, const vixl::MemOperand& dst);
26467555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames
26567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  // Generate code to invoke a runtime entry point.
26667555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void InvokeRuntime(int32_t offset, HInstruction* instruction, uint32_t dex_pc);
267fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames
2683e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  ParallelMoveResolverARM64* GetMoveResolver() { return &move_resolver_; }
269f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
270840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
271840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray    return false;
272840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  }
273840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray
2745319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
2755319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Labels for each block that will be compiled.
2765319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::Label* block_labels_;
2775319defdf502fc4569316473846b83180ec08035Alexandre Rames
2785319defdf502fc4569316473846b83180ec08035Alexandre Rames  LocationsBuilderARM64 location_builder_;
2795319defdf502fc4569316473846b83180ec08035Alexandre Rames  InstructionCodeGeneratorARM64 instruction_visitor_;
2803e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  ParallelMoveResolverARM64 move_resolver_;
2815319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler assembler_;
2825319defdf502fc4569316473846b83180ec08035Alexandre Rames
2835319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM64);
2845319defdf502fc4569316473846b83180ec08035Alexandre Rames};
2855319defdf502fc4569316473846b83180ec08035Alexandre Rames
2863e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Ramesinline Arm64Assembler* ParallelMoveResolverARM64::GetAssembler() const {
2873e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  return codegen_->GetAssembler();
2883e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames}
2893e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
2905319defdf502fc4569316473846b83180ec08035Alexandre Rames}  // namespace arm64
2915319defdf502fc4569316473846b83180ec08035Alexandre Rames}  // namespace art
2925319defdf502fc4569316473846b83180ec08035Alexandre Rames
2935319defdf502fc4569316473846b83180ec08035Alexandre Rames#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
294