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