code_generator.h revision 175dc732c80e6f2afd83209348124df349290ba8
1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/*
2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License.
6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at
7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and
14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License.
15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */
16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
17d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
18d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
19d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h"
213416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle#include "arch/instruction_set_features.h"
22f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_containers.h"
23f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_object.h"
2401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray#include "base/bit_field.h"
25cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
26bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#include "globals.h"
27eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames#include "graph_visualizer.h"
284e3d23aa1523718ea1fdf3a32516d2f9d81e84feNicolas Geoffray#include "locations.h"
29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "memory_region.h"
30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
31ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu#include "optimizing_compiler_stats.h"
323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray#include "stack_map_stream.h"
33d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
34d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
35d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
366d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double.
376d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double.
396d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
406d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain
41e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive integer.
42e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int32_t constexpr kPrimIntMin = 0x80000000;
43e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive long.
44e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000);
45e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell
463f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer.
473f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff;
48624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long.
49e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff);
503f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain
5192a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler;
52e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator;
5392cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffrayclass DexCompilationUnit;
54581550137ee3a068a14224870e71aeee924a0646Vladimir Markoclass LinkerPatch;
55f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver;
56e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeclass SrcMapElem;
57e21dc3db191df04c100620965bee4617b3b24397Andreas Gampetemplate <class Alloc>
58e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass SrcMap;
59e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeusing DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
6092cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray
61d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator {
62d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
63e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  CodeAllocator() {}
64e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~CodeAllocator() {}
65d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
66d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) = 0;
67d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
68d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
69d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
70d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
71d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
726a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> {
73e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public:
74eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  SlowPathCode() {
75eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) {
76eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_core_stack_offsets_[i] = kRegisterNotSaved;
77eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_fpu_stack_offsets_[i] = kRegisterNotSaved;
78eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    }
79eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
80eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
81e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~SlowPathCode() {}
82e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
83e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
84e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
85da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
86da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
87a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
88eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsCoreRegisterSaved(int reg) const {
89eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg] != kRegisterNotSaved;
90eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
91eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
92eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsFpuRegisterSaved(int reg) const {
93eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved;
94eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
95eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
96eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfCoreRegister(int reg) const {
97eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg];
98eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
99eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
100eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfFpuRegister(int reg) const {
101eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg];
102eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
103eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
1048158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames  virtual bool IsFatal() const { return false; }
1058158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames
1069931f319cf86c56c2855d800339a3410697633a6Alexandre Rames  virtual const char* GetDescription() const = 0;
1079931f319cf86c56c2855d800339a3410697633a6Alexandre Rames
108da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu protected:
109eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr size_t kMaximumNumberOfExpectedRegisters = 32;
110eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr uint32_t kRegisterNotSaved = -1;
111eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters];
112eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters];
113da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu
114da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu private:
115e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
116e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray};
117e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
1182d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitor {
1192d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain public:
1202d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  virtual Location GetNextLocation(Primitive::Type type) = 0;
121fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  virtual Location GetReturnLocation(Primitive::Type type) const = 0;
122fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  virtual Location GetMethodLocation() const = 0;
1232d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1242d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain protected:
1252d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  InvokeDexCallingConventionVisitor() {}
1262d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  virtual ~InvokeDexCallingConventionVisitor() {}
1272d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1282d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current index for core registers.
1292d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t gp_index_ = 0u;
1302d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current index for floating-point registers.
1312d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t float_index_ = 0u;
1322d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current stack index.
1332d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t stack_index_ = 0u;
1342d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1352d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain private:
1362d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
1372d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain};
1382d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
13912df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffrayclass CodeGenerator {
140d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
141d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // Compiles the graph to executable instructions. Returns whether the compilation
142d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // succeeded.
14373e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false);
14486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void CompileOptimized(CodeAllocator* allocator);
14512df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  static CodeGenerator* Create(HGraph* graph,
1463416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle                               InstructionSet instruction_set,
147cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const InstructionSetFeatures& isa_features,
148ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                               const CompilerOptions& compiler_options,
149ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                               OptimizingCompilerStats* stats = nullptr);
15012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  virtual ~CodeGenerator() {}
151d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
152787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* GetGraph() const { return graph_; }
153d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
154dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* GetNextBlockToEmit() const;
155dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const;
156bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
157bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
15886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
15986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Note that this follows the current calling convention.
16086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return GetFrameSize()
161e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        + InstructionSetPointerSize(GetInstructionSet())  // Art method
162e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray        + parameter->GetIndex() * kVRegSize;
16386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
16486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
16592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Initialize() = 0;
16632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  virtual void Finalize(CodeAllocator* allocator);
167581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  virtual void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches);
168d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameEntry() = 0;
169d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameExit() = 0;
17092a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Bind(HBasicBlock* block) = 0;
1714a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
172175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  virtual void MoveConstant(Location destination, int32_t value) = 0;
173787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual Assembler* GetAssembler() = 0;
174eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  virtual const Assembler& GetAssembler() const = 0;
175707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray  virtual size_t GetWordSize() const = 0;
176f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  virtual size_t GetFloatingPointSpillSlotSize() const = 0;
177de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual uintptr_t GetAddressOf(HBasicBlock* block) const = 0;
1784c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void InitializeCodeGeneration(size_t number_of_spill_slots,
1794c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_core_registers,
1804c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_fp_registers,
1814c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t number_of_out_slots,
182fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko                                const ArenaVector<HBasicBlock*>& block_order);
183ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  int32_t GetStackSlot(HLocal* local) const;
184ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  Location GetTemporaryLocation(HTemporary* temp) const;
185787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
186787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint32_t GetFrameSize() const { return frame_size_; }
187787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  void SetFrameSize(uint32_t size) { frame_size_ = size; }
1888ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
189d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; }
1908ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
19171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; }
19271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; }
193988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  virtual void SetupBlockedRegisters(bool is_baseline) const = 0;
19471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
1954dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  virtual void ComputeSpillMask() {
1964dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
1974dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
1984dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
1994dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
2004dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
2014dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  static uint32_t ComputeRegisterMask(const int* registers, size_t length) {
2024dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    uint32_t mask = 0;
2034dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    for (size_t i = 0, e = length; i < e; ++i) {
2044dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray      mask |= (1 << registers[i]);
2054dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    }
2064dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    return mask;
2074dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
2084dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
209a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
210a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
211412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  virtual InstructionSet GetInstructionSet() const = 0;
212cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
213cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
214cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
215ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu  void MaybeRecordStat(MethodCompilationStat compilation_stat, size_t count = 1) const;
216ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu
217102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Saves the register in the stack. Returns the size taken on stack.
218102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
219102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Restores the register from the stack. Returns the size taken on stack.
220102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
221234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
222234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
223234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
224234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
225840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0;
226234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  // Returns whether we should split long moves in parallel moves.
227234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual bool ShouldSplitLongMoves() const { return false; }
228a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
229988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsCoreCalleeSaveRegister(int reg) const {
230988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (core_callee_save_mask_ & (1 << reg)) != 0;
231988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
232988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
233988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsFloatingPointCalleeSaveRegister(int reg) const {
234988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (fpu_callee_save_mask_ & (1 << reg)) != 0;
235988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
236988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
2372a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  // Record native to dex mapping for a suspend point.  Required by runtime.
238eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr);
2392a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  // Record additional native to dex mappings for native debugging/profiling tools.
2402a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  void RecordNativeDebugInfo(uint32_t dex_pc, uintptr_t native_pc_begin, uintptr_t native_pc_end);
2412a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban
24277520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  bool CanMoveNullCheckToUser(HNullCheck* null_check);
24377520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  void MaybeRecordImplicitNullCheck(HInstruction* instruction);
244787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
24577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // Records a stack map which the runtime might use to set catch phi values
24677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // during exception delivery.
24777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // TODO: Replace with a catch-entering instruction that records the environment.
24877a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  void RecordCatchBlockInfo();
24977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil
25077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // Returns true if implicit null checks are allowed in the compiler options
25177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // and if the null check is not inside a try block. We currently cannot do
25277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // implicit null checks in that case because we need the NullCheckSlowPath to
25377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // save live registers, which may be needed by the runtime to set catch phis.
25477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const;
25577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil
256e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void AddSlowPath(SlowPathCode* slow_path) {
257e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray    slow_paths_.Add(slow_path);
258e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  }
259e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
2602a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  void SetSrcMap(DefaultSrcMap* src_map) { src_map_ = src_map; }
2612a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban
262f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko  void BuildMappingTable(ArenaVector<uint8_t>* vector) const;
263f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko  void BuildVMapTable(ArenaVector<uint8_t>* vector) const;
26492cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray  void BuildNativeGCMap(
265f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko      ArenaVector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
266f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko  void BuildStackMaps(ArenaVector<uint8_t>* vector);
267787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
2683e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain  bool IsBaseline() const {
2693e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain    return is_baseline_;
2703e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain  }
2713e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain
272f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool IsLeafMethod() const {
273f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    return is_leaf_;
274f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
275f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
276f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  void MarkNotLeaf() {
277f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    is_leaf_ = false;
278c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
279c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
280c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
281c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void SetRequiresCurrentMethod() {
282c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
283c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
284c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
285c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool RequiresCurrentMethod() const {
286c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return requires_current_method_;
287f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
288f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
2893c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // Clears the spill slots taken by loop phis in the `LocationSummary` of the
2903c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // suspend check. This is called when the code generator generates code
2913c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // for the suspend check at the back edge (instead of where the suspend check
2923c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // is, which is the loop entry). At this point, the spill slots for the phis
2933c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // have not been written to.
2943c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const;
2953c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
29671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
297102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
29871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
29919a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Helper that returns the pointer offset of an index in an object array.
30019a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Note: this method assumes we always have the same pointer size, regardless
30119a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // of the architecture.
30219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  static size_t GetCacheOffset(uint32_t index);
303e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  // Pointer variant for ArtMethod and ArtField arrays.
304e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  size_t GetCachePointerOffset(uint32_t index);
30519a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
3069021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray  void EmitParallelMoves(Location from1,
3079021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to1,
3089021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type1,
3099021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location from2,
3109021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to2,
3119021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type2);
312f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
313af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) {
314522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    // Check that null value is not represented as an integer constant.
315522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant());
316522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    return type == Primitive::kPrimNot && !value->IsNullConstant();
317af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  }
318af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray
31978e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames  void ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path);
32078e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames
321988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  void AddAllocatedRegister(Location location) {
322988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    allocated_registers_.Add(location);
323988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
324988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
32545b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray  bool HasAllocatedRegister(bool is_core, int reg) const {
32645b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray    return is_core
32745b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray        ? allocated_registers_.ContainsCoreRegister(reg)
32845b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray        : allocated_registers_.ContainsFloatingPointRegister(reg);
32945b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray  }
33045b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray
331c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void AllocateLocations(HInstruction* instruction);
332c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
333aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // Tells whether the stack frame of the compiled method is
334aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // considered "empty", that is either actually having a size of zero,
335aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // or just containing the saved return address register.
336aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  bool HasEmptyFrame() const {
337aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain    return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
338aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  }
339aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain
340d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int32_t GetInt32ValueOf(HConstant* constant) {
341d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
342d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
343d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
344d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
345d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
346d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsFloatConstant());
347da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
348d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
349d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
350d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
351d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int64_t GetInt64ValueOf(HConstant* constant) {
352d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
353d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
354d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
355d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
356d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsFloatConstant()) {
357da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
358d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsLongConstant()) {
359d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsLongConstant()->GetValue();
360d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
361d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsDoubleConstant());
362da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
363d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
364d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
365d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
366a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  size_t GetFirstRegisterSlotInSlowPath() const {
367a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return first_register_slot_in_slow_path_;
368a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
369a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
370a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  uint32_t FrameEntrySpillSize() const {
371a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return GetFpuSpillSize() + GetCoreSpillSize();
372a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
373a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
374ec525fc30848189051b888da53ba051bc0878b78Roland Levillain  virtual ParallelMoveResolver* GetMoveResolver() = 0;
375a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
376fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  static void CreateCommonInvokeLocationSummary(
377fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray      HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor);
378fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray
379175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
380175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
381eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; }
382eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; }
383eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames
384175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  virtual void InvokeRuntime(QuickEntrypointEnum entrypoint,
385175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             HInstruction* instruction,
386175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             uint32_t dex_pc,
387175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             SlowPathCode* slow_path) = 0;
388175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
389787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected:
390581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // Method patch info used for recording locations of required linker patches and
391581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // target methods. The target method can be used for various purposes, whether for
392581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // patching the address of the method or the code pointer or a PC-relative call.
393581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  template <typename LabelType>
394581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  struct MethodPatchInfo {
395581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    explicit MethodPatchInfo(MethodReference m) : target_method(m), label() { }
396581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
397581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    MethodReference target_method;
398581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    LabelType label;
399581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  };
400581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
40171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  CodeGenerator(HGraph* graph,
40271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_core_registers,
40371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_fpu_registers,
404cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                size_t number_of_register_pairs,
405988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t core_callee_save_mask,
406988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t fpu_callee_save_mask,
407ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                const CompilerOptions& compiler_options,
408ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                OptimizingCompilerStats* stats)
409c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      : frame_size_(0),
4104361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray        core_spill_mask_(0),
411d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray        fpu_spill_mask_(0),
4123bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        first_register_slot_in_slow_path_(0),
41371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers)),
41471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers)),
41571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs)),
41671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_core_registers_(number_of_core_registers),
41771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers),
41871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_register_pairs_(number_of_register_pairs),
419988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        core_callee_save_mask_(core_callee_save_mask),
420988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        fpu_callee_save_mask_(fpu_callee_save_mask),
421cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        stack_map_stream_(graph->GetArena()),
422cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        block_order_(nullptr),
4233e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain        is_baseline_(false),
424eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames        disasm_info_(nullptr),
425ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu        stats_(stats),
426787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray        graph_(graph),
427cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle        compiler_options_(compiler_options),
4282a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban        src_map_(nullptr),
429e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray        slow_paths_(graph->GetArena(), 8),
4304c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        current_block_index_(0),
4313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        is_leaf_(true),
432cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        requires_current_method_(false) {}
433d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
434a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Register allocation logic.
435a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  void AllocateRegistersLocally(HInstruction* instruction) const;
436a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
437a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Backend specific implementation for allocating a register.
43871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  virtual Location AllocateFreeRegister(Primitive::Type type) const = 0;
439a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
44071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  static size_t FindFreeEntry(bool* array, size_t length);
4413c03503d66df3b4440f851ae7d0c4fae5e7872dfNicolas Geoffray  static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length);
442a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
443a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  virtual Location GetStackLocation(HLoadLocal* load) const = 0;
444a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
445c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetLocationBuilder() = 0;
446c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetInstructionVisitor() = 0;
447f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
448d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // Returns the location of the first spilled entry for floating point registers,
449d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // relative to the stack pointer.
450d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillStart() const {
451d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return GetFrameSize() - FrameEntrySpillSize();
452d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
453d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
454d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillSize() const {
455d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize();
456d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
457d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
458d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetCoreSpillSize() const {
459d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(core_spill_mask_) * GetWordSize();
460d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
461d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
462c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool HasAllocatedCalleeSaveRegisters() const {
463c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    // We check the core registers against 1 because it always comprises the return PC.
464c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1)
465c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0);
466c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
467c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
468c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool CallPushesPC() const {
469c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    InstructionSet instruction_set = GetInstructionSet();
470c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return instruction_set == kX86 || instruction_set == kX86_64;
471c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
472c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
473dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // Arm64 has its own type for a label, so we need to templatize this method
474dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // to share the logic.
475581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  template <typename LabelType>
476581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const {
477dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    block = FirstNonEmptyBlock(block);
478dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    return raw_pointer_to_labels_array + block->GetBlockId();
479dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  }
480dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray
4818ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  // Frame size required for this method.
4828ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t frame_size_;
4838ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t core_spill_mask_;
484d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t fpu_spill_mask_;
4853bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  uint32_t first_register_slot_in_slow_path_;
4868ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
487988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  // Registers that were allocated during linear scan.
488988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  RegisterSet allocated_registers_;
489988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
49071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // Arrays used when doing register allocation to know which
49171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // registers we can allocate. `SetupBlockedRegisters` updates the
49271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // arrays.
49371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_core_registers_;
49471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_fpu_registers_;
49571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_register_pairs_;
49671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_core_registers_;
49771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_fpu_registers_;
49871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_register_pairs_;
499988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t core_callee_save_mask_;
500988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t fpu_callee_save_mask_;
50171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
502cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  StackMapStream stack_map_stream_;
503cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
504cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The order to use for code generation.
505fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  const ArenaVector<HBasicBlock*>* block_order_;
506cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
5073e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain  // Whether we are using baseline.
5083e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain  bool is_baseline_;
5093e3d73349a2de81d14e2279f60ffbd9ab3f3ac28Roland Levillain
510eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  DisassemblyInformation* disasm_info_;
511eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames
512bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private:
513c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void InitLocationsBaseline(HInstruction* instruction);
5143bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  size_t GetStackOffsetOfSavedRegister(size_t index);
515eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  void GenerateSlowPaths();
5164c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void CompileInternal(CodeAllocator* allocator, bool is_baseline);
5175f8741860d465410bfed495dbb5f794590d338daMark Mendell  void BlockIfInRegister(Location location, bool is_out = false) const;
518b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path);
519d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
520ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu  OptimizingCompilerStats* stats_;
521ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu
522787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* const graph_;
523cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& compiler_options_;
524d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
5252a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  // Native to dex_pc map used for native debugging/profiling tools.
5262a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  DefaultSrcMap* src_map_;
527e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  GrowableArray<SlowPathCode*> slow_paths_;
528d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
5294c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The current block index in `block_order_` of the block
5304c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // we are generating code for.
5314c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  size_t current_block_index_;
5324c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
533c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether the method is a leaf method.
534f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool is_leaf_;
535f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
536c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether an instruction in the graph accesses the current method.
537c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool requires_current_method_;
538c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
539c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  friend class OptimizingCFITest;
540c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
541d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
542d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
543d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
5447fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F>
5454a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention {
5464a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public:
5477fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  CallingConvention(const C* registers,
5487fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_registers,
5497fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    const F* fpu_registers,
550e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    size_t number_of_fpu_registers,
551e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    size_t pointer_size)
5527fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray      : registers_(registers),
5537fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_registers_(number_of_registers),
5547fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        fpu_registers_(fpu_registers),
555e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        number_of_fpu_registers_(number_of_fpu_registers),
556e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        pointer_size_(pointer_size) {}
5574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
5584a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  size_t GetNumberOfRegisters() const { return number_of_registers_; }
5597fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
5604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
5617fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  C GetRegisterAt(size_t index) const {
5624a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    DCHECK_LT(index, number_of_registers_);
5634a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    return registers_[index];
5644a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
5654a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
5667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  F GetFpuRegisterAt(size_t index) const {
5677fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    DCHECK_LT(index, number_of_fpu_registers_);
5687fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    return fpu_registers_[index];
5697fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  }
5707fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray
5717fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetStackOffsetOf(size_t index) const {
5724a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    // We still reserve the space for parameters passed by registers.
573e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    // Add space for the method pointer.
574e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    return pointer_size_ + index * kVRegSize;
5754a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
5764a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
5774a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private:
5787fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const C* registers_;
5794a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  const size_t number_of_registers_;
5807fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const F* fpu_registers_;
5817fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const size_t number_of_fpu_registers_;
582e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  const size_t pointer_size_;
5834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
5844a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
5854a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray};
5864a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
587d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
588d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
589d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
590