diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2012-11-21 17:28:27 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2012-11-21 17:28:27 +0000 |
commit | 0ae61240341ca76e1329f251c64d2f475fa89278 (patch) | |
tree | 2b982b4a637f566b0a5c4246491b9cbf7298f75e | |
parent | 6cbeb4d839a7fc465c651f0df0b090052cd87a5c (diff) |
Add support for varargs functions for msp430.
Patch by Job Noorman!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168440 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.cpp | 31 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.h | 1 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430MachineFunctionInfo.h | 6 | ||||
-rw-r--r-- | test/CodeGen/MSP430/vararg.ll | 50 |
4 files changed, 86 insertions, 2 deletions
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 6b6a34824f..c79e5f181b 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -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. diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 991304c23d..bf021eaac5 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -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 diff --git a/lib/Target/MSP430/MSP430MachineFunctionInfo.h b/lib/Target/MSP430/MSP430MachineFunctionInfo.h index 632d6dee27..d1697f478c 100644 --- a/lib/Target/MSP430/MSP430MachineFunctionInfo.h +++ b/lib/Target/MSP430/MSP430MachineFunctionInfo.h @@ -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 index 0000000000..603d3ec6b6 --- /dev/null +++ b/test/CodeGen/MSP430/vararg.ll @@ -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 +} |