1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/*
2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License.
6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at
7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray *
10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and
14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License.
15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */
16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
17d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
18d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
19d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h"
213416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle#include "arch/instruction_set_features.h"
22f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_containers.h"
23f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_object.h"
2401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray#include "base/bit_field.h"
25d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray#include "compiled_method.h"
26cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
27bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#include "globals.h"
28eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames#include "graph_visualizer.h"
294e3d23aa1523718ea1fdf3a32516d2f9d81e84feNicolas Geoffray#include "locations.h"
30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "memory_region.h"
31d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h"
32ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu#include "optimizing_compiler_stats.h"
333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray#include "stack_map_stream.h"
3485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "utils/label.h"
35d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
36d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art {
37d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double.
396d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000);
406d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double.
416d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
426d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain
43e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive integer.
44e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int32_t constexpr kPrimIntMin = 0x80000000;
45e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive long.
46e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000);
47e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell
483f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer.
493f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff;
50624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long.
51e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff);
523f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain
5392a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler;
54e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator;
55d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffrayclass CompilerDriver;
56581550137ee3a068a14224870e71aeee924a0646Vladimir Markoclass LinkerPatch;
57f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver;
5892cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray
59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator {
60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
61e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  CodeAllocator() {}
62e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~CodeAllocator() {}
63d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
64d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual uint8_t* Allocate(size_t size) = 0;
65d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
66d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private:
67d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
68d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
69d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
70c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Ramesclass SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> {
71e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public:
729cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  explicit SlowPathCode(HInstruction* instruction) : instruction_(instruction) {
73eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) {
74eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_core_stack_offsets_[i] = kRegisterNotSaved;
75eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray      saved_fpu_stack_offsets_[i] = kRegisterNotSaved;
76eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    }
77eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
78eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
79e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual ~SlowPathCode() {}
80e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
81e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
82e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
83da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
84da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu  virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
85a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
86eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsCoreRegisterSaved(int reg) const {
87eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg] != kRegisterNotSaved;
88eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
89eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
90eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  bool IsFpuRegisterSaved(int reg) const {
91eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved;
92eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
93eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
94eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfCoreRegister(int reg) const {
95eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_core_stack_offsets_[reg];
96eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
97eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
98eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t GetStackOffsetOfFpuRegister(int reg) const {
99eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray    return saved_fpu_stack_offsets_[reg];
100eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  }
101eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray
1028158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames  virtual bool IsFatal() const { return false; }
1038158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames
1049931f319cf86c56c2855d800339a3410697633a6Alexandre Rames  virtual const char* GetDescription() const = 0;
1059931f319cf86c56c2855d800339a3410697633a6Alexandre Rames
10685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  Label* GetEntryLabel() { return &entry_label_; }
10785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  Label* GetExitLabel() { return &exit_label_; }
10885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
109d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky  HInstruction* GetInstruction() const {
110d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky    return instruction_;
111d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky  }
112d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky
1139cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  uint32_t GetDexPc() const {
1149cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky    return instruction_ != nullptr ? instruction_->GetDexPc() : kNoDexPc;
1159cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  }
1169cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky
117da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu protected:
118eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr size_t kMaximumNumberOfExpectedRegisters = 32;
119eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  static constexpr uint32_t kRegisterNotSaved = -1;
1209cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  // The instruction where this slow path is happening.
1219cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky  HInstruction* instruction_;
122eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters];
123eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters];
124da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu
125da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu private:
12685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  Label entry_label_;
12785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  Label exit_label_;
12885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
129e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
130e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray};
131e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
1322d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitor {
1332d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain public:
1342d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  virtual Location GetNextLocation(Primitive::Type type) = 0;
135fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  virtual Location GetReturnLocation(Primitive::Type type) const = 0;
136fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  virtual Location GetMethodLocation() const = 0;
1372d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1382d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain protected:
1392d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  InvokeDexCallingConventionVisitor() {}
1402d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  virtual ~InvokeDexCallingConventionVisitor() {}
1412d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1422d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current index for core registers.
1432d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t gp_index_ = 0u;
1442d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current index for floating-point registers.
1452d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t float_index_ = 0u;
1462d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  // The current stack index.
1472d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  uint32_t stack_index_ = 0u;
1482d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
1492d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain private:
1502d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
1512d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain};
1522d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain
153e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConvention {
154e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public:
155e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual Location GetObjectLocation() const = 0;
156e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual Location GetFieldIndexLocation() const = 0;
157e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual Location GetReturnLocation(Primitive::Type type) const = 0;
158e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual Location GetSetValueLocation(Primitive::Type type, bool is_instance) const = 0;
159e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual Location GetFpuLocation(Primitive::Type type) const = 0;
160e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual ~FieldAccessCallingConvention() {}
161e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
162e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle protected:
163e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  FieldAccessCallingConvention() {}
164e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
165e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private:
166e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConvention);
167e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle};
168e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
169d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Markoclass CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> {
170d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public:
17158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  // Compiles the graph to executable instructions.
17258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  void Compile(CodeAllocator* allocator);
173d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko  static std::unique_ptr<CodeGenerator> Create(HGraph* graph,
174d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko                                               InstructionSet instruction_set,
175d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko                                               const InstructionSetFeatures& isa_features,
176d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko                                               const CompilerOptions& compiler_options,
177d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko                                               OptimizingCompilerStats* stats = nullptr);
17812df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray  virtual ~CodeGenerator() {}
179d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
180dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // Get the graph. This is the outermost graph, never the graph of a method being inlined.
181787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* GetGraph() const { return graph_; }
182d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
183dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* GetNextBlockToEmit() const;
184dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const;
185bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
186bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray
18786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
18886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Note that this follows the current calling convention.
18986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return GetFrameSize()
190e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        + InstructionSetPointerSize(GetInstructionSet())  // Art method
191e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray        + parameter->GetIndex() * kVRegSize;
19286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
19386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
19492a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Initialize() = 0;
19532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu  virtual void Finalize(CodeAllocator* allocator);
196581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  virtual void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches);
197d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameEntry() = 0;
198d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  virtual void GenerateFrameExit() = 0;
19992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray  virtual void Bind(HBasicBlock* block) = 0;
200175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  virtual void MoveConstant(Location destination, int32_t value) = 0;
201e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual void MoveLocation(Location dst, Location src, Primitive::Type dst_type) = 0;
202e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0;
203e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
204787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  virtual Assembler* GetAssembler() = 0;
205eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  virtual const Assembler& GetAssembler() const = 0;
206707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray  virtual size_t GetWordSize() const = 0;
207f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell  virtual size_t GetFloatingPointSpillSlotSize() const = 0;
208c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  virtual uintptr_t GetAddressOf(HBasicBlock* block) = 0;
2094c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  void InitializeCodeGeneration(size_t number_of_spill_slots,
2104c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t maximum_number_of_live_core_registers,
2110d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain                                size_t maximum_number_of_live_fpu_registers,
2124c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray                                size_t number_of_out_slots,
213fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko                                const ArenaVector<HBasicBlock*>& block_order);
214787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
215787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  uint32_t GetFrameSize() const { return frame_size_; }
216787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  void SetFrameSize(uint32_t size) { frame_size_ = size; }
2178ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
218d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; }
2198ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
22071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; }
22171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; }
22258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil  virtual void SetupBlockedRegisters() const = 0;
22371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
2244dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  virtual void ComputeSpillMask() {
2254dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
2264dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved";
2274dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_;
2284dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
2294dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
2304dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  static uint32_t ComputeRegisterMask(const int* registers, size_t length) {
2314dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    uint32_t mask = 0;
2324dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    for (size_t i = 0, e = length; i < e; ++i) {
2334dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray      mask |= (1 << registers[i]);
2344dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    }
2354dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray    return mask;
2364dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray  }
2374dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray
238a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0;
239a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0;
240412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  virtual InstructionSet GetInstructionSet() const = 0;
241cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
242cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& GetCompilerOptions() const { return compiler_options_; }
243cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle
244ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu  void MaybeRecordStat(MethodCompilationStat compilation_stat, size_t count = 1) const;
245ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu
246102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Saves the register in the stack. Returns the size taken on stack.
247102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
248102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  // Restores the register from the stack. Returns the size taken on stack.
249102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0;
250234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
251234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
252234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0;
253234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray
254840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray  virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0;
255234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  // Returns whether we should split long moves in parallel moves.
256234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray  virtual bool ShouldSplitLongMoves() const { return false; }
257a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
2580d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain  size_t GetNumberOfCoreCalleeSaveRegisters() const {
2590d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    return POPCOUNT(core_callee_save_mask_);
2600d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain  }
2610d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain
2620d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain  size_t GetNumberOfCoreCallerSaveRegisters() const {
2630d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    DCHECK_GE(GetNumberOfCoreRegisters(), GetNumberOfCoreCalleeSaveRegisters());
2640d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain    return GetNumberOfCoreRegisters() - GetNumberOfCoreCalleeSaveRegisters();
2650d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain  }
2660d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain
267988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsCoreCalleeSaveRegister(int reg) const {
268988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (core_callee_save_mask_ & (1 << reg)) != 0;
269988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
270988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
271988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  bool IsFloatingPointCalleeSaveRegister(int reg) const {
272988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    return (fpu_callee_save_mask_ & (1 << reg)) != 0;
273988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
274988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
2752a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban  // Record native to dex mapping for a suspend point.  Required by runtime.
276eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray  void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr);
277b7070a2db8b0b7eca14f01f932be305be64ded57David Srbecky  // Check whether we have already recorded mapping at this PC.
278b7070a2db8b0b7eca14f01f932be305be64ded57David Srbecky  bool HasStackMapAtCurrentPc();
279c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky  // Record extra stack maps if we support native debugging.
280d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky  void MaybeRecordNativeDebugInfo(HInstruction* instruction,
281d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky                                  uint32_t dex_pc,
282d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky                                  SlowPathCode* slow_path = nullptr);
2832a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban
28477520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  bool CanMoveNullCheckToUser(HNullCheck* null_check);
28577520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle  void MaybeRecordImplicitNullCheck(HInstruction* instruction);
2862ae48182573da7087bffc2873730bc758ec29696Calin Juravle  void GenerateNullCheck(HNullCheck* null_check);
2872ae48182573da7087bffc2873730bc758ec29696Calin Juravle  virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
2882ae48182573da7087bffc2873730bc758ec29696Calin Juravle  virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
289787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
29077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // Records a stack map which the runtime might use to set catch phi values
29177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // during exception delivery.
29277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // TODO: Replace with a catch-entering instruction that records the environment.
29377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  void RecordCatchBlockInfo();
29477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil
29577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // Returns true if implicit null checks are allowed in the compiler options
29677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // and if the null check is not inside a try block. We currently cannot do
29777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // implicit null checks in that case because we need the NullCheckSlowPath to
29877a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  // save live registers, which may be needed by the runtime to set catch phis.
29977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil  bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const;
30077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil
301c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  // TODO: Avoid creating the `std::unique_ptr` here.
302e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  void AddSlowPath(SlowPathCode* slow_path) {
303c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    slow_paths_.push_back(std::unique_ptr<SlowPathCode>(slow_path));
304e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray  }
305e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray
306b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray  void BuildStackMaps(MemoryRegion region, const DexFile::CodeItem& code_item);
307d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray  size_t ComputeStackMapsSize();
308787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray
309f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool IsLeafMethod() const {
310f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    return is_leaf_;
311f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
312f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
313f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  void MarkNotLeaf() {
314f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray    is_leaf_ = false;
315c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
316c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
317c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
318c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void SetRequiresCurrentMethod() {
319c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    requires_current_method_ = true;
320c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
321c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
322c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool RequiresCurrentMethod() const {
323c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return requires_current_method_;
324f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  }
325f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
3263c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // Clears the spill slots taken by loop phis in the `LocationSummary` of the
3273c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // suspend check. This is called when the code generator generates code
3283c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // for the suspend check at the back edge (instead of where the suspend check
3293c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // is, which is the loop entry). At this point, the spill slots for the phis
3303c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  // have not been written to.
3313c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray  void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const;
3323c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray
33371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; }
334102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; }
33571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
33619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Helper that returns the pointer offset of an index in an object array.
33719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // Note: this method assumes we always have the same pointer size, regardless
33819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  // of the architecture.
33919a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray  static size_t GetCacheOffset(uint32_t index);
340e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  // Pointer variant for ArtMethod and ArtField arrays.
341e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  size_t GetCachePointerOffset(uint32_t index);
34219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray
3439021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray  void EmitParallelMoves(Location from1,
3449021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to1,
3459021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type1,
3469021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location from2,
3479021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Location to2,
3489021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray                         Primitive::Type type2);
349f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
350af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) {
351522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    // Check that null value is not represented as an integer constant.
352522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant());
353522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil    return type == Primitive::kPrimNot && !value->IsNullConstant();
354af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray  }
355af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray
35678e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames  void ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path);
35778e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames
358988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  void AddAllocatedRegister(Location location) {
359988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray    allocated_registers_.Add(location);
360988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  }
361988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
36245b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray  bool HasAllocatedRegister(bool is_core, int reg) const {
36345b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray    return is_core
36445b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray        ? allocated_registers_.ContainsCoreRegister(reg)
36545b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray        : allocated_registers_.ContainsFloatingPointRegister(reg);
36645b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray  }
36745b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray
368c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  void AllocateLocations(HInstruction* instruction);
369c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
370aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // Tells whether the stack frame of the compiled method is
371aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // considered "empty", that is either actually having a size of zero,
372aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  // or just containing the saved return address register.
373aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  bool HasEmptyFrame() const {
374aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain    return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0);
375aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain  }
376aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain
377d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int32_t GetInt32ValueOf(HConstant* constant) {
378d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
379d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
380d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
381d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
382d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
383d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsFloatConstant());
384da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
385d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
386d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
387d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
388d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  static int64_t GetInt64ValueOf(HConstant* constant) {
389d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    if (constant->IsIntConstant()) {
390d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsIntConstant()->GetValue();
391d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsNullConstant()) {
392d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return 0;
393d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsFloatConstant()) {
394da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue());
395d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else if (constant->IsLongConstant()) {
396d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      return constant->AsLongConstant()->GetValue();
397d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    } else {
398d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray      DCHECK(constant->IsDoubleConstant());
399da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain      return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue());
400d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray    }
401d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray  }
402d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray
403a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  size_t GetFirstRegisterSlotInSlowPath() const {
404a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return first_register_slot_in_slow_path_;
405a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
406a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
407a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  uint32_t FrameEntrySpillSize() const {
408a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray    return GetFpuSpillSize() + GetCoreSpillSize();
409a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray  }
410a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
411ec525fc30848189051b888da53ba051bc0878b78Roland Levillain  virtual ParallelMoveResolver* GetMoveResolver() = 0;
412a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray
413fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray  static void CreateCommonInvokeLocationSummary(
414fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray      HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor);
415fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray
416175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke);
417175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
418e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void CreateUnresolvedFieldLocationSummary(
419e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      HInstruction* field_access,
420e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      Primitive::Type field_type,
421e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      const FieldAccessCallingConvention& calling_convention);
422e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
423e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle  void GenerateUnresolvedFieldAccess(
424e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      HInstruction* field_access,
425e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      Primitive::Type field_type,
426e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      uint32_t field_index,
427e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      uint32_t dex_pc,
428e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle      const FieldAccessCallingConvention& calling_convention);
429e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle
43098893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  // TODO: This overlaps a bit with MoveFromReturnRegister. Refactor for a better design.
43198893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle  static void CreateLoadClassLocationSummary(HLoadClass* cls,
43298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle                                             Location runtime_type_index_location,
4330d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain                                             Location runtime_return_location,
4340d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain                                             bool code_generator_supports_read_barrier = false);
43598893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle
4365bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray  static void CreateSystemArrayCopyLocationSummary(HInvoke* invoke);
4375bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray
438eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; }
439eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; }
440eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames
441175dc732c80e6f2afd83209348124df349290ba8Calin Juravle  virtual void InvokeRuntime(QuickEntrypointEnum entrypoint,
442175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             HInstruction* instruction,
443175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             uint32_t dex_pc,
444175dc732c80e6f2afd83209348124df349290ba8Calin Juravle                             SlowPathCode* slow_path) = 0;
445175dc732c80e6f2afd83209348124df349290ba8Calin Juravle
446cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Check if the desired_string_load_kind is supported. If it is, return it,
447cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // otherwise return a fall-back info that should be used instead.
448cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  virtual HLoadString::LoadKind GetSupportedLoadStringKind(
449cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      HLoadString::LoadKind desired_string_load_kind) = 0;
450cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
451dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // Check if the desired_dispatch_info is supported. If it is, return it,
452dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  // otherwise return a fall-back info that should be used instead.
453dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko  virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch(
454dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
455dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko      MethodReference target_method) = 0;
456dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko
45785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  // Generate a call to a static or direct method.
45885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  virtual void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) = 0;
45985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  // Generate a call to a virtual method.
46085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  virtual void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) = 0;
46185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
46285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  // Copy the result of a call into the given target.
46385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  virtual void MoveFromReturnRegister(Location trg, Primitive::Type type) = 0;
46485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
465c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky  virtual void GenerateNop() = 0;
466c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky
467787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected:
468581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // Method patch info used for recording locations of required linker patches and
469581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // target methods. The target method can be used for various purposes, whether for
470581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  // patching the address of the method or the code pointer or a PC-relative call.
471581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  template <typename LabelType>
472581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  struct MethodPatchInfo {
473581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    explicit MethodPatchInfo(MethodReference m) : target_method(m), label() { }
474581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
475581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    MethodReference target_method;
476581550137ee3a068a14224870e71aeee924a0646Vladimir Marko    LabelType label;
477581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  };
478581550137ee3a068a14224870e71aeee924a0646Vladimir Marko
479cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // String patch info used for recording locations of required linker patches and
480cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // target strings. The actual string address can be absolute or PC-relative.
481cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  template <typename LabelType>
482cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  struct StringPatchInfo {
483cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    StringPatchInfo(const DexFile& df, uint32_t index)
484cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko        : dex_file(df), string_index(index), label() { }
485cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
486cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    const DexFile& dex_file;
487cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    uint32_t string_index;
488cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    LabelType label;
489cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  };
490cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
49171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  CodeGenerator(HGraph* graph,
49271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_core_registers,
49371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray                size_t number_of_fpu_registers,
494cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle                size_t number_of_register_pairs,
495988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t core_callee_save_mask,
496988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray                uint32_t fpu_callee_save_mask,
497ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                const CompilerOptions& compiler_options,
498ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu                OptimizingCompilerStats* stats)
499c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      : frame_size_(0),
5004361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray        core_spill_mask_(0),
501d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray        fpu_spill_mask_(0),
5023bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        first_register_slot_in_slow_path_(0),
5035233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko        blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers,
5045233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko                                                                    kArenaAllocCodeGenerator)),
5055233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko        blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers,
5065233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko                                                                   kArenaAllocCodeGenerator)),
5075233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko        blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs,
5085233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko                                                                    kArenaAllocCodeGenerator)),
50971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_core_registers_(number_of_core_registers),
51071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_fpu_registers_(number_of_fpu_registers),
51171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        number_of_register_pairs_(number_of_register_pairs),
512988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        core_callee_save_mask_(core_callee_save_mask),
513988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray        fpu_callee_save_mask_(fpu_callee_save_mask),
514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        stack_map_stream_(graph->GetArena()),
515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko        block_order_(nullptr),
516eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames        disasm_info_(nullptr),
517ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu        stats_(stats),
518787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray        graph_(graph),
519cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle        compiler_options_(compiler_options),
520225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko        slow_paths_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)),
5210f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko        current_slow_path_(nullptr),
5224c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray        current_block_index_(0),
5233946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        is_leaf_(true),
524225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko        requires_current_method_(false) {
525225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    slow_paths_.reserve(8);
526225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  }
527d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
528c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetLocationBuilder() = 0;
529c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  virtual HGraphVisitor* GetInstructionVisitor() = 0;
530f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray
531d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // Returns the location of the first spilled entry for floating point registers,
532d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  // relative to the stack pointer.
533d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillStart() const {
534d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return GetFrameSize() - FrameEntrySpillSize();
535d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
536d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
537d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetFpuSpillSize() const {
538d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize();
539d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
540d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
541d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t GetCoreSpillSize() const {
542d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray    return POPCOUNT(core_spill_mask_) * GetWordSize();
543d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  }
544d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray
545c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool HasAllocatedCalleeSaveRegisters() const {
546c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    // We check the core registers against 1 because it always comprises the return PC.
547c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1)
548c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray      || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0);
549c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
550c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
551c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool CallPushesPC() const {
552c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    InstructionSet instruction_set = GetInstructionSet();
553c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray    return instruction_set == kX86 || instruction_set == kX86_64;
554c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  }
555c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
556225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  // Arm64 has its own type for a label, so we need to templatize these methods
557dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  // to share the logic.
558225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko
559225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  template <typename LabelType>
560225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  LabelType* CommonInitializeLabels() {
561b95fb775cc4c08349d0d905adbc96ad85e50601dVladimir Marko    // We use raw array allocations instead of ArenaVector<> because Labels are
562b95fb775cc4c08349d0d905adbc96ad85e50601dVladimir Marko    // non-constructible and non-movable and as such cannot be held in a vector.
563225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    size_t size = GetGraph()->GetBlocks().size();
564225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    LabelType* labels = GetGraph()->GetArena()->AllocArray<LabelType>(size,
565225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko                                                                      kArenaAllocCodeGenerator);
566225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    for (size_t i = 0; i != size; ++i) {
567225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko      new(labels + i) LabelType();
568225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    }
569225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko    return labels;
570225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko  }
571225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko
572581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  template <typename LabelType>
573581550137ee3a068a14224870e71aeee924a0646Vladimir Marko  LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const {
574dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    block = FirstNonEmptyBlock(block);
575dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray    return raw_pointer_to_labels_array + block->GetBlockId();
576dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray  }
577dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray
5780f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  SlowPathCode* GetCurrentSlowPath() {
5790f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    return current_slow_path_;
5800f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  }
5810f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko
5828ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  // Frame size required for this method.
5838ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t frame_size_;
5848ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray  uint32_t core_spill_mask_;
585d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray  uint32_t fpu_spill_mask_;
5863bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  uint32_t first_register_slot_in_slow_path_;
5878ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray
588988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  // Registers that were allocated during linear scan.
589988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  RegisterSet allocated_registers_;
590988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray
59171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // Arrays used when doing register allocation to know which
59271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // registers we can allocate. `SetupBlockedRegisters` updates the
59371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  // arrays.
59471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_core_registers_;
59571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_fpu_registers_;
59671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  bool* const blocked_register_pairs_;
59771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_core_registers_;
59871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_fpu_registers_;
59971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  size_t number_of_register_pairs_;
600988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t core_callee_save_mask_;
601988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray  const uint32_t fpu_callee_save_mask_;
60271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray
603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  StackMapStream stack_map_stream_;
604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // The order to use for code generation.
606fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko  const ArenaVector<HBasicBlock*>* block_order_;
607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
608eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  DisassemblyInformation* disasm_info_;
609eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames
610bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private:
6113bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  size_t GetStackOffsetOfSavedRegister(size_t index);
612eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  void GenerateSlowPaths();
6135f8741860d465410bfed495dbb5f794590d338daMark Mendell  void BlockIfInRegister(Location location, bool is_out = false) const;
614b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray  void EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path);
615d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
616ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu  OptimizingCompilerStats* stats_;
617ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu
618787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray  HGraph* const graph_;
619cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle  const CompilerOptions& compiler_options_;
620d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
621c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  ArenaVector<std::unique_ptr<SlowPathCode>> slow_paths_;
622d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
62342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // The current slow-path that we're generating code for.
6240f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko  SlowPathCode* current_slow_path_;
6250f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko
6264c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // The current block index in `block_order_` of the block
6274c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  // we are generating code for.
6284c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray  size_t current_block_index_;
6294c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray
630c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether the method is a leaf method.
631f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray  bool is_leaf_;
632f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray
633c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  // Whether an instruction in the graph accesses the current method.
634c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray  bool requires_current_method_;
635c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray
636c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  friend class OptimizingCFITest;
637c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
638d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
639d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray};
640d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
6417fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F>
6424a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention {
6434a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public:
6447fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  CallingConvention(const C* registers,
6457fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    size_t number_of_registers,
6467fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                    const F* fpu_registers,
647e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    size_t number_of_fpu_registers,
648e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                    size_t pointer_size)
6497fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray      : registers_(registers),
6507fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        number_of_registers_(number_of_registers),
6517fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray        fpu_registers_(fpu_registers),
652e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        number_of_fpu_registers_(number_of_fpu_registers),
653e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier        pointer_size_(pointer_size) {}
6544a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
6554a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  size_t GetNumberOfRegisters() const { return number_of_registers_; }
6567fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
6574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
6587fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  C GetRegisterAt(size_t index) const {
6594a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    DCHECK_LT(index, number_of_registers_);
6604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    return registers_[index];
6614a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
6624a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
6637fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  F GetFpuRegisterAt(size_t index) const {
6647fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    DCHECK_LT(index, number_of_fpu_registers_);
6657fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray    return fpu_registers_[index];
6667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  }
6677fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray
6687fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  size_t GetStackOffsetOf(size_t index) const {
6694a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray    // We still reserve the space for parameters passed by registers.
670e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    // Add space for the method pointer.
671e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    return pointer_size_ + index * kVRegSize;
6724a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  }
6734a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
6744a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private:
6757fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const C* registers_;
6764a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  const size_t number_of_registers_;
6777fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const F* fpu_registers_;
6787fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  const size_t number_of_fpu_registers_;
679e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  const size_t pointer_size_;
6804a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
6814a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
6824a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray};
6834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray
68442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik/**
68542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * A templated class SlowPathGenerator with a templated method NewSlowPath()
68642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * that can be used by any code generator to share equivalent slow-paths with
68742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * the objective of reducing generated code size.
68842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik *
68942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * InstructionType:  instruction that requires SlowPathCodeType
69042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * SlowPathCodeType: subclass of SlowPathCode, with constructor SlowPathCodeType(InstructionType *)
69142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik */
69242249c3602c3d0243396ee3627ffb5906aa77c1eAart Biktemplate <typename InstructionType>
69342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass SlowPathGenerator {
69442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  static_assert(std::is_base_of<HInstruction, InstructionType>::value,
69542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik                "InstructionType is not a subclass of art::HInstruction");
69642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
69742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik public:
69842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  SlowPathGenerator(HGraph* graph, CodeGenerator* codegen)
69942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      : graph_(graph),
70042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        codegen_(codegen),
70142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        slow_path_map_(std::less<uint32_t>(), graph->GetArena()->Adapter(kArenaAllocSlowPaths)) {}
70242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
70342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Creates and adds a new slow-path, if needed, or returns existing one otherwise.
70442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Templating the method (rather than the whole class) on the slow-path type enables
70542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // keeping this code at a generic, non architecture-specific place.
70642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  //
70742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // NOTE: This approach assumes each InstructionType only generates one SlowPathCodeType.
70842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  //       To relax this requirement, we would need some RTTI on the stored slow-paths,
70942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  //       or template the class as a whole on SlowPathType.
71042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  template <typename SlowPathCodeType>
71142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  SlowPathCodeType* NewSlowPath(InstructionType* instruction) {
71242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    static_assert(std::is_base_of<SlowPathCode, SlowPathCodeType>::value,
71342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik                  "SlowPathCodeType is not a subclass of art::SlowPathCode");
71442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    static_assert(std::is_constructible<SlowPathCodeType, InstructionType*>::value,
71542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik                  "SlowPathCodeType is not constructible from InstructionType*");
71642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // Iterate over potential candidates for sharing. Currently, only same-typed
71742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // slow-paths with exactly the same dex-pc are viable candidates.
71842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // TODO: pass dex-pc/slow-path-type to run-time to allow even more sharing?
71942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    const uint32_t dex_pc = instruction->GetDexPc();
72042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    auto iter = slow_path_map_.find(dex_pc);
72142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    if (iter != slow_path_map_.end()) {
72242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      auto candidates = iter->second;
72342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      for (const auto& it : candidates) {
72442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        InstructionType* other_instruction = it.first;
72542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        SlowPathCodeType* other_slow_path = down_cast<SlowPathCodeType*>(it.second);
72642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        // Determine if the instructions allow for slow-path sharing.
72742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        if (HaveSameLiveRegisters(instruction, other_instruction) &&
72842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik            HaveSameStackMap(instruction, other_instruction)) {
72942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik          // Can share: reuse existing one.
73042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik          return other_slow_path;
73142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        }
73242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      }
73342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    } else {
73442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      // First time this dex-pc is seen.
73542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      iter = slow_path_map_.Put(dex_pc, {{}, {graph_->GetArena()->Adapter(kArenaAllocSlowPaths)}});
73642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    }
73742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // Cannot share: create and add new slow-path for this particular dex-pc.
73842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    SlowPathCodeType* slow_path = new (graph_->GetArena()) SlowPathCodeType(instruction);
73942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    iter->second.emplace_back(std::make_pair(instruction, slow_path));
74042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    codegen_->AddSlowPath(slow_path);
74142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    return slow_path;
74242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  }
74342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
74442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik private:
74542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Tests if both instructions have same set of live physical registers. This ensures
74642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // the slow-path has exactly the same preamble on saving these registers to stack.
74742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  bool HaveSameLiveRegisters(const InstructionType* i1, const InstructionType* i2) const {
74842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    const uint32_t core_spill = ~codegen_->GetCoreSpillMask();
74942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    const uint32_t fpu_spill = ~codegen_->GetFpuSpillMask();
75042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    RegisterSet* live1 = i1->GetLocations()->GetLiveRegisters();
75142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    RegisterSet* live2 = i2->GetLocations()->GetLiveRegisters();
75242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    return (((live1->GetCoreRegisters() & core_spill) ==
75342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik             (live2->GetCoreRegisters() & core_spill)) &&
75442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik            ((live1->GetFloatingPointRegisters() & fpu_spill) ==
75542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik             (live2->GetFloatingPointRegisters() & fpu_spill)));
75642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  }
75742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
75842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Tests if both instructions have the same stack map. This ensures the interpreter
75942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // will find exactly the same dex-registers at the same entries.
76042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  bool HaveSameStackMap(const InstructionType* i1, const InstructionType* i2) const {
76142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    DCHECK(i1->HasEnvironment());
76242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    DCHECK(i2->HasEnvironment());
76342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // We conservatively test if the two instructions find exactly the same instructions
76442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    // and location in each dex-register. This guarantees they will have the same stack map.
76542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    HEnvironment* e1 = i1->GetEnvironment();
76642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    HEnvironment* e2 = i2->GetEnvironment();
76742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    if (e1->GetParent() != e2->GetParent() || e1->Size() != e2->Size()) {
76842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      return false;
76942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    }
77042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    for (size_t i = 0, sz = e1->Size(); i < sz; ++i) {
77142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      if (e1->GetInstructionAt(i) != e2->GetInstructionAt(i) ||
77242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik          !e1->GetLocationAt(i).Equals(e2->GetLocationAt(i))) {
77342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        return false;
77442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      }
77542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    }
77642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik    return true;
77742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  }
77842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
77942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  HGraph* const graph_;
78042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  CodeGenerator* const codegen_;
78142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
78242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Map from dex-pc to vector of already existing instruction/slow-path pairs.
78342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  ArenaSafeMap<uint32_t, ArenaVector<std::pair<InstructionType*, SlowPathCode*>>> slow_path_map_;
78442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
78542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  DISALLOW_COPY_AND_ASSIGN(SlowPathGenerator);
78642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik};
78742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
78842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass InstructionCodeGenerator : public HGraphVisitor {
78942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik public:
79042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  InstructionCodeGenerator(HGraph* graph, CodeGenerator* codegen)
79142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik      : HGraphVisitor(graph),
79242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik        deopt_slow_paths_(graph, codegen) {}
79342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
79442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik protected:
79542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // Add slow-path generator for each instruction/slow-path combination that desires sharing.
79642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  // TODO: under current regime, only deopt sharing make sense; extend later.
79742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik  SlowPathGenerator<HDeoptimize> deopt_slow_paths_;
79842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik};
79942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik
800d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}  // namespace art
801d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
802d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
803