code_generator_x86_64.h revision 71175b7f19a4f6cf9cc264feafd820dbafa371fb
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(int mem1, int mem2);
84  void Exchange64(CpuRegister reg, int mem);
85  void Exchange64(int mem1, int mem2);
86
87  CodeGeneratorX86_64* const codegen_;
88
89  DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64);
90};
91
92class LocationsBuilderX86_64 : public HGraphVisitor {
93 public:
94  LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
95      : HGraphVisitor(graph), codegen_(codegen) {}
96
97#define DECLARE_VISIT_INSTRUCTION(name, super)     \
98  virtual void Visit##name(H##name* instr);
99
100  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
101
102#undef DECLARE_VISIT_INSTRUCTION
103
104  void HandleInvoke(HInvoke* invoke);
105
106 private:
107  CodeGeneratorX86_64* const codegen_;
108  InvokeDexCallingConventionVisitor parameter_visitor_;
109
110  DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64);
111};
112
113class InstructionCodeGeneratorX86_64 : public HGraphVisitor {
114 public:
115  InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen);
116
117#define DECLARE_VISIT_INSTRUCTION(name, super)     \
118  virtual void Visit##name(H##name* instr);
119
120  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
121
122#undef DECLARE_VISIT_INSTRUCTION
123
124  void LoadCurrentMethod(CpuRegister reg);
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(Label* label) OVERRIDE;
148  virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
149  virtual void SaveCoreRegister(Location stack_location, uint32_t reg_id) OVERRIDE;
150  virtual void RestoreCoreRegister(Location stack_location, uint32_t reg_id) OVERRIDE;
151
152  virtual size_t GetWordSize() const OVERRIDE {
153    return kX86_64WordSize;
154  }
155
156  virtual size_t FrameEntrySpillSize() const OVERRIDE;
157
158  virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
159    return &location_builder_;
160  }
161
162  virtual HGraphVisitor* GetInstructionVisitor() OVERRIDE {
163    return &instruction_visitor_;
164  }
165
166  virtual X86_64Assembler* GetAssembler() OVERRIDE {
167    return &assembler_;
168  }
169
170  ParallelMoveResolverX86_64* GetMoveResolver() {
171    return &move_resolver_;
172  }
173
174  virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
175
176  virtual void SetupBlockedRegisters() const OVERRIDE;
177  virtual Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE;
178  virtual void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
179  virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
180
181  virtual InstructionSet GetInstructionSet() const OVERRIDE {
182    return InstructionSet::kX86_64;
183  }
184
185  // Emit a write barrier.
186  void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object, CpuRegister value);
187
188  // Helper method to move a value between two locations.
189  void Move(Location destination, Location source);
190
191 private:
192  LocationsBuilderX86_64 location_builder_;
193  InstructionCodeGeneratorX86_64 instruction_visitor_;
194  ParallelMoveResolverX86_64 move_resolver_;
195  X86_64Assembler assembler_;
196
197  DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64);
198};
199
200}  // namespace x86_64
201}  // namespace art
202
203#endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
204