ELF / PIC requires GOT be in the EBX register during calls via PLT GOT pointer.
[oota-llvm.git] / lib / Target / X86 / X86ISelLowering.cpp
index 0dce6fd6ed30c2fad66d6e919c86910593637e63..839eb8a8ab2a578ca375d498984765938883cb34 100644 (file)
@@ -777,6 +777,10 @@ SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
     }
   }
 
+  // Sanity check: we haven't seen NumSRetBytes > 4
+  assert((NumSRetBytes<=4) &&
+         "Too much space for struct-return pointer requested");
+    
   if (!MemOpChains.empty())
     Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
                         &MemOpChains[0], MemOpChains.size());
@@ -790,6 +794,8 @@ SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
     InFlag = Chain.getValue(1);
   }
 
+  // ELF / PIC requires GOT in the EBX register before function calls via PLT
+  // GOT pointer.
   if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
       Subtarget->isPICStyleGOT()) {
     Chain = DAG.getCopyToReg(Chain, X86::EBX,
@@ -821,6 +827,11 @@ SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                   RegsToPass[i].second.getValueType()));
+
+  // Add an implicit use GOT pointer in EBX.
+  if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
+      Subtarget->isPICStyleGOT())
+    Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy()));
   
   if (InFlag.Val)
     Ops.push_back(InFlag);
@@ -1542,11 +1553,12 @@ X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG,
       default: assert(0 && "Unhandled argument type!");
       case MVT::i8:
       case MVT::i16:
-      case MVT::i32:
-       unsigned RegToUse = GPRArgRegs[ObjectVT-MVT::i8][GPRInd][NumIntRegs];
-       Reg = AddLiveIn(MF, RegToUse, GPRClasses[ObjectVT-MVT::i8]);
-       ArgValue = DAG.getCopyFromReg(Root, Reg, ObjectVT);
-       break;
+      case MVT::i32: {
+        unsigned RegToUse = GPRArgRegs[ObjectVT-MVT::i8][GPRInd][NumIntRegs];
+        Reg = AddLiveIn(MF, RegToUse, GPRClasses[ObjectVT-MVT::i8]);
+        ArgValue = DAG.getCopyFromReg(Root, Reg, ObjectVT);
+        break;
+      }
       case MVT::v16i8:
       case MVT::v8i16:
       case MVT::v4i32:
@@ -1783,6 +1795,8 @@ SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
     Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
 
+  // ELF / PIC requires GOT in the EBX register before function calls via PLT
+  // GOT pointer.
   if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
       Subtarget->isPICStyleGOT()) {
     Chain = DAG.getCopyToReg(Chain, X86::EBX,
@@ -1804,6 +1818,11 @@ SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
     Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                   RegsToPass[i].second.getValueType()));
 
+  // Add an implicit use GOT pointer in EBX.
+  if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
+      Subtarget->isPICStyleGOT())
+    Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy()));
+
   if (InFlag.Val)
     Ops.push_back(InFlag);
 
@@ -1939,25 +1958,6 @@ SDOperand X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) {
 
 
 
-std::pair<SDOperand, SDOperand> X86TargetLowering::
-LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
-                        SelectionDAG &DAG) {
-  SDOperand Result;
-  if (Depth)        // Depths > 0 not supported yet!
-    Result = DAG.getConstant(0, getPointerTy());
-  else {
-    SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
-    if (!isFrameAddress)
-      // Just load the return address
-      Result = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI,
-                           NULL, 0);
-    else
-      Result = DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI,
-                           DAG.getConstant(4, getPointerTy()));
-  }
-  return std::make_pair(Result, Chain);
-}
-
 /// translateX86CC - do a one to one translation of a ISD::CondCode to the X86
 /// specific condition code. It returns a false if it cannot do a direct
 /// translation. X86CC is the translated CondCode.  LHS/RHS are modified as
@@ -4620,6 +4620,26 @@ X86TargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG) {
   }
 }
 
+SDOperand X86TargetLowering::LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) {
+  // Depths > 0 not supported yet!
+  if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
+    return SDOperand();
+  
+  // Just load the return address
+  SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
+  return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0);
+}
+
+SDOperand X86TargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) {
+  // Depths > 0 not supported yet!
+  if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
+    return SDOperand();
+    
+  SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
+  return DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI, 
+                     DAG.getConstant(4, getPointerTy()));
+}
+
 /// LowerOperation - Provide custom lowering hooks for some operations.
 ///
 SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
@@ -4653,6 +4673,8 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
   case ISD::READCYCLECOUNTER:   return LowerREADCYCLCECOUNTER(Op, DAG);
   case ISD::VASTART:            return LowerVASTART(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
+  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
+  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
   }
 }