1 /* 2 * Copyright (C) 2015 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_MIPS64_H_ 18 #define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_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/mips64/assembler_mips64.h" 26 27 namespace art { 28 namespace mips64 { 29 30 // Use a local definition to prevent copying mistakes. 31 static constexpr size_t kMips64WordSize = kMips64PointerSize; 32 33 34 // InvokeDexCallingConvention registers 35 36 static constexpr GpuRegister kParameterCoreRegisters[] = 37 { A1, A2, A3, A4, A5, A6, A7 }; 38 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 39 40 static constexpr FpuRegister kParameterFpuRegisters[] = 41 { F13, F14, F15, F16, F17, F18, F19 }; 42 static constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters); 43 44 45 // InvokeRuntimeCallingConvention registers 46 47 static constexpr GpuRegister kRuntimeParameterCoreRegisters[] = 48 { A0, A1, A2, A3, A4, A5, A6, A7 }; 49 static constexpr size_t kRuntimeParameterCoreRegistersLength = 50 arraysize(kRuntimeParameterCoreRegisters); 51 52 static constexpr FpuRegister kRuntimeParameterFpuRegisters[] = 53 { F12, F13, F14, F15, F16, F17, F18, F19 }; 54 static constexpr size_t kRuntimeParameterFpuRegistersLength = 55 arraysize(kRuntimeParameterFpuRegisters); 56 57 58 static constexpr GpuRegister kCoreCalleeSaves[] = 59 { S0, S1, S2, S3, S4, S5, S6, S7, GP, S8, RA }; // TODO: review 60 static constexpr FpuRegister kFpuCalleeSaves[] = 61 { F24, F25, F26, F27, F28, F29, F30, F31 }; 62 63 64 class CodeGeneratorMIPS64; 65 66 class InvokeDexCallingConvention : public CallingConvention<GpuRegister, FpuRegister> { 67 public: InvokeDexCallingConvention()68 InvokeDexCallingConvention() 69 : CallingConvention(kParameterCoreRegisters, 70 kParameterCoreRegistersLength, 71 kParameterFpuRegisters, 72 kParameterFpuRegistersLength, 73 kMips64PointerSize) {} 74 75 private: 76 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 77 }; 78 79 class InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventionVisitor { 80 public: InvokeDexCallingConventionVisitorMIPS64()81 InvokeDexCallingConventionVisitorMIPS64() {} ~InvokeDexCallingConventionVisitorMIPS64()82 virtual ~InvokeDexCallingConventionVisitorMIPS64() {} 83 84 Location GetNextLocation(Primitive::Type type) OVERRIDE; 85 Location GetReturnLocation(Primitive::Type type) const; 86 87 private: 88 InvokeDexCallingConvention calling_convention; 89 90 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorMIPS64); 91 }; 92 93 class InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, FpuRegister> { 94 public: InvokeRuntimeCallingConvention()95 InvokeRuntimeCallingConvention() 96 : CallingConvention(kRuntimeParameterCoreRegisters, 97 kRuntimeParameterCoreRegistersLength, 98 kRuntimeParameterFpuRegisters, 99 kRuntimeParameterFpuRegistersLength, 100 kMips64PointerSize) {} 101 102 Location GetReturnLocation(Primitive::Type return_type); 103 104 private: 105 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 106 }; 107 108 class ParallelMoveResolverMIPS64 : public ParallelMoveResolverWithSwap { 109 public: ParallelMoveResolverMIPS64(ArenaAllocator * allocator,CodeGeneratorMIPS64 * codegen)110 ParallelMoveResolverMIPS64(ArenaAllocator* allocator, CodeGeneratorMIPS64* codegen) 111 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 112 113 void EmitMove(size_t index) OVERRIDE; 114 void EmitSwap(size_t index) OVERRIDE; 115 void SpillScratch(int reg) OVERRIDE; 116 void RestoreScratch(int reg) OVERRIDE; 117 118 void Exchange(int index1, int index2, bool double_slot); 119 120 Mips64Assembler* GetAssembler() const; 121 122 private: 123 CodeGeneratorMIPS64* const codegen_; 124 125 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverMIPS64); 126 }; 127 128 class SlowPathCodeMIPS64 : public SlowPathCode { 129 public: SlowPathCodeMIPS64()130 SlowPathCodeMIPS64() : entry_label_(), exit_label_() {} 131 GetEntryLabel()132 Label* GetEntryLabel() { return &entry_label_; } GetExitLabel()133 Label* GetExitLabel() { return &exit_label_; } 134 135 private: 136 Label entry_label_; 137 Label exit_label_; 138 139 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeMIPS64); 140 }; 141 142 class LocationsBuilderMIPS64 : public HGraphVisitor { 143 public: LocationsBuilderMIPS64(HGraph * graph,CodeGeneratorMIPS64 * codegen)144 LocationsBuilderMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen) 145 : HGraphVisitor(graph), codegen_(codegen) {} 146 147 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 148 void Visit##name(H##name* instr); 149 150 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 151 152 #undef DECLARE_VISIT_INSTRUCTION 153 154 private: 155 void HandleInvoke(HInvoke* invoke); 156 void HandleBinaryOp(HBinaryOperation* operation); 157 void HandleShift(HBinaryOperation* operation); 158 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 159 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 160 161 InvokeDexCallingConventionVisitorMIPS64 parameter_visitor_; 162 163 CodeGeneratorMIPS64* const codegen_; 164 165 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderMIPS64); 166 }; 167 168 class InstructionCodeGeneratorMIPS64 : public HGraphVisitor { 169 public: 170 InstructionCodeGeneratorMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen); 171 172 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 173 void Visit##name(H##name* instr); 174 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)175 FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) 176 177 #undef DECLARE_VISIT_INSTRUCTION 178 179 Mips64Assembler* GetAssembler() const { return assembler_; } 180 181 private: 182 // Generate code for the given suspend check. If not null, `successor` 183 // is the block to branch to if the suspend check is not needed, and after 184 // the suspend call. 185 void GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path, GpuRegister class_reg); 186 void GenerateMemoryBarrier(MemBarrierKind kind); 187 void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor); 188 void HandleBinaryOp(HBinaryOperation* operation); 189 void HandleShift(HBinaryOperation* operation); 190 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 191 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 192 void GenerateImplicitNullCheck(HNullCheck* instruction); 193 void GenerateExplicitNullCheck(HNullCheck* instruction); 194 void GenerateTestAndBranch(HInstruction* instruction, 195 Label* true_target, 196 Label* false_target, 197 Label* always_true_target); 198 199 Mips64Assembler* const assembler_; 200 CodeGeneratorMIPS64* const codegen_; 201 202 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorMIPS64); 203 }; 204 205 class CodeGeneratorMIPS64 : public CodeGenerator { 206 public: 207 CodeGeneratorMIPS64(HGraph* graph, 208 const Mips64InstructionSetFeatures& isa_features, 209 const CompilerOptions& compiler_options); ~CodeGeneratorMIPS64()210 virtual ~CodeGeneratorMIPS64() {} 211 212 void GenerateFrameEntry() OVERRIDE; 213 void GenerateFrameExit() OVERRIDE; 214 215 void Bind(HBasicBlock* block) OVERRIDE; 216 217 void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE; 218 GetWordSize()219 size_t GetWordSize() const OVERRIDE { return kMips64WordSize; } 220 GetFloatingPointSpillSlotSize()221 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64WordSize; } 222 GetAddressOf(HBasicBlock * block)223 uintptr_t GetAddressOf(HBasicBlock* block) const OVERRIDE { 224 return GetLabelOf(block)->Position(); 225 } 226 GetLocationBuilder()227 HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; } GetInstructionVisitor()228 HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; } GetAssembler()229 Mips64Assembler* GetAssembler() OVERRIDE { return &assembler_; } 230 231 void MarkGCCard(GpuRegister object, GpuRegister value); 232 233 // Register allocation. 234 235 void SetupBlockedRegisters(bool is_baseline) const OVERRIDE; 236 // AllocateFreeRegister() is only used when allocating registers locally 237 // during CompileBaseline(). 238 Location AllocateFreeRegister(Primitive::Type type) const OVERRIDE; 239 240 Location GetStackLocation(HLoadLocal* load) const OVERRIDE; 241 242 size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id); 243 size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id); 244 size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id); 245 size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id); 246 247 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 248 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 249 GetInstructionSet()250 InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; } 251 GetInstructionSetFeatures()252 const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const { 253 return isa_features_; 254 } 255 GetLabelOf(HBasicBlock * block)256 Label* GetLabelOf(HBasicBlock* block) const { 257 return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block); 258 } 259 Initialize()260 void Initialize() OVERRIDE { 261 block_labels_.SetSize(GetGraph()->GetBlocks().Size()); 262 } 263 264 void Finalize(CodeAllocator* allocator) OVERRIDE; 265 266 // Code generation helpers. 267 268 void MoveLocation(Location destination, Location source, Primitive::Type type); 269 270 void SwapLocations(Location loc1, Location loc2, Primitive::Type type); 271 272 void LoadCurrentMethod(GpuRegister current_method); 273 274 // Generate code to invoke a runtime entry point. 275 void InvokeRuntime(int32_t offset, 276 HInstruction* instruction, 277 uint32_t dex_pc, 278 SlowPathCode* slow_path); 279 GetMoveResolver()280 ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; } 281 NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED)282 bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const { return false; } 283 284 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, GpuRegister temp); 285 286 private: 287 // Labels for each block that will be compiled. 288 GrowableArray<Label> block_labels_; 289 Label frame_entry_label_; 290 LocationsBuilderMIPS64 location_builder_; 291 InstructionCodeGeneratorMIPS64 instruction_visitor_; 292 ParallelMoveResolverMIPS64 move_resolver_; 293 Mips64Assembler assembler_; 294 const Mips64InstructionSetFeatures& isa_features_; 295 296 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorMIPS64); 297 }; 298 299 } // namespace mips64 300 } // namespace art 301 302 #endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_ 303