mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	Added support for PIC code with "explicit relocations" *only*.
Removed all macro code for PIC (goodbye "la"). Support tested with shootout bench. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43697 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF) | |||||||
|   emitMaskDirective(MF); |   emitMaskDirective(MF); | ||||||
|   emitFMaskDirective(MF); |   emitFMaskDirective(MF); | ||||||
|  |  | ||||||
|   if (MF.getTarget().getRelocationModel() == Reloc::Static) { |   if (TM.getRelocationModel() == Reloc::Static) { | ||||||
|     emitSetDirective(NOREORDER); |     emitSetDirective(NOREORDER); | ||||||
|     emitSetDirective(NOMACRO); |     emitSetDirective(NOMACRO); | ||||||
|   } |   } | ||||||
| @@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF) | |||||||
| void MipsAsmPrinter:: | void MipsAsmPrinter:: | ||||||
| emitFunctionEnd(MachineFunction &MF)  | emitFunctionEnd(MachineFunction &MF)  | ||||||
| { | { | ||||||
|   if (MF.getTarget().getRelocationModel() == Reloc::Static) { |   if (TM.getRelocationModel() == Reloc::Static) { | ||||||
|     emitSetDirective(MACRO); |     emitSetDirective(MACRO); | ||||||
|     emitSetDirective(REORDER); |     emitSetDirective(REORDER); | ||||||
|   }     |   }     | ||||||
| @@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF) | |||||||
|       printInstruction(II); |       printInstruction(II); | ||||||
|       ++EmittedInsts; |       ++EmittedInsts; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Each Basic Block is separated by a newline | ||||||
|  |     O << '\n'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Emit function end directives |   // Emit function end directives | ||||||
| @@ -320,16 +323,40 @@ printOperand(const MachineInstr *MI, int opNum) | |||||||
|   const MachineOperand &MO = MI->getOperand(opNum); |   const MachineOperand &MO = MI->getOperand(opNum); | ||||||
|   const MRegisterInfo  &RI = *TM.getRegisterInfo(); |   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()  |   if (MI->getOpcode() == Mips::LUi && !MO.isRegister()  | ||||||
|       && !MO.isImmediate()) { |       && !MO.isImmediate()) { | ||||||
|  |     if ((isPIC) && (isCodeLarge)) | ||||||
|  |       O << "%call_hi("; | ||||||
|  |     else | ||||||
|       O << "%hi("; |       O << "%hi("; | ||||||
|     closeP = true; |     closeP = true; | ||||||
|   } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()  |   } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()  | ||||||
|              && !MO.isImmediate()) { |              && !MO.isImmediate()) { | ||||||
|     O << "%lo("; |     O << "%lo("; | ||||||
|     closeP = true; |     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())  |   switch (MO.getType())  | ||||||
| @@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum) | |||||||
|       O << MO.getSymbolName(); |       O << MO.getSymbolName(); | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|  |     // FIXME: Verify correct | ||||||
|     case MachineOperand::MO_ConstantPoolIndex: |     case MachineOperand::MO_ConstantPoolIndex: | ||||||
|       O << TAI->getPrivateGlobalPrefix() << "CPI" |       O << TAI->getPrivateGlobalPrefix() << "CPI" | ||||||
|         << getFunctionNumber() << "_" << MO.getConstantPoolIndex(); |         << getFunctionNumber() << "_" << MO.getConstantPoolIndex(); | ||||||
| @@ -386,6 +414,8 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // 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); |   printOperand(MI, opNum); | ||||||
|   O << "("; |   O << "("; | ||||||
|   printOperand(MI, opNum+1); |   printOperand(MI, opNum+1); | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ | |||||||
|  |  | ||||||
| #include "Mips.h" | #include "Mips.h" | ||||||
| #include "MipsISelLowering.h" | #include "MipsISelLowering.h" | ||||||
|  | #include "MipsMachineFunction.h" | ||||||
| #include "MipsRegisterInfo.h" | #include "MipsRegisterInfo.h" | ||||||
| #include "MipsSubtarget.h" | #include "MipsSubtarget.h" | ||||||
| #include "MipsTargetMachine.h" | #include "MipsTargetMachine.h" | ||||||
| @@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base) | |||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|      |      | ||||||
|   // TargetExternalSymbol and TargetGlobalAddress are |   // on PIC code Load GA | ||||||
|   // lowered and their addresses go into registers, so |   if (TM.getRelocationModel() == Reloc::PIC_) { | ||||||
|   // they should not be touched here. |     if (Addr.getOpcode() == ISD::TargetGlobalAddress) { | ||||||
|  |       Base   = CurDAG->getRegister(Mips::GP, MVT::i32); | ||||||
|  |       Offset = Addr; | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|     if ((Addr.getOpcode() == ISD::TargetExternalSymbol || |     if ((Addr.getOpcode() == ISD::TargetExternalSymbol || | ||||||
|         Addr.getOpcode() == ISD::TargetGlobalAddress)) |         Addr.getOpcode() == ISD::TargetGlobalAddress)) | ||||||
|       return false; |       return false; | ||||||
|  |   }     | ||||||
|    |    | ||||||
|   // Operand is a result from an ADD. |   // Operand is a result from an ADD. | ||||||
|   if (Addr.getOpcode() == ISD::ADD)  |   if (Addr.getOpcode() == ISD::ADD) { | ||||||
|   { |     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { | ||||||
|     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))  |       if (Predicate_immSExt16(CN)) { | ||||||
|     { |  | ||||||
|       if (Predicate_immSExt16(CN))  |  | ||||||
|       { |  | ||||||
|         // If the first operand is a FI, get the TargetFI Node |         // If the first operand is a FI, get the TargetFI Node | ||||||
|         if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> |         if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> | ||||||
|                                     (Addr.getOperand(0))) { |                                     (Addr.getOperand(0))) { | ||||||
| @@ -247,6 +252,51 @@ Select(SDOperand N) | |||||||
|       SDOperand MFInFlag = SDOperand(RemNode, 0); |       SDOperand MFInFlag = SDOperand(RemNode, 0); | ||||||
|       return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag); |       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<GlobalAddressSDNode>(Callee)) || | ||||||
|  |              (isa<ExternalSymbolSDNode>(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 |   // Select the default instruction | ||||||
|   | |||||||
| @@ -43,8 +43,6 @@ getTargetNodeName(unsigned Opcode) const | |||||||
|     case MipsISD::Hi      : return "MipsISD::Hi"; |     case MipsISD::Hi      : return "MipsISD::Hi"; | ||||||
|     case MipsISD::Lo      : return "MipsISD::Lo"; |     case MipsISD::Lo      : return "MipsISD::Lo"; | ||||||
|     case MipsISD::Ret     : return "MipsISD::Ret"; |     case MipsISD::Ret     : return "MipsISD::Ret"; | ||||||
|     case MipsISD::Add       : return "MipsISD::Add"; |  | ||||||
|     case MipsISD::LoadAddr  : return "MipsISD::LoadAddr"; |  | ||||||
|     default               : return NULL; |     default               : return NULL; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) | |||||||
| { | { | ||||||
|   SDOperand ResNode; |   SDOperand ResNode; | ||||||
|   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); |   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | ||||||
|  |  | ||||||
|   SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); |   SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); | ||||||
|  |   bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_); | ||||||
|  |  | ||||||
|   // On PIC code global addresses are loaded with "la" instruction |   SDOperand HiPart;  | ||||||
|   if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) { |   if (!isPIC) { | ||||||
|     const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag); |     const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32); | ||||||
|     SDOperand Ops[] = { GA }; |     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); | ||||||
|  |  | ||||||
|  |   // 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<Function>(GV)))) | ||||||
|  |     return HiPart; | ||||||
|  |  | ||||||
|     SDOperand Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1); |  | ||||||
|   SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); |   SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); | ||||||
|  |   ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo); | ||||||
|     SDOperand InFlag = Hi.getValue(1); |  | ||||||
|     ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag); |  | ||||||
|   } else |  | ||||||
|     ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA); |  | ||||||
|  |  | ||||||
|   return ResNode; |   return ResNode; | ||||||
| } | } | ||||||
| @@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG) | |||||||
| /// LowerCCCCallTo - functions arguments are copied from virtual | /// LowerCCCCallTo - functions arguments are copied from virtual | ||||||
| /// regs to (physical regs)/(stack frame), CALLSEQ_START and | /// regs to (physical regs)/(stack frame), CALLSEQ_START and | ||||||
| /// CALLSEQ_END are emitted. | /// CALLSEQ_END are emitted. | ||||||
| /// TODO: isVarArg, isTailCall, sret, GOT, linkage types. | /// TODO: isVarArg, isTailCall, sret. | ||||||
| SDOperand MipsTargetLowering:: | SDOperand MipsTargetLowering:: | ||||||
| LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)  | LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)  | ||||||
| { | { | ||||||
| @@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) | |||||||
|   SmallVector<SDOperand, 8> MemOpChains; |   SmallVector<SDOperand, 8> MemOpChains; | ||||||
|  |  | ||||||
|   SDOperand StackPtr; |   SDOperand StackPtr; | ||||||
|   unsigned LastStackLoc=0; |   int LastStackLoc=0; | ||||||
|  |  | ||||||
|   // Walk the register/memloc assignments, inserting copies/loads. |   // Walk the register/memloc assignments, inserting copies/loads. | ||||||
|   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | ||||||
| @@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     // Arguments that can be passed on register,  |     // Arguments that can be passed on register must be kept at  | ||||||
|     // must be kept at RegsToPass vector |     // RegsToPass vector | ||||||
|     if (VA.isRegLoc()) { |     if (VA.isRegLoc()) { | ||||||
|       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); |       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | ||||||
|     } else { |     } 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<MipsFunctionInfo>(); |  | ||||||
|       MFI->CreateFixedObject(4, LastStackLoc); |  | ||||||
|       MipsFI->setGPStackOffset(LastStackLoc); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Transform all store nodes into one single node because |   // Transform all store nodes into one single node because | ||||||
|   // all store nodes are independent of each other. |   // all store nodes are independent of each other. | ||||||
|   if (!MemOpChains.empty())      |   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 |   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every | ||||||
|   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol  |   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol  | ||||||
|   // node so that legalize doesn't hack it. Otherwise we have an indirect call, |   // node so that legalize doesn't hack it.  | ||||||
|   // if PIC is used, the call must use register GP |  | ||||||
|   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))  |   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))  | ||||||
|     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); |     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); | ||||||
|   else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) |   else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) | ||||||
|     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); |     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); | ||||||
|  |  | ||||||
|  |  | ||||||
|   // MipsJmpLink = #chain, #target_address, #opt_in_flags... |   // MipsJmpLink = #chain, #target_address, #opt_in_flags... | ||||||
|   //             = Chain, Callee, Reg#1, Reg#2, ...   |   //             = 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()); |   Chain  = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size()); | ||||||
|   InFlag = Chain.getValue(1); |   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<MipsFunctionInfo>(); | ||||||
|  |       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. |   // Create the CALLSEQ_END node. | ||||||
|   NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); |   NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); | ||||||
|   Ops.clear(); |   Ops.clear(); | ||||||
| @@ -389,8 +413,9 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall, | |||||||
|     ResultVals.push_back(Chain.getValue(0)); |     ResultVals.push_back(Chain.getValue(0)); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   // Merge everything together with a MERGE_VALUES node. |  | ||||||
|   ResultVals.push_back(Chain); |   ResultVals.push_back(Chain); | ||||||
|  |  | ||||||
|  |   // Merge everything together with a MERGE_VALUES node. | ||||||
|   return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(), |   return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(), | ||||||
|                      &ResultVals[0], ResultVals.size()).Val;                        |                      &ResultVals[0], ResultVals.size()).Val;                        | ||||||
| } | } | ||||||
|   | |||||||
| @@ -38,13 +38,7 @@ namespace llvm { | |||||||
|       Lo,  |       Lo,  | ||||||
|  |  | ||||||
|       // Return  |       // Return  | ||||||
|       Ret, |       Ret | ||||||
|  |  | ||||||
|       // Need to support addition with a input flag |  | ||||||
|       Add, |  | ||||||
|  |  | ||||||
|       // Used on PIC Code to load global addresses |  | ||||||
|       LoadAddr |  | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,21 +22,12 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; | |||||||
| def MipsJmpLink     : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, | def MipsJmpLink     : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, | ||||||
|                              SDNPOutFlag]>; |                              SDNPOutFlag]>; | ||||||
|  |  | ||||||
| // Hi and Lo nodes are created to let easy manipulation of 16-bit when | // Hi and Lo nodes are used to handle global addresses. Used on  | ||||||
| // handling 32-bit immediates. They are used on MipsISelLowering to | // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol  | ||||||
| // lower stuff like GlobalAddress, ExternalSymbol, ... on static model | // static model. (nothing to do with Mips Registers Hi and Lo) | ||||||
| // This two nodes have nothing to do with Mips Registers Hi and Lo. |  | ||||||
| def MipsHi  : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>; | def MipsHi  : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>; | ||||||
| def MipsLo  : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; | 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>; |  | ||||||
|  |  | ||||||
| // Return | // Return | ||||||
| def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; | def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; | ||||||
| def MipsRet     : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, | def MipsRet     : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, | ||||||
| @@ -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 | // are used, we have the same behavior, but get also a bunch of warnings | ||||||
| // from the assembler. | // from the assembler. | ||||||
| def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg), | 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), | def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc), | ||||||
|                               ".cprestore $loc", []>; |                               ".cprestore $loc\n", []>; | ||||||
|  |  | ||||||
| // 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", []>; |  | ||||||
|  |  | ||||||
| //===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||
| // Instruction definition | // 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. | // ADDiu just accept 16-bit immediates but we handle this on Pat's. | ||||||
| // immZExt32 is used here so it can match GlobalAddress immediates. | // 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 ADDi    : ArithI<0x08, "addi",  add, simm16, immSExt16>; | ||||||
| def MUL     : ArithR<0x1c, 0x02, "mul", mul, IIImul>; | def MUL     : ArithR<0x1c, 0x02, "mul", mul, IIImul>; | ||||||
| def ADDu    : ArithR<0x00, 0x21, "addu", add, IIAlu>; | def ADDu    : ArithR<0x00, 0x21, "addu", add, IIAlu>; | ||||||
| def SUBu    : ArithR<0x00, 0x23, "subu", sub, IIAlu>; | def SUBu    : ArithR<0x00, 0x23, "subu", sub, IIAlu>; | ||||||
| def ADD     : ArithOverflowR<0x00, 0x20, "add">; | def ADD     : ArithOverflowR<0x00, 0x20, "add">; | ||||||
| def SUB     : ArithOverflowR<0x00, 0x22, "sub">; | 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 | // Logical | ||||||
| def AND     : LogicR<0x24, "and", and>; | def AND     : LogicR<0x24, "and", and>; | ||||||
| @@ -485,6 +466,12 @@ def MTLO    : MoveFromTo<0x13, "mtlo">; | |||||||
| //def CLO     : CountLeading<0x21, "clo">; | //def CLO     : CountLeading<0x21, "clo">; | ||||||
| //def CLZ     : CountLeading<0x20, "clz">; | //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 | // No operation | ||||||
| let addr=0 in | let addr=0 in | ||||||
| def NOP     : FJ<0, (outs), (ins), "nop", [], IIAlu>; | def NOP     : FJ<0, (outs), (ins), "nop", [], IIAlu>; | ||||||
| @@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst), | |||||||
| // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable | // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable | ||||||
| def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; | def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; | ||||||
| def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, 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)>; |           (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; | ||||||
| def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>; |  | ||||||
|  |  | ||||||
| // Mips does not have not, so we increase the operation | // Mips does not have not, so we increase the operation | ||||||
| def : Pat<(not CPURegs:$in), | 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), | def : Pat<(truncstorei1 CPURegs:$src, addr:$addr), | ||||||
|            (SB CPURegs:$src, addr:$addr)>; |            (SB CPURegs:$src, addr:$addr)>; | ||||||
|  |  | ||||||
|  | // some peepholes | ||||||
|  | def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; | ||||||
|  |  | ||||||
| /// | /// | ||||||
| /// brcond patterns | /// brcond patterns | ||||||
| /// | /// | ||||||
|   | |||||||
| @@ -33,11 +33,6 @@ private: | |||||||
|   /// the Return Address must be saved |   /// the Return Address must be saved | ||||||
|   int RAStackOffset; |   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 |   /// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset | ||||||
|   struct MipsFIHolder { |   struct MipsFIHolder { | ||||||
|  |  | ||||||
| @@ -48,6 +43,13 @@ private: | |||||||
|       : FI(FrameIndex), SPOffset(StackPointerOffset) {} |       : 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, |   // On LowerFORMAL_ARGUMENTS the stack size is unknown, | ||||||
|   // so the Stack Pointer Offset calculation of "not in  |   // so the Stack Pointer Offset calculation of "not in  | ||||||
|   // register arguments" must be postponed to emitPrologue.  |   // register arguments" must be postponed to emitPrologue.  | ||||||
| @@ -64,7 +66,7 @@ private: | |||||||
|  |  | ||||||
| public: | public: | ||||||
|   MipsFunctionInfo(MachineFunction& MF)  |   MipsFunctionInfo(MachineFunction& MF)  | ||||||
|   : FPStackOffset(0), RAStackOffset(0),  |   : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1), | ||||||
|     HasLoadArgs(false), HasStoreVarArgs(false) |     HasLoadArgs(false), HasStoreVarArgs(false) | ||||||
|   {} |   {} | ||||||
|  |  | ||||||
| @@ -74,8 +76,10 @@ public: | |||||||
|   int getRAStackOffset() const { return RAStackOffset; } |   int getRAStackOffset() const { return RAStackOffset; } | ||||||
|   void setRAStackOffset(int Off) { RAStackOffset = Off; } |   void setRAStackOffset(int Off) { RAStackOffset = Off; } | ||||||
|  |  | ||||||
|   int getGPStackOffset() const { return GPStackOffset; } |   int getGPStackOffset() const { return GPHolder.SPOffset; } | ||||||
|   void setGPStackOffset(int Off) { GPStackOffset = Off; } |   int getGPFI() const { return GPHolder.FI; } | ||||||
|  |   void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; } | ||||||
|  |   void setGPFI(int FI) { GPHolder.FI = FI; } | ||||||
|  |  | ||||||
|   int getTopSavedRegOffset() const {  |   int getTopSavedRegOffset() const {  | ||||||
|     return (RAStackOffset > FPStackOffset) ?  |     return (RAStackOffset > FPStackOffset) ?  | ||||||
|   | |||||||
| @@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const | |||||||
|   return NewMI; |   return NewMI; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | MachineInstr *MipsRegisterInfo:: | ||||||
|  | foldMemoryOperand(MachineInstr* MI, unsigned OpNum, | ||||||
|  |                                 MachineInstr* LoadMI) const { | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
| //===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||||
| // | // | ||||||
| // Callee Saved Registers methods  | // Callee Saved Registers methods  | ||||||
| @@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const | |||||||
|   if ((isPIC) && (MFI->hasCalls())) |   if ((isPIC) && (MFI->hasCalls())) | ||||||
|     BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE)) |     BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE)) | ||||||
|       .addImm(MipsFI->getGPStackOffset()); |       .addImm(MipsFI->getGPStackOffset()); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void MipsRegisterInfo:: | void MipsRegisterInfo:: | ||||||
| @@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const | |||||||
|  |  | ||||||
| void MipsRegisterInfo:: | void MipsRegisterInfo:: | ||||||
| processFunctionBeforeFrameFinalized(MachineFunction &MF) const { | 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<MipsFunctionInfo>(); | ||||||
|  |     #ifndef NDEBUG | ||||||
|  |     DOUT << "processFunctionBeforeFrameFinalized\n"; | ||||||
|  |     DOUT << "GPOffset :" << MipsFI->getGPStackOffset() << "\n"; | ||||||
|  |     DOUT << "FI :" << MipsFI->getGPFI() << "\n"; | ||||||
|  |     #endif | ||||||
|  |     MFI->setObjectOffset(MipsFI->getGPFI(), MipsFI->getGPStackOffset()); | ||||||
|  |   }     | ||||||
| } | } | ||||||
|  |  | ||||||
| unsigned MipsRegisterInfo:: | unsigned MipsRegisterInfo:: | ||||||
|   | |||||||
| @@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { | |||||||
|                                   int FrameIndex) const; |                                   int FrameIndex) const; | ||||||
|  |  | ||||||
|   MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, |   MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, | ||||||
|                                   MachineInstr* LoadMI) const { |                                   MachineInstr* LoadMI) const; | ||||||
|     return 0; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |   void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | ||||||
|           unsigned DestReg, unsigned SrcReg, |           unsigned DestReg, unsigned SrcReg, | ||||||
|   | |||||||
| @@ -35,6 +35,9 @@ createTargetAsmInfo() const | |||||||
| // On function prologue, the stack is created by decrementing | // On function prologue, the stack is created by decrementing | ||||||
| // its pointer. Once decremented, all references are done with positive | // its pointer. Once decremented, all references are done with positive | ||||||
| // offset from the stack/frame pointer, so StackGrowsUp is used. | // offset from the stack/frame pointer, so StackGrowsUp is used. | ||||||
|  | // When using CodeModel::Large the behaviour  | ||||||
|  | // | ||||||
|  | //  | ||||||
| MipsTargetMachine:: | MipsTargetMachine:: | ||||||
| MipsTargetMachine(const Module &M, const std::string &FS):  | MipsTargetMachine(const Module &M, const std::string &FS):  | ||||||
|   Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"),  |   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) |   if (getRelocationModel() != Reloc::Static) | ||||||
|     setRelocationModel(Reloc::PIC_);   |     setRelocationModel(Reloc::PIC_);   | ||||||
|  |   if (getCodeModel() == CodeModel::Default) | ||||||
|  |     setCodeModel(CodeModel::Small); | ||||||
| } | } | ||||||
|  |  | ||||||
| // return 0 and must specify -march to gen MIPS code. | // return 0 and must specify -march to gen MIPS code. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user