Add proper ISD::RET lowering
authorAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 12:59:50 +0000 (12:59 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Sun, 3 May 2009 12:59:50 +0000 (12:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70703 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/MSP430/MSP430ISelLowering.cpp
lib/Target/MSP430/MSP430ISelLowering.h
lib/Target/MSP430/MSP430InstrInfo.td

index 99996bbb8487ceaf371ab1379f1e7d7f4cc7aae1..625df96d19850a3714c785de5ea226d2a0d96611 100644 (file)
@@ -43,12 +43,15 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
 
   // Compute derived properties from the register classes
   computeRegisterProperties();
+
+  setOperationAction(ISD::RET, MVT::Other, Custom);
 }
 
 SDValue MSP430TargetLowering::
 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();
@@ -154,3 +157,58 @@ SDValue MSP430TargetLowering:: LowerCCCArguments(SDValue Op,
   return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(),
                      &ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
 }
+
+SDValue MSP430TargetLowering::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_MSP430);
+
+  // 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(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
+
+  // Return Void
+  return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain);
+}
+
+const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
+  switch (Opcode) {
+  default: return NULL;
+  case MSP430ISD::RET_FLAG:           return "MSP430ISD::RET_FLAG";
+  }
+}
+
index 0d17ddc57415615ea71c773103fe612caa833a19..4ee7a9c8cc4ea6f8676f5babbdc8b08063c9f890 100644 (file)
 #include "llvm/Target/TargetLowering.h"
 
 namespace llvm {
+  namespace MSP430ISD {
+    enum {
+      FIRST_NUMBER = ISD::BUILTIN_OP_END,
+
+      /// Return with a flag operand. Operand 0 is the chain operand.
+      RET_FLAG
+    };
+  }
 
   class MSP430Subtarget;
   class MSP430TargetMachine;
@@ -30,7 +38,13 @@ namespace llvm {
 
     /// LowerOperation - Provide custom lowering hooks for some operations.
     virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
+
+    /// getTargetNodeName - This method returns the name of a target specific
+    /// 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);
 
   private:
index 74fcebc91548e912d346c1c8d6e773f09456e42a..cd70fd3c13629aafefcf731071efc776f98988b3 100644 (file)
@@ -26,9 +26,20 @@ class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
 //===----------------------------------------------------------------------===//
 // MSP430 Specific Node Definitions.
 //===----------------------------------------------------------------------===//
+def retflag : SDNode<"MSP430ISD::RET_FLAG", SDTNone,
+                     [SDNPHasChain, SDNPOptInFlag]>;
 
 //===----------------------------------------------------------------------===//
 // Pseudo Instructions
 //===----------------------------------------------------------------------===//
 
 def NOP : Pseudo<(outs), (ins), "nop", []>;
+
+//===----------------------------------------------------------------------===//
+// Real Instructions
+//===----------------------------------------------------------------------===//
+
+// FIXME: Provide proper encoding!
+let isReturn = 1, isTerminator = 1 in {
+  def RETI: Pseudo<(outs), (ins), "reti", [(retflag)]>;
+}