diff options
| author | Anton Korobeynikov <asl@math.spbu.ru> | 2009-07-16 13:28:59 +0000 | 
|---|---|---|
| committer | Anton Korobeynikov <asl@math.spbu.ru> | 2009-07-16 13:28:59 +0000 | 
| commit | cf4ba97dba12002ebb09e6b922596b7f2285205e (patch) | |
| tree | c34912d8e3aee3aea2d28b1fdf01ccd7e4a00a70 /llvm/lib | |
| parent | a3ceeaeda59a7e67a6e9c1cd090848f808e9f9bf (diff) | |
| download | bcm5719-llvm-cf4ba97dba12002ebb09e6b922596b7f2285205e.tar.gz bcm5719-llvm-cf4ba97dba12002ebb09e6b922596b7f2285205e.zip  | |
Minimal lowering for formal_arguments / ret
llvm-svn: 75911
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 147 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.h | 13 | ||||
| -rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 15 | 
3 files changed, 174 insertions, 1 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 31572af1bd3..e22df99b834 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -48,10 +48,15 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :    setStackPointerRegisterToSaveRestore(SystemZ::R15);    setSchedulingPreference(SchedulingForLatency); + +  setOperationAction(ISD::RET,              MVT::Other, Custom); +  }  SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {    switch (Op.getOpcode()) { +  case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG); +  case ISD::RET:              return LowerRET(Op, DAG);    default:      assert(0 && "unimplemented operand");      return SDValue(); @@ -64,8 +69,150 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {  #include "SystemZGenCallingConv.inc" +SDValue SystemZTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, +                                                     SelectionDAG &DAG) { +  unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); +  switch (CC) { +  default: +    assert(0 && "Unsupported calling convention"); +  case CallingConv::C: +  case CallingConv::Fast: +    return LowerCCCArguments(Op, DAG); +  } +} + +/// 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 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_SystemZ); + +  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::i64: +        unsigned VReg = +          RegInfo.createVirtualRegister(SystemZ::GR64RegisterClass); +        RegInfo.addLiveIn(VA.getLocReg(), VReg); +        SDValue ArgValue = DAG.getCopyFromReg(Root, 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); + +        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 > 8) { +        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::i64); +      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 SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { +  // CCValAssign - represent the assignment of the return value to a location +  SmallVector<CCValAssign, 16> RVLocs; +  unsigned CC   = DAG.getMachineFunction().getFunction()->getCallingConv(); +  bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); +  DebugLoc dl = Op.getDebugLoc(); + +  // CCState - Info about the registers and stack slot. +  CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs); + +  // Analize return values of ISD::RET +  CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SystemZ); + +  // If this is the first return lowered for this function, add the regs to the +  // liveout set for the function. +  if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { +    for (unsigned i = 0; i != RVLocs.size(); ++i) +      if (RVLocs[i].isRegLoc()) +        DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); +  } + +  // The chain is always operand #0 +  SDValue Chain = Op.getOperand(0); +  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!"); + +    // ISD::RET => ret chain, (regnum1,val1), ... +    // So i*2+1 index only the regnums +    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), +                             Op.getOperand(i*2+1), Flag); + +    // Guarantee that all emitted copies are stuck together, +    // avoiding something bad. +    Flag = Chain.getValue(1); +  } + +  if (Flag.getNode()) +    return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + +  // Return Void +  return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain); +} +  const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {    switch (Opcode) { +  case SystemZISD::RET_FLAG:           return "SystemZISD::RET_FLAG";    default: return NULL;    }  } diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index ca9918d111a..feb5cd8dbec 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -22,7 +22,10 @@  namespace llvm {    namespace SystemZISD {      enum { -      FIRST_NUMBER = ISD::BUILTIN_OP_END +      FIRST_NUMBER = ISD::BUILTIN_OP_END, + +      /// Return with a flag operand. Operand 0 is the chain operand. +      RET_FLAG      };    } @@ -40,6 +43,14 @@ namespace llvm {      /// DAG node.      virtual const char *getTargetNodeName(unsigned Opcode) const; +    SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); +    SDValue LowerRET(SDValue Op, SelectionDAG &DAG); +    SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG); + +    SDNode* LowerCallResult(SDValue Chain, SDValue InFlag, +                            CallSDNode *TheCall, +                            unsigned CallingConv, SelectionDAG &DAG); +    private:      const SystemZSubtarget &Subtarget;      const SystemZTargetMachine &TM; diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index c2f27a15300..54e0969bc52 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -13,5 +13,20 @@  include "SystemZInstrFormats.td" +//===----------------------------------------------------------------------===// +// SystemZ Specific Node Definitions. +//===----------------------------------------------------------------------===// +def SystemZretflag : SDNode<"SystemZISD::RET_FLAG", SDTNone, +                     [SDNPHasChain, SDNPOptInFlag]>; +  let neverHasSideEffects = 1 in  def NOP : Pseudo<(outs), (ins), "# no-op", []>; + +//===----------------------------------------------------------------------===// +//  Control Flow Instructions... +// + +// FIXME: Provide proper encoding! +let isReturn = 1, isTerminator = 1 in { +  def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>; +}  | 

