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 "arch/x86_64/instruction_set_features_x86_64.h" 21 #include "code_generator.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 27 namespace art { 28 namespace x86_64 { 29 30 // Use a local definition to prevent copying mistakes. 31 static constexpr size_t kX86_64WordSize = static_cast<size_t>(kX86_64PointerSize); 32 33 // Some x86_64 instructions require a register to be available as temp. 34 static constexpr Register TMP = R11; 35 36 static constexpr Register kParameterCoreRegisters[] = { RSI, RDX, RCX, R8, R9 }; 37 static constexpr FloatRegister kParameterFloatRegisters[] = 38 { XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7 }; 39 40 static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); 41 static constexpr size_t kParameterFloatRegistersLength = arraysize(kParameterFloatRegisters); 42 43 static constexpr Register kRuntimeParameterCoreRegisters[] = { RDI, RSI, RDX, RCX }; 44 static constexpr size_t kRuntimeParameterCoreRegistersLength = 45 arraysize(kRuntimeParameterCoreRegisters); 46 static constexpr FloatRegister kRuntimeParameterFpuRegisters[] = { XMM0, XMM1 }; 47 static constexpr size_t kRuntimeParameterFpuRegistersLength = 48 arraysize(kRuntimeParameterFpuRegisters); 49 50 // These XMM registers are non-volatile in ART ABI, but volatile in native ABI. 51 // If the ART ABI changes, this list must be updated. It is used to ensure that 52 // these are not clobbered by any direct call to native code (such as math intrinsics). 53 static constexpr FloatRegister non_volatile_xmm_regs[] = { XMM12, XMM13, XMM14, XMM15 }; 54 55 56 class InvokeRuntimeCallingConvention : public CallingConvention<Register, FloatRegister> { 57 public: InvokeRuntimeCallingConvention()58 InvokeRuntimeCallingConvention() 59 : CallingConvention(kRuntimeParameterCoreRegisters, 60 kRuntimeParameterCoreRegistersLength, 61 kRuntimeParameterFpuRegisters, 62 kRuntimeParameterFpuRegistersLength, 63 kX86_64PointerSize) {} 64 65 private: 66 DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention); 67 }; 68 69 class InvokeDexCallingConvention : public CallingConvention<Register, FloatRegister> { 70 public: InvokeDexCallingConvention()71 InvokeDexCallingConvention() : CallingConvention( 72 kParameterCoreRegisters, 73 kParameterCoreRegistersLength, 74 kParameterFloatRegisters, 75 kParameterFloatRegistersLength, 76 kX86_64PointerSize) {} 77 78 private: 79 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); 80 }; 81 82 class FieldAccessCallingConventionX86_64 : public FieldAccessCallingConvention { 83 public: FieldAccessCallingConventionX86_64()84 FieldAccessCallingConventionX86_64() {} 85 GetObjectLocation()86 Location GetObjectLocation() const OVERRIDE { 87 return Location::RegisterLocation(RSI); 88 } GetFieldIndexLocation()89 Location GetFieldIndexLocation() const OVERRIDE { 90 return Location::RegisterLocation(RDI); 91 } GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED)92 Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 93 return Location::RegisterLocation(RAX); 94 } GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED,bool is_instance)95 Location GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED, bool is_instance) 96 const OVERRIDE { 97 return is_instance 98 ? Location::RegisterLocation(RDX) 99 : Location::RegisterLocation(RSI); 100 } GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED)101 Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 102 return Location::FpuRegisterLocation(XMM0); 103 } 104 105 private: 106 DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConventionX86_64); 107 }; 108 109 110 class InvokeDexCallingConventionVisitorX86_64 : public InvokeDexCallingConventionVisitor { 111 public: InvokeDexCallingConventionVisitorX86_64()112 InvokeDexCallingConventionVisitorX86_64() {} ~InvokeDexCallingConventionVisitorX86_64()113 virtual ~InvokeDexCallingConventionVisitorX86_64() {} 114 115 Location GetNextLocation(Primitive::Type type) OVERRIDE; 116 Location GetReturnLocation(Primitive::Type type) const OVERRIDE; 117 Location GetMethodLocation() const OVERRIDE; 118 119 private: 120 InvokeDexCallingConvention calling_convention; 121 122 DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitorX86_64); 123 }; 124 125 class CodeGeneratorX86_64; 126 127 class ParallelMoveResolverX86_64 : public ParallelMoveResolverWithSwap { 128 public: ParallelMoveResolverX86_64(ArenaAllocator * allocator,CodeGeneratorX86_64 * codegen)129 ParallelMoveResolverX86_64(ArenaAllocator* allocator, CodeGeneratorX86_64* codegen) 130 : ParallelMoveResolverWithSwap(allocator), codegen_(codegen) {} 131 132 void EmitMove(size_t index) OVERRIDE; 133 void EmitSwap(size_t index) OVERRIDE; 134 void SpillScratch(int reg) OVERRIDE; 135 void RestoreScratch(int reg) OVERRIDE; 136 137 X86_64Assembler* GetAssembler() const; 138 139 private: 140 void Exchange32(CpuRegister reg, int mem); 141 void Exchange32(XmmRegister reg, int mem); 142 void Exchange32(int mem1, int mem2); 143 void Exchange64(CpuRegister reg1, CpuRegister reg2); 144 void Exchange64(CpuRegister reg, int mem); 145 void Exchange64(XmmRegister reg, int mem); 146 void Exchange64(int mem1, int mem2); 147 148 CodeGeneratorX86_64* const codegen_; 149 150 DISALLOW_COPY_AND_ASSIGN(ParallelMoveResolverX86_64); 151 }; 152 153 class LocationsBuilderX86_64 : public HGraphVisitor { 154 public: LocationsBuilderX86_64(HGraph * graph,CodeGeneratorX86_64 * codegen)155 LocationsBuilderX86_64(HGraph* graph, CodeGeneratorX86_64* codegen) 156 : HGraphVisitor(graph), codegen_(codegen) {} 157 158 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 159 void Visit##name(H##name* instr) OVERRIDE; 160 161 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION)162 FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION) 163 164 #undef DECLARE_VISIT_INSTRUCTION 165 166 void VisitInstruction(HInstruction* instruction) OVERRIDE { 167 LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 168 << " (id " << instruction->GetId() << ")"; 169 } 170 171 private: 172 void HandleInvoke(HInvoke* invoke); 173 void HandleBitwiseOperation(HBinaryOperation* operation); 174 void HandleCondition(HCondition* condition); 175 void HandleShift(HBinaryOperation* operation); 176 void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); 177 void HandleFieldGet(HInstruction* instruction); 178 179 CodeGeneratorX86_64* const codegen_; 180 InvokeDexCallingConventionVisitorX86_64 parameter_visitor_; 181 182 DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86_64); 183 }; 184 185 class InstructionCodeGeneratorX86_64 : public InstructionCodeGenerator { 186 public: 187 InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen); 188 189 #define DECLARE_VISIT_INSTRUCTION(name, super) \ 190 void Visit##name(H##name* instr) OVERRIDE; 191 192 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(DECLARE_VISIT_INSTRUCTION) FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION)193 FOR_EACH_CONCRETE_INSTRUCTION_X86_64(DECLARE_VISIT_INSTRUCTION) 194 195 #undef DECLARE_VISIT_INSTRUCTION 196 197 void VisitInstruction(HInstruction* instruction) OVERRIDE { 198 LOG(FATAL) << "Unreachable instruction " << instruction->DebugName() 199 << " (id " << instruction->GetId() << ")"; 200 } 201 GetAssembler()202 X86_64Assembler* GetAssembler() const { return assembler_; } 203 204 private: 205 // Generate code for the given suspend check. If not null, `successor` 206 // is the block to branch to if the suspend check is not needed, and after 207 // the suspend call. 208 void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor); 209 void GenerateClassInitializationCheck(SlowPathCode* slow_path, CpuRegister class_reg); 210 void HandleBitwiseOperation(HBinaryOperation* operation); 211 void GenerateRemFP(HRem* rem); 212 void DivRemOneOrMinusOne(HBinaryOperation* instruction); 213 void DivByPowerOfTwo(HDiv* instruction); 214 void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction); 215 void GenerateDivRemIntegral(HBinaryOperation* instruction); 216 void HandleCondition(HCondition* condition); 217 void HandleShift(HBinaryOperation* operation); 218 219 void HandleFieldSet(HInstruction* instruction, 220 const FieldInfo& field_info, 221 bool value_can_be_null); 222 void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); 223 224 // Generate a heap reference load using one register `out`: 225 // 226 // out <- *(out + offset) 227 // 228 // while honoring heap poisoning and/or read barriers (if any). 229 // 230 // Location `maybe_temp` is used when generating a read barrier and 231 // shall be a register in that case; it may be an invalid location 232 // otherwise. 233 void GenerateReferenceLoadOneRegister(HInstruction* instruction, 234 Location out, 235 uint32_t offset, 236 Location maybe_temp, 237 ReadBarrierOption read_barrier_option); 238 // Generate a heap reference load using two different registers 239 // `out` and `obj`: 240 // 241 // out <- *(obj + offset) 242 // 243 // while honoring heap poisoning and/or read barriers (if any). 244 // 245 // Location `maybe_temp` is used when generating a Baker's (fast 246 // path) read barrier and shall be a register in that case; it may 247 // be an invalid location otherwise. 248 void GenerateReferenceLoadTwoRegisters(HInstruction* instruction, 249 Location out, 250 Location obj, 251 uint32_t offset, 252 ReadBarrierOption read_barrier_option); 253 // Generate a GC root reference load: 254 // 255 // root <- *address 256 // 257 // while honoring read barriers based on read_barrier_option. 258 void GenerateGcRootFieldLoad(HInstruction* instruction, 259 Location root, 260 const Address& address, 261 Label* fixup_label, 262 ReadBarrierOption read_barrier_option); 263 264 void PushOntoFPStack(Location source, uint32_t temp_offset, 265 uint32_t stack_adjustment, bool is_float); 266 void GenerateCompareTest(HCondition* condition); 267 template<class LabelType> 268 void GenerateTestAndBranch(HInstruction* instruction, 269 size_t condition_input_index, 270 LabelType* true_target, 271 LabelType* false_target); 272 template<class LabelType> 273 void GenerateCompareTestAndBranch(HCondition* condition, 274 LabelType* true_target, 275 LabelType* false_target); 276 template<class LabelType> 277 void GenerateFPJumps(HCondition* cond, LabelType* true_label, LabelType* false_label); 278 279 void HandleGoto(HInstruction* got, HBasicBlock* successor); 280 281 X86_64Assembler* const assembler_; 282 CodeGeneratorX86_64* const codegen_; 283 284 DISALLOW_COPY_AND_ASSIGN(InstructionCodeGeneratorX86_64); 285 }; 286 287 // Class for fixups to jump tables. 288 class JumpTableRIPFixup; 289 290 class CodeGeneratorX86_64 : public CodeGenerator { 291 public: 292 CodeGeneratorX86_64(HGraph* graph, 293 const X86_64InstructionSetFeatures& isa_features, 294 const CompilerOptions& compiler_options, 295 OptimizingCompilerStats* stats = nullptr); ~CodeGeneratorX86_64()296 virtual ~CodeGeneratorX86_64() {} 297 298 void GenerateFrameEntry() OVERRIDE; 299 void GenerateFrameExit() OVERRIDE; 300 void Bind(HBasicBlock* block) OVERRIDE; 301 void MoveConstant(Location destination, int32_t value) OVERRIDE; 302 void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE; 303 void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE; 304 305 size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 306 size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 307 size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 308 size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE; 309 310 // Generate code to invoke a runtime entry point. 311 void InvokeRuntime(QuickEntrypointEnum entrypoint, 312 HInstruction* instruction, 313 uint32_t dex_pc, 314 SlowPathCode* slow_path = nullptr) OVERRIDE; 315 316 // Generate code to invoke a runtime entry point, but do not record 317 // PC-related information in a stack map. 318 void InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset, 319 HInstruction* instruction, 320 SlowPathCode* slow_path); 321 322 void GenerateInvokeRuntime(int32_t entry_point_offset); 323 GetWordSize()324 size_t GetWordSize() const OVERRIDE { 325 return kX86_64WordSize; 326 } 327 GetFloatingPointSpillSlotSize()328 size_t GetFloatingPointSpillSlotSize() const OVERRIDE { 329 return GetGraph()->HasSIMD() 330 ? 2 * kX86_64WordSize // 16 bytes == 2 x86_64 words for each spill 331 : 1 * kX86_64WordSize; // 8 bytes == 1 x86_64 words for each spill 332 } 333 GetLocationBuilder()334 HGraphVisitor* GetLocationBuilder() OVERRIDE { 335 return &location_builder_; 336 } 337 GetInstructionVisitor()338 HGraphVisitor* GetInstructionVisitor() OVERRIDE { 339 return &instruction_visitor_; 340 } 341 GetAssembler()342 X86_64Assembler* GetAssembler() OVERRIDE { 343 return &assembler_; 344 } 345 GetAssembler()346 const X86_64Assembler& GetAssembler() const OVERRIDE { 347 return assembler_; 348 } 349 GetMoveResolver()350 ParallelMoveResolverX86_64* GetMoveResolver() OVERRIDE { 351 return &move_resolver_; 352 } 353 GetAddressOf(HBasicBlock * block)354 uintptr_t GetAddressOf(HBasicBlock* block) OVERRIDE { 355 return GetLabelOf(block)->Position(); 356 } 357 358 void SetupBlockedRegisters() const OVERRIDE; 359 void DumpCoreRegister(std::ostream& stream, int reg) const OVERRIDE; 360 void DumpFloatingPointRegister(std::ostream& stream, int reg) const OVERRIDE; 361 void Finalize(CodeAllocator* allocator) OVERRIDE; 362 GetInstructionSet()363 InstructionSet GetInstructionSet() const OVERRIDE { 364 return InstructionSet::kX86_64; 365 } 366 367 // Emit a write barrier. 368 void MarkGCCard(CpuRegister temp, 369 CpuRegister card, 370 CpuRegister object, 371 CpuRegister value, 372 bool value_can_be_null); 373 374 void GenerateMemoryBarrier(MemBarrierKind kind); 375 376 // Helper method to move a value between two locations. 377 void Move(Location destination, Location source); 378 GetLabelOf(HBasicBlock * block)379 Label* GetLabelOf(HBasicBlock* block) const { 380 return CommonGetLabelOf<Label>(block_labels_, block); 381 } 382 Initialize()383 void Initialize() OVERRIDE { 384 block_labels_ = CommonInitializeLabels<Label>(); 385 } 386 NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED)387 bool NeedsTwoRegisters(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { 388 return false; 389 } 390 391 // Check if the desired_string_load_kind is supported. If it is, return it, 392 // otherwise return a fall-back kind that should be used instead. 393 HLoadString::LoadKind GetSupportedLoadStringKind( 394 HLoadString::LoadKind desired_string_load_kind) OVERRIDE; 395 396 // Check if the desired_class_load_kind is supported. If it is, return it, 397 // otherwise return a fall-back kind that should be used instead. 398 HLoadClass::LoadKind GetSupportedLoadClassKind( 399 HLoadClass::LoadKind desired_class_load_kind) OVERRIDE; 400 401 // Check if the desired_dispatch_info is supported. If it is, return it, 402 // otherwise return a fall-back info that should be used instead. 403 HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 404 const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 405 HInvokeStaticOrDirect* invoke) OVERRIDE; 406 407 Location GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp); 408 void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; 409 void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; 410 411 void RecordBootStringPatch(HLoadString* load_string); 412 void RecordBootTypePatch(HLoadClass* load_class); 413 Label* NewTypeBssEntryPatch(HLoadClass* load_class); 414 Label* NewStringBssEntryPatch(HLoadString* load_string); 415 Label* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file, uint32_t element_offset); 416 Label* NewJitRootStringPatch(const DexFile& dex_file, 417 dex::StringIndex dex_index, 418 Handle<mirror::String> handle); 419 Label* NewJitRootClassPatch(const DexFile& dex_file, 420 dex::TypeIndex dex_index, 421 Handle<mirror::Class> handle); 422 423 void MoveFromReturnRegister(Location trg, Primitive::Type type) OVERRIDE; 424 425 void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE; 426 427 void PatchJitRootUse(uint8_t* code, 428 const uint8_t* roots_data, 429 const PatchInfo<Label>& info, 430 uint64_t index_in_table) const; 431 432 void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE; 433 GetInstructionSetFeatures()434 const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const { 435 return isa_features_; 436 } 437 438 // Fast path implementation of ReadBarrier::Barrier for a heap 439 // reference field load when Baker's read barriers are used. 440 void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, 441 Location ref, 442 CpuRegister obj, 443 uint32_t offset, 444 bool needs_null_check); 445 // Fast path implementation of ReadBarrier::Barrier for a heap 446 // reference array load when Baker's read barriers are used. 447 void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, 448 Location ref, 449 CpuRegister obj, 450 uint32_t data_offset, 451 Location index, 452 bool needs_null_check); 453 // Factored implementation, used by GenerateFieldLoadWithBakerReadBarrier, 454 // GenerateArrayLoadWithBakerReadBarrier and some intrinsics. 455 // 456 // Load the object reference located at address `src`, held by 457 // object `obj`, into `ref`, and mark it if needed. The base of 458 // address `src` must be `obj`. 459 // 460 // If `always_update_field` is true, the value of the reference is 461 // atomically updated in the holder (`obj`). This operation 462 // requires two temporary registers, which must be provided as 463 // non-null pointers (`temp1` and `temp2`). 464 void GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction, 465 Location ref, 466 CpuRegister obj, 467 const Address& src, 468 bool needs_null_check, 469 bool always_update_field = false, 470 CpuRegister* temp1 = nullptr, 471 CpuRegister* temp2 = nullptr); 472 473 // Generate a read barrier for a heap reference within `instruction` 474 // using a slow path. 475 // 476 // A read barrier for an object reference read from the heap is 477 // implemented as a call to the artReadBarrierSlow runtime entry 478 // point, which is passed the values in locations `ref`, `obj`, and 479 // `offset`: 480 // 481 // mirror::Object* artReadBarrierSlow(mirror::Object* ref, 482 // mirror::Object* obj, 483 // uint32_t offset); 484 // 485 // The `out` location contains the value returned by 486 // artReadBarrierSlow. 487 // 488 // When `index` provided (i.e., when it is different from 489 // Location::NoLocation()), the offset value passed to 490 // artReadBarrierSlow is adjusted to take `index` into account. 491 void GenerateReadBarrierSlow(HInstruction* instruction, 492 Location out, 493 Location ref, 494 Location obj, 495 uint32_t offset, 496 Location index = Location::NoLocation()); 497 498 // If read barriers are enabled, generate a read barrier for a heap 499 // reference using a slow path. If heap poisoning is enabled, also 500 // unpoison the reference in `out`. 501 void MaybeGenerateReadBarrierSlow(HInstruction* instruction, 502 Location out, 503 Location ref, 504 Location obj, 505 uint32_t offset, 506 Location index = Location::NoLocation()); 507 508 // Generate a read barrier for a GC root within `instruction` using 509 // a slow path. 510 // 511 // A read barrier for an object reference GC root is implemented as 512 // a call to the artReadBarrierForRootSlow runtime entry point, 513 // which is passed the value in location `root`: 514 // 515 // mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root); 516 // 517 // The `out` location contains the value returned by 518 // artReadBarrierForRootSlow. 519 void GenerateReadBarrierForRootSlow(HInstruction* instruction, Location out, Location root); 520 ConstantAreaStart()521 int ConstantAreaStart() const { 522 return constant_area_start_; 523 } 524 525 Address LiteralDoubleAddress(double v); 526 Address LiteralFloatAddress(float v); 527 Address LiteralInt32Address(int32_t v); 528 Address LiteralInt64Address(int64_t v); 529 530 // Load a 32/64-bit value into a register in the most efficient manner. 531 void Load32BitValue(CpuRegister dest, int32_t value); 532 void Load64BitValue(CpuRegister dest, int64_t value); 533 void Load32BitValue(XmmRegister dest, int32_t value); 534 void Load64BitValue(XmmRegister dest, int64_t value); 535 void Load32BitValue(XmmRegister dest, float value); 536 void Load64BitValue(XmmRegister dest, double value); 537 538 // Compare a register with a 32/64-bit value in the most efficient manner. 539 void Compare32BitValue(CpuRegister dest, int32_t value); 540 void Compare64BitValue(CpuRegister dest, int64_t value); 541 542 // Compare int values. Supports register locations for `lhs`. 543 void GenerateIntCompare(Location lhs, Location rhs); 544 void GenerateIntCompare(CpuRegister lhs, Location rhs); 545 546 // Compare long values. Supports only register locations for `lhs`. 547 void GenerateLongCompare(Location lhs, Location rhs); 548 549 // Construct address for array access. 550 static Address ArrayAddress(CpuRegister obj, 551 Location index, 552 ScaleFactor scale, 553 uint32_t data_offset); 554 555 Address LiteralCaseTable(HPackedSwitch* switch_instr); 556 557 // Store a 64 bit value into a DoubleStackSlot in the most efficient manner. 558 void Store64BitValueToStack(Location dest, int64_t value); 559 560 // Assign a 64 bit constant to an address. 561 void MoveInt64ToAddress(const Address& addr_low, 562 const Address& addr_high, 563 int64_t v, 564 HInstruction* instruction); 565 566 // Ensure that prior stores complete to memory before subsequent loads. 567 // The locked add implementation will avoid serializing device memory, but will 568 // touch (but not change) the top of the stack. 569 // The 'non_temporal' parameter should be used to ensure ordering of non-temporal stores. 570 void MemoryFence(bool force_mfence = false) { 571 if (!force_mfence) { 572 assembler_.lock()->addl(Address(CpuRegister(RSP), 0), Immediate(0)); 573 } else { 574 assembler_.mfence(); 575 } 576 } 577 578 void GenerateNop() OVERRIDE; 579 void GenerateImplicitNullCheck(HNullCheck* instruction) OVERRIDE; 580 void GenerateExplicitNullCheck(HNullCheck* instruction) OVERRIDE; 581 582 // When we don't know the proper offset for the value, we use kDummy32BitOffset. 583 // We will fix this up in the linker later to have the right value. 584 static constexpr int32_t kDummy32BitOffset = 256; 585 586 private: 587 template <LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)> 588 static void EmitPcRelativeLinkerPatches(const ArenaDeque<PatchInfo<Label>>& infos, 589 ArenaVector<LinkerPatch>* linker_patches); 590 591 // Labels for each block that will be compiled. 592 Label* block_labels_; // Indexed by block id. 593 Label frame_entry_label_; 594 LocationsBuilderX86_64 location_builder_; 595 InstructionCodeGeneratorX86_64 instruction_visitor_; 596 ParallelMoveResolverX86_64 move_resolver_; 597 X86_64Assembler assembler_; 598 const X86_64InstructionSetFeatures& isa_features_; 599 600 // Offset to the start of the constant area in the assembled code. 601 // Used for fixups to the constant area. 602 int constant_area_start_; 603 604 // PC-relative DexCache access info. 605 ArenaDeque<PatchInfo<Label>> pc_relative_dex_cache_patches_; 606 // String patch locations; type depends on configuration (app .bss or boot image PIC). 607 ArenaDeque<PatchInfo<Label>> string_patches_; 608 // Type patch locations for boot image (always PIC). 609 ArenaDeque<PatchInfo<Label>> boot_image_type_patches_; 610 // Type patch locations for kBssEntry. 611 ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_; 612 613 // Fixups for jump tables need to be handled specially. 614 ArenaVector<JumpTableRIPFixup*> fixups_to_jump_tables_; 615 616 // Patches for string literals in JIT compiled code. 617 ArenaDeque<PatchInfo<Label>> jit_string_patches_; 618 619 // Patches for class literals in JIT compiled code. 620 ArenaDeque<PatchInfo<Label>> jit_class_patches_; 621 622 DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86_64); 623 }; 624 625 } // namespace x86_64 626 } // namespace art 627 628 #endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_X86_64_H_ 629