code_generator_x86_64.h revision 19a19cffd197a28ae4c9c3e59eff6352fd392241
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_X86_64_H_
18#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
19
20#include "code_generator.h"
21#include "nodes.h"
22#include "parallel_move_resolver.h"
23#include "utils/x86_64/assembler_x86_64.h"
24
25namespace art {
26namespace x86_64 {
27
28static constexpr size_t kX86_64WordSize = 8;
29
30static constexpr Register kParameterCoreRegisters[] = { RSI, RDX, RCX, R8, R9 };
31static constexpr FloatRegister kParameterFloatRegisters[] =
32    { XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7 };
33
34static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
35static constexpr size_t kParameterFloatRegistersLength = arraysize(kParameterFloatRegisters);
36
37class InvokeDexCallingConvention : public CallingConvention<Register, FloatRegister> {
38 public:
39  InvokeDexCallingConvention() : CallingConvention(
40      kParameterCoreRegisters,
41      kParameterCoreRegistersLength,
42      kParameterFloatRegisters,
43      kParameterFloatRegistersLength) {}
44
45 private:
46  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
47};
48
49class InvokeDexCallingConventionVisitor {
50 public:
51  InvokeDexCallingConventionVisitor() : gp_index_(0), fp_index_(0), stack_index_(0) {}
52
53  Location GetNextLocation(Primitive::Type type);
54
55 private:
56  InvokeDexCallingConvention calling_convention;
57  // The current index for cpu registers.
58  uint32_t gp_index_;
59  // The current index for fpu registers.
60  uint32_t fp_index_;
61  // The current stack index.
62  uint32_t stack_index_;
63
64  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
65};
66
67class CodeGeneratorX86_64;
68
69class ParallelMoveResolverX86_64 : public ParallelMoveResolver {
70 public:
71  ParallelMoveResolverX86_64(ArenaAllocator* allocator, CodeGeneratorX86_64* codegen)
72      : ParallelMoveResolver(allocator), codegen_(codegen) {}
73
74  virtual void EmitMove(size_t index) OVERRIDE;
75  virtual void EmitSwap(size_t index) OVERRIDE;
76  virtual void SpillScratch(int reg) OVERRIDE;
77  virtual void RestoreScratch(int reg) OVERRIDE;
78
79  X86_64Assembler* GetAssembler() const;
80
81 private:
82  void Exchange32(CpuRegister reg, int mem);
83  void Exchange32(XmmRegister reg, int mem);
84  void Exchange32(int mem1, int mem2);
85  void Exchange64(CpuRegister reg, int mem);
86  void Exchange64(XmmRegister reg, int mem);
87  void Exchange64(int mem1, int mem2);
88
89  CodeGeneratorX86_64* const codegen_;
90
91  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64);
92};
93
94class LocationsBuilderX86_64 : public HGraphVisitor {
95 public:
96  LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
97      : HGraphVisitor(graph), codegen_(codegen) {}
98
99#define DECLARE_VISIT_INSTRUCTION(name, super)     \
100  virtual void Visit##name(H##name* instr);
101
102  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
103
104#undef DECLARE_VISIT_INSTRUCTION
105
106  void HandleInvoke(HInvoke* invoke);
107
108 private:
109  CodeGeneratorX86_64* const codegen_;
110  InvokeDexCallingConventionVisitor parameter_visitor_;
111
112  DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64);
113};
114
115class InstructionCodeGeneratorX86_64 : public HGraphVisitor {
116 public:
117  InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen);
118
119#define DECLARE_VISIT_INSTRUCTION(name, super)     \
120  virtual void Visit##name(H##name* instr);
121
122  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
123
124#undef DECLARE_VISIT_INSTRUCTION
125
126  X86_64Assembler* GetAssembler() const { return assembler_; }
127
128 private:
129  // Generate code for the given suspend check. If not null, `successor`
130  // is the block to branch to if the suspend check is not needed, and after
131  // the suspend call.
132  void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
133
134  X86_64Assembler* const assembler_;
135  CodeGeneratorX86_64* const codegen_;
136
137  DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86_64);
138};
139
140class CodeGeneratorX86_64 : public CodeGenerator {
141 public:
142  explicit CodeGeneratorX86_64(HGraph* graph);
143  virtual ~CodeGeneratorX86_64() {}
144
145  virtual void GenerateFrameEntry() OVERRIDE;
146  virtual void GenerateFrameExit() OVERRIDE;
147  virtual void Bind(HBasicBlock* block) OVERRIDE;
148  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
149  virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
150  virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
151  virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
152  virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
153
154  virtual size_t GetWordSize() const OVERRIDE {
155    return kX86_64WordSize;
156  }
157
158  virtual size_t FrameEntrySpillSize() const OVERRIDE;
159
160  virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
161    return &location_builder_;
162  }
163
164  virtual HGraphVisitor* GetInstructionVisitor() OVERRIDE {
165    return &instruction_visitor_;
166  }
167
168  virtual X86_64Assembler* GetAssembler() OVERRIDE {
169    return &assembler_;
170  }
171
172  ParallelMoveResolverX86_64* GetMoveResolver() {
173    return &move_resolver_;
174  }
175
176  virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
177
178  virtual void SetupBlockedRegisters() const OVERRIDE;
179  virtual Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE;
180  virtual void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
181  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
182
183  virtual InstructionSet GetInstructionSet() const OVERRIDE {
184    return InstructionSet::kX86_64;
185  }
186
187  // Emit a write barrier.
188  void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object, CpuRegister value);
189
190  // Helper method to move a value between two locations.
191  void Move(Location destination, Location source);
192
193  void LoadCurrentMethod(CpuRegister reg);
194
195  Label* GetLabelOf(HBasicBlock* block) const {
196    return block_labels_.GetRawStorage() + block->GetBlockId();
197  }
198
199  virtual void Initialize() OVERRIDE {
200    block_labels_.SetSize(GetGraph()->GetBlocks().Size());
201  }
202
203 private:
204  // Labels for each block that will be compiled.
205  GrowableArray<Label> block_labels_;
206  LocationsBuilderX86_64 location_builder_;
207  InstructionCodeGeneratorX86_64 instruction_visitor_;
208  ParallelMoveResolverX86_64 move_resolver_;
209  X86_64Assembler assembler_;
210
211  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64);
212};
213
214}  // namespace x86_64
215}  // namespace art
216
217#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
218