code_generator_x86_64.h revision 92e83bf8c0b2df8c977ffbc527989631d94b1819
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, RCX }; 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 InvokeDexCallingConventionVisitorX86_64 : public InvokeDexCallingConventionVisitor { 72 public: 73 InvokeDexCallingConventionVisitorX86_64() {} 74 virtual ~InvokeDexCallingConventionVisitorX86_64() {} 75 76 Location GetNextLocation(Primitive::Type type) OVERRIDE; 77 78 private: 79 InvokeDexCallingConvention calling_convention; 80 81 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86_64); 82}; 83 84class CodeGeneratorX86_64; 85 86class SlowPathCodeX86_64 : public SlowPathCode { 87 public: 88 SlowPathCodeX86_64() : entry_label_(), exit_label_() {} 89 90 Label* GetEntryLabel() { return &entry_label_; } 91 Label* GetExitLabel() { return &exit_label_; } 92 93 private: 94 Label entry_label_; 95 Label exit_label_; 96 97 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeX86_64); 98}; 99 100class ParallelMoveResolverX86_64 : public ParallelMoveResolverWithSwap { 101 public: 102 ParallelMoveResolverX86_64(ArenaAllocator* allocator, CodeGeneratorX86_64* codegen) 103 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 104 105 void EmitMove(size_t index) OVERRIDE; 106 void EmitSwap(size_t index) OVERRIDE; 107 void SpillScratch(int reg) OVERRIDE; 108 void RestoreScratch(int reg) OVERRIDE; 109 110 X86_64Assembler* GetAssembler() const; 111 112 private: 113 void Exchange32(CpuRegister reg, int mem); 114 void Exchange32(XmmRegister reg, int mem); 115 void Exchange32(int mem1, int mem2); 116 void Exchange64(CpuRegister reg, int mem); 117 void Exchange64(XmmRegister reg, int mem); 118 void Exchange64(int mem1, int mem2); 119 120 CodeGeneratorX86_64* const codegen_; 121 122 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64); 123}; 124 125class LocationsBuilderX86_64 : public HGraphVisitor { 126 public: 127 LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen) 128 : HGraphVisitor(graph), codegen_(codegen) {} 129 130#define DECLARE_VISIT_INSTRUCTION(name, super) \ 131 void Visit##name(H##name* instr) OVERRIDE; 132 133 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 134 135#undef DECLARE_VISIT_INSTRUCTION 136 137 private: 138 void HandleInvoke(HInvoke* invoke); 139 void HandleBitwiseOperation(HBinaryOperation* operation); 140 void HandleShift(HBinaryOperation* operation); 141 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 142 void HandleFieldGet(HInstruction* instruction); 143 144 CodeGeneratorX86_64* const codegen_; 145 InvokeDexCallingConventionVisitorX86_64 parameter_visitor_; 146 147 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64); 148}; 149 150class InstructionCodeGeneratorX86_64 : public HGraphVisitor { 151 public: 152 InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen); 153 154#define DECLARE_VISIT_INSTRUCTION(name, super) \ 155 void Visit##name(H##name* instr) OVERRIDE; 156 157 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 158 159#undef DECLARE_VISIT_INSTRUCTION 160 161 X86_64Assembler* GetAssembler() const { return assembler_; } 162 163 private: 164 // Generate code for the given suspend check. If not null, `successor` 165 // is the block to branch to if the suspend check is not needed, and after 166 // the suspend call. 167 void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor); 168 void GenerateClassInitializationCheck(SlowPathCodeX86_64* slow_path, CpuRegister class_reg); 169 void HandleBitwiseOperation(HBinaryOperation* operation); 170 void GenerateRemFP(HRem *rem); 171 void DivRemOneOrMinusOne(HBinaryOperation* instruction); 172 void DivByPowerOfTwo(HDiv* instruction); 173 void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 174 void GenerateDivRemIntegral(HBinaryOperation* instruction); 175 void HandleShift(HBinaryOperation* operation); 176 void GenerateMemoryBarrier(MemBarrierKind kind); 177 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 178 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 179 void GenerateImplicitNullCheck(HNullCheck* instruction); 180 void GenerateExplicitNullCheck(HNullCheck* instruction); 181 void PushOntoFPStack(Location source, uint32_t temp_offset, 182 uint32_t stack_adjustment, bool is_float); 183 void GenerateTestAndBranch(HInstruction* instruction, 184 Label* true_target, 185 Label* false_target, 186 Label* always_true_target); 187 188 X86_64Assembler* const assembler_; 189 CodeGeneratorX86_64* const codegen_; 190 191 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86_64); 192}; 193 194class CodeGeneratorX86_64 : public CodeGenerator { 195 public: 196 CodeGeneratorX86_64(HGraph* graph, 197 const X86_64InstructionSetFeatures& isa_features, 198 const CompilerOptions& compiler_options); 199 virtual ~CodeGeneratorX86_64() {} 200 201 void GenerateFrameEntry() OVERRIDE; 202 void GenerateFrameExit() OVERRIDE; 203 void Bind(HBasicBlock* block) OVERRIDE; 204 void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 205 size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 206 size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 207 size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 208 size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 209 210 size_t GetWordSize() const OVERRIDE { 211 return kX86_64WordSize; 212 } 213 214 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 215 return kX86_64WordSize; 216 } 217 218 HGraphVisitor* GetLocationBuilder() OVERRIDE { 219 return &location_builder_; 220 } 221 222 HGraphVisitor* GetInstructionVisitor() OVERRIDE { 223 return &instruction_visitor_; 224 } 225 226 X86_64Assembler* GetAssembler() OVERRIDE { 227 return &assembler_; 228 } 229 230 ParallelMoveResolverX86_64* GetMoveResolver() OVERRIDE { 231 return &move_resolver_; 232 } 233 234 uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 235 return GetLabelOf(block)->Position(); 236 } 237 238 Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 239 240 void SetupBlockedRegisters(bool is_baseline) const OVERRIDE; 241 Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE; 242 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 243 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 244 void Finalize(CodeAllocator* allocator) OVERRIDE; 245 246 InstructionSet GetInstructionSet() const OVERRIDE { 247 return InstructionSet::kX86_64; 248 } 249 250 // Emit a write barrier. 251 void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object, CpuRegister value); 252 253 // Helper method to move a value between two locations. 254 void Move(Location destination, Location source); 255 256 void LoadCurrentMethod(CpuRegister reg); 257 258 Label* GetLabelOf(HBasicBlock* block) const { 259 return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block); 260 } 261 262 void Initialize() OVERRIDE { 263 block_labels_.SetSize(GetGraph()->GetBlocks().Size()); 264 } 265 266 bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 267 return false; 268 } 269 270 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, CpuRegister temp); 271 272 const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const { 273 return isa_features_; 274 } 275 276 int ConstantAreaStart() const { 277 return constant_area_start_; 278 } 279 280 Address LiteralDoubleAddress(double v); 281 Address LiteralFloatAddress(float v); 282 Address LiteralInt32Address(int32_t v); 283 Address LiteralInt64Address(int64_t v); 284 285 // Load a 64 bit value into a register in the most efficient manner. 286 void Load64BitValue(CpuRegister dest, int64_t value); 287 288 private: 289 // Labels for each block that will be compiled. 290 GrowableArray<Label> block_labels_; 291 Label frame_entry_label_; 292 LocationsBuilderX86_64 location_builder_; 293 InstructionCodeGeneratorX86_64 instruction_visitor_; 294 ParallelMoveResolverX86_64 move_resolver_; 295 X86_64Assembler assembler_; 296 const X86_64InstructionSetFeatures& isa_features_; 297 298 // Offset to the start of the constant area in the assembled code. 299 // Used for fixups to the constant area. 300 int constant_area_start_; 301 302 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64); 303}; 304 305} // namespace x86_64 306} // namespace art 307 308#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_ 309