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