/// LowerCallResult - Lower the result values of a call into the
/// appropriate copies out of appropriate physical registers.
///
SDValue
MSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
                                      CallingConv::ID CallConv, bool isVarArg,
                                      const SmallVectorImpl<ISD::InputArg> &Ins,
                                      DebugLoc dl, SelectionDAG &DAG,
                                      SmallVectorImpl<SDValue> &InVals) const {

  // Assign locations to each value returned by this call.
  SmallVector<CCValAssign, 16> RVLocs;
  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
		 getTargetMachine(), RVLocs, *DAG.getContext());

  CCInfo.AnalyzeCallResult(Ins, RetCC_MSP430);

  // Copy all of the result registers out of their specified physreg.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
                               RVLocs[i].getValVT(), InFlag).getValue(1);
    InFlag = Chain.getValue(2);
    InVals.push_back(Chain.getValue(0));
  }

  return Chain;
}
std::vector<SDOperand>
IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
  std::vector<SDOperand> ArgValues;
  //
  // add beautiful description of IA64 stack frame format
  // here (from intel 24535803.pdf most likely)
  //
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
  
  GP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
  SP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
  RP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
  
  MachineBasicBlock& BB = MF.front();

  unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35,
                         IA64::r36, IA64::r37, IA64::r38, IA64::r39};

  unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
                        IA64::F12,IA64::F13,IA64::F14, IA64::F15};

  unsigned argVreg[8];
  unsigned argPreg[8];
  unsigned argOpc[8];

  unsigned used_FPArgs = 0; // how many FP args have been used so far?

  unsigned ArgOffset = 0;
  int count = 0;

  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
    {
      SDOperand newroot, argt;
      if(count < 8) { // need to fix this logic? maybe.

        switch (getValueType(I->getType())) {
          default:
            assert(0 && "ERROR in LowerArgs: can't lower this type of arg.\n"); 
          case MVT::f32:
            // fixme? (well, will need to for weird FP structy stuff,
            // see intel ABI docs)
          case MVT::f64:
//XXX            BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
            MF.getRegInfo().addLiveIn(args_FP[used_FPArgs]);
            // mark this reg as liveIn
            // floating point args go into f8..f15 as-needed, the increment
            argVreg[count] =                              // is below..:
            MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::f64));
            // FP args go into f8..f15 as needed: (hence the ++)
            argPreg[count] = args_FP[used_FPArgs++];
            argOpc[count] = IA64::FMOV;
            argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), argVreg[count],
                                                MVT::f64);
            if (I->getType() == Type::FloatTy)
              argt = DAG.getNode(ISD::FP_ROUND, MVT::f32, argt,
                                 DAG.getIntPtrConstant(0));
            break;
          case MVT::i1: // NOTE: as far as C abi stuff goes,
                        // bools are just boring old ints
          case MVT::i8:
          case MVT::i16:
          case MVT::i32:
          case MVT::i64:
//XXX            BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
            MF.getRegInfo().addLiveIn(args_int[count]);
            // mark this register as liveIn
            argVreg[count] =
            MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
            argPreg[count] = args_int[count];
            argOpc[count] = IA64::MOV;
            argt = newroot =
              DAG.getCopyFromReg(DAG.getRoot(), argVreg[count], MVT::i64);
            if ( getValueType(I->getType()) != MVT::i64)
              argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()),
                  newroot);
            break;
        }
      } else { // more than 8 args go into the frame
        // Create the frame index object for this incoming parameter...
        ArgOffset = 16 + 8 * (count - 8);
        int FI = MFI->CreateFixedObject(8, ArgOffset);

        // Create the SelectionDAG nodes corresponding to a load
        //from this parameter
        SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
        argt = newroot = DAG.getLoad(getValueType(I->getType()),
                                     DAG.getEntryNode(), FIN, NULL, 0);
      }
      ++count;
      DAG.setRoot(newroot.getValue(1));
      ArgValues.push_back(argt);
    }


  // Create a vreg to hold the output of (what will become)
  // the "alloc" instruction
  VirtGPR = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
  BuildMI(&BB, TII->get(IA64::PSEUDO_ALLOC), VirtGPR);
  // we create a PSEUDO_ALLOC (pseudo)instruction for now
/*
  BuildMI(&BB, IA64::IDEF, 0, IA64::r1);

  // hmm:
  BuildMI(&BB, IA64::IDEF, 0, IA64::r12);
  BuildMI(&BB, IA64::IDEF, 0, IA64::rp);
  // ..hmm.
  
  BuildMI(&BB, IA64::MOV, 1, GP).addReg(IA64::r1);

  // hmm:
  BuildMI(&BB, IA64::MOV, 1, SP).addReg(IA64::r12);
  BuildMI(&BB, IA64::MOV, 1, RP).addReg(IA64::rp);
  // ..hmm.
*/

  unsigned tempOffset=0;

  // if this is a varargs function, we simply lower llvm.va_start by
  // pointing to the first entry
  if(F.isVarArg()) {
    tempOffset=0;
    VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset);
  }

  // here we actually do the moving of args, and store them to the stack
  // too if this is a varargs function:
  for (int i = 0; i < count && i < 8; ++i) {
    BuildMI(&BB, TII->get(argOpc[i]), argVreg[i]).addReg(argPreg[i]);
    if(F.isVarArg()) {
      // if this is a varargs function, we copy the input registers to the stack
      int FI = MFI->CreateFixedObject(8, tempOffset);
      tempOffset+=8;   //XXX: is it safe to use r22 like this?
      BuildMI(&BB, TII->get(IA64::MOV), IA64::r22).addFrameIndex(FI);
      // FIXME: we should use st8.spill here, one day
      BuildMI(&BB, TII->get(IA64::ST8), IA64::r22).addReg(argPreg[i]);
    }
  }

  // Finally, inform the code generator which regs we return values in.
  // (see the ISD::RET: case in the instruction selector)
  switch (getValueType(F.getReturnType())) {
  default: assert(0 && "i have no idea where to return this type!");
  case MVT::isVoid: break;
  case MVT::i1:
  case MVT::i8:
  case MVT::i16:
  case MVT::i32:
  case MVT::i64:
    MF.getRegInfo().addLiveOut(IA64::r8);
    break;
  case MVT::f32:
  case MVT::f64:
    MF.getRegInfo().addLiveOut(IA64::F8);
    break;
  }

  return ArgValues;
}
Example #3
0
/// LowerCCCCallTo - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: sret.
SDValue
MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
                                     CallingConv::ID CallConv, bool isVarArg,
                                     bool isTailCall,
                                     const SmallVectorImpl<ISD::OutputArg>
                                       &Outs,
                                     const SmallVectorImpl<SDValue> &OutVals,
                                     const SmallVectorImpl<ISD::InputArg> &Ins,
                                     DebugLoc dl, SelectionDAG &DAG,
                                     SmallVectorImpl<SDValue> &InVals) const {
  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());

  CCInfo.AnalyzeCallOperands(Outs, CC_MSP430);

  // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = CCInfo.getNextStackOffset();

  Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
                                                      getPointerTy(), true));

  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
  SmallVector<SDValue, 12> MemOpChains;
  SDValue StackPtr;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    SDValue Arg = OutVals[i];

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
      default: llvm_unreachable("Unknown loc info!");
      case CCValAssign::Full: break;
      case CCValAssign::SExt:
        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
        break;
      case CCValAssign::ZExt:
        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
        break;
      case CCValAssign::AExt:
        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
        break;
    }

    // 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 {
      assert(VA.isMemLoc());

      if (StackPtr.getNode() == 0)
        StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy());

      SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
                                   StackPtr,
                                   DAG.getIntPtrConstant(VA.getLocMemOffset()));


      MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                         MachinePointerInfo(),false, false, 0));
    }
  }

  // Transform all store nodes into one single node because all store nodes are
  // independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emitted instructions must be stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
                             RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16);

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
                                  RegsToPass[i].second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(Chain,
                             DAG.getConstant(NumBytes, getPointerTy(), true),
                             DAG.getConstant(0, getPointerTy(), true),
                             InFlag);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
                         DAG, InVals);
}
Example #4
0
/// LowerCCCArguments - transform physical registers into virtual registers and
/// generate load operations for arguments places on the stack.
// FIXME: struct return stuff
// FIXME: varargs
SDValue
SystemZTargetLowering::LowerCCCArguments(SDValue Chain,
        CallingConv::ID CallConv,
        bool isVarArg,
        const SmallVectorImpl<ISD::InputArg>
        &Ins,
        DebugLoc dl,
        SelectionDAG &DAG,
        SmallVectorImpl<SDValue> &InVals) {

    MachineFunction &MF = DAG.getMachineFunction();
    MachineFrameInfo *MFI = MF.getFrameInfo();
    MachineRegisterInfo &RegInfo = MF.getRegInfo();

    // Assign locations to all of the incoming arguments.
    SmallVector<CCValAssign, 16> ArgLocs;
    CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                   ArgLocs, *DAG.getContext());
    CCInfo.AnalyzeFormalArguments(Ins, CC_SystemZ);

    if (isVarArg)
        report_fatal_error("Varargs not supported yet");

    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
        SDValue ArgValue;
        CCValAssign &VA = ArgLocs[i];
        EVT LocVT = VA.getLocVT();
        if (VA.isRegLoc()) {
            // Arguments passed in registers
            TargetRegisterClass *RC;
            switch (LocVT.getSimpleVT().SimpleTy) {
            default:
#ifndef NDEBUG
                errs() << "LowerFormalArguments Unhandled argument type: "
                       << LocVT.getSimpleVT().SimpleTy
                       << "\n";
#endif
                llvm_unreachable(0);
            case MVT::i64:
                RC = SystemZ::GR64RegisterClass;
                break;
            case MVT::f32:
                RC = SystemZ::FP32RegisterClass;
                break;
            case MVT::f64:
                RC = SystemZ::FP64RegisterClass;
                break;
            }

            unsigned VReg = RegInfo.createVirtualRegister(RC);
            RegInfo.addLiveIn(VA.getLocReg(), VReg);
            ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, LocVT);
        } else {
            // Sanity check
            assert(VA.isMemLoc());

            // Create the nodes corresponding to a load from this parameter slot.
            // Create the frame index object for this incoming parameter...
            int FI = MFI->CreateFixedObject(LocVT.getSizeInBits()/8,
                                            VA.getLocMemOffset(), true, false);

            // Create the SelectionDAG nodes corresponding to a load
            // from this parameter
            SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
            ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN,
                                   PseudoSourceValue::getFixedStack(FI), 0,
                                   false, false, 0);
        }

        // If this is an 8/16/32-bit value, it is really passed promoted to 64
        // bits. Insert an assert[sz]ext to capture this, then truncate to the
        // right size.
        if (VA.getLocInfo() == CCValAssign::SExt)
            ArgValue = DAG.getNode(ISD::AssertSext, dl, LocVT, ArgValue,
                                   DAG.getValueType(VA.getValVT()));
        else if (VA.getLocInfo() == CCValAssign::ZExt)
            ArgValue = DAG.getNode(ISD::AssertZext, dl, LocVT, ArgValue,
                                   DAG.getValueType(VA.getValVT()));

        if (VA.getLocInfo() != CCValAssign::Full)
            ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);

        InVals.push_back(ArgValue);
    }

    return Chain;
}
SDValue
BlackfinTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
                                  CallingConv::ID CallConv, bool isVarArg,
                                  bool &isTailCall,
                                  const SmallVectorImpl<ISD::OutputArg> &Outs,
                                  const SmallVectorImpl<SDValue> &OutVals,
                                  const SmallVectorImpl<ISD::InputArg> &Ins,
                                  DebugLoc dl, SelectionDAG &DAG,
                                  SmallVectorImpl<SDValue> &InVals) const {
  // Blackfin target does not yet support tail call optimization.
  isTailCall = false;

  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
		 DAG.getTarget(), ArgLocs, *DAG.getContext());
  CCInfo.AllocateStack(12, 4);  // ABI requires 12 bytes stack space
  CCInfo.AnalyzeCallOperands(Outs, CC_Blackfin);

  // Get the size of the outgoing arguments stack space requirement.
  unsigned ArgsSize = CCInfo.getNextStackOffset();

  Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));
  SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
  SmallVector<SDValue, 8> MemOpChains;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue Arg = OutVals[i];

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    default: llvm_unreachable("Unknown loc info!");
    case CCValAssign::Full: break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    }

    // 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 {
      assert(VA.isMemLoc() && "CCValAssign must be RegLoc or MemLoc");
      int Offset = VA.getLocMemOffset();
      assert(Offset%4 == 0 && "Unaligned LocMemOffset");
      assert(VA.getLocVT()==MVT::i32 && "Illegal CCValAssign type");
      SDValue SPN = DAG.getCopyFromReg(Chain, dl, BF::SP, MVT::i32);
      SDValue OffsetN = DAG.getIntPtrConstant(Offset);
      OffsetN = DAG.getNode(ISD::ADD, dl, MVT::i32, SPN, OffsetN);
      MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, OffsetN,
                                         MachinePointerInfo(),false, false, 0));
    }
  }

  // Transform all store nodes into one single node because
  // all store nodes are independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token
  // chain and flag operands which copy the outgoing args into registers.
  // The InFlag in necessary since all emitted instructions must be
  // stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
                             RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);

  std::vector<EVT> NodeTys;
  NodeTys.push_back(MVT::Other);   // Returns a chain
  NodeTys.push_back(MVT::Glue);    // Returns a flag for retval copy to use.
  SDValue Ops[] = { Chain, Callee, InFlag };
  Chain = DAG.getNode(BFISD::CALL, dl, NodeTys, Ops,
                      InFlag.getNode() ? 3 : 2);
  InFlag = Chain.getValue(1);

  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true),
                             DAG.getIntPtrConstant(0, true), InFlag);
  InFlag = Chain.getValue(1);

  // Assign locations to each value returned by this call.
  SmallVector<CCValAssign, 16> RVLocs;
  CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(),
		 DAG.getTarget(), RVLocs, *DAG.getContext());

  RVInfo.AnalyzeCallResult(Ins, RetCC_Blackfin);

  // Copy all of the result registers out of their specified physreg.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    CCValAssign &RV = RVLocs[i];
    unsigned Reg = RV.getLocReg();

    Chain = DAG.getCopyFromReg(Chain, dl, Reg,
                               RVLocs[i].getLocVT(), InFlag);
    SDValue Val = Chain.getValue(0);
    InFlag = Chain.getValue(2);
    Chain = Chain.getValue(1);

    // Callee is responsible for extending any i16 return values.
    switch (RV.getLocInfo()) {
    case CCValAssign::SExt:
      Val = DAG.getNode(ISD::AssertSext, dl, RV.getLocVT(), Val,
                        DAG.getValueType(RV.getValVT()));
      break;
    case CCValAssign::ZExt:
      Val = DAG.getNode(ISD::AssertZext, dl, RV.getLocVT(), Val,
                        DAG.getValueType(RV.getValVT()));
      break;
    default:
      break;
    }

    // Truncate to valtype
    if (RV.getLocInfo() != CCValAssign::Full)
      Val = DAG.getNode(ISD::TRUNCATE, dl, RV.getValVT(), Val);
    InVals.push_back(Val);
  }

  return Chain;
}
Example #6
0
SDValue
Cpu0TargetLowering::LowerReturn(SDValue Chain,
                                CallingConv::ID CallConv, bool isVarArg,
                                const SmallVectorImpl<ISD::OutputArg> &Outs,
                                const SmallVectorImpl<SDValue> &OutVals,
                                SDLoc DL, SelectionDAG &DAG) const {

  // CCValAssign - represent the assignment of
  // the return value to a location
  SmallVector<CCValAssign, 16> RVLocs;

  // CCState - Info about the registers and stack slot.
  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
		 getTargetMachine(), RVLocs, *DAG.getContext());

  // Analize return values.
  CCInfo.AnalyzeReturn(Outs, RetCC_Cpu0);

  SDValue Flag;
  SmallVector<SDValue, 4> RetOps(1, Chain);

  // Copy the result values into the output registers.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    CCValAssign &VA = RVLocs[i];
    assert(VA.isRegLoc() && "Can only return in registers!");

    Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);

    // Guarantee that all emitted copies are stuck together with flags.
    Flag = Chain.getValue(1);
    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
  }

