code_generator.h revision 01bc96d007b67fdb7fe349232a83e4b354ce3d08
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
18#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
19
20#include "base/bit_field.h"
21#include "globals.h"
22#include "instruction_set.h"
23#include "memory_region.h"
24#include "nodes.h"
25#include "utils/assembler.h"
26
27namespace art {
28
29class DexCompilationUnit;
30
31class CodeAllocator {
32 public:
33  CodeAllocator() { }
34  virtual ~CodeAllocator() { }
35
36  virtual uint8_t* Allocate(size_t size) = 0;
37
38 private:
39  DISALLOW_COPY_AND_ASSIGN(CodeAllocator);
40};
41
42struct PcInfo {
43  uint32_t dex_pc;
44  uintptr_t native_pc;
45};
46
47/**
48 * A Location is an abstraction over the potential location
49 * of an instruction. It could be in register or stack.
50 */
51class Location : public ValueObject {
52 public:
53  enum Kind {
54    kInvalid = 0,
55    kStackSlot = 1,  // Word size slot.
56    kDoubleStackSlot = 2,  // 64bit stack slot.
57    kRegister = 3,
58    // On 32bits architectures, quick can pass a long where the
59    // low bits are in the last parameter register, and the high
60    // bits are in a stack slot. The kQuickParameter kind is for
61    // handling this special case.
62    kQuickParameter = 4,
63  };
64
65  Location() : value_(kInvalid) {
66    DCHECK(!IsValid());
67  }
68
69  Location(const Location& other) : ValueObject(), value_(other.value_) {}
70
71  Location& operator=(const Location& other) {
72    value_ = other.value_;
73    return *this;
74  }
75
76  bool IsValid() const {
77    return value_ != kInvalid;
78  }
79
80  // Register locations.
81  static Location RegisterLocation(ManagedRegister reg) {
82    return Location(kRegister, reg.RegId());
83  }
84
85  bool IsRegister() const {
86    return GetKind() == kRegister;
87  }
88
89  ManagedRegister reg() const {
90    DCHECK(IsRegister());
91    return static_cast<ManagedRegister>(GetPayload());
92  }
93
94  static uword EncodeStackIndex(intptr_t stack_index) {
95    DCHECK(-kStackIndexBias <= stack_index);
96    DCHECK(stack_index < kStackIndexBias);
97    return static_cast<uword>(kStackIndexBias + stack_index);
98  }
99
100  static Location StackSlot(intptr_t stack_index) {
101    uword payload = EncodeStackIndex(stack_index);
102    Location loc(kStackSlot, payload);
103    // Ensure that sign is preserved.
104    DCHECK_EQ(loc.GetStackIndex(), stack_index);
105    return loc;
106  }
107
108  bool IsStackSlot() const {
109    return GetKind() == kStackSlot;
110  }
111
112  static Location DoubleStackSlot(intptr_t stack_index) {
113    uword payload = EncodeStackIndex(stack_index);
114    Location loc(kDoubleStackSlot, payload);
115    // Ensure that sign is preserved.
116    DCHECK_EQ(loc.GetStackIndex(), stack_index);
117    return loc;
118  }
119
120  bool IsDoubleStackSlot() const {
121    return GetKind() == kDoubleStackSlot;
122  }
123
124  intptr_t GetStackIndex() const {
125    DCHECK(IsStackSlot() || IsDoubleStackSlot());
126    // Decode stack index manually to preserve sign.
127    return GetPayload() - kStackIndexBias;
128  }
129
130  intptr_t GetHighStackIndex(uintptr_t word_size) const {
131    DCHECK(IsDoubleStackSlot());
132    // Decode stack index manually to preserve sign.
133    return GetPayload() - kStackIndexBias + word_size;
134  }
135
136  static Location QuickParameter(uint32_t parameter_index) {
137    return Location(kQuickParameter, parameter_index);
138  }
139
140  uint32_t GetQuickParameterIndex() const {
141    DCHECK(IsQuickParameter());
142    return GetPayload();
143  }
144
145  bool IsQuickParameter() const {
146    return GetKind() == kQuickParameter;
147  }
148
149  arm::ArmManagedRegister AsArm() const;
150  x86::X86ManagedRegister AsX86() const;
151
152  Kind GetKind() const {
153    return KindField::Decode(value_);
154  }
155
156  bool Equals(Location other) const {
157    return value_ == other.value_;
158  }
159
160  const char* DebugString() const {
161    switch (GetKind()) {
162      case kInvalid: return "?";
163      case kRegister: return "R";
164      case kStackSlot: return "S";
165      case kDoubleStackSlot: return "DS";
166      case kQuickParameter: return "Q";
167    }
168    return "?";
169  }
170
171 private:
172  // Number of bits required to encode Kind value.
173  static constexpr uint32_t kBitsForKind = 4;
174  static constexpr uint32_t kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind;
175
176  explicit Location(uword value) : value_(value) {}
177
178  Location(Kind kind, uword payload)
179      : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
180
181  uword GetPayload() const {
182    return PayloadField::Decode(value_);
183  }
184
185  typedef BitField<Kind, 0, kBitsForKind> KindField;
186  typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField;
187
188  // Layout for stack slots.
189  static const intptr_t kStackIndexBias =
190      static_cast<intptr_t>(1) << (kBitsForPayload - 1);
191
192  // Location either contains kind and payload fields or a tagged handle for
193  // a constant locations. Values of enumeration Kind are selected in such a
194  // way that none of them can be interpreted as a kConstant tag.
195  uword value_;
196};
197
198/**
199 * The code generator computes LocationSummary for each instruction so that
200 * the instruction itself knows what code to generate: where to find the inputs
201 * and where to place the result.
202 *
203 * The intent is to have the code for generating the instruction independent of
204 * register allocation. A register allocator just has to provide a LocationSummary.
205 */
206class LocationSummary : public ArenaObject {
207 public:
208  explicit LocationSummary(HInstruction* instruction)
209      : inputs(instruction->GetBlock()->GetGraph()->GetArena(), instruction->InputCount()),
210        temps(instruction->GetBlock()->GetGraph()->GetArena(), 0) {
211    inputs.SetSize(instruction->InputCount());
212    for (int i = 0; i < instruction->InputCount(); i++) {
213      inputs.Put(i, Location());
214    }
215  }
216
217  void SetInAt(uint32_t at, Location location) {
218    inputs.Put(at, location);
219  }
220
221  Location InAt(uint32_t at) const {
222    return inputs.Get(at);
223  }
224
225  void SetOut(Location location) {
226    output = Location(location);
227  }
228
229  void AddTemp(Location location) {
230    temps.Add(location);
231  }
232
233  Location GetTemp(uint32_t at) const {
234    return temps.Get(at);
235  }
236
237  Location Out() const { return output; }
238
239 private:
240  GrowableArray<Location> inputs;
241  GrowableArray<Location> temps;
242  Location output;
243
244  DISALLOW_COPY_AND_ASSIGN(LocationSummary);
245};
246
247class CodeGenerator : public ArenaObject {
248 public:
249  // Compiles the graph to executable instructions. Returns whether the compilation
250  // succeeded.
251  void Compile(CodeAllocator* allocator);
252  static CodeGenerator* Create(ArenaAllocator* allocator,
253                               HGraph* graph,
254                               InstructionSet instruction_set);
255
256  HGraph* GetGraph() const { return graph_; }
257
258  Label* GetLabelOf(HBasicBlock* block) const;
259  bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const;
260
261  virtual void GenerateFrameEntry() = 0;
262  virtual void GenerateFrameExit() = 0;
263  virtual void Bind(Label* label) = 0;
264  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
265  virtual HGraphVisitor* GetLocationBuilder() = 0;
266  virtual HGraphVisitor* GetInstructionVisitor() = 0;
267  virtual Assembler* GetAssembler() = 0;
268  virtual size_t GetWordSize() const = 0;
269
270  uint32_t GetFrameSize() const { return frame_size_; }
271  void SetFrameSize(uint32_t size) { frame_size_ = size; }
272  uint32_t GetCoreSpillMask() const { return core_spill_mask_; }
273
274  void RecordPcInfo(uint32_t dex_pc) {
275    struct PcInfo pc_info;
276    pc_info.dex_pc = dex_pc;
277    pc_info.native_pc = GetAssembler()->CodeSize();
278    pc_infos_.Add(pc_info);
279  }
280
281  void BuildMappingTable(std::vector<uint8_t>* vector) const;
282  void BuildVMapTable(std::vector<uint8_t>* vector) const;
283  void BuildNativeGCMap(
284      std::vector<uint8_t>* vector, const DexCompilationUnit& dex_compilation_unit) const;
285
286 protected:
287  explicit CodeGenerator(HGraph* graph)
288      : frame_size_(0),
289        graph_(graph),
290        block_labels_(graph->GetArena(), 0),
291        pc_infos_(graph->GetArena(), 32) {
292    block_labels_.SetSize(graph->GetBlocks()->Size());
293  }
294  ~CodeGenerator() { }
295
296  // Frame size required for this method.
297  uint32_t frame_size_;
298  uint32_t core_spill_mask_;
299
300 private:
301  void InitLocations(HInstruction* instruction);
302  void CompileBlock(HBasicBlock* block);
303
304  HGraph* const graph_;
305
306  // Labels for each block that will be compiled.
307  GrowableArray<Label> block_labels_;
308  GrowableArray<PcInfo> pc_infos_;
309
310  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
311};
312
313template <typename T>
314class CallingConvention {
315 public:
316  CallingConvention(const T* registers, int number_of_registers)
317      : registers_(registers), number_of_registers_(number_of_registers) {}
318
319  size_t GetNumberOfRegisters() const { return number_of_registers_; }
320
321  T GetRegisterAt(size_t index) const {
322    DCHECK_LT(index, number_of_registers_);
323    return registers_[index];
324  }
325
326  uint8_t GetStackOffsetOf(size_t index) const {
327    // We still reserve the space for parameters passed by registers.
328    // Add kWordSize for the method pointer.
329    return index * kWordSize + kWordSize;
330  }
331
332 private:
333  const T* registers_;
334  const size_t number_of_registers_;
335
336  DISALLOW_COPY_AND_ASSIGN(CallingConvention);
337};
338
339}  // namespace art
340
341#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_
342