Index: lib/Target/X86/X86CallingConv.td =================================================================== --- lib/Target/X86/X86CallingConv.td +++ lib/Target/X86/X86CallingConv.td @@ -590,9 +590,11 @@ // Calling convention used on Win64 def CC_X86_Win64_C : CallingConv<[ - // FIXME: Handle byval stuff. // FIXME: Handle varargs. + // Byval aggrevates are passed by pointer + CCIfByVal>, + // Promote i1/v1i1 arguments to i8. CCIfType<[i1, v1i1], CCPromoteToType>, Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -3621,13 +3621,27 @@ Arg = DAG.getBitcast(RegVT, Arg); break; case CCValAssign::Indirect: { - // Store the argument. - SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT()); - int FI = cast(SpillSlot)->getIndex(); - Chain = DAG.getStore( - Chain, dl, Arg, SpillSlot, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); - Arg = SpillSlot; + if (isByVal) { + // Copy the argument into a temportary spill slot + int FrameIdx = MF.getFrameInfo().CreateStackObject( + Flags.getByValSize(), std::max(16, (int)Flags.getByValAlign()), + false); + SDValue SpillSlot = + DAG.getFrameIndex(FrameIdx, getPointerTy(DAG.getDataLayout())); + Chain = + CreateCopyOfByValArgument(Arg, SpillSlot, Chain, Flags, DAG, dl); + // From now on treat this as a regular pointer + Arg = SpillSlot; + isByVal = false; + } else { + // Store the argument. + SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT()); + int FI = cast(SpillSlot)->getIndex(); + Chain = DAG.getStore( + Chain, dl, Arg, SpillSlot, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); + Arg = SpillSlot; + } break; } } Index: test/CodeGen/X86/win64-byval.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/win64-byval.ll @@ -0,0 +1,18 @@ +; RUN: llc -mtriple x86_64-w64-mingw32 %s -o - | FileCheck %s + +declare void @foo({ float, double }* byval); +@G = external constant { float, double } + +define void @bar() +{ +; Make sure we're creating a temporary stack slot, rather than just passing +; the pointer through unmodified. +; CHECK-LABEL: @bar +; CHECK: movq G+8(%rip), %rax +; CHECK: movq %rax, 40(%rsp) +; CHECK: movq G(%rip), %rax +; CHECK: movq %rax, 32(%rsp) +; CHECK: leaq 32(%rsp), %rcx + call void @foo({ float, double }* byval @G) + ret void +}