From 569b5512b0d2629c98f37c8a82078ca041f0166d Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 5 Nov 2007 03:02:32 +0000 Subject: [PATCH] Added support for PIC code with "explicit relocations" *only*. Removed all macro code for PIC (goodbye "la"). Support tested with shootout bench. llvm-svn: 43697 --- lib/Target/Mips/MipsAsmPrinter.cpp | 42 ++++++++++-- lib/Target/Mips/MipsISelDAGToDAG.cpp | 74 +++++++++++++++++---- lib/Target/Mips/MipsISelLowering.cpp | 93 +++++++++++++++++---------- lib/Target/Mips/MipsISelLowering.h | 8 +-- lib/Target/Mips/MipsInstrInfo.td | 49 ++++++-------- lib/Target/Mips/MipsMachineFunction.h | 20 +++--- lib/Target/Mips/MipsRegisterInfo.cpp | 22 ++++++- lib/Target/Mips/MipsRegisterInfo.h | 4 +- lib/Target/Mips/MipsTargetMachine.cpp | 5 ++ 9 files changed, 214 insertions(+), 103 deletions(-) diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 4ed3f64a728..2dc9c2f2663 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF) emitMaskDirective(MF); emitFMaskDirective(MF); - if (MF.getTarget().getRelocationModel() == Reloc::Static) { + if (TM.getRelocationModel() == Reloc::Static) { emitSetDirective(NOREORDER); emitSetDirective(NOMACRO); } @@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF) void MipsAsmPrinter:: emitFunctionEnd(MachineFunction &MF) { - if (MF.getTarget().getRelocationModel() == Reloc::Static) { + if (TM.getRelocationModel() == Reloc::Static) { emitSetDirective(MACRO); emitSetDirective(REORDER); } @@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF) printInstruction(II); ++EmittedInsts; } + + // Each Basic Block is separated by a newline + O << '\n'; } // Emit function end directives @@ -319,17 +322,41 @@ printOperand(const MachineInstr *MI, int opNum) { const MachineOperand &MO = MI->getOperand(opNum); const MRegisterInfo &RI = *TM.getRegisterInfo(); - bool closeP=false; + bool closeP = false; + bool isPIC = (TM.getRelocationModel() == Reloc::PIC_); + bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large); - // %hi and %lo used on mips gas to break large constants + // %hi and %lo used on mips gas to load global addresses on + // static code. %got is used to load global addresses when + // using PIC_. %call16 is used to load direct call targets + // on PIC_ and small code size. %call_lo and %call_hi load + // direct call targets on PIC_ and large code size. if (MI->getOpcode() == Mips::LUi && !MO.isRegister() && !MO.isImmediate()) { - O << "%hi("; + if ((isPIC) && (isCodeLarge)) + O << "%call_hi("; + else + O << "%hi("; closeP = true; } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() && !MO.isImmediate()) { O << "%lo("; closeP = true; + } else if ((isPIC) && (MI->getOpcode() == Mips::LW) + && (!MO.isRegister()) && (!MO.isImmediate())) { + const MachineOperand &firstMO = MI->getOperand(opNum-1); + const MachineOperand &lastMO = MI->getOperand(opNum+1); + if ((firstMO.isRegister()) && (lastMO.isRegister())) { + if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP) + && (!isCodeLarge)) + O << "%call16("; + else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP)) + O << "%got("; + else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP) + && (isCodeLarge)) + O << "%call_lo("; + closeP = true; + } } switch (MO.getType()) @@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum) O << MO.getSymbolName(); break; + // FIXME: Verify correct case MachineOperand::MO_ConstantPoolIndex: O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" << MO.getConstantPoolIndex(); @@ -385,7 +413,9 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) return; } - // Load/Store memory operands -- imm($reg) + // Load/Store memory operands -- imm($reg) + // If PIC target the target is loaded as the + // pattern lw $25,%call16($28) printOperand(MI, opNum); O << "("; printOperand(MI, opNum+1); diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 85fa640bb09..6165d584bf8 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "Mips.h" #include "MipsISelLowering.h" +#include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" @@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base) return true; } - // TargetExternalSymbol and TargetGlobalAddress are - // lowered and their addresses go into registers, so - // they should not be touched here. - if ((Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress)) - return false; + // on PIC code Load GA + if (TM.getRelocationModel() == Reloc::PIC_) { + if (Addr.getOpcode() == ISD::TargetGlobalAddress) { + Base = CurDAG->getRegister(Mips::GP, MVT::i32); + Offset = Addr; + return true; + } + } else { + if ((Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress)) + return false; + } // Operand is a result from an ADD. - if (Addr.getOpcode() == ISD::ADD) - { - if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) - { - if (Predicate_immSExt16(CN)) - { + if (Addr.getOpcode() == ISD::ADD) { + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { + if (Predicate_immSExt16(CN)) { + // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast (Addr.getOperand(0))) { @@ -247,6 +252,51 @@ Select(SDOperand N) SDOperand MFInFlag = SDOperand(RemNode, 0); return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag); } + + /// Handle direct and indirect calls when using PIC. On PIC, when + /// GOT is smaller than about 64k (small code) the GA target is + /// loaded with only one instruction. Otherwise GA's target must + /// be loaded with 3 instructions. + case MipsISD::JmpLink: { + if (TM.getRelocationModel() == Reloc::PIC_) { + //bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large); + SDOperand Chain = Node->getOperand(0); + SDOperand Callee = Node->getOperand(1); + AddToISelQueue(Chain); + SDOperand T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32); + SDOperand InFlag(0, 0); + + if ( (isa(Callee)) || + (isa(Callee)) ) + { + /// Direct call for global addresses and external symbols + SDOperand GPReg = CurDAG->getRegister(Mips::GP, MVT::i32); + + // Use load to get GOT target + SDOperand Ops[] = { Callee, GPReg, Chain }; + SDOperand Load = SDOperand(CurDAG->getTargetNode(Mips::LW, MVT::i32, + MVT::Other, Ops, 3), 0); + Chain = Load.getValue(1); + AddToISelQueue(Chain); + + // Call target must be on T9 + Chain = CurDAG->getCopyToReg(Chain, T9Reg, Load, InFlag); + } else + /// Indirect call + Chain = CurDAG->getCopyToReg(Chain, T9Reg, Callee, InFlag); + + AddToISelQueue(Chain); + + // Emit Jump and Link Register + SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, MVT::Other, + MVT::Flag, T9Reg, Chain); + Chain = SDOperand(ResNode, 0); + InFlag = SDOperand(ResNode, 1); + ReplaceUses(SDOperand(Node, 0), Chain); + ReplaceUses(SDOperand(Node, 1), InFlag); + return ResNode; + } + } } // Select the default instruction diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 5b4ee2602a8..440d3e35e09 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -39,13 +39,11 @@ getTargetNodeName(unsigned Opcode) const { switch (Opcode) { - case MipsISD::JmpLink : return "MipsISD::JmpLink"; - case MipsISD::Hi : return "MipsISD::Hi"; - case MipsISD::Lo : return "MipsISD::Lo"; - case MipsISD::Ret : return "MipsISD::Ret"; - case MipsISD::Add : return "MipsISD::Add"; - case MipsISD::LoadAddr : return "MipsISD::LoadAddr"; - default : return NULL; + case MipsISD::JmpLink : return "MipsISD::JmpLink"; + case MipsISD::Hi : return "MipsISD::Hi"; + case MipsISD::Lo : return "MipsISD::Lo"; + case MipsISD::Ret : return "MipsISD::Ret"; + default : return NULL; } } @@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { SDOperand ResNode; GlobalValue *GV = cast(Op)->getGlobal(); - SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); + bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_); - // On PIC code global addresses are loaded with "la" instruction - if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) { - const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag); + SDOperand HiPart; + if (!isPIC) { + const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32); SDOperand Ops[] = { GA }; + HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1); + } else // Emit Load from Global Pointer + HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0); - SDOperand Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1); - SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); + // On functions and global targets not internal linked only + // a load from got/GP is necessary for PIC to work. + if ((isPIC) && ((!GV->hasInternalLinkage()) || (isa(GV)))) + return HiPart; - SDOperand InFlag = Hi.getValue(1); - ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag); - } else - ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA); + SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); + ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo); return ResNode; } @@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG) /// LowerCCCCallTo - functions arguments are copied from virtual /// regs to (physical regs)/(stack frame), CALLSEQ_START and /// CALLSEQ_END are emitted. -/// TODO: isVarArg, isTailCall, sret, GOT, linkage types. +/// TODO: isVarArg, isTailCall, sret. SDOperand MipsTargetLowering:: LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) { @@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) SmallVector MemOpChains; SDOperand StackPtr; - unsigned LastStackLoc=0; + int LastStackLoc=0; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { @@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) break; } - // Arguments that can be passed on register, - // must be kept at RegsToPass vector + // Arguments that can be passed on register must be kept at + // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else { @@ -294,14 +295,6 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) } } - // Create a stack location to hold GP when PIC is used - if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { - LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4); - MipsFunctionInfo *MipsFI = MF.getInfo(); - MFI->CreateFixedObject(4, LastStackLoc); - MipsFI->setGPStackOffset(LastStackLoc); - } - // Transform all store nodes into one single node because // all store nodes are independent of each other. if (!MemOpChains.empty()) @@ -321,13 +314,13 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol - // node so that legalize doesn't hack it. Otherwise we have an indirect call, - // if PIC is used, the call must use register GP - if (GlobalAddressSDNode *G = dyn_cast(Callee)) + // node so that legalize doesn't hack it. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); + // MipsJmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... // @@ -349,6 +342,37 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); + // Create a stack location to hold GP when PIC is used. This stack + // location is used on function prologue to save GP and also after all + // emited CALL's to restore GP. + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + + // Function can have an arbitrary number of calls, so + // hold the LastStackLoc with the biggest offset. + int FI; + MipsFunctionInfo *MipsFI = MF.getInfo(); + if (LastStackLoc >= MipsFI->getGPStackOffset()) { + + LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4); + // Create the frame index only once. SPOffset here can be anything + // (this will be fixed on processFunctionBeforeFrameFinalized) + if (MipsFI->getGPStackOffset() == -1) { + FI = MFI->CreateFixedObject(4, 0); + MipsFI->setGPFI(FI); + } + MipsFI->setGPStackOffset(LastStackLoc); + } + + + // Reload GP value. + FI = MipsFI->getGPFI(); + SDOperand FIN = DAG.getFrameIndex(FI,getPointerTy()); + SDOperand GPLoad = DAG.getLoad(MVT::i32, Chain, FIN, NULL, 0); + Chain = GPLoad.getValue(1); + Chain = DAG.getCopyToReg(Chain, DAG.getRegister(Mips::GP, MVT::i32), + GPLoad, SDOperand(0,0)); + } + // Create the CALLSEQ_END node. NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); Ops.clear(); @@ -389,10 +413,11 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall, ResultVals.push_back(Chain.getValue(0)); } - // Merge everything together with a MERGE_VALUES node. ResultVals.push_back(Chain); + + // Merge everything together with a MERGE_VALUES node. return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(), - &ResultVals[0], ResultVals.size()).Val; + &ResultVals[0], ResultVals.size()).Val; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 2d230a7ceb3..37c39f3c59d 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -38,13 +38,7 @@ namespace llvm { Lo, // Return - Ret, - - // Need to support addition with a input flag - Add, - - // Used on PIC Code to load global addresses - LoadAddr + Ret }; } diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 70bc7dd59c1..c6fcaed11f3 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -22,20 +22,11 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, SDNPOutFlag]>; -// Hi and Lo nodes are created to let easy manipulation of 16-bit when -// handling 32-bit immediates. They are used on MipsISelLowering to -// lower stuff like GlobalAddress, ExternalSymbol, ... on static model -// This two nodes have nothing to do with Mips Registers Hi and Lo. -def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>; -def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; - -// Necessary to generate glued instructions when loading GlobalAddress -// into registers. -def MipsAdd : SDNode<"MipsISD::Add", SDTIntBinOp, [SDNPCommutative, - SDNPAssociative, SDNPOptInFlag]>; - -// Used to Load Addresses on PIC code. -def MipsLoadAddr: SDNode<"MipsISD::LoadAddr", SDTIntUnaryOp>; +// Hi and Lo nodes are used to handle global addresses. Used on +// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// static model. (nothing to do with Mips Registers Hi and Lo) +def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>; +def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; // Return def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; @@ -371,15 +362,9 @@ def IMPLICIT_DEF_CPURegs : PseudoInstMips<(outs CPURegs:$dst), (ins), // are used, we have the same behavior, but get also a bunch of warnings // from the assembler. def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg), - ".set noreorder\n\t.cpload $reg\n\t.set reorder", []>; + ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>; def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc), - ".cprestore $loc", []>; - -// Used on PIC code only, it loads the address of label into register reg. The -// address is calculated from the global pointer ($gp) and is expanded by the -// assembler into two instructions "lw" and "addiu". -def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label), - "la $dst, $label", []>; + ".cprestore $loc\n", []>; //===----------------------------------------------------------------------===// // Instruction definition @@ -393,17 +378,13 @@ def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label), // ADDiu just accept 16-bit immediates but we handle this on Pat's. // immZExt32 is used here so it can match GlobalAddress immediates. -def ADDiu : ArithI<0x09, "addiu", MipsAdd, uimm16, immZExt16>; +def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>; def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>; def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>; def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; def ADD : ArithOverflowR<0x00, 0x20, "add">; def SUB : ArithOverflowR<0x00, 0x22, "sub">; -def MADD : MArithR<0x00, "madd">; -def MADDU : MArithR<0x01, "maddu">; -def MSUB : MArithR<0x04, "msub">; -def MSUBU : MArithR<0x05, "msubu">; // Logical def AND : LogicR<0x24, "and", and>; @@ -481,10 +462,16 @@ def MTLO : MoveFromTo<0x13, "mtlo">; // Count Leading // CLO/CLZ are part of the newer MIPS32(tm) instruction // set and not older Mips I keep this for future use -// though. +// though. //def CLO : CountLeading<0x21, "clo">; //def CLZ : CountLeading<0x20, "clz">; +// MADD*/MSUB* are not part of MipsI either. +//def MADD : MArithR<0x00, "madd">; +//def MADDU : MArithR<0x01, "maddu">; +//def MSUB : MArithR<0x04, "msub">; +//def MSUBU : MArithR<0x05, "msubu">; + // No operation let addr=0 in def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>; @@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst), // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; -def : Pat<(MipsAdd CPURegs:$hi, (MipsLo tglobaladdr:$lo)), +def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; -def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>; // Mips does not have not, so we increase the operation def : Pat<(not CPURegs:$in), @@ -544,6 +530,9 @@ def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; def : Pat<(truncstorei1 CPURegs:$src, addr:$addr), (SB CPURegs:$src, addr:$addr)>; +// some peepholes +def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; + /// /// brcond patterns /// diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index 2515aa0438a..d4f4312058a 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -33,11 +33,6 @@ private: /// the Return Address must be saved int RAStackOffset; - /// When PIC is used the GP must be saved on the stack - /// on the function prologue, so a reference to its stack - /// location must be kept. - int GPStackOffset; - /// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset struct MipsFIHolder { @@ -48,6 +43,13 @@ private: : FI(FrameIndex), SPOffset(StackPointerOffset) {} }; + /// When PIC is used the GP must be saved on the stack + /// on the function prologue and must be reloaded from this + /// stack location after every call. A reference to its stack + /// location and frame index must be kept to be used on + /// emitPrologue and processFunctionBeforeFrameFinalized. + MipsFIHolder GPHolder; + // On LowerFORMAL_ARGUMENTS the stack size is unknown, // so the Stack Pointer Offset calculation of "not in // register arguments" must be postponed to emitPrologue. @@ -64,7 +66,7 @@ private: public: MipsFunctionInfo(MachineFunction& MF) - : FPStackOffset(0), RAStackOffset(0), + : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1), HasLoadArgs(false), HasStoreVarArgs(false) {} @@ -74,8 +76,10 @@ public: int getRAStackOffset() const { return RAStackOffset; } void setRAStackOffset(int Off) { RAStackOffset = Off; } - int getGPStackOffset() const { return GPStackOffset; } - void setGPStackOffset(int Off) { GPStackOffset = Off; } + int getGPStackOffset() const { return GPHolder.SPOffset; } + int getGPFI() const { return GPHolder.FI; } + void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; } + void setGPFI(int FI) { GPHolder.FI = FI; } int getTopSavedRegOffset() const { return (RAStackOffset > FPStackOffset) ? diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index cd61fe88304..711a9cfde7d 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const return NewMI; } +MachineInstr *MipsRegisterInfo:: +foldMemoryOperand(MachineInstr* MI, unsigned OpNum, + MachineInstr* LoadMI) const { + return NULL; +} + //===----------------------------------------------------------------------===// // // Callee Saved Registers methods @@ -325,7 +331,7 @@ void MipsRegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { - MachineInstr &MI = *II; + MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); unsigned i = 0; @@ -359,7 +365,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, #endif MI.getOperand(i-1).ChangeToImmediate(Offset); - MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false); + MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); } void MipsRegisterInfo:: @@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const if ((isPIC) && (MFI->hasCalls())) BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE)) .addImm(MipsFI->getGPStackOffset()); - } void MipsRegisterInfo:: @@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const void MipsRegisterInfo:: processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + // Set the SPOffset on the FI where GP must be saved/loaded. + MachineFrameInfo *MFI = MF.getFrameInfo(); + if (MFI->hasCalls()) { + MipsFunctionInfo *MipsFI = MF.getInfo(); + #ifndef NDEBUG + DOUT << "processFunctionBeforeFrameFinalized\n"; + DOUT << "GPOffset :" << MipsFI->getGPStackOffset() << "\n"; + DOUT << "FI :" << MipsFI->getGPFI() << "\n"; + #endif + MFI->setObjectOffset(MipsFI->getGPFI(), MipsFI->getGPStackOffset()); + } } unsigned MipsRegisterInfo:: diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 9afc3b5dba5..adec3ed6e9c 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { int FrameIndex) const; MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, - MachineInstr* LoadMI) const { - return 0; - } + MachineInstr* LoadMI) const; void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 64516594f66..187dceef603 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -35,6 +35,9 @@ createTargetAsmInfo() const // On function prologue, the stack is created by decrementing // its pointer. Once decremented, all references are done with positive // offset from the stack/frame pointer, so StackGrowsUp is used. +// When using CodeModel::Large the behaviour +// +// MipsTargetMachine:: MipsTargetMachine(const Module &M, const std::string &FS): Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"), @@ -43,6 +46,8 @@ MipsTargetMachine(const Module &M, const std::string &FS): { if (getRelocationModel() != Reloc::Static) setRelocationModel(Reloc::PIC_); + if (getCodeModel() == CodeModel::Default) + setCodeModel(CodeModel::Small); } // return 0 and must specify -march to gen MIPS code.