#if 1 // structure return begin. Without this, it will use $3 instead of $2 
  // as return register. The cpu0 ABIs for returning structs by value requires 
  // that we copy the sret argument into $v0 for the return. We saved the 
  // argument into a virtual register in the entry block, so now we copy the 
  // value out and into $v0.
  if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
    MachineFunction &MF      = DAG.getMachineFunction();
    Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>();
    unsigned Reg = Cpu0FI->getSRetReturnReg();

    if (!Reg)
      llvm_unreachable("sret virtual register not created in the entry block");
    SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy());

    Chain = DAG.getCopyToReg(Chain, DL, Cpu0::V0, Val, Flag);
    Flag = Chain.getValue(1);
    RetOps.push_back(DAG.getRegister(Cpu0::V0, getPointerTy()));
  }
#endif // structure return end

  RetOps[0] = Chain;  // Update chain.

  // Add the flag if we have it.
  if (Flag.getNode())
    RetOps.push_back(Flag);

  // Return on Cpu0 is always a "ret $lr"
  return DAG.getNode(Cpu0ISD::Ret, DL, MVT::Other, RetOps);
}
Example #7
0
/// LowerFormalArguments - transform physical registers into
/// virtual registers and generate load operations for
/// arguments places on the stack.
SDValue MBlazeTargetLowering::
LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
                     const SmallVectorImpl<ISD::InputArg> &Ins,
                     DebugLoc dl, SelectionDAG &DAG,
                     SmallVectorImpl<SDValue> &InVals) const {
    MachineFunction &MF = DAG.getMachineFunction();
    MachineFrameInfo *MFI = MF.getFrameInfo();
    MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();

    unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
    MBlazeFI->setVarArgsFrameIndex(0);

    // Used with vargs to acumulate store chains.
    std::vector<SDValue> OutChains;

    // Keep track of the last register used for arguments
    unsigned ArgRegEnd = 0;

    // Assign locations to all of the incoming arguments.
    SmallVector<CCValAssign, 16> ArgLocs;
    CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                   ArgLocs, *DAG.getContext());

    CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze);
    SDValue StackPtr;

    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
        CCValAssign &VA = ArgLocs[i];

        // Arguments stored on registers
        if (VA.isRegLoc()) {
            MVT RegVT = VA.getLocVT();
            ArgRegEnd = VA.getLocReg();
            TargetRegisterClass *RC = 0;

            if (RegVT == MVT::i32)
                RC = MBlaze::GPRRegisterClass;
            else if (RegVT == MVT::f32)
                RC = MBlaze::GPRRegisterClass;
            else
                llvm_unreachable("RegVT not supported by LowerFormalArguments");

            // Transform the arguments stored on
            // physical registers into virtual ones
            unsigned Reg = MF.addLiveIn(ArgRegEnd, RC);
            SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);

            // If this is an 8 or 16-bit value, it has been passed promoted
            // to 32 bits.  Insert an assert[sz]ext to capture this, then
            // truncate to the right size. If if is a floating point value
            // then convert to the correct type.
            if (VA.getLocInfo() != CCValAssign::Full) {
                unsigned Opcode = 0;
                if (VA.getLocInfo() == CCValAssign::SExt)
                    Opcode = ISD::AssertSext;
                else if (VA.getLocInfo() == CCValAssign::ZExt)
                    Opcode = ISD::AssertZext;
                if (Opcode)
                    ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue,
                                           DAG.getValueType(VA.getValVT()));
                ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
            }

            InVals.push_back(ArgValue);
        } else { // VA.isRegLoc()
            // sanity check
            assert(VA.isMemLoc());

            // The last argument is not a register
            ArgRegEnd = 0;

            // The stack pointer offset is relative to the caller stack frame.
            // Since the real stack size is unknown here, a negative SPOffset
            // is used so there's a way to adjust these offsets when the stack
            // size get known (on EliminateFrameIndex). A dummy SPOffset is
            // used instead of a direct negative address (which is recorded to
            // be used on emitPrologue) to avoid mis-calc of the first stack
            // offset on PEI::calculateFrameObjectOffsets.
            // Arguments are always 32-bit.
            unsigned ArgSize = VA.getLocVT().getSizeInBits()/8;
            unsigned StackLoc = VA.getLocMemOffset() + 4;
            int FI = MFI->CreateFixedObject(ArgSize, 0, true);
            MBlazeFI->recordLoadArgsFI(FI, -StackLoc);

            // Create load nodes to retrieve arguments from the stack
            SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
            InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
                                         MachinePointerInfo::getFixedStack(FI),
                                         false, false, 0));
        }
    }

    // To meet ABI, when VARARGS are passed on registers, the registers
    // must have their values written to the caller stack frame. If the last
    // argument was placed in the stack, there's no need to save any register.
    if ((isVarArg) && ArgRegEnd) {
        if (StackPtr.getNode() == 0)
            StackPtr = DAG.getRegister(StackReg, getPointerTy());

        // The last register argument that must be saved is MBlaze::R10
        TargetRegisterClass *RC = MBlaze::GPRRegisterClass;

        unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5);
        unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1);
        unsigned End   = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10);
        unsigned StackLoc = Start - Begin + 1;

        for (; Start <= End; ++Start, ++StackLoc) {
            unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
            unsigned LiveReg = MF.addLiveIn(Reg, RC);
            SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);

            int FI = MFI->CreateFixedObject(4, 0, true);
            MBlazeFI->recordStoreVarArgsFI(FI, -(StackLoc*4));
            SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
            OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff,
                                             MachinePointerInfo(),
                                             false, false, 0));

            // Record the frame index of the first variable argument
            // which is a value necessary to VASTART.
            if (!MBlazeFI->getVarArgsFrameIndex())
                MBlazeFI->setVarArgsFrameIndex(FI);
        }
    }

    // All stores are grouped in one node to allow the matching between
    // the size of Ins and InVals. This only happens when on varg functions
    if (!OutChains.empty()) {
        OutChains.push_back(Chain);
        Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                            &OutChains[0], OutChains.size());
    }

    return Chain;
}
Example #8
0
SDValue AVM2TargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const
{
    DebugLoc DL = Op.getDebugLoc();
    switch (Op.getOpcode()) {
    default: {
        assert(0 && "Shouldn't custom lower this");
    }
    // XXX TODO isn't this just Promote?
    case ISD::FADD:
    case ISD::FSUB:
    case ISD::FPOW:
    case ISD::FMUL:
    case ISD::FDIV:
    case ISD::FREM: {
        SDValue L = Op.getOperand(0);
        SDValue R = Op.getOperand(1);

        assert(L.getValueType() == R.getValueType() && L.getValueType() == MVT::f32);

        L = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, L);
        R = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, R);

        SDValue result = DAG.getNode(Op.getOpcode(), DL, MVT::f64, L, R);

        return DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, result, DAG.getIntPtrConstant(0));
    }
    // XXX TODO isn't this just Promote?
    case ISD::FSIN:
    case ISD::FCOS:
    case ISD::FSQRT:
    case ISD::FNEG:
    case ISD::FABS: {
        SDValue L = Op.getOperand(0);

        assert(L.getValueType() == MVT::f32);

        L = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, L);

        SDValue result = DAG.getNode(Op.getOpcode(), DL, MVT::f64, L);

        return DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, result, DAG.getIntPtrConstant(0));
    }
    case ISD::SELECT_CC: {
        ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
        SDValue L = Op.getOperand(0);
        SDValue R = Op.getOperand(1);
        SDValue A = Op.getOperand(2);
        SDValue B = Op.getOperand(3);

        // promote everything that is an f32
        if(L.getValueType() == MVT::f32) {
            L = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, L);
            R = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, R);
        }
        if(A.getValueType() == MVT::f32) {
            A = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, A);
            B = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, B);
        }

        bool IsFloat = L.getValueType() == MVT::f64;
        bool RIsFloat = A.getValueType() == MVT::f64;

        SDValue result = DAG.getNode(RIsFloat ? AVM2ISD::FSL : AVM2ISD::SL, DL, RIsFloat ? MVT::f64 : MVT::i32,
                                     DAG.getNode(IsFloat ? AVM2ISD::FCNOP: AVM2ISD::CNOP, DL, MVT::i32,
                                             DAG.getTargetConstant((int)CC, MVT::i32), L, R), A, B);
        if(Op.getValueType() == MVT::f32) {
            result = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, result, DAG.getIntPtrConstant(0));
        }
        return result;
    }

    // case ISD::BR_CC: { return LowerBR_CC(Op, DAG); }
    case ISD::BR_CC: {
        SDValue Chain = Op.getOperand(0);
        ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
        SDValue L = Op.getOperand(2);
        SDValue R = Op.getOperand(3);
        SDValue Dest = Op.getOperand(4);


        // If this is a br_cc of a "setcc", and if the setcc got lowered into
        // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
        if(L.getValueType() == MVT::f32) {
            L = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, L);
            R = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, R);
        } else if(L.getValueType() == MVT::i32 /*|| L.getValueType() == MVT::i64*/) {
            if(ConstantSDNode *node = dyn_cast<ConstantSDNode>(L)) {
                L = DAG.getTargetConstant((int)node->getSExtValue(), MVT::i32);
            }
            if(ConstantSDNode *node = dyn_cast<ConstantSDNode>(R)) {
                R = DAG.getTargetConstant((int)node->getSExtValue(), MVT::i32);
            }
        }


        int Opc;
        int Cmp;
        bool IsFloat = L.getValueType() == MVT::f64;
        if( IsFloat ) {
            Opc = AVM2ISD::FCBR;
            Cmp = AVM2ISD::FCNOP;
        } else {
            Opc = AVM2ISD::CBR;
            Cmp = AVM2ISD::CNOP;
        }

        SDValue NOP = DAG.getNode( Cmp, DL, MVT::i32, DAG.getTargetConstant(CC, MVT::i32), L, R);
        return DAG.getNode(Opc, DL, MVT::Other, Chain, NOP, Dest);
    }


    // XXX TODO can't this just be Legal?
    case ISD::ConstantFP: {
        union {
            double d;
            struct {
                unsigned a, b;
            } i;
        } u;

        APFloat apf(cast<ConstantFPSDNode>(Op)->getValueAPF());

        bool losesInfo = false;
        apf.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo);
        u.d = apf.convertToDouble();
        SDValue result = DAG.getNode(AVM2ISD::FNOP, DL, MVT::f64,
                                     DAG.getNode(AVM2ISD::F64, DL, MVT::f64,
                                             DAG.getTargetConstant(u.i.a, MVT::i32),
                                             DAG.getTargetConstant(u.i.b, MVT::i32)));
        if(Op.getValueType() == MVT::f32) {
            result = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, result,DAG.getIntPtrConstant(0));
        }
        return result;
    }
    case ISD::ConstantPool: {
        const Constant *C = cast<ConstantPoolSDNode>(Op)->getConstVal();
        SDValue CP = DAG.getTargetConstantPool(C, MVT::i32,
                                               cast<ConstantPoolSDNode>(Op)->getAlignment());
        return CP;
    }
    case ISD::BRIND:  {
        return LowerBRIND(Op, DAG);
    }
    case ISD::BlockAddress:  {
        return LowerBlockAddress(Op, DAG);
    }
    case ISD::TRAMPOLINE:  {
        return LowerTRAMPOLINE(Op, DAG);
    }
    case ISD::GlobalAddress: {
        const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
        if(GV->isDeclaration()) {
            // TODO ok? probably a leak
            std::string Str = "\2" + GV->getNameStr();
            const char *N = strdup(Str.c_str());
            return DAG.getNode(AVM2ISD::INOP, DL, MVT::i32, DAG.getTargetExternalSymbol(N, MVT::i32));
        }
        EVT VT(MVT::i32);
        return DAG.getNode(AVM2ISD::INOP, DL, MVT::i32, DAG.getTargetGlobalAddress(GV, DL, VT));
    }
    case ISD::ExternalSymbol : {
        const char *N = cast<ExternalSymbolSDNode>(Op)->getSymbol();
        const Module *M = DAG.getMachineFunction().getFunction()->getParent();
        const GlobalValue *GV = M->getGlobalVariable(N);
        if(GV && !GV->isDeclaration()) {
            EVT VT(MVT::i32);
            return DAG.getNode(AVM2ISD::INOP, DL, MVT::i32, DAG.getTargetGlobalAddress(GV, DL, VT));
        }
        return DAG.getNode(AVM2ISD::INOP, DL, MVT::i32, DAG.getTargetExternalSymbol(N, MVT::i32));
    }
    case ISD::VASTART: {
        // vastart just stores the address of the VarArgsFrameIndex slot into the
        // memory location argument.
        SDValue Offset = DAG.getNode(ISD::ADD, DL, MVT::i32,
                                     DAG.getRegister(AVM2::EBP, MVT::i32),
                                     DAG.getConstant(DAG.getMachineFunction().getInfo<AVM2MachineFunctionInfo>()->getVarArgsFrameOffset(), MVT::i32));

        /*
         http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?revision=46585&view=markup

         Create a new class, MemOperand, for describing memory references
         in the backend. Introduce a new SDNode type, MemOperandSDNode, for
         holding a MemOperand in the SelectionDAG IR, and add a MemOperand
         list to MachineInstr, and code to manage them. Remove the offset
         field from SrcValueSDNode; uses of SrcValueSDNode that were using
         it are all all using MemOperandSDNode now.

         Also, begin updating some getLoad and getStore calls to use the
         PseudoSourceValue objects.

         Most of this was written by Florian Brander, some
         reorganization and updating to TOT by me.
         */


        const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
        return DAG.getStore(Op.getOperand(0), DL, Offset,
                            Op.getOperand(1), MachinePointerInfo(SV), false, false, 0);

    }
    case ISD::VAARG: {
        SDNode *Node = Op.getNode();
        MVT::SimpleValueType VT = Node->getValueType(0).getSimpleVT().SimpleTy;
        SDValue InChain = Node->getOperand(0);
        SDValue VAListPtr = Node->getOperand(1);
        const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
        SDValue VAList = DAG.getLoad(getPointerTy(), DL, InChain, VAListPtr,
                                     MachinePointerInfo(SV), false, false, 0);
        // Increment the pointer, VAList, to the next vaarg
        SDValue NextPtr = DAG.getNode(ISD::ADD, DL, getPointerTy(), VAList,
                                      DAG.getConstant(Node->getValueType(0).getSizeInBits()/8,
                                              getPointerTy()));
        // Store the incremented VAList to the legalized pointer
        InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr,
                               VAListPtr, MachinePointerInfo(SV), false, false, 0);
        // Load the actual argument out of the pointer VAList
        return DAG.getLoad(VT, DL, InChain, VAList, MachinePointerInfo(), false, false, 0);
    }
    case ISD::DYNAMIC_STACKALLOC: {
        SDValue Chain = Op.getOperand(0);  // Legalize the chain.
        SDValue Size  = Op.getOperand(1);  // Legalize the size.

        unsigned SPReg = AVM2::ESP;
        SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32);
        SDValue NewSP = DAG.getNode(ISD::SUB, DL, MVT::i32, SP, Size);    // Value
        unsigned Align = getTargetMachine().getFrameLowering()->getStackAlignment();

        assert(!(Align & (Align - 1))); // must be power of 2
        SDValue NewSPAligned = DAG.getNode(ISD::AND, DL, MVT::i32, NewSP, DAG.getIntPtrConstant(~(Align - 1)));
        Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSPAligned);      // Output chain

        std::vector<EVT> Tys;
        Tys.push_back(MVT::i32);
        Tys.push_back(MVT::Other);
        SDValue Ops[2] = { NewSPAligned, Chain };
        return DAG.getNode(ISD::MERGE_VALUES, DL, Tys, Ops, 2);
    }

    /*
     http://llvm.org/viewvc/llvm-project?view=rev&revision=78142
     Major calling convention code refactoring.

     Instead of awkwardly encoding calling-convention information with ISD::CALL,
     ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
     provides three virtual functions for targets to override:
     LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
     lowering done on the special nodes. They provide the same information, but
     in a more immediately usable format.

     This also reworks much of the target-independent tail call logic. The
     decision of whether or not to perform a tail call is now cleanly split
     between target-independent portions, and the target dependent portion
     in IsEligibleForTailCallOptimization.

     This also synchronizes all in-tree targets, to help enable future
     refactoring and feature work.

     setOperationAction(ISD::RET               , MVT::Other, Custom);

     case ISD::RET: {
     SDValue Copy;

     switch(Op.getNumOperands()) {
     default:
     assert(0 && "Do not know how to return this many arguments!");
     abort();
     case 1:
     return DAG.getNode(AVM2ISD::RET_FLAG, DL, MVT::Other, Op.getOperand(0), DAG.getConstant(0, MVT::i32));
     case 3: {
     unsigned ArgReg;
     switch(Op.getOperand(1).getValueType()) {
     default: assert(0 && "Unknown type to return!");
     case MVT::i32: ArgReg = AVM2::EAX; break;
     case MVT::f32: ArgReg = AVM2::SST0; break;
     case MVT::f64: ArgReg = AVM2::ST0; break;
     }
     Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1),
     SDValue());
     break;
     }
     case 5:
     Copy = DAG.getCopyToReg(Op.getOperand(0), AVM2::EDX, Op.getOperand(3),
     SDValue());
     Copy = DAG.getCopyToReg(Copy, AVM2::EAX, Op.getOperand(1), Copy.getValue(1));
     break;
     }
     return DAG.getNode(AVM2ISD::RET_FLAG, DL, MVT::Other, Copy, Copy.getValue(1));
     }
     */
    case ISD::FRAMEADDR:
        return LowerFRAMEADDR(Op, DAG);
    case ISD::EH_SJLJ_SETJMP:
        return LowerEH_SJLJ_SETJMP(Op, DAG);
    case ISD::EH_SJLJ_LONGJMP:
        return LowerEH_SJLJ_LONGJMP(Op, DAG);
    case ISD::EH_SJLJ_DISPATCHSETUP:
        return LowerEH_SJLJ_DISPATCHSETUP(Op, DAG);
    case ISD::INTRINSIC_WO_CHAIN:
        return LowerINTRINSIC_WO_CHAIN(Op, DAG, SubTarget);
        // Return address.  Currently unimplemented
    case ISD::RETURNADDR:
        break;
    }
    return SDValue();
}
Example #9
0
SDValue Y86TargetLowering::
LowerFormalArguments(SDValue Chain,
                     CallingConv::ID CallConv,
                     bool isVarArg,
                     const SmallVectorImpl<ISD::InputArg> &Ins,
                     SDLoc dl,
                     SelectionDAG &DAG,
                     SmallVectorImpl<SDValue> &InVals) const {
  MachineFunction &MF = DAG.getMachineFunction();

  // Gather info about the formals.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
  CCInfo.AnalyzeFormalArguments(Ins, CC_Y86);

  // Push corresponding SDValues for the arguments.
  SDValue ArgValue;
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    if (VA.isRegLoc()) {
      EVT RegVT = VA.getLocVT();
      const TargetRegisterClass *RC;
      if (RegVT == MVT::i32)
        RC = &Y86::GPRRegClass;
      else
        llvm_unreachable("Unknown EVT");

      unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
      ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
    } else {
      assert(VA.isMemLoc());

      EVT ValVT;
      if (VA.getLocInfo() == CCValAssign::Indirect)
        ValVT = VA.getLocVT();
      else
        ValVT = VA.getValVT();

      // Create space in the stack (and an associated frame index)
      // accordingly: Either the complete size of the object is it's
      // a call by value or a pointer size otherwise.
      MachineFrameInfo *MFI = MF.getFrameInfo();
      ISD::ArgFlagsTy Flags = Ins[i].Flags;
      if (Flags.isByVal()) {
        unsigned Bytes = Flags.getByValSize();
        if (Bytes == 0)
          Bytes = 1; // Don't create zero-sized stack objects.
        int FI = MFI->CreateFixedObject(Bytes, VA.getLocMemOffset(), false);
        ArgValue = DAG.getFrameIndex(FI, getPointerTy());
      } else {
        int FI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8,
                                        VA.getLocMemOffset(), true);
        SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
        ArgValue = DAG.getLoad(ValVT, dl, Chain, FIN,
                               MachinePointerInfo::getFixedStack(FI),
                               false, false, false, 0);
      }
    }

    InVals.push_back(ArgValue);
  }

  return Chain;
}
/// LowerCCCArguments - transform physical registers into virtual registers and
/// generate load operations for arguments places on the stack.
// FIXME: struct return stuff
// FIXME: varargs
SDValue MSP430TargetLowering::LowerCCCArguments(SDValue Op,
        SelectionDAG &DAG) {
    MachineFunction &MF = DAG.getMachineFunction();
    MachineFrameInfo *MFI = MF.getFrameInfo();
    MachineRegisterInfo &RegInfo = MF.getRegInfo();
    SDValue Root = Op.getOperand(0);
    bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
    unsigned CC = MF.getFunction()->getCallingConv();
    DebugLoc dl = Op.getDebugLoc();

    // Assign locations to all of the incoming arguments.
    SmallVector<CCValAssign, 16> ArgLocs;
    CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
    CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_MSP430);

    assert(!isVarArg && "Varargs not supported yet");

    SmallVector<SDValue, 16> ArgValues;
    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
        CCValAssign &VA = ArgLocs[i];
        if (VA.isRegLoc()) {
            // Arguments passed in registers
            MVT RegVT = VA.getLocVT();
            switch (RegVT.getSimpleVT()) {
            default:
                cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
                     << RegVT.getSimpleVT()
                     << "\n";
                abort();
            case MVT::i16:
                unsigned VReg =
                    RegInfo.createVirtualRegister(MSP430::GR16RegisterClass);
                RegInfo.addLiveIn(VA.getLocReg(), VReg);
                SDValue ArgValue = DAG.getCopyFromReg(Root, dl, VReg, RegVT);

                // If this is an 8-bit value, it is really passed promoted to 16
                // bits. Insert an assert[sz]ext to capture this, then truncate to the
                // right size.
                if (VA.getLocInfo() == CCValAssign::SExt)
                    ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
                                           DAG.getValueType(VA.getValVT()));
                else if (VA.getLocInfo() == CCValAssign::ZExt)
                    ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
                                           DAG.getValueType(VA.getValVT()));

                if (VA.getLocInfo() != CCValAssign::Full)
                    ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);

                ArgValues.push_back(ArgValue);
            }
        } else {
            // Sanity check
            assert(VA.isMemLoc());
            // Load the argument to a virtual register
            unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
            if (ObjSize > 2) {
                cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
                     << VA.getLocVT().getSimpleVT()
                     << "\n";
            }
            // Create the frame index object for this incoming parameter...
            int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset());

            // Create the SelectionDAG nodes corresponding to a load
            //from this parameter
            SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);
            ArgValues.push_back(DAG.getLoad(VA.getLocVT(), dl, Root, FIN,
                                            PseudoSourceValue::getFixedStack(FI), 0));
        }
    }

    ArgValues.push_back(Root);

    // Return the new list of results.
    return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
                       &ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
}
SDValue
SparcTargetLowering::LowerReturn(SDValue Chain,
                                 CallingConv::ID CallConv, bool isVarArg,
                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
                                 const SmallVectorImpl<SDValue> &OutVals,
                                 DebugLoc dl, SelectionDAG &DAG) const {

  MachineFunction &MF = DAG.getMachineFunction();

  // CCValAssign - represent the assignment of the return value to locations.
  SmallVector<CCValAssign, 16> RVLocs;

  // CCState - Info about the registers and stack slot.
  CCState CCInfo(CallConv, isVarArg, DAG.getTarget(),
                 RVLocs, *DAG.getContext());

  // Analize return values.
  CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);

  // If this is the first return lowered for this function, add the regs to the
  // liveout set for the function.
  if (MF.getRegInfo().liveout_empty()) {
    for (unsigned i = 0; i != RVLocs.size(); ++i)
      if (RVLocs[i].isRegLoc())
        MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg());
  }

  SDValue Flag;

  // Copy the result values into the output registers.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    CCValAssign &VA = RVLocs[i];
    assert(VA.isRegLoc() && "Can only return in registers!");

    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
                             OutVals[i], Flag);

    // Guarantee that all emitted copies are stuck together with flags.
    Flag = Chain.getValue(1);
  }

  unsigned RetAddrOffset = 8; //Call Inst + Delay Slot
  // If the function returns a struct, copy the SRetReturnReg to I0
  if (MF.getFunction()->hasStructRetAttr()) {
    SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
    unsigned Reg = SFI->getSRetReturnReg();
    if (!Reg)
      llvm_unreachable("sret virtual register not created in the entry block");
    SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy());
    Chain = DAG.getCopyToReg(Chain, dl, SP::I0, Val, Flag);
    Flag = Chain.getValue(1);
    if (MF.getRegInfo().liveout_empty())
      MF.getRegInfo().addLiveOut(SP::I0);
    RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
  }

  SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32);

  if (Flag.getNode())
    return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain,
                       RetAddrOffsetNode, Flag);
  return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, 
                     RetAddrOffsetNode);
}
SDValue
SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
                               CallingConv::ID CallConv, bool isVarArg,
                               bool &isTailCall,
                               const SmallVectorImpl<ISD::OutputArg> &Outs,
                               const SmallVectorImpl<SDValue> &OutVals,
                               const SmallVectorImpl<ISD::InputArg> &Ins,
                               DebugLoc dl, SelectionDAG &DAG,
                               SmallVectorImpl<SDValue> &InVals) const {
  // Sparc target does not yet support tail call optimization.
  isTailCall = false;

  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs,
                 *DAG.getContext());
  CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);

  // Get the size of the outgoing arguments stack space requirement.
  unsigned ArgsSize = CCInfo.getNextStackOffset();

  // Keep stack frames 8-byte aligned.
  ArgsSize = (ArgsSize+7) & ~7;

  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();

  //Create local copies for byval args.
  SmallVector<SDValue, 8> ByValArgs;
  for (unsigned i = 0,  e = Outs.size(); i != e; ++i) {
    ISD::ArgFlagsTy Flags = Outs[i].Flags;
    if (!Flags.isByVal())
      continue;

    SDValue Arg = OutVals[i];
    unsigned Size = Flags.getByValSize();
    unsigned Align = Flags.getByValAlign();

    int FI = MFI->CreateStackObject(Size, Align, false);
    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy());
    SDValue SizeNode = DAG.getConstant(Size, MVT::i32);

    Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align,
                          false,        //isVolatile,
                          (Size <= 32), //AlwaysInline if size <= 32
                          MachinePointerInfo(), MachinePointerInfo());
    ByValArgs.push_back(FIPtr);
  }

  Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));

  SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
  SmallVector<SDValue, 8> MemOpChains;

  const unsigned StackOffset = 92;
  bool hasStructRetAttr = false;
  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
       i != e;
       ++i, ++realArgIdx) {
    CCValAssign &VA = ArgLocs[i];
    SDValue Arg = OutVals[realArgIdx];

    ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags;

    //Use local copy if it is a byval arg.
    if (Flags.isByVal())
      Arg = ByValArgs[byvalArgIdx++];

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    default: llvm_unreachable("Unknown loc info!");
    case CCValAssign::Full: break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
      break;
    case CCValAssign::BCvt:
      Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg);
      break;
    }

    if (Flags.isSRet()) {
      assert(VA.needsCustom());
      // store SRet argument in %sp+64
      SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
      SDValue PtrOff = DAG.getIntPtrConstant(64);
      PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
      MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                         MachinePointerInfo(),
                                         false, false, 0));
      hasStructRetAttr = true;
      continue;
    }

    if (VA.needsCustom()) {
      assert(VA.getLocVT() == MVT::f64);

      if (VA.isMemLoc()) {
        unsigned Offset = VA.getLocMemOffset() + StackOffset;
        //if it is double-word aligned, just store.
        if (Offset % 8 == 0) {
          SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
          SDValue PtrOff = DAG.getIntPtrConstant(Offset);
          PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
          MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                             MachinePointerInfo(),
                                             false, false, 0));
          continue;
        }
      }

      SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32);
      SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
                                   Arg, StackPtr, MachinePointerInfo(),
                                   false, false, 0);
      // Sparc is big-endian, so the high part comes first.
      SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr,
                               MachinePointerInfo(), false, false, 0);
      // Increment the pointer to the other half.
      StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
                             DAG.getIntPtrConstant(4));
      // Load the low part.
      SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr,
                               MachinePointerInfo(), false, false, 0);

      if (VA.isRegLoc()) {
        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Hi));
        assert(i+1 != e);
        CCValAssign &NextVA = ArgLocs[++i];
        if (NextVA.isRegLoc()) {
          RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Lo));
        } else {
          //Store the low part in stack.
          unsigned Offset = NextVA.getLocMemOffset() + StackOffset;
          SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
          SDValue PtrOff = DAG.getIntPtrConstant(Offset);
          PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
          MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff,
                                             MachinePointerInfo(),
                                             false, false, 0));
        }
      } else {
        unsigned Offset = VA.getLocMemOffset() + StackOffset;
        // Store the high part.
        SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
        SDValue PtrOff = DAG.getIntPtrConstant(Offset);
        PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
        MemOpChains.push_back(DAG.getStore(Chain, dl, Hi, PtrOff,
                                           MachinePointerInfo(),
                                           false, false, 0));
        // Store the low part.
        PtrOff = DAG.getIntPtrConstant(Offset+4);
        PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
        MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff,
                                           MachinePointerInfo(),
                                           false, false, 0));
      }
      continue;
    }

    // Arguments that can be passed on register must be kept at
    // RegsToPass vector
    if (VA.isRegLoc()) {
      if (VA.getLocVT() != MVT::f32) {
        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
        continue;
      }
      Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg);
      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
      continue;
    }

    assert(VA.isMemLoc());

    // Create a store off the stack pointer for this argument.
    SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
    SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+StackOffset);
    PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
    MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
                                       MachinePointerInfo(),
                                       false, false, 0));
  }


  // Emit all stores, make sure the occur before any copies into physregs.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token
  // chain and flag operands which copy the outgoing args into registers.
  // The InFlag in necessary since all emitted instructions must be
  // stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    unsigned Reg = RegsToPass[i].first;
    // Remap I0->I7 -> O0->O7.
    if (Reg >= SP::I0 && Reg <= SP::I7)
      Reg = Reg-SP::I0+SP::O0;

    Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0;

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);

  // Returns a chain & a flag for retval copy to use
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);
  if (hasStructRetAttr)
    Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32));
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    unsigned Reg = RegsToPass[i].first;
    if (Reg >= SP::I0 && Reg <= SP::I7)
      Reg = Reg-SP::I0+SP::O0;

    Ops.push_back(DAG.getRegister(Reg, RegsToPass[i].second.getValueType()));
  }
  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
  InFlag = Chain.getValue(1);

  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true),
                             DAG.getIntPtrConstant(0, true), InFlag);
  InFlag = Chain.getValue(1);

  // Assign locations to each value returned by this call.
  SmallVector<CCValAssign, 16> RVLocs;
  CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
                 RVLocs, *DAG.getContext());

  RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);

  // Copy all of the result registers out of their specified physreg.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    unsigned Reg = RVLocs[i].getLocReg();

    // Remap I0->I7 -> O0->O7.
    if (Reg >= SP::I0 && Reg <= SP::I7)
      Reg = Reg-SP::I0+SP::O0;

    Chain = DAG.getCopyFromReg(Chain, dl, Reg,
                               RVLocs[i].getValVT(), InFlag).getValue(1);
    InFlag = Chain.getValue(2);
    InVals.push_back(Chain.getValue(0));
  }

  return Chain;
}
/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
/// passed in either one or two GPRs, including FP values.  TODO: we should
/// pass FP values in FP registers for fastcc functions.
SDValue
SparcTargetLowering::LowerFormalArguments(SDValue Chain,
                                          CallingConv::ID CallConv, bool isVarArg,
                                          const SmallVectorImpl<ISD::InputArg>
                                            &Ins,
                                          DebugLoc dl, SelectionDAG &DAG,
                                          SmallVectorImpl<SDValue> &InVals)
                                            const {

  MachineFunction &MF = DAG.getMachineFunction();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());
  CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);

  const unsigned StackOffset = 92;

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    if (i == 0  && Ins[i].Flags.isSRet()) {
      //Get SRet from [%fp+64]
      int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, 64, true);
      SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
      SDValue Arg = DAG.getLoad(MVT::i32, dl, Chain, FIPtr,
                                MachinePointerInfo(),
                                false, false, 0);
      InVals.push_back(Arg);
      continue;
    }

    if (VA.isRegLoc()) {
      if (VA.needsCustom()) {
        assert(VA.getLocVT() == MVT::f64);
        unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
        MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi);
        SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);

        assert(i+1 < e);
        CCValAssign &NextVA = ArgLocs[++i];

        SDValue LoVal;
        if (NextVA.isMemLoc()) {
          int FrameIdx = MF.getFrameInfo()->
            CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true);
          SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
          LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr,
                              MachinePointerInfo(),
                              false, false, 0);
        } else {
          unsigned loReg = MF.addLiveIn(NextVA.getLocReg(),
                                        &SP::IntRegsRegClass);
          LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
        }
        SDValue WholeValue =
          DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
        WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue);
        InVals.push_back(WholeValue);
        continue;
      }
      unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
      MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg);
      SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
      if (VA.getLocVT() == MVT::f32)
        Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg);
      else if (VA.getLocVT() != MVT::i32) {
        Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg,
                          DAG.getValueType(VA.getLocVT()));
        Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg);
      }
      InVals.push_back(Arg);
      continue;
    }

    assert(VA.isMemLoc());

    unsigned Offset = VA.getLocMemOffset()+StackOffset;

    if (VA.needsCustom()) {
      assert(VA.getValVT() == MVT::f64);
      //If it is double-word aligned, just load.
      if (Offset % 8 == 0) {
        int FI = MF.getFrameInfo()->CreateFixedObject(8,
                                                      Offset,
                                                      true);
        SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy());
        SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
                                   MachinePointerInfo(),
                                   false,false, 0);
        InVals.push_back(Load);
        continue;
      }

      int FI = MF.getFrameInfo()->CreateFixedObject(4,
                                                    Offset,
                                                    true);
      SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy());
      SDValue HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr,
                                  MachinePointerInfo(),
                                  false, false, 0);
      int FI2 = MF.getFrameInfo()->CreateFixedObject(4,
                                                     Offset+4,
                                                     true);
      SDValue FIPtr2 = DAG.getFrameIndex(FI2, getPointerTy());

      SDValue LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr2,
                                  MachinePointerInfo(),
                                  false, false, 0);

      SDValue WholeValue =
        DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
      WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue);
      InVals.push_back(WholeValue);
      continue;
    }

    int FI = MF.getFrameInfo()->CreateFixedObject(4,
                                                  Offset,
                                                  true);
    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy());
    SDValue Load ;
    if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
      Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
                         MachinePointerInfo(),
                         false, false, 0);
    } else {
      ISD::LoadExtType LoadOp = ISD::SEXTLOAD;
      // Sparc is big endian, so add an offset based on the ObjectVT.
      unsigned Offset = 4-std::max(1U, VA.getValVT().getSizeInBits()/8);
      FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
                          DAG.getConstant(Offset, MVT::i32));
      Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr,
                            MachinePointerInfo(),
                            VA.getValVT(), false, false,0);
      Load = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), Load);
    }
    InVals.push_back(Load);
  }

  if (MF.getFunction()->hasStructRetAttr()) {
    //Copy the SRet Argument to SRetReturnReg
    SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
    unsigned Reg = SFI->getSRetReturnReg();
    if (!Reg) {
      Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass);
      SFI->setSRetReturnReg(Reg);
    }
    SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
  }

  // Store remaining ArgRegs to the stack if this is a varargs function.
  if (isVarArg) {
    static const unsigned ArgRegs[] = {
      SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
    };
    unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs, 6);
    const unsigned *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6;
    unsigned ArgOffset = CCInfo.getNextStackOffset();
    if (NumAllocated == 6)
      ArgOffset += StackOffset;
    else {
      assert(!ArgOffset);
      ArgOffset = 68+4*NumAllocated;
    }

    // Remember the vararg offset for the va_start implementation.
    FuncInfo->setVarArgsFrameOffset(ArgOffset);

    std::vector<SDValue> OutChains;

    for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
      unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
      MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
      SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);

      int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset,
                                                          true);
      SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);

      OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr,
                                       MachinePointerInfo(),
                                       false, false, 0));
      ArgOffset += 4;
    }

    if (!OutChains.empty()) {
      OutChains.push_back(Chain);
      Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                          &OutChains[0], OutChains.size());
    }
  }

  return Chain;
}
SDOperand IA64TargetLowering::
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
  switch (Op.getOpcode()) {
  default: assert(0 && "Should not custom lower this!");
  case ISD::GlobalTLSAddress:
    assert(0 && "TLS not implemented for IA64.");
  case ISD::RET: {
    SDOperand AR_PFSVal, Copy;
    
    switch(Op.getNumOperands()) {
     default:
      assert(0 && "Do not know how to return this many arguments!");
      abort();
    case 1: 
      AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64);
      AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), IA64::AR_PFS, 
                                   AR_PFSVal);
      return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other, AR_PFSVal);
    case 3: {
      // Copy the result into the output register & restore ar.pfs
      MVT::ValueType ArgVT = Op.getOperand(1).getValueType();
      unsigned ArgReg = MVT::isInteger(ArgVT) ? IA64::r8 : IA64::F8;

      AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), VirtGPR, MVT::i64);
      Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), ArgReg, Op.getOperand(1),
                              SDOperand());
      AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), IA64::AR_PFS, AR_PFSVal,
                                   Copy.getValue(1));
      return DAG.getNode(IA64ISD::RET_FLAG, MVT::Other,
                         AR_PFSVal, AR_PFSVal.getValue(1));
    }
    }
    return SDOperand();
  }
  case ISD::VAARG: {
    MVT::ValueType VT = getPointerTy();
    const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
    SDOperand VAList = DAG.getLoad(VT, Op.getOperand(0), Op.getOperand(1), 
                                   SV, 0);
    // Increment the pointer, VAList, to the next vaarg
    SDOperand VAIncr = DAG.getNode(ISD::ADD, VT, VAList, 
                                   DAG.getConstant(MVT::getSizeInBits(VT)/8, 
                                                   VT));
    // Store the incremented VAList to the legalized pointer
    VAIncr = DAG.getStore(VAList.getValue(1), VAIncr,
                          Op.getOperand(1), SV, 0);
    // Load the actual argument out of the pointer VAList
    return DAG.getLoad(Op.getValueType(), VAIncr, VAList, NULL, 0);
  }
  case ISD::VASTART: {
    // vastart just stores the address of the VarArgsFrameIndex slot into the
    // memory location argument.
    SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64);
    const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
    return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0);
  }
  // Frame & Return address.  Currently unimplemented
  case ISD::RETURNADDR:         break;
  case ISD::FRAMEADDR:          break;
  }
  return SDOperand();
}
std::pair<SDOperand, SDOperand>
IA64TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
                                bool RetSExt, bool RetZExt,
                                bool isVarArg, unsigned CallingConv, 
                                bool isTailCall, SDOperand Callee, 
                                ArgListTy &Args, SelectionDAG &DAG) {

  MachineFunction &MF = DAG.getMachineFunction();

  unsigned NumBytes = 16;
  unsigned outRegsUsed = 0;

  if (Args.size() > 8) {
    NumBytes += (Args.size() - 8) * 8;
    outRegsUsed = 8;
  } else {
    outRegsUsed = Args.size();
  }

  // FIXME? this WILL fail if we ever try to pass around an arg that
  // consumes more than a single output slot (a 'real' double, int128
  // some sort of aggregate etc.), as we'll underestimate how many 'outX'
  // registers we use. Hopefully, the assembler will notice.
  MF.getInfo<IA64FunctionInfo>()->outRegsUsed=
    std::max(outRegsUsed, MF.getInfo<IA64FunctionInfo>()->outRegsUsed);

  // keep stack frame 16-byte aligned
  // assert(NumBytes==((NumBytes+15) & ~15) && 
  //        "stack frame not 16-byte aligned!");
  NumBytes = (NumBytes+15) & ~15;
  
  Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));

  SDOperand StackPtr;
  std::vector<SDOperand> Stores;
  std::vector<SDOperand> Converts;
  std::vector<SDOperand> RegValuesToPass;
  unsigned ArgOffset = 16;
  
  for (unsigned i = 0, e = Args.size(); i != e; ++i)
    {
      SDOperand Val = Args[i].Node;
      MVT::ValueType ObjectVT = Val.getValueType();
      SDOperand ValToStore(0, 0), ValToConvert(0, 0);
      unsigned ObjSize=8;
      switch (ObjectVT) {
      default: assert(0 && "unexpected argument type!");
      case MVT::i1:
      case MVT::i8:
      case MVT::i16:
      case MVT::i32: {
        //promote to 64-bits, sign/zero extending based on type
        //of the argument
        ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
        if (Args[i].isSExt)
          ExtendKind = ISD::SIGN_EXTEND;
        else if (Args[i].isZExt)
          ExtendKind = ISD::ZERO_EXTEND;
        Val = DAG.getNode(ExtendKind, MVT::i64, Val);
        // XXX: fall through
      }
      case MVT::i64:
        //ObjSize = 8;
        if(RegValuesToPass.size() >= 8) {
          ValToStore = Val;
        } else {
          RegValuesToPass.push_back(Val);
        }
        break;
      case MVT::f32:
        //promote to 64-bits
        Val = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Val);
        // XXX: fall through
      case MVT::f64:
        if(RegValuesToPass.size() >= 8) {
          ValToStore = Val;
        } else {
          RegValuesToPass.push_back(Val);
          if(1 /* TODO: if(calling external or varadic function)*/ ) {
            ValToConvert = Val; // additionally pass this FP value as an int
          }
        }
        break;
      }
      
      if(ValToStore.Val) {
        if(!StackPtr.Val) {
          StackPtr = DAG.getRegister(IA64::r12, MVT::i64);
        }
        SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
        PtrOff = DAG.getNode(ISD::ADD, MVT::i64, StackPtr, PtrOff);
        Stores.push_back(DAG.getStore(Chain, ValToStore, PtrOff, NULL, 0));
        ArgOffset += ObjSize;
      }

      if(ValToConvert.Val) {
        Converts.push_back(DAG.getNode(IA64ISD::GETFD, MVT::i64, ValToConvert)); 
      }
    }

  // Emit all stores, make sure they occur before any copies into physregs.
  if (!Stores.empty())
    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0],Stores.size());

  static const unsigned IntArgRegs[] = {
    IA64::out0, IA64::out1, IA64::out2, IA64::out3, 
    IA64::out4, IA64::out5, IA64::out6, IA64::out7
  };

  static const unsigned FPArgRegs[] = {
    IA64::F8,  IA64::F9,  IA64::F10, IA64::F11, 
    IA64::F12, IA64::F13, IA64::F14, IA64::F15
  };

  SDOperand InFlag;
  
  // save the current GP, SP and RP : FIXME: do we need to do all 3 always?
  SDOperand GPBeforeCall = DAG.getCopyFromReg(Chain, IA64::r1, MVT::i64, InFlag);
  Chain = GPBeforeCall.getValue(1);
  InFlag = Chain.getValue(2);
  SDOperand SPBeforeCall = DAG.getCopyFromReg(Chain, IA64::r12, MVT::i64, InFlag);
  Chain = SPBeforeCall.getValue(1);
  InFlag = Chain.getValue(2);
  SDOperand RPBeforeCall = DAG.getCopyFromReg(Chain, IA64::rp, MVT::i64, InFlag);
  Chain = RPBeforeCall.getValue(1);
  InFlag = Chain.getValue(2);

  // Build a sequence of copy-to-reg nodes chained together with token chain
  // and flag operands which copy the outgoing integer args into regs out[0-7]
  // mapped 1:1 and the FP args into regs F8-F15 "lazily"
  // TODO: for performance, we should only copy FP args into int regs when we
  // know this is required (i.e. for varardic or external (unknown) functions)

  // first to the FP->(integer representation) conversions, these are
  // flagged for now, but shouldn't have to be (TODO)
  unsigned seenConverts = 0;
  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
    if(MVT::isFloatingPoint(RegValuesToPass[i].getValueType())) {
      Chain = DAG.getCopyToReg(Chain, IntArgRegs[i], Converts[seenConverts++], 
                               InFlag);
      InFlag = Chain.getValue(1);
    }
  }

  // next copy args into the usual places, these are flagged
  unsigned usedFPArgs = 0;
  for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
    Chain = DAG.getCopyToReg(Chain,
      MVT::isInteger(RegValuesToPass[i].getValueType()) ?
        IntArgRegs[i] : FPArgRegs[usedFPArgs++], RegValuesToPass[i], InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
/*
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64);
  }
*/

  std::vector<MVT::ValueType> NodeTys;
  std::vector<SDOperand> CallOperands;
  NodeTys.push_back(MVT::Other);   // Returns a chain
  NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
  CallOperands.push_back(Chain);
  CallOperands.push_back(Callee);

  // emit the call itself
  if (InFlag.Val)
    CallOperands.push_back(InFlag);
  else
    assert(0 && "this should never happen!\n");

  // to make way for a hack:
  Chain = DAG.getNode(IA64ISD::BRCALL, NodeTys,
                      &CallOperands[0], CallOperands.size());
  InFlag = Chain.getValue(1);

  // restore the GP, SP and RP after the call  
  Chain = DAG.getCopyToReg(Chain, IA64::r1, GPBeforeCall, InFlag);
  InFlag = Chain.getValue(1);
  Chain = DAG.getCopyToReg(Chain, IA64::r12, SPBeforeCall, InFlag);
  InFlag = Chain.getValue(1);
  Chain = DAG.getCopyToReg(Chain, IA64::rp, RPBeforeCall, InFlag);
  InFlag = Chain.getValue(1);
 
  std::vector<MVT::ValueType> RetVals;
  RetVals.push_back(MVT::Other);
  RetVals.push_back(MVT::Flag);
 
  MVT::ValueType RetTyVT = getValueType(RetTy);
  SDOperand RetVal;
  if (RetTyVT != MVT::isVoid) {
    switch (RetTyVT) {
    default: assert(0 && "Unknown value type to return!");
    case MVT::i1: { // bools are just like other integers (returned in r8)
      // we *could* fall through to the truncate below, but this saves a
      // few redundant predicate ops
      SDOperand boolInR8 = DAG.getCopyFromReg(Chain, IA64::r8, MVT::i64,InFlag);
      InFlag = boolInR8.getValue(2);
      Chain = boolInR8.getValue(1);
      SDOperand zeroReg = DAG.getCopyFromReg(Chain, IA64::r0, MVT::i64, InFlag);
      InFlag = zeroReg.getValue(2);
      Chain = zeroReg.getValue(1);
      
      RetVal = DAG.getSetCC(MVT::i1, boolInR8, zeroReg, ISD::SETNE);
      break;
    }
    case MVT::i8:
    case MVT::i16:
    case MVT::i32:
      RetVal = DAG.getCopyFromReg(Chain, IA64::r8, MVT::i64, InFlag);
      Chain = RetVal.getValue(1);
      
      // keep track of whether it is sign or zero extended (todo: bools?)
/* XXX
      RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext,
                           MVT::i64, RetVal, DAG.getValueType(RetTyVT));
*/
      RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal);
      break;
    case MVT::i64:
      RetVal = DAG.getCopyFromReg(Chain, IA64::r8, MVT::i64, InFlag);
      Chain = RetVal.getValue(1);
      InFlag = RetVal.getValue(2); // XXX dead
      break;
    case MVT::f32:
      RetVal = DAG.getCopyFromReg(Chain, IA64::F8, MVT::f64, InFlag);
      Chain = RetVal.getValue(1);
      RetVal = DAG.getNode(ISD::TRUNCATE, MVT::f32, RetVal);
      break;
    case MVT::f64:
      RetVal = DAG.getCopyFromReg(Chain, IA64::F8, MVT::f64, InFlag);
      Chain = RetVal.getValue(1);
      InFlag = RetVal.getValue(2); // XXX dead
      break;
    }
  }
  
  Chain = DAG.getCALLSEQ_END(Chain,
                             DAG.getConstant(NumBytes, getPointerTy()),
                             DAG.getConstant(0, getPointerTy()),
                             SDOperand());
  return std::make_pair(RetVal, Chain);
}
Example #16
0
SDValue PTXTargetLowering::
  LowerFormalArguments(SDValue Chain,
                       CallingConv::ID CallConv,
                       bool isVarArg,
                       const SmallVectorImpl<ISD::InputArg> &Ins,
                       DebugLoc dl,
                       SelectionDAG &DAG,
                       SmallVectorImpl<SDValue> &InVals) const {
  if (isVarArg) llvm_unreachable("PTX does not support varargs");

  MachineFunction &MF = DAG.getMachineFunction();
  PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();

  switch (CallConv) {
    default:
      llvm_unreachable("Unsupported calling convention");
      break;
    case CallingConv::PTX_Kernel:
      MFI->setKernel(true);
      break;
    case CallingConv::PTX_Device:
      MFI->setKernel(false);
      break;
  }

  if (MFI->isKernel()) {
    // For kernel functions, we just need to emit the proper READ_PARAM ISDs
    for (unsigned i = 0, e = Ins.size(); i != e; ++i) {

      assert(Ins[i].VT != MVT::i1 && "Kernels cannot take pred operands");

      SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, Ins[i].VT, Chain,
                                     DAG.getTargetConstant(i, MVT::i32));
      InVals.push_back(ArgValue);

      // Instead of storing a physical register in our argument list, we just
      // store the total size of the parameter, in bits.  The ASM printer
      // knows how to process this.
      MFI->addArgReg(Ins[i].VT.getStoreSizeInBits());
    }
  }
  else {
    // For device functions, we use the PTX calling convention to do register
    // assignments then create CopyFromReg ISDs for the allocated registers

    SmallVector<CCValAssign, 16> ArgLocs;
    CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), ArgLocs,
                   *DAG.getContext());

    CCInfo.AnalyzeFormalArguments(Ins, CC_PTX);

    for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {

      CCValAssign&         VA    = ArgLocs[i];
      EVT                  RegVT = VA.getLocVT();
      TargetRegisterClass* TRC   = 0;

      assert(VA.isRegLoc() && "CCValAssign must be RegLoc");

      // Determine which register class we need
      if (RegVT == MVT::i1) {
        TRC = PTX::RegPredRegisterClass;
      }
      else if (RegVT == MVT::i16) {
        TRC = PTX::RegI16RegisterClass;
      }
      else if (RegVT == MVT::i32) {
        TRC = PTX::RegI32RegisterClass;
      }
      else if (RegVT == MVT::i64) {
        TRC = PTX::RegI64RegisterClass;
      }
      else if (RegVT == MVT::f32) {
        TRC = PTX::RegF32RegisterClass;
      }
      else if (RegVT == MVT::f64) {
        TRC = PTX::RegF64RegisterClass;
      }
      else {
        llvm_unreachable("Unknown parameter type");
      }

      unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
      MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg);

      SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
      InVals.push_back(ArgValue);

      MFI->addArgReg(VA.getLocReg());
    }
  }

  return Chain;
}
static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
                                       int &VarArgsBase,
                                       int &VarArgsOffset) {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  std::vector<SDOperand> ArgValues;
  SDOperand Root = Op.getOperand(0);

  AddLiveIn(MF, Alpha::R29, &Alpha::GPRCRegClass); //GP
  AddLiveIn(MF, Alpha::R26, &Alpha::GPRCRegClass); //RA

  unsigned args_int[] = {
    Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
  unsigned args_float[] = {
    Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
  
  for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
    SDOperand argt;
    MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
    SDOperand ArgVal;

    if (ArgNo  < 6) {
      switch (ObjectVT) {
      default:
        cerr << "Unknown Type " << ObjectVT << "\n";
        abort();
      case MVT::f64:
        args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 
                                      &Alpha::F8RCRegClass);
        ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT);
        break;
      case MVT::f32:
        args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 
                                      &Alpha::F4RCRegClass);
        ArgVal = DAG.getCopyFromReg(Root, args_float[ArgNo], ObjectVT);
        break;
      case MVT::i64:
        args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], 
                                    &Alpha::GPRCRegClass);
        ArgVal = DAG.getCopyFromReg(Root, args_int[ArgNo], MVT::i64);
        break;
      }
    } else { //more args
      // Create the frame index object for this incoming parameter...
      int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6));

      // Create the SelectionDAG nodes corresponding to a load
      //from this parameter
      SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
      ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0);
    }
    ArgValues.push_back(ArgVal);
  }

  // If the functions takes variable number of arguments, copy all regs to stack
  bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
  if (isVarArg) {
    VarArgsOffset = (Op.Val->getNumValues()-1) * 8;
    std::vector<SDOperand> LS;
    for (int i = 0; i < 6; ++i) {
      if (MRegisterInfo::isPhysicalRegister(args_int[i]))
        args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass);
      SDOperand argt = DAG.getCopyFromReg(Root, args_int[i], MVT::i64);
      int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
      if (i == 0) VarArgsBase = FI;
      SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64);
      LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0));

      if (MRegisterInfo::isPhysicalRegister(args_float[i]))
        args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass);
      argt = DAG.getCopyFromReg(Root, args_float[i], MVT::f64);
      FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
      SDFI = DAG.getFrameIndex(FI, MVT::i64);
      LS.push_back(DAG.getStore(Root, argt, SDFI, NULL, 0));
    }

    //Set up a token factor with all the stack traffic
    Root = DAG.getNode(ISD::TokenFactor, MVT::Other, &LS[0], LS.size());
  }

  ArgValues.push_back(Root);

  // Return the new list of results.
  std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
                                    Op.Val->value_end());
  return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size());
}
Example #18
0
/// LowerArguments - V8 uses a very simple ABI, where all values are passed in
/// either one or two GPRs, including FP values.  TODO: we should pass FP values
/// in FP registers for fastcc functions.
void
SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
                                    SmallVectorImpl<SDValue> &ArgValues,
                                    DebugLoc dl) {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();

  static const unsigned ArgRegs[] = {
    SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
  };

  const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
  unsigned ArgOffset = 68;

  SDValue Root = DAG.getRoot();
  std::vector<SDValue> OutChains;

  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
    MVT ObjectVT = getValueType(I->getType());

    switch (ObjectVT.getSimpleVT()) {
    default: assert(0 && "Unhandled argument type!");
    case MVT::i1:
    case MVT::i8:
    case MVT::i16:
    case MVT::i32:
      if (I->use_empty()) {                // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        ArgValues.push_back(DAG.getUNDEF(ObjectVT));
      } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
        unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
        MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
        SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
        if (ObjectVT != MVT::i32) {
          unsigned AssertOp = ISD::AssertSext;
          Arg = DAG.getNode(AssertOp, dl, MVT::i32, Arg,
                            DAG.getValueType(ObjectVT));
          Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg);
        }
        ArgValues.push_back(Arg);
      } else {
        int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
        SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
        SDValue Load;
        if (ObjectVT == MVT::i32) {
          Load = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
        } else {
          ISD::LoadExtType LoadOp = ISD::SEXTLOAD;

          // Sparc is big endian, so add an offset based on the ObjectVT.
          unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8);
          FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
                              DAG.getConstant(Offset, MVT::i32));
          Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Root, FIPtr,
                                NULL, 0, ObjectVT);
          Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load);
        }
        ArgValues.push_back(Load);
      }

      ArgOffset += 4;
      break;
    case MVT::f32:
      if (I->use_empty()) {                // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        ArgValues.push_back(DAG.getUNDEF(ObjectVT));
      } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
        // FP value is passed in an integer register.
        unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
        MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
        SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);

        Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg);
        ArgValues.push_back(Arg);
      } else {
        int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
        SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
        SDValue Load = DAG.getLoad(MVT::f32, dl, Root, FIPtr, NULL, 0);
        ArgValues.push_back(Load);
      }
      ArgOffset += 4;
      break;

    case MVT::i64:
    case MVT::f64:
      if (I->use_empty()) {                // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        ArgValues.push_back(DAG.getUNDEF(ObjectVT));
      } else {
        SDValue HiVal;
        if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
          unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
          MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
          HiVal = DAG.getCopyFromReg(Root, dl, VRegHi, MVT::i32);
        } else {
          int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
          SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
          HiVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
        }

        SDValue LoVal;
        if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
          unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
          MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
          LoVal = DAG.getCopyFromReg(Root, dl, VRegLo, MVT::i32);
        } else {
          int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
          SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
          LoVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
        }

        // Compose the two halves together into an i64 unit.
        SDValue WholeValue =
          DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);

        // If we want a double, do a bit convert.
        if (ObjectVT == MVT::f64)
          WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue);

        ArgValues.push_back(WholeValue);
      }
      ArgOffset += 8;
      break;
    }
  }

  // Store remaining ArgRegs to the stack if this is a varargs function.
  if (F.isVarArg()) {
    // Remember the vararg offset for the va_start implementation.
    VarArgsFrameOffset = ArgOffset;

    for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
      unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
      MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
      SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);

      int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
      SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);

      OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0));
      ArgOffset += 4;
    }
  }

  if (!OutChains.empty())
    DAG.setRoot(DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                            &OutChains[0], OutChains.size()));
}
Example #19
0
// TODO refactor?
SDValue AVM2TargetLowering::
LowerCall(SDValue Chain, SDValue Callee,
          CallingConv::ID CallConv, bool isVarArg, bool& isTailCall,
          const SmallVectorImpl<ISD::OutputArg> &Outs,
          const SmallVectorImpl<SDValue> &OutVals,
          const SmallVectorImpl<ISD::InputArg> &Ins,
          DebugLoc DL, SelectionDAG &DAG,
          SmallVectorImpl<SDValue> &InVals) const
{
    // AVM2 target does not yet support tail call optimization.
    isTailCall = false;

    // Count the size of the outgoing arguments.
    unsigned ArgsSize = 0;

    for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
        switch (OutVals[i].getValueType().getSimpleVT().SimpleTy) {
        default:
            assert(0 && "Unknown value type!");
        case MVT::i1:
        case MVT::i8:
        case MVT::i16:
        case MVT::i32:
        case MVT::f32:
            ArgsSize += 4;
            break;
        case MVT::i64:
        case MVT::f64:
            ArgsSize += 8;
            break;
        }
    }

    unsigned Align = getTargetMachine().getFrameLowering()->getStackAlignment();
    unsigned AlignAdjust = (Align - (ArgsSize % Align)) % Align;
    ArgsSize += AlignAdjust;
    unsigned ArgOffset = 0;

    Chain = DAG.getCALLSEQ_START(Chain,DAG.getIntPtrConstant(ArgsSize, true));
    // Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));

    // Analyze operands of the call, assigning locations to each operand.
    SmallVector<CCValAssign, 16> ArgLocs;
    CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs, *DAG.getContext());
    CCInfo.AnalyzeCallOperands(Outs, CC_AVM2_32);

    SDValue StackPtr;
    SmallVector<SDValue, 8> MemOpChains;
    for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
        SDValue Val = OutVals[i];
        EVT ObjectVT = Val.getValueType();
        SDValue ValToStore(0, 0);
        unsigned ObjSize;
        switch (ObjectVT.getSimpleVT().SimpleTy) {
        default:
            assert(0 && "Unhandled argument type!");
        case MVT::i1:
        case MVT::i8:
        case MVT::i16: {
            CCValAssign &VA = ArgLocs[i];
            // Promote the integer to 32-bits.  If the input type is signed, use a
            // sign extend, otherwise use a zero extend.
            ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
            if (VA.getLocInfo() == CCValAssign::SExt) {
                ExtendKind = ISD::SIGN_EXTEND;
            } else if (VA.getLocInfo() == CCValAssign::ZExt) {
                ExtendKind = ISD::ZERO_EXTEND;
            } else if (VA.getLocInfo() == CCValAssign::AExt) {
                ExtendKind = ISD::ANY_EXTEND;
            }
            Val = DAG.getNode(ExtendKind, DL, MVT::i32, Val);
            // FALL THROUGH
        }
        case MVT::i32: // TODO unify
            ObjSize = 4;
            ValToStore = Val;
            break;
        case MVT::f32:
            ObjSize = 4;
            ValToStore = Val;
            break;
        case MVT::f64:
            ObjSize = 8;
            ValToStore = Val;
            break;
        case MVT::i64:
            ObjSize = 8;
            ValToStore = Val; // Whole thing is passed in memory.
            break;
        }


        if (ValToStore.getNode()) {
            SDValue StackPtr = DAG.getRegister(AVM2::ESP, MVT::i32);
            SDValue PtrOff = DAG.getConstant(ArgOffset, MVT::i32);
            PtrOff = DAG.getNode(ISD::ADD, DL, MVT::i32, StackPtr, PtrOff);
            if(ObjectVT == MVT::i64) { // 2 stores for 64 bit
                SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, ValToStore, DAG.getConstant(0, MVT::i32));
                SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, ValToStore, DAG.getConstant(1, MVT::i32));
                SDValue PtrOff4 = DAG.getNode(ISD::ADD, DL, MVT::i32, PtrOff, DAG.getConstant(4, MVT::i32));

                MemOpChains.push_back(DAG.getStore(Chain, DL, Lo, PtrOff, MachinePointerInfo(), false, false, 0));
                MemOpChains.push_back(DAG.getStore(Chain, DL, Hi, PtrOff4, MachinePointerInfo(), false, false, 0));
            } else
                MemOpChains.push_back(DAG.getStore(Chain, DL, ValToStore,
                                                   PtrOff, MachinePointerInfo(),
                                                   false, false, 0));
        }

        ArgOffset += ObjSize;
    }

    // Emit all stores, make sure the occur before any copies into physregs.
    if (!MemOpChains.empty()) {
        Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, &MemOpChains[0], MemOpChains.size());
    }

    std::vector<EVT> NodeTys;
    NodeTys.push_back(MVT::Other); // Returns a chain
    NodeTys.push_back(MVT::Glue);  // Returns a flag for retval copy to use.
    SDValue Ops[] = { Chain, Callee };
    Chain = DAG.getNode(AVM2ISD::CALL, DL, NodeTys, Ops, 2);
    SDValue InFlag = Chain.getValue(1);
    // Chain = DAG.getNode(ISD::CALLSEQ_END, DL, MVT::Other, Chain, DAG.getConstant(ArgsSize, getPointerTy()));
    Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true), DAG.getIntPtrConstant(0, true), InFlag);

    // If the function returns void, just return the chain.
    if (Ins.empty()) {
        return Chain;
    }

    InFlag = Chain.getValue(1);

    /*
    	// Assign locations to each value returned by this call.
    	SmallVector<CCValAssign, 16> RVLocs;
    	CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
    				   RVLocs, *DAG.getContext());

    	RVInfo.AnalyzeCallResult(Ins, RetCC_AVM2_32);
    	const MVT::SimpleValueType RetTyVT = RVLocs.size() == 0 ? MVT::isVoid : RVLocs[0].getValVT().SimpleTy;

    	// Copy all of the result registers out of their specified physreg.
    	for (unsigned i = 0; i != RVLocs.size(); ++i) {
    		unsigned Reg = RVLocs[i].getLocReg();
    		Chain = DAG.getCopyFromReg(Chain, DL, Reg,
    								   RVLocs[i].getValVT(), InFlag).getValue(1);
    		InFlag = Chain.getValue(2);
    		InVals.push_back(Chain.getValue(0));
    	}
    */

    SmallVector<CCValAssign, 16> RVLocs;
    CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
                   RVLocs, *DAG.getContext());
    if(!RVInfo.CheckReturn(Ins, RetCC_AVM2_32)) {
      report_fatal_error("Flascc does not yet support LLVM SIMD intrinsics.\n");
    }

    for (unsigned i = 0, e = Ins.size(); i != e; ++i) {

        const MVT::SimpleValueType RetTyVT = Ins[i].VT.SimpleTy;

        SDValue RetVal;
        if (RetTyVT != MVT::isVoid) {
            // SDVTList Tys = DAG.getVTList(AVM2::EAX, MVT::i32, MVT::Glue);

            switch (RetTyVT) {
            default:
                assert(0 && "Unknown value type to return!");
            case MVT::i1:
            case MVT::i8:
            case MVT::i16: {
                assert( i <= 1 && "More than 2 return values for i1/i8/i16." );
                if( i == 0 ) {
                    RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::EAX, MVT::i32, InFlag);
                } else {
                    RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::EDX, MVT::i32, InFlag);
                }

                Chain = RetVal.getValue(1);
                InFlag = Chain.getValue(2);

                // Add a note to keep track of whether it is sign or zero extended.
                CCValAssign &VA = RVLocs[i];
                ISD::NodeType AssertKind = ISD::AssertZext;
                if (VA.getLocInfo() == CCValAssign::SExt) {
                    AssertKind = ISD::AssertSext;
                }
                RetVal = DAG.getNode(AssertKind, DL, MVT::i32, RetVal,
                                     DAG.getValueType(RetTyVT));
                RetVal = DAG.getNode(ISD::TRUNCATE, DL, RetTyVT, RetVal);
                break;
            }
            case MVT::i32:
                assert( i <= 1 && "More than 2 return values for i32." );
                if( i == 0 ) {
                    RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::EAX, MVT::i32, InFlag);
                } else {
                    RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::EDX, MVT::i32, InFlag);
                }

                Chain = RetVal.getValue(1);
                InFlag = Chain.getValue(2);
                // Chain = DAG.getCopyFromReg(Chain, DL, AVM2::EAX, MVT::i32, InFlag);
                break;
            case MVT::f32:
                assert( i == 0 && "More than 1 return value for f32." );
                RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::SST0, MVT::f32, InFlag);
                Chain = RetVal.getValue(1);
                InFlag = Chain.getValue(2);
                break;
            case MVT::f64:
                assert( i == 0 && "More than 1 return value for f64." );
                RetVal = DAG.getCopyFromReg(Chain, DL, AVM2::ST0, MVT::f64, InFlag);
                Chain = RetVal.getValue(1);
                InFlag = Chain.getValue(2);
                break;
            case MVT::i64: {
                assert( i == 0 && "More than 1 return value for i64." );
                SDValue Lo = DAG.getCopyFromReg(Chain, DL, AVM2::EAX, MVT::i32, InFlag);
                SDValue Hi = DAG.getCopyFromReg(Lo.getValue(1), DL, AVM2::EDX, MVT::i32,
                                                Lo.getValue(2));
                RetVal = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
                Chain = Hi.getValue(1);
                InFlag = Chain.getValue(2);
            }
            break;
            }
        }

        InVals.push_back(Chain.getValue(0));
    }


