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 
25 namespace art {
26 namespace x86_64 {
27 
28 static constexpr size_t kX86_64WordSize = 8;
29 
30 static constexpr Register kParameterCoreRegisters[] = { RSI, RDX, RCX, R8, R9 };
31 
32 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
33 
34 class InvokeDexCallingConvention : public CallingConvention<Register> {
35  public:
InvokeDexCallingConvention()36   InvokeDexCallingConvention()
37       : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
38 
39  private:
40   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
41 };
42 
43 class InvokeDexCallingConventionVisitor {
44  public:
InvokeDexCallingConventionVisitor()45   InvokeDexCallingConventionVisitor() : gp_index_(0), stack_index_(0) {}
46 
47   Location GetNextLocation(Primitive::Type type);
48 
49  private:
50   InvokeDexCallingConvention calling_convention;
51   uint32_t gp_index_;
52   uint32_t stack_index_;
53 
54   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
55 };
56 
57 class CodeGeneratorX86_64;
58 
59 class ParallelMoveResolverX86_64 : public ParallelMoveResolver {
60  public:
ParallelMoveResolverX86_64(ArenaAllocator * allocator,CodeGeneratorX86_64 * codegen)61   ParallelMoveResolverX86_64(ArenaAllocator* allocator, CodeGeneratorX86_64* codegen)
62       : ParallelMoveResolver(allocator), codegen_(codegen) {}
63 
64   virtual void EmitMove(size_t index) OVERRIDE;
65   virtual void EmitSwap(size_t index) OVERRIDE;
66   virtual void SpillScratch(int reg) OVERRIDE;
67   virtual void RestoreScratch(int reg) OVERRIDE;
68 
69   X86_64Assembler* GetAssembler() const;
70 
71  private:
72   void Exchange32(CpuRegister reg, int mem);
73   void Exchange32(int mem1, int mem2);
74   void Exchange64(CpuRegister reg, int mem);
75   void Exchange64(int mem1, int mem2);
76 
77   CodeGeneratorX86_64* const codegen_;
78 
79   DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64);
80 };
81 
82 class LocationsBuilderX86_64 : public HGraphVisitor {
83  public:
LocationsBuilderX86_64(HGraph * graph,CodeGeneratorX86_64 * codegen)84   LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
85       : HGraphVisitor(graph), codegen_(codegen) {}
86 
87 #define DECLARE_VISIT_INSTRUCTION(name)     \
88   virtual void Visit##name(H##name* instr);
89 
90   FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
91 
92 #undef DECLARE_VISIT_INSTRUCTION
93 
94  private:
95   CodeGeneratorX86_64* const codegen_;
96   InvokeDexCallingConventionVisitor parameter_visitor_;
97 
98   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64);
99 };
100 
101 class InstructionCodeGeneratorX86_64 : public HGraphVisitor {
102  public:
103   InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen);
104 
105 #define DECLARE_VISIT_INSTRUCTION(name)     \
106   virtual void Visit##name(H##name* instr);
107 
108   FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
109 
110 #undef DECLARE_VISIT_INSTRUCTION
111 
112   void LoadCurrentMethod(CpuRegister reg);
113 
GetAssembler()114   X86_64Assembler* GetAssembler() const { return assembler_; }
115 
116  private:
117   X86_64Assembler* const assembler_;
118   CodeGeneratorX86_64* const codegen_;
119 
120   DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86_64);
121 };
122 
123 class CodeGeneratorX86_64 : public CodeGenerator {
124  public:
125   explicit CodeGeneratorX86_64(HGraph* graph);
~CodeGeneratorX86_64()126   virtual ~CodeGeneratorX86_64() {}
127 
128   virtual void GenerateFrameEntry() OVERRIDE;
129   virtual void GenerateFrameExit() OVERRIDE;
130   virtual void Bind(Label* label) OVERRIDE;
131   virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
132 
GetWordSize()133   virtual size_t GetWordSize() const OVERRIDE {
134     return kX86_64WordSize;
135   }
136 
137   virtual size_t FrameEntrySpillSize() const OVERRIDE;
138 
GetLocationBuilder()139   virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
140     return &location_builder_;
141   }
142 
GetInstructionVisitor()143   virtual HGraphVisitor* GetInstructionVisitor() OVERRIDE {
144     return &instruction_visitor_;
145   }
146 
GetAssembler()147   virtual X86_64Assembler* GetAssembler() OVERRIDE {
148     return &assembler_;
149   }
150 
GetMoveResolver()151   ParallelMoveResolverX86_64* GetMoveResolver() {
152     return &move_resolver_;
153   }
154 
155   virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
156 
GetNumberOfRegisters()157   virtual size_t GetNumberOfRegisters() const OVERRIDE {
158     return kNumberOfRegIds;
159   }
160 
GetNumberOfCoreRegisters()161   virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
162     return kNumberOfCpuRegisters;
163   }
164 
GetNumberOfFloatingPointRegisters()165   virtual size_t GetNumberOfFloatingPointRegisters() const OVERRIDE {
166     return kNumberOfFloatRegisters;
167   }
168 
169   virtual void SetupBlockedRegisters(bool* blocked_registers) const OVERRIDE;
170   virtual ManagedRegister AllocateFreeRegister(
171       Primitive::Type type, bool* blocked_registers) const OVERRIDE;
172   virtual void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE;
173   virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE;
174 
GetInstructionSet()175   virtual InstructionSet GetInstructionSet() const OVERRIDE {
176     return InstructionSet::kX86_64;
177   }
178 
179   // Emit a write barrier.
180   void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object, CpuRegister value);
181 
182   // Helper method to move a value between two locations.
183   void Move(Location destination, Location source);
184 
185  private:
186   LocationsBuilderX86_64 location_builder_;
187   InstructionCodeGeneratorX86_64 instruction_visitor_;
188   ParallelMoveResolverX86_64 move_resolver_;
189   X86_64Assembler assembler_;
190 
191   DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64);
192 };
193 
194 }  // namespace x86_64
195 }  // namespace art
196 
197 #endif  // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_
198