You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			472 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			472 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//
 | |
| //
 | |
| //                     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 ARC implementation of the TargetFrameLowering class.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "ARCFrameLowering.h"
 | |
| #include "ARCMachineFunctionInfo.h"
 | |
| #include "ARCSubtarget.h"
 | |
| #include "llvm/CodeGen/MachineInstrBuilder.h"
 | |
| #include "llvm/CodeGen/MachineModuleInfo.h"
 | |
| #include "llvm/CodeGen/RegisterScavenging.h"
 | |
| #include "llvm/CodeGen/TargetRegisterInfo.h"
 | |
| #include "llvm/IR/Function.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| 
 | |
| #define DEBUG_TYPE "arc-frame-lowering"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| static cl::opt<bool>
 | |
|     UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
 | |
|                           cl::desc("Use arc callee save/restore functions"),
 | |
|                           cl::init(true));
 | |
| 
 | |
| static const char *store_funclet_name[] = {
 | |
|     "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",
 | |
|     "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",
 | |
|     "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",
 | |
| };
 | |
| 
 | |
| static const char *load_funclet_name[] = {
 | |
|     "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",
 | |
|     "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",
 | |
|     "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",
 | |
| };
 | |
| 
 | |
| static void generateStackAdjustment(MachineBasicBlock &MBB,
 | |
|                                     MachineBasicBlock::iterator MBBI,
 | |
|                                     const ARCInstrInfo &TII, DebugLoc dl,
 | |
|                                     int Amount, int StackPtr) {
 | |
|   unsigned AdjOp;
 | |
|   if (!Amount)
 | |
|     return;
 | |
|   bool Positive;
 | |
|   unsigned AbsAmount;
 | |
|   if (Amount < 0) {
 | |
|     AbsAmount = -Amount;
 | |
|     Positive = false;
 | |
|   } else {
 | |
|     AbsAmount = Amount;
 | |
|     Positive = true;
 | |
|   }
 | |
| 
 | |
|   DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," << AbsAmount
 | |
|                << "\n");
 | |
| 
 | |
|   assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");
 | |
|   if (isUInt<6>(AbsAmount))
 | |
|     AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
 | |
|   else
 | |
|     AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
 | |
| 
 | |
|   BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
 | |
|       .addReg(StackPtr)
 | |
|       .addImm(AbsAmount);
 | |
| }
 | |
| 
 | |
| static unsigned
 | |
| determineLastCalleeSave(const std::vector<CalleeSavedInfo> &CSI) {
 | |
|   unsigned Last = 0;
 | |
|   for (auto Reg : CSI) {
 | |
|     assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&
 | |
|            "Unexpected callee saved reg.");
 | |
|     if (Reg.getReg() > Last)
 | |
|       Last = Reg.getReg();
 | |
|   }
 | |
|   return Last;
 | |
| }
 | |
| 
 | |
| void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF,
 | |
|                                             BitVector &SavedRegs,
 | |
|                                             RegScavenger *RS) const {
 | |
|   DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName()
 | |
|                << "\n");
 | |
|   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 | |
|   SavedRegs.set(ARC::BLINK);
 | |
| }
 | |
| 
 | |
| void ARCFrameLowering::adjustStackToMatchRecords(
 | |
|     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
 | |
|     bool Allocate) const {
 | |
|   MachineFunction &MF = *MBB.getParent();
 | |
|   int ScalarAlloc = MF.getFrameInfo().getStackSize();
 | |
| 
 | |
|   if (Allocate) {
 | |
|     // Allocate by adjusting by the negative of what the record holder tracked
 | |
|     // it tracked a positive offset in a downward growing stack.
 | |
|     ScalarAlloc = -ScalarAlloc;
 | |
|   }
 | |
| 
 | |
|   generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),
 | |
|                           ScalarAlloc, ARC::SP);
 | |
| }
 | |
| 
 | |
