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