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
20cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko#include "arch/arm64/quick_method_frame_info_arm64.h"
215319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "code_generator.h"
22e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle#include "common_arm64.h"
2302d81cc8d162a31f0664249535456775e397b608Serban Constantinescu#include "dex/compiler_enums.h"
24cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
255319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "nodes.h"
265319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "parallel_move_resolver.h"
275319defdf502fc4569316473846b83180ec08035Alexandre Rames#include "utils/arm64/assembler_arm64.h"
28cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko#include "utils/string_reference.h"
2982e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/disasm-a64.h"
3082e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/macro-assembler-a64.h"
315319defdf502fc4569316473846b83180ec08035Alexandre Rames
325319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace art {
335319defdf502fc4569316473846b83180ec08035Alexandre Ramesnamespace arm64 {
345319defdf502fc4569316473846b83180ec08035Alexandre Rames
355319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64;
36878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
3786a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray// Use a local definition to prevent copying mistakes.
3886a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffraystatic constexpr size_t kArm64WordSize = kArm64PointerSize;
3986a8d7afc7f00ff0f5ea7b8aaf4d50514250a4e6Nicolas Geoffray
405319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::Register kParameterCoreRegisters[] = {
415319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::x1, vixl::x2, vixl::x3, vixl::x4, vixl::x5, vixl::x6, vixl::x7
425319defdf502fc4569316473846b83180ec08035Alexandre Rames};
435319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
445319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic const vixl::FPRegister kParameterFPRegisters[] = {
455319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::d0, vixl::d1, vixl::d2, vixl::d3, vixl::d4, vixl::d5, vixl::d6, vixl::d7
465319defdf502fc4569316473846b83180ec08035Alexandre Rames};
475319defdf502fc4569316473846b83180ec08035Alexandre Ramesstatic constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters);
485319defdf502fc4569316473846b83180ec08035Alexandre Rames
499bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescuconst vixl::Register tr = vixl::x19;                        // Thread Register
50e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstatic const vixl::Register kArtMethodRegister = vixl::x0;  // Method register on invoke.
515319defdf502fc4569316473846b83180ec08035Alexandre Rames
525319defdf502fc4569316473846b83180ec08035Alexandre Ramesconst vixl::CPURegList vixl_reserved_core_registers(vixl::ip0, vixl::ip1);
53a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Ramesconst vixl::CPURegList vixl_reserved_fp_registers(vixl::d31);
545319defdf502fc4569316473846b83180ec08035Alexandre Rames
5569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xuconst vixl::CPURegList runtime_reserved_core_registers(tr, vixl::lr);
563d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu
579bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu// Callee-saved registers AAPCS64 (without x19 - Thread Register)
583d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescuconst vixl::CPURegList callee_saved_core_registers(vixl::CPURegister::kRegister,
593d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu                                                   vixl::kXRegSize,
609bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu                                                   vixl::x20.code(),
613d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu                                                   vixl::x30.code());
623d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescuconst vixl::CPURegList callee_saved_fp_registers(vixl::CPURegister::kFPRegister,
633d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu                                                 vixl::kDRegSize,
643d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu                                                 vixl::d8.code(),
653d087decd1886b818adcccd4f16802e5e54dd03eSerban Constantinescu                                                 vixl::d15.code());
66a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre RamesLocation ARM64ReturnLocation(Primitive::Type return_type);
67a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames
68878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampeclass SlowPathCodeARM64 : public SlowPathCode {
69878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe public:
709cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  explicit SlowPathCodeARM64(HInstruction* instruction)
719cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky      : SlowPathCode(instruction), entry_label_(), exit_label_() {}
72878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
73878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe  vixl::Label* GetEntryLabel() { return &entry_label_; }
74878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe  vixl::Label* GetExitLabel() { return &exit_label_; }
75878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
76da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
77da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
78da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu
79878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe private:
80878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe  vixl::Label entry_label_;
81878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe  vixl::Label exit_label_;
82878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
83878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe  DISALLOW_COPY_AND_ASSIGN(SlowPathCodeARM64);
84878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe};
85878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
86c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Ramesclass JumpTableARM64 : public DeletableArenaObject<kArenaAllocSwitchTable> {
873927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu public:
883927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  explicit JumpTableARM64(HPackedSwitch* switch_instr)
893927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu    : switch_instr_(switch_instr), table_start_() {}
903927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
913927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  vixl::Label* GetTableStartLabel() { return &table_start_; }
923927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
933927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  void EmitTable(CodeGeneratorARM64* codegen);
943927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
953927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu private:
963927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  HPackedSwitch* const switch_instr_;
973927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  vixl::Label table_start_;
983927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
993927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  DISALLOW_COPY_AND_ASSIGN(JumpTableARM64);
1003927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu};
1013927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
102d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic const vixl::Register kRuntimeParameterCoreRegisters[] =
103d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray    { vixl::x0, vixl::x1, vixl::x2, vixl::x3, vixl::x4, vixl::x5, vixl::x6, vixl::x7 };
104d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterCoreRegistersLength =
105d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray    arraysize(kRuntimeParameterCoreRegisters);
106d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic const vixl::FPRegister kRuntimeParameterFpuRegisters[] =
107d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray    { vixl::d0, vixl::d1, vixl::d2, vixl::d3, vixl::d4, vixl::d5, vixl::d6, vixl::d7 };
108d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffraystatic constexpr size_t kRuntimeParameterFpuRegistersLength =
109d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray    arraysize(kRuntimeParameterCoreRegisters);
110d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray
111d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffrayclass InvokeRuntimeCallingConvention : public CallingConvention<vixl::Register, vixl::FPRegister> {
112d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray public:
113d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray  static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
114d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray
115d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray  InvokeRuntimeCallingConvention()
116d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray      : CallingConvention(kRuntimeParameterCoreRegisters,
117d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray                          kRuntimeParameterCoreRegistersLength,
118d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray                          kRuntimeParameterFpuRegisters,
119e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                          kRuntimeParameterFpuRegistersLength,
120e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                          kArm64PointerSize) {}
121d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray
122d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray  Location GetReturnLocation(Primitive::Type return_type);
123d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray
124d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray private:
125d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
126d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray};
127d75948ac93a4a317feaf136cae78823071234ba5Nicolas Geoffray
1285319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass InvokeDexCallingConvention : public CallingConvention<vixl::Register, vixl::FPRegister> {
1295319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
1305319defdf502fc4569316473846b83180ec08035Alexandre Rames  InvokeDexCallingConvention()
1315319defdf502fc4569316473846b83180ec08035Alexandre Rames      : CallingConvention(kParameterCoreRegisters,
1325319defdf502fc4569316473846b83180ec08035Alexandre Rames                          kParameterCoreRegistersLength,
1335319defdf502fc4569316473846b83180ec08035Alexandre Rames                          kParameterFPRegisters,
134e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                          kParameterFPRegistersLength,
135e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                          kArm64PointerSize) {}
1365319defdf502fc4569316473846b83180ec08035Alexandre Rames
137fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  Location GetReturnLocation(Primitive::Type return_type) const {
138a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames    return ARM64ReturnLocation(return_type);
1395319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
1405319defdf502fc4569316473846b83180ec08035Alexandre Rames
1415319defdf502fc4569316473846b83180ec08035Alexandre Rames
1425319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
1435319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
1445319defdf502fc4569316473846b83180ec08035Alexandre Rames};
1455319defdf502fc4569316473846b83180ec08035Alexandre Rames
1462d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitorARM64 : public InvokeDexCallingConventionVisitor {
1475319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
1482d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  InvokeDexCallingConventionVisitorARM64() {}
1492d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  virtual ~InvokeDexCallingConventionVisitorARM64() {}
1505319defdf502fc4569316473846b83180ec08035Alexandre Rames
1512d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  Location GetNextLocation(Primitive::Type type) OVERRIDE;
152fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  Location GetReturnLocation(Primitive::Type return_type) const OVERRIDE {
1535319defdf502fc4569316473846b83180ec08035Alexandre Rames    return calling_convention.GetReturnLocation(return_type);
1545319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
155fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  Location GetMethodLocation() const OVERRIDE;
1565319defdf502fc4569316473846b83180ec08035Alexandre Rames
1575319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
1585319defdf502fc4569316473846b83180ec08035Alexandre Rames  InvokeDexCallingConvention calling_convention;
1592d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1602d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorARM64);
1615319defdf502fc4569316473846b83180ec08035Alexandre Rames};
1625319defdf502fc4569316473846b83180ec08035Alexandre Rames
163e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConventionARM64 : public FieldAccessCallingConvention {
164e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public:
165e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  FieldAccessCallingConventionARM64() {}
166e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
167e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetObjectLocation() const OVERRIDE {
168e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return helpers::LocationFrom(vixl::x1);
169e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
170e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFieldIndexLocation() const OVERRIDE {
171e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return helpers::LocationFrom(vixl::x0);
172e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
173e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
174e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return helpers::LocationFrom(vixl::x0);
175e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
176e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE {
177e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return Primitive::Is64BitType(type)
178e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle        ? helpers::LocationFrom(vixl::x2)
179e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle        : (is_instance
180e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle            ? helpers::LocationFrom(vixl::x2)
181e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle            : helpers::LocationFrom(vixl::x1));
182e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
183e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
184e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle    return helpers::LocationFrom(vixl::d0);
185e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  }
186e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
187e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private:
188e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionARM64);
189e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle};
190e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
19142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass InstructionCodeGeneratorARM64 : public InstructionCodeGenerator {
1925319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
1935319defdf502fc4569316473846b83180ec08035Alexandre Rames  InstructionCodeGeneratorARM64(HGraph* graph, CodeGeneratorARM64* codegen);
1945319defdf502fc4569316473846b83180ec08035Alexandre Rames
1955319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \
196de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Visit##name(H##name* instr) OVERRIDE;
197ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
198ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
199ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
2004a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko  FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
201ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
2025319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION
2035319defdf502fc4569316473846b83180ec08035Alexandre Rames
204ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  void VisitInstruction(HInstruction* instruction) OVERRIDE {
205ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames    LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
206ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames               << " (id " << instruction->GetId() << ")";
207ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  }
208ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
2095319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler* GetAssembler() const { return assembler_; }
21067555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; }
2115319defdf502fc4569316473846b83180ec08035Alexandre Rames
2125319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
21367555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path, vixl::Register class_reg);
21402164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu  void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
21567555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void HandleBinaryOp(HBinaryOperation* instr);
21644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
21707276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray  void HandleFieldSet(HInstruction* instruction,
21807276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray                      const FieldInfo& field_info,
21907276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray                      bool value_can_be_null);
22009a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames  void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
2215f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko  void HandleCondition(HCondition* instruction);
22244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
22344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Generate a heap reference load using one register `out`:
22444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
22544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //   out <- *(out + offset)
22644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
22744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // while honoring heap poisoning and/or read barriers (if any).
22844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
22944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Location `maybe_temp` is used when generating a read barrier and
23044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // shall be a register in that case; it may be an invalid location
23144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // otherwise.
23244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateReferenceLoadOneRegister(HInstruction* instruction,
23344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                        Location out,
23444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                        uint32_t offset,
23544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                        Location maybe_temp);
23644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Generate a heap reference load using two different registers
23744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // `out` and `obj`:
23844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
23944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //   out <- *(obj + offset)
24044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
24144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // while honoring heap poisoning and/or read barriers (if any).
24244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
24344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Location `maybe_temp` is used when generating a Baker's (fast
24444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // path) read barrier and shall be a register in that case; it may
24544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // be an invalid location otherwise.
24644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateReferenceLoadTwoRegisters(HInstruction* instruction,
24744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                         Location out,
24844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                         Location obj,
24944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                         uint32_t offset,
25044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                         Location maybe_temp);
25144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Generate a GC root reference load:
25244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
25344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //   root <- *(obj + offset)
25444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  //
25544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // while honoring read barriers (if any).
25644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateGcRootFieldLoad(HInstruction* instruction,
25744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               Location root,
25844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               vixl::Register obj,
259cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                               uint32_t offset,
260cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                               vixl::Label* fixup_label = nullptr);
26144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
2621a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain  // Generate a floating-point comparison.
2631a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain  void GenerateFcmp(HInstruction* instruction);
2641a65388f1d86bb232c2e44fecb44cebe13105d2eRoland Levillain
26502164b352a1474c616771582ca9a73a2cc514c1fSerban Constantinescu  void HandleShift(HBinaryOperation* instr);
266d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang  void GenerateTestAndBranch(HInstruction* instruction,
2670debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil                             size_t condition_input_index,
268d43b3ac88cd46b8815890188c9c2b9a3f1564648Mingyao Yang                             vixl::Label* true_target,
2690debae7bc89eb05f7a2bf7dccd223318fad7c88dDavid Brazdil                             vixl::Label* false_target);
270c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  void DivRemOneOrMinusOne(HBinaryOperation* instruction);
271c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  void DivRemByPowerOfTwo(HBinaryOperation* instruction);
272c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
273c66671076b12a0ee8b9d1ae782732cc91beacb73Zheng Xu  void GenerateDivRemIntegral(HBinaryOperation* instruction);
274fc6a86ab2b70781e72b807c1798b83829ca7f931David Brazdil  void HandleGoto(HInstruction* got, HBasicBlock* successor);
2755319defdf502fc4569316473846b83180ec08035Alexandre Rames
2765319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler* const assembler_;
2775319defdf502fc4569316473846b83180ec08035Alexandre Rames  CodeGeneratorARM64* const codegen_;
2785319defdf502fc4569316473846b83180ec08035Alexandre Rames
2795319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARM64);
2805319defdf502fc4569316473846b83180ec08035Alexandre Rames};
2815319defdf502fc4569316473846b83180ec08035Alexandre Rames
2825319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass LocationsBuilderARM64 : public HGraphVisitor {
2835319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
2843887c468d731420e929e6ad3acf190d5431e94fcRoland Levillain  LocationsBuilderARM64(HGraph* graph, CodeGeneratorARM64* codegen)
2855319defdf502fc4569316473846b83180ec08035Alexandre Rames      : HGraphVisitor(graph), codegen_(codegen) {}
2865319defdf502fc4569316473846b83180ec08035Alexandre Rames
2875319defdf502fc4569316473846b83180ec08035Alexandre Rames#define DECLARE_VISIT_INSTRUCTION(name, super) \
288de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Visit##name(H##name* instr) OVERRIDE;
289ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
290ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION)
291ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
2924a0dad67867f389e01a5a6c0fe381d210f687c0dArtem Udovichenko  FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
293ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
2945319defdf502fc4569316473846b83180ec08035Alexandre Rames#undef DECLARE_VISIT_INSTRUCTION
2955319defdf502fc4569316473846b83180ec08035Alexandre Rames
296ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  void VisitInstruction(HInstruction* instruction) OVERRIDE {
297ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames    LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
298ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames               << " (id " << instruction->GetId() << ")";
299ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames  }
300ef20f71e16f035a39a329c8524d7e59ca6a11f04Alexandre Rames
3015319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
30267555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void HandleBinaryOp(HBinaryOperation* instr);
30309a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames  void HandleFieldSet(HInstruction* instruction);
30409a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames  void HandleFieldGet(HInstruction* instruction);
3055319defdf502fc4569316473846b83180ec08035Alexandre Rames  void HandleInvoke(HInvoke* instr);
3065f7b58ea1adfc0639dd605b65f59198d3763f801Vladimir Marko  void HandleCondition(HCondition* instruction);
30709a99965bb27649f5b1d373f76bfbec6a2500c9eAlexandre Rames  void HandleShift(HBinaryOperation* instr);
3085319defdf502fc4569316473846b83180ec08035Alexandre Rames
3095319defdf502fc4569316473846b83180ec08035Alexandre Rames  CodeGeneratorARM64* const codegen_;
3102d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  InvokeDexCallingConventionVisitorARM64 parameter_visitor_;
3115319defdf502fc4569316473846b83180ec08035Alexandre Rames
3125319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM64);
3135319defdf502fc4569316473846b83180ec08035Alexandre Rames};
3145319defdf502fc4569316473846b83180ec08035Alexandre Rames
315ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xuclass ParallelMoveResolverARM64 : public ParallelMoveResolverNoSwap {
3163e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames public:
3173e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  ParallelMoveResolverARM64(ArenaAllocator* allocator, CodeGeneratorARM64* codegen)
318ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu      : ParallelMoveResolverNoSwap(allocator), codegen_(codegen), vixl_temps_() {}
3193e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
320ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu protected:
321ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu  void PrepareForEmitNativeCode() OVERRIDE;
322ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu  void FinishEmitNativeCode() OVERRIDE;
323ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu  Location AllocateScratchLocationFor(Location::Kind kind) OVERRIDE;
324ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu  void FreeScratchLocation(Location loc) OVERRIDE;
3253e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  void EmitMove(size_t index) OVERRIDE;
3263e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
3273e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames private:
3283e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  Arm64Assembler* GetAssembler() const;
3293e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() const {
3303e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames    return GetAssembler()->vixl_masm_;
3313e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  }
3323e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
3333e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  CodeGeneratorARM64* const codegen_;
334ad4450e5c3ffaa9566216cc6fafbf5c11186c467Zheng Xu  vixl::UseScratchRegisterScope vixl_temps_;
3353e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
3363e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARM64);
3373e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames};
3383e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
3395319defdf502fc4569316473846b83180ec08035Alexandre Ramesclass CodeGeneratorARM64 : public CodeGenerator {
3405319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
341579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu  CodeGeneratorARM64(HGraph* graph,
342579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu                     const Arm64InstructionSetFeatures& isa_features,
343ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                     const CompilerOptions& compiler_options,
344ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                     OptimizingCompilerStats* stats = nullptr);
345de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual ~CodeGeneratorARM64() {}
3465319defdf502fc4569316473846b83180ec08035Alexandre Rames
347de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void GenerateFrameEntry() OVERRIDE;
348de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void GenerateFrameExit() OVERRIDE;
3495319defdf502fc4569316473846b83180ec08035Alexandre Rames
350da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  vixl::CPURegList GetFramePreservedCoreRegisters() const;
351da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  vixl::CPURegList GetFramePreservedFPRegisters() const;
3525319defdf502fc4569316473846b83180ec08035Alexandre Rames
353de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Bind(HBasicBlock* block) OVERRIDE;
3545319defdf502fc4569316473846b83180ec08035Alexandre Rames
355c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  vixl::Label* GetLabelOf(HBasicBlock* block) {
356c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    block = FirstNonEmptyBlock(block);
357c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    return &(block_labels_[block->GetBlockId()]);
3585319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
3595319defdf502fc4569316473846b83180ec08035Alexandre Rames
360de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  size_t GetWordSize() const OVERRIDE {
3615319defdf502fc4569316473846b83180ec08035Alexandre Rames    return kArm64WordSize;
3625319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
3635319defdf502fc4569316473846b83180ec08035Alexandre Rames
364f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  size_t GetFloatingPointSpillSlotSize() const OVERRIDE {
365f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell    // Allocated in D registers, which are word sized.
366f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell    return kArm64WordSize;
367f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  }
368f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell
369c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE {
37067555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    vixl::Label* block_entry_label = GetLabelOf(block);
37167555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    DCHECK(block_entry_label->IsBound());
37267555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames    return block_entry_label->location();
373de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  }
374de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray
375de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; }
376de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; }
377de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  Arm64Assembler* GetAssembler() OVERRIDE { return &assembler_; }
378eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  const Arm64Assembler& GetAssembler() const OVERRIDE { return assembler_; }
37967555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; }
3805319defdf502fc4569316473846b83180ec08035Alexandre Rames
3815319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Emit a write barrier.
38207276db28d654594e0e86e9e467cad393f752e6eNicolas Geoffray  void MarkGCCard(vixl::Register object, vixl::Register value, bool value_can_be_null);
3835319defdf502fc4569316473846b83180ec08035Alexandre Rames
38444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateMemoryBarrier(MemBarrierKind kind);
38544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
3865319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Register allocation.
3875319defdf502fc4569316473846b83180ec08035Alexandre Rames
38858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  void SetupBlockedRegisters() const OVERRIDE;
3895319defdf502fc4569316473846b83180ec08035Alexandre Rames
390da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
391da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
392da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
393da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
3945319defdf502fc4569316473846b83180ec08035Alexandre Rames
3955319defdf502fc4569316473846b83180ec08035Alexandre Rames  // The number of registers that can be allocated. The register allocator may
3965319defdf502fc4569316473846b83180ec08035Alexandre Rames  // decide to reserve and not use a few of them.
3975319defdf502fc4569316473846b83180ec08035Alexandre Rames  // We do not consider registers sp, xzr, wzr. They are either not allocatable
3985319defdf502fc4569316473846b83180ec08035Alexandre Rames  // (xzr, wzr), or make for poor allocatable registers (sp alignment
3995319defdf502fc4569316473846b83180ec08035Alexandre Rames  // requirements, etc.). This also facilitates our task as all other registers
4005319defdf502fc4569316473846b83180ec08035Alexandre Rames  // can easily be mapped via to or from their type and index or code.
401a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  static const int kNumberOfAllocatableRegisters = vixl::kNumberOfRegisters - 1;
402a89086e3be94fb262c4c4feb15241b30616c3b8fAlexandre Rames  static const int kNumberOfAllocatableFPRegisters = vixl::kNumberOfFPRegisters;
4035319defdf502fc4569316473846b83180ec08035Alexandre Rames  static constexpr int kNumberOfAllocatableRegisterPairs = 0;
4045319defdf502fc4569316473846b83180ec08035Alexandre Rames
405de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
406de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
4075319defdf502fc4569316473846b83180ec08035Alexandre Rames
408de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  InstructionSet GetInstructionSet() const OVERRIDE {
4095319defdf502fc4569316473846b83180ec08035Alexandre Rames    return InstructionSet::kArm64;
4105319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
4115319defdf502fc4569316473846b83180ec08035Alexandre Rames
412579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu  const Arm64InstructionSetFeatures& GetInstructionSetFeatures() const {
413579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu    return isa_features_;
414579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu  }
415579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu
416de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  void Initialize() OVERRIDE {
417c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    block_labels_.resize(GetGraph()->GetBlocks().size());
4185319defdf502fc4569316473846b83180ec08035Alexandre Rames  }
4195319defdf502fc4569316473846b83180ec08035Alexandre Rames
420c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  JumpTableARM64* CreateJumpTable(HPackedSwitch* switch_instr) {
421c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    jump_tables_.emplace_back(new (GetGraph()->GetArena()) JumpTableARM64(switch_instr));
422c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    return jump_tables_.back().get();
4233927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  }
4243927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
42532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  void Finalize(CodeAllocator* allocator) OVERRIDE;
42632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu
427fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames  // Code generation helpers.
42867555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void MoveConstant(vixl::CPURegister destination, HConstant* constant);
429175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void MoveConstant(Location destination, int32_t value) OVERRIDE;
430e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
431e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
432e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
43367555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  void Load(Primitive::Type type, vixl::CPURegister dst, const vixl::MemOperand& src);
43444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void Store(Primitive::Type type, vixl::CPURegister src, const vixl::MemOperand& dst);
43544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void LoadAcquire(HInstruction* instruction,
43644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                   vixl::CPURegister dst,
43744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                   const vixl::MemOperand& src,
43844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                   bool needs_null_check);
43944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void StoreRelease(Primitive::Type type, vixl::CPURegister src, const vixl::MemOperand& dst);
44067555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames
44167555f7e9a05a9d436e034f67ae683bbf02d072dAlexandre Rames  // Generate code to invoke a runtime entry point.
442175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void InvokeRuntime(QuickEntrypointEnum entrypoint,
443175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     HInstruction* instruction,
444175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     uint32_t dex_pc,
445175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                     SlowPathCode* slow_path) OVERRIDE;
446175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
447eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  void InvokeRuntime(int32_t offset,
448eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray                     HInstruction* instruction,
449eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray                     uint32_t dex_pc,
450eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray                     SlowPathCode* slow_path);
451fc19de8b201475231751b9df08fce01a093e5c2bAlexandre Rames
452e6dbf48d7a549e58a3d798bbbdc391e4d091b432Alexandre Rames  ParallelMoveResolverARM64* GetMoveResolver() OVERRIDE { return &move_resolver_; }
453f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
454840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE {
455840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray    return false;
456840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  }
457840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray
458cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Check if the desired_string_load_kind is supported. If it is, return it,
459cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // otherwise return a fall-back kind that should be used instead.
460cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  HLoadString::LoadKind GetSupportedLoadStringKind(
461cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      HLoadString::LoadKind desired_string_load_kind) OVERRIDE;
462cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
463dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // Check if the desired_dispatch_info is supported. If it is, return it,
464dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // otherwise return a fall-back info that should be used instead.
465dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
466dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
467dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      MethodReference target_method) OVERRIDE;
468dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko
46985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE;
47085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE;
47185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
47285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,
47385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe                              Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE {
47485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    UNIMPLEMENTED(FATAL);
47585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
476878d58cbaf6b17a9e3dcab790754527f3ebc69e5Andreas Gampe
477cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Add a new PC-relative string patch for an instruction and return the label
478cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // to be bound before the instruction. The instruction will be either the
479cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
480cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // to the associated ADRP patch label).
481cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Label* NewPcRelativeStringPatch(const DexFile& dex_file,
482cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                        uint32_t string_index,
483cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                        vixl::Label* adrp_label = nullptr);
484cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
485cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Add a new PC-relative dex cache array patch for an instruction and return
486cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // the label to be bound before the instruction. The instruction will be
487cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // either the ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label`
488cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // pointing to the associated ADRP patch label).
489cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
490cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                               uint32_t element_offset,
491cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                               vixl::Label* adrp_label = nullptr);
492cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
493cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Literal<uint32_t>* DeduplicateBootImageStringLiteral(const DexFile& dex_file,
494cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                                             uint32_t string_index);
495cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Literal<uint32_t>* DeduplicateBootImageAddressLiteral(uint64_t address);
496cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Literal<uint64_t>* DeduplicateDexCacheAddressLiteral(uint64_t address);
497cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
498581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
499581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
50044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Fast path implementation of ReadBarrier::Barrier for a heap
50144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // reference field load when Baker's read barriers are used.
50244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
50344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             Location ref,
50444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             vixl::Register obj,
50544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             uint32_t offset,
50644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             vixl::Register temp,
50744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             bool needs_null_check,
50844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             bool use_load_acquire);
50944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Fast path implementation of ReadBarrier::Barrier for a heap
51044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // reference array load when Baker's read barriers are used.
51144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction,
51244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             Location ref,
51344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             vixl::Register obj,
51444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             uint32_t data_offset,
51544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             Location index,
51644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             vixl::Register temp,
51744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                             bool needs_null_check);
51844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
51944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Generate a read barrier for a heap reference within `instruction`
52044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // using a slow path.
52122ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
52222ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // A read barrier for an object reference read from the heap is
52322ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // implemented as a call to the artReadBarrierSlow runtime entry
52422ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // point, which is passed the values in locations `ref`, `obj`, and
52522ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // `offset`:
52622ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
52722ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //   mirror::Object* artReadBarrierSlow(mirror::Object* ref,
52822ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //                                      mirror::Object* obj,
52922ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //                                      uint32_t offset);
53022ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
53122ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // The `out` location contains the value returned by
53222ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // artReadBarrierSlow.
53322ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
53422ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // When `index` is provided (i.e. for array accesses), the offset
53522ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // value passed to artReadBarrierSlow is adjusted to take `index`
53622ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // into account.
53744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateReadBarrierSlow(HInstruction* instruction,
53844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               Location out,
53944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               Location ref,
54044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               Location obj,
54144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               uint32_t offset,
54244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                               Location index = Location::NoLocation());
54344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
54444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // If read barriers are enabled, generate a read barrier for a heap
54544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // reference using a slow path. If heap poisoning is enabled, also
54644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // unpoison the reference in `out`.
54744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
54844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                    Location out,
54944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                    Location ref,
55044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                    Location obj,
55144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                    uint32_t offset,
55244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                    Location index = Location::NoLocation());
55344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
55444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Generate a read barrier for a GC root within `instruction` using
55544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // a slow path.
55622ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
55722ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // A read barrier for an object reference GC root is implemented as
55822ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // a call to the artReadBarrierForRootSlow runtime entry point,
55922ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // which is passed the value in location `root`:
56022ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
56122ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //   mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root);
56222ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  //
56322ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // The `out` location contains the value returned by
56422ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain  // artReadBarrierForRootSlow.
56544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
56622ccc3a93d32fa6991535eaebb17daf5abaf4ebfRoland Levillain
567c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky  void GenerateNop();
568c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky
5692ae48182573da7087bffc2873730bc758ec29696Calin Juravle  void GenerateImplicitNullCheck(HNullCheck* instruction);
5702ae48182573da7087bffc2873730bc758ec29696Calin Juravle  void GenerateExplicitNullCheck(HNullCheck* instruction);
5712ae48182573da7087bffc2873730bc758ec29696Calin Juravle
5725319defdf502fc4569316473846b83180ec08035Alexandre Rames private:
57344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // Factored implementation of GenerateFieldLoadWithBakerReadBarrier
57444015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  // and GenerateArrayLoadWithBakerReadBarrier.
57544015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain  void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction,
57644015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 Location ref,
57744015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 vixl::Register obj,
57844015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 uint32_t offset,
57944015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 Location index,
58044015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 vixl::Register temp,
58144015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 bool needs_null_check,
58244015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain                                                 bool use_load_acquire);
58344015868a5ed9f6915d510ade42e84949b719e3aRoland Levillain
584581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  using Uint64ToLiteralMap = ArenaSafeMap<uint64_t, vixl::Literal<uint64_t>*>;
585cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  using Uint32ToLiteralMap = ArenaSafeMap<uint32_t, vixl::Literal<uint32_t>*>;
586581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  using MethodToLiteralMap = ArenaSafeMap<MethodReference,
587581550137ee3a068a14224870e71aeee924a0646Vladimir Marko                                          vixl::Literal<uint64_t>*,
588581550137ee3a068a14224870e71aeee924a0646Vladimir Marko                                          MethodReferenceComparator>;
589cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  using BootStringToLiteralMap = ArenaSafeMap<StringReference,
590cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                              vixl::Literal<uint32_t>*,
591cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                              StringReferenceValueComparator>;
592581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
593cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Literal<uint32_t>* DeduplicateUint32Literal(uint32_t value, Uint32ToLiteralMap* map);
594581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  vixl::Literal<uint64_t>* DeduplicateUint64Literal(uint64_t value);
595581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  vixl::Literal<uint64_t>* DeduplicateMethodLiteral(MethodReference target_method,
596581550137ee3a068a14224870e71aeee924a0646Vladimir Marko                                                    MethodToLiteralMap* map);
597581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  vixl::Literal<uint64_t>* DeduplicateMethodAddressLiteral(MethodReference target_method);
598581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  vixl::Literal<uint64_t>* DeduplicateMethodCodeLiteral(MethodReference target_method);
599581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
600cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays
601cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // and boot image strings. The only difference is the interpretation of the offset_or_index.
602cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  struct PcRelativePatchInfo {
603cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    PcRelativePatchInfo(const DexFile& dex_file, uint32_t off_or_idx)
604cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko        : target_dex_file(dex_file), offset_or_index(off_or_idx), label(), pc_insn_label() { }
605581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
606581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    const DexFile& target_dex_file;
607cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    // Either the dex cache array element offset or the string index.
608cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    uint32_t offset_or_index;
609581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    vixl::Label label;
610581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    vixl::Label* pc_insn_label;
611581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  };
612581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
613cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  vixl::Label* NewPcRelativePatch(const DexFile& dex_file,
614cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                  uint32_t offset_or_index,
615cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                  vixl::Label* adrp_label,
616cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                  ArenaDeque<PcRelativePatchInfo>* patches);
617cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
6183927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu  void EmitJumpTables();
6193927c8b8361336f1b16aae6eb2ed7577b20560f4Zheng Xu
6205319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Labels for each block that will be compiled.
621c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  // We use a deque so that the `vixl::Label` objects do not move in memory.
622c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  ArenaDeque<vixl::Label> block_labels_;  // Indexed by block id.
6231cf95287364948689f6a1a320567acd7728e94a3Nicolas Geoffray  vixl::Label frame_entry_label_;
624c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  ArenaVector<std::unique_ptr<JumpTableARM64>> jump_tables_;
6255319defdf502fc4569316473846b83180ec08035Alexandre Rames
6265319defdf502fc4569316473846b83180ec08035Alexandre Rames  LocationsBuilderARM64 location_builder_;
6275319defdf502fc4569316473846b83180ec08035Alexandre Rames  InstructionCodeGeneratorARM64 instruction_visitor_;
6283e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  ParallelMoveResolverARM64 move_resolver_;
6295319defdf502fc4569316473846b83180ec08035Alexandre Rames  Arm64Assembler assembler_;
630579885a26d761f5ba9550f2a1cd7f0f598c2e1e3Serban Constantinescu  const Arm64InstructionSetFeatures& isa_features_;
6315319defdf502fc4569316473846b83180ec08035Alexandre Rames
632cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
633cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Uint32ToLiteralMap uint32_literals_;
634cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Deduplication map for 64-bit literals, used for non-patchable method address, method code
635cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // or string dex cache address.
636581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  Uint64ToLiteralMap uint64_literals_;
637581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // Method patch info, map MethodReference to a literal for method address and method code.
638581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  MethodToLiteralMap method_patches_;
639581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  MethodToLiteralMap call_patches_;
640581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // Relative call patch info.
641581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // Using ArenaDeque<> which retains element addresses on push/emplace_back().
642581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  ArenaDeque<MethodPatchInfo<vixl::Label>> relative_call_patches_;
643581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // PC-relative DexCache access info.
644cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ArenaDeque<PcRelativePatchInfo> pc_relative_dex_cache_patches_;
645cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Deduplication map for boot string literals for kBootImageLinkTimeAddress.
646cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  BootStringToLiteralMap boot_image_string_patches_;
647cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // PC-relative String patch info.
648cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ArenaDeque<PcRelativePatchInfo> pc_relative_string_patches_;
649cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Deduplication map for patchable boot image addresses.
650cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Uint32ToLiteralMap boot_image_address_patches_;
651581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
6525319defdf502fc4569316473846b83180ec08035Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM64);
6535319defdf502fc4569316473846b83180ec08035Alexandre Rames};
6545319defdf502fc4569316473846b83180ec08035Alexandre Rames
6553e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Ramesinline Arm64Assembler* ParallelMoveResolverARM64::GetAssembler() const {
6563e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames  return codegen_->GetAssembler();
6573e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames}
6583e69f16ae3fddfd24f4f0e29deb106d564ab296cAlexandre Rames
6595319defdf502fc4569316473846b83180ec08035Alexandre Rames}  // namespace arm64
6605319defdf502fc4569316473846b83180ec08035Alexandre Rames}  // namespace art
6615319defdf502fc4569316473846b83180ec08035Alexandre Rames
6625319defdf502fc4569316473846b83180ec08035Alexandre Rames#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
663