code_generator.h revision da40309f61f98c16d7d58e4c34cc0f5eef626f93
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"
2201bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray#include "base/bit_field.h"
23cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
24bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#include "globals.h"
254e3d23aa1523718ea1fdf3a32516d2f9d81e84feNicolas Geoffray#include "locations.h"
26d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "memory_region.h"
27d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray#include "stack_map_stream.h"
29d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
31d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
326d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double.
336d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
346d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double.
356d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
366d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain
373f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer.
383f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff;
39624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long.
40624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillainstatic int64_t constexpr kPrimLongMax = 0x7fffffffffffffff;
413f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain
4292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler;
43e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator;
4492cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffrayclass DexCompilationUnit;
45f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver;
46e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeclass SrcMapElem;
47e21dc3db191df04c100620965bee4617b3b24397Andreas Gampetemplate <class Alloc>
48e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass SrcMap;
49e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeusing DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
5092cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray
51d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator {
52d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
53e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  CodeAllocator() {}
54e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~CodeAllocator() {}
55d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
56d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) = 0;
57d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
58d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
61d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
628ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffraystruct PcInfo {
638ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t dex_pc;
648ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uintptr_t native_pc;
658ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray};
668ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> {
68e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public:
69eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  SlowPathCode() {
70eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) {
71eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_core_stack_offsets_[i] = kRegisterNotSaved;
72eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_fpu_stack_offsets_[i] = kRegisterNotSaved;
73eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    }
74eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
75eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
76e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~SlowPathCode() {}
77e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
78e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
79e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
80da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
81da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
82a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  void RecordPcInfo(CodeGenerator* codegen, HInstruction* instruction, uint32_t dex_pc);
83a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
84eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsCoreRegisterSaved(int reg) const {
85eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg] != kRegisterNotSaved;
86eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
87eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
88eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsFpuRegisterSaved(int reg) const {
89eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved;
90eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
91eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
92eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfCoreRegister(int reg) const {
93eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg];
94eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
95eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
96eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfFpuRegister(int reg) const {
97eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg];
98eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
99eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
100da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu protected:
101eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr size_t kMaximumNumberOfExpectedRegisters = 32;
102eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr uint32_t kRegisterNotSaved = -1;
103eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters];
104eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters];
105da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu
106da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu private:
107e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
108e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray};
109e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
11012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffrayclass CodeGenerator {
111d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
112d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // Compiles the graph to executable instructions. Returns whether the compilation
113d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // succeeded.
11473e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false);
11586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void CompileOptimized(CodeAllocator* allocator);
11612df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  static CodeGenerator* Create(HGraph* graph,
1173416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle                               InstructionSet instruction_set,
118cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const InstructionSetFeatures& isa_features,
119cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const CompilerOptions& compiler_options);
12012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  virtual ~CodeGenerator() {}
121d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
122787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* GetGraph() const { return graph_; }
123d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
124dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* GetNextBlockToEmit() const;
125dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const;
126bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
127bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
12886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
12986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Note that this follows the current calling convention.
13086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return GetFrameSize()
13186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        + kVRegSize  // Art method
132e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray        + parameter->GetIndex() * kVRegSize;
13386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
13486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
13592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Initialize() = 0;
13632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  virtual void Finalize(CodeAllocator* allocator);
137d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameEntry() = 0;
138d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameExit() = 0;
13992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Bind(HBasicBlock* block) = 0;
1404a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
141787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual Assembler* GetAssembler() = 0;
142707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray  virtual size_t GetWordSize() const = 0;
143f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  virtual size_t GetFloatingPointSpillSlotSize() const = 0;
144de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual uintptr_t GetAddressOf(HBasicBlock* block) const = 0;
1454c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void InitializeCodeGeneration(size_t number_of_spill_slots,
1464c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_core_registers,
1474c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_fp_registers,
1484c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t number_of_out_slots,
1494c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                const GrowableArray<HBasicBlock*>& block_order);
150ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  int32_t GetStackSlot(HLocal* local) const;
151ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  Location GetTemporaryLocation(HTemporary* temp) const;
152787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
153787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint32_t GetFrameSize() const { return frame_size_; }
154787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  void SetFrameSize(uint32_t size) { frame_size_ = size; }
1558ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
156d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; }
1578ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
15871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; }
15971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; }
160988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  virtual void SetupBlockedRegisters(bool is_baseline) const = 0;
16171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
1624dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  virtual void ComputeSpillMask() {
1634dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
1644dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
1654dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
1664dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
1674dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
1684dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  static uint32_t ComputeRegisterMask(const int* registers, size_t length) {
1694dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    uint32_t mask = 0;
1704dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    for (size_t i = 0, e = length; i < e; ++i) {
1714dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray      mask |= (1 << registers[i]);
1724dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    }
1734dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    return mask;
1744dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
1754dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
176a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
177a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
178412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  virtual InstructionSet GetInstructionSet() const = 0;
179cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
180cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
181cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
182102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Saves the register in the stack. Returns the size taken on stack.
183102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
184102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Restores the register from the stack. Returns the size taken on stack.
185102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
186234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
187234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
188234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
189234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
190840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0;
191234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  // Returns whether we should split long moves in parallel moves.
192234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual bool ShouldSplitLongMoves() const { return false; }
193a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
194988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsCoreCalleeSaveRegister(int reg) const {
195988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (core_callee_save_mask_ & (1 << reg)) != 0;
196988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
197988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
198988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsFloatingPointCalleeSaveRegister(int reg) const {
199988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (fpu_callee_save_mask_ & (1 << reg)) != 0;
200988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
201988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
202eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr);
20377520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  bool CanMoveNullCheckToUser(HNullCheck* null_check);
20477520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  void MaybeRecordImplicitNullCheck(HInstruction* instruction);
205787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
206e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void AddSlowPath(SlowPathCode* slow_path) {
207e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray    slow_paths_.Add(slow_path);
208e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  }
209e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
210c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  void BuildSourceMap(DefaultSrcMap* src_map) const;
211c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  void BuildMappingTable(std::vector<uint8_t>* vector) const;
2128ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  void BuildVMapTable(std::vector<uint8_t>* vector) const;
21392cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray  void BuildNativeGCMap(
21492cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray      std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
2153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void BuildStackMaps(std::vector<uint8_t>* vector);
216787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
217f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool IsLeafMethod() const {
218f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    return is_leaf_;
219f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
220f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
221f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  void MarkNotLeaf() {
222f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    is_leaf_ = false;
223c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
224c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
225c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
226c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void SetRequiresCurrentMethod() {
227c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
228c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
229c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
230c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool RequiresCurrentMethod() const {
231c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return requires_current_method_;
232f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
233f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
2343c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // Clears the spill slots taken by loop phis in the `LocationSummary` of the
2353c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // suspend check. This is called when the code generator generates code
2363c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // for the suspend check at the back edge (instead of where the suspend check
2373c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // is, which is the loop entry). At this point, the spill slots for the phis
2383c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // have not been written to.
2393c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const;
2403c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
24171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
242102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
24371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
24419a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Helper that returns the pointer offset of an index in an object array.
24519a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Note: this method assumes we always have the same pointer size, regardless
24619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // of the architecture.
24719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  static size_t GetCacheOffset(uint32_t index);
24819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
2499021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray  void EmitParallelMoves(Location from1,
2509021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to1,
2519021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type1,
2529021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location from2,
2539021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to2,
2549021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type2);
255f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
256af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) {
257522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    // Check that null value is not represented as an integer constant.
258522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant());
259522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    return type == Primitive::kPrimNot && !value->IsNullConstant();
260af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  }
261af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray
262988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  void AddAllocatedRegister(Location location) {
263988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    allocated_registers_.Add(location);
264988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
265988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
266c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void AllocateLocations(HInstruction* instruction);
267c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
268aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // Tells whether the stack frame of the compiled method is
269aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // considered "empty", that is either actually having a size of zero,
270aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // or just containing the saved return address register.
271aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  bool HasEmptyFrame() const {
272aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain    return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
273aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  }
274aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain
275d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int32_t GetInt32ValueOf(HConstant* constant) {
276d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
277d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
278d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
279d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
280d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
281d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsFloatConstant());
282da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
283d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
284d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
285d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
286d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int64_t GetInt64ValueOf(HConstant* constant) {
287d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
288d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
289d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
290d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
291d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsFloatConstant()) {
292da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
293d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsLongConstant()) {
294d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsLongConstant()->GetValue();
295d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
296d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsDoubleConstant());
297da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
298d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
299d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
300d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
301a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  size_t GetFirstRegisterSlotInSlowPath() const {
302a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return first_register_slot_in_slow_path_;
303a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
304a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
305a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  uint32_t FrameEntrySpillSize() const {
306a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return GetFpuSpillSize() + GetCoreSpillSize();
307a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
308a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
309a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
310787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected:
31171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  CodeGenerator(HGraph* graph,
31271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_core_registers,
31371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_fpu_registers,
314cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                size_t number_of_register_pairs,
315988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t core_callee_save_mask,
316988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t fpu_callee_save_mask,
317cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                const CompilerOptions& compiler_options)
318c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      : frame_size_(0),
3194361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray        core_spill_mask_(0),
320d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray        fpu_spill_mask_(0),
3213bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        first_register_slot_in_slow_path_(0),
32271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers)),
32371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers)),
32471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs)),
32571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_core_registers_(number_of_core_registers),
32671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers),
32771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_register_pairs_(number_of_register_pairs),
328988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        core_callee_save_mask_(core_callee_save_mask),
329988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        fpu_callee_save_mask_(fpu_callee_save_mask),
330787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray        graph_(graph),
331cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle        compiler_options_(compiler_options),
332a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray        pc_infos_(graph->GetArena(), 32),
333e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray        slow_paths_(graph->GetArena(), 8),
3344c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        block_order_(nullptr),
3354c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        current_block_index_(0),
3363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        is_leaf_(true),
337c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray        requires_current_method_(false),
3383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        stack_map_stream_(graph->GetArena()) {}
339d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
340a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Register allocation logic.
341a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  void AllocateRegistersLocally(HInstruction* instruction) const;
342a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
343a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Backend specific implementation for allocating a register.
34471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  virtual Location AllocateFreeRegister(Primitive::Type type) const = 0;
345a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
34671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  static size_t FindFreeEntry(bool* array, size_t length);
3473c03503d66df3b4440f851ae7d0c4fae5e7872dfNicolas Geoffray  static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length);
348a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
349a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  virtual Location GetStackLocation(HLoadLocal* load) const = 0;
350a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
351f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray  virtual ParallelMoveResolver* GetMoveResolver() = 0;
352c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetLocationBuilder() = 0;
353c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetInstructionVisitor() = 0;
354f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
355d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // Returns the location of the first spilled entry for floating point registers,
356d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // relative to the stack pointer.
357d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillStart() const {
358d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return GetFrameSize() - FrameEntrySpillSize();
359d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
360d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
361d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillSize() const {
362d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize();
363d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
364d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
365d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetCoreSpillSize() const {
366d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(core_spill_mask_) * GetWordSize();
367d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
368d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
369c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool HasAllocatedCalleeSaveRegisters() const {
370c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    // We check the core registers against 1 because it always comprises the return PC.
371c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1)
372c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0);
373c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
374c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
375c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool CallPushesPC() const {
376c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    InstructionSet instruction_set = GetInstructionSet();
377c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return instruction_set == kX86 || instruction_set == kX86_64;
378c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
379c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
380dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // Arm64 has its own type for a label, so we need to templatize this method
381dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // to share the logic.
382dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  template <typename T>
383dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  T* CommonGetLabelOf(T* raw_pointer_to_labels_array, HBasicBlock* block) const {
384dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    block = FirstNonEmptyBlock(block);
385dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    return raw_pointer_to_labels_array + block->GetBlockId();
386dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  }
387dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray
3888ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  // Frame size required for this method.
3898ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t frame_size_;
3908ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t core_spill_mask_;
391d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t fpu_spill_mask_;
3923bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  uint32_t first_register_slot_in_slow_path_;
3938ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
394988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  // Registers that were allocated during linear scan.
395988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  RegisterSet allocated_registers_;
396988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
39771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // Arrays used when doing register allocation to know which
39871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // registers we can allocate. `SetupBlockedRegisters` updates the
39971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // arrays.
40071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_core_registers_;
40171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_fpu_registers_;
40271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_register_pairs_;
40371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_core_registers_;
40471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_fpu_registers_;
40571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_register_pairs_;
406988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t core_callee_save_mask_;
407988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t fpu_callee_save_mask_;
40871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
409bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private:
410c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void InitLocationsBaseline(HInstruction* instruction);
4113bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  size_t GetStackOffsetOfSavedRegister(size_t index);
4124c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void CompileInternal(CodeAllocator* allocator, bool is_baseline);
4135f8741860d465410bfed495dbb5f794590d338daMark Mendell  void BlockIfInRegister(Location location, bool is_out = false) const;
414d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
415787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* const graph_;
416cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& compiler_options_;
417d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
4188ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  GrowableArray<PcInfo> pc_infos_;
419e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  GrowableArray<SlowPathCode*> slow_paths_;
420d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
4214c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The order to use for code generation.
4224c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  const GrowableArray<HBasicBlock*>* block_order_;
4234c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
4244c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The current block index in `block_order_` of the block
4254c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // we are generating code for.
4264c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  size_t current_block_index_;
4274c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
428c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether the method is a leaf method.
429f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool is_leaf_;
430f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
431c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether an instruction in the graph accesses the current method.
432c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool requires_current_method_;
433c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
4343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMapStream stack_map_stream_;
4353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
436c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  friend class OptimizingCFITest;
437c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
438d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
439d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
440d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
4417fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F>
4424a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention {
4434a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public:
4447fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  CallingConvention(const C* registers,
4457fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_registers,
4467fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    const F* fpu_registers,
4477fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_fpu_registers)
4487fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray      : registers_(registers),
4497fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_registers_(number_of_registers),
4507fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        fpu_registers_(fpu_registers),
4517fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers) {}
4524a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4534a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  size_t GetNumberOfRegisters() const { return number_of_registers_; }
4547fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
4554a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4567fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  C GetRegisterAt(size_t index) const {
4574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    DCHECK_LT(index, number_of_registers_);
4584a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    return registers_[index];
4594a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
4604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4617fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  F GetFpuRegisterAt(size_t index) const {
4627fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    DCHECK_LT(index, number_of_fpu_registers_);
4637fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    return fpu_registers_[index];
4647fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  }
4657fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray
4667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetStackOffsetOf(size_t index) const {
4674a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    // We still reserve the space for parameters passed by registers.
4689cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    // Add one for the method pointer.
4699cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    return (index + 1) * kVRegSize;
4704a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
4714a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4724a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private:
4737fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const C* registers_;
4744a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  const size_t number_of_registers_;
4757fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const F* fpu_registers_;
4767fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const size_t number_of_fpu_registers_;
4774a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4784a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
4794a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray};
4804a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
481d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
482d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
483d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
484