#ifdef _DEBUG
    int InVals_size = InVals.size();
    int Ins_size = Ins.size();
    const char* err;

    // pre-check conditions that will assert in TargetLowering::LowerCallTo()
    if( InVals_size != Ins_size ) {
        // "LowerCall didn't emit the correct number of values!"
        Ins_size = InVals_size;
    }

    for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
        if( !InVals[i].getNode()  ) {
            err = "LowerCall emitted a null value!";
        }

        EVT vt = Ins[i].VT;
        if( vt != InVals[i].getValueType() ) {
            err = "LowerCall emitted a value with the wrong type!";
            EVT vt1 = Ins[i].VT;
            EVT vt2 = InVals[i].getValueType();
            vt1 = vt2;
        }
    }

#endif

    return Chain;
}
SDValue
SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
                               CallingConv::ID CallConv, bool isVarArg,
                               bool &isTailCall,
                               const SmallVectorImpl<ISD::OutputArg> &Outs,
                               const SmallVectorImpl<ISD::InputArg> &Ins,
                               DebugLoc dl, SelectionDAG &DAG,
                               SmallVectorImpl<SDValue> &InVals) const {
  // Sparc target does not yet support tail call optimization.
  isTailCall = false;

#if 0
  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs);
  CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);

  // Get the size of the outgoing arguments stack space requirement.
  unsigned ArgsSize = CCInfo.getNextStackOffset();
  // FIXME: We can't use this until f64 is known to take two GPRs.
