code_generator.h revision 234d69d075d1608f80adb647f7935077b62b6376
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
32a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffraystatic size_t constexpr kVRegSize = 4;
33a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray
346d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double.
356d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
366d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double.
376d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain
393f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer.
403f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff;
41624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long.
42624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillainstatic int64_t constexpr kPrimLongMax = 0x7fffffffffffffff;
433f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain
4492a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler;
45e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator;
4692cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffrayclass DexCompilationUnit;
47f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver;
48e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeclass SrcMapElem;
49e21dc3db191df04c100620965bee4617b3b24397Andreas Gampetemplate <class Alloc>
50e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass SrcMap;
51e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeusing DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
5292cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray
53d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator {
54d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
55e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  CodeAllocator() {}
56e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~CodeAllocator() {}
57d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
58d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) = 0;
59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
61d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
62d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
63d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
648ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffraystruct PcInfo {
658ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t dex_pc;
668ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uintptr_t native_pc;
678ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray};
688ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
696a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> {
70e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public:
7192a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  SlowPathCode() {}
72e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~SlowPathCode() {}
73e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
74e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
75e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
76e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray private:
77e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
78e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray};
79e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
8012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffrayclass CodeGenerator {
81d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
82d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // Compiles the graph to executable instructions. Returns whether the compilation
83d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // succeeded.
8473e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false);
8586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void CompileOptimized(CodeAllocator* allocator);
8612df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  static CodeGenerator* Create(HGraph* graph,
873416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle                               InstructionSet instruction_set,
88cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const InstructionSetFeatures& isa_features,
89cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const CompilerOptions& compiler_options);
9012df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  virtual ~CodeGenerator() {}
91d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
92787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* GetGraph() const { return graph_; }
93d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
94dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* GetNextBlockToEmit() const;
95dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const;
96bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
97bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
9886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
9986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Note that this follows the current calling convention.
10086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return GetFrameSize()
10186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        + kVRegSize  // Art method
102e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray        + parameter->GetIndex() * kVRegSize;
10386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
10486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Initialize() = 0;
10632f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  virtual void Finalize(CodeAllocator* allocator);
107d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameEntry() = 0;
108d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameExit() = 0;
10992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Bind(HBasicBlock* block) = 0;
1104a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
111787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual Assembler* GetAssembler() = 0;
112707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray  virtual size_t GetWordSize() const = 0;
113f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  virtual size_t GetFloatingPointSpillSlotSize() const = 0;
114de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual uintptr_t GetAddressOf(HBasicBlock* block) const = 0;
1154c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void InitializeCodeGeneration(size_t number_of_spill_slots,
1164c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_core_registers,
1174c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_fp_registers,
1184c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t number_of_out_slots,
1194c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                const GrowableArray<HBasicBlock*>& block_order);
120ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  int32_t GetStackSlot(HLocal* local) const;
121ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  Location GetTemporaryLocation(HTemporary* temp) const;
122787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
123787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint32_t GetFrameSize() const { return frame_size_; }
124787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  void SetFrameSize(uint32_t size) { frame_size_ = size; }
1258ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
126d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; }
1278ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
12871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; }
12971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; }
130988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  virtual void SetupBlockedRegisters(bool is_baseline) const = 0;
13171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
1324dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  virtual void ComputeSpillMask() {
1334dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
1344dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
1354dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
1364dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
1374dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
1384dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  static uint32_t ComputeRegisterMask(const int* registers, size_t length) {
1394dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    uint32_t mask = 0;
1404dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    for (size_t i = 0, e = length; i < e; ++i) {
1414dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray      mask |= (1 << registers[i]);
1424dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    }
1434dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    return mask;
1444dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
1454dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
146a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
147a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
148412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  virtual InstructionSet GetInstructionSet() const = 0;
149cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
150cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
151cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
152102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Saves the register in the stack. Returns the size taken on stack.
153102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
154102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Restores the register from the stack. Returns the size taken on stack.
155102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
156234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
157234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
158234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
159234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
160840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0;
161234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  // Returns whether we should split long moves in parallel moves.
162234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual bool ShouldSplitLongMoves() const { return false; }
163a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
164988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsCoreCalleeSaveRegister(int reg) const {
165988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (core_callee_save_mask_ & (1 << reg)) != 0;
166988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
167988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
168988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsFloatingPointCalleeSaveRegister(int reg) const {
169988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (fpu_callee_save_mask_ & (1 << reg)) != 0;
170988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
171988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
1723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc);
17377520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  bool CanMoveNullCheckToUser(HNullCheck* null_check);
17477520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  void MaybeRecordImplicitNullCheck(HInstruction* instruction);
175787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
176e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void AddSlowPath(SlowPathCode* slow_path) {
177e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray    slow_paths_.Add(slow_path);
178e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  }
179e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
180e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  void BuildMappingTable(std::vector<uint8_t>* vector, DefaultSrcMap* src_map) const;
1818ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  void BuildVMapTable(std::vector<uint8_t>* vector) const;
18292cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray  void BuildNativeGCMap(
18392cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray      std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
1843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void BuildStackMaps(std::vector<uint8_t>* vector);
1853bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  void SaveLiveRegisters(LocationSummary* locations);
1863bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  void RestoreLiveRegisters(LocationSummary* locations);
187787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
188f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool IsLeafMethod() const {
189f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    return is_leaf_;
190f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
191f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
192f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  void MarkNotLeaf() {
193f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    is_leaf_ = false;
194c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
195c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
196c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
197c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void SetRequiresCurrentMethod() {
198c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
199c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
200c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
201c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool RequiresCurrentMethod() const {
202c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return requires_current_method_;
203f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
204f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
2053c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // Clears the spill slots taken by loop phis in the `LocationSummary` of the
2063c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // suspend check. This is called when the code generator generates code
2073c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // for the suspend check at the back edge (instead of where the suspend check
2083c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // is, which is the loop entry). At this point, the spill slots for the phis
2093c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // have not been written to.
2103c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const;
2113c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
21271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
213102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
21471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
21519a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Helper that returns the pointer offset of an index in an object array.
21619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Note: this method assumes we always have the same pointer size, regardless
21719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // of the architecture.
21819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  static size_t GetCacheOffset(uint32_t index);
21919a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
220f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray  void EmitParallelMoves(Location from1, Location to1, Location from2, Location to2);
221f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
222af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) {
223af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    if (kIsDebugBuild) {
224af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray      if (type == Primitive::kPrimNot && value->IsIntConstant()) {
225900f6eb15db5215deeea23e4e087b553b4f696f7Nicolas Geoffray        CHECK_EQ(value->AsIntConstant()->GetValue(), 0);
226af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray      }
227af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    }
228af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    return type == Primitive::kPrimNot && !value->IsIntConstant();
229af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  }
230af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray
231988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  void AddAllocatedRegister(Location location) {
232988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    allocated_registers_.Add(location);
233988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
234988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
235c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void AllocateLocations(HInstruction* instruction);
236c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
237aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // Tells whether the stack frame of the compiled method is
238aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // considered "empty", that is either actually having a size of zero,
239aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // or just containing the saved return address register.
240aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  bool HasEmptyFrame() const {
241aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain    return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
242aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  }
243aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain
244d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int32_t GetInt32ValueOf(HConstant* constant) {
245d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
246d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
247d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
248d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
249d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
250d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsFloatConstant());
251d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return bit_cast<float, int32_t>(constant->AsFloatConstant()->GetValue());
252d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
253d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
254d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
255d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int64_t GetInt64ValueOf(HConstant* constant) {
256d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
257d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
258d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
259d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
260d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsFloatConstant()) {
261d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return bit_cast<float, int32_t>(constant->AsFloatConstant()->GetValue());
262d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsLongConstant()) {
263d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsLongConstant()->GetValue();
264d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
265d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsDoubleConstant());
266d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return bit_cast<double, int64_t>(constant->AsDoubleConstant()->GetValue());
267d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
268d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
269d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
270787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected:
27171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  CodeGenerator(HGraph* graph,
27271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_core_registers,
27371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_fpu_registers,
274cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                size_t number_of_register_pairs,
275988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t core_callee_save_mask,
276988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t fpu_callee_save_mask,
277cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                const CompilerOptions& compiler_options)
278c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      : frame_size_(0),
2794361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray        core_spill_mask_(0),
280d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray        fpu_spill_mask_(0),
2813bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        first_register_slot_in_slow_path_(0),
28271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers)),
28371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers)),
28471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs)),
28571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_core_registers_(number_of_core_registers),
28671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers),
28771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_register_pairs_(number_of_register_pairs),
288988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        core_callee_save_mask_(core_callee_save_mask),
289988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        fpu_callee_save_mask_(fpu_callee_save_mask),
290787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray        graph_(graph),
291cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle        compiler_options_(compiler_options),
292a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray        pc_infos_(graph->GetArena(), 32),
293e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray        slow_paths_(graph->GetArena(), 8),
2944c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        block_order_(nullptr),
2954c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        current_block_index_(0),
2963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        is_leaf_(true),
297c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray        requires_current_method_(false),
2983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        stack_map_stream_(graph->GetArena()) {}
299d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
300a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Register allocation logic.
301a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  void AllocateRegistersLocally(HInstruction* instruction) const;
302a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
303a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Backend specific implementation for allocating a register.
30471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  virtual Location AllocateFreeRegister(Primitive::Type type) const = 0;
305a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
30671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  static size_t FindFreeEntry(bool* array, size_t length);
3073c03503d66df3b4440f851ae7d0c4fae5e7872dfNicolas Geoffray  static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length);
308a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
309a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  virtual Location GetStackLocation(HLoadLocal* load) const = 0;
310a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
311f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray  virtual ParallelMoveResolver* GetMoveResolver() = 0;
312c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetLocationBuilder() = 0;
313c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetInstructionVisitor() = 0;
314f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
315d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // Returns the location of the first spilled entry for floating point registers,
316d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // relative to the stack pointer.
317d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillStart() const {
318d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return GetFrameSize() - FrameEntrySpillSize();
319d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
320d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
321d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillSize() const {
322d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize();
323d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
324d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
325d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetCoreSpillSize() const {
326d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(core_spill_mask_) * GetWordSize();
327d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
328d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
329d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t FrameEntrySpillSize() const {
330d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return GetFpuSpillSize() + GetCoreSpillSize();
331d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
332d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
333c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool HasAllocatedCalleeSaveRegisters() const {
334c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    // We check the core registers against 1 because it always comprises the return PC.
335c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1)
336c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0);
337c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
338c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
339c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool CallPushesPC() const {
340c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    InstructionSet instruction_set = GetInstructionSet();
341c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return instruction_set == kX86 || instruction_set == kX86_64;
342c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
343c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
344dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // Arm64 has its own type for a label, so we need to templatize this method
345dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // to share the logic.
346dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  template <typename T>
347dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  T* CommonGetLabelOf(T* raw_pointer_to_labels_array, HBasicBlock* block) const {
348dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    block = FirstNonEmptyBlock(block);
349dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    return raw_pointer_to_labels_array + block->GetBlockId();
350dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  }
351dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray
3528ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  // Frame size required for this method.
3538ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t frame_size_;
3548ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t core_spill_mask_;
355d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t fpu_spill_mask_;
3563bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  uint32_t first_register_slot_in_slow_path_;
3578ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
358988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  // Registers that were allocated during linear scan.
359988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  RegisterSet allocated_registers_;
360988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
36171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // Arrays used when doing register allocation to know which
36271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // registers we can allocate. `SetupBlockedRegisters` updates the
36371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // arrays.
36471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_core_registers_;
36571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_fpu_registers_;
36671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_register_pairs_;
36771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_core_registers_;
36871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_fpu_registers_;
36971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_register_pairs_;
370988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t core_callee_save_mask_;
371988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t fpu_callee_save_mask_;
37271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
373bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private:
374c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void InitLocationsBaseline(HInstruction* instruction);
3753bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  size_t GetStackOffsetOfSavedRegister(size_t index);
3764c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void CompileInternal(CodeAllocator* allocator, bool is_baseline);
3775f8741860d465410bfed495dbb5f794590d338daMark Mendell  void BlockIfInRegister(Location location, bool is_out = false) const;
378d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
379787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* const graph_;
380cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& compiler_options_;
381d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
3828ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  GrowableArray<PcInfo> pc_infos_;
383e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  GrowableArray<SlowPathCode*> slow_paths_;
384d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
3854c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The order to use for code generation.
3864c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  const GrowableArray<HBasicBlock*>* block_order_;
3874c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
3884c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The current block index in `block_order_` of the block
3894c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // we are generating code for.
3904c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  size_t current_block_index_;
3914c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
392c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether the method is a leaf method.
393f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool is_leaf_;
394f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
395c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether an instruction in the graph accesses the current method.
396c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool requires_current_method_;
397c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
3983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMapStream stack_map_stream_;
3993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
400d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
401d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
402d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
4037fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F>
4044a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention {
4054a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public:
4067fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  CallingConvention(const C* registers,
4077fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_registers,
4087fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    const F* fpu_registers,
4097fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_fpu_registers)
4107fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray      : registers_(registers),
4117fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_registers_(number_of_registers),
4127fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        fpu_registers_(fpu_registers),
4137fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers) {}
4144a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4154a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  size_t GetNumberOfRegisters() const { return number_of_registers_; }
4167fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
4174a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4187fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  C GetRegisterAt(size_t index) const {
4194a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    DCHECK_LT(index, number_of_registers_);
4204a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    return registers_[index];
4214a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
4224a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4237fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  F GetFpuRegisterAt(size_t index) const {
4247fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    DCHECK_LT(index, number_of_fpu_registers_);
4257fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    return fpu_registers_[index];
4267fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  }
4277fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray
4287fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetStackOffsetOf(size_t index) const {
4294a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    // We still reserve the space for parameters passed by registers.
4309cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    // Add one for the method pointer.
4319cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    return (index + 1) * kVRegSize;
4324a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
4334a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4344a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private:
4357fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const C* registers_;
4364a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  const size_t number_of_registers_;
4377fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const F* fpu_registers_;
4387fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const size_t number_of_fpu_registers_;
4394a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
4404a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
4414a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray};
4424a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
443d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
444d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
445d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
446