|  | //======-- MSP430FrameLowering.cpp - MSP430 Frame Information -------=========// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains the MSP430 implementation of TargetFrameLowering class. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "MSP430FrameLowering.h" | 
|  | #include "MSP430InstrInfo.h" | 
|  | #include "MSP430MachineFunctionInfo.h" | 
|  | #include "llvm/Function.h" | 
|  | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | #include "llvm/CodeGen/MachineFunction.h" | 
|  | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | #include "llvm/CodeGen/MachineModuleInfo.h" | 
|  | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | #include "llvm/Target/TargetData.h" | 
|  | #include "llvm/Target/TargetOptions.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const { | 
|  | const MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  |  | 
|  | return (DisableFramePointerElim(MF) || | 
|  | MF.getFrameInfo()->hasVarSizedObjects() || | 
|  | MFI->isFrameAddressTaken()); | 
|  | } | 
|  |  | 
|  | bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { | 
|  | return !MF.getFrameInfo()->hasVarSizedObjects(); | 
|  | } | 
|  |  | 
|  | void MSP430FrameLowering::emitPrologue(MachineFunction &MF) const { | 
|  | MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB | 
|  | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>(); | 
|  | const MSP430InstrInfo &TII = | 
|  | *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo()); | 
|  |  | 
|  | MachineBasicBlock::iterator MBBI = MBB.begin(); | 
|  | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | 
|  |  | 
|  | // Get the number of bytes to allocate from the FrameInfo. | 
|  | uint64_t StackSize = MFI->getStackSize(); | 
|  |  | 
|  | uint64_t NumBytes = 0; | 
|  | if (hasFP(MF)) { | 
|  | // Calculate required stack adjustment | 
|  | uint64_t FrameSize = StackSize - 2; | 
|  | NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize(); | 
|  |  | 
|  | // Get the offset of the stack slot for the EBP register... which is | 
|  | // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. | 
|  | // Update the frame offset adjustment. | 
|  | MFI->setOffsetAdjustment(-NumBytes); | 
|  |  | 
|  | // Save FPW into the appropriate stack slot... | 
|  | BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r)) | 
|  | .addReg(MSP430::FPW, RegState::Kill); | 
|  |  | 
|  | // Update FPW with the new base value... | 
|  | BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FPW) | 
|  | .addReg(MSP430::SPW); | 
|  |  | 
|  | // Mark the FramePtr as live-in in every block except the entry. | 
|  | for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); | 
|  | I != E; ++I) | 
|  | I->addLiveIn(MSP430::FPW); | 
|  |  | 
|  | } else | 
|  | NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize(); | 
|  |  | 
|  | // Skip the callee-saved push instructions. | 
|  | while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r)) | 
|  | ++MBBI; | 
|  |  | 
|  | if (MBBI != MBB.end()) | 
|  | DL = MBBI->getDebugLoc(); | 
|  |  | 
|  | if (NumBytes) { // adjust stack pointer: SPW -= numbytes | 
|  | // If there is an SUB16ri of SPW immediately before this instruction, merge | 
|  | // the two. | 
|  | //NumBytes -= mergeSPUpdates(MBB, MBBI, true); | 
|  | // If there is an ADD16ri or SUB16ri of SPW immediately after this | 
|  | // instruction, merge the two instructions. | 
|  | // mergeSPUpdatesDown(MBB, MBBI, &NumBytes); | 
|  |  | 
|  | if (NumBytes) { | 
|  | MachineInstr *MI = | 
|  | BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SPW) | 
|  | .addReg(MSP430::SPW).addImm(NumBytes); | 
|  | // The SRW implicit def is dead. | 
|  | MI->getOperand(3).setIsDead(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void MSP430FrameLowering::emitEpilogue(MachineFunction &MF, | 
|  | MachineBasicBlock &MBB) const { | 
|  | const MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>(); | 
|  | const MSP430InstrInfo &TII = | 
|  | *static_cast<const MSP430InstrInfo*>(MF.getTarget().getInstrInfo()); | 
|  |  | 
|  | MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); | 
|  | unsigned RetOpcode = MBBI->getOpcode(); | 
|  | DebugLoc DL = MBBI->getDebugLoc(); | 
|  |  | 
|  | switch (RetOpcode) { | 
|  | case MSP430::RET: | 
|  | case MSP430::RETI: break;  // These are ok | 
|  | default: | 
|  | llvm_unreachable("Can only insert epilog into returning blocks"); | 
|  | } | 
|  |  | 
|  | // Get the number of bytes to allocate from the FrameInfo | 
|  | uint64_t StackSize = MFI->getStackSize(); | 
|  | unsigned CSSize = MSP430FI->getCalleeSavedFrameSize(); | 
|  | uint64_t NumBytes = 0; | 
|  |  | 
|  | if (hasFP(MF)) { | 
|  | // Calculate required stack adjustment | 
|  | uint64_t FrameSize = StackSize - 2; | 
|  | NumBytes = FrameSize - CSSize; | 
|  |  | 
|  | // pop FPW. | 
|  | BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FPW); | 
|  | } else | 
|  | NumBytes = StackSize - CSSize; | 
|  |  | 
|  | // Skip the callee-saved pop instructions. | 
|  | while (MBBI != MBB.begin()) { | 
|  | MachineBasicBlock::iterator PI = prior(MBBI); | 
|  | unsigned Opc = PI->getOpcode(); | 
|  | if (Opc != MSP430::POP16r && !PI->getDesc().isTerminator()) | 
|  | break; | 
|  | --MBBI; | 
|  | } | 
|  |  | 
|  | DL = MBBI->getDebugLoc(); | 
|  |  | 
|  | // If there is an ADD16ri or SUB16ri of SPW immediately before this | 
|  | // instruction, merge the two instructions. | 
|  | //if (NumBytes || MFI->hasVarSizedObjects()) | 
|  | //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes); | 
|  |  | 
|  | if (MFI->hasVarSizedObjects()) { | 
|  | BuildMI(MBB, MBBI, DL, | 
|  | TII.get(MSP430::MOV16rr), MSP430::SPW).addReg(MSP430::FPW); | 
|  | if (CSSize) { | 
|  | MachineInstr *MI = | 
|  | BuildMI(MBB, MBBI, DL, | 
|  | TII.get(MSP430::SUB16ri), MSP430::SPW) | 
|  | .addReg(MSP430::SPW).addImm(CSSize); | 
|  | // The SRW implicit def is dead. | 
|  | MI->getOperand(3).setIsDead(); | 
|  | } | 
|  | } else { | 
|  | // adjust stack pointer back: SPW += numbytes | 
|  | if (NumBytes) { | 
|  | MachineInstr *MI = | 
|  | BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SPW) | 
|  | .addReg(MSP430::SPW).addImm(NumBytes); | 
|  | // The SRW implicit def is dead. | 
|  | MI->getOperand(3).setIsDead(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // FIXME: Can we eleminate these in favour of generic code? | 
|  | bool | 
|  | MSP430FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MI, | 
|  | const std::vector<CalleeSavedInfo> &CSI, | 
|  | const TargetRegisterInfo *TRI) const { | 
|  | if (CSI.empty()) | 
|  | return false; | 
|  |  | 
|  | DebugLoc DL; | 
|  | if (MI != MBB.end()) DL = MI->getDebugLoc(); | 
|  |  | 
|  | MachineFunction &MF = *MBB.getParent(); | 
|  | const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); | 
|  | MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>(); | 
|  | MFI->setCalleeSavedFrameSize(CSI.size() * 2); | 
|  |  | 
|  | for (unsigned i = CSI.size(); i != 0; --i) { | 
|  | unsigned Reg = CSI[i-1].getReg(); | 
|  | // Add the callee-saved register as live-in. It's killed at the spill. | 
|  | MBB.addLiveIn(Reg); | 
|  | BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r)) | 
|  | .addReg(Reg, RegState::Kill); | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool | 
|  | MSP430FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MI, | 
|  | const std::vector<CalleeSavedInfo> &CSI, | 
|  | const TargetRegisterInfo *TRI) const { | 
|  | if (CSI.empty()) | 
|  | return false; | 
|  |  | 
|  | DebugLoc DL; | 
|  | if (MI != MBB.end()) DL = MI->getDebugLoc(); | 
|  |  | 
|  | MachineFunction &MF = *MBB.getParent(); | 
|  | const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); | 
|  |  | 
|  | for (unsigned i = 0, e = CSI.size(); i != e; ++i) | 
|  | BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg()); | 
|  |  | 
|  | return true; | 
|  | } |