Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/Target/X86/X86FrameLowering.cpp
Show First 20 Lines • Show All 952 Lines • ▼ Show 20 Lines | void X86FrameLowering::emitPrologue(MachineFunction &MF, | ||||
bool NeedsDwarfCFI = | bool NeedsDwarfCFI = | ||||
!IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); | !IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); | ||||
unsigned FramePtr = TRI->getFrameRegister(MF); | unsigned FramePtr = TRI->getFrameRegister(MF); | ||||
const unsigned MachineFramePtr = | const unsigned MachineFramePtr = | ||||
STI.isTarget64BitILP32() | STI.isTarget64BitILP32() | ||||
? getX86SubSuperRegister(FramePtr, 64) : FramePtr; | ? getX86SubSuperRegister(FramePtr, 64) : FramePtr; | ||||
unsigned BasePtr = TRI->getBaseRegister(); | unsigned BasePtr = TRI->getBaseRegister(); | ||||
bool HasWinCFI = false; | bool HasWinCFI = false; | ||||
bool InsertedCFI = false; | |||||
// Debug location must be unknown since the first debug location is used | // Debug location must be unknown since the first debug location is used | ||||
// to determine the end of the prologue. | // to determine the end of the prologue. | ||||
DebugLoc DL; | DebugLoc DL; | ||||
// Add RETADDR move area to callee saved frame size. | // Add RETADDR move area to callee saved frame size. | ||||
int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); | int TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); | ||||
if (TailCallReturnAddrDelta && IsWin64Prologue) | if (TailCallReturnAddrDelta && IsWin64Prologue) | ||||
report_fatal_error("Can't handle guaranteed tail call under win64 yet"); | report_fatal_error("Can't handle guaranteed tail call under win64 yet"); | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64r : X86::PUSH32r)) | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
if (NeedsDwarfCFI) { | if (NeedsDwarfCFI) { | ||||
// Mark the place where EBP/RBP was saved. | // Mark the place where EBP/RBP was saved. | ||||
// Define the current CFA rule to use the provided offset. | // Define the current CFA rule to use the provided offset. | ||||
assert(StackSize); | assert(StackSize); | ||||
BuildCFI(MBB, MBBI, DL, | BuildCFI(MBB, MBBI, DL, | ||||
MCCFIInstruction::createDefCfaOffset(nullptr, 2 * stackGrowth)); | MCCFIInstruction::createDefCfaOffset(nullptr, 2 * stackGrowth)); | ||||
MBB.setDefOffset(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
// Change the rule for the FramePtr to be an "offset" rule. | // Change the rule for the FramePtr to be an "offset" rule. | ||||
unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); | unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); | ||||
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createOffset( | BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createOffset( | ||||
nullptr, DwarfFramePtr, 2 * stackGrowth)); | nullptr, DwarfFramePtr, 2 * stackGrowth)); | ||||
} | } | ||||
if (NeedsWinCFI) { | if (NeedsWinCFI) { | ||||
Show All 12 Lines | if (!IsWin64Prologue && !IsFunclet) { | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
if (NeedsDwarfCFI) { | if (NeedsDwarfCFI) { | ||||
// Mark effective beginning of when frame pointer becomes valid. | // Mark effective beginning of when frame pointer becomes valid. | ||||
// Define the current CFA to use the EBP/RBP register. | // Define the current CFA to use the EBP/RBP register. | ||||
unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); | unsigned DwarfFramePtr = TRI->getDwarfRegNum(MachineFramePtr, true); | ||||
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaRegister( | BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaRegister( | ||||
nullptr, DwarfFramePtr)); | nullptr, DwarfFramePtr)); | ||||
MBB.setDefRegister(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
assert(!IsFunclet && "funclets without FPs not yet implemented"); | assert(!IsFunclet && "funclets without FPs not yet implemented"); | ||||
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize(); | NumBytes = StackSize - X86FI->getCalleeSavedFrameSize(); | ||||
} | } | ||||
// For EH funclets, only allocate enough space for outgoing calls. Save the | // For EH funclets, only allocate enough space for outgoing calls. Save the | ||||
Show All 15 Lines | while (MBBI != MBB.end() && | ||||
++MBBI; | ++MBBI; | ||||
if (!HasFP && NeedsDwarfCFI) { | if (!HasFP && NeedsDwarfCFI) { | ||||
// Mark callee-saved push instruction. | // Mark callee-saved push instruction. | ||||
// Define the current CFA rule to use the provided offset. | // Define the current CFA rule to use the provided offset. | ||||
assert(StackSize); | assert(StackSize); | ||||
BuildCFI(MBB, MBBI, DL, | BuildCFI(MBB, MBBI, DL, | ||||
MCCFIInstruction::createDefCfaOffset(nullptr, StackOffset)); | MCCFIInstruction::createDefCfaOffset(nullptr, StackOffset)); | ||||
MBB.setDefOffset(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
StackOffset += stackGrowth; | StackOffset += stackGrowth; | ||||
} | } | ||||
if (NeedsWinCFI) { | if (NeedsWinCFI) { | ||||
HasWinCFI = true; | HasWinCFI = true; | ||||
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag( | BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag( | ||||
MachineInstr::FrameSetup); | MachineInstr::FrameSetup); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | void X86FrameLowering::emitPrologue(MachineFunction &MF, | ||||
if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) { | if (((!HasFP && NumBytes) || PushedRegs) && NeedsDwarfCFI) { | ||||
// Mark end of stack pointer adjustment. | // Mark end of stack pointer adjustment. | ||||
if (!HasFP && NumBytes) { | if (!HasFP && NumBytes) { | ||||
// Define the current CFA rule to use the provided offset. | // Define the current CFA rule to use the provided offset. | ||||
assert(StackSize); | assert(StackSize); | ||||
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaOffset( | BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaOffset( | ||||
nullptr, -StackSize + stackGrowth)); | nullptr, -StackSize + stackGrowth)); | ||||
MBB.setDefOffset(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
} | } | ||||
// Emit DWARF info specifying the offsets of the callee-saved registers. | // Emit DWARF info specifying the offsets of the callee-saved registers. | ||||
if (PushedRegs) | if (PushedRegs) | ||||
emitCalleeSavedFrameMoves(MBB, MBBI, DL); | emitCalleeSavedFrameMoves(MBB, MBBI, DL); | ||||
} | } | ||||
// X86 Interrupt handling function cannot assume anything about the direction | // X86 Interrupt handling function cannot assume anything about the direction | ||||
// flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction | // flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction | ||||
// in each prologue of interrupt handler function. | // in each prologue of interrupt handler function. | ||||
// | // | ||||
// FIXME: Create "cld" instruction only in these cases: | // FIXME: Create "cld" instruction only in these cases: | ||||
// 1. The interrupt handling function uses any of the "rep" instructions. | // 1. The interrupt handling function uses any of the "rep" instructions. | ||||
// 2. Interrupt handling function calls another function. | // 2. Interrupt handling function calls another function. | ||||
// | // | ||||
if (Fn->getCallingConv() == CallingConv::X86_INTR) | if (Fn->getCallingConv() == CallingConv::X86_INTR) | ||||
BuildMI(MBB, MBBI, DL, TII.get(X86::CLD)) | BuildMI(MBB, MBBI, DL, TII.get(X86::CLD)) | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
// At this point we know if the function has WinCFI or not. | // At this point we know if the function has WinCFI or not. | ||||
MF.setHasWinCFI(HasWinCFI); | MF.setHasWinCFI(HasWinCFI); | ||||
if (InsertedCFI) | |||||
MBB.updateCFIInfoSucc(); | |||||
} | } | ||||
bool X86FrameLowering::canUseLEAForSPInEpilogue( | bool X86FrameLowering::canUseLEAForSPInEpilogue( | ||||
const MachineFunction &MF) const { | const MachineFunction &MF) const { | ||||
// We can't use LEA instructions for adjusting the stack pointer if we don't | // We can't use LEA instructions for adjusting the stack pointer if we don't | ||||
// have a frame pointer in the Win64 ABI. Only ADD instructions may be used | // have a frame pointer in the Win64 ABI. Only ADD instructions may be used | ||||
// to deallocate the stack. | // to deallocate the stack. | ||||
// This means that we can use LEA for SP in two situations: | // This means that we can use LEA for SP in two situations: | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | void X86FrameLowering::emitEpilogue(MachineFunction &MF, | ||||
MachineBasicBlock *TargetMBB = nullptr; | MachineBasicBlock *TargetMBB = nullptr; | ||||
// Get the number of bytes to allocate from the FrameInfo. | // Get the number of bytes to allocate from the FrameInfo. | ||||
uint64_t StackSize = MFI.getStackSize(); | uint64_t StackSize = MFI.getStackSize(); | ||||
uint64_t MaxAlign = calculateMaxStackAlign(MF); | uint64_t MaxAlign = calculateMaxStackAlign(MF); | ||||
unsigned CSSize = X86FI->getCalleeSavedFrameSize(); | unsigned CSSize = X86FI->getCalleeSavedFrameSize(); | ||||
uint64_t NumBytes = 0; | uint64_t NumBytes = 0; | ||||
bool NeedsDwarfCFI = (MF.getMMI().hasDebugInfo() || | |||||
MF.getFunction()->needsUnwindTableEntry()) && | |||||
(!MF.getSubtarget<X86Subtarget>().isTargetDarwin() && | |||||
!MF.getSubtarget<X86Subtarget>().isOSWindows()); | |||||
bool InsertedCFI = false; | |||||
if (RetOpcode && *RetOpcode == X86::CATCHRET) { | if (RetOpcode && *RetOpcode == X86::CATCHRET) { | ||||
// SEH shouldn't use catchret. | // SEH shouldn't use catchret. | ||||
assert(!isAsynchronousEHPersonality( | assert(!isAsynchronousEHPersonality( | ||||
classifyEHPersonality(MF.getFunction()->getPersonalityFn())) && | classifyEHPersonality(MF.getFunction()->getPersonalityFn())) && | ||||
"SEH should not use CATCHRET"); | "SEH should not use CATCHRET"); | ||||
NumBytes = getWinEHFuncletFrameSize(MF); | NumBytes = getWinEHFuncletFrameSize(MF); | ||||
assert(hasFP(MF) && "EH funclets without FP not yet implemented"); | assert(hasFP(MF) && "EH funclets without FP not yet implemented"); | ||||
Show All 18 Lines | if (RetOpcode && *RetOpcode == X86::CATCHRET) { | ||||
// realigned. | // realigned. | ||||
if (TRI->needsStackRealignment(MF) && !IsWin64Prologue) | if (TRI->needsStackRealignment(MF) && !IsWin64Prologue) | ||||
NumBytes = alignTo(FrameSize, MaxAlign); | NumBytes = alignTo(FrameSize, MaxAlign); | ||||
// Pop EBP. | // Pop EBP. | ||||
BuildMI(MBB, MBBI, DL, | BuildMI(MBB, MBBI, DL, | ||||
TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) | TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) | ||||
.setMIFlag(MachineInstr::FrameDestroy); | .setMIFlag(MachineInstr::FrameDestroy); | ||||
if (NeedsDwarfCFI) { | |||||
unsigned DwarfStackPtr = | |||||
TRI->getDwarfRegNum(Is64Bit ? X86::RSP : X86::ESP, true); | |||||
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfa( | |||||
nullptr, DwarfStackPtr, -SlotSize)); | |||||
--MBBI; | |||||
MBB.setDefOffset(true); | |||||
MBB.setDefRegister(true); | |||||
MBB.updateCFIInfo(MBBI); | |||||
InsertedCFI = true; | |||||
} | |||||
} else { | } else { | ||||
NumBytes = StackSize - CSSize; | NumBytes = StackSize - CSSize; | ||||
} | } | ||||
uint64_t SEHStackAllocAmt = NumBytes; | uint64_t SEHStackAllocAmt = NumBytes; | ||||
MachineBasicBlock::iterator FirstCSPop = MBBI; | MachineBasicBlock::iterator FirstCSPop = MBBI; | ||||
// Skip the callee-saved pop instructions. | // Skip the callee-saved pop instructions. | ||||
while (MBBI != MBB.begin()) { | while (MBBI != MBB.begin()) { | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | if (LEAAmount != 0) { | ||||
unsigned Opc = (Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr); | unsigned Opc = (Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr); | ||||
BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) | BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) | ||||
.addReg(FramePtr); | .addReg(FramePtr); | ||||
--MBBI; | --MBBI; | ||||
} | } | ||||
} else if (NumBytes) { | } else if (NumBytes) { | ||||
// Adjust stack pointer back: ESP += numbytes. | // Adjust stack pointer back: ESP += numbytes. | ||||
emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true); | emitSPUpdate(MBB, MBBI, NumBytes, /*InEpilogue=*/true); | ||||
if (!hasFP(MF) && NeedsDwarfCFI) { | |||||
// Define the current CFA rule to use the provided offset. | |||||
BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaOffset( | |||||
nullptr, -CSSize - SlotSize)); | |||||
MBB.setDefOffset(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
} | |||||
--MBBI; | --MBBI; | ||||
} | } | ||||
// Windows unwinder will not invoke function's exception handler if IP is | // Windows unwinder will not invoke function's exception handler if IP is | ||||
// either in prologue or in epilogue. This behavior causes a problem when a | // either in prologue or in epilogue. This behavior causes a problem when a | ||||
// call immediately precedes an epilogue, because the return address points | // call immediately precedes an epilogue, because the return address points | ||||
// into the epilogue. To cope with that, we insert an epilogue marker here, | // into the epilogue. To cope with that, we insert an epilogue marker here, | ||||
// then replace it with a 'nop' if it ends up immediately after a CALL in the | // then replace it with a 'nop' if it ends up immediately after a CALL in the | ||||
// final emitted code. | // final emitted code. | ||||
if (NeedsWinCFI && MF.hasWinCFI()) | if (NeedsWinCFI && MF.hasWinCFI()) | ||||
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue)); | BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue)); | ||||
if (!hasFP(MF) && NeedsDwarfCFI) { | |||||
MBBI = FirstCSPop; | |||||
int64_t Offset = -CSSize - SlotSize; | |||||
// Mark callee-saved pop instruction. | |||||
// Define the current CFA rule to use the provided offset. | |||||
while (MBBI != MBB.end()) { | |||||
MachineBasicBlock::iterator PI = MBBI; | |||||
unsigned Opc = PI->getOpcode(); | |||||
++MBBI; | |||||
if (Opc == X86::POP32r || Opc == X86::POP64r) { | |||||
Offset += SlotSize; | |||||
BuildCFI(MBB, MBBI, DL, | |||||
MCCFIInstruction::createDefCfaOffset(nullptr, Offset)); | |||||
MBB.setDefOffset(true); | |||||
MBB.updateCFIInfo(std::prev(MBBI)); | |||||
InsertedCFI = true; | |||||
} | |||||
} | |||||
} | |||||
if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) { | if (!RetOpcode || !isTailCallOpcode(*RetOpcode)) { | ||||
// Add the return addr area delta back since we are not tail calling. | // Add the return addr area delta back since we are not tail calling. | ||||
int Offset = -1 * X86FI->getTCReturnAddrDelta(); | int Offset = -1 * X86FI->getTCReturnAddrDelta(); | ||||
assert(Offset >= 0 && "TCDelta should never be positive"); | assert(Offset >= 0 && "TCDelta should never be positive"); | ||||
if (Offset) { | if (Offset) { | ||||
MBBI = MBB.getFirstTerminator(); | MBBI = MBB.getFirstTerminator(); | ||||
// Check for possible merge with preceding ADD instruction. | // Check for possible merge with preceding ADD instruction. | ||||
Offset += mergeSPUpdates(MBB, MBBI, true); | Offset += mergeSPUpdates(MBB, MBBI, true); | ||||
emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); | emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); | ||||
} | } | ||||
} | } | ||||
if (InsertedCFI) | |||||
MBB.updateCFIInfoSucc(); | |||||
} | } | ||||
int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, | int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, | ||||
unsigned &FrameReg) const { | unsigned &FrameReg) const { | ||||
const MachineFrameInfo &MFI = MF.getFrameInfo(); | const MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
bool IsFixed = MFI.isFixedObjectIndex(FI); | bool IsFixed = MFI.isFixedObjectIndex(FI); | ||||
// We can't calculate offset from frame pointer if the stack is realigned, | // We can't calculate offset from frame pointer if the stack is realigned, | ||||
▲ Show 20 Lines • Show All 658 Lines • ▼ Show 20 Lines | void X86FrameLowering::adjustForSegmentedStacks( | ||||
else | else | ||||
BuildMI(allocMBB, DL, TII.get(X86::MORESTACK_RET)); | BuildMI(allocMBB, DL, TII.get(X86::MORESTACK_RET)); | ||||
allocMBB->addSuccessor(&PrologueMBB); | allocMBB->addSuccessor(&PrologueMBB); | ||||
checkMBB->addSuccessor(allocMBB); | checkMBB->addSuccessor(allocMBB); | ||||
checkMBB->addSuccessor(&PrologueMBB); | checkMBB->addSuccessor(&PrologueMBB); | ||||
int InitialOffset = TRI->getSlotSize(); | |||||
unsigned InitialRegister = TRI->getDwarfRegNum(StackPtr, true); | |||||
// Set CFI info for checkMBB. | |||||
checkMBB->setIncomingCFAOffset(InitialOffset); | |||||
checkMBB->setIncomingCFARegister(InitialRegister); | |||||
checkMBB->setOutgoingCFAOffset(InitialOffset); | |||||
checkMBB->setOutgoingCFARegister(InitialRegister); | |||||
// Set CFI info for allocMBB. | |||||
allocMBB->setIncomingCFAOffset(InitialOffset); | |||||
allocMBB->setIncomingCFARegister(InitialRegister); | |||||
allocMBB->setOutgoingCFAOffset(InitialOffset); | |||||
allocMBB->setOutgoingCFARegister(InitialRegister); | |||||
#ifdef EXPENSIVE_CHECKS | #ifdef EXPENSIVE_CHECKS | ||||
MF.verify(); | MF.verify(); | ||||
#endif | #endif | ||||
} | } | ||||
/// Lookup an ERTS parameter in the !hipe.literals named metadata node. | /// Lookup an ERTS parameter in the !hipe.literals named metadata node. | ||||
/// HiPE provides Erlang Runtime System-internal parameters, such as PCB offsets | /// HiPE provides Erlang Runtime System-internal parameters, such as PCB offsets | ||||
/// to fields it needs, through a named metadata node "hipe.literals" containing | /// to fields it needs, through a named metadata node "hipe.literals" containing | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | if (MaxStack > Guaranteed) { | ||||
addRegOffset(BuildMI(incStackMBB, DL, TII.get(CMPop)) | addRegOffset(BuildMI(incStackMBB, DL, TII.get(CMPop)) | ||||
.addReg(ScratchReg), PReg, false, SPLimitOffset); | .addReg(ScratchReg), PReg, false, SPLimitOffset); | ||||
BuildMI(incStackMBB, DL, TII.get(X86::JLE_1)).addMBB(incStackMBB); | BuildMI(incStackMBB, DL, TII.get(X86::JLE_1)).addMBB(incStackMBB); | ||||
stackCheckMBB->addSuccessor(&PrologueMBB, {99, 100}); | stackCheckMBB->addSuccessor(&PrologueMBB, {99, 100}); | ||||
stackCheckMBB->addSuccessor(incStackMBB, {1, 100}); | stackCheckMBB->addSuccessor(incStackMBB, {1, 100}); | ||||
incStackMBB->addSuccessor(&PrologueMBB, {99, 100}); | incStackMBB->addSuccessor(&PrologueMBB, {99, 100}); | ||||
incStackMBB->addSuccessor(incStackMBB, {1, 100}); | incStackMBB->addSuccessor(incStackMBB, {1, 100}); | ||||
int InitialOffset = TRI->getSlotSize(); | |||||
unsigned InitialRegister = TRI->getDwarfRegNum(StackPtr, true); | |||||
// Set CFI info to stackCheckMBB. | |||||
stackCheckMBB->setIncomingCFAOffset(InitialOffset); | |||||
stackCheckMBB->setIncomingCFARegister(InitialRegister); | |||||
stackCheckMBB->setOutgoingCFAOffset(InitialOffset); | |||||
stackCheckMBB->setOutgoingCFARegister(InitialRegister); | |||||
// Set CFI info to incStackMBB. | |||||
incStackMBB->setIncomingCFAOffset(InitialOffset); | |||||
incStackMBB->setIncomingCFARegister(InitialRegister); | |||||
incStackMBB->setOutgoingCFAOffset(InitialOffset); | |||||
incStackMBB->setOutgoingCFARegister(InitialRegister); | |||||
} | } | ||||
#ifdef EXPENSIVE_CHECKS | #ifdef EXPENSIVE_CHECKS | ||||
MF.verify(); | MF.verify(); | ||||
#endif | #endif | ||||
} | } | ||||
bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, | bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, | ||||
MachineBasicBlock::iterator MBBI, | MachineBasicBlock::iterator MBBI, | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | if (!reserveCallFrame) { | ||||
unsigned StackAlign = getStackAlignment(); | unsigned StackAlign = getStackAlignment(); | ||||
Amount = alignTo(Amount, StackAlign); | Amount = alignTo(Amount, StackAlign); | ||||
MachineModuleInfo &MMI = MF.getMMI(); | MachineModuleInfo &MMI = MF.getMMI(); | ||||
const Function *Fn = MF.getFunction(); | const Function *Fn = MF.getFunction(); | ||||
bool WindowsCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); | bool WindowsCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); | ||||
bool DwarfCFI = !WindowsCFI && | bool DwarfCFI = !WindowsCFI && | ||||
(MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); | (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); | ||||
bool InsertedCFI = false; | |||||
// If we have any exception handlers in this function, and we adjust | // If we have any exception handlers in this function, and we adjust | ||||
// the SP before calls, we may need to indicate this to the unwinder | // the SP before calls, we may need to indicate this to the unwinder | ||||
// using GNU_ARGS_SIZE. Note that this may be necessary even when | // using GNU_ARGS_SIZE. Note that this may be necessary even when | ||||
// Amount == 0, because the preceding function may have set a non-0 | // Amount == 0, because the preceding function may have set a non-0 | ||||
// GNU_ARGS_SIZE. | // GNU_ARGS_SIZE. | ||||
// TODO: We don't need to reset this between subsequent functions, | // TODO: We don't need to reset this between subsequent functions, | ||||
// if it didn't change. | // if it didn't change. | ||||
Show All 9 Lines | if (!reserveCallFrame) { | ||||
// Factor out the amount that gets handled inside the sequence | // Factor out the amount that gets handled inside the sequence | ||||
// (Pushes of argument for frame setup, callee pops for frame destroy) | // (Pushes of argument for frame setup, callee pops for frame destroy) | ||||
Amount -= InternalAmt; | Amount -= InternalAmt; | ||||
// TODO: This is needed only if we require precise CFA. | // TODO: This is needed only if we require precise CFA. | ||||
// If this is a callee-pop calling convention, emit a CFA adjust for | // If this is a callee-pop calling convention, emit a CFA adjust for | ||||
// the amount the callee popped. | // the amount the callee popped. | ||||
if (isDestroy && InternalAmt && DwarfCFI && !hasFP(MF)) | if (isDestroy && InternalAmt && DwarfCFI && !hasFP(MF)) { | ||||
BuildCFI(MBB, InsertPos, DL, | BuildCFI(MBB, InsertPos, DL, | ||||
MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt)); | MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt)); | ||||
MBB.updateCFIInfo(std::prev(InsertPos)); | |||||
InsertedCFI = true; | |||||
} | |||||
// Add Amount to SP to destroy a frame, or subtract to setup. | // Add Amount to SP to destroy a frame, or subtract to setup. | ||||
int64_t StackAdjustment = isDestroy ? Amount : -Amount; | int64_t StackAdjustment = isDestroy ? Amount : -Amount; | ||||
int64_t CfaAdjustment = -StackAdjustment; | int64_t CfaAdjustment = -StackAdjustment; | ||||
if (StackAdjustment) { | if (StackAdjustment) { | ||||
// Merge with any previous or following adjustment instruction. Note: the | // Merge with any previous or following adjustment instruction. Note: the | ||||
// instructions merged with here do not have CFI, so their stack | // instructions merged with here do not have CFI, so their stack | ||||
// adjustments do not feed into CfaAdjustment. | // adjustments do not feed into CfaAdjustment. | ||||
Show All 17 Lines | if (DwarfCFI && !hasFP(MF)) { | ||||
// it to be more precise. | // it to be more precise. | ||||
// TODO: When not using precise CFA, we also need to adjust for the | // TODO: When not using precise CFA, we also need to adjust for the | ||||
// InternalAmt here. | // InternalAmt here. | ||||
if (CfaAdjustment) { | if (CfaAdjustment) { | ||||
BuildCFI(MBB, InsertPos, DL, | BuildCFI(MBB, InsertPos, DL, | ||||
MCCFIInstruction::createAdjustCfaOffset(nullptr, | MCCFIInstruction::createAdjustCfaOffset(nullptr, | ||||
CfaAdjustment)); | CfaAdjustment)); | ||||
MBB.updateCFIInfo(std::prev(InsertPos)); | |||||
InsertedCFI = true; | |||||
} | } | ||||
} | } | ||||
if (InsertedCFI) MBB.updateCFIInfoSucc(); | |||||
return I; | return I; | ||||
} | } | ||||
if (isDestroy && InternalAmt) { | if (isDestroy && InternalAmt) { | ||||
// If we are performing frame pointer elimination and if the callee pops | // If we are performing frame pointer elimination and if the callee pops | ||||
// something off the stack pointer, add it back. We do this until we have | // something off the stack pointer, add it back. We do this until we have | ||||
// more advanced stack pointer tracking ability. | // more advanced stack pointer tracking ability. | ||||
// We are not tracking the stack pointer adjustment by the callee, so make | // We are not tracking the stack pointer adjustment by the callee, so make | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), FramePtr), | ||||
UsedReg, true, Offset) | UsedReg, true, Offset) | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
} else { | } else { | ||||
llvm_unreachable("32-bit frames with WinEH must use FramePtr or BasePtr"); | llvm_unreachable("32-bit frames with WinEH must use FramePtr or BasePtr"); | ||||
} | } | ||||
return MBBI; | return MBBI; | ||||
} | } | ||||
void X86FrameLowering::initializeCFIInfo(MachineFunction &MF) const { | |||||
int InitialOffset = TRI->getSlotSize(); | |||||
unsigned InitialRegister = TRI->getDwarfRegNum(StackPtr, true); | |||||
// Initialize CFI info if it hasn't already been initialized. | |||||
for (auto &MBB : MF) { | |||||
if (MBB.getIncomingCFAOffset() == -1) | |||||
MBB.setIncomingCFAOffset(InitialOffset); | |||||
if (MBB.getOutgoingCFAOffset() == -1) | |||||
MBB.setOutgoingCFAOffset(InitialOffset); | |||||
if (MBB.getIncomingCFARegister() == 0) | |||||
MBB.setIncomingCFARegister(InitialRegister); | |||||
if (MBB.getOutgoingCFARegister() == 0) | |||||
MBB.setOutgoingCFARegister(InitialRegister); | |||||
} | |||||
} | |||||
bool X86FrameLowering::maintainsCFIInfo() const { return true; } | |||||
namespace { | namespace { | ||||
// Struct used by orderFrameObjects to help sort the stack objects. | // Struct used by orderFrameObjects to help sort the stack objects. | ||||
struct X86FrameSortingObject { | struct X86FrameSortingObject { | ||||
bool IsValid = false; // true if we care about this Object. | bool IsValid = false; // true if we care about this Object. | ||||
unsigned ObjectIndex = 0; // Index of Object into MFI list. | unsigned ObjectIndex = 0; // Index of Object into MFI list. | ||||
unsigned ObjectSize = 0; // Size of Object in bytes. | unsigned ObjectSize = 0; // Size of Object in bytes. | ||||
unsigned ObjectAlignment = 1; // Alignment of Object in bytes. | unsigned ObjectAlignment = 1; // Alignment of Object in bytes. | ||||
unsigned ObjectNumUses = 0; // Object static number of uses. | unsigned ObjectNumUses = 0; // Object static number of uses. | ||||
▲ Show 20 Lines • Show All 204 Lines • Show Last 20 Lines |