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 // InvokeDexCallingConvention registers 31 32 static constexpr GpuRegister kParameterCoreRegisters[] = 33 { A1, A2, A3, A4, A5, A6, A7 }; 34 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 35 36 static constexpr FpuRegister kParameterFpuRegisters[] = 37 { F13, F14, F15, F16, F17, F18, F19 }; 38 static constexpr size_t kParameterFpuRegistersLength = arraysize(kParameterFpuRegisters); 39 40 41 // InvokeRuntimeCallingConvention registers 42 43 static constexpr GpuRegister kRuntimeParameterCoreRegisters[] = 44 { A0, A1, A2, A3, A4, A5, A6, A7 }; 45 static constexpr size_t kRuntimeParameterCoreRegistersLength = 46 arraysize(kRuntimeParameterCoreRegisters); 47 48 static constexpr FpuRegister kRuntimeParameterFpuRegisters[] = 49 { F12, F13, F14, F15, F16, F17, F18, F19 }; 50 static constexpr size_t kRuntimeParameterFpuRegistersLength = 51 arraysize(kRuntimeParameterFpuRegisters); 52 53 54 static constexpr GpuRegister kCoreCalleeSaves[] = 55 { S0, S1, S2, S3, S4, S5, S6, S7, GP, S8, RA }; // TODO: review 56 static constexpr FpuRegister kFpuCalleeSaves[] = 57 { F24, F25, F26, F27, F28, F29, F30, F31 }; 58 59 60 class CodeGeneratorMIPS64; 61 62 class InvokeDexCallingConvention : public CallingConvention<GpuRegister, FpuRegister> { 63 public: InvokeDexCallingConvention()64 InvokeDexCallingConvention() 65 : CallingConvention(kParameterCoreRegisters, 66 kParameterCoreRegistersLength, 67 kParameterFpuRegisters, 68 kParameterFpuRegistersLength, 69 kMips64PointerSize) {} 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 73 }; 74 75 class InvokeDexCallingConventionVisitorMIPS64 : public InvokeDexCallingConventionVisitor { 76 public: InvokeDexCallingConventionVisitorMIPS64()77 InvokeDexCallingConventionVisitorMIPS64() {} ~InvokeDexCallingConventionVisitorMIPS64()78 virtual ~InvokeDexCallingConventionVisitorMIPS64() {} 79 80 Location GetNextLocation(Primitive::Type type) OVERRIDE; 81 Location GetReturnLocation(Primitive::Type type) const OVERRIDE; 82 Location GetMethodLocation() const OVERRIDE; 83 84 private: 85 InvokeDexCallingConvention calling_convention; 86 87 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorMIPS64); 88 }; 89 90 class InvokeRuntimeCallingConvention : public CallingConvention<GpuRegister, FpuRegister> { 91 public: InvokeRuntimeCallingConvention()92 InvokeRuntimeCallingConvention() 93 : CallingConvention(kRuntimeParameterCoreRegisters, 94 kRuntimeParameterCoreRegistersLength, 95 kRuntimeParameterFpuRegisters, 96 kRuntimeParameterFpuRegistersLength, 97 kMips64PointerSize) {} 98 99 Location GetReturnLocation(Primitive::Type return_type); 100 101 private: 102 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 103 }; 104 105 class FieldAccessCallingConventionMIPS64 : public FieldAccessCallingConvention { 106 public: FieldAccessCallingConventionMIPS64()107 FieldAccessCallingConventionMIPS64() {} 108 GetObjectLocation()109 Location GetObjectLocation() const OVERRIDE { 110 return Location::RegisterLocation(A1); 111 } GetFieldIndexLocation()112 Location GetFieldIndexLocation() const OVERRIDE { 113 return Location::RegisterLocation(A0); 114 } GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED)115 Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 116 return Location::RegisterLocation(V0); 117 } GetSetValueLocation(Primitive::Type type,bool is_instance)118 Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { 119 return Primitive::Is64BitType(type) 120 ? Location::RegisterLocation(A2) 121 : (is_instance 122 ? Location::RegisterLocation(A2) 123 : Location::RegisterLocation(A1)); 124 } GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED)125 Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 126 return Location::FpuRegisterLocation(F0); 127 } 128 129 private: 130 DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionMIPS64); 131 }; 132 133 class ParallelMoveResolverMIPS64 : public ParallelMoveResolverWithSwap { 134 public: ParallelMoveResolverMIPS64(ArenaAllocator * allocator,CodeGeneratorMIPS64 * codegen)135 ParallelMoveResolverMIPS64(ArenaAllocator* allocator, CodeGeneratorMIPS64* codegen) 136 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 137 138 void EmitMove(size_t index) OVERRIDE; 139 void EmitSwap(size_t index) OVERRIDE; 140 void SpillScratch(int reg) OVERRIDE; 141 void RestoreScratch(int reg) OVERRIDE; 142 143 void Exchange(int index1, int index2, bool double_slot); 144 145 Mips64Assembler* GetAssembler() const; 146 147 private: 148 CodeGeneratorMIPS64* const codegen_; 149 150 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverMIPS64); 151 }; 152 153 class SlowPathCodeMIPS64 : public SlowPathCode { 154 public: SlowPathCodeMIPS64(HInstruction * instruction)155 explicit SlowPathCodeMIPS64(HInstruction* instruction) 156 : SlowPathCode(instruction), entry_label_(), exit_label_() {} 157 GetEntryLabel()158 Mips64Label* GetEntryLabel() { return &entry_label_; } GetExitLabel()159 Mips64Label* GetExitLabel() { return &exit_label_; } 160 161 private: 162 Mips64Label entry_label_; 163 Mips64Label exit_label_; 164 165 DISALLOW_COPY_AND_ASSIGN(SlowPathCodeMIPS64); 166 }; 167 168 class LocationsBuilderMIPS64 : public HGraphVisitor { 169 public: LocationsBuilderMIPS64(HGraph * graph,CodeGeneratorMIPS64 * codegen)170 LocationsBuilderMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen) 171 : HGraphVisitor(graph), codegen_(codegen) {} 172 173 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 174 void Visit##name(H##name* instr) OVERRIDE; 175 176 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION)177 FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION) 178 179 #undef DECLARE_VISIT_INSTRUCTION 180 181 void VisitInstruction(HInstruction* instruction) OVERRIDE { 182 LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 183 << " (id " << instruction->GetId() << ")"; 184 } 185 186 private: 187 void HandleInvoke(HInvoke* invoke); 188 void HandleBinaryOp(HBinaryOperation* operation); 189 void HandleCondition(HCondition* instruction); 190 void HandleShift(HBinaryOperation* operation); 191 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 192 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 193 194 InvokeDexCallingConventionVisitorMIPS64 parameter_visitor_; 195 196 CodeGeneratorMIPS64* const codegen_; 197 198 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderMIPS64); 199 }; 200 201 class InstructionCodeGeneratorMIPS64 : public InstructionCodeGenerator { 202 public: 203 InstructionCodeGeneratorMIPS64(HGraph* graph, CodeGeneratorMIPS64* codegen); 204 205 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 206 void Visit##name(H##name* instr) OVERRIDE; 207 208 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION)209 FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(DECLARE_VISIT_INSTRUCTION) 210 211 #undef DECLARE_VISIT_INSTRUCTION 212 213 void VisitInstruction(HInstruction* instruction) OVERRIDE { 214 LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 215 << " (id " << instruction->GetId() << ")"; 216 } 217 GetAssembler()218 Mips64Assembler* GetAssembler() const { return assembler_; } 219 220 private: 221 void GenerateClassInitializationCheck(SlowPathCodeMIPS64* slow_path, GpuRegister class_reg); 222 void GenerateMemoryBarrier(MemBarrierKind kind); 223 void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor); 224 void HandleBinaryOp(HBinaryOperation* operation); 225 void HandleCondition(HCondition* instruction); 226 void HandleShift(HBinaryOperation* operation); 227 void HandleFieldSet(HInstruction* instruction, 228 const FieldInfo& field_info, 229 bool value_can_be_null); 230 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 231 void GenerateTestAndBranch(HInstruction* instruction, 232 size_t condition_input_index, 233 Mips64Label* true_target, 234 Mips64Label* false_target); 235 void DivRemOneOrMinusOne(HBinaryOperation* instruction); 236 void DivRemByPowerOfTwo(HBinaryOperation* instruction); 237 void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 238 void GenerateDivRemIntegral(HBinaryOperation* instruction); 239 void GenerateIntLongCompare(IfCondition cond, bool is64bit, LocationSummary* locations); 240 void GenerateIntLongCompareAndBranch(IfCondition cond, 241 bool is64bit, 242 LocationSummary* locations, 243 Mips64Label* label); 244 void GenerateFpCompareAndBranch(IfCondition cond, 245 bool gt_bias, 246 Primitive::Type type, 247 LocationSummary* locations, 248 Mips64Label* label); 249 void HandleGoto(HInstruction* got, HBasicBlock* successor); 250 251 Mips64Assembler* const assembler_; 252 CodeGeneratorMIPS64* const codegen_; 253 254 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorMIPS64); 255 }; 256 257 class CodeGeneratorMIPS64 : public CodeGenerator { 258 public: 259 CodeGeneratorMIPS64(HGraph* graph, 260 const Mips64InstructionSetFeatures& isa_features, 261 const CompilerOptions& compiler_options, 262 OptimizingCompilerStats* stats = nullptr); ~CodeGeneratorMIPS64()263 virtual ~CodeGeneratorMIPS64() {} 264 265 void GenerateFrameEntry() OVERRIDE; 266 void GenerateFrameExit() OVERRIDE; 267 268 void Bind(HBasicBlock* block) OVERRIDE; 269 GetWordSize()270 size_t GetWordSize() const OVERRIDE { return kMips64DoublewordSize; } 271 GetFloatingPointSpillSlotSize()272 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64DoublewordSize; } 273 GetAddressOf(HBasicBlock * block)274 uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE { 275 return assembler_.GetLabelLocation(GetLabelOf(block)); 276 } 277 GetLocationBuilder()278 HGraphVisitor* GetLocationBuilder() OVERRIDE { return &location_builder_; } GetInstructionVisitor()279 HGraphVisitor* GetInstructionVisitor() OVERRIDE { return &instruction_visitor_; } GetAssembler()280 Mips64Assembler* GetAssembler() OVERRIDE { return &assembler_; } GetAssembler()281 const Mips64Assembler& GetAssembler() const OVERRIDE { return assembler_; } 282 283 void MarkGCCard(GpuRegister object, GpuRegister value, bool value_can_be_null); 284 285 // Register allocation. 286 287 void SetupBlockedRegisters() const OVERRIDE; 288 289 size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id); 290 size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id); 291 size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id); 292 size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id); 293 294 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 295 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 296 GetInstructionSet()297 InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; } 298 GetInstructionSetFeatures()299 const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const { 300 return isa_features_; 301 } 302 GetLabelOf(HBasicBlock * block)303 Mips64Label* GetLabelOf(HBasicBlock* block) const { 304 return CommonGetLabelOf<Mips64Label>(block_labels_, block); 305 } 306 Initialize()307 void Initialize() OVERRIDE { 308 block_labels_ = CommonInitializeLabels<Mips64Label>(); 309 } 310 311 void Finalize(CodeAllocator* allocator) OVERRIDE; 312 313 // Code generation helpers. 314 void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 315 316 void MoveConstant(Location destination, int32_t value) OVERRIDE; 317 318 void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 319 320 321 void SwapLocations(Location loc1, Location loc2, Primitive::Type type); 322 323 // Generate code to invoke a runtime entry point. 324 void InvokeRuntime(QuickEntrypointEnum entrypoint, 325 HInstruction* instruction, 326 uint32_t dex_pc, 327 SlowPathCode* slow_path) OVERRIDE; 328 329 void InvokeRuntime(int32_t offset, 330 HInstruction* instruction, 331 uint32_t dex_pc, 332 SlowPathCode* slow_path); 333 GetMoveResolver()334 ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; } 335 NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED)336 bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const { return false; } 337 338 // Check if the desired_string_load_kind is supported. If it is, return it, 339 // otherwise return a fall-back kind that should be used instead. 340 HLoadString::LoadKind GetSupportedLoadStringKind( 341 HLoadString::LoadKind desired_string_load_kind) OVERRIDE; 342 343 // Check if the desired_dispatch_info is supported. If it is, return it, 344 // otherwise return a fall-back info that should be used instead. 345 HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 346 const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 347 MethodReference target_method) OVERRIDE; 348 349 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 350 void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 351 MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED,Primitive::Type type ATTRIBUTE_UNUSED)352 void MoveFromReturnRegister(Location trg ATTRIBUTE_UNUSED, 353 Primitive::Type type ATTRIBUTE_UNUSED) OVERRIDE { 354 UNIMPLEMENTED(FATAL) << "Not implemented on MIPS64"; 355 } 356 357 void GenerateNop(); 358 void GenerateImplicitNullCheck(HNullCheck* instruction); 359 void GenerateExplicitNullCheck(HNullCheck* instruction); 360 361 private: 362 // Labels for each block that will be compiled. 363 Mips64Label* block_labels_; // Indexed by block id. 364 Mips64Label frame_entry_label_; 365 LocationsBuilderMIPS64 location_builder_; 366 InstructionCodeGeneratorMIPS64 instruction_visitor_; 367 ParallelMoveResolverMIPS64 move_resolver_; 368 Mips64Assembler assembler_; 369 const Mips64InstructionSetFeatures& isa_features_; 370 371 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorMIPS64); 372 }; 373 374 } // namespace mips64 375 } // namespace art 376 377 #endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_MIPS64_H_ 378