code_generator.h revision 77520bca97ec44e3758510cebd0f20e3bb4584ea
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;
3386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic size_t constexpr kUninitializedFrameSize = 0;
34a747a392fb5f88d2ecc4c6021edf9f1f6615ba16Nicolas Geoffray
356d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double.
366d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
376d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double.
386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
396d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain
403f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer.
413f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff;
42624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long.
43624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillainstatic int64_t constexpr kPrimLongMax = 0x7fffffffffffffff;
443f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain
4592a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler;
46e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator;
4792cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffrayclass DexCompilationUnit;
48f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver;
49e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeclass SrcMapElem;
50e21dc3db191df04c100620965bee4617b3b24397Andreas Gampetemplate <class Alloc>
51e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Roubanclass SrcMap;
52e21dc3db191df04c100620965bee4617b3b24397Andreas Gampeusing DefaultSrcMap = SrcMap<std::allocator<SrcMapElem>>;
5392cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray
54d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator {
55d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
56e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  CodeAllocator() {}
57e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~CodeAllocator() {}
58d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) = 0;
60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
61d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
62d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
63d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
64d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
658ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffraystruct PcInfo {
668ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t dex_pc;
678ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uintptr_t native_pc;
688ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray};
698ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
706a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersclass SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> {
71e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public:
7292a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  SlowPathCode() {}
73e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~SlowPathCode() {}
74e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
75e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
76e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
77e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray private:
78e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
79e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray};
80e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
8112df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffrayclass CodeGenerator {
82d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
83d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // Compiles the graph to executable instructions. Returns whether the compilation
84d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // succeeded.
8573e80c3ae76fafdb53afe3a85306dcb491fb5b00Nicolas Geoffray  void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false);
8686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  void CompileOptimized(CodeAllocator* allocator);
8712df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  static CodeGenerator* Create(HGraph* graph,
883416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle                               InstructionSet instruction_set,
89cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const InstructionSetFeatures& isa_features,
90cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                               const CompilerOptions& compiler_options);
9112df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  virtual ~CodeGenerator() {}
92d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
93787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* GetGraph() const { return graph_; }
94d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
95bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
96bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
9786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
9886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Note that this follows the current calling convention.
9986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return GetFrameSize()
10086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        + kVRegSize  // Art method
101e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray        + parameter->GetIndex() * kVRegSize;
10286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
10386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10492a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Initialize() = 0;
10532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  virtual void Finalize(CodeAllocator* allocator);
106d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameEntry() = 0;
107d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameExit() = 0;
10892a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Bind(HBasicBlock* block) = 0;
1094a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
110bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  virtual HGraphVisitor* GetLocationBuilder() = 0;
111787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual HGraphVisitor* GetInstructionVisitor() = 0;
112787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual Assembler* GetAssembler() = 0;
113707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray  virtual size_t GetWordSize() const = 0;
114f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  virtual size_t GetFloatingPointSpillSlotSize() const = 0;
115de58ab2c03ff8112b07ab827c8fa38f670dfc656Nicolas Geoffray  virtual uintptr_t GetAddressOf(HBasicBlock* block) const = 0;
1163bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  void ComputeFrameSize(size_t number_of_spill_slots,
117f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell                        size_t maximum_number_of_live_core_registers,
118f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell                        size_t maximum_number_of_live_fp_registers,
1193bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray                        size_t number_of_out_slots);
120ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  virtual size_t FrameEntrySpillSize() const = 0;
121ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  int32_t GetStackSlot(HLocal* local) const;
122ab032bc1ff57831106fdac6a91a136293609401fNicolas Geoffray  Location GetTemporaryLocation(HTemporary* temp) const;
123787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
124787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint32_t GetFrameSize() const { return frame_size_; }
125787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  void SetFrameSize(uint32_t size) { frame_size_ = size; }
1268ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t GetCoreSpillMask() const { return core_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_; }
13071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  virtual void SetupBlockedRegisters() const = 0;
13171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
132a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
133a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
134412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  virtual InstructionSet GetInstructionSet() const = 0;
135cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
136cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
137cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
138102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Saves the register in the stack. Returns the size taken on stack.
139102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
140102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Restores the register from the stack. Returns the size taken on stack.
141102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
142102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
1436a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNUSED(stack_index, reg_id);
1446a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNIMPLEMENTED(FATAL);
1456a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNREACHABLE();
146102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  }
147102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
1486a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNUSED(stack_index, reg_id);
1496a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNIMPLEMENTED(FATAL);
1506a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers    UNREACHABLE();
151102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  }
152840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0;
153a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc);
15577520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  bool CanMoveNullCheckToUser(HNullCheck* null_check);
15677520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  void MaybeRecordImplicitNullCheck(HInstruction* instruction);
157787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
158e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void AddSlowPath(SlowPathCode* slow_path) {
159e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray    slow_paths_.Add(slow_path);
160e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  }
161e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
162e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void GenerateSlowPaths();
163e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
164e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  void BuildMappingTable(std::vector<uint8_t>* vector, DefaultSrcMap* src_map) const;
1658ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  void BuildVMapTable(std::vector<uint8_t>* vector) const;
16692cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray  void BuildNativeGCMap(
16792cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray      std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
1683946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  void BuildStackMaps(std::vector<uint8_t>* vector);
1693bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  void SaveLiveRegisters(LocationSummary* locations);
1703bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  void RestoreLiveRegisters(LocationSummary* locations);
171787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
172f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool IsLeafMethod() const {
173f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    return is_leaf_;
174f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
175f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
176f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  void MarkNotLeaf() {
177f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    is_leaf_ = false;
178f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
179f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
1803c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // Clears the spill slots taken by loop phis in the `LocationSummary` of the
1813c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // suspend check. This is called when the code generator generates code
1823c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // for the suspend check at the back edge (instead of where the suspend check
1833c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // is, which is the loop entry). At this point, the spill slots for the phis
1843c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // have not been written to.
1853c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const;
1863c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
18771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
188102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
18971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
19019a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Helper that returns the pointer offset of an index in an object array.
19119a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Note: this method assumes we always have the same pointer size, regardless
19219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // of the architecture.
19319a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  static size_t GetCacheOffset(uint32_t index);
19419a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
195f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray  void EmitParallelMoves(Location from1, Location to1, Location from2, Location to2);
196f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
197af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) {
198af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    if (kIsDebugBuild) {
199af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray      if (type == Primitive::kPrimNot && value->IsIntConstant()) {
200900f6eb15db5215deeea23e4e087b553b4f696f7Nicolas Geoffray        CHECK_EQ(value->AsIntConstant()->GetValue(), 0);
201af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray      }
202af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    }
203af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray    return type == Primitive::kPrimNot && !value->IsIntConstant();
204af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  }
205af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray
206787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected:
20771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  CodeGenerator(HGraph* graph,
20871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_core_registers,
20971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_fpu_registers,
210cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                size_t number_of_register_pairs,
211cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                const CompilerOptions& compiler_options)
21286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      : frame_size_(kUninitializedFrameSize),
2134361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray        core_spill_mask_(0),
2143bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        first_register_slot_in_slow_path_(0),
21571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers)),
21671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers)),
21771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs)),
21871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_core_registers_(number_of_core_registers),
21971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers),
22071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_register_pairs_(number_of_register_pairs),
221787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray        graph_(graph),
222cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle        compiler_options_(compiler_options),
223a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray        pc_infos_(graph->GetArena(), 32),
224e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray        slow_paths_(graph->GetArena(), 8),
2253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        is_leaf_(true),
2263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        stack_map_stream_(graph->GetArena()) {}
227d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
228a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Register allocation logic.
229a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  void AllocateRegistersLocally(HInstruction* instruction) const;
230a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
231a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  // Backend specific implementation for allocating a register.
23271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  virtual Location AllocateFreeRegister(Primitive::Type type) const = 0;
233a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
23471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  static size_t FindFreeEntry(bool* array, size_t length);
2353c03503d66df3b4440f851ae7d0c4fae5e7872dfNicolas Geoffray  static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length);
236a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
237a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray  virtual Location GetStackLocation(HLoadLocal* load) const = 0;
238a7aca370a7d62ca04a1e24423d90e8020d6f1a58Nicolas Geoffray
239f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray  virtual ParallelMoveResolver* GetMoveResolver() = 0;
240f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
2418ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  // Frame size required for this method.
2428ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t frame_size_;
2438ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t core_spill_mask_;
2443bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  uint32_t first_register_slot_in_slow_path_;
2458ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
24671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // Arrays used when doing register allocation to know which
24771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // registers we can allocate. `SetupBlockedRegisters` updates the
24871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // arrays.
24971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_core_registers_;
25071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_fpu_registers_;
25171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_register_pairs_;
25271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_core_registers_;
25371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_fpu_registers_;
25471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_register_pairs_;
25571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
256bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private:
257bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  void InitLocations(HInstruction* instruction);
2583bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  size_t GetStackOffsetOfSavedRegister(size_t index);
259d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
260787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* const graph_;
261cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& compiler_options_;
262d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2638ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  GrowableArray<PcInfo> pc_infos_;
264e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  GrowableArray<SlowPathCode*> slow_paths_;
265d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
266f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool is_leaf_;
267f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
2683946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  StackMapStream stack_map_stream_;
2693946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
270d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
271d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
272d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
2737fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F>
2744a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention {
2754a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public:
2767fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  CallingConvention(const C* registers,
2777fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_registers,
2787fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    const F* fpu_registers,
2797fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_fpu_registers)
2807fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray      : registers_(registers),
2817fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_registers_(number_of_registers),
2827fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        fpu_registers_(fpu_registers),
2837fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers) {}
2844a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
2854a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  size_t GetNumberOfRegisters() const { return number_of_registers_; }
2867fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
2874a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
2887fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  C GetRegisterAt(size_t index) const {
2894a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    DCHECK_LT(index, number_of_registers_);
2904a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    return registers_[index];
2914a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
2924a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
2937fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  F GetFpuRegisterAt(size_t index) const {
2947fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    DCHECK_LT(index, number_of_fpu_registers_);
2957fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    return fpu_registers_[index];
2967fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  }
2977fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray
2987fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetStackOffsetOf(size_t index) const {
2994a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    // We still reserve the space for parameters passed by registers.
3009cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    // Add one for the method pointer.
3019cf35523764d829ae0470dae2d5dd99be469c841Nicolas Geoffray    return (index + 1) * kVRegSize;
3024a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
3034a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
3044a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private:
3057fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const C* registers_;
3064a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  const size_t number_of_registers_;
3077fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const F* fpu_registers_;
3087fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const size_t number_of_fpu_registers_;
3094a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
3104a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
3114a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray};
3124a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
313d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
314d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
315d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
316