| //===-- MipsEmitGPRestore.cpp - Emit GP restore instruction----------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This pass emits instructions that restore $gp right |
| // after jalr instructions. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "emit-gp-restore" |
| |
| #include "Mips.h" |
| #include "MipsTargetMachine.h" |
| #include "MipsMachineFunction.h" |
| #include "llvm/CodeGen/MachineFunctionPass.h" |
| #include "llvm/CodeGen/MachineInstrBuilder.h" |
| #include "llvm/Target/TargetInstrInfo.h" |
| #include "llvm/ADT/Statistic.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| struct Inserter : public MachineFunctionPass { |
| |
| TargetMachine &TM; |
| const TargetInstrInfo *TII; |
| |
| static char ID; |
| Inserter(TargetMachine &tm) |
| : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } |
| |
| virtual const char *getPassName() const { |
| return "Mips Emit GP Restore"; |
| } |
| |
| bool runOnMachineFunction(MachineFunction &F); |
| }; |
| char Inserter::ID = 0; |
| } // end of anonymous namespace |
| |
| bool Inserter::runOnMachineFunction(MachineFunction &F) { |
| if (TM.getRelocationModel() != Reloc::PIC_) |
| return false; |
| |
| bool Changed = false; |
| int FI = F.getInfo<MipsFunctionInfo>()->getGPFI(); |
| |
| for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); |
| MFI != MFE; ++MFI) { |
| MachineBasicBlock& MBB = *MFI; |
| MachineBasicBlock::iterator I = MFI->begin(); |
| |
| // If MBB is a landing pad, insert instruction that restores $gp after |
| // EH_LABEL. |
| if (MBB.isLandingPad()) { |
| // Find EH_LABEL first. |
| for (; I->getOpcode() != TargetOpcode::EH_LABEL; ++I) ; |
| |
| // Insert lw. |
| ++I; |
| DebugLoc dl = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); |
| BuildMI(MBB, I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) |
| .addImm(0); |
| Changed = true; |
| } |
| |
| while (I != MFI->end()) { |
| if (I->getOpcode() != Mips::JALR) { |
| ++I; |
| continue; |
| } |
| |
| DebugLoc dl = I->getDebugLoc(); |
| // emit lw $gp, ($gp save slot on stack) after jalr |
| BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) |
| .addImm(0); |
| Changed = true; |
| } |
| } |
| |
| return Changed; |
| } |
| |
| /// createMipsEmitGPRestorePass - Returns a pass that emits instructions that |
| /// restores $gp clobbered by jalr instructions. |
| FunctionPass *llvm::createMipsEmitGPRestorePass(MipsTargetMachine &tm) { |
| return new Inserter(tm); |
| } |
| |