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