llvm.org GIT mirror llvm / c731587
ARM byval support. Will be enabled by another patch to the FE. <rdar://problem/7662569> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129858 91177308-0d34-0410-b5e6-96231b3b80d8 Stuart Hastings 9 years ago
6 changed file(s) with 193 addition(s) and 84 deletion(s). Raw diff Collapse all Expand all
140140 MVT &LocVT, CCValAssign::LocInfo &LocInfo,
141141 ISD::ArgFlagsTy &ArgFlags, CCState &State);
142142
143 typedef enum { Invalid, Prologue, Call } ParmContext;
144
143145 /// CCState - This class holds information needed while lowering arguments and
144146 /// return values. It captures which registers are already assigned and which
145147 /// stack slots are used. It provides accessors to allocate these values.
153155
154156 unsigned StackOffset;
155157 SmallVector UsedRegs;
158 unsigned FirstByValReg;
159 bool FirstByValRegValid;
160 ParmContext CallOrPrologue;
156161 public:
157162 CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM,
158163 SmallVector &locs, LLVMContext &C);
287292 MVT LocVT, CCValAssign::LocInfo LocInfo,
288293 int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags);
289294
295 // First GPR that carries part of a byval aggregate that's split
296 // between registers and memory.
297 unsigned getFirstByValReg() { return FirstByValRegValid ? FirstByValReg : 0; }
298 void setFirstByValReg(unsigned r) { FirstByValReg = r; FirstByValRegValid = true; }
299 void clearFirstByValReg() { FirstByValReg = 0; FirstByValRegValid = false; }
300 bool isFirstByValRegValid() { return FirstByValRegValid; }
301
302 ParmContext getCallOrPrologue() { return CallOrPrologue; }
303 void setCallOrPrologue(ParmContext pc) { CallOrPrologue = pc; }
304
290305 private:
291306 /// MarkAllocated - Mark a register and all of its aliases as allocated.
292307 void MarkAllocated(unsigned Reg);
12521252 }
12531253
12541254 /// HandleByVal - Target-specific cleanup for formal ByVal parameters.
1255 virtual void HandleByVal(CCState *) const {}
1255 virtual void HandleByVal(CCState *, unsigned &) const {}
12561256
12571257 /// CanLowerReturn - This hook should be implemented to check whether the
12581258 /// return values described by the Outs array can fit into the return
2424 CCState::CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &tm,
2525 SmallVector &locs, LLVMContext &C)
2626 : CallingConv(CC), IsVarArg(isVarArg), TM(tm),
27 TRI(*TM.getRegisterInfo()), Locs(locs), Context(C) {
27 TRI(*TM.getRegisterInfo()), Locs(locs), Context(C),
28 CallOrPrologue(Invalid) {
2829 // No stack is used.
2930 StackOffset = 0;
3031
32 clearFirstByValReg();
3133 UsedRegs.resize((TRI.getNumRegs()+31)/32);
3234 }
3335
4446 Size = MinSize;
4547 if (MinAlign > (int)Align)
4648 Align = MinAlign;
49 TM.getTargetLowering()->HandleByVal(const_cast(this), Size);
4750 unsigned Offset = AllocateStack(Size, Align);
48
4951 addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
50 TM.getTargetLowering()->HandleByVal(const_cast(this));
5152 }
5253
5354 /// MarkAllocated - Mark a register and all of its aliases as allocated.
2222 def CC_ARM_APCS : CallingConv<[
2323
2424 // Handles byval parameters.
25 CCIfByVal8, 8>>,
25 CCIfByVal4, 4>>,
2626
2727 CCIfType<[i8, i16], CCPromoteToType>,
2828
7070 ARMInterworking("arm-interworking", cl::Hidden,
7171 cl::desc("Enable / disable ARM interworking (for debugging only)"),
7272 cl::init(true));
73
74 // The APCS parameter registers.
75 static const unsigned GPRArgRegs[] = {
76 ARM::R0, ARM::R1, ARM::R2, ARM::R3
77 };
78
79 static cl::opt
80 UseDivMod("arm-divmod-libcall", cl::Hidden,
81 cl::desc("Use __{u}divmod libcalls for div / rem pairs"),
82 cl::init(false));
7383
7484 void ARMTargetLowering::addTypeForNEON(EVT VT, EVT PromotedLdStVT,
7585 EVT PromotedBitwiseVT) {
11161126 return Chain;
11171127 }
11181128
1119 /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
1120 /// by "Src" to address "Dst" of size "Size". Alignment information is
1121 /// specified by the specific parameter attribute. The copy will be passed as
1122 /// a byval function parameter.
1123 /// Sometimes what we are copying is the end of a larger object, the part that
1124 /// does not fit in registers.
1125 static SDValue
1126 CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
1127 ISD::ArgFlagsTy Flags, SelectionDAG &DAG,
1128 DebugLoc dl) {
1129 SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32);
1130 return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(),
1131 /*isVolatile=*/false, /*AlwaysInline=*/false,
1132 MachinePointerInfo(0), MachinePointerInfo(0));
1133 }
1134
11351129 /// LowerMemOpCallTo - Store the argument to the stack.
11361130 SDValue
11371131 ARMTargetLowering::LowerMemOpCallTo(SDValue Chain,
11421136 unsigned LocMemOffset = VA.getLocMemOffset();
11431137 SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset);
11441138 PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff);
1145 if (Flags.isByVal())
1146 return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl);
1147
11481139 return DAG.getStore(Chain, dl, Arg, PtrOff,
11491140 MachinePointerInfo::getStack(LocMemOffset),
11501141 false, false, 0);
12101201 SmallVector ArgLocs;
12111202 CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
12121203 *DAG.getContext());
1204 CCInfo.setCallOrPrologue(Call);
12131205 CCInfo.AnalyzeCallOperands(Outs,
12141206 CCAssignFnForNode(CallConv, /* Return*/ false,
12151207 isVarArg));
12861278 }
12871279 } else if (VA.isRegLoc()) {
12881280 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1289 } else if (!IsSibCall || isByVal) {
1281 } else if (isByVal) {
1282 assert(VA.isMemLoc());
1283 unsigned offset = 0;
1284
1285 // True if this byval aggregate will be split between registers
1286 // and memory.
1287 if (CCInfo.isFirstByValRegValid()) {
1288 EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
1289 unsigned int i, j;
1290 for (i = 0, j = CCInfo.getFirstByValReg(); j < ARM::R4; i++, j++) {
1291 SDValue Const = DAG.getConstant(4*i, MVT::i32);
1292 SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const);
1293 SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg,
1294 MachinePointerInfo(),
1295 false, false, 0);
1296 MemOpChains.push_back(Load.getValue(1));
1297 RegsToPass.push_back(std::make_pair(j, Load));
1298 }
1299 offset = ARM::R4 - CCInfo.getFirstByValReg();
1300 CCInfo.clearFirstByValReg();
1301 }
1302
1303 unsigned LocMemOffset = VA.getLocMemOffset();
1304 SDValue StkPtrOff = DAG.getIntPtrConstant(LocMemOffset);
1305 SDValue Dst = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr,
1306 StkPtrOff);
1307 SDValue SrcOffset = DAG.getIntPtrConstant(4*offset);
1308 SDValue Src = DAG.getNode(ISD::ADD, dl, getPointerTy(), Arg, SrcOffset);
1309 SDValue SizeNode = DAG.getConstant(Flags.getByValSize() - 4*offset,
1310 MVT::i32);
1311 MemOpChains.push_back(DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode,
1312 Flags.getByValAlign(),
1313 /*isVolatile=*/false,
1314 /*AlwaysInline=*/false,
1315 MachinePointerInfo(0),
1316 MachinePointerInfo(0)));
1317
1318 } else if (!IsSibCall) {
12901319 assert(VA.isMemLoc());
12911320
12921321 MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg,
14801509 }
14811510
14821511 /// HandleByVal - Every parameter *after* a byval parameter is passed
1483 /// on the stack. Confiscate all the parameter registers to insure
1512 /// on the stack. Remember the next parameter register to allocate,
1513 /// and then confiscate the rest of the parameter registers to insure
14841514 /// this.
14851515 void
1486 llvm::ARMTargetLowering::HandleByVal(CCState *State) const {
1487 static const unsigned RegList1[] = {
1488 ARM::R0, ARM::R1, ARM::R2, ARM::R3
1489 };
1490 do {} while (State->AllocateReg(RegList1, 4));
1516 llvm::ARMTargetLowering::HandleByVal(CCState *State, unsigned &size) const {
1517 unsigned reg = State->AllocateReg(GPRArgRegs, 4);
1518 assert((State->getCallOrPrologue() == Prologue ||
1519 State->getCallOrPrologue() == Call) &&
1520 "unhandled ParmContext");
1521 if ((!State->isFirstByValRegValid()) &&
1522 (ARM::R0 <= reg) && (reg <= ARM::R3)) {
1523 State->setFirstByValReg(reg);
1524 // At a call site, a byval parameter that is split between
1525 // registers and memory needs its size truncated here. In a
1526 // function prologue, such byval parameters are reassembled in
1527 // memory, and are not truncated.
1528 if (State->getCallOrPrologue() == Call) {
1529 unsigned excess = 4 * (ARM::R4 - reg);
1530 assert(size >= excess && "expected larger existing stack allocation");
1531 size -= excess;
1532 }
1533 }
1534 // Confiscate any remaining parameter registers to preclude their
1535 // assignment to subsequent parameters.
1536 while (State->AllocateReg(GPRArgRegs, 4))
1537 ;
14911538 }
14921539
14931540 /// MatchingStackOffset - Return true if the given stack call argument is
22722319 return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
22732320 }
22742321
2322 void
2323 ARMTargetLowering::computeRegArea(CCState &CCInfo, MachineFunction &MF,
2324 unsigned &VARegSize, unsigned &VARegSaveSize)
2325 const {
2326 unsigned NumGPRs;
2327 if (CCInfo.isFirstByValRegValid())
2328 NumGPRs = ARM::R4 - CCInfo.getFirstByValReg();
2329 else {
2330 unsigned int firstUnalloced;
2331 firstUnalloced = CCInfo.getFirstUnallocated(GPRArgRegs,
2332 sizeof(GPRArgRegs) /
2333 sizeof(GPRArgRegs[0]));
2334 NumGPRs = (firstUnalloced <= 3) ? (4 - firstUnalloced) : 0;
2335 }
2336
2337 unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment();
2338 VARegSize = NumGPRs * 4;
2339 VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1);
2340 }
2341
2342 // The remaining GPRs hold either the beginning of variable-argument
2343 // data, or the beginning of an aggregate passed by value (usuall
2344 // byval). Either way, we allocate stack slots adjacent to the data
2345 // provided by our caller, and store the unallocated registers there.
2346 // If this is a variadic function, the va_list pointer will begin with
2347 // these values; otherwise, this reassembles a (byval) structure that
2348 // was split between registers and memory.
2349 void
2350 ARMTargetLowering::VarArgStyleRegisters(CCState &CCInfo, SelectionDAG &DAG,
2351 DebugLoc dl, SDValue &Chain,
2352 unsigned ArgOffset) const {
2353 MachineFunction &MF = DAG.getMachineFunction();
2354 MachineFrameInfo *MFI = MF.getFrameInfo();
2355 ARMFunctionInfo *AFI = MF.getInfo();
2356 unsigned firstRegToSaveIndex;
2357 if (CCInfo.isFirstByValRegValid())
2358 firstRegToSaveIndex = CCInfo.getFirstByValReg() - ARM::R0;
2359 else {
2360 firstRegToSaveIndex = CCInfo.getFirstUnallocated
2361 (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0]));
2362 }
2363
2364 unsigned VARegSize, VARegSaveSize;
2365 computeRegArea(CCInfo, MF, VARegSize, VARegSaveSize);
2366 if (VARegSaveSize) {
2367 // If this function is vararg, store any remaining integer argument regs
2368 // to their spots on the stack so that they may be loaded by deferencing
2369 // the result of va_next.
2370 AFI->setVarArgsRegSaveSize(VARegSaveSize);
2371 AFI->setVarArgsFrameIndex(
2372 MFI->CreateFixedObject(VARegSaveSize,
2373 ArgOffset + VARegSaveSize - VARegSize,
2374 false));
2375 SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(),
2376 getPointerTy());
2377
2378 SmallVector MemOps;
2379 for (; firstRegToSaveIndex < 4; ++firstRegToSaveIndex) {
2380 TargetRegisterClass *RC;
2381 if (AFI->isThumb1OnlyFunction())
2382 RC = ARM::tGPRRegisterClass;
2383 else
2384 RC = ARM::GPRRegisterClass;
2385
2386 unsigned VReg = MF.addLiveIn(GPRArgRegs[firstRegToSaveIndex], RC);
2387 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
2388 SDValue Store =
2389 DAG.getStore(Val.getValue(1), dl, Val, FIN,
2390 MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()),
2391 false, false, 0);
2392 MemOps.push_back(Store);
2393 FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN,
2394 DAG.getConstant(4, getPointerTy()));
2395 }
2396 if (!MemOps.empty())
2397 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
2398 &MemOps[0], MemOps.size());
2399 } else
2400 // This will point to the next argument passed via stack.
2401 AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(4, ArgOffset, true));
2402 }
2403
22752404 SDValue
22762405 ARMTargetLowering::LowerFormalArguments(SDValue Chain,
22772406 CallingConv::ID CallConv, bool isVarArg,
22802409 DebugLoc dl, SelectionDAG &DAG,
22812410 SmallVectorImpl &InVals)
22822411 const {
2283
22842412 MachineFunction &MF = DAG.getMachineFunction();
22852413 MachineFrameInfo *MFI = MF.getFrameInfo();
22862414
22902418 SmallVector ArgLocs;
22912419 CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs,
22922420 *DAG.getContext());
2421 CCInfo.setCallOrPrologue(Prologue);
22932422 CCInfo.AnalyzeFormalArguments(Ins,
22942423 CCAssignFnForNode(CallConv, /* Return*/ false,
22952424 isVarArg));
23922521 // In case of tail call optimization mark all arguments mutable. Since they
23932522 // could be overwritten by lowering of arguments in case of a tail call.
23942523 if (Flags.isByVal()) {
2395 unsigned Bytes = Flags.getByValSize();
2524 unsigned VARegSize, VARegSaveSize;
2525 computeRegArea(CCInfo, MF, VARegSize, VARegSaveSize);
2526 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, 0);
2527 unsigned Bytes = Flags.getByValSize() - VARegSize;
23962528 if (Bytes == 0) Bytes = 1; // Don't create zero-sized stack objects.
2397 int FI = MFI->CreateFixedObject(Bytes, VA.getLocMemOffset(), false);
2529 int FI = MFI->CreateFixedObject(Bytes,
2530 VA.getLocMemOffset(), false);
23982531 InVals.push_back(DAG.getFrameIndex(FI, getPointerTy()));
23992532 } else {
24002533 int FI = MFI->CreateFixedObject(VA.getLocVT().getSizeInBits()/8,
24122545 }
24132546
24142547 // varargs
2415 if (isVarArg) {
2416 static const unsigned GPRArgRegs[] = {
2417 ARM::R0, ARM::R1, ARM::R2, ARM::R3
2418 };
2419
2420 unsigned NumGPRs = CCInfo.getFirstUnallocated
2421 (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0]));
2422
2423 unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment();
2424 unsigned VARegSize = (4 - NumGPRs) * 4;
2425 unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1);
2426 unsigned ArgOffset = CCInfo.getNextStackOffset();
2427 if (VARegSaveSize) {
2428 // If this function is vararg, store any remaining integer argument regs
2429 // to their spots on the stack so that they may be loaded by deferencing
2430 // the result of va_next.
2431 AFI->setVarArgsRegSaveSize(VARegSaveSize);
2432 AFI->setVarArgsFrameIndex(
2433 MFI->CreateFixedObject(VARegSaveSize,
2434 ArgOffset + VARegSaveSize - VARegSize,
2435 false));
2436 SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(),
2437 getPointerTy());
2438
2439 SmallVector MemOps;
2440 for (; NumGPRs < 4; ++NumGPRs) {
2441 TargetRegisterClass *RC;
2442 if (AFI->isThumb1OnlyFunction())
2443 RC = ARM::tGPRRegisterClass;
2444 else
2445 RC = ARM::GPRRegisterClass;
2446
2447 unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC);
2448 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
2449 SDValue Store =
2450 DAG.getStore(Val.getValue(1), dl, Val, FIN,
2451 MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()),
2452 false, false, 0);
2453 MemOps.push_back(Store);
2454 FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN,
2455 DAG.getConstant(4, getPointerTy()));
2456 }
2457 if (!MemOps.empty())
2458 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
2459 &MemOps[0], MemOps.size());
2460 } else
2461 // This will point to the next argument passed via stack.
2462 AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(4, ArgOffset, true));
2463 }
2548 if (isVarArg)
2549 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.getNextStackOffset());
24642550
24652551 return Chain;
24662552 }
425425 DebugLoc dl, SelectionDAG &DAG,
426426 SmallVectorImpl &InVals) const;
427427
428 void VarArgStyleRegisters(CCState &CCInfo, SelectionDAG &DAG,
429 DebugLoc dl, SDValue &Chain, unsigned ArgOffset)
430 const;
431
432 void computeRegArea(CCState &CCInfo, MachineFunction &MF,
433 unsigned &VARegSize, unsigned &VARegSaveSize) const;
434
428435 virtual SDValue
429436 LowerCall(SDValue Chain, SDValue Callee,
430437 CallingConv::ID CallConv, bool isVarArg,
436443 SmallVectorImpl &InVals) const;
437444
438445 /// HandleByVal - Target-specific cleanup for ByVal support.
439 virtual void HandleByVal(CCState *) const;
446 virtual void HandleByVal(CCState *, unsigned &) const;
440447
441448 /// IsEligibleForTailCallOptimization - Check whether the call is eligible
442449 /// for tail call optimization. Targets which want to do tail call