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