[llvm-commits] [llvm] r131986 - /llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
Akira Hatanaka
ahatanak at gmail.com
Tue May 24 12:18:33 PDT 2011
Author: ahatanak
Date: Tue May 24 14:18:33 2011
New Revision: 131986
URL: http://llvm.org/viewvc/llvm-project?rev=131986&view=rev
Log:
Implement byval structure argument passing. The following limitations or
deficiencies exist:
- Works only if ABI is o32.
- Zero-sized structures cannot be passed.
- There is a lot of redundancy in generated code.
Modified:
llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=131986&r1=131985&r2=131986&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Tue May 24 14:18:33 2011
@@ -959,6 +959,17 @@
Mips::D6, Mips::D7
};
+ // ByVal Args
+ if (ArgFlags.isByVal()) {
+ State.HandleByVal(ValNo, ValVT, LocVT, LocInfo,
+ 1 /*MinSize*/, 4 /*MinAlign*/, ArgFlags);
+ unsigned NextReg = (State.getNextStackOffset() + 3) / 4;
+ for (unsigned r = State.getFirstUnallocated(IntRegs, IntRegsSize);
+ r < std::min(IntRegsSize, NextReg); ++r)
+ State.AllocateReg(IntRegs[r]);
+ return false;
+ }
+
// Promote i8 and i16
if (LocVT == MVT::i8 || LocVT == MVT::i16) {
LocVT = MVT::i32;
@@ -1027,6 +1038,55 @@
// Call Calling Convention Implementation
//===----------------------------------------------------------------------===//
+static const unsigned O32IntRegsSize = 4;
+
+static const unsigned O32IntRegs[] = {
+ Mips::A0, Mips::A1, Mips::A2, Mips::A3
+};
+
+// Write ByVal Arg to arg registers and stack.
+static void
+WriteByValArg(SDValue& Chain, DebugLoc dl,
+ SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass,
+ SmallVector<SDValue, 8>& MemOpChains, int& LastFI,
+ MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
+ const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, MVT PtrType) {
+ unsigned FirstWord = VA.getLocMemOffset() / 4;
+ unsigned NumWords = (Flags.getByValSize() + 3) / 4;
+ unsigned LastWord = FirstWord + NumWords;
+ unsigned CurWord;
+
+ // copy the first 4 words of byval arg to registers A0 - A3
+ for (CurWord = FirstWord; CurWord < std::min(LastWord, O32IntRegsSize);
+ ++CurWord) {
+ SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
+ DAG.getConstant((CurWord - FirstWord) * 4,
+ MVT::i32));
+ SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr,
+ MachinePointerInfo(),
+ false, false, 0);
+ MemOpChains.push_back(LoadVal.getValue(1));
+ unsigned DstReg = O32IntRegs[CurWord];
+ RegsToPass.push_back(std::make_pair(DstReg, LoadVal));
+ }
+
+ // copy remaining part of byval arg to stack.
+ if (CurWord < LastWord) {
+ unsigned SizeInBytes = (LastWord - CurWord) * 4;
+ SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg,
+ DAG.getConstant((CurWord - FirstWord) * 4,
+ MVT::i32));
+ LastFI = MFI->CreateFixedObject(SizeInBytes, CurWord * 4, true);
+ SDValue Dst = DAG.getFrameIndex(LastFI, PtrType);
+ Chain = DAG.getMemcpy(Chain, dl, Dst, Src,
+ DAG.getConstant(SizeInBytes, MVT::i32),
+ /*Align*/4,
+ /*isVolatile=*/false, /*AlwaysInline=*/false,
+ MachinePointerInfo(0), MachinePointerInfo(0));
+ MemOpChains.push_back(Chain);
+ }
+}
+
/// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: isTailCall.
@@ -1121,6 +1181,18 @@
// Register can't get to this point...
assert(VA.isMemLoc());
+ // ByVal Arg.
+ ISD::ArgFlagsTy Flags = Outs[i].Flags;
+ if (Flags.isByVal()) {
+ assert(Subtarget->isABI_O32() &&
+ "No support for ByVal args by ABIs other than O32 yet.");
+ assert(Flags.getByValSize() &&
+ "ByVal args of size 0 should have been ignored by front-end.");
+ WriteByValArg(Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg,
+ VA, Flags, getPointerTy());
+ continue;
+ }
+
// Create the frame index object for this incoming parameter
// This guarantees that when allocating Local Area the firsts
// 16 bytes which are alwayes reserved won't be overwritten
@@ -1299,6 +1371,29 @@
//===----------------------------------------------------------------------===//
// Formal Arguments Calling Convention Implementation
//===----------------------------------------------------------------------===//
+static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl,
+ std::vector<SDValue>& OutChains,
+ SelectionDAG &DAG, unsigned NumWords, SDValue FIN,
+ const CCValAssign &VA, const ISD::ArgFlagsTy& Flags) {
+ unsigned LocMem = VA.getLocMemOffset();
+ unsigned FirstWord = LocMem / 4;
+
+ // copy register A0 - A3 to frame object
+ for (unsigned i = 0; i < NumWords; ++i) {
+ unsigned CurWord = FirstWord + i;
+ if (CurWord >= O32IntRegsSize)
+ break;
+
+ unsigned SrcReg = O32IntRegs[CurWord];
+ unsigned Reg = AddLiveIn(MF, SrcReg, Mips::CPURegsRegisterClass);
+ SDValue StorePtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
+ DAG.getConstant(i * 4, MVT::i32));
+ SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(Reg, MVT::i32),
+ StorePtr, MachinePointerInfo(), false,
+ false, 0);
+ OutChains.push_back(Store);
+ }
+}
/// LowerFormalArguments - transform physical registers into virtual registers
/// and generate load operations for arguments places on the stack.
@@ -1393,6 +1488,23 @@
// sanity check
assert(VA.isMemLoc());
+ ISD::ArgFlagsTy Flags = Ins[i].Flags;
+
+ if (Flags.isByVal()) {
+ assert(Subtarget->isABI_O32() &&
+ "No support for ByVal args by ABIs other than O32 yet.");
+ assert(Flags.getByValSize() &&
+ "ByVal args of size 0 should have been ignored by front-end.");
+ unsigned NumWords = (Flags.getByValSize() + 3) / 4;
+ LastFI = MFI->CreateFixedObject(NumWords * 4, VA.getLocMemOffset(),
+ true);
+ SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy());
+ InVals.push_back(FIN);
+ ReadByValArg(MF, Chain, dl, OutChains, DAG, NumWords, FIN, VA, Flags);
+
+ continue;
+ }
+
// 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
@@ -1431,14 +1543,12 @@
// Record the frame index of the first variable argument
// which is a value necessary to VASTART.
unsigned NextStackOffset = CCInfo.getNextStackOffset();
+ assert(NextStackOffset % 4 == 0 &&
+ "NextStackOffset must be aligned to 4-byte boundaries.");
LastFI = MFI->CreateFixedObject(4, NextStackOffset, true);
MipsFI->setVarArgsFrameIndex(LastFI);
- const unsigned O32IntRegs[] = {
- Mips::A0, Mips::A1, Mips::A2, Mips::A3
- };
-
- // Copy variable arguments passed in registers to stack.
+ // Copy variable arguments passed in registers to stack.
for (; NextStackOffset < 16; NextStackOffset += 4) {
TargetRegisterClass *RC = Mips::CPURegsRegisterClass;
unsigned Idx = NextStackOffset / 4;
More information about the llvm-commits
mailing list