#else
  (void)CC_Sparc32;

  // Count the size of the outgoing arguments.
  unsigned ArgsSize = 0;
  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
    switch (Outs[i].Val.getValueType().getSimpleVT().SimpleTy) {
      default: llvm_unreachable("Unknown value type!");
      case MVT::i1:
      case MVT::i8:
      case MVT::i16:
      case MVT::i32:
      case MVT::f32:
        ArgsSize += 4;
        break;
      case MVT::i64:
      case MVT::f64:
        ArgsSize += 8;
        break;
    }
  }
  if (ArgsSize > 4*6)
    ArgsSize -= 4*6;    // Space for first 6 arguments is prereserved.
  else
    ArgsSize = 0;
#endif

  // Keep stack frames 8-byte aligned.
  ArgsSize = (ArgsSize+7) & ~7;

  Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));

  SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
  SmallVector<SDValue, 8> MemOpChains;

#if 0
  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue Arg = Outs[i].Val;

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    default: llvm_unreachable("Unknown loc info!");
    case CCValAssign::Full: break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
      break;
    }

    // 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));
      continue;
    }

    assert(VA.isMemLoc());

    // Create a store off the stack pointer for this argument.
    SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
    // FIXME: VERIFY THAT 68 IS RIGHT.
    SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+68);
    PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
    MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0,
                                       false, false, 0));
  }

