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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 XmmArgs.push_back(Arg); | 186 XmmArgs.push_back(Arg); |
187 } else if (isScalarIntegerType(Ty) && | 187 } else if (isScalarIntegerType(Ty) && |
188 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) { | 188 GprArgs.size() < Traits::X86_MAX_GPR_ARGS) { |
189 GprArgs.push_back(Arg); | 189 GprArgs.push_back(Arg); |
190 } else { | 190 } else { |
191 StackArgs.push_back(Arg); | 191 StackArgs.push_back(Arg); |
192 if (isVectorType(Arg->getType())) { | 192 if (isVectorType(Arg->getType())) { |
193 ParameterAreaSizeBytes = | 193 ParameterAreaSizeBytes = |
194 Traits::applyStackAlignment(ParameterAreaSizeBytes); | 194 Traits::applyStackAlignment(ParameterAreaSizeBytes); |
195 } | 195 } |
196 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 196 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); |
197 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); | 197 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); |
198 StackArgLocations.push_back( | 198 StackArgLocations.push_back( |
199 Traits::X86OperandMem::create(Func, Ty, esp, Loc)); | 199 Traits::X86OperandMem::create(Func, Ty, esp, Loc)); |
200 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); | 200 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); |
201 } | 201 } |
202 } | 202 } |
203 | 203 |
204 // Adjust the parameter area so that the stack is aligned. It is assumed that | 204 // Adjust the parameter area so that the stack is aligned. It is assumed that |
205 // the stack is already aligned at the start of the calling sequence. | 205 // the stack is already aligned at the start of the calling sequence. |
206 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes); | 206 ParameterAreaSizeBytes = Traits::applyStackAlignment(ParameterAreaSizeBytes); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); | 269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); |
270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
271 if (NeedSandboxing) { | 271 if (NeedSandboxing) { |
272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
273 } | 273 } |
274 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); | 274 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); |
275 if (NeedSandboxing) { | 275 if (NeedSandboxing) { |
276 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 276 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
277 } | 277 } |
278 | 278 |
279 // Add the appropriate offset to esp. The call instruction takes care of | |
280 // resetting the stack offset during emission. | |
281 if (ParameterAreaSizeBytes) { | |
282 Variable *Esp = | |
283 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | |
284 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); | |
285 } | |
286 | |
287 // Insert a register-kill pseudo instruction. | 279 // Insert a register-kill pseudo instruction. |
288 Context.insert<InstFakeKill>(NewCall); | 280 Context.insert<InstFakeKill>(NewCall); |
289 | 281 |
290 // Generate a FakeUse to keep the call live if necessary. | 282 // Generate a FakeUse to keep the call live if necessary. |
291 if (Instr->hasSideEffects() && ReturnReg) { | 283 if (Instr->hasSideEffects() && ReturnReg) { |
292 Context.insert<InstFakeUse>(ReturnReg); | 284 Context.insert<InstFakeUse>(ReturnReg); |
293 } | 285 } |
294 | 286 |
295 if (!Dest) | 287 if (!Dest) |
296 return; | 288 return; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 // Compute the list of spilled variables and bounds for GlobalsSize, etc. | 450 // Compute the list of spilled variables and bounds for GlobalsSize, etc. |
459 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | 451 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, |
460 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | 452 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, |
461 &LocalsSlotsAlignmentBytes, TargetVarHook); | 453 &LocalsSlotsAlignmentBytes, TargetVarHook); |
462 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; | 454 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; |
463 SpillAreaSizeBytes += GlobalsSize; | 455 SpillAreaSizeBytes += GlobalsSize; |
464 | 456 |
465 // Add push instructions for preserved registers. | 457 // Add push instructions for preserved registers. |
466 uint32_t NumCallee = 0; | 458 uint32_t NumCallee = 0; |
467 size_t PreservedRegsSizeBytes = 0; | 459 size_t PreservedRegsSizeBytes = 0; |
| 460 llvm::SmallBitVector Pushed(CalleeSaves.size()); |
468 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 461 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
469 if (CalleeSaves[i] && RegsUsed[i]) { | 462 const int32_t Canonical = Traits::getBaseReg(i); |
470 ++NumCallee; | 463 assert(Canonical == Traits::getBaseReg(Canonical)); |
471 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | 464 if (CalleeSaves[i] && RegsUsed[i]) |
472 _push(getPhysicalRegister(i)); | 465 Pushed[Canonical] = true; |
473 } | 466 } |
| 467 for (SizeT i = 0; i < Pushed.size(); ++i) { |
| 468 if (!Pushed[i]) |
| 469 continue; |
| 470 assert(static_cast<int32_t>(i) == Traits::getBaseReg(i)); |
| 471 ++NumCallee; |
| 472 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 473 _push(getPhysicalRegister(i, IceType_i64)); |
474 } | 474 } |
475 Ctx->statsUpdateRegistersSaved(NumCallee); | 475 Ctx->statsUpdateRegistersSaved(NumCallee); |
476 | 476 |
477 // Generate "push ebp; mov ebp, esp" | 477 // Generate "push ebp; mov ebp, esp" |
478 if (IsEbpBasedFrame) { | 478 if (IsEbpBasedFrame) { |
479 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | 479 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
480 .count() == 0); | 480 .count() == 0); |
481 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | 481 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
482 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 482 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_rbp); |
483 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 483 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); |
484 _push(ebp); | 484 _push(ebp); |
485 _mov(ebp, esp); | 485 _mov(ebp, esp); |
486 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | 486 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). |
487 Context.insert<InstFakeUse>(ebp); | 487 Context.insert<InstFakeUse>(ebp); |
488 } | 488 } |
489 | 489 |
490 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 490 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
491 // after the preserved registers and before the spill areas. | 491 // after the preserved registers and before the spill areas. |
492 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 492 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
493 // locals area if they are separate. | 493 // locals area if they are separate. |
(...skipping 20 matching lines...) Expand all Loading... |
514 } else { | 514 } else { |
515 SpillAreaSizeBytes += maxOutArgsSizeBytes(); | 515 SpillAreaSizeBytes += maxOutArgsSizeBytes(); |
516 } | 516 } |
517 | 517 |
518 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the | 518 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the |
519 // fixed allocations in the prolog. | 519 // fixed allocations in the prolog. |
520 if (PrologEmitsFixedAllocas) | 520 if (PrologEmitsFixedAllocas) |
521 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 521 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
522 // Generate "sub esp, SpillAreaSizeBytes" | 522 // Generate "sub esp, SpillAreaSizeBytes" |
523 if (SpillAreaSizeBytes) { | 523 if (SpillAreaSizeBytes) { |
524 _sub(getPhysicalRegister(Traits::RegisterSet::Reg_esp), | 524 _sub(getPhysicalRegister(getStackReg(), IceType_i64), |
525 Ctx->getConstantInt32(SpillAreaSizeBytes)); | 525 Ctx->getConstantInt32(SpillAreaSizeBytes)); |
526 // If the fixed allocas are aligned more than the stack frame, align the | 526 // If the fixed allocas are aligned more than the stack frame, align the |
527 // stack pointer accordingly. | 527 // stack pointer accordingly. |
528 if (PrologEmitsFixedAllocas && | 528 if (PrologEmitsFixedAllocas && |
529 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { | 529 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { |
530 assert(IsEbpBasedFrame); | 530 assert(IsEbpBasedFrame); |
531 _and(getPhysicalRegister(Traits::RegisterSet::Reg_esp), | 531 _and(getPhysicalRegister(Traits::RegisterSet::Reg_rsp), |
532 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); | 532 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); |
533 } | 533 } |
534 } | 534 } |
535 | 535 |
536 // Account for alloca instructions with known frame offsets. | 536 // Account for alloca instructions with known frame offsets. |
537 if (!PrologEmitsFixedAllocas) | 537 if (!PrologEmitsFixedAllocas) |
538 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 538 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
539 | 539 |
540 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 540 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
541 | 541 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 if (RI == E) | 630 if (RI == E) |
631 return; | 631 return; |
632 | 632 |
633 // Convert the reverse_iterator position into its corresponding (forward) | 633 // Convert the reverse_iterator position into its corresponding (forward) |
634 // iterator position. | 634 // iterator position. |
635 InstList::iterator InsertPoint = RI.base(); | 635 InstList::iterator InsertPoint = RI.base(); |
636 --InsertPoint; | 636 --InsertPoint; |
637 Context.init(Node); | 637 Context.init(Node); |
638 Context.setInsertPoint(InsertPoint); | 638 Context.setInsertPoint(InsertPoint); |
639 | 639 |
640 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 640 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_rsp); |
641 if (IsEbpBasedFrame) { | 641 if (IsEbpBasedFrame) { |
642 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 642 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_rbp); |
643 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 643 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
644 // use of esp before the assignment of esp=ebp keeps previous esp | 644 // use of esp before the assignment of esp=ebp keeps previous esp |
645 // adjustments from being dead-code eliminated. | 645 // adjustments from being dead-code eliminated. |
646 Context.insert<InstFakeUse>(esp); | 646 Context.insert<InstFakeUse>(esp); |
647 _mov(esp, ebp); | 647 _mov(esp, ebp); |
648 _pop(ebp); | 648 _pop(ebp); |
649 } else { | 649 } else { |
650 // add esp, SpillAreaSizeBytes | 650 // add esp, SpillAreaSizeBytes |
651 if (SpillAreaSizeBytes) | 651 if (SpillAreaSizeBytes) |
652 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); | 652 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); |
653 } | 653 } |
654 | 654 |
655 // Add pop instructions for preserved registers. | 655 // Add pop instructions for preserved registers. |
656 llvm::SmallBitVector CalleeSaves = | 656 llvm::SmallBitVector CalleeSaves = |
657 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 657 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
658 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 658 llvm::SmallBitVector Popped(CalleeSaves.size()); |
659 SizeT j = CalleeSaves.size() - i - 1; | 659 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) { |
660 if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame) | 660 if (i == Traits::RegisterSet::Reg_rbp && IsEbpBasedFrame) |
661 continue; | 661 continue; |
662 if (CalleeSaves[j] && RegsUsed[j]) { | 662 const SizeT Canonical = Traits::getBaseReg(i); |
663 _pop(getPhysicalRegister(j)); | 663 if (CalleeSaves[i] && RegsUsed[i]) |
664 } | 664 Popped[Canonical] = true; |
| 665 } |
| 666 for (int32_t i = Popped.size() - 1; i >= 0; --i) { |
| 667 if (!Popped[i]) |
| 668 continue; |
| 669 assert(i == Traits::getBaseReg(i)); |
| 670 _pop(getPhysicalRegister(i, IceType_i64)); |
665 } | 671 } |
666 | 672 |
667 if (Ctx->getFlags().getUseSandboxing()) { | 673 if (Ctx->getFlags().getUseSandboxing()) { |
668 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 674 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
669 } | 675 } |
670 } | 676 } |
671 | 677 |
672 void TargetX8664::emitJumpTable(const Cfg *Func, | 678 void TargetX8664::emitJumpTable(const Cfg *Func, |
673 const InstJumpTable *JumpTable) const { | 679 const InstJumpTable *JumpTable) const { |
674 if (!BuildDefs::dump()) | 680 if (!BuildDefs::dump()) |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 // case the high-level table has extra entries. | 983 // case the high-level table has extra entries. |
978 #define X(tag, sizeLog2, align, elts, elty, str) \ | 984 #define X(tag, sizeLog2, align, elts, elty, str) \ |
979 static_assert(_table1_##tag == _table2_##tag, \ | 985 static_assert(_table1_##tag == _table2_##tag, \ |
980 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 986 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
981 ICETYPE_TABLE | 987 ICETYPE_TABLE |
982 #undef X | 988 #undef X |
983 } // end of namespace dummy3 | 989 } // end of namespace dummy3 |
984 } // end of anonymous namespace | 990 } // end of anonymous namespace |
985 | 991 |
986 } // end of namespace Ice | 992 } // end of namespace Ice |
OLD | NEW |