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