#else
  static const unsigned ArgRegs[] = {
    SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
  };
  unsigned ArgOffset = 68;

  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
    SDValue Val = Outs[i].Val;
    EVT ObjectVT = Val.getValueType();
    SDValue ValToStore(0, 0);
    unsigned ObjSize;
    switch (ObjectVT.getSimpleVT().SimpleTy) {
    default: llvm_unreachable("Unhandled argument type!");
    case MVT::i32:
      ObjSize = 4;

      if (RegsToPass.size() >= 6) {
        ValToStore = Val;
      } else {
        RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val));
      }
      break;
    case MVT::f32:
      ObjSize = 4;
      if (RegsToPass.size() >= 6) {
        ValToStore = Val;
      } else {
        // Convert this to a FP value in an int reg.
        Val = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Val);
        RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val));
      }
      break;
    case MVT::f64: {
      ObjSize = 8;
      if (RegsToPass.size() >= 6) {
        ValToStore = Val;    // Whole thing is passed in memory.
        break;
      }

      // Break into top and bottom parts by storing to the stack and loading
      // out the parts as integers.  Top part goes in a reg.
      SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32);
      SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, 
                                   Val, StackPtr, NULL, 0,
                                   false, false, 0);
      // Sparc is big-endian, so the high part comes first.
      SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0,
                               false, false, 0);
      // Increment the pointer to the other half.
      StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
                             DAG.getIntPtrConstant(4));
      // Load the low part.
      SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0,
                               false, false, 0);

      RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));

      if (RegsToPass.size() >= 6) {
        ValToStore = Lo;
        ArgOffset += 4;
        ObjSize = 4;
      } else {
        RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
      }
      break;
    }
    case MVT::i64: {
      ObjSize = 8;
      if (RegsToPass.size() >= 6) {
        ValToStore = Val;    // Whole thing is passed in memory.
        break;
      }

      // Split the value into top and bottom part.  Top part goes in a reg.
      SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val,
                                 DAG.getConstant(1, MVT::i32));
      SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val,
                                 DAG.getConstant(0, MVT::i32));
      RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));

      if (RegsToPass.size() >= 6) {
        ValToStore = Lo;
        ArgOffset += 4;
        ObjSize = 4;
      } else {
        RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
      }
      break;
    }
    }

    if (ValToStore.getNode()) {
      SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
      SDValue PtrOff = DAG.getConstant(ArgOffset, MVT::i32);
      PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
      MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore, 
                                         PtrOff, NULL, 0,
                                         false, false, 0));
    }
    ArgOffset += ObjSize;
  }