| /// Insert prolog code into the function.
 | |
| /// For ARC, this inserts a call to a function that puts required callee saved
 | |
| /// registers onto the stack, when enough callee saved registers are required.
 | |
| void ARCFrameLowering::emitPrologue(MachineFunction &MF,
 | |
|                                     MachineBasicBlock &MBB) const {
 | |
|   DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n");
 | |
|   auto *AFI = MF.getInfo<ARCFunctionInfo>();
 | |
|   MachineModuleInfo &MMI = MF.getMMI();
 | |
|   MCContext &Context = MMI.getContext();
 | |
|   const MCRegisterInfo *MRI = Context.getRegisterInfo();
 | |
|   const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
 | |
|   MachineBasicBlock::iterator MBBI = MBB.begin();
 | |
|   // Debug location must be unknown since the first debug location is used
 | |
|   // to determine the end of the prologue.
 | |
|   DebugLoc dl;
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
 | |
|   unsigned Last = determineLastCalleeSave(CSI);
 | |
|   unsigned StackSlotsUsedByFunclet = 0;
 | |
|   bool SavedBlink = false;
 | |
|   unsigned AlreadyAdjusted = 0;
 | |
|   if (MF.getFunction().isVarArg()) {
 | |
|     // Add in the varargs area here first.
 | |
|     DEBUG(dbgs() << "Varargs\n");
 | |
|     unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
 | |
|         .addReg(ARC::SP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(VarArgsBytes);
 | |
|   }
 | |
|   if (hasFP(MF)) {
 | |
|     DEBUG(dbgs() << "Saving FP\n");
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
 | |
|         .addReg(ARC::SP, RegState::Define)
 | |
|         .addReg(ARC::FP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(-4);
 | |
|     AlreadyAdjusted += 4;
 | |
|   }
 | |
|   if (UseSaveRestoreFunclet && Last > ARC::R14) {
 | |
|     DEBUG(dbgs() << "Creating store funclet.\n");
 | |
|     // BL to __save_r13_to_<TRI->getRegAsmName()>
 | |
|     StackSlotsUsedByFunclet = Last - ARC::R12;
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
 | |
|         .addReg(ARC::SP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(4 * StackSlotsUsedByFunclet);
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))
 | |
|         .addExternalSymbol(store_funclet_name[Last - ARC::R15])
 | |
|         .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
 | |
|     AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
 | |
|     SavedBlink = true;
 | |
|   }
 | |
|   // If we haven't saved BLINK, but we need to...do that now.
 | |
|   if (MFI.hasCalls() && !SavedBlink) {
 | |
|     DEBUG(dbgs() << "Creating save blink.\n");
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
 | |
|     AlreadyAdjusted += 4;
 | |
|   }
 | |
|   if (AFI->MaxCallStackReq > 0)
 | |
|     MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);
 | |
|   // We have already saved some of the stack...
 | |
|   DEBUG(dbgs() << "Adjusting stack by: "
 | |
|                << (MFI.getStackSize() - AlreadyAdjusted) << "\n");
 | |
|   generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,
 | |
|                           -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);
 | |
| 
 | |
|   if (hasFP(MF)) {
 | |
|     DEBUG(dbgs() << "Setting FP from SP.\n");
 | |
|     BuildMI(MBB, MBBI, dl,
 | |
|             TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6
 | |
|                                                    : ARC::ADD_rrlimm),
 | |
|             ARC::FP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(MFI.getStackSize());
 | |
|   }
 | |
| 
 | |
|   // Emit CFI records:
 | |
|   // .cfi_def_cfa_offset StackSize
 | |
|   // .cfi_offset fp, -StackSize
 | |
|   // .cfi_offset blink, -StackSize+4
 | |
