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