#endif

  // Emit all stores, make sure the occur before any copies into physregs.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                        &MemOpChains[0], MemOpChains.size());

  // Build a sequence of copy-to-reg nodes chained together with token
  // chain and flag operands which copy the outgoing args into registers.
  // The InFlag in necessary since all emited instructions must be
  // stuck together.
  SDValue InFlag;
  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
    unsigned Reg = RegsToPass[i].first;
    // Remap I0->I7 -> O0->O7.
    if (Reg >= SP::I0 && Reg <= SP::I7)
      Reg = Reg-SP::I0+SP::O0;

    Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);

  std::vector<EVT> NodeTys;
  NodeTys.push_back(MVT::Other);   // Returns a chain
  NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use.
  SDValue Ops[] = { Chain, Callee, InFlag };
  Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops, InFlag.getNode() ? 3 : 2);
  InFlag = Chain.getValue(1);

  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true),
                             DAG.getIntPtrConstant(0, true), InFlag);
  InFlag = Chain.getValue(1);

  // Assign locations to each value returned by this call.
  SmallVector<CCValAssign, 16> RVLocs;
  CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
                 RVLocs, *DAG.getContext());

  RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);

  // Copy all of the result registers out of their specified physreg.
  for (unsigned i = 0; i != RVLocs.size(); ++i) {
    unsigned Reg = RVLocs[i].getLocReg();

    // Remap I0->I7 -> O0->O7.
    if (Reg >= SP::I0 && Reg <= SP::I7)
      Reg = Reg-SP::I0+SP::O0;

    Chain = DAG.getCopyFromReg(Chain, dl, Reg,
                               RVLocs[i].getValVT(), InFlag).getValue(1);
    InFlag = Chain.getValue(2);
    InVals.push_back(Chain.getValue(0));
  }

  return Chain;
}
SDValue
AlphaTargetLowering::LowerFormalArguments(SDValue Chain,
                                          unsigned CallConv, bool isVarArg,
                                          const SmallVectorImpl<ISD::InputArg>
                                            &Ins,
                                          DebugLoc dl, SelectionDAG &DAG,
                                          SmallVectorImpl<SDValue> &InVals) {

  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo *MFI = MF.getFrameInfo();

  unsigned args_int[] = {
    Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21};
  unsigned args_float[] = {
    Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21};
  
  for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
    SDValue argt;
    EVT ObjectVT = Ins[ArgNo].VT;
    SDValue ArgVal;

    if (ArgNo  < 6) {
      switch (ObjectVT.getSimpleVT().SimpleTy) {
      default:
        assert(false && "Invalid value type!");
      case MVT::f64:
        args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 
                                      &Alpha::F8RCRegClass);
        ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
        break;
      case MVT::f32:
        args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], 
                                      &Alpha::F4RCRegClass);
        ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT);
        break;
      case MVT::i64:
        args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], 
                                    &Alpha::GPRCRegClass);
        ArgVal = DAG.getCopyFromReg(Chain, dl, args_int[ArgNo], MVT::i64);
        break;
      }
    } else { //more args
      // Create the frame index object for this incoming parameter...
      int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6));

      // Create the SelectionDAG nodes corresponding to a load
      //from this parameter
      SDValue FIN = DAG.getFrameIndex(FI, MVT::i64);
      ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0);
    }
    InVals.push_back(ArgVal);
  }

  // If the functions takes variable number of arguments, copy all regs to stack
  if (isVarArg) {
    VarArgsOffset = Ins.size() * 8;
    std::vector<SDValue> LS;
    for (int i = 0; i < 6; ++i) {
      if (TargetRegisterInfo::isPhysicalRegister(args_int[i]))
        args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass);
      SDValue argt = DAG.getCopyFromReg(Chain, dl, args_int[i], MVT::i64);
      int FI = MFI->CreateFixedObject(8, -8 * (6 - i));
      if (i == 0) VarArgsBase = FI;
      SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64);
      LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));

      if (TargetRegisterInfo::isPhysicalRegister(args_float[i]))
        args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass);
      argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64);
      FI = MFI->CreateFixedObject(8, - 8 * (12 - i));
      SDFI = DAG.getFrameIndex(FI, MVT::i64);
      LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0));
    }

    //Set up a token factor with all the stack traffic
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size());
  }

  return Chain;
}
/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
/// passed in either one or two GPRs, including FP values.  TODO: we should
/// pass FP values in FP registers for fastcc functions.
SDValue
SparcTargetLowering::LowerFormalArguments(SDValue Chain,
                                          CallingConv::ID CallConv, bool isVarArg,
                                          const SmallVectorImpl<ISD::InputArg>
                                            &Ins,
                                          DebugLoc dl, SelectionDAG &DAG,
                                          SmallVectorImpl<SDValue> &InVals)
                                            const {

  MachineFunction &MF = DAG.getMachineFunction();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());
  CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);

  static const unsigned ArgRegs[] = {
    SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
  };
  const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
  unsigned ArgOffset = 68;

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    SDValue ArgValue;
    CCValAssign &VA = ArgLocs[i];
    // FIXME: We ignore the register assignments of AnalyzeFormalArguments
    // because it doesn't know how to split a double into two i32 registers.
    EVT ObjectVT = VA.getValVT();
    switch (ObjectVT.getSimpleVT().SimpleTy) {
    default: llvm_unreachable("Unhandled argument type!");
    case MVT::i1:
    case MVT::i8:
    case MVT::i16:
    case MVT::i32:
      if (!Ins[i].Used) {                  // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        InVals.push_back(DAG.getUNDEF(ObjectVT));
      } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
        unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
        MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
        SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
        if (ObjectVT != MVT::i32) {
          unsigned AssertOp = ISD::AssertSext;
          Arg = DAG.getNode(AssertOp, dl, MVT::i32, Arg,
                            DAG.getValueType(ObjectVT));
          Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg);
        }
        InVals.push_back(Arg);
      } else {
        int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset,
                                                            true, false);
        SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
        SDValue Load;
        if (ObjectVT == MVT::i32) {
          Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0,
                             false, false, 0);
        } else {
          ISD::LoadExtType LoadOp = ISD::SEXTLOAD;

          // Sparc is big endian, so add an offset based on the ObjectVT.
          unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8);
          FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
                              DAG.getConstant(Offset, MVT::i32));
          Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr,
                                NULL, 0, ObjectVT, false, false, 0);
          Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load);
        }
        InVals.push_back(Load);
      }

      ArgOffset += 4;
      break;
    case MVT::f32:
      if (!Ins[i].Used) {                  // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        InVals.push_back(DAG.getUNDEF(ObjectVT));
      } else if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
        // FP value is passed in an integer register.
        unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
        MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
        SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);

        Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg);
        InVals.push_back(Arg);
      } else {
        int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset,
                                                            true, false);
        SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
        SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0,
                                   false, false, 0);
        InVals.push_back(Load);
      }
      ArgOffset += 4;
      break;

    case MVT::i64:
    case MVT::f64:
      if (!Ins[i].Used) {                // Argument is dead.
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        if (CurArgReg < ArgRegEnd) ++CurArgReg;
        InVals.push_back(DAG.getUNDEF(ObjectVT));
      } else {
        SDValue HiVal;
        if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
          unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
          MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
          HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
        } else {
          int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset,
                                                              true, false);
          SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
          HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0,
                              false, false, 0);
        }

        SDValue LoVal;
        if (CurArgReg < ArgRegEnd) {  // Lives in an incoming GPR
          unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
          MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
          LoVal = DAG.getCopyFromReg(Chain, dl, VRegLo, MVT::i32);
        } else {
          int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4,
                                                              true, false);
          SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
          LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0,
                              false, false, 0);
        }

        // Compose the two halves together into an i64 unit.
        SDValue WholeValue =
          DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);

        // If we want a double, do a bit convert.
        if (ObjectVT == MVT::f64)
          WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue);

        InVals.push_back(WholeValue);
      }
      ArgOffset += 8;
      break;
    }
  }

  // Store remaining ArgRegs to the stack if this is a varargs function.
  if (isVarArg) {
    // Remember the vararg offset for the va_start implementation.
    FuncInfo->setVarArgsFrameOffset(ArgOffset);

    std::vector<SDValue> OutChains;

    for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
      unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
      MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
      SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);

      int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset,
                                                          true, false);
      SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);

      OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0,
                                       false, false, 0));
      ArgOffset += 4;
    }

    if (!OutChains.empty()) {
      OutChains.push_back(Chain);
      Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                          &OutChains[0], OutChains.size());
    }
  }

  return Chain;
}
Example #23
0
SDValue PTXTargetLowering::
  LowerFormalArguments(SDValue Chain,
                       CallingConv::ID CallConv,
                       bool isVarArg,
                       const SmallVectorImpl<ISD::InputArg> &Ins,
                       DebugLoc dl,
                       SelectionDAG &DAG,
                       SmallVectorImpl<SDValue> &InVals) const {
  if (isVarArg) llvm_unreachable("PTX does not support varargs");

  MachineFunction &MF = DAG.getMachineFunction();
  PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();

  switch (CallConv) {
    default:
      llvm_unreachable("Unsupported calling convention");
      break;
    case CallingConv::PTX_Kernel:
      MFI->setKernel(true);
      break;
    case CallingConv::PTX_Device:
      MFI->setKernel(false);
      break;
  }

  // Make sure we don't add argument registers twice
  if (MFI->isDoneAddArg())
    llvm_unreachable("cannot add argument registers twice");

  // Reset argmap before allocation
  for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap);
       i != e; ++ i)
    i->reset();

  for (int i = 0, e = Ins.size(); i != e; ++ i) {
    MVT::SimpleValueType VT = Ins[i].VT.SimpleTy;

    struct argmap_entry *entry = std::find(argmap,
                                           argmap + array_lengthof(argmap), VT);
    if (entry == argmap + array_lengthof(argmap))
      llvm_unreachable("Type of argument is not supported");

    if (MFI->isKernel() && entry->RC == PTX::PredsRegisterClass)
      llvm_unreachable("cannot pass preds to kernel");

    MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();

    unsigned preg = *++(entry->loc); // allocate start from register 1
    unsigned vreg = RegInfo.createVirtualRegister(entry->RC);
    RegInfo.addLiveIn(preg, vreg);

    MFI->addArgReg(preg);

    SDValue inval;
    if (MFI->isKernel())
      inval = DAG.getNode(PTXISD::READ_PARAM, dl, VT, Chain,
                          DAG.getTargetConstant(i, MVT::i32));
    else
      inval = DAG.getCopyFromReg(Chain, dl, vreg, VT);
    InVals.push_back(inval);
  }

  MFI->doneAddArg();

  return Chain;
}
Example #24
0
/// Transform physical registers into virtual registers, and generate load
/// operations for argument places on the stack.
SDValue ARCTargetLowering::LowerCallArguments(
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,
    SmallVectorImpl<SDValue> &InVals) const {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  auto *AFI = MF.getInfo<ARCFunctionInfo>();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                 *DAG.getContext());

  CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);

  unsigned StackSlotSize = 4;

  if (!IsVarArg)
    AFI->setReturnStackOffset(CCInfo.getNextStackOffset());

  // All getCopyFromReg ops must precede any getMemcpys to prevent the
  // scheduler clobbering a register before it has been copied.
  // The stages are:
  // 1. CopyFromReg (and load) arg & vararg registers.
  // 2. Chain CopyFromReg nodes into a TokenFactor.
  // 3. Memcpy 'byVal' args & push final InVals.
  // 4. Chain mem ops nodes into a TokenFactor.
  SmallVector<SDValue, 4> CFRegNode;
  SmallVector<ArgDataPair, 4> ArgData;
  SmallVector<SDValue, 4> MemOps;

  // 1a. CopyFromReg (and load) arg registers.
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    SDValue ArgIn;

    if (VA.isRegLoc()) {
      // Arguments passed in registers
      EVT RegVT = VA.getLocVT();
      switch (RegVT.getSimpleVT().SimpleTy) {
      default: {
        DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
                     << RegVT.getSimpleVT().SimpleTy << "\n");
        llvm_unreachable("Unhandled LowerFormalArguments type.");
      }
      case MVT::i32:
        unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
        RegInfo.addLiveIn(VA.getLocReg(), VReg);
        ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
        CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
      }
    } else {
      // sanity check
      assert(VA.isMemLoc());
      // Load the argument to a virtual register
      unsigned ObjSize = VA.getLocVT().getStoreSize();
      assert((ObjSize <= StackSlotSize) && "Unhandled argument");

      // Create the frame index object for this incoming parameter...
      int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);

      // Create the SelectionDAG nodes corresponding to a load
      // from this parameter
      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
      ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
                          MachinePointerInfo::getFixedStack(MF, FI));
    }
    const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
    ArgData.push_back(ADP);
  }

  // 1b. CopyFromReg vararg registers.
  if (IsVarArg) {
    // Argument registers
    static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
                                        ARC::R4, ARC::R5, ARC::R6, ARC::R7};
    auto *AFI = MF.getInfo<ARCFunctionInfo>();
    unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
    if (FirstVAReg < array_lengthof(ArgRegs)) {
      int Offset = 0;
      // Save remaining registers, storing higher register numbers at a higher
      // address
      // There are (array_lengthof(ArgRegs) - FirstVAReg) registers which
      // need to be saved.
      int VarFI =
          MFI.CreateFixedObject((array_lengthof(ArgRegs) - FirstVAReg) * 4,
                                CCInfo.getNextStackOffset(), true);
      AFI->setVarArgsFrameIndex(VarFI);
      SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
      for (unsigned i = FirstVAReg; i < array_lengthof(ArgRegs); i++) {
        // Move argument from phys reg -> virt reg
        unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
        RegInfo.addLiveIn(ArgRegs[i], VReg);
        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
        CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
        SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
                                    DAG.getConstant(Offset, dl, MVT::i32));
        // Move argument from virt reg -> stack
        SDValue Store =
            DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
        MemOps.push_back(Store);
        Offset += 4;
      }
    } else {
      llvm_unreachable("Too many var args parameters.");
    }
  }

  // 2. Chain CopyFromReg nodes into a TokenFactor.
  if (!CFRegNode.empty())
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);

  // 3. Memcpy 'byVal' args & push final InVals.
  // Aggregates passed "byVal" need to be copied by the callee.
  // The callee will use a pointer to this copy, rather than the original
  // pointer.
  for (const auto &ArgDI : ArgData) {
    if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
      unsigned Size = ArgDI.Flags.getByValSize();
      unsigned Align = std::max(StackSlotSize, ArgDI.Flags.getByValAlign());
      // Create a new object on the stack and copy the pointee into it.
      int FI = MFI.CreateStackObject(Size, Align, false);
      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
      InVals.push_back(FIN);
      MemOps.push_back(DAG.getMemcpy(
          Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32), Align,
          false, false, false, MachinePointerInfo(), MachinePointerInfo()));
    } else {
      InVals.push_back(ArgDI.SDV);
    }
  }

  // 4. Chain mem ops nodes into a TokenFactor.
  if (!MemOps.empty()) {
    MemOps.push_back(Chain);
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
  }

  return Chain;
}
SDValue BPFTargetLowering::LowerFormalArguments(
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
    SmallVectorImpl<SDValue> &InVals) const {
  switch (CallConv) {
  default:
    llvm_unreachable("Unsupported calling convention");
  case CallingConv::C:
  case CallingConv::Fast:
    break;
  }

  MachineFunction &MF = DAG.getMachineFunction();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
  CCInfo.AnalyzeFormalArguments(Ins, CC_BPF64);

  for (auto &VA : ArgLocs) {
    if (VA.isRegLoc()) {
      // Arguments passed in registers
      EVT RegVT = VA.getLocVT();
      switch (RegVT.getSimpleVT().SimpleTy) {
      default: {
        errs() << "LowerFormalArguments Unhandled argument type: "
               << RegVT.getSimpleVT().SimpleTy << '\n';
        llvm_unreachable(0);
      }
      case MVT::i64:
        unsigned VReg = RegInfo.createVirtualRegister(&BPF::GPRRegClass);
        RegInfo.addLiveIn(VA.getLocReg(), VReg);
        SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);

        // If this is an 8/16/32-bit value, it is really passed promoted to 64
        // bits. Insert an assert[sz]ext to capture this, then truncate to the
        // right size.
        if (VA.getLocInfo() == CCValAssign::SExt)
          ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));
        else if (VA.getLocInfo() == CCValAssign::ZExt)
          ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));

        if (VA.getLocInfo() != CCValAssign::Full)
          ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);

        InVals.push_back(ArgValue);
      }
    } else {
      DiagnosticInfoUnsupported Err(DL, *MF.getFunction(),
                                    "defined with too many args", SDValue());
      DAG.getContext()->diagnose(Err);
    }
  }

  if (IsVarArg || MF.getFunction()->hasStructRetAttr()) {
    DiagnosticInfoUnsupported Err(
        DL, *MF.getFunction(),
        "functions with VarArgs or StructRet are not supported", SDValue());
    DAG.getContext()->diagnose(Err);
  }

  return Chain;
}
Example #26
0
// LowerCCCArguments - transform physical registers into virtual registers and
// generate load operations for arguments places on the stack.
SDValue LanaiTargetLowering::LowerCCCArguments(
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
    SmallVectorImpl<SDValue> &InVals) const {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  LanaiMachineFunctionInfo *LanaiMFI = MF.getInfo<LanaiMachineFunctionInfo>();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                 *DAG.getContext());
  if (CallConv == CallingConv::Fast) {
    CCInfo.AnalyzeFormalArguments(Ins, CC_Lanai32_Fast);
  } else {
    CCInfo.AnalyzeFormalArguments(Ins, CC_Lanai32);
  }

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    if (VA.isRegLoc()) {
      // Arguments passed in registers
      EVT RegVT = VA.getLocVT();
      switch (RegVT.getSimpleVT().SimpleTy) {
      case MVT::i32: {
        unsigned VReg = RegInfo.createVirtualRegister(&Lanai::GPRRegClass);
        RegInfo.addLiveIn(VA.getLocReg(), VReg);
        SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);

        // If this is an 8/16-bit value, it is really passed promoted to 32
        // bits. Insert an assert[sz]ext to capture this, then truncate to the
        // right size.
        if (VA.getLocInfo() == CCValAssign::SExt)
          ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));
        else if (VA.getLocInfo() == CCValAssign::ZExt)
          ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));

        if (VA.getLocInfo() != CCValAssign::Full)
          ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);

        InVals.push_back(ArgValue);
        break;
      }
      default:
        DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
                     << RegVT.getSimpleVT().SimpleTy << "\n");
        llvm_unreachable("unhandled argument type");
      }
    } else {
      // Sanity check
      assert(VA.isMemLoc());
      // Load the argument to a virtual register
      unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
      // Check that the argument fits in stack slot
      if (ObjSize > 4) {
        errs() << "LowerFormalArguments Unhandled argument type: "
               << EVT(VA.getLocVT()).getEVTString() << "\n";
      }
      // Create the frame index object for this incoming parameter...
      int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);

      // Create the SelectionDAG nodes corresponding to a load
      // from this parameter
      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
      InVals.push_back(DAG.getLoad(
          VA.getLocVT(), DL, Chain, FIN,
          MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI),
          false, false, false, 0));
    }
  }

  // The Lanai ABI for returning structs by value requires that we copy
  // the sret argument into rv for the return. Save the argument into
  // a virtual register so that we can access it from the return points.
  if (MF.getFunction()->hasStructRetAttr()) {
    unsigned Reg = LanaiMFI->getSRetReturnReg();
    if (!Reg) {
      Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
      LanaiMFI->setSRetReturnReg(Reg);
    }
    SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[0]);
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
  }

  if (IsVarArg) {
    // Record the frame index of the first variable argument
    // which is a value necessary to VASTART.
    int FI = MFI->CreateFixedObject(4, CCInfo.getNextStackOffset(), true);
    LanaiMFI->setVarArgsFrameIndex(FI);
  }

  return Chain;
}
Example #27
0
/// LowerCCCArguments - transform physical registers into virtual registers and
/// generate load operations for arguments places on the stack.
// FIXME: struct return stuff
// FIXME: varargs
SDValue
MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
                                        CallingConv::ID CallConv,
                                        bool isVarArg,
                                        const SmallVectorImpl<ISD::InputArg>
                                          &Ins,
                                        DebugLoc dl,
                                        SelectionDAG &DAG,
                                        SmallVectorImpl<SDValue> &InVals)
                                          const {
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo *MFI = MF.getFrameInfo();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();

  // Assign locations to all of the incoming arguments.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
                 ArgLocs, *DAG.getContext());
  CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430);

  assert(!isVarArg && "Varargs not supported yet");

  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];
    if (VA.isRegLoc()) {
      // Arguments passed in registers
      EVT RegVT = VA.getLocVT();
      switch (RegVT.getSimpleVT().SimpleTy) {
      default:
        {
#ifndef NDEBUG
          errs() << "LowerFormalArguments Unhandled argument type: "
               << RegVT.getSimpleVT().SimpleTy << "\n";
#endif
          llvm_unreachable(0);
        }
      case MVT::i16:
        unsigned VReg =
          RegInfo.createVirtualRegister(MSP430::GR16RegisterClass);
        RegInfo.addLiveIn(VA.getLocReg(), VReg);
        SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);

        // If this is an 8-bit value, it is really passed promoted to 16
        // bits. Insert an assert[sz]ext to capture this, then truncate to the
        // right size.
        if (VA.getLocInfo() == CCValAssign::SExt)
          ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));
        else if (VA.getLocInfo() == CCValAssign::ZExt)
          ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
                                 DAG.getValueType(VA.getValVT()));

        if (VA.getLocInfo() != CCValAssign::Full)
          ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);

        InVals.push_back(ArgValue);
      }
    } else {
      // Sanity check
      assert(VA.isMemLoc());
      // Load the argument to a virtual register
      unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
      if (ObjSize > 2) {
        errs() << "LowerFormalArguments Unhandled argument type: "
             << EVT(VA.getLocVT()).getEVTString()
             << "\n";
      }
      // Create the frame index object for this incoming parameter...
      int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);

      // Create the SelectionDAG nodes corresponding to a load
      //from this parameter
      SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);
      InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
                                   MachinePointerInfo::getFixedStack(FI),
                                   false, false, 0));
    }
  }

  return Chain;
}
Example #28
0
// LowerCCCCallTo - functions arguments are copied from virtual regs to
// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
SDValue LanaiTargetLowering::LowerCCCCallTo(
    SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool IsVarArg,
    bool IsTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
    const SmallVectorImpl<SDValue> &OutVals,
    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
    SmallVectorImpl<SDValue> &InVals) const {
  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
                 *DAG.getContext());
  GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
  MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();

  NumFixedArgs = 0;
  if (IsVarArg && G) {
    const Function *CalleeFn = dyn_cast<Function>(G->getGlobal());
    if (CalleeFn)
      NumFixedArgs = CalleeFn->getFunctionType()->getNumParams();
  }
  if (NumFixedArgs)
    CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32_VarArg);
  else {
    if (CallConv == CallingConv::Fast)
      CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32_Fast);
    else
      CCInfo.AnalyzeCallOperands(Outs, CC_Lanai32);
  }

  // Get a count of how many bytes are to be pushed on the stack.
  unsigned NumBytes = CCInfo.getNextStackOffset();

  // Create local copies for byval args.
  SmallVector<SDValue, 8> ByValArgs;
  for (unsigned I = 0, E = Outs.size(); I != E; ++I) {
    ISD::ArgFlagsTy Flags = Outs[I].Flags;
    if (!Flags.isByVal())
      continue;

    SDValue Arg = OutVals[I];
    unsigned Size = Flags.getByValSize();
    unsigned Align = Flags.getByValAlign();

    int FI = MFI->CreateStackObject(Size, Align, false);
    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
    SDValue SizeNode = DAG.getConstant(Size, DL, MVT::i32);

    Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Align,
                          /*IsVolatile=*/false,
                          /*AlwaysInline=*/false,
                          /*IsTailCall=*/false, MachinePointerInfo(),
                          MachinePointerInfo());
    ByValArgs.push_back(FIPtr);
  }

  Chain = DAG.getCALLSEQ_START(
      Chain,
      DAG.getConstant(NumBytes, DL, getPointerTy(DAG.getDataLayout()), true),
      DL);

  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
  SmallVector<SDValue, 12> MemOpChains;
  SDValue StackPtr;

  // Walk the register/memloc assignments, inserting copies/loads.
  for (unsigned I = 0, J = 0, E = ArgLocs.size(); I != E; ++I) {
    CCValAssign &VA = ArgLocs[I];
    SDValue Arg = OutVals[I];
    ISD::ArgFlagsTy Flags = Outs[I].Flags;

    // Promote the value if needed.
    switch (VA.getLocInfo()) {
    case CCValAssign::Full:
      break;
    case CCValAssign::SExt:
      Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::ZExt:
      Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    case CCValAssign::AExt:
      Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
      break;
    default:
      llvm_unreachable("Unknown loc info!");
    }

    // Use local copy if it is a byval arg.
    if (Flags.isByVal())
      Arg = ByValArgs[J++];

    // 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 {
      assert(VA.isMemLoc());

      if (StackPtr.getNode() == 0)
        StackPtr = DAG.getCopyFromReg(Chain, DL, Lanai::SP,
                                      getPointerTy(DAG.getDataLayout()));

      SDValue PtrOff =
          DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr,
                      DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));

      MemOpChains.push_back(DAG.getStore(
          Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, false, 0));
    }
  }

  // Transform all store nodes into one single node because all store nodes are
  // independent of each other.
  if (!MemOpChains.empty())
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
                        ArrayRef<SDValue>(&MemOpChains[0], MemOpChains.size()));

  SDValue InFlag;

  // Build a sequence of copy-to-reg nodes chained together with token chain and
  // flag operands which copy the outgoing args into registers.  The InFlag in
  // necessary since all emitted instructions must be stuck together.
  for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
    Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[I].first,
                             RegsToPass[I].second, InFlag);
    InFlag = Chain.getValue(1);
  }

  // If the callee is a GlobalAddress node (quite common, every direct call is)
  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
  // Likewise ExternalSymbol -> TargetExternalSymbol.
  uint8_t OpFlag = LanaiII::MO_NO_FLAG;
  if (G) {
    Callee = DAG.getTargetGlobalAddress(
        G->getGlobal(), DL, getPointerTy(DAG.getDataLayout()), 0, OpFlag);
  } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
    Callee = DAG.getTargetExternalSymbol(
        E->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlag);
  }

  // Returns a chain & a flag for retval copy to use.
  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add a register mask operand representing the call-preserved registers.
  // TODO: Should return-twice functions be handled?
  const uint32_t *Mask =
      TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
  assert(Mask && "Missing call preserved mask for calling convention");
  Ops.push_back(DAG.getRegisterMask(Mask));

  // Add argument registers to the end of the list so that they are
  // known live into the call.
  for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I)
    Ops.push_back(DAG.getRegister(RegsToPass[I].first,
                                  RegsToPass[I].second.getValueType()));

  if (InFlag.getNode())
    Ops.push_back(InFlag);

  Chain = DAG.getNode(LanaiISD::CALL, DL, NodeTys,
                      ArrayRef<SDValue>(&Ops[0], Ops.size()));
  InFlag = Chain.getValue(1);

  // Create the CALLSEQ_END node.
  Chain = DAG.getCALLSEQ_END(
      Chain,
      DAG.getConstant(NumBytes, DL, getPointerTy(DAG.getDataLayout()), true),
      DAG.getConstant(0, DL, getPointerTy(DAG.getDataLayout()), true), InFlag,
      DL);
  InFlag = Chain.getValue(1);

  // Handle result values, copying them out of physregs into vregs that we
  // return.
  return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG,
                         InVals);
}
Example #29
0
SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
  SDValue LHS   = Op.getOperand(0);
  SDValue RHS   = Op.getOperand(1);
  DebugLoc dl   = Op.getDebugLoc();

  // If we are doing an AND and testing against zero, then the CMP
  // will not be generated.  The AND (or BIT) will generate the condition codes,
  // but they are different from CMP.
  // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
  // lowering & isel wouldn't diverge.
  bool andCC = false;
  if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
    if (RHSC->isNullValue() && LHS.hasOneUse() &&
        (LHS.getOpcode() == ISD::AND ||
         (LHS.getOpcode() == ISD::TRUNCATE &&
          LHS.getOperand(0).getOpcode() == ISD::AND))) {
      andCC = true;
    }
  }
  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
  SDValue TargetCC;
  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);

  // Get the condition codes directly from the status register, if its easy.
  // Otherwise a branch will be generated.  Note that the AND and BIT
  // instructions generate different flags than CMP, the carry bit can be used
  // for NE/EQ.
  bool Invert = false;
  bool Shift = false;
  bool Convert = true;
  switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
   default:
    Convert = false;
    break;
   case MSP430CC::COND_HS:
     // Res = SRW & 1, no processing is required
     break;
   case MSP430CC::COND_LO:
     // Res = ~(SRW & 1)
     Invert = true;
     break;
   case MSP430CC::COND_NE:
     if (andCC) {
       // C = ~Z, thus Res = SRW & 1, no processing is required
     } else {
       // Res = ~((SRW >> 1) & 1)
       Shift = true;
       Invert = true;
     }
     break;
   case MSP430CC::COND_E:
     Shift = true;
     // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however,
     // Res = (SRW >> 1) & 1 is 1 word shorter.
     break;
  }
  EVT VT = Op.getValueType();
  SDValue One  = DAG.getConstant(1, VT);
  if (Convert) {
    SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW,
                                    MVT::i16, Flag);
    if (Shift)
      // FIXME: somewhere this is turned into a SRL, lower it MSP specific?
      SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);
    SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One);
    if (Invert)
      SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One);
    return SR;
  } else {
    SDValue Zero = DAG.getConstant(0, VT);
    SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
    SmallVector<SDValue, 4> Ops;
    Ops.push_back(One);
    Ops.push_back(Zero);
    Ops.push_back(TargetCC);
    Ops.push_back(Flag);
    return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
  }
}
Example #30
0
SDValue NvfcTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
  SDValue LHS   = Op.getOperand(0);
  SDValue RHS   = Op.getOperand(1);
  DebugLoc dl   = Op.getDebugLoc();

  // If we are doing an AND and testing against zero, then the CMP
  // will not be generated.  The AND (or OR) will generate the condition codes,
  // but they are different from CMP.
  // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
  // lowering & isel wouldn't diverge.
  bool andCC = false;
  if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
    if (RHSC->isNullValue() && LHS.hasOneUse() &&
        (LHS.getOpcode() == ISD::AND ||
         (LHS.getOpcode() == ISD::TRUNCATE &&
          LHS.getOperand(0).getOpcode() == ISD::AND))) {
      andCC = true;
    }
  }
  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
  SDValue TargetCC;
  SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);

  // Get the condition codes directly from the status register, if its easy.
  // Otherwise a branch will be generated.  Note that the AND and OR
  // instructions generate different flags than CMP, the carry bit can be used
  // for NE/EQ.
  bool Invert = false;
  bool Convert = true;
  int Shamt = 0; 
  switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
   default:
    Convert = false;
    break;
   case NvfcCC::COND_HS:
     // Res = (FLG >> 8) & 1
     Shamt = 8;
     break;
   case NvfcCC::COND_LO:
     // Res = ~((FLG >> 8) & 1)
     Shamt = 8;    
     Invert = true;
     break;
   case NvfcCC::COND_NE:
     if (andCC) {
       // C = ~Z, thus Res = (FLG >> 8) & 1
       Shamt = 8;
     } else {
       // Res = ~((FLG >> 0xb) & 1)
       Shamt = 0xb;
       Invert = true;
     }
     break;
   case NvfcCC::COND_E:
     // Res = (FLG >> 0xb) & 1
     Shamt = 0xb;
     break;
  }
  EVT VT = Op.getValueType();
  SDValue One  = DAG.getConstant(1, VT);
  if (Convert) {
    SDValue Shift = DAG.getConstant(Shamt, VT);
    SDValue FLG = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Nvfc::FLG,
    				     MVT::i32, Flag);
    FLG = DAG.getNode(NvfcISD::XBIT, dl, MVT::i32, FLG, Shift, Flag);
    if (Invert) {
	FLG = DAG.getNode(ISD::XOR, dl, MVT::i32, FLG, One);
	//FLG = DAG.getNode(ISD::NOT, dl, MVT::i32, FLG);
    }
    
    return FLG;
  } else {
    SDValue Zero = DAG.getConstant(0, VT);
    SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
    SmallVector<SDValue, 4> Ops;
    Ops.push_back(One);
    Ops.push_back(Zero);
    Ops.push_back(TargetCC);
    Ops.push_back(Flag);
    return DAG.getNode(NvfcISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
  }
}