|   unsigned CFIIndex = MF.addFrameInst(
 | |
|       MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
 | |
|   BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
 | |
|       .addCFIIndex(CFIIndex)
 | |
|       .setMIFlags(MachineInstr::FrameSetup);
 | |
| 
 | |
|   int CurOffset = -4;
 | |
|   if (hasFP(MF)) {
 | |
|     CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
 | |
|         nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
 | |
|         .addCFIIndex(CFIIndex)
 | |
|         .setMIFlags(MachineInstr::FrameSetup);
 | |
|     CurOffset -= 4;
 | |
|   }
 | |
| 
 | |
|   if (MFI.hasCalls()) {
 | |
|     CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
 | |
|         nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
 | |
|         .addCFIIndex(CFIIndex)
 | |
|         .setMIFlags(MachineInstr::FrameSetup);
 | |
|   }
 | |
|   // CFI for the rest of the registers.
 | |
|   for (const auto &Entry : CSI) {
 | |
|     unsigned Reg = Entry.getReg();
 | |
|     int FI = Entry.getFrameIdx();
 | |
|     // Skip BLINK and FP.
 | |
|     if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))
 | |
|       continue;
 | |
|     CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
 | |
|         nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
 | |
|     BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
 | |
|         .addCFIIndex(CFIIndex)
 | |
|         .setMIFlags(MachineInstr::FrameSetup);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// Insert epilog code into the function.
 | |
| /// For ARC, this inserts a call to a function that restores callee saved
 | |
| /// registers onto the stack, when enough callee saved registers are required.
 | |
| void ARCFrameLowering::emitEpilogue(MachineFunction &MF,
 | |
|                                     MachineBasicBlock &MBB) const {
 | |
|   DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n");
 | |
|   auto *AFI = MF.getInfo<ARCFunctionInfo>();
 | |
|   const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
 | |
|   MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   uint64_t StackSize = MF.getFrameInfo().getStackSize();
 | |
|   bool SavedBlink = false;
 | |
|   unsigned AmountAboveFunclet = 0;
 | |
|   // If we have variable sized frame objects, then we have to move
 | |
|   // the stack pointer to a known spot (fp - StackSize).
 | |
|   // Then, replace the frame pointer by (new) [sp,StackSize-4].
 | |
|   // Then, move the stack pointer the rest of the way (sp = sp + StackSize).
 | |
|   if (hasFP(MF)) {
 | |
|     BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARC::SUB_rru6), ARC::SP)
 | |
|         .addReg(ARC::FP)
 | |
|         .addImm(StackSize);
 | |
|     AmountAboveFunclet += 4;
 | |
|   }
 | |
| 
 | |
|   // Now, move the stack pointer to the bottom of the save area for the funclet.
 | |
|   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
 | |
|   unsigned Last = determineLastCalleeSave(CSI);
 | |
|   unsigned StackSlotsUsedByFunclet = 0;
 | |
|   // Now, restore the callee save registers.
 | |
|   if (UseSaveRestoreFunclet && Last > ARC::R14) {
 | |
|     // BL to __ld_r13_to_<TRI->getRegAsmName()>
 | |
|     StackSlotsUsedByFunclet = Last - ARC::R12;
 | |
|     AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
 | |
|     SavedBlink = true;
 | |
|   }
 | |
| 
 | |
|   if (MFI.hasCalls() && !SavedBlink) {
 | |
|     AmountAboveFunclet += 4;
 | |
|     SavedBlink = true;
 | |
|   }
 | |
| 
 | |
|   // Move the stack pointer up to the point of the funclet.
 | |
|   if (StackSize - AmountAboveFunclet) {
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
 | |
|         .addReg(ARC::SP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(StackSize - AmountAboveFunclet);
 | |
|   }
 | |
| 
 | |
|   if (StackSlotsUsedByFunclet) {
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))
 | |
|         .addExternalSymbol(load_funclet_name[Last - ARC::R15])
 | |
|         .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
 | |
|         .addReg(ARC::SP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(4 * (StackSlotsUsedByFunclet));
 | |
|   }
 | |
