Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 // push 0 | 208 // push 0 |
| 209 // mov %ebp, %(rsp) | 209 // mov %ebp, %(rsp) |
| 210 // .bundle_end | 210 // .bundle_end |
| 211 // | 211 // |
| 212 // to avoid leaking the upper 32-bits (i.e., the sandbox address.) | 212 // to avoid leaking the upper 32-bits (i.e., the sandbox address.) |
| 213 AutoBundle _(this); | 213 AutoBundle _(this); |
| 214 _push(_0); | 214 _push(_0); |
| 215 Context.insert<typename Traits::Insts::Store>(ebp, TopOfStack); | 215 Context.insert<typename Traits::Insts::Store>(ebp, TopOfStack); |
| 216 } | 216 } |
| 217 | 217 |
| 218 void TargetX8664::_link_bp() { | |
| 219 Variable *esp = | |
| 220 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); | |
| 221 Variable *rsp = | |
| 222 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, Traits::WordType); | |
| 223 Variable *ebp = | |
| 224 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32); | |
| 225 Variable *rbp = | |
| 226 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, Traits::WordType); | |
| 227 Variable *r15 = | |
| 228 getPhysicalRegister(Traits::RegisterSet::Reg_r15, Traits::WordType); | |
| 229 | |
| 230 if (!NeedSandboxing) { | |
| 231 _push(rbp); | |
| 232 _mov(rbp, rsp); | |
| 233 } else { | |
| 234 _push_rbp(); | |
| 235 | |
| 236 AutoBundle _(this); | |
| 237 _redefined(Context.insert<InstFakeDef>(ebp, rbp)); | |
| 238 _redefined(Context.insert<InstFakeDef>(esp, rsp)); | |
| 239 _mov(ebp, esp); | |
| 240 _redefined(Context.insert<InstFakeDef>(rsp, esp)); | |
| 241 _add(rbp, r15); | |
| 242 } | |
| 243 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | |
| 244 Context.insert<InstFakeUse>(rbp); | |
| 245 } | |
| 246 | |
| 247 void TargetX8664::_unlink_bp() { | |
| 248 Variable *rsp = | |
| 249 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); | |
| 250 Variable *rbp = | |
| 251 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); | |
| 252 Variable *ebp = | |
| 253 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32); | |
| 254 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | |
| 255 // use of rsp before the assignment of rsp=rbp keeps previous rsp | |
| 256 // adjustments from being dead-code eliminated. | |
| 257 Context.insert<InstFakeUse>(rsp); | |
| 258 if (!NeedSandboxing) { | |
| 259 _mov(rsp, rbp); | |
| 260 _pop(rbp); | |
| 261 } else { | |
| 262 _mov_sp(ebp); | |
| 263 | |
| 264 Variable *r15 = | |
| 265 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | |
| 266 Variable *rcx = | |
| 267 getPhysicalRegister(Traits::RegisterSet::Reg_rcx, IceType_i64); | |
| 268 Variable *ecx = | |
| 269 getPhysicalRegister(Traits::RegisterSet::Reg_ecx, IceType_i32); | |
| 270 | |
| 271 _pop(rcx); | |
| 272 Context.insert<InstFakeDef>(ecx, rcx); | |
| 273 AutoBundle _(this); | |
| 274 _mov(ebp, ecx); | |
| 275 | |
| 276 _redefined(Context.insert<InstFakeDef>(rbp, ebp)); | |
| 277 _add(rbp, r15); | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 | |
| 282 void TargetX8664::_push_reg(Variable *Reg) { | |
| 283 Variable *rbp = | |
| 284 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, Traits::WordType); | |
| 285 if (Reg != rbp || !NeedSandboxing) { | |
| 286 _push(Reg); | |
| 287 } else { | |
| 288 _push_rbp(); | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 void TargetX8664::emitGetIP(CfgNode *Node) { | |
| 293 // No IP base register is needed on X86-64. | |
| 294 (void)Node; | |
| 295 } | |
| 296 | |
| 218 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { | 297 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { |
| 219 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.) | 298 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.) |
| 220 // NaCl sandboxing also requires that any registers that are not %rsp and | 299 // NaCl sandboxing also requires that any registers that are not %rsp and |
| 221 // %rbp to be 'truncated' to 32-bit before memory access. | 300 // %rbp to be 'truncated' to 32-bit before memory access. |
| 222 assert(NeedSandboxing); | 301 assert(NeedSandboxing); |
| 223 Variable *Base = Mem->getBase(); | 302 Variable *Base = Mem->getBase(); |
| 224 Variable *Index = Mem->getIndex(); | 303 Variable *Index = Mem->getIndex(); |
| 225 uint16_t Shift = 0; | 304 uint16_t Shift = 0; |
| 226 Variable *r15 = | 305 Variable *r15 = |
| 227 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 306 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 Offset = nullptr; | 397 Offset = nullptr; |
| 319 } | 398 } |
| 320 | 399 |
| 321 static constexpr bool IsRebased = true; | 400 static constexpr bool IsRebased = true; |
| 322 return Traits::X86OperandMem::create( | 401 return Traits::X86OperandMem::create( |
| 323 Func, Mem->getType(), r15, Offset, T, Shift, | 402 Func, Mem->getType(), r15, Offset, T, Shift, |
| 324 Traits::X86OperandMem::DefaultSegment, IsRebased); | 403 Traits::X86OperandMem::DefaultSegment, IsRebased); |
| 325 } | 404 } |
| 326 | 405 |
| 327 void TargetX8664::_sub_sp(Operand *Adjustment) { | 406 void TargetX8664::_sub_sp(Operand *Adjustment) { |
| 328 Variable *rsp = | 407 Variable *rsp = getPhysicalRegister(getStackReg(), Traits::WordType); |
|
John
2016/01/21 15:04:52
why? just curious...
sehr
2016/01/21 16:02:10
I honestly think semantically referring to this as
| |
| 329 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); | |
| 330 if (!NeedSandboxing) { | 408 if (!NeedSandboxing) { |
| 331 _sub(rsp, Adjustment); | 409 _sub(rsp, Adjustment); |
| 332 return; | 410 return; |
| 333 } | 411 } |
| 334 | 412 |
| 335 Variable *esp = | 413 Variable *esp = |
| 336 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); | 414 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); |
| 337 Variable *r15 = | 415 Variable *r15 = |
| 338 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 416 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
| 339 | 417 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 return legalizeToReg(Value, Traits::RegisterSet::Reg_xmm0); | 519 return legalizeToReg(Value, Traits::RegisterSet::Reg_xmm0); |
| 442 } else { | 520 } else { |
| 443 assert(ReturnType == IceType_i32 || ReturnType == IceType_i64); | 521 assert(ReturnType == IceType_i32 || ReturnType == IceType_i64); |
| 444 Variable *Reg = nullptr; | 522 Variable *Reg = nullptr; |
| 445 _mov(Reg, Value, | 523 _mov(Reg, Value, |
| 446 Traits::getGprForType(ReturnType, Traits::RegisterSet::Reg_rax)); | 524 Traits::getGprForType(ReturnType, Traits::RegisterSet::Reg_rax)); |
| 447 return Reg; | 525 return Reg; |
| 448 } | 526 } |
| 449 } | 527 } |
| 450 | 528 |
| 451 void TargetX8664::addProlog(CfgNode *Node) { | 529 void TargetX8664::emitSandboxedReturn() { |
| 452 // Stack frame layout: | |
| 453 // | |
| 454 // +------------------------+ | |
| 455 // | 1. return address | | |
| 456 // +------------------------+ | |
| 457 // | 2. preserved registers | | |
| 458 // +------------------------+ | |
| 459 // | 3. padding | | |
| 460 // +------------------------+ | |
| 461 // | 4. global spill area | | |
| 462 // +------------------------+ | |
| 463 // | 5. padding | | |
| 464 // +------------------------+ | |
| 465 // | 6. local spill area | | |
| 466 // +------------------------+ | |
| 467 // | 7. padding | | |
| 468 // +------------------------+ | |
| 469 // | 8. allocas | | |
| 470 // +------------------------+ | |
| 471 // | 9. padding | | |
| 472 // +------------------------+ | |
| 473 // | 10. out args | | |
| 474 // +------------------------+ <--- StackPointer | |
| 475 // | |
| 476 // The following variables record the size in bytes of the given areas: | |
| 477 // * X86_RET_IP_SIZE_BYTES: area 1 | |
| 478 // * PreservedRegsSizeBytes: area 2 | |
| 479 // * SpillAreaPaddingBytes: area 3 | |
| 480 // * GlobalsSize: area 4 | |
| 481 // * GlobalsAndSubsequentPaddingSize: areas 4 - 5 | |
| 482 // * LocalsSpillAreaSize: area 6 | |
| 483 // * SpillAreaSizeBytes: areas 3 - 10 | |
| 484 // * maxOutArgsSizeBytes(): area 10 | |
| 485 | |
| 486 // Determine stack frame offsets for each Variable without a register | |
| 487 // assignment. This can be done as one variable per stack slot. Or, do | |
| 488 // coalescing by running the register allocator again with an infinite set of | |
| 489 // registers (as a side effect, this gives variables a second chance at | |
| 490 // physical register assignment). | |
| 491 // | |
| 492 // A middle ground approach is to leverage sparsity and allocate one block of | |
| 493 // space on the frame for globals (variables with multi-block lifetime), and | |
| 494 // one block to share for locals (single-block lifetime). | |
| 495 | |
| 496 Context.init(Node); | |
| 497 Context.setInsertPoint(Context.getCur()); | |
| 498 | |
| 499 llvm::SmallBitVector CalleeSaves = | |
| 500 getRegisterSet(RegSet_CalleeSave, RegSet_None); | |
| 501 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); | |
| 502 VarList SortedSpilledVariables, VariablesLinkedToSpillSlots; | |
| 503 size_t GlobalsSize = 0; | |
| 504 // If there is a separate locals area, this represents that area. Otherwise | |
| 505 // it counts any variable not counted by GlobalsSize. | |
| 506 SpillAreaSizeBytes = 0; | |
| 507 // If there is a separate locals area, this specifies the alignment for it. | |
| 508 uint32_t LocalsSlotsAlignmentBytes = 0; | |
| 509 // The entire spill locations area gets aligned to largest natural alignment | |
| 510 // of the variables that have a spill slot. | |
| 511 uint32_t SpillAreaAlignmentBytes = 0; | |
| 512 // A spill slot linked to a variable with a stack slot should reuse that | |
| 513 // stack slot. | |
| 514 std::function<bool(Variable *)> TargetVarHook = | |
| 515 [&VariablesLinkedToSpillSlots](Variable *Var) { | |
| 516 if (auto *SpillVar = | |
| 517 llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { | |
| 518 assert(Var->mustNotHaveReg()); | |
| 519 if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { | |
| 520 VariablesLinkedToSpillSlots.push_back(Var); | |
| 521 return true; | |
| 522 } | |
| 523 } | |
| 524 return false; | |
| 525 }; | |
| 526 | |
| 527 // Compute the list of spilled variables and bounds for GlobalsSize, etc. | |
| 528 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | |
| 529 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | |
| 530 &LocalsSlotsAlignmentBytes, TargetVarHook); | |
| 531 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; | |
| 532 SpillAreaSizeBytes += GlobalsSize; | |
| 533 | |
| 534 // Add push instructions for preserved registers. | |
| 535 uint32_t NumCallee = 0; | |
| 536 size_t PreservedRegsSizeBytes = 0; | |
| 537 llvm::SmallBitVector Pushed(CalleeSaves.size()); | |
| 538 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | |
| 539 const int32_t Canonical = Traits::getBaseReg(i); | |
| 540 assert(Canonical == Traits::getBaseReg(Canonical)); | |
| 541 if (CalleeSaves[i] && RegsUsed[i]) | |
| 542 Pushed[Canonical] = true; | |
| 543 } | |
| 544 | |
| 545 Variable *rbp = | |
| 546 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); | |
| 547 Variable *ebp = | |
| 548 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32); | |
| 549 Variable *rsp = | |
| 550 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); | |
| 551 | |
| 552 for (SizeT i = 0; i < Pushed.size(); ++i) { | |
| 553 if (!Pushed[i]) | |
| 554 continue; | |
| 555 assert(static_cast<int32_t>(i) == Traits::getBaseReg(i)); | |
| 556 ++NumCallee; | |
| 557 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | |
| 558 Variable *Src = getPhysicalRegister(i, IceType_i64); | |
| 559 if (Src != rbp || !NeedSandboxing) { | |
| 560 _push(getPhysicalRegister(i, IceType_i64)); | |
| 561 } else { | |
| 562 _push_rbp(); | |
| 563 } | |
| 564 } | |
| 565 Ctx->statsUpdateRegistersSaved(NumCallee); | |
| 566 | |
| 567 // Generate "push ebp; mov ebp, esp" | |
| 568 if (IsEbpBasedFrame) { | |
| 569 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | |
| 570 .count() == 0); | |
| 571 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | |
| 572 Variable *esp = | |
| 573 getPhysicalRegister(Traits::RegisterSet::Reg_esp, IceType_i32); | |
| 574 Variable *r15 = | |
| 575 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | |
| 576 | |
| 577 if (!NeedSandboxing) { | |
| 578 _push(rbp); | |
| 579 _mov(rbp, rsp); | |
| 580 } else { | |
| 581 _push_rbp(); | |
| 582 | |
| 583 AutoBundle _(this); | |
| 584 _redefined(Context.insert<InstFakeDef>(ebp, rbp)); | |
| 585 _redefined(Context.insert<InstFakeDef>(esp, rsp)); | |
| 586 _mov(ebp, esp); | |
| 587 _redefined(Context.insert<InstFakeDef>(rsp, esp)); | |
| 588 _add(rbp, r15); | |
| 589 } | |
| 590 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | |
| 591 Context.insert<InstFakeUse>(rbp); | |
| 592 } | |
| 593 | |
| 594 // Align the variables area. SpillAreaPaddingBytes is the size of the region | |
| 595 // after the preserved registers and before the spill areas. | |
| 596 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | |
| 597 // locals area if they are separate. | |
| 598 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); | |
| 599 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | |
| 600 uint32_t SpillAreaPaddingBytes = 0; | |
| 601 uint32_t LocalsSlotsPaddingBytes = 0; | |
| 602 alignStackSpillAreas(Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes, | |
| 603 SpillAreaAlignmentBytes, GlobalsSize, | |
| 604 LocalsSlotsAlignmentBytes, &SpillAreaPaddingBytes, | |
| 605 &LocalsSlotsPaddingBytes); | |
| 606 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; | |
| 607 uint32_t GlobalsAndSubsequentPaddingSize = | |
| 608 GlobalsSize + LocalsSlotsPaddingBytes; | |
| 609 | |
| 610 // Align esp if necessary. | |
| 611 if (NeedsStackAlignment) { | |
| 612 uint32_t StackOffset = | |
| 613 Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes; | |
| 614 uint32_t StackSize = | |
| 615 Traits::applyStackAlignment(StackOffset + SpillAreaSizeBytes); | |
| 616 StackSize = Traits::applyStackAlignment(StackSize + maxOutArgsSizeBytes()); | |
| 617 SpillAreaSizeBytes = StackSize - StackOffset; | |
| 618 } else { | |
| 619 SpillAreaSizeBytes += maxOutArgsSizeBytes(); | |
| 620 } | |
| 621 | |
| 622 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the | |
| 623 // fixed allocations in the prolog. | |
| 624 if (PrologEmitsFixedAllocas) | |
| 625 SpillAreaSizeBytes += FixedAllocaSizeBytes; | |
| 626 // Generate "sub esp, SpillAreaSizeBytes" | |
| 627 if (SpillAreaSizeBytes) { | |
| 628 if (NeedSandboxing) { | |
| 629 _sub_sp(Ctx->getConstantInt32(SpillAreaSizeBytes)); | |
| 630 } else { | |
| 631 _sub(getPhysicalRegister(getStackReg(), IceType_i64), | |
| 632 Ctx->getConstantInt32(SpillAreaSizeBytes)); | |
| 633 } | |
| 634 // If the fixed allocas are aligned more than the stack frame, align the | |
| 635 // stack pointer accordingly. | |
| 636 if (PrologEmitsFixedAllocas && | |
| 637 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { | |
| 638 assert(IsEbpBasedFrame); | |
| 639 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64), | |
| 640 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 // Account for alloca instructions with known frame offsets. | |
| 645 if (!PrologEmitsFixedAllocas) | |
| 646 SpillAreaSizeBytes += FixedAllocaSizeBytes; | |
| 647 | |
| 648 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | |
| 649 | |
| 650 // Fill in stack offsets for stack args, and copy args into registers for | |
| 651 // those that were register-allocated. Args are pushed right to left, so | |
| 652 // Arg[0] is closest to the stack/frame pointer. | |
| 653 Variable *FramePtr = | |
| 654 getPhysicalRegister(getFrameOrStackReg(), Traits::WordType); | |
| 655 size_t BasicFrameOffset = | |
| 656 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; | |
| 657 if (!IsEbpBasedFrame) | |
| 658 BasicFrameOffset += SpillAreaSizeBytes; | |
| 659 | |
| 660 const VarList &Args = Func->getArgs(); | |
| 661 size_t InArgsSizeBytes = 0; | |
| 662 unsigned NumXmmArgs = 0; | |
| 663 unsigned NumGPRArgs = 0; | |
| 664 for (Variable *Arg : Args) { | |
| 665 // Skip arguments passed in registers. | |
| 666 if (isVectorType(Arg->getType()) || isScalarFloatingType(Arg->getType())) { | |
| 667 if (NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | |
| 668 ++NumXmmArgs; | |
| 669 continue; | |
| 670 } | |
| 671 } else { | |
| 672 assert(isScalarIntegerType(Arg->getType())); | |
| 673 if (NumGPRArgs < Traits::X86_MAX_GPR_ARGS) { | |
| 674 ++NumGPRArgs; | |
| 675 continue; | |
| 676 } | |
| 677 } | |
| 678 // For esp-based frames, the esp value may not stabilize to its home value | |
| 679 // until after all the fixed-size alloca instructions have executed. In | |
| 680 // this case, a stack adjustment is needed when accessing in-args in order | |
| 681 // to copy them into registers. | |
| 682 size_t StackAdjBytes = 0; | |
| 683 if (!IsEbpBasedFrame && !PrologEmitsFixedAllocas) | |
| 684 StackAdjBytes -= FixedAllocaSizeBytes; | |
| 685 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, StackAdjBytes, | |
| 686 InArgsSizeBytes); | |
| 687 } | |
| 688 | |
| 689 // Fill in stack offsets for locals. | |
| 690 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | |
| 691 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | |
| 692 IsEbpBasedFrame); | |
| 693 // Assign stack offsets to variables that have been linked to spilled | |
| 694 // variables. | |
| 695 for (Variable *Var : VariablesLinkedToSpillSlots) { | |
| 696 Variable *Linked = | |
| 697 (llvm::cast<typename Traits::SpillVariable>(Var))->getLinkedTo(); | |
| 698 Var->setStackOffset(Linked->getStackOffset()); | |
| 699 } | |
| 700 this->HasComputedFrame = true; | |
| 701 | |
| 702 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | |
| 703 OstreamLocker L(Func->getContext()); | |
| 704 Ostream &Str = Func->getContext()->getStrDump(); | |
| 705 | |
| 706 Str << "Stack layout:\n"; | |
| 707 uint32_t EspAdjustmentPaddingSize = | |
| 708 SpillAreaSizeBytes - LocalsSpillAreaSize - | |
| 709 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes - | |
| 710 maxOutArgsSizeBytes(); | |
| 711 Str << " in-args = " << InArgsSizeBytes << " bytes\n" | |
| 712 << " return address = " << Traits::X86_RET_IP_SIZE_BYTES << " bytes\n" | |
| 713 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" | |
| 714 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" | |
| 715 << " globals spill area = " << GlobalsSize << " bytes\n" | |
| 716 << " globals-locals spill areas intermediate padding = " | |
| 717 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" | |
| 718 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" | |
| 719 << " esp alignment padding = " << EspAdjustmentPaddingSize | |
| 720 << " bytes\n"; | |
| 721 | |
| 722 Str << "Stack details:\n" | |
| 723 << " esp adjustment = " << SpillAreaSizeBytes << " bytes\n" | |
| 724 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" | |
| 725 << " outgoing args size = " << maxOutArgsSizeBytes() << " bytes\n" | |
| 726 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes | |
| 727 << " bytes\n" | |
| 728 << " is ebp based = " << IsEbpBasedFrame << "\n"; | |
| 729 } | |
| 730 } | |
| 731 | |
| 732 void TargetX8664::addEpilog(CfgNode *Node) { | |
| 733 InstList &Insts = Node->getInsts(); | |
| 734 InstList::reverse_iterator RI, E; | |
| 735 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { | |
| 736 if (llvm::isa<typename Traits::Insts::Ret>(*RI)) | |
| 737 break; | |
| 738 } | |
| 739 if (RI == E) | |
| 740 return; | |
| 741 | |
| 742 // Convert the reverse_iterator position into its corresponding (forward) | |
| 743 // iterator position. | |
| 744 InstList::iterator InsertPoint = RI.base(); | |
| 745 --InsertPoint; | |
| 746 Context.init(Node); | |
| 747 Context.setInsertPoint(InsertPoint); | |
| 748 | |
| 749 Variable *rsp = | |
| 750 getPhysicalRegister(Traits::RegisterSet::Reg_rsp, IceType_i64); | |
| 751 | |
| 752 if (!IsEbpBasedFrame) { | |
| 753 // add rsp, SpillAreaSizeBytes | |
| 754 if (SpillAreaSizeBytes != 0) { | |
| 755 _add_sp(Ctx->getConstantInt32(SpillAreaSizeBytes)); | |
| 756 } | |
| 757 } else { | |
| 758 Variable *rbp = | |
| 759 getPhysicalRegister(Traits::RegisterSet::Reg_rbp, IceType_i64); | |
| 760 Variable *ebp = | |
| 761 getPhysicalRegister(Traits::RegisterSet::Reg_ebp, IceType_i32); | |
| 762 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | |
| 763 // use of rsp before the assignment of rsp=rbp keeps previous rsp | |
| 764 // adjustments from being dead-code eliminated. | |
| 765 Context.insert<InstFakeUse>(rsp); | |
| 766 if (!NeedSandboxing) { | |
| 767 _mov(rsp, rbp); | |
| 768 _pop(rbp); | |
| 769 } else { | |
| 770 _mov_sp(ebp); | |
| 771 | |
| 772 Variable *r15 = | |
| 773 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | |
| 774 Variable *rcx = | |
| 775 getPhysicalRegister(Traits::RegisterSet::Reg_rcx, IceType_i64); | |
| 776 Variable *ecx = | |
| 777 getPhysicalRegister(Traits::RegisterSet::Reg_ecx, IceType_i32); | |
| 778 | |
| 779 _pop(rcx); | |
| 780 Context.insert<InstFakeDef>(ecx, rcx); | |
| 781 AutoBundle _(this); | |
| 782 _mov(ebp, ecx); | |
| 783 | |
| 784 _redefined(Context.insert<InstFakeDef>(rbp, ebp)); | |
| 785 _add(rbp, r15); | |
| 786 } | |
| 787 } | |
| 788 | |
| 789 // Add pop instructions for preserved registers. | |
| 790 llvm::SmallBitVector CalleeSaves = | |
| 791 getRegisterSet(RegSet_CalleeSave, RegSet_None); | |
| 792 llvm::SmallBitVector Popped(CalleeSaves.size()); | |
| 793 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) { | |
| 794 if (i == Traits::RegisterSet::Reg_rbp && IsEbpBasedFrame) | |
| 795 continue; | |
| 796 const SizeT Canonical = Traits::getBaseReg(i); | |
| 797 if (CalleeSaves[i] && RegsUsed[i]) | |
| 798 Popped[Canonical] = true; | |
| 799 } | |
| 800 for (int32_t i = Popped.size() - 1; i >= 0; --i) { | |
| 801 if (!Popped[i]) | |
| 802 continue; | |
| 803 assert(i == Traits::getBaseReg(i)); | |
| 804 _pop(getPhysicalRegister(i, IceType_i64)); | |
| 805 } | |
| 806 | |
| 807 if (!NeedSandboxing) { | |
| 808 return; | |
| 809 } | |
| 810 | |
| 811 Variable *T_rcx = makeReg(IceType_i64, Traits::RegisterSet::Reg_rcx); | 530 Variable *T_rcx = makeReg(IceType_i64, Traits::RegisterSet::Reg_rcx); |
| 812 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); | 531 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
| 813 _pop(T_rcx); | 532 _pop(T_rcx); |
| 814 _mov(T_ecx, T_rcx); | 533 _mov(T_ecx, T_rcx); |
| 815 | |
| 816 // lowerIndirectJump(T_ecx); | 534 // lowerIndirectJump(T_ecx); |
| 817 Variable *r15 = | 535 Variable *r15 = |
| 818 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | 536 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); |
| 819 | 537 |
| 820 /* AutoBundle scoping */ { | 538 /* AutoBundle scoping */ { |
| 821 AutoBundle _(this); | 539 AutoBundle _(this); |
| 822 const SizeT BundleSize = | 540 const SizeT BundleSize = |
| 823 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | 541 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
| 824 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); | 542 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); |
| 825 Context.insert<InstFakeDef>(T_rcx, T_ecx); | 543 Context.insert<InstFakeDef>(T_rcx, T_ecx); |
| 826 _add(T_rcx, r15); | 544 _add(T_rcx, r15); |
| 827 | 545 |
| 828 _jmp(T_rcx); | 546 _jmp(T_rcx); |
| 829 } | 547 } |
| 830 | |
| 831 if (RI->getSrcSize()) { | |
| 832 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | |
| 833 Context.insert<InstFakeUse>(RetValue); | |
| 834 } | |
| 835 RI->setDeleted(); | |
| 836 } | 548 } |
| 837 | 549 |
| 838 void TargetX8664::emitJumpTable(const Cfg *Func, | 550 void TargetX8664::emitJumpTable(const Cfg *Func, |
| 839 const InstJumpTable *JumpTable) const { | 551 const InstJumpTable *JumpTable) const { |
| 840 if (!BuildDefs::dump()) | 552 if (!BuildDefs::dump()) |
| 841 return; | 553 return; |
| 842 Ostream &Str = Ctx->getStrEmit(); | 554 Ostream &Str = Ctx->getStrEmit(); |
| 843 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 555 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 844 Str << "\t.section\t.rodata." << MangledName | 556 Str << "\t.section\t.rodata." << MangledName |
| 845 << "$jumptable,\"a\",@progbits\n"; | 557 << "$jumptable,\"a\",@progbits\n"; |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1146 #define X(tag, sizeLog2, align, elts, elty, str) \ | 858 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 1147 static_assert(_table1_##tag == _table2_##tag, \ | 859 static_assert(_table1_##tag == _table2_##tag, \ |
| 1148 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 860 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 1149 ICETYPE_TABLE | 861 ICETYPE_TABLE |
| 1150 #undef X | 862 #undef X |
| 1151 } // end of namespace dummy3 | 863 } // end of namespace dummy3 |
| 1152 } // end of anonymous namespace | 864 } // end of anonymous namespace |
| 1153 | 865 |
| 1154 } // end of namespace X8664 | 866 } // end of namespace X8664 |
| 1155 } // end of namespace Ice | 867 } // end of namespace Ice |
| OLD | NEW |