@@ -2201,6 +2201,74 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22012201 unsigned NumBytesToPush = NumBytes;
22022202 unsigned NumBytesToPop = NumBytes;
22032203
2204+ SDValue StackPtr;
2205+ const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo ();
2206+ int RetAddrSize = 8 ;
2207+
2208+ // If we are doing a tail-call, any byval arguments will be written to stack
2209+ // space which was used for incoming arguments. If any the values being used
2210+ // are incoming byval arguments to this function, then they might be
2211+ // overwritten by the stores of the outgoing arguments. To avoid this, we
2212+ // need to make a temporary copy of them in local stack space, then copy back
2213+ // to the argument area.
2214+ DenseMap<unsigned , SDValue> ByValTemporaries;
2215+ SDValue ByValTempChain;
2216+ if (isTailCall) {
2217+ SmallVector<SDValue, 8 > ByValCopyChains;
2218+ for (const CCValAssign &VA : ArgLocs) {
2219+ unsigned ArgIdx = VA.getValNo ();
2220+ SDValue Src = OutVals[ArgIdx];
2221+ ISD::ArgFlagsTy Flags = Outs[ArgIdx].Flags ;
2222+
2223+ if (!Flags.isByVal ())
2224+ continue ;
2225+
2226+ auto PtrVT = getPointerTy (DAG.getDataLayout ());
2227+
2228+ if (!StackPtr.getNode ())
2229+ StackPtr =
2230+ DAG.getCopyFromReg (Chain, dl, RegInfo->getStackRegister (), PtrVT);
2231+
2232+ // Destination: where this byval should live in the callee’s frame
2233+ // after the tail call.
2234+ int32_t Offset = VA.getLocMemOffset () + FPDiff + RetAddrSize;
2235+ SDValue Dst = DAG.getNode (ISD::ADD, dl, PtrVT, StackPtr,
2236+ DAG.getIntPtrConstant (Offset, dl));
2237+
2238+ ByValCopyKind Copy = ByValNeedsCopyForTailCall (DAG, Src, Dst, Flags);
2239+
2240+ if (Copy == NoCopy) {
2241+ // If the argument is already at the correct offset on the stack
2242+ // (because we are forwarding a byval argument from our caller), we
2243+ // don't need any copying.
2244+ continue ;
2245+ } else if (Copy == CopyOnce) {
2246+ // If the argument is in our local stack frame, no other argument
2247+ // preparation can clobber it, so we can copy it to the final location
2248+ // later.
2249+ ByValTemporaries[ArgIdx] = Src;
2250+ } else {
2251+ assert (Copy == CopyViaTemp && " unexpected enum value" );
2252+ // If we might be copying this argument from the outgoing argument
2253+ // stack area, we need to copy via a temporary in the local stack
2254+ // frame.
2255+ MachineFrameInfo &MFI = MF.getFrameInfo ();
2256+ int TempFrameIdx = MFI.CreateStackObject (Flags.getByValSize (),
2257+ Flags.getNonZeroByValAlign (),
2258+ /* isSS=*/ false );
2259+ SDValue Temp =
2260+ DAG.getFrameIndex (TempFrameIdx, getPointerTy (DAG.getDataLayout ()));
2261+
2262+ SDValue CopyChain =
2263+ CreateCopyOfByValArgument (Src, Temp, Chain, Flags, DAG, dl);
2264+ ByValCopyChains.push_back (CopyChain);
2265+ }
2266+ }
2267+ if (!ByValCopyChains.empty ())
2268+ ByValTempChain =
2269+ DAG.getNode (ISD::TokenFactor, dl, MVT::Other, ByValCopyChains);
2270+ }
2271+
22042272 // If we have an inalloca argument, all stack space has already been allocated
22052273 // for us and be right at the top of the stack. We don't support multiple
22062274 // arguments passed in memory when using inalloca.
@@ -2241,7 +2309,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22412309
22422310 SmallVector<std::pair<Register, SDValue>, 8 > RegsToPass;
22432311 SmallVector<SDValue, 8 > MemOpChains;
2244- SDValue StackPtr;
22452312
22462313 // The next loop assumes that the locations are in the same order of the
22472314 // input arguments.
@@ -2250,7 +2317,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22502317
22512318 // Walk the register/memloc assignments, inserting copies/loads. In the case
22522319 // of tail call optimization arguments are handle later.
2253- const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo ();
22542320 for (unsigned I = 0 , OutIndex = 0 , E = ArgLocs.size (); I != E;
22552321 ++I, ++OutIndex) {
22562322 assert (OutIndex < Outs.size () && " Invalid Out index" );
@@ -2459,13 +2525,20 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24592525 FIN = DAG.getFrameIndex (FI, getPointerTy (DAG.getDataLayout ()));
24602526
24612527 if (Flags.isByVal ()) {
2462- // Copy relative to framepointer.
2528+ SDValue ByValSrc;
2529+ bool NeedsStackCopy;
2530+ if (auto It = ByValTemporaries.find (OutsIndex);
2531+ It != ByValTemporaries.end ()) {
2532+ ByValSrc = It->second ;
2533+ NeedsStackCopy = true ;
2534+ } else {
2535+ ByValSrc = Arg;
2536+ NeedsStackCopy = !isTailCall;
2537+ }
2538+
24632539 SDValue Source = DAG.getIntPtrConstant (VA.getLocMemOffset (), dl);
2464- if (!StackPtr.getNode ())
2465- StackPtr = DAG.getCopyFromReg (Chain, dl, RegInfo->getStackRegister (),
2466- getPointerTy (DAG.getDataLayout ()));
24672540 Source = DAG.getNode (ISD::ADD, dl, getPointerTy (DAG.getDataLayout ()),
2468- StackPtr , Source);
2541+ ByValSrc , Source);
24692542
24702543 MemOpChains2.push_back (
24712544 CreateCopyOfByValArgument (Source, FIN, Chain, Flags, DAG, dl));
0 commit comments