|   // Now, pop blink if necessary.
 | |
|   if (SavedBlink) {
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
 | |
|   }
 | |
|   // Now, pop fp if necessary.
 | |
|   if (hasFP(MF)) {
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))
 | |
|         .addReg(ARC::SP, RegState::Define)
 | |
|         .addReg(ARC::FP, RegState::Define)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(4);
 | |
|   }
 | |
| 
 | |
|   // Relieve the varargs area if necessary.
 | |
|   if (MF.getFunction().isVarArg()) {
 | |
|     // Add in the varargs area here first.
 | |
|     DEBUG(dbgs() << "Varargs\n");
 | |
|     unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
 | |
|     BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
 | |
|         .addReg(ARC::SP)
 | |
|         .addReg(ARC::SP)
 | |
|         .addImm(VarArgsBytes);
 | |
|   }
 | |
| }
 | |
| 
 | |
| static std::vector<CalleeSavedInfo>::iterator
 | |
| getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {
 | |
|   for (auto I = V.begin(), E = V.end(); I != E; ++I) {
 | |
|     if (reg == I->getReg())
 | |
|       return I;
 | |
|   }
 | |
|   return V.end();
 | |
| }
 | |
| 
 | |
| bool ARCFrameLowering::assignCalleeSavedSpillSlots(
 | |
|     MachineFunction &MF, const TargetRegisterInfo *TRI,
 | |
|     std::vector<CalleeSavedInfo> &CSI) const {
 | |
|   // Use this opportunity to assign the spill slots for all of the potential
 | |
|   // callee save registers (blink, fp, r13->r25) that we care about the
 | |
|   // placement for.  We can calculate all of that data here.
 | |
|   int CurOffset = -4;
 | |
|   unsigned Last = determineLastCalleeSave(CSI);
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   if (hasFP(MF)) {
 | |
|     // Create a fixed slot at for FP
 | |
|     int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
 | |
|     DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "
 | |
|                  << CurOffset << "\n");
 | |
|     (void)StackObj;
 | |
|     CurOffset -= 4;
 | |
|   }
 | |
|   if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {
 | |
|     // Create a fixed slot for BLINK.
 | |
|     int StackObj  = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
 | |
|     DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for BLINK at "
 | |
|                  << CurOffset << "\n");
 | |
|     (void)StackObj;
 | |
|     CurOffset -= 4;
 | |
|   }
 | |
| 
 | |
|   // Create slots for last down to r13.
 | |
|   for (unsigned Which = Last; Which > ARC::R12; Which--) {
 | |
|     auto RegI = getSavedReg(CSI, Which);
 | |
|     if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
 | |
|       // Always create the stack slot.  If for some reason the register isn't in
 | |
|       // the save list, then don't worry about it.
 | |
|       int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
 | |
|       if (RegI != CSI.end())
 | |
|         RegI->setFrameIdx(FI);
 | |
|     } else
 | |
|       MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);
 | |
|     CurOffset -= 4;
 | |
|   }
 | |
|   for (auto &I : CSI) {
 | |
|     if (I.getReg() > ARC::R12)
 | |
|       continue;
 | |
|     if (I.getFrameIdx() == 0) {
 | |
|       I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true));
 | |
|       DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
 | |
|                    << ") for other register at " << CurOffset << "\n");
 | |
|     } else {
 | |
|       MFI.setObjectOffset(I.getFrameIdx(), CurOffset);
 | |
|       DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()
 | |
|                    << ") for other register at " << CurOffset << "\n");
 | |
|     }
 | |
