Add support for varargs functions for msp430.
authorAnton Korobeynikov <asl@math.spbu.ru>
Wed, 21 Nov 2012 17:28:27 +0000 (17:28 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Wed, 21 Nov 2012 17:28:27 +0000 (17:28 +0000)
Patch by Job Noorman!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168440 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/MSP430/MSP430ISelLowering.cpp
lib/Target/MSP430/MSP430ISelLowering.h
lib/Target/MSP430/MSP430MachineFunctionInfo.h
test/CodeGen/MSP430/vararg.ll [new file with mode: 0644]

index 6b6a34824f6418cb587bb2f5a6fe707c61be668b..c79e5f181b4061585d51f6865a779f8b891d8561 100644 (file)
@@ -164,6 +164,12 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
   setOperationAction(ISD::SDIVREM,          MVT::i16,   Expand);
   setOperationAction(ISD::SREM,             MVT::i16,   Expand);
 
+  // varargs support
+  setOperationAction(ISD::VASTART,          MVT::Other, Custom);
+  setOperationAction(ISD::VAARG,            MVT::Other, Expand);
+  setOperationAction(ISD::VAEND,            MVT::Other, Expand);
+  setOperationAction(ISD::VACOPY,           MVT::Other, Expand);
+
   // Libcalls names.
   if (HWMultMode == HWMultIntr) {
     setLibcallName(RTLIB::MUL_I8,  "__mulqi3hw");
@@ -192,6 +198,7 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op,
   case ISD::SIGN_EXTEND:      return LowerSIGN_EXTEND(Op, DAG);
   case ISD::RETURNADDR:       return LowerRETURNADDR(Op, DAG);
   case ISD::FRAMEADDR:        return LowerFRAMEADDR(Op, DAG);
+  case ISD::VASTART:          return LowerVASTART(Op, DAG);
   default:
     llvm_unreachable("unimplemented operand");
   }
@@ -297,7 +304,6 @@ MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
 /// 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,
@@ -311,6 +317,7 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo *MFI = MF.getFrameInfo();
   MachineRegisterInfo &RegInfo = MF.getRegInfo();
+  MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
 
   // Assign locations to all of the incoming arguments.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -318,7 +325,11 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
                  getTargetMachine(), ArgLocs, *DAG.getContext());
   CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430);
 
-  assert(!isVarArg && "Varargs not supported yet");
+  // Create frame index for the start of the first vararg value
+  if (isVarArg) {
+    unsigned Offset = CCInfo.getNextStackOffset();
+    FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, Offset, true));
+  }
 
   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
     CCValAssign &VA = ArgLocs[i];
@@ -957,6 +968,22 @@ SDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op,
   return FrameAddr;
 }
 
+SDValue MSP430TargetLowering::LowerVASTART(SDValue Op,
+                                           SelectionDAG &DAG) const {
+  MachineFunction &MF = DAG.getMachineFunction();
+  MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
+
+  // Frame index of first vararg argument
+  SDValue FrameIndex = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
+                                         getPointerTy());
+  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+
+  // Create a store of the frame index to the location operand
+  return DAG.getStore(Op.getOperand(0), Op.getDebugLoc(), FrameIndex,
+                      Op.getOperand(1), MachinePointerInfo(SV),
+                      false, false, 0);
+}
+
 /// getPostIndexedAddressParts - returns true by value, base pointer and
 /// offset pointer and addressing mode by reference if this node can be
 /// combined with a load / store to form a post-indexed load / store.
index 991304c23de302d979ead27cf69cb937bbb896c2..bf021eaac5f5d02385b7017fca8798270920042b 100644 (file)
@@ -92,6 +92,7 @@ namespace llvm {
     SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
     SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const;
 
     TargetLowering::ConstraintType
index 632d6dee275fec30615459b76f356bbea2cf947c..d1697f478cc290cb44f2b2ba5556da7ee664c923 100644 (file)
@@ -30,6 +30,9 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo {
   /// ReturnAddrIndex - FrameIndex for return slot.
   int ReturnAddrIndex;
 
+  /// VarArgsFrameIndex - FrameIndex for start of varargs area.
+  int VarArgsFrameIndex;
+
 public:
   MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {}
 
@@ -41,6 +44,9 @@ public:
 
   int getRAIndex() const { return ReturnAddrIndex; }
   void setRAIndex(int Index) { ReturnAddrIndex = Index; }
+
+  int getVarArgsFrameIndex() const { return VarArgsFrameIndex;}
+  void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
 };
 
 } // End llvm namespace
diff --git a/test/CodeGen/MSP430/vararg.ll b/test/CodeGen/MSP430/vararg.ll
new file mode 100644 (file)
index 0000000..603d3ec
--- /dev/null
@@ -0,0 +1,50 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"
+target triple = "msp430---elf"
+
+declare void @llvm.va_start(i8*) nounwind
+declare void @llvm.va_end(i8*) nounwind
+declare void @llvm.va_copy(i8*, i8*) nounwind
+
+define void @va_start(i16 %a, ...) nounwind {
+entry:
+; CHECK: va_start:
+; CHECK: sub.w #2, r1
+  %vl = alloca i8*, align 2
+  %vl1 = bitcast i8** %vl to i8*
+; CHECK-NEXT: mov.w r1, [[REG:r[0-9]+]]
+; CHECK-NEXT: add.w #6, [[REG]]
+; CHECK-NEXT: mov.w [[REG]], 0(r1)
+  call void @llvm.va_start(i8* %vl1)
+  call void @llvm.va_end(i8* %vl1)
+  ret void
+}
+
+define i16 @va_arg(i8* %vl) nounwind {
+entry:
+; CHECK: va_arg:
+  %vl.addr = alloca i8*, align 2
+; CHECK: mov.w r15, 0(r1)
+  store i8* %vl, i8** %vl.addr, align 2
+; CHECK: mov.w r15, [[REG:r[0-9]+]]
+; CHECK-NEXT: add.w #2, [[REG]]
+; CHECK-NEXT: mov.w [[REG]], 0(r1)
+  %0 = va_arg i8** %vl.addr, i16
+; CHECK-NEXT: mov.w 0(r15), r15
+  ret i16 %0
+}
+
+define void @va_copy(i8* %vl) nounwind {
+entry:
+; CHECK: va_copy:
+  %vl.addr = alloca i8*, align 2
+  %vl2 = alloca i8*, align 2
+; CHECK: mov.w r15, 2(r1)
+  store i8* %vl, i8** %vl.addr, align 2
+  %0 = bitcast i8** %vl2 to i8*
+  %1 = bitcast i8** %vl.addr to i8*
+; CHECK-NEXT: mov.w r15, 0(r1)
+  call void @llvm.va_copy(i8* %0, i8* %1)
+  ret void
+}