xref: /aosp_15_r20/art/compiler/optimizing/code_generator_arm64.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/bit_field.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
22*795d594fSAndroid Build Coastguard Worker #include "class_root.h"
23*795d594fSAndroid Build Coastguard Worker #include "code_generator.h"
24*795d594fSAndroid Build Coastguard Worker #include "common_arm64.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
26*795d594fSAndroid Build Coastguard Worker #include "dex/string_reference.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex/type_reference.h"
28*795d594fSAndroid Build Coastguard Worker #include "driver/compiler_options.h"
29*795d594fSAndroid Build Coastguard Worker #include "jit_patches_arm64.h"
30*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
31*795d594fSAndroid Build Coastguard Worker #include "parallel_move_resolver.h"
32*795d594fSAndroid Build Coastguard Worker #include "utils/arm64/assembler_arm64.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker // TODO(VIXL): Make VIXL compile cleanly with -Wshadow, -Wdeprecated-declarations.
35*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic push
36*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wshadow"
37*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
38*795d594fSAndroid Build Coastguard Worker #include "aarch64/disasm-aarch64.h"
39*795d594fSAndroid Build Coastguard Worker #include "aarch64/macro-assembler-aarch64.h"
40*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker namespace linker {
45*795d594fSAndroid Build Coastguard Worker class Arm64RelativePatcherTest;
46*795d594fSAndroid Build Coastguard Worker }  // namespace linker
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker namespace arm64 {
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker class CodeGeneratorARM64;
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker // Use a local definition to prevent copying mistakes.
53*795d594fSAndroid Build Coastguard Worker static constexpr size_t kArm64WordSize = static_cast<size_t>(kArm64PointerSize);
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker // This constant is used as an approximate margin when emission of veneer and literal pools
56*795d594fSAndroid Build Coastguard Worker // must be blocked.
57*795d594fSAndroid Build Coastguard Worker static constexpr int kMaxMacroInstructionSizeInBytes = 15 * vixl::aarch64::kInstructionSize;
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker // Reference load (except object array loads) is using LDR Wt, [Xn, #offset] which can handle
60*795d594fSAndroid Build Coastguard Worker // offset < 16KiB. For offsets >= 16KiB, the load shall be emitted as two or more instructions.
61*795d594fSAndroid Build Coastguard Worker // For the Baker read barrier implementation using link-time generated thunks we need to split
62*795d594fSAndroid Build Coastguard Worker // the offset explicitly.
63*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kReferenceLoadMinFarOffset = 16 * KB;
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker static const vixl::aarch64::Register kParameterCoreRegisters[] = {
66*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x1,
67*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x2,
68*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x3,
69*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x4,
70*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x5,
71*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x6,
72*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x7
73*795d594fSAndroid Build Coastguard Worker };
74*795d594fSAndroid Build Coastguard Worker static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
75*795d594fSAndroid Build Coastguard Worker static const vixl::aarch64::VRegister kParameterFPRegisters[] = {
76*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d0,
77*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d1,
78*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d2,
79*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d3,
80*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d4,
81*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d5,
82*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d6,
83*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d7
84*795d594fSAndroid Build Coastguard Worker };
85*795d594fSAndroid Build Coastguard Worker static constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters);
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker // Thread Register.
88*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::Register tr = vixl::aarch64::x19;
89*795d594fSAndroid Build Coastguard Worker // Marking Register.
90*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::Register mr = vixl::aarch64::x20;
91*795d594fSAndroid Build Coastguard Worker // Implicit suspend check register.
92*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::Register kImplicitSuspendCheckRegister = vixl::aarch64::x21;
93*795d594fSAndroid Build Coastguard Worker // Method register on invoke.
94*795d594fSAndroid Build Coastguard Worker static const vixl::aarch64::Register kArtMethodRegister = vixl::aarch64::x0;
95*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::CPURegList vixl_reserved_core_registers(vixl::aarch64::ip0,
96*795d594fSAndroid Build Coastguard Worker                                                              vixl::aarch64::ip1);
97*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::CPURegList vixl_reserved_fp_registers(vixl::aarch64::d31);
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::CPURegList runtime_reserved_core_registers =
100*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::CPURegList(
101*795d594fSAndroid Build Coastguard Worker         tr,
102*795d594fSAndroid Build Coastguard Worker         // Reserve X20 as Marking Register when emitting Baker read barriers.
103*795d594fSAndroid Build Coastguard Worker         // TODO: We don't need to reserve marking-register for userfaultfd GC. But
104*795d594fSAndroid Build Coastguard Worker         // that would require some work in the assembler code as the right GC is
105*795d594fSAndroid Build Coastguard Worker         // chosen at load-time and not compile time.
106*795d594fSAndroid Build Coastguard Worker         (kReserveMarkingRegister ? mr : vixl::aarch64::NoCPUReg),
107*795d594fSAndroid Build Coastguard Worker         kImplicitSuspendCheckRegister,
108*795d594fSAndroid Build Coastguard Worker         vixl::aarch64::lr);
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker // Some instructions have special requirements for a temporary, for example
111*795d594fSAndroid Build Coastguard Worker // LoadClass/kBssEntry and LoadString/kBssEntry for Baker read barrier require
112*795d594fSAndroid Build Coastguard Worker // temp that's not an R0 (to avoid an extra move) and Baker read barrier field
113*795d594fSAndroid Build Coastguard Worker // loads with large offsets need a fixed register to limit the number of link-time
114*795d594fSAndroid Build Coastguard Worker // thunks we generate. For these and similar cases, we want to reserve a specific
115*795d594fSAndroid Build Coastguard Worker // register that's neither callee-save nor an argument register. We choose x15.
FixedTempLocation()116*795d594fSAndroid Build Coastguard Worker inline Location FixedTempLocation() {
117*795d594fSAndroid Build Coastguard Worker   return Location::RegisterLocation(vixl::aarch64::x15.GetCode());
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker // Callee-save registers AAPCS64, without x19 (Thread Register) (nor
121*795d594fSAndroid Build Coastguard Worker // x20 (Marking Register) when emitting Baker read barriers).
122*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::CPURegList callee_saved_core_registers(
123*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::CPURegister::kRegister,
124*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::kXRegSize,
125*795d594fSAndroid Build Coastguard Worker     (kReserveMarkingRegister ? vixl::aarch64::x21.GetCode() : vixl::aarch64::x20.GetCode()),
126*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x30.GetCode());
127*795d594fSAndroid Build Coastguard Worker const vixl::aarch64::CPURegList callee_saved_fp_registers(vixl::aarch64::CPURegister::kVRegister,
128*795d594fSAndroid Build Coastguard Worker                                                           vixl::aarch64::kDRegSize,
129*795d594fSAndroid Build Coastguard Worker                                                           vixl::aarch64::d8.GetCode(),
130*795d594fSAndroid Build Coastguard Worker                                                           vixl::aarch64::d15.GetCode());
131*795d594fSAndroid Build Coastguard Worker Location ARM64ReturnLocation(DataType::Type return_type);
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker vixl::aarch64::Condition ARM64PCondition(HVecPredToBoolean::PCondKind cond);
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker #define UNIMPLEMENTED_INTRINSIC_LIST_ARM64(V) \
136*795d594fSAndroid Build Coastguard Worker   V(MathSignumFloat)                          \
137*795d594fSAndroid Build Coastguard Worker   V(MathSignumDouble)                         \
138*795d594fSAndroid Build Coastguard Worker   V(MathCopySignFloat)                        \
139*795d594fSAndroid Build Coastguard Worker   V(MathCopySignDouble)                       \
140*795d594fSAndroid Build Coastguard Worker   V(IntegerRemainderUnsigned)                 \
141*795d594fSAndroid Build Coastguard Worker   V(LongRemainderUnsigned)                    \
142*795d594fSAndroid Build Coastguard Worker   V(StringStringIndexOf)                      \
143*795d594fSAndroid Build Coastguard Worker   V(StringStringIndexOfAfter)                 \
144*795d594fSAndroid Build Coastguard Worker   V(StringBufferAppend)                       \
145*795d594fSAndroid Build Coastguard Worker   V(StringBufferLength)                       \
146*795d594fSAndroid Build Coastguard Worker   V(StringBufferToString)                     \
147*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendObject)                \
148*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendString)                \
149*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendCharSequence)          \
150*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendCharArray)             \
151*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendBoolean)               \
152*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendChar)                  \
153*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendInt)                   \
154*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendLong)                  \
155*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendFloat)                 \
156*795d594fSAndroid Build Coastguard Worker   V(StringBuilderAppendDouble)                \
157*795d594fSAndroid Build Coastguard Worker   V(StringBuilderLength)                      \
158*795d594fSAndroid Build Coastguard Worker   V(StringBuilderToString)                    \
159*795d594fSAndroid Build Coastguard Worker   V(SystemArrayCopyByte)                      \
160*795d594fSAndroid Build Coastguard Worker   V(SystemArrayCopyInt)                       \
161*795d594fSAndroid Build Coastguard Worker   V(UnsafeArrayBaseOffset)                    \
162*795d594fSAndroid Build Coastguard Worker   /* 1.8 */                                   \
163*795d594fSAndroid Build Coastguard Worker   V(MethodHandleInvoke)                       \
164*795d594fSAndroid Build Coastguard Worker   /* OpenJDK 11 */                            \
165*795d594fSAndroid Build Coastguard Worker   V(JdkUnsafeArrayBaseOffset)
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker class SlowPathCodeARM64 : public SlowPathCode {
168*795d594fSAndroid Build Coastguard Worker  public:
SlowPathCodeARM64(HInstruction * instruction)169*795d594fSAndroid Build Coastguard Worker   explicit SlowPathCodeARM64(HInstruction* instruction)
170*795d594fSAndroid Build Coastguard Worker       : SlowPathCode(instruction), entry_label_(), exit_label_() {}
171*795d594fSAndroid Build Coastguard Worker 
GetEntryLabel()172*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* GetEntryLabel() { return &entry_label_; }
GetExitLabel()173*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* GetExitLabel() { return &exit_label_; }
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker   void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) override;
176*795d594fSAndroid Build Coastguard Worker   void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) override;
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker  private:
179*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label entry_label_;
180*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label exit_label_;
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SlowPathCodeARM64);
183*795d594fSAndroid Build Coastguard Worker };
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker class JumpTableARM64 : public DeletableArenaObject<kArenaAllocSwitchTable> {
186*795d594fSAndroid Build Coastguard Worker  public:
187*795d594fSAndroid Build Coastguard Worker   using VIXLInt32Literal = vixl::aarch64::Literal<int32_t>;
188*795d594fSAndroid Build Coastguard Worker 
JumpTableARM64(HPackedSwitch * switch_instr)189*795d594fSAndroid Build Coastguard Worker   explicit JumpTableARM64(HPackedSwitch* switch_instr)
190*795d594fSAndroid Build Coastguard Worker       : switch_instr_(switch_instr),
191*795d594fSAndroid Build Coastguard Worker         table_start_(),
192*795d594fSAndroid Build Coastguard Worker         jump_targets_(switch_instr->GetAllocator()->Adapter(kArenaAllocCodeGenerator)) {
193*795d594fSAndroid Build Coastguard Worker       uint32_t num_entries = switch_instr_->GetNumEntries();
194*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i < num_entries; i++) {
195*795d594fSAndroid Build Coastguard Worker         VIXLInt32Literal* lit = new VIXLInt32Literal(0);
196*795d594fSAndroid Build Coastguard Worker         jump_targets_.emplace_back(lit);
197*795d594fSAndroid Build Coastguard Worker       }
198*795d594fSAndroid Build Coastguard Worker     }
199*795d594fSAndroid Build Coastguard Worker 
GetTableStartLabel()200*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* GetTableStartLabel() { return &table_start_; }
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   // Emits the jump table into the code buffer; jump target offsets are not yet known.
203*795d594fSAndroid Build Coastguard Worker   void EmitTable(CodeGeneratorARM64* codegen);
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   // Updates the offsets in the jump table, to be used when the jump targets basic blocks
206*795d594fSAndroid Build Coastguard Worker   // addresses are resolved.
207*795d594fSAndroid Build Coastguard Worker   void FixTable(CodeGeneratorARM64* codegen);
208*795d594fSAndroid Build Coastguard Worker 
209*795d594fSAndroid Build Coastguard Worker  private:
210*795d594fSAndroid Build Coastguard Worker   HPackedSwitch* const switch_instr_;
211*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label table_start_;
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker   // Contains literals for the switch's jump targets.
214*795d594fSAndroid Build Coastguard Worker   ArenaVector<std::unique_ptr<VIXLInt32Literal>> jump_targets_;
215*795d594fSAndroid Build Coastguard Worker 
216*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(JumpTableARM64);
217*795d594fSAndroid Build Coastguard Worker };
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker static const vixl::aarch64::Register kRuntimeParameterCoreRegisters[] = {
220*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x0,
221*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x1,
222*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x2,
223*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x3,
224*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x4,
225*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x5,
226*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x6,
227*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::x7
228*795d594fSAndroid Build Coastguard Worker };
229*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRuntimeParameterCoreRegistersLength =
230*795d594fSAndroid Build Coastguard Worker     arraysize(kRuntimeParameterCoreRegisters);
231*795d594fSAndroid Build Coastguard Worker static const vixl::aarch64::VRegister kRuntimeParameterFpuRegisters[] = {
232*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d0,
233*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d1,
234*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d2,
235*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d3,
236*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d4,
237*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d5,
238*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d6,
239*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::d7
240*795d594fSAndroid Build Coastguard Worker };
241*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRuntimeParameterFpuRegistersLength =
242*795d594fSAndroid Build Coastguard Worker     arraysize(kRuntimeParameterCoreRegisters);
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker class InvokeRuntimeCallingConvention : public CallingConvention<vixl::aarch64::Register,
245*795d594fSAndroid Build Coastguard Worker                                                                 vixl::aarch64::VRegister> {
246*795d594fSAndroid Build Coastguard Worker  public:
InvokeRuntimeCallingConvention()247*795d594fSAndroid Build Coastguard Worker   InvokeRuntimeCallingConvention()
248*795d594fSAndroid Build Coastguard Worker       : CallingConvention(kRuntimeParameterCoreRegisters,
249*795d594fSAndroid Build Coastguard Worker                           kRuntimeParameterCoreRegistersLength,
250*795d594fSAndroid Build Coastguard Worker                           kRuntimeParameterFpuRegisters,
251*795d594fSAndroid Build Coastguard Worker                           kRuntimeParameterFpuRegistersLength,
252*795d594fSAndroid Build Coastguard Worker                           kArm64PointerSize) {}
253*795d594fSAndroid Build Coastguard Worker 
254*795d594fSAndroid Build Coastguard Worker   Location GetReturnLocation(DataType::Type return_type);
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker  private:
257*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
258*795d594fSAndroid Build Coastguard Worker };
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker class InvokeDexCallingConvention : public CallingConvention<vixl::aarch64::Register,
261*795d594fSAndroid Build Coastguard Worker                                                             vixl::aarch64::VRegister> {
262*795d594fSAndroid Build Coastguard Worker  public:
InvokeDexCallingConvention()263*795d594fSAndroid Build Coastguard Worker   InvokeDexCallingConvention()
264*795d594fSAndroid Build Coastguard Worker       : CallingConvention(kParameterCoreRegisters,
265*795d594fSAndroid Build Coastguard Worker                           kParameterCoreRegistersLength,
266*795d594fSAndroid Build Coastguard Worker                           kParameterFPRegisters,
267*795d594fSAndroid Build Coastguard Worker                           kParameterFPRegistersLength,
268*795d594fSAndroid Build Coastguard Worker                           kArm64PointerSize) {}
269*795d594fSAndroid Build Coastguard Worker 
GetReturnLocation(DataType::Type return_type)270*795d594fSAndroid Build Coastguard Worker   Location GetReturnLocation(DataType::Type return_type) const {
271*795d594fSAndroid Build Coastguard Worker     return ARM64ReturnLocation(return_type);
272*795d594fSAndroid Build Coastguard Worker   }
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker  private:
276*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
277*795d594fSAndroid Build Coastguard Worker };
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker class InvokeDexCallingConventionVisitorARM64 : public InvokeDexCallingConventionVisitor {
280*795d594fSAndroid Build Coastguard Worker  public:
InvokeDexCallingConventionVisitorARM64()281*795d594fSAndroid Build Coastguard Worker   InvokeDexCallingConventionVisitorARM64() {}
~InvokeDexCallingConventionVisitorARM64()282*795d594fSAndroid Build Coastguard Worker   virtual ~InvokeDexCallingConventionVisitorARM64() {}
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   Location GetNextLocation(DataType::Type type) override;
GetReturnLocation(DataType::Type return_type)285*795d594fSAndroid Build Coastguard Worker   Location GetReturnLocation(DataType::Type return_type) const override {
286*795d594fSAndroid Build Coastguard Worker     return calling_convention.GetReturnLocation(return_type);
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker   Location GetMethodLocation() const override;
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker  private:
291*795d594fSAndroid Build Coastguard Worker   InvokeDexCallingConvention calling_convention;
292*795d594fSAndroid Build Coastguard Worker 
293*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorARM64);
294*795d594fSAndroid Build Coastguard Worker };
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker class CriticalNativeCallingConventionVisitorARM64 : public InvokeDexCallingConventionVisitor {
297*795d594fSAndroid Build Coastguard Worker  public:
CriticalNativeCallingConventionVisitorARM64(bool for_register_allocation)298*795d594fSAndroid Build Coastguard Worker   explicit CriticalNativeCallingConventionVisitorARM64(bool for_register_allocation)
299*795d594fSAndroid Build Coastguard Worker       : for_register_allocation_(for_register_allocation) {}
300*795d594fSAndroid Build Coastguard Worker 
~CriticalNativeCallingConventionVisitorARM64()301*795d594fSAndroid Build Coastguard Worker   virtual ~CriticalNativeCallingConventionVisitorARM64() {}
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker   Location GetNextLocation(DataType::Type type) override;
304*795d594fSAndroid Build Coastguard Worker   Location GetReturnLocation(DataType::Type type) const override;
305*795d594fSAndroid Build Coastguard Worker   Location GetMethodLocation() const override;
306*795d594fSAndroid Build Coastguard Worker 
GetStackOffset()307*795d594fSAndroid Build Coastguard Worker   size_t GetStackOffset() const { return stack_offset_; }
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker  private:
310*795d594fSAndroid Build Coastguard Worker   // Register allocator does not support adjusting frame size, so we cannot provide final locations
311*795d594fSAndroid Build Coastguard Worker   // of stack arguments for register allocation. We ask the register allocator for any location and
312*795d594fSAndroid Build Coastguard Worker   // move these arguments to the right place after adjusting the SP when generating the call.
313*795d594fSAndroid Build Coastguard Worker   const bool for_register_allocation_;
314*795d594fSAndroid Build Coastguard Worker   size_t gpr_index_ = 0u;
315*795d594fSAndroid Build Coastguard Worker   size_t fpr_index_ = 0u;
316*795d594fSAndroid Build Coastguard Worker   size_t stack_offset_ = 0u;
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CriticalNativeCallingConventionVisitorARM64);
319*795d594fSAndroid Build Coastguard Worker };
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker class FieldAccessCallingConventionARM64 : public FieldAccessCallingConvention {
322*795d594fSAndroid Build Coastguard Worker  public:
FieldAccessCallingConventionARM64()323*795d594fSAndroid Build Coastguard Worker   FieldAccessCallingConventionARM64() {}
324*795d594fSAndroid Build Coastguard Worker 
GetObjectLocation()325*795d594fSAndroid Build Coastguard Worker   Location GetObjectLocation() const override {
326*795d594fSAndroid Build Coastguard Worker     return helpers::LocationFrom(vixl::aarch64::x1);
327*795d594fSAndroid Build Coastguard Worker   }
GetFieldIndexLocation()328*795d594fSAndroid Build Coastguard Worker   Location GetFieldIndexLocation() const override {
329*795d594fSAndroid Build Coastguard Worker     return helpers::LocationFrom(vixl::aarch64::x0);
330*795d594fSAndroid Build Coastguard Worker   }
GetReturnLocation(DataType::Type type)331*795d594fSAndroid Build Coastguard Worker   Location GetReturnLocation([[maybe_unused]] DataType::Type type) const override {
332*795d594fSAndroid Build Coastguard Worker     return helpers::LocationFrom(vixl::aarch64::x0);
333*795d594fSAndroid Build Coastguard Worker   }
GetSetValueLocation(DataType::Type type,bool is_instance)334*795d594fSAndroid Build Coastguard Worker   Location GetSetValueLocation([[maybe_unused]] DataType::Type type,
335*795d594fSAndroid Build Coastguard Worker                                bool is_instance) const override {
336*795d594fSAndroid Build Coastguard Worker     return is_instance
337*795d594fSAndroid Build Coastguard Worker         ? helpers::LocationFrom(vixl::aarch64::x2)
338*795d594fSAndroid Build Coastguard Worker         : helpers::LocationFrom(vixl::aarch64::x1);
339*795d594fSAndroid Build Coastguard Worker   }
GetFpuLocation(DataType::Type type)340*795d594fSAndroid Build Coastguard Worker   Location GetFpuLocation([[maybe_unused]] DataType::Type type) const override {
341*795d594fSAndroid Build Coastguard Worker     return helpers::LocationFrom(vixl::aarch64::d0);
342*795d594fSAndroid Build Coastguard Worker   }
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker  private:
345*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionARM64);
346*795d594fSAndroid Build Coastguard Worker };
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker class InstructionCodeGeneratorARM64 : public InstructionCodeGenerator {
349*795d594fSAndroid Build Coastguard Worker  public:
350*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64(HGraph* graph, CodeGeneratorARM64* codegen);
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
353*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(DECLARE_VISIT_INSTRUCTION)
FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)356*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
357*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
358*795d594fSAndroid Build Coastguard Worker 
359*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker   void VisitInstruction(HInstruction* instruction) override {
362*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
363*795d594fSAndroid Build Coastguard Worker                << " (id " << instruction->GetId() << ")";
364*795d594fSAndroid Build Coastguard Worker   }
365*795d594fSAndroid Build Coastguard Worker 
GetAssembler()366*795d594fSAndroid Build Coastguard Worker   Arm64Assembler* GetAssembler() const { return assembler_; }
GetVIXLAssembler()367*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
368*795d594fSAndroid Build Coastguard Worker 
369*795d594fSAndroid Build Coastguard Worker   // SIMD helpers.
370*795d594fSAndroid Build Coastguard Worker   virtual Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) = 0;
371*795d594fSAndroid Build Coastguard Worker   virtual void FreeSIMDScratchLocation(Location loc,
372*795d594fSAndroid Build Coastguard Worker                                        vixl::aarch64::UseScratchRegisterScope* scope)  = 0;
373*795d594fSAndroid Build Coastguard Worker   virtual void LoadSIMDRegFromStack(Location destination, Location source) = 0;
374*795d594fSAndroid Build Coastguard Worker   virtual void MoveSIMDRegToSIMDReg(Location destination, Location source) = 0;
375*795d594fSAndroid Build Coastguard Worker   virtual void MoveToSIMDStackSlot(Location destination, Location source) = 0;
376*795d594fSAndroid Build Coastguard Worker   virtual void SaveLiveRegistersHelper(LocationSummary* locations,
377*795d594fSAndroid Build Coastguard Worker                                        int64_t spill_offset) = 0;
378*795d594fSAndroid Build Coastguard Worker   virtual void RestoreLiveRegistersHelper(LocationSummary* locations,
379*795d594fSAndroid Build Coastguard Worker                                           int64_t spill_offset) = 0;
380*795d594fSAndroid Build Coastguard Worker 
381*795d594fSAndroid Build Coastguard Worker  protected:
382*795d594fSAndroid Build Coastguard Worker   void GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path,
383*795d594fSAndroid Build Coastguard Worker                                         vixl::aarch64::Register class_reg);
384*795d594fSAndroid Build Coastguard Worker   void GenerateBitstringTypeCheckCompare(HTypeCheckInstruction* check,
385*795d594fSAndroid Build Coastguard Worker                                          vixl::aarch64::Register temp);
386*795d594fSAndroid Build Coastguard Worker   void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
387*795d594fSAndroid Build Coastguard Worker   void HandleBinaryOp(HBinaryOperation* instr);
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker   void HandleFieldSet(HInstruction* instruction,
390*795d594fSAndroid Build Coastguard Worker                       const FieldInfo& field_info,
391*795d594fSAndroid Build Coastguard Worker                       bool value_can_be_null,
392*795d594fSAndroid Build Coastguard Worker                       WriteBarrierKind write_barrier_kind);
393*795d594fSAndroid Build Coastguard Worker   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
394*795d594fSAndroid Build Coastguard Worker   void HandleCondition(HCondition* instruction);
395*795d594fSAndroid Build Coastguard Worker 
396*795d594fSAndroid Build Coastguard Worker   // Generate a heap reference load using one register `out`:
397*795d594fSAndroid Build Coastguard Worker   //
398*795d594fSAndroid Build Coastguard Worker   //   out <- *(out + offset)
399*795d594fSAndroid Build Coastguard Worker   //
400*795d594fSAndroid Build Coastguard Worker   // while honoring heap poisoning and/or read barriers (if any).
401*795d594fSAndroid Build Coastguard Worker   //
402*795d594fSAndroid Build Coastguard Worker   // Location `maybe_temp` is used when generating a read barrier and
403*795d594fSAndroid Build Coastguard Worker   // shall be a register in that case; it may be an invalid location
404*795d594fSAndroid Build Coastguard Worker   // otherwise.
405*795d594fSAndroid Build Coastguard Worker   void GenerateReferenceLoadOneRegister(HInstruction* instruction,
406*795d594fSAndroid Build Coastguard Worker                                         Location out,
407*795d594fSAndroid Build Coastguard Worker                                         uint32_t offset,
408*795d594fSAndroid Build Coastguard Worker                                         Location maybe_temp,
409*795d594fSAndroid Build Coastguard Worker                                         ReadBarrierOption read_barrier_option);
410*795d594fSAndroid Build Coastguard Worker   // Generate a heap reference load using two different registers
411*795d594fSAndroid Build Coastguard Worker   // `out` and `obj`:
412*795d594fSAndroid Build Coastguard Worker   //
413*795d594fSAndroid Build Coastguard Worker   //   out <- *(obj + offset)
414*795d594fSAndroid Build Coastguard Worker   //
415*795d594fSAndroid Build Coastguard Worker   // while honoring heap poisoning and/or read barriers (if any).
416*795d594fSAndroid Build Coastguard Worker   //
417*795d594fSAndroid Build Coastguard Worker   // Location `maybe_temp` is used when generating a Baker's (fast
418*795d594fSAndroid Build Coastguard Worker   // path) read barrier and shall be a register in that case; it may
419*795d594fSAndroid Build Coastguard Worker   // be an invalid location otherwise.
420*795d594fSAndroid Build Coastguard Worker   void GenerateReferenceLoadTwoRegisters(HInstruction* instruction,
421*795d594fSAndroid Build Coastguard Worker                                          Location out,
422*795d594fSAndroid Build Coastguard Worker                                          Location obj,
423*795d594fSAndroid Build Coastguard Worker                                          uint32_t offset,
424*795d594fSAndroid Build Coastguard Worker                                          Location maybe_temp,
425*795d594fSAndroid Build Coastguard Worker                                          ReadBarrierOption read_barrier_option);
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker   // Generate a floating-point comparison.
428*795d594fSAndroid Build Coastguard Worker   void GenerateFcmp(HInstruction* instruction);
429*795d594fSAndroid Build Coastguard Worker 
430*795d594fSAndroid Build Coastguard Worker   void HandleShift(HBinaryOperation* instr);
431*795d594fSAndroid Build Coastguard Worker   void GenerateTestAndBranch(HInstruction* instruction,
432*795d594fSAndroid Build Coastguard Worker                              size_t condition_input_index,
433*795d594fSAndroid Build Coastguard Worker                              vixl::aarch64::Label* true_target,
434*795d594fSAndroid Build Coastguard Worker                              vixl::aarch64::Label* false_target);
435*795d594fSAndroid Build Coastguard Worker   void DivRemOneOrMinusOne(HBinaryOperation* instruction);
436*795d594fSAndroid Build Coastguard Worker   void DivRemByPowerOfTwo(HBinaryOperation* instruction);
437*795d594fSAndroid Build Coastguard Worker   void GenerateIncrementNegativeByOne(vixl::aarch64::Register out,
438*795d594fSAndroid Build Coastguard Worker                                       vixl::aarch64::Register in, bool use_cond_inc);
439*795d594fSAndroid Build Coastguard Worker   void GenerateResultRemWithAnyConstant(vixl::aarch64::Register out,
440*795d594fSAndroid Build Coastguard Worker                                         vixl::aarch64::Register dividend,
441*795d594fSAndroid Build Coastguard Worker                                         vixl::aarch64::Register quotient,
442*795d594fSAndroid Build Coastguard Worker                                         int64_t divisor,
443*795d594fSAndroid Build Coastguard Worker                                         // This function may acquire a scratch register.
444*795d594fSAndroid Build Coastguard Worker                                         vixl::aarch64::UseScratchRegisterScope* temps_scope);
445*795d594fSAndroid Build Coastguard Worker   void GenerateInt64UnsignedDivRemWithAnyPositiveConstant(HBinaryOperation* instruction);
446*795d594fSAndroid Build Coastguard Worker   void GenerateInt64DivRemWithAnyConstant(HBinaryOperation* instruction);
447*795d594fSAndroid Build Coastguard Worker   void GenerateInt32DivRemWithAnyConstant(HBinaryOperation* instruction);
448*795d594fSAndroid Build Coastguard Worker   void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction, int64_t divisor);
449*795d594fSAndroid Build Coastguard Worker   void GenerateIntDiv(HDiv* instruction);
450*795d594fSAndroid Build Coastguard Worker   void GenerateIntDivForConstDenom(HDiv *instruction);
451*795d594fSAndroid Build Coastguard Worker   void GenerateIntDivForPower2Denom(HDiv *instruction);
452*795d594fSAndroid Build Coastguard Worker   void GenerateIntRem(HRem* instruction);
453*795d594fSAndroid Build Coastguard Worker   void GenerateIntRemForConstDenom(HRem *instruction);
454*795d594fSAndroid Build Coastguard Worker   void GenerateIntRemForPower2Denom(HRem *instruction);
455*795d594fSAndroid Build Coastguard Worker   void HandleGoto(HInstruction* got, HBasicBlock* successor);
456*795d594fSAndroid Build Coastguard Worker   void GenerateMethodEntryExitHook(HInstruction* instruction);
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker   // Helpers to set up locations for vector memory operations. Returns the memory operand and,
459*795d594fSAndroid Build Coastguard Worker   // if used, sets the output parameter scratch to a temporary register used in this operand,
460*795d594fSAndroid Build Coastguard Worker   // so that the client can release it right after the memory operand use.
461*795d594fSAndroid Build Coastguard Worker   // Neon version.
462*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::MemOperand VecNEONAddress(
463*795d594fSAndroid Build Coastguard Worker       HVecMemoryOperation* instruction,
464*795d594fSAndroid Build Coastguard Worker       // This function may acquire a scratch register.
465*795d594fSAndroid Build Coastguard Worker       vixl::aarch64::UseScratchRegisterScope* temps_scope,
466*795d594fSAndroid Build Coastguard Worker       size_t size,
467*795d594fSAndroid Build Coastguard Worker       bool is_string_char_at,
468*795d594fSAndroid Build Coastguard Worker       /*out*/ vixl::aarch64::Register* scratch);
469*795d594fSAndroid Build Coastguard Worker   // SVE version.
470*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::SVEMemOperand VecSVEAddress(
471*795d594fSAndroid Build Coastguard Worker       HVecMemoryOperation* instruction,
472*795d594fSAndroid Build Coastguard Worker       // This function may acquire a scratch register.
473*795d594fSAndroid Build Coastguard Worker       vixl::aarch64::UseScratchRegisterScope* temps_scope,
474*795d594fSAndroid Build Coastguard Worker       size_t size,
475*795d594fSAndroid Build Coastguard Worker       bool is_string_char_at,
476*795d594fSAndroid Build Coastguard Worker       /*out*/ vixl::aarch64::Register* scratch);
477*795d594fSAndroid Build Coastguard Worker 
478*795d594fSAndroid Build Coastguard Worker   Arm64Assembler* const assembler_;
479*795d594fSAndroid Build Coastguard Worker   CodeGeneratorARM64* const codegen_;
480*795d594fSAndroid Build Coastguard Worker 
481*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorARM64);
482*795d594fSAndroid Build Coastguard Worker };
483*795d594fSAndroid Build Coastguard Worker 
484*795d594fSAndroid Build Coastguard Worker class LocationsBuilderARM64 : public HGraphVisitor {
485*795d594fSAndroid Build Coastguard Worker  public:
LocationsBuilderARM64(HGraph * graph,CodeGeneratorARM64 * codegen)486*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64(HGraph* graph, CodeGeneratorARM64* codegen)
487*795d594fSAndroid Build Coastguard Worker       : HGraphVisitor(graph), codegen_(codegen) {}
488*795d594fSAndroid Build Coastguard Worker 
489*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
490*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
491*795d594fSAndroid Build Coastguard Worker 
492*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(DECLARE_VISIT_INSTRUCTION)
FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)493*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
494*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SHARED(DECLARE_VISIT_INSTRUCTION)
495*795d594fSAndroid Build Coastguard Worker 
496*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
497*795d594fSAndroid Build Coastguard Worker 
498*795d594fSAndroid Build Coastguard Worker   void VisitInstruction(HInstruction* instruction) override {
499*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unreachable instruction " << instruction->DebugName()
500*795d594fSAndroid Build Coastguard Worker                << " (id " << instruction->GetId() << ")";
501*795d594fSAndroid Build Coastguard Worker   }
502*795d594fSAndroid Build Coastguard Worker 
503*795d594fSAndroid Build Coastguard Worker  protected:
504*795d594fSAndroid Build Coastguard Worker   void HandleBinaryOp(HBinaryOperation* instr);
505*795d594fSAndroid Build Coastguard Worker   void HandleFieldSet(HInstruction* instruction);
506*795d594fSAndroid Build Coastguard Worker   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
507*795d594fSAndroid Build Coastguard Worker   void HandleInvoke(HInvoke* instr);
508*795d594fSAndroid Build Coastguard Worker   void HandleCondition(HCondition* instruction);
509*795d594fSAndroid Build Coastguard Worker   void HandleShift(HBinaryOperation* instr);
510*795d594fSAndroid Build Coastguard Worker 
511*795d594fSAndroid Build Coastguard Worker   CodeGeneratorARM64* const codegen_;
512*795d594fSAndroid Build Coastguard Worker   InvokeDexCallingConventionVisitorARM64 parameter_visitor_;
513*795d594fSAndroid Build Coastguard Worker 
514*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM64);
515*795d594fSAndroid Build Coastguard Worker };
516*795d594fSAndroid Build Coastguard Worker 
517*795d594fSAndroid Build Coastguard Worker class InstructionCodeGeneratorARM64Neon : public InstructionCodeGeneratorARM64 {
518*795d594fSAndroid Build Coastguard Worker  public:
InstructionCodeGeneratorARM64Neon(HGraph * graph,CodeGeneratorARM64 * codegen)519*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64Neon(HGraph* graph, CodeGeneratorARM64* codegen) :
520*795d594fSAndroid Build Coastguard Worker       InstructionCodeGeneratorARM64(graph, codegen) {}
521*795d594fSAndroid Build Coastguard Worker 
522*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
523*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
526*795d594fSAndroid Build Coastguard Worker 
527*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
528*795d594fSAndroid Build Coastguard Worker 
529*795d594fSAndroid Build Coastguard Worker   Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) override;
530*795d594fSAndroid Build Coastguard Worker   void FreeSIMDScratchLocation(Location loc,
531*795d594fSAndroid Build Coastguard Worker                                vixl::aarch64::UseScratchRegisterScope* scope) override;
532*795d594fSAndroid Build Coastguard Worker   void LoadSIMDRegFromStack(Location destination, Location source) override;
533*795d594fSAndroid Build Coastguard Worker   void MoveSIMDRegToSIMDReg(Location destination, Location source) override;
534*795d594fSAndroid Build Coastguard Worker   void MoveToSIMDStackSlot(Location destination, Location source) override;
535*795d594fSAndroid Build Coastguard Worker   void SaveLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
536*795d594fSAndroid Build Coastguard Worker   void RestoreLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
537*795d594fSAndroid Build Coastguard Worker };
538*795d594fSAndroid Build Coastguard Worker 
539*795d594fSAndroid Build Coastguard Worker class LocationsBuilderARM64Neon : public LocationsBuilderARM64 {
540*795d594fSAndroid Build Coastguard Worker  public:
LocationsBuilderARM64Neon(HGraph * graph,CodeGeneratorARM64 * codegen)541*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64Neon(HGraph* graph, CodeGeneratorARM64* codegen) :
542*795d594fSAndroid Build Coastguard Worker       LocationsBuilderARM64(graph, codegen) {}
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
545*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
546*795d594fSAndroid Build Coastguard Worker 
547*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
550*795d594fSAndroid Build Coastguard Worker };
551*795d594fSAndroid Build Coastguard Worker 
552*795d594fSAndroid Build Coastguard Worker class InstructionCodeGeneratorARM64Sve : public InstructionCodeGeneratorARM64 {
553*795d594fSAndroid Build Coastguard Worker  public:
InstructionCodeGeneratorARM64Sve(HGraph * graph,CodeGeneratorARM64 * codegen)554*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64Sve(HGraph* graph, CodeGeneratorARM64* codegen) :
555*795d594fSAndroid Build Coastguard Worker       InstructionCodeGeneratorARM64(graph, codegen) {}
556*795d594fSAndroid Build Coastguard Worker 
557*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
558*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
559*795d594fSAndroid Build Coastguard Worker 
560*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
561*795d594fSAndroid Build Coastguard Worker 
562*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
563*795d594fSAndroid Build Coastguard Worker 
564*795d594fSAndroid Build Coastguard Worker   Location AllocateSIMDScratchLocation(vixl::aarch64::UseScratchRegisterScope* scope) override;
565*795d594fSAndroid Build Coastguard Worker   void FreeSIMDScratchLocation(Location loc,
566*795d594fSAndroid Build Coastguard Worker                                vixl::aarch64::UseScratchRegisterScope* scope) override;
567*795d594fSAndroid Build Coastguard Worker   void LoadSIMDRegFromStack(Location destination, Location source) override;
568*795d594fSAndroid Build Coastguard Worker   void MoveSIMDRegToSIMDReg(Location destination, Location source) override;
569*795d594fSAndroid Build Coastguard Worker   void MoveToSIMDStackSlot(Location destination, Location source) override;
570*795d594fSAndroid Build Coastguard Worker   void SaveLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
571*795d594fSAndroid Build Coastguard Worker   void RestoreLiveRegistersHelper(LocationSummary* locations, int64_t spill_offset) override;
572*795d594fSAndroid Build Coastguard Worker 
573*795d594fSAndroid Build Coastguard Worker  private:
574*795d594fSAndroid Build Coastguard Worker   // Validate that instruction vector length and packed type are compliant with the SIMD
575*795d594fSAndroid Build Coastguard Worker   // register size (full SIMD register is used).
576*795d594fSAndroid Build Coastguard Worker   void ValidateVectorLength(HVecOperation* instr) const;
577*795d594fSAndroid Build Coastguard Worker 
GetVecGoverningPReg(HVecOperation * instr)578*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::PRegister GetVecGoverningPReg(HVecOperation* instr) {
579*795d594fSAndroid Build Coastguard Worker     return GetVecPredSetFixedOutPReg(instr->GetGoverningPredicate());
580*795d594fSAndroid Build Coastguard Worker   }
581*795d594fSAndroid Build Coastguard Worker 
582*795d594fSAndroid Build Coastguard Worker   // Returns a fixed p-reg for predicate setting instruction.
583*795d594fSAndroid Build Coastguard Worker   //
584*795d594fSAndroid Build Coastguard Worker   // Currently we only support diamond CF loops for predicated vectorization; also we don't have
585*795d594fSAndroid Build Coastguard Worker   // register allocator support for vector predicates. Thus we use fixed P-regs for loop main,
586*795d594fSAndroid Build Coastguard Worker   // True and False predicates as a temporary solution.
587*795d594fSAndroid Build Coastguard Worker   //
588*795d594fSAndroid Build Coastguard Worker   // TODO: Support SIMD types and registers in ART.
GetVecPredSetFixedOutPReg(HVecPredSetOperation * instr)589*795d594fSAndroid Build Coastguard Worker   static vixl::aarch64::PRegister GetVecPredSetFixedOutPReg(HVecPredSetOperation* instr) {
590*795d594fSAndroid Build Coastguard Worker     if (instr->IsVecPredWhile() || instr->IsVecPredSetAll()) {
591*795d594fSAndroid Build Coastguard Worker       // VecPredWhile and VecPredSetAll live ranges never overlap due to the current vectorization
592*795d594fSAndroid Build Coastguard Worker       // scheme: the former only is live inside a vectorized loop and the later is never in a
593*795d594fSAndroid Build Coastguard Worker       // loop and never spans across loops.
594*795d594fSAndroid Build Coastguard Worker       return vixl::aarch64::p0;
595*795d594fSAndroid Build Coastguard Worker     } else if (instr->IsVecPredNot()) {
596*795d594fSAndroid Build Coastguard Worker       // This relies on the fact that we only use PredNot manually in the autovectorizer,
597*795d594fSAndroid Build Coastguard Worker       // so there is only one of them in each loop.
598*795d594fSAndroid Build Coastguard Worker       return vixl::aarch64::p1;
599*795d594fSAndroid Build Coastguard Worker     } else {
600*795d594fSAndroid Build Coastguard Worker       DCHECK(instr->IsVecCondition());
601*795d594fSAndroid Build Coastguard Worker       return vixl::aarch64::p2;
602*795d594fSAndroid Build Coastguard Worker     }
603*795d594fSAndroid Build Coastguard Worker   }
604*795d594fSAndroid Build Coastguard Worker 
605*795d594fSAndroid Build Coastguard Worker   // Generate a vector comparison instruction based on the IfCondition.
606*795d594fSAndroid Build Coastguard Worker   void GenerateIntegerVecComparison(const vixl::aarch64::PRegisterWithLaneSize& pd,
607*795d594fSAndroid Build Coastguard Worker                                     const vixl::aarch64::PRegisterZ& pg,
608*795d594fSAndroid Build Coastguard Worker                                     const vixl::aarch64::ZRegister& zn,
609*795d594fSAndroid Build Coastguard Worker                                     const vixl::aarch64::ZRegister& zm,
610*795d594fSAndroid Build Coastguard Worker                                     IfCondition cond);
611*795d594fSAndroid Build Coastguard Worker   void HandleVecCondition(HVecCondition* instruction);
612*795d594fSAndroid Build Coastguard Worker };
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker class LocationsBuilderARM64Sve : public LocationsBuilderARM64 {
615*795d594fSAndroid Build Coastguard Worker  public:
LocationsBuilderARM64Sve(HGraph * graph,CodeGeneratorARM64 * codegen)616*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64Sve(HGraph* graph, CodeGeneratorARM64* codegen) :
617*795d594fSAndroid Build Coastguard Worker       LocationsBuilderARM64(graph, codegen) {}
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super) \
620*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override;
621*795d594fSAndroid Build Coastguard Worker 
622*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(DECLARE_VISIT_INSTRUCTION)
623*795d594fSAndroid Build Coastguard Worker 
624*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
625*795d594fSAndroid Build Coastguard Worker  private:
626*795d594fSAndroid Build Coastguard Worker   void HandleVecCondition(HVecCondition* instruction);
627*795d594fSAndroid Build Coastguard Worker };
628*795d594fSAndroid Build Coastguard Worker 
629*795d594fSAndroid Build Coastguard Worker class ParallelMoveResolverARM64 : public ParallelMoveResolverNoSwap {
630*795d594fSAndroid Build Coastguard Worker  public:
ParallelMoveResolverARM64(ArenaAllocator * allocator,CodeGeneratorARM64 * codegen)631*795d594fSAndroid Build Coastguard Worker   ParallelMoveResolverARM64(ArenaAllocator* allocator, CodeGeneratorARM64* codegen)
632*795d594fSAndroid Build Coastguard Worker       : ParallelMoveResolverNoSwap(allocator), codegen_(codegen), vixl_temps_() {}
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker  protected:
635*795d594fSAndroid Build Coastguard Worker   void PrepareForEmitNativeCode() override;
636*795d594fSAndroid Build Coastguard Worker   void FinishEmitNativeCode() override;
637*795d594fSAndroid Build Coastguard Worker   Location AllocateScratchLocationFor(Location::Kind kind) override;
638*795d594fSAndroid Build Coastguard Worker   void FreeScratchLocation(Location loc) override;
639*795d594fSAndroid Build Coastguard Worker   void EmitMove(size_t index) override;
640*795d594fSAndroid Build Coastguard Worker 
641*795d594fSAndroid Build Coastguard Worker  private:
642*795d594fSAndroid Build Coastguard Worker   Arm64Assembler* GetAssembler() const;
GetVIXLAssembler()643*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::MacroAssembler* GetVIXLAssembler() const {
644*795d594fSAndroid Build Coastguard Worker     return GetAssembler()->GetVIXLAssembler();
645*795d594fSAndroid Build Coastguard Worker   }
646*795d594fSAndroid Build Coastguard Worker 
647*795d594fSAndroid Build Coastguard Worker   CodeGeneratorARM64* const codegen_;
648*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::UseScratchRegisterScope vixl_temps_;
649*795d594fSAndroid Build Coastguard Worker 
650*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverARM64);
651*795d594fSAndroid Build Coastguard Worker };
652*795d594fSAndroid Build Coastguard Worker 
653*795d594fSAndroid Build Coastguard Worker class CodeGeneratorARM64 : public CodeGenerator {
654*795d594fSAndroid Build Coastguard Worker  public:
655*795d594fSAndroid Build Coastguard Worker   CodeGeneratorARM64(HGraph* graph,
656*795d594fSAndroid Build Coastguard Worker                      const CompilerOptions& compiler_options,
657*795d594fSAndroid Build Coastguard Worker                      OptimizingCompilerStats* stats = nullptr);
~CodeGeneratorARM64()658*795d594fSAndroid Build Coastguard Worker   virtual ~CodeGeneratorARM64() {}
659*795d594fSAndroid Build Coastguard Worker 
660*795d594fSAndroid Build Coastguard Worker   void GenerateFrameEntry() override;
661*795d594fSAndroid Build Coastguard Worker   void GenerateFrameExit() override;
662*795d594fSAndroid Build Coastguard Worker 
663*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::CPURegList GetFramePreservedCoreRegisters() const;
664*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::CPURegList GetFramePreservedFPRegisters() const;
665*795d594fSAndroid Build Coastguard Worker 
666*795d594fSAndroid Build Coastguard Worker   void Bind(HBasicBlock* block) override;
667*795d594fSAndroid Build Coastguard Worker 
GetLabelOf(HBasicBlock * block)668*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* GetLabelOf(HBasicBlock* block) {
669*795d594fSAndroid Build Coastguard Worker     block = FirstNonEmptyBlock(block);
670*795d594fSAndroid Build Coastguard Worker     return &(block_labels_[block->GetBlockId()]);
671*795d594fSAndroid Build Coastguard Worker   }
672*795d594fSAndroid Build Coastguard Worker 
GetWordSize()673*795d594fSAndroid Build Coastguard Worker   size_t GetWordSize() const override {
674*795d594fSAndroid Build Coastguard Worker     return kArm64WordSize;
675*795d594fSAndroid Build Coastguard Worker   }
676*795d594fSAndroid Build Coastguard Worker 
SupportsPredicatedSIMD()677*795d594fSAndroid Build Coastguard Worker   bool SupportsPredicatedSIMD() const override { return ShouldUseSVE(); }
678*795d594fSAndroid Build Coastguard Worker 
GetSlowPathFPWidth()679*795d594fSAndroid Build Coastguard Worker   size_t GetSlowPathFPWidth() const override {
680*795d594fSAndroid Build Coastguard Worker     return GetGraph()->HasSIMD()
681*795d594fSAndroid Build Coastguard Worker         ? GetSIMDRegisterWidth()
682*795d594fSAndroid Build Coastguard Worker         : vixl::aarch64::kDRegSizeInBytes;
683*795d594fSAndroid Build Coastguard Worker   }
684*795d594fSAndroid Build Coastguard Worker 
GetCalleePreservedFPWidth()685*795d594fSAndroid Build Coastguard Worker   size_t GetCalleePreservedFPWidth() const override {
686*795d594fSAndroid Build Coastguard Worker     return vixl::aarch64::kDRegSizeInBytes;
687*795d594fSAndroid Build Coastguard Worker   }
688*795d594fSAndroid Build Coastguard Worker 
689*795d594fSAndroid Build Coastguard Worker   size_t GetSIMDRegisterWidth() const override;
690*795d594fSAndroid Build Coastguard Worker 
GetAddressOf(HBasicBlock * block)691*795d594fSAndroid Build Coastguard Worker   uintptr_t GetAddressOf(HBasicBlock* block) override {
692*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::Label* block_entry_label = GetLabelOf(block);
693*795d594fSAndroid Build Coastguard Worker     DCHECK(block_entry_label->IsBound());
694*795d594fSAndroid Build Coastguard Worker     return block_entry_label->GetLocation();
695*795d594fSAndroid Build Coastguard Worker   }
696*795d594fSAndroid Build Coastguard Worker 
GetLocationBuilder()697*795d594fSAndroid Build Coastguard Worker   HGraphVisitor* GetLocationBuilder() override { return location_builder_; }
GetInstructionCodeGeneratorArm64()698*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64* GetInstructionCodeGeneratorArm64() {
699*795d594fSAndroid Build Coastguard Worker     return instruction_visitor_;
700*795d594fSAndroid Build Coastguard Worker   }
GetInstructionVisitor()701*795d594fSAndroid Build Coastguard Worker   HGraphVisitor* GetInstructionVisitor() override { return GetInstructionCodeGeneratorArm64(); }
GetAssembler()702*795d594fSAndroid Build Coastguard Worker   Arm64Assembler* GetAssembler() override { return &assembler_; }
GetAssembler()703*795d594fSAndroid Build Coastguard Worker   const Arm64Assembler& GetAssembler() const override { return assembler_; }
GetVIXLAssembler()704*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->GetVIXLAssembler(); }
705*795d594fSAndroid Build Coastguard Worker 
706*795d594fSAndroid Build Coastguard Worker   // Emit a write barrier if:
707*795d594fSAndroid Build Coastguard Worker   // A) emit_null_check is false
708*795d594fSAndroid Build Coastguard Worker   // B) emit_null_check is true, and value is not null.
709*795d594fSAndroid Build Coastguard Worker   void MaybeMarkGCCard(vixl::aarch64::Register object,
710*795d594fSAndroid Build Coastguard Worker                        vixl::aarch64::Register value,
711*795d594fSAndroid Build Coastguard Worker                        bool emit_null_check);
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker   // Emit a write barrier unconditionally.
714*795d594fSAndroid Build Coastguard Worker   void MarkGCCard(vixl::aarch64::Register object);
715*795d594fSAndroid Build Coastguard Worker 
716*795d594fSAndroid Build Coastguard Worker   // Crash if the card table is not valid. This check is only emitted for the CC GC. We assert
717*795d594fSAndroid Build Coastguard Worker   // `(!clean || !self->is_gc_marking)`, since the card table should not be set to clean when the CC
718*795d594fSAndroid Build Coastguard Worker   // GC is marking for eliminated write barriers.
719*795d594fSAndroid Build Coastguard Worker   void CheckGCCardIsValid(vixl::aarch64::Register object);
720*795d594fSAndroid Build Coastguard Worker 
721*795d594fSAndroid Build Coastguard Worker   void GenerateMemoryBarrier(MemBarrierKind kind);
722*795d594fSAndroid Build Coastguard Worker 
723*795d594fSAndroid Build Coastguard Worker   // Register allocation.
724*795d594fSAndroid Build Coastguard Worker 
725*795d594fSAndroid Build Coastguard Worker   void SetupBlockedRegisters() const override;
726*795d594fSAndroid Build Coastguard Worker 
727*795d594fSAndroid Build Coastguard Worker   size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) override;
728*795d594fSAndroid Build Coastguard Worker   size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) override;
729*795d594fSAndroid Build Coastguard Worker   size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) override;
730*795d594fSAndroid Build Coastguard Worker   size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) override;
731*795d594fSAndroid Build Coastguard Worker 
732*795d594fSAndroid Build Coastguard Worker   // The number of registers that can be allocated. The register allocator may
733*795d594fSAndroid Build Coastguard Worker   // decide to reserve and not use a few of them.
734*795d594fSAndroid Build Coastguard Worker   // We do not consider registers sp, xzr, wzr. They are either not allocatable
735*795d594fSAndroid Build Coastguard Worker   // (xzr, wzr), or make for poor allocatable registers (sp alignment
736*795d594fSAndroid Build Coastguard Worker   // requirements, etc.). This also facilitates our task as all other registers
737*795d594fSAndroid Build Coastguard Worker   // can easily be mapped via to or from their type and index or code.
738*795d594fSAndroid Build Coastguard Worker   static const int kNumberOfAllocatableRegisters = vixl::aarch64::kNumberOfRegisters - 1;
739*795d594fSAndroid Build Coastguard Worker   static const int kNumberOfAllocatableFPRegisters = vixl::aarch64::kNumberOfVRegisters;
740*795d594fSAndroid Build Coastguard Worker   static constexpr int kNumberOfAllocatableRegisterPairs = 0;
741*795d594fSAndroid Build Coastguard Worker 
742*795d594fSAndroid Build Coastguard Worker   void DumpCoreRegister(std::ostream& stream, int reg) const override;
743*795d594fSAndroid Build Coastguard Worker   void DumpFloatingPointRegister(std::ostream& stream, int reg) const override;
744*795d594fSAndroid Build Coastguard Worker 
GetInstructionSet()745*795d594fSAndroid Build Coastguard Worker   InstructionSet GetInstructionSet() const override {
746*795d594fSAndroid Build Coastguard Worker     return InstructionSet::kArm64;
747*795d594fSAndroid Build Coastguard Worker   }
748*795d594fSAndroid Build Coastguard Worker 
749*795d594fSAndroid Build Coastguard Worker   const Arm64InstructionSetFeatures& GetInstructionSetFeatures() const;
750*795d594fSAndroid Build Coastguard Worker 
Initialize()751*795d594fSAndroid Build Coastguard Worker   void Initialize() override {
752*795d594fSAndroid Build Coastguard Worker     block_labels_.resize(GetGraph()->GetBlocks().size());
753*795d594fSAndroid Build Coastguard Worker   }
754*795d594fSAndroid Build Coastguard Worker 
755*795d594fSAndroid Build Coastguard Worker   // We want to use the STP and LDP instructions to spill and restore registers for slow paths.
756*795d594fSAndroid Build Coastguard Worker   // These instructions can only encode offsets that are multiples of the register size accessed.
GetPreferredSlotsAlignment()757*795d594fSAndroid Build Coastguard Worker   uint32_t GetPreferredSlotsAlignment() const override { return vixl::aarch64::kXRegSizeInBytes; }
758*795d594fSAndroid Build Coastguard Worker 
CreateJumpTable(HPackedSwitch * switch_instr)759*795d594fSAndroid Build Coastguard Worker   JumpTableARM64* CreateJumpTable(HPackedSwitch* switch_instr) {
760*795d594fSAndroid Build Coastguard Worker     jump_tables_.emplace_back(new (GetGraph()->GetAllocator()) JumpTableARM64(switch_instr));
761*795d594fSAndroid Build Coastguard Worker     return jump_tables_.back().get();
762*795d594fSAndroid Build Coastguard Worker   }
763*795d594fSAndroid Build Coastguard Worker 
764*795d594fSAndroid Build Coastguard Worker   void Finalize() override;
765*795d594fSAndroid Build Coastguard Worker 
766*795d594fSAndroid Build Coastguard Worker   // Code generation helpers.
767*795d594fSAndroid Build Coastguard Worker   void MoveConstant(vixl::aarch64::CPURegister destination, HConstant* constant);
768*795d594fSAndroid Build Coastguard Worker   void MoveConstant(Location destination, int32_t value) override;
769*795d594fSAndroid Build Coastguard Worker   void MoveLocation(Location dst, Location src, DataType::Type dst_type) override;
770*795d594fSAndroid Build Coastguard Worker   void AddLocationAsTemp(Location location, LocationSummary* locations) override;
771*795d594fSAndroid Build Coastguard Worker 
772*795d594fSAndroid Build Coastguard Worker   void Load(DataType::Type type,
773*795d594fSAndroid Build Coastguard Worker             vixl::aarch64::CPURegister dst,
774*795d594fSAndroid Build Coastguard Worker             const vixl::aarch64::MemOperand& src);
775*795d594fSAndroid Build Coastguard Worker   void Store(DataType::Type type,
776*795d594fSAndroid Build Coastguard Worker              vixl::aarch64::CPURegister src,
777*795d594fSAndroid Build Coastguard Worker              const vixl::aarch64::MemOperand& dst);
778*795d594fSAndroid Build Coastguard Worker   void LoadAcquire(HInstruction* instruction,
779*795d594fSAndroid Build Coastguard Worker                    DataType::Type type,
780*795d594fSAndroid Build Coastguard Worker                    vixl::aarch64::CPURegister dst,
781*795d594fSAndroid Build Coastguard Worker                    const vixl::aarch64::MemOperand& src,
782*795d594fSAndroid Build Coastguard Worker                    bool needs_null_check);
783*795d594fSAndroid Build Coastguard Worker   void StoreRelease(HInstruction* instruction,
784*795d594fSAndroid Build Coastguard Worker                     DataType::Type type,
785*795d594fSAndroid Build Coastguard Worker                     vixl::aarch64::CPURegister src,
786*795d594fSAndroid Build Coastguard Worker                     const vixl::aarch64::MemOperand& dst,
787*795d594fSAndroid Build Coastguard Worker                     bool needs_null_check);
788*795d594fSAndroid Build Coastguard Worker 
789*795d594fSAndroid Build Coastguard Worker   // Generate code to invoke a runtime entry point.
790*795d594fSAndroid Build Coastguard Worker   void InvokeRuntime(QuickEntrypointEnum entrypoint,
791*795d594fSAndroid Build Coastguard Worker                      HInstruction* instruction,
792*795d594fSAndroid Build Coastguard Worker                      uint32_t dex_pc,
793*795d594fSAndroid Build Coastguard Worker                      SlowPathCode* slow_path = nullptr) override;
794*795d594fSAndroid Build Coastguard Worker 
795*795d594fSAndroid Build Coastguard Worker   // Generate code to invoke a runtime entry point, but do not record
796*795d594fSAndroid Build Coastguard Worker   // PC-related information in a stack map.
797*795d594fSAndroid Build Coastguard Worker   void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
798*795d594fSAndroid Build Coastguard Worker                                            HInstruction* instruction,
799*795d594fSAndroid Build Coastguard Worker                                            SlowPathCode* slow_path);
800*795d594fSAndroid Build Coastguard Worker 
GetMoveResolver()801*795d594fSAndroid Build Coastguard Worker   ParallelMoveResolverARM64* GetMoveResolver() override { return &move_resolver_; }
802*795d594fSAndroid Build Coastguard Worker 
NeedsTwoRegisters(DataType::Type type)803*795d594fSAndroid Build Coastguard Worker   bool NeedsTwoRegisters([[maybe_unused]] DataType::Type type) const override { return false; }
804*795d594fSAndroid Build Coastguard Worker 
805*795d594fSAndroid Build Coastguard Worker   // Check if the desired_string_load_kind is supported. If it is, return it,
806*795d594fSAndroid Build Coastguard Worker   // otherwise return a fall-back kind that should be used instead.
807*795d594fSAndroid Build Coastguard Worker   HLoadString::LoadKind GetSupportedLoadStringKind(
808*795d594fSAndroid Build Coastguard Worker       HLoadString::LoadKind desired_string_load_kind) override;
809*795d594fSAndroid Build Coastguard Worker 
810*795d594fSAndroid Build Coastguard Worker   // Check if the desired_class_load_kind is supported. If it is, return it,
811*795d594fSAndroid Build Coastguard Worker   // otherwise return a fall-back kind that should be used instead.
812*795d594fSAndroid Build Coastguard Worker   HLoadClass::LoadKind GetSupportedLoadClassKind(
813*795d594fSAndroid Build Coastguard Worker       HLoadClass::LoadKind desired_class_load_kind) override;
814*795d594fSAndroid Build Coastguard Worker 
815*795d594fSAndroid Build Coastguard Worker   // Check if the desired_dispatch_info is supported. If it is, return it,
816*795d594fSAndroid Build Coastguard Worker   // otherwise return a fall-back info that should be used instead.
817*795d594fSAndroid Build Coastguard Worker   HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
818*795d594fSAndroid Build Coastguard Worker       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
819*795d594fSAndroid Build Coastguard Worker       ArtMethod* method) override;
820*795d594fSAndroid Build Coastguard Worker 
821*795d594fSAndroid Build Coastguard Worker   void LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke);
822*795d594fSAndroid Build Coastguard Worker   void GenerateStaticOrDirectCall(
823*795d594fSAndroid Build Coastguard Worker       HInvokeStaticOrDirect* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
824*795d594fSAndroid Build Coastguard Worker   void GenerateVirtualCall(
825*795d594fSAndroid Build Coastguard Worker       HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) override;
826*795d594fSAndroid Build Coastguard Worker 
827*795d594fSAndroid Build Coastguard Worker   void MoveFromReturnRegister(Location trg, DataType::Type type) override;
828*795d594fSAndroid Build Coastguard Worker 
829*795d594fSAndroid Build Coastguard Worker   // Add a new boot image intrinsic patch for an instruction and return the label
830*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
831*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
832*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
833*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageIntrinsicPatch(uint32_t intrinsic_data,
834*795d594fSAndroid Build Coastguard Worker                                                    vixl::aarch64::Label* adrp_label = nullptr);
835*795d594fSAndroid Build Coastguard Worker 
836*795d594fSAndroid Build Coastguard Worker   // Add a new boot image relocation patch for an instruction and return the label
837*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
838*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
839*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
840*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageRelRoPatch(uint32_t boot_image_offset,
841*795d594fSAndroid Build Coastguard Worker                                                vixl::aarch64::Label* adrp_label = nullptr);
842*795d594fSAndroid Build Coastguard Worker 
843*795d594fSAndroid Build Coastguard Worker   // Add a new boot image method patch for an instruction and return the label
844*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
845*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
846*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
847*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageMethodPatch(MethodReference target_method,
848*795d594fSAndroid Build Coastguard Worker                                                 vixl::aarch64::Label* adrp_label = nullptr);
849*795d594fSAndroid Build Coastguard Worker 
850*795d594fSAndroid Build Coastguard Worker   // Add a new app image method patch for an instruction and return the label
851*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
852*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
853*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
854*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewAppImageMethodPatch(MethodReference target_method,
855*795d594fSAndroid Build Coastguard Worker                                                vixl::aarch64::Label* adrp_label = nullptr);
856*795d594fSAndroid Build Coastguard Worker 
857*795d594fSAndroid Build Coastguard Worker   // Add a new .bss entry method patch for an instruction and return
858*795d594fSAndroid Build Coastguard Worker   // the label to be bound before the instruction. The instruction will be
859*795d594fSAndroid Build Coastguard Worker   // either the ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label`
860*795d594fSAndroid Build Coastguard Worker   // pointing to the associated ADRP patch label).
861*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewMethodBssEntryPatch(MethodReference target_method,
862*795d594fSAndroid Build Coastguard Worker                                                vixl::aarch64::Label* adrp_label = nullptr);
863*795d594fSAndroid Build Coastguard Worker 
864*795d594fSAndroid Build Coastguard Worker   // Add a new boot image type patch for an instruction and return the label
865*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
866*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
867*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
868*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageTypePatch(const DexFile& dex_file,
869*795d594fSAndroid Build Coastguard Worker                                               dex::TypeIndex type_index,
870*795d594fSAndroid Build Coastguard Worker                                               vixl::aarch64::Label* adrp_label = nullptr);
871*795d594fSAndroid Build Coastguard Worker 
872*795d594fSAndroid Build Coastguard Worker   // Add a new app image type patch for an instruction and return the label
873*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
874*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
875*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
876*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewAppImageTypePatch(const DexFile& dex_file,
877*795d594fSAndroid Build Coastguard Worker                                              dex::TypeIndex type_index,
878*795d594fSAndroid Build Coastguard Worker                                              vixl::aarch64::Label* adrp_label = nullptr);
879*795d594fSAndroid Build Coastguard Worker 
880*795d594fSAndroid Build Coastguard Worker   // Add a new .bss entry type patch for an instruction and return the label
881*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
882*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
883*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
884*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBssEntryTypePatch(HLoadClass* load_class,
885*795d594fSAndroid Build Coastguard Worker                                              vixl::aarch64::Label* adrp_label = nullptr);
886*795d594fSAndroid Build Coastguard Worker 
887*795d594fSAndroid Build Coastguard Worker   // Add a new boot image string patch for an instruction and return the label
888*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
889*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
890*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
891*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageStringPatch(const DexFile& dex_file,
892*795d594fSAndroid Build Coastguard Worker                                                 dex::StringIndex string_index,
893*795d594fSAndroid Build Coastguard Worker                                                 vixl::aarch64::Label* adrp_label = nullptr);
894*795d594fSAndroid Build Coastguard Worker 
895*795d594fSAndroid Build Coastguard Worker   // Add a new .bss entry string patch for an instruction and return the label
896*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
897*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
898*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
899*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewStringBssEntryPatch(const DexFile& dex_file,
900*795d594fSAndroid Build Coastguard Worker                                                dex::StringIndex string_index,
901*795d594fSAndroid Build Coastguard Worker                                                vixl::aarch64::Label* adrp_label = nullptr);
902*795d594fSAndroid Build Coastguard Worker 
903*795d594fSAndroid Build Coastguard Worker   // Add a new .bss entry MethodType patch for an instruction and return the label
904*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
905*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
906*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
907*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewMethodTypeBssEntryPatch(HLoadMethodType* load_method_type,
908*795d594fSAndroid Build Coastguard Worker                                                    vixl::aarch64::Label* adrp_label = nullptr);
909*795d594fSAndroid Build Coastguard Worker 
910*795d594fSAndroid Build Coastguard Worker   // Add a new boot image JNI entrypoint patch for an instruction and return the label
911*795d594fSAndroid Build Coastguard Worker   // to be bound before the instruction. The instruction will be either the
912*795d594fSAndroid Build Coastguard Worker   // ADRP (pass `adrp_label = null`) or the LDR (pass `adrp_label` pointing
913*795d594fSAndroid Build Coastguard Worker   // to the associated ADRP patch label).
914*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewBootImageJniEntrypointPatch(MethodReference target_method,
915*795d594fSAndroid Build Coastguard Worker                                                        vixl::aarch64::Label* adrp_label = nullptr);
916*795d594fSAndroid Build Coastguard Worker 
917*795d594fSAndroid Build Coastguard Worker   // Emit the BL instruction for entrypoint thunk call and record the associated patch for AOT.
918*795d594fSAndroid Build Coastguard Worker   void EmitEntrypointThunkCall(ThreadOffset64 entrypoint_offset);
919*795d594fSAndroid Build Coastguard Worker 
920*795d594fSAndroid Build Coastguard Worker   // Emit the CBNZ instruction for baker read barrier and record
921*795d594fSAndroid Build Coastguard Worker   // the associated patch for AOT or slow path for JIT.
922*795d594fSAndroid Build Coastguard Worker   void EmitBakerReadBarrierCbnz(uint32_t custom_data);
923*795d594fSAndroid Build Coastguard Worker 
DeduplicateBootImageAddressLiteral(uint64_t address)924*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageAddressLiteral(uint64_t address) {
925*795d594fSAndroid Build Coastguard Worker     return jit_patches_.DeduplicateBootImageAddressLiteral(address);
926*795d594fSAndroid Build Coastguard Worker   }
DeduplicateJitStringLiteral(const DexFile & dex_file,dex::StringIndex string_index,Handle<mirror::String> handle)927*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Literal<uint32_t>* DeduplicateJitStringLiteral(const DexFile& dex_file,
928*795d594fSAndroid Build Coastguard Worker                                                                 dex::StringIndex string_index,
929*795d594fSAndroid Build Coastguard Worker                                                                 Handle<mirror::String> handle) {
930*795d594fSAndroid Build Coastguard Worker     return jit_patches_.DeduplicateJitStringLiteral(
931*795d594fSAndroid Build Coastguard Worker         dex_file, string_index, handle, GetCodeGenerationData());
932*795d594fSAndroid Build Coastguard Worker   }
DeduplicateJitClassLiteral(const DexFile & dex_file,dex::TypeIndex class_index,Handle<mirror::Class> handle)933*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Literal<uint32_t>* DeduplicateJitClassLiteral(const DexFile& dex_file,
934*795d594fSAndroid Build Coastguard Worker                                                                dex::TypeIndex class_index,
935*795d594fSAndroid Build Coastguard Worker                                                                Handle<mirror::Class> handle) {
936*795d594fSAndroid Build Coastguard Worker     return jit_patches_.DeduplicateJitClassLiteral(
937*795d594fSAndroid Build Coastguard Worker         dex_file, class_index, handle, GetCodeGenerationData());
938*795d594fSAndroid Build Coastguard Worker   }
DeduplicateJitMethodTypeLiteral(const DexFile & dex_file,dex::ProtoIndex proto_index,Handle<mirror::MethodType> handle)939*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Literal<uint32_t>* DeduplicateJitMethodTypeLiteral(
940*795d594fSAndroid Build Coastguard Worker       const DexFile& dex_file,
941*795d594fSAndroid Build Coastguard Worker       dex::ProtoIndex proto_index,
942*795d594fSAndroid Build Coastguard Worker       Handle<mirror::MethodType> handle) {
943*795d594fSAndroid Build Coastguard Worker     return jit_patches_.DeduplicateJitMethodTypeLiteral(
944*795d594fSAndroid Build Coastguard Worker         dex_file, proto_index, handle, GetCodeGenerationData());
945*795d594fSAndroid Build Coastguard Worker   }
946*795d594fSAndroid Build Coastguard Worker 
947*795d594fSAndroid Build Coastguard Worker   void EmitAdrpPlaceholder(vixl::aarch64::Label* fixup_label, vixl::aarch64::Register reg);
948*795d594fSAndroid Build Coastguard Worker   void EmitAddPlaceholder(vixl::aarch64::Label* fixup_label,
949*795d594fSAndroid Build Coastguard Worker                           vixl::aarch64::Register out,
950*795d594fSAndroid Build Coastguard Worker                           vixl::aarch64::Register base);
951*795d594fSAndroid Build Coastguard Worker   void EmitLdrOffsetPlaceholder(vixl::aarch64::Label* fixup_label,
952*795d594fSAndroid Build Coastguard Worker                                 vixl::aarch64::Register out,
953*795d594fSAndroid Build Coastguard Worker                                 vixl::aarch64::Register base);
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker   void LoadBootImageRelRoEntry(vixl::aarch64::Register reg, uint32_t boot_image_offset);
956*795d594fSAndroid Build Coastguard Worker   void LoadBootImageAddress(vixl::aarch64::Register reg, uint32_t boot_image_reference);
957*795d594fSAndroid Build Coastguard Worker   void LoadTypeForBootImageIntrinsic(vixl::aarch64::Register reg, TypeReference type_reference);
958*795d594fSAndroid Build Coastguard Worker   void LoadIntrinsicDeclaringClass(vixl::aarch64::Register reg, HInvoke* invoke);
959*795d594fSAndroid Build Coastguard Worker   void LoadClassRootForIntrinsic(vixl::aarch64::Register reg, ClassRoot class_root);
960*795d594fSAndroid Build Coastguard Worker 
961*795d594fSAndroid Build Coastguard Worker   void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
962*795d594fSAndroid Build Coastguard Worker   bool NeedsThunkCode(const linker::LinkerPatch& patch) const override;
963*795d594fSAndroid Build Coastguard Worker   void EmitThunkCode(const linker::LinkerPatch& patch,
964*795d594fSAndroid Build Coastguard Worker                      /*out*/ ArenaVector<uint8_t>* code,
965*795d594fSAndroid Build Coastguard Worker                      /*out*/ std::string* debug_name) override;
966*795d594fSAndroid Build Coastguard Worker 
967*795d594fSAndroid Build Coastguard Worker   void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) override;
968*795d594fSAndroid Build Coastguard Worker 
969*795d594fSAndroid Build Coastguard Worker   // Generate a GC root reference load:
970*795d594fSAndroid Build Coastguard Worker   //
971*795d594fSAndroid Build Coastguard Worker   //   root <- *(obj + offset)
972*795d594fSAndroid Build Coastguard Worker   //
973*795d594fSAndroid Build Coastguard Worker   // while honoring read barriers based on read_barrier_option.
974*795d594fSAndroid Build Coastguard Worker   void GenerateGcRootFieldLoad(HInstruction* instruction,
975*795d594fSAndroid Build Coastguard Worker                                Location root,
976*795d594fSAndroid Build Coastguard Worker                                vixl::aarch64::Register obj,
977*795d594fSAndroid Build Coastguard Worker                                uint32_t offset,
978*795d594fSAndroid Build Coastguard Worker                                vixl::aarch64::Label* fixup_label,
979*795d594fSAndroid Build Coastguard Worker                                ReadBarrierOption read_barrier_option);
980*795d594fSAndroid Build Coastguard Worker   // Generate MOV for the `old_value` in intrinsic and mark it with Baker read barrier.
981*795d594fSAndroid Build Coastguard Worker   void GenerateIntrinsicMoveWithBakerReadBarrier(vixl::aarch64::Register marked_old_value,
982*795d594fSAndroid Build Coastguard Worker                                                  vixl::aarch64::Register old_value);
983*795d594fSAndroid Build Coastguard Worker   // Fast path implementation of ReadBarrier::Barrier for a heap
984*795d594fSAndroid Build Coastguard Worker   // reference field load when Baker's read barriers are used.
985*795d594fSAndroid Build Coastguard Worker   // Overload suitable for Unsafe.getObject/-Volatile() intrinsic.
986*795d594fSAndroid Build Coastguard Worker   void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
987*795d594fSAndroid Build Coastguard Worker                                              Location ref,
988*795d594fSAndroid Build Coastguard Worker                                              vixl::aarch64::Register obj,
989*795d594fSAndroid Build Coastguard Worker                                              const vixl::aarch64::MemOperand& src,
990*795d594fSAndroid Build Coastguard Worker                                              bool needs_null_check,
991*795d594fSAndroid Build Coastguard Worker                                              bool use_load_acquire);
992*795d594fSAndroid Build Coastguard Worker   // Fast path implementation of ReadBarrier::Barrier for a heap
993*795d594fSAndroid Build Coastguard Worker   // reference field load when Baker's read barriers are used.
994*795d594fSAndroid Build Coastguard Worker   void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
995*795d594fSAndroid Build Coastguard Worker                                              Location ref,
996*795d594fSAndroid Build Coastguard Worker                                              vixl::aarch64::Register obj,
997*795d594fSAndroid Build Coastguard Worker                                              uint32_t offset,
998*795d594fSAndroid Build Coastguard Worker                                              Location maybe_temp,
999*795d594fSAndroid Build Coastguard Worker                                              bool needs_null_check,
1000*795d594fSAndroid Build Coastguard Worker                                              bool use_load_acquire);
1001*795d594fSAndroid Build Coastguard Worker   // Fast path implementation of ReadBarrier::Barrier for a heap
1002*795d594fSAndroid Build Coastguard Worker   // reference array load when Baker's read barriers are used.
1003*795d594fSAndroid Build Coastguard Worker   void GenerateArrayLoadWithBakerReadBarrier(HArrayGet* instruction,
1004*795d594fSAndroid Build Coastguard Worker                                              Location ref,
1005*795d594fSAndroid Build Coastguard Worker                                              vixl::aarch64::Register obj,
1006*795d594fSAndroid Build Coastguard Worker                                              uint32_t data_offset,
1007*795d594fSAndroid Build Coastguard Worker                                              Location index,
1008*795d594fSAndroid Build Coastguard Worker                                              bool needs_null_check);
1009*795d594fSAndroid Build Coastguard Worker 
1010*795d594fSAndroid Build Coastguard Worker   // Emit code checking the status of the Marking Register, and
1011*795d594fSAndroid Build Coastguard Worker   // aborting the program if MR does not match the value stored in the
1012*795d594fSAndroid Build Coastguard Worker   // art::Thread object. Code is only emitted in debug mode and if
1013*795d594fSAndroid Build Coastguard Worker   // CompilerOptions::EmitRunTimeChecksInDebugMode returns true.
1014*795d594fSAndroid Build Coastguard Worker   //
1015*795d594fSAndroid Build Coastguard Worker   // Argument `code` is used to identify the different occurrences of
1016*795d594fSAndroid Build Coastguard Worker   // MaybeGenerateMarkingRegisterCheck in the code generator, and is
1017*795d594fSAndroid Build Coastguard Worker   // passed to the BRK instruction.
1018*795d594fSAndroid Build Coastguard Worker   //
1019*795d594fSAndroid Build Coastguard Worker   // If `temp_loc` is a valid location, it is expected to be a
1020*795d594fSAndroid Build Coastguard Worker   // register and will be used as a temporary to generate code;
1021*795d594fSAndroid Build Coastguard Worker   // otherwise, a temporary will be fetched from the core register
1022*795d594fSAndroid Build Coastguard Worker   // scratch pool.
1023*795d594fSAndroid Build Coastguard Worker   virtual void MaybeGenerateMarkingRegisterCheck(int code,
1024*795d594fSAndroid Build Coastguard Worker                                                  Location temp_loc = Location::NoLocation());
1025*795d594fSAndroid Build Coastguard Worker 
1026*795d594fSAndroid Build Coastguard Worker   // Create slow path for a read barrier for a heap reference within `instruction`.
1027*795d594fSAndroid Build Coastguard Worker   //
1028*795d594fSAndroid Build Coastguard Worker   // This is a helper function for GenerateReadBarrierSlow() that has the same
1029*795d594fSAndroid Build Coastguard Worker   // arguments. The creation and adding of the slow path is exposed for intrinsics
1030*795d594fSAndroid Build Coastguard Worker   // that cannot use GenerateReadBarrierSlow() from their own slow paths.
1031*795d594fSAndroid Build Coastguard Worker   SlowPathCodeARM64* AddReadBarrierSlowPath(HInstruction* instruction,
1032*795d594fSAndroid Build Coastguard Worker                                             Location out,
1033*795d594fSAndroid Build Coastguard Worker                                             Location ref,
1034*795d594fSAndroid Build Coastguard Worker                                             Location obj,
1035*795d594fSAndroid Build Coastguard Worker                                             uint32_t offset,
1036*795d594fSAndroid Build Coastguard Worker                                             Location index);
1037*795d594fSAndroid Build Coastguard Worker 
1038*795d594fSAndroid Build Coastguard Worker   // Generate a read barrier for a heap reference within `instruction`
1039*795d594fSAndroid Build Coastguard Worker   // using a slow path.
1040*795d594fSAndroid Build Coastguard Worker   //
1041*795d594fSAndroid Build Coastguard Worker   // A read barrier for an object reference read from the heap is
1042*795d594fSAndroid Build Coastguard Worker   // implemented as a call to the artReadBarrierSlow runtime entry
1043*795d594fSAndroid Build Coastguard Worker   // point, which is passed the values in locations `ref`, `obj`, and
1044*795d594fSAndroid Build Coastguard Worker   // `offset`:
1045*795d594fSAndroid Build Coastguard Worker   //
1046*795d594fSAndroid Build Coastguard Worker   //   mirror::Object* artReadBarrierSlow(mirror::Object* ref,
1047*795d594fSAndroid Build Coastguard Worker   //                                      mirror::Object* obj,
1048*795d594fSAndroid Build Coastguard Worker   //                                      uint32_t offset);
1049*795d594fSAndroid Build Coastguard Worker   //
1050*795d594fSAndroid Build Coastguard Worker   // The `out` location contains the value returned by
1051*795d594fSAndroid Build Coastguard Worker   // artReadBarrierSlow.
1052*795d594fSAndroid Build Coastguard Worker   //
1053*795d594fSAndroid Build Coastguard Worker   // When `index` is provided (i.e. for array accesses), the offset
1054*795d594fSAndroid Build Coastguard Worker   // value passed to artReadBarrierSlow is adjusted to take `index`
1055*795d594fSAndroid Build Coastguard Worker   // into account.
1056*795d594fSAndroid Build Coastguard Worker   void GenerateReadBarrierSlow(HInstruction* instruction,
1057*795d594fSAndroid Build Coastguard Worker                                Location out,
1058*795d594fSAndroid Build Coastguard Worker                                Location ref,
1059*795d594fSAndroid Build Coastguard Worker                                Location obj,
1060*795d594fSAndroid Build Coastguard Worker                                uint32_t offset,
1061*795d594fSAndroid Build Coastguard Worker                                Location index = Location::NoLocation());
1062*795d594fSAndroid Build Coastguard Worker 
1063*795d594fSAndroid Build Coastguard Worker   // If read barriers are enabled, generate a read barrier for a heap
1064*795d594fSAndroid Build Coastguard Worker   // reference using a slow path. If heap poisoning is enabled, also
1065*795d594fSAndroid Build Coastguard Worker   // unpoison the reference in `out`.
1066*795d594fSAndroid Build Coastguard Worker   void MaybeGenerateReadBarrierSlow(HInstruction* instruction,
1067*795d594fSAndroid Build Coastguard Worker                                     Location out,
1068*795d594fSAndroid Build Coastguard Worker                                     Location ref,
1069*795d594fSAndroid Build Coastguard Worker                                     Location obj,
1070*795d594fSAndroid Build Coastguard Worker                                     uint32_t offset,
1071*795d594fSAndroid Build Coastguard Worker                                     Location index = Location::NoLocation());
1072*795d594fSAndroid Build Coastguard Worker 
1073*795d594fSAndroid Build Coastguard Worker   // Generate a read barrier for a GC root within `instruction` using
1074*795d594fSAndroid Build Coastguard Worker   // a slow path.
1075*795d594fSAndroid Build Coastguard Worker   //
1076*795d594fSAndroid Build Coastguard Worker   // A read barrier for an object reference GC root is implemented as
1077*795d594fSAndroid Build Coastguard Worker   // a call to the artReadBarrierForRootSlow runtime entry point,
1078*795d594fSAndroid Build Coastguard Worker   // which is passed the value in location `root`:
1079*795d594fSAndroid Build Coastguard Worker   //
1080*795d594fSAndroid Build Coastguard Worker   //   mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root);
1081*795d594fSAndroid Build Coastguard Worker   //
1082*795d594fSAndroid Build Coastguard Worker   // The `out` location contains the value returned by
1083*795d594fSAndroid Build Coastguard Worker   // artReadBarrierForRootSlow.
1084*795d594fSAndroid Build Coastguard Worker   void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root);
1085*795d594fSAndroid Build Coastguard Worker 
1086*795d594fSAndroid Build Coastguard Worker   void IncreaseFrame(size_t adjustment) override;
1087*795d594fSAndroid Build Coastguard Worker   void DecreaseFrame(size_t adjustment) override;
1088*795d594fSAndroid Build Coastguard Worker 
1089*795d594fSAndroid Build Coastguard Worker   void GenerateNop() override;
1090*795d594fSAndroid Build Coastguard Worker 
1091*795d594fSAndroid Build Coastguard Worker   void GenerateImplicitNullCheck(HNullCheck* instruction) override;
1092*795d594fSAndroid Build Coastguard Worker   void GenerateExplicitNullCheck(HNullCheck* instruction) override;
1093*795d594fSAndroid Build Coastguard Worker 
MaybeRecordImplicitNullCheck(HInstruction * instr)1094*795d594fSAndroid Build Coastguard Worker   void MaybeRecordImplicitNullCheck(HInstruction* instr) final {
1095*795d594fSAndroid Build Coastguard Worker     // The function must be only called within special scopes
1096*795d594fSAndroid Build Coastguard Worker     // (EmissionCheckScope, ExactAssemblyScope) which prevent generation of
1097*795d594fSAndroid Build Coastguard Worker     // veneer/literal pools by VIXL assembler.
1098*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(GetVIXLAssembler()->ArePoolsBlocked(), true)
1099*795d594fSAndroid Build Coastguard Worker         << "The function must only be called within EmissionCheckScope or ExactAssemblyScope";
1100*795d594fSAndroid Build Coastguard Worker     CodeGenerator::MaybeRecordImplicitNullCheck(instr);
1101*795d594fSAndroid Build Coastguard Worker   }
1102*795d594fSAndroid Build Coastguard Worker 
1103*795d594fSAndroid Build Coastguard Worker   void MaybeGenerateInlineCacheCheck(HInstruction* instruction, vixl::aarch64::Register klass);
1104*795d594fSAndroid Build Coastguard Worker   void MaybeIncrementHotness(HSuspendCheck* suspend_check, bool is_frame_entry);
1105*795d594fSAndroid Build Coastguard Worker   void MaybeRecordTraceEvent(bool is_method_entry);
1106*795d594fSAndroid Build Coastguard Worker 
1107*795d594fSAndroid Build Coastguard Worker   bool CanUseImplicitSuspendCheck() const;
1108*795d594fSAndroid Build Coastguard Worker 
1109*795d594fSAndroid Build Coastguard Worker  private:
1110*795d594fSAndroid Build Coastguard Worker   // Encoding of thunk type and data for link-time generated thunks for Baker read barriers.
1111*795d594fSAndroid Build Coastguard Worker 
1112*795d594fSAndroid Build Coastguard Worker   enum class BakerReadBarrierKind : uint8_t {
1113*795d594fSAndroid Build Coastguard Worker     kField,     // Field get or array get with constant offset (i.e. constant index).
1114*795d594fSAndroid Build Coastguard Worker     kAcquire,   // Volatile field get.
1115*795d594fSAndroid Build Coastguard Worker     kArray,     // Array get with index in register.
1116*795d594fSAndroid Build Coastguard Worker     kGcRoot,    // GC root load.
1117*795d594fSAndroid Build Coastguard Worker     kLast = kGcRoot
1118*795d594fSAndroid Build Coastguard Worker   };
1119*795d594fSAndroid Build Coastguard Worker 
1120*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kBakerReadBarrierInvalidEncodedReg = /* sp/zr is invalid */ 31u;
1121*795d594fSAndroid Build Coastguard Worker 
1122*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBitsForBakerReadBarrierKind =
1123*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(BakerReadBarrierKind::kLast));
1124*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBakerReadBarrierBitsForRegister =
1125*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(kBakerReadBarrierInvalidEncodedReg);
1126*795d594fSAndroid Build Coastguard Worker   using BakerReadBarrierKindField =
1127*795d594fSAndroid Build Coastguard Worker       BitField<BakerReadBarrierKind, 0, kBitsForBakerReadBarrierKind>;
1128*795d594fSAndroid Build Coastguard Worker   using BakerReadBarrierFirstRegField =
1129*795d594fSAndroid Build Coastguard Worker       BitField<uint32_t, kBitsForBakerReadBarrierKind, kBakerReadBarrierBitsForRegister>;
1130*795d594fSAndroid Build Coastguard Worker   using BakerReadBarrierSecondRegField =
1131*795d594fSAndroid Build Coastguard Worker       BitField<uint32_t,
1132*795d594fSAndroid Build Coastguard Worker                kBitsForBakerReadBarrierKind + kBakerReadBarrierBitsForRegister,
1133*795d594fSAndroid Build Coastguard Worker                kBakerReadBarrierBitsForRegister>;
1134*795d594fSAndroid Build Coastguard Worker 
CheckValidReg(uint32_t reg)1135*795d594fSAndroid Build Coastguard Worker   static void CheckValidReg(uint32_t reg) {
1136*795d594fSAndroid Build Coastguard Worker     DCHECK(reg < vixl::aarch64::lr.GetCode() &&
1137*795d594fSAndroid Build Coastguard Worker            reg != vixl::aarch64::ip0.GetCode() &&
1138*795d594fSAndroid Build Coastguard Worker            reg != vixl::aarch64::ip1.GetCode()) << reg;
1139*795d594fSAndroid Build Coastguard Worker   }
1140*795d594fSAndroid Build Coastguard Worker 
EncodeBakerReadBarrierFieldData(uint32_t base_reg,uint32_t holder_reg)1141*795d594fSAndroid Build Coastguard Worker   static inline uint32_t EncodeBakerReadBarrierFieldData(uint32_t base_reg, uint32_t holder_reg) {
1142*795d594fSAndroid Build Coastguard Worker     CheckValidReg(base_reg);
1143*795d594fSAndroid Build Coastguard Worker     CheckValidReg(holder_reg);
1144*795d594fSAndroid Build Coastguard Worker     return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kField) |
1145*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierFirstRegField::Encode(base_reg) |
1146*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierSecondRegField::Encode(holder_reg);
1147*795d594fSAndroid Build Coastguard Worker   }
1148*795d594fSAndroid Build Coastguard Worker 
EncodeBakerReadBarrierAcquireData(uint32_t base_reg,uint32_t holder_reg)1149*795d594fSAndroid Build Coastguard Worker   static inline uint32_t EncodeBakerReadBarrierAcquireData(uint32_t base_reg, uint32_t holder_reg) {
1150*795d594fSAndroid Build Coastguard Worker     CheckValidReg(base_reg);
1151*795d594fSAndroid Build Coastguard Worker     CheckValidReg(holder_reg);
1152*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(base_reg, holder_reg);
1153*795d594fSAndroid Build Coastguard Worker     return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kAcquire) |
1154*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierFirstRegField::Encode(base_reg) |
1155*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierSecondRegField::Encode(holder_reg);
1156*795d594fSAndroid Build Coastguard Worker   }
1157*795d594fSAndroid Build Coastguard Worker 
EncodeBakerReadBarrierArrayData(uint32_t base_reg)1158*795d594fSAndroid Build Coastguard Worker   static inline uint32_t EncodeBakerReadBarrierArrayData(uint32_t base_reg) {
1159*795d594fSAndroid Build Coastguard Worker     CheckValidReg(base_reg);
1160*795d594fSAndroid Build Coastguard Worker     return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kArray) |
1161*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierFirstRegField::Encode(base_reg) |
1162*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierSecondRegField::Encode(kBakerReadBarrierInvalidEncodedReg);
1163*795d594fSAndroid Build Coastguard Worker   }
1164*795d594fSAndroid Build Coastguard Worker 
EncodeBakerReadBarrierGcRootData(uint32_t root_reg)1165*795d594fSAndroid Build Coastguard Worker   static inline uint32_t EncodeBakerReadBarrierGcRootData(uint32_t root_reg) {
1166*795d594fSAndroid Build Coastguard Worker     CheckValidReg(root_reg);
1167*795d594fSAndroid Build Coastguard Worker     return BakerReadBarrierKindField::Encode(BakerReadBarrierKind::kGcRoot) |
1168*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierFirstRegField::Encode(root_reg) |
1169*795d594fSAndroid Build Coastguard Worker            BakerReadBarrierSecondRegField::Encode(kBakerReadBarrierInvalidEncodedReg);
1170*795d594fSAndroid Build Coastguard Worker   }
1171*795d594fSAndroid Build Coastguard Worker 
1172*795d594fSAndroid Build Coastguard Worker   void CompileBakerReadBarrierThunk(Arm64Assembler& assembler,
1173*795d594fSAndroid Build Coastguard Worker                                     uint32_t encoded_data,
1174*795d594fSAndroid Build Coastguard Worker                                     /*out*/ std::string* debug_name);
1175*795d594fSAndroid Build Coastguard Worker 
1176*795d594fSAndroid Build Coastguard Worker   // The PcRelativePatchInfo is used for PC-relative addressing of methods/strings/types,
1177*795d594fSAndroid Build Coastguard Worker   // whether through .data.img.rel.ro, .bss, or directly in the boot image.
1178*795d594fSAndroid Build Coastguard Worker   struct PcRelativePatchInfo : PatchInfo<vixl::aarch64::Label> {
PcRelativePatchInfoPcRelativePatchInfo1179*795d594fSAndroid Build Coastguard Worker     PcRelativePatchInfo(const DexFile* dex_file, uint32_t off_or_idx)
1180*795d594fSAndroid Build Coastguard Worker         : PatchInfo<vixl::aarch64::Label>(dex_file, off_or_idx), pc_insn_label() { }
1181*795d594fSAndroid Build Coastguard Worker 
1182*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::Label* pc_insn_label;
1183*795d594fSAndroid Build Coastguard Worker   };
1184*795d594fSAndroid Build Coastguard Worker 
1185*795d594fSAndroid Build Coastguard Worker   struct BakerReadBarrierPatchInfo {
BakerReadBarrierPatchInfoBakerReadBarrierPatchInfo1186*795d594fSAndroid Build Coastguard Worker     explicit BakerReadBarrierPatchInfo(uint32_t data) : label(), custom_data(data) { }
1187*795d594fSAndroid Build Coastguard Worker 
1188*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::Label label;
1189*795d594fSAndroid Build Coastguard Worker     uint32_t custom_data;
1190*795d594fSAndroid Build Coastguard Worker   };
1191*795d594fSAndroid Build Coastguard Worker 
1192*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label* NewPcRelativePatch(const DexFile* dex_file,
1193*795d594fSAndroid Build Coastguard Worker                                            uint32_t offset_or_index,
1194*795d594fSAndroid Build Coastguard Worker                                            vixl::aarch64::Label* adrp_label,
1195*795d594fSAndroid Build Coastguard Worker                                            ArenaDeque<PcRelativePatchInfo>* patches);
1196*795d594fSAndroid Build Coastguard Worker 
1197*795d594fSAndroid Build Coastguard Worker   void FixJumpTables();
1198*795d594fSAndroid Build Coastguard Worker 
1199*795d594fSAndroid Build Coastguard Worker   template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
1200*795d594fSAndroid Build Coastguard Worker   static void EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo>& infos,
1201*795d594fSAndroid Build Coastguard Worker                                           ArenaVector<linker::LinkerPatch>* linker_patches);
1202*795d594fSAndroid Build Coastguard Worker 
1203*795d594fSAndroid Build Coastguard Worker   // Returns whether SVE features are supported and should be used.
1204*795d594fSAndroid Build Coastguard Worker   bool ShouldUseSVE() const;
1205*795d594fSAndroid Build Coastguard Worker 
1206*795d594fSAndroid Build Coastguard Worker   // Labels for each block that will be compiled.
1207*795d594fSAndroid Build Coastguard Worker   // We use a deque so that the `vixl::aarch64::Label` objects do not move in memory.
1208*795d594fSAndroid Build Coastguard Worker   ArenaDeque<vixl::aarch64::Label> block_labels_;  // Indexed by block id.
1209*795d594fSAndroid Build Coastguard Worker   vixl::aarch64::Label frame_entry_label_;
1210*795d594fSAndroid Build Coastguard Worker   ArenaVector<std::unique_ptr<JumpTableARM64>> jump_tables_;
1211*795d594fSAndroid Build Coastguard Worker 
1212*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64Neon location_builder_neon_;
1213*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64Neon instruction_visitor_neon_;
1214*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64Sve location_builder_sve_;
1215*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64Sve instruction_visitor_sve_;
1216*795d594fSAndroid Build Coastguard Worker 
1217*795d594fSAndroid Build Coastguard Worker   LocationsBuilderARM64* location_builder_;
1218*795d594fSAndroid Build Coastguard Worker   InstructionCodeGeneratorARM64* instruction_visitor_;
1219*795d594fSAndroid Build Coastguard Worker   ParallelMoveResolverARM64 move_resolver_;
1220*795d594fSAndroid Build Coastguard Worker   Arm64Assembler assembler_;
1221*795d594fSAndroid Build Coastguard Worker 
1222*795d594fSAndroid Build Coastguard Worker   // PC-relative method patch info for kBootImageLinkTimePcRelative.
1223*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
1224*795d594fSAndroid Build Coastguard Worker   // PC-relative method patch info for kAppImageRelRo.
1225*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> app_image_method_patches_;
1226*795d594fSAndroid Build Coastguard Worker   // PC-relative method patch info for kBssEntry.
1227*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
1228*795d594fSAndroid Build Coastguard Worker   // PC-relative type patch info for kBootImageLinkTimePcRelative.
1229*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
1230*795d594fSAndroid Build Coastguard Worker   // PC-relative type patch info for kAppImageRelRo.
1231*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> app_image_type_patches_;
1232*795d594fSAndroid Build Coastguard Worker   // PC-relative type patch info for kBssEntry.
1233*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
1234*795d594fSAndroid Build Coastguard Worker   // PC-relative public type patch info for kBssEntryPublic.
1235*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_;
1236*795d594fSAndroid Build Coastguard Worker   // PC-relative package type patch info for kBssEntryPackage.
1237*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_;
1238*795d594fSAndroid Build Coastguard Worker   // PC-relative String patch info for kBootImageLinkTimePcRelative.
1239*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
1240*795d594fSAndroid Build Coastguard Worker   // PC-relative String patch info for kBssEntry.
1241*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
1242*795d594fSAndroid Build Coastguard Worker   // PC-relative MethodType patch info for kBssEntry.
1243*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> method_type_bss_entry_patches_;
1244*795d594fSAndroid Build Coastguard Worker   // PC-relative method patch info for kBootImageLinkTimePcRelative+kCallCriticalNative.
1245*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> boot_image_jni_entrypoint_patches_;
1246*795d594fSAndroid Build Coastguard Worker   // PC-relative patch info for IntrinsicObjects for the boot image,
1247*795d594fSAndroid Build Coastguard Worker   // and for method/type/string patches for kBootImageRelRo otherwise.
1248*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PcRelativePatchInfo> boot_image_other_patches_;
1249*795d594fSAndroid Build Coastguard Worker   // Patch info for calls to entrypoint dispatch thunks. Used for slow paths.
1250*795d594fSAndroid Build Coastguard Worker   ArenaDeque<PatchInfo<vixl::aarch64::Label>> call_entrypoint_patches_;
1251*795d594fSAndroid Build Coastguard Worker   // Baker read barrier patch info.
1252*795d594fSAndroid Build Coastguard Worker   ArenaDeque<BakerReadBarrierPatchInfo> baker_read_barrier_patches_;
1253*795d594fSAndroid Build Coastguard Worker 
1254*795d594fSAndroid Build Coastguard Worker   JitPatchesARM64 jit_patches_;
1255*795d594fSAndroid Build Coastguard Worker 
1256*795d594fSAndroid Build Coastguard Worker   // Baker read barrier slow paths, mapping custom data (uint32_t) to label.
1257*795d594fSAndroid Build Coastguard Worker   // Wrap the label to work around vixl::aarch64::Label being non-copyable
1258*795d594fSAndroid Build Coastguard Worker   // and non-moveable and as such unusable in ArenaSafeMap<>.
1259*795d594fSAndroid Build Coastguard Worker   struct LabelWrapper {
LabelWrapperLabelWrapper1260*795d594fSAndroid Build Coastguard Worker     LabelWrapper(const LabelWrapper& src)
1261*795d594fSAndroid Build Coastguard Worker         : label() {
1262*795d594fSAndroid Build Coastguard Worker       DCHECK(!src.label.IsLinked() && !src.label.IsBound());
1263*795d594fSAndroid Build Coastguard Worker     }
1264*795d594fSAndroid Build Coastguard Worker     LabelWrapper() = default;
1265*795d594fSAndroid Build Coastguard Worker     vixl::aarch64::Label label;
1266*795d594fSAndroid Build Coastguard Worker   };
1267*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<uint32_t, LabelWrapper> jit_baker_read_barrier_slow_paths_;
1268*795d594fSAndroid Build Coastguard Worker 
1269*795d594fSAndroid Build Coastguard Worker   friend class linker::Arm64RelativePatcherTest;
1270*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CodeGeneratorARM64);
1271*795d594fSAndroid Build Coastguard Worker };
1272*795d594fSAndroid Build Coastguard Worker 
GetAssembler()1273*795d594fSAndroid Build Coastguard Worker inline Arm64Assembler* ParallelMoveResolverARM64::GetAssembler() const {
1274*795d594fSAndroid Build Coastguard Worker   return codegen_->GetAssembler();
1275*795d594fSAndroid Build Coastguard Worker }
1276*795d594fSAndroid Build Coastguard Worker 
1277*795d594fSAndroid Build Coastguard Worker }  // namespace arm64
1278*795d594fSAndroid Build Coastguard Worker }  // namespace art
1279*795d594fSAndroid Build Coastguard Worker 
1280*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_ARM64_H_
1281