|     CurOffset -= 4;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool ARCFrameLowering::spillCalleeSavedRegisters(
 | |
|     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
 | |
|     const std::vector<CalleeSavedInfo> &CSI,
 | |
|     const TargetRegisterInfo *TRI) const {
 | |
|   DEBUG(dbgs() << "Spill callee saved registers: "
 | |
|                << MBB.getParent()->getName() << "\n");
 | |
|   // There are routines for saving at least 3 registers (r13 to r15, etc.)
 | |
|   unsigned Last = determineLastCalleeSave(CSI);
 | |
|   if (UseSaveRestoreFunclet && Last > ARC::R14) {
 | |
|     // Use setObjectOffset for these registers.
 | |
|     // Needs to be in or before processFunctionBeforeFrameFinalized.
 | |
|     // Or, do assignCalleeSaveSpillSlots?
 | |
|     // Will be handled in prolog.
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool ARCFrameLowering::restoreCalleeSavedRegisters(
 | |
|     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
 | |
|     std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const {
 | |
|   DEBUG(dbgs() << "Restore callee saved registers: "
 | |
|                << MBB.getParent()->getName() << "\n");
 | |
|   // There are routines for saving at least 3 registers (r13 to r15, etc.)
 | |
|   unsigned Last = determineLastCalleeSave(CSI);
 | |
|   if (UseSaveRestoreFunclet && Last > ARC::R14) {
 | |
|     // Will be handled in epilog.
 | |
|     return true;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // Adjust local variables that are 4-bytes or larger to 4-byte boundary
 | |
| void ARCFrameLowering::processFunctionBeforeFrameFinalized(
 | |
|     MachineFunction &MF, RegScavenger *RS) const {
 | |
|   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
 | |
|   DEBUG(dbgs() << "Process function before frame finalized: "
 | |
|                << MF.getName() << "\n");
 | |
|   MachineFrameInfo &MFI = MF.getFrameInfo();
 | |
|   DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");
 | |
|   const TargetRegisterClass *RC = &ARC::GPR32RegClass;
 | |
|   if (MFI.hasStackObjects()) {
 | |
|     int RegScavFI = MFI.CreateStackObject(
 | |
|         RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
 | |
|     RS->addScavengingFrameIndex(RegScavFI);
 | |
|     DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI << "\n");
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void emitRegUpdate(MachineBasicBlock &MBB,
 | |
|                           MachineBasicBlock::iterator &MBBI, DebugLoc dl,
 | |
|                           unsigned Reg, int NumBytes, bool IsAdd,
 | |
|                           const ARCInstrInfo *TII) {
 | |
|   unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
 | |
|   BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
 | |
|       .addReg(Reg, RegState::Kill)
 | |
|       .addImm(NumBytes);
 | |
| }
 | |
| 
 | |
| MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(
 | |
|     MachineFunction &MF, MachineBasicBlock &MBB,
 | |
|     MachineBasicBlock::iterator I) const {
 | |
|   DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n");
 | |
|   const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
 | |
|   MachineInstr &Old = *I;
 | |
|   DebugLoc dl = Old.getDebugLoc();
 | |
|   unsigned Amt = Old.getOperand(0).getImm();
 | |
|   auto *AFI = MF.getInfo<ARCFunctionInfo>();
 | |
|   if (!hasFP(MF)) {
 | |
|     if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)
 | |
|       AFI->MaxCallStackReq = Amt;
 | |
|   } else {
 | |
|     if (Amt != 0) {
 | |
|       assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||
 | |
|               Old.getOpcode() == ARC::ADJCALLSTACKUP) &&
 | |
|              "Unknown Frame Pseudo.");
 | |
|       bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);
 | |
|       emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);
 | |
|     }
 | |
|   }
 | |
|   return MBB.erase(I);
 | |
| }
 | |
| 
 | |
| bool ARCFrameLowering::hasFP(const MachineFunction &MF) const {
 | |
|   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
 | |
|   bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||
 | |
|                MF.getFrameInfo().hasVarSizedObjects() ||
 | |
|                MF.getFrameInfo().isFrameAddressTaken() ||
 | |
|                RegInfo->needsStackRealignment(MF);
 | |
|   return HasFP;
 | |
| }
 |