1*5f757f3fSDimitry Andric //===- llvm/lib/Target/X86/X86CallLowering.cpp - Call lowering ------------===// 2*5f757f3fSDimitry Andric // 3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5f757f3fSDimitry Andric // 7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 8*5f757f3fSDimitry Andric // 9*5f757f3fSDimitry Andric /// \file 10*5f757f3fSDimitry Andric /// This file implements the lowering of LLVM calls to machine code calls for 11*5f757f3fSDimitry Andric /// GlobalISel. 12*5f757f3fSDimitry Andric // 13*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 14*5f757f3fSDimitry Andric 15*5f757f3fSDimitry Andric #include "X86CallLowering.h" 16*5f757f3fSDimitry Andric #include "X86CallingConv.h" 17*5f757f3fSDimitry Andric #include "X86ISelLowering.h" 18*5f757f3fSDimitry Andric #include "X86InstrInfo.h" 19*5f757f3fSDimitry Andric #include "X86RegisterInfo.h" 20*5f757f3fSDimitry Andric #include "X86Subtarget.h" 21*5f757f3fSDimitry Andric #include "llvm/ADT/ArrayRef.h" 22*5f757f3fSDimitry Andric #include "llvm/ADT/SmallVector.h" 23*5f757f3fSDimitry Andric #include "llvm/CodeGen/Analysis.h" 24*5f757f3fSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 25*5f757f3fSDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h" 26*5f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 27*5f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h" 28*5f757f3fSDimitry Andric #include "llvm/CodeGen/LowLevelType.h" 29*5f757f3fSDimitry Andric #include "llvm/CodeGen/LowLevelTypeUtils.h" 30*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 31*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 32*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 33*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 34*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 35*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 36*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 37*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineValueType.h" 38*5f757f3fSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 39*5f757f3fSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 40*5f757f3fSDimitry Andric #include "llvm/CodeGen/ValueTypes.h" 41*5f757f3fSDimitry Andric #include "llvm/IR/Attributes.h" 42*5f757f3fSDimitry Andric #include "llvm/IR/DataLayout.h" 43*5f757f3fSDimitry Andric #include "llvm/IR/Function.h" 44*5f757f3fSDimitry Andric #include "llvm/IR/Value.h" 45*5f757f3fSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 46*5f757f3fSDimitry Andric #include <cassert> 47*5f757f3fSDimitry Andric #include <cstdint> 48*5f757f3fSDimitry Andric 49*5f757f3fSDimitry Andric using namespace llvm; 50*5f757f3fSDimitry Andric 51*5f757f3fSDimitry Andric X86CallLowering::X86CallLowering(const X86TargetLowering &TLI) 52*5f757f3fSDimitry Andric : CallLowering(&TLI) {} 53*5f757f3fSDimitry Andric 54*5f757f3fSDimitry Andric namespace { 55*5f757f3fSDimitry Andric 56*5f757f3fSDimitry Andric struct X86OutgoingValueAssigner : public CallLowering::OutgoingValueAssigner { 57*5f757f3fSDimitry Andric private: 58*5f757f3fSDimitry Andric uint64_t StackSize = 0; 59*5f757f3fSDimitry Andric unsigned NumXMMRegs = 0; 60*5f757f3fSDimitry Andric 61*5f757f3fSDimitry Andric public: 62*5f757f3fSDimitry Andric uint64_t getStackSize() { return StackSize; } 63*5f757f3fSDimitry Andric unsigned getNumXmmRegs() { return NumXMMRegs; } 64*5f757f3fSDimitry Andric 65*5f757f3fSDimitry Andric X86OutgoingValueAssigner(CCAssignFn *AssignFn_) 66*5f757f3fSDimitry Andric : CallLowering::OutgoingValueAssigner(AssignFn_) {} 67*5f757f3fSDimitry Andric 68*5f757f3fSDimitry Andric bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, 69*5f757f3fSDimitry Andric CCValAssign::LocInfo LocInfo, 70*5f757f3fSDimitry Andric const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, 71*5f757f3fSDimitry Andric CCState &State) override { 72*5f757f3fSDimitry Andric bool Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State); 73*5f757f3fSDimitry Andric StackSize = State.getStackSize(); 74*5f757f3fSDimitry Andric 75*5f757f3fSDimitry Andric static const MCPhysReg XMMArgRegs[] = {X86::XMM0, X86::XMM1, X86::XMM2, 76*5f757f3fSDimitry Andric X86::XMM3, X86::XMM4, X86::XMM5, 77*5f757f3fSDimitry Andric X86::XMM6, X86::XMM7}; 78*5f757f3fSDimitry Andric if (!Info.IsFixed) 79*5f757f3fSDimitry Andric NumXMMRegs = State.getFirstUnallocated(XMMArgRegs); 80*5f757f3fSDimitry Andric 81*5f757f3fSDimitry Andric return Res; 82*5f757f3fSDimitry Andric } 83*5f757f3fSDimitry Andric }; 84*5f757f3fSDimitry Andric 85*5f757f3fSDimitry Andric struct X86OutgoingValueHandler : public CallLowering::OutgoingValueHandler { 86*5f757f3fSDimitry Andric X86OutgoingValueHandler(MachineIRBuilder &MIRBuilder, 87*5f757f3fSDimitry Andric MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) 88*5f757f3fSDimitry Andric : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB), 89*5f757f3fSDimitry Andric DL(MIRBuilder.getMF().getDataLayout()), 90*5f757f3fSDimitry Andric STI(MIRBuilder.getMF().getSubtarget<X86Subtarget>()) {} 91*5f757f3fSDimitry Andric 92*5f757f3fSDimitry Andric Register getStackAddress(uint64_t Size, int64_t Offset, 93*5f757f3fSDimitry Andric MachinePointerInfo &MPO, 94*5f757f3fSDimitry Andric ISD::ArgFlagsTy Flags) override { 95*5f757f3fSDimitry Andric LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0)); 96*5f757f3fSDimitry Andric LLT SType = LLT::scalar(DL.getPointerSizeInBits(0)); 97*5f757f3fSDimitry Andric auto SPReg = 98*5f757f3fSDimitry Andric MIRBuilder.buildCopy(p0, STI.getRegisterInfo()->getStackRegister()); 99*5f757f3fSDimitry Andric 100*5f757f3fSDimitry Andric auto OffsetReg = MIRBuilder.buildConstant(SType, Offset); 101*5f757f3fSDimitry Andric 102*5f757f3fSDimitry Andric auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); 103*5f757f3fSDimitry Andric 104*5f757f3fSDimitry Andric MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 105*5f757f3fSDimitry Andric return AddrReg.getReg(0); 106*5f757f3fSDimitry Andric } 107*5f757f3fSDimitry Andric 108*5f757f3fSDimitry Andric void assignValueToReg(Register ValVReg, Register PhysReg, 109*5f757f3fSDimitry Andric const CCValAssign &VA) override { 110*5f757f3fSDimitry Andric MIB.addUse(PhysReg, RegState::Implicit); 111*5f757f3fSDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 112*5f757f3fSDimitry Andric MIRBuilder.buildCopy(PhysReg, ExtReg); 113*5f757f3fSDimitry Andric } 114*5f757f3fSDimitry Andric 115*5f757f3fSDimitry Andric void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 116*5f757f3fSDimitry Andric const MachinePointerInfo &MPO, 117*5f757f3fSDimitry Andric const CCValAssign &VA) override { 118*5f757f3fSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 119*5f757f3fSDimitry Andric Register ExtReg = extendRegister(ValVReg, VA); 120*5f757f3fSDimitry Andric 121*5f757f3fSDimitry Andric auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy, 122*5f757f3fSDimitry Andric inferAlignFromPtrInfo(MF, MPO)); 123*5f757f3fSDimitry Andric MIRBuilder.buildStore(ExtReg, Addr, *MMO); 124*5f757f3fSDimitry Andric } 125*5f757f3fSDimitry Andric 126*5f757f3fSDimitry Andric protected: 127*5f757f3fSDimitry Andric MachineInstrBuilder &MIB; 128*5f757f3fSDimitry Andric const DataLayout &DL; 129*5f757f3fSDimitry Andric const X86Subtarget &STI; 130*5f757f3fSDimitry Andric }; 131*5f757f3fSDimitry Andric 132*5f757f3fSDimitry Andric } // end anonymous namespace 133*5f757f3fSDimitry Andric 134*5f757f3fSDimitry Andric bool X86CallLowering::canLowerReturn( 135*5f757f3fSDimitry Andric MachineFunction &MF, CallingConv::ID CallConv, 136*5f757f3fSDimitry Andric SmallVectorImpl<CallLowering::BaseArgInfo> &Outs, bool IsVarArg) const { 137*5f757f3fSDimitry Andric LLVMContext &Context = MF.getFunction().getContext(); 138*5f757f3fSDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 139*5f757f3fSDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); 140*5f757f3fSDimitry Andric return checkReturn(CCInfo, Outs, RetCC_X86); 141*5f757f3fSDimitry Andric } 142*5f757f3fSDimitry Andric 143*5f757f3fSDimitry Andric bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 144*5f757f3fSDimitry Andric const Value *Val, ArrayRef<Register> VRegs, 145*5f757f3fSDimitry Andric FunctionLoweringInfo &FLI) const { 146*5f757f3fSDimitry Andric assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && 147*5f757f3fSDimitry Andric "Return value without a vreg"); 148*5f757f3fSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 149*5f757f3fSDimitry Andric auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0); 150*5f757f3fSDimitry Andric const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); 151*5f757f3fSDimitry Andric bool Is64Bit = STI.is64Bit(); 152*5f757f3fSDimitry Andric 153*5f757f3fSDimitry Andric if (!FLI.CanLowerReturn) { 154*5f757f3fSDimitry Andric insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister); 155*5f757f3fSDimitry Andric MIRBuilder.buildCopy(Is64Bit ? X86::RAX : X86::EAX, FLI.DemoteRegister); 156*5f757f3fSDimitry Andric } else if (!VRegs.empty()) { 157*5f757f3fSDimitry Andric const Function &F = MF.getFunction(); 158*5f757f3fSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 159*5f757f3fSDimitry Andric const DataLayout &DL = MF.getDataLayout(); 160*5f757f3fSDimitry Andric 161*5f757f3fSDimitry Andric ArgInfo OrigRetInfo(VRegs, Val->getType(), 0); 162*5f757f3fSDimitry Andric setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F); 163*5f757f3fSDimitry Andric 164*5f757f3fSDimitry Andric SmallVector<ArgInfo, 4> SplitRetInfos; 165*5f757f3fSDimitry Andric splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv()); 166*5f757f3fSDimitry Andric 167*5f757f3fSDimitry Andric X86OutgoingValueAssigner Assigner(RetCC_X86); 168*5f757f3fSDimitry Andric X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB); 169*5f757f3fSDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, SplitRetInfos, 170*5f757f3fSDimitry Andric MIRBuilder, F.getCallingConv(), 171*5f757f3fSDimitry Andric F.isVarArg())) 172*5f757f3fSDimitry Andric return false; 173*5f757f3fSDimitry Andric } 174*5f757f3fSDimitry Andric 175*5f757f3fSDimitry Andric MIRBuilder.insertInstr(MIB); 176*5f757f3fSDimitry Andric return true; 177*5f757f3fSDimitry Andric } 178*5f757f3fSDimitry Andric 179*5f757f3fSDimitry Andric namespace { 180*5f757f3fSDimitry Andric 181*5f757f3fSDimitry Andric struct X86IncomingValueHandler : public CallLowering::IncomingValueHandler { 182*5f757f3fSDimitry Andric X86IncomingValueHandler(MachineIRBuilder &MIRBuilder, 183*5f757f3fSDimitry Andric MachineRegisterInfo &MRI) 184*5f757f3fSDimitry Andric : IncomingValueHandler(MIRBuilder, MRI), 185*5f757f3fSDimitry Andric DL(MIRBuilder.getMF().getDataLayout()) {} 186*5f757f3fSDimitry Andric 187*5f757f3fSDimitry Andric Register getStackAddress(uint64_t Size, int64_t Offset, 188*5f757f3fSDimitry Andric MachinePointerInfo &MPO, 189*5f757f3fSDimitry Andric ISD::ArgFlagsTy Flags) override { 190*5f757f3fSDimitry Andric auto &MFI = MIRBuilder.getMF().getFrameInfo(); 191*5f757f3fSDimitry Andric 192*5f757f3fSDimitry Andric // Byval is assumed to be writable memory, but other stack passed arguments 193*5f757f3fSDimitry Andric // are not. 194*5f757f3fSDimitry Andric const bool IsImmutable = !Flags.isByVal(); 195*5f757f3fSDimitry Andric 196*5f757f3fSDimitry Andric int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 197*5f757f3fSDimitry Andric MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 198*5f757f3fSDimitry Andric 199*5f757f3fSDimitry Andric return MIRBuilder 200*5f757f3fSDimitry Andric .buildFrameIndex(LLT::pointer(0, DL.getPointerSizeInBits(0)), FI) 201*5f757f3fSDimitry Andric .getReg(0); 202*5f757f3fSDimitry Andric } 203*5f757f3fSDimitry Andric 204*5f757f3fSDimitry Andric void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 205*5f757f3fSDimitry Andric const MachinePointerInfo &MPO, 206*5f757f3fSDimitry Andric const CCValAssign &VA) override { 207*5f757f3fSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 208*5f757f3fSDimitry Andric auto *MMO = MF.getMachineMemOperand( 209*5f757f3fSDimitry Andric MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, MemTy, 210*5f757f3fSDimitry Andric inferAlignFromPtrInfo(MF, MPO)); 211*5f757f3fSDimitry Andric MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 212*5f757f3fSDimitry Andric } 213*5f757f3fSDimitry Andric 214*5f757f3fSDimitry Andric void assignValueToReg(Register ValVReg, Register PhysReg, 215*5f757f3fSDimitry Andric const CCValAssign &VA) override { 216*5f757f3fSDimitry Andric markPhysRegUsed(PhysReg); 217*5f757f3fSDimitry Andric IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); 218*5f757f3fSDimitry Andric } 219*5f757f3fSDimitry Andric 220*5f757f3fSDimitry Andric /// How the physical register gets marked varies between formal 221*5f757f3fSDimitry Andric /// parameters (it's a basic-block live-in), and a call instruction 222*5f757f3fSDimitry Andric /// (it's an implicit-def of the BL). 223*5f757f3fSDimitry Andric virtual void markPhysRegUsed(unsigned PhysReg) = 0; 224*5f757f3fSDimitry Andric 225*5f757f3fSDimitry Andric protected: 226*5f757f3fSDimitry Andric const DataLayout &DL; 227*5f757f3fSDimitry Andric }; 228*5f757f3fSDimitry Andric 229*5f757f3fSDimitry Andric struct FormalArgHandler : public X86IncomingValueHandler { 230*5f757f3fSDimitry Andric FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 231*5f757f3fSDimitry Andric : X86IncomingValueHandler(MIRBuilder, MRI) {} 232*5f757f3fSDimitry Andric 233*5f757f3fSDimitry Andric void markPhysRegUsed(unsigned PhysReg) override { 234*5f757f3fSDimitry Andric MIRBuilder.getMRI()->addLiveIn(PhysReg); 235*5f757f3fSDimitry Andric MIRBuilder.getMBB().addLiveIn(PhysReg); 236*5f757f3fSDimitry Andric } 237*5f757f3fSDimitry Andric }; 238*5f757f3fSDimitry Andric 239*5f757f3fSDimitry Andric struct CallReturnHandler : public X86IncomingValueHandler { 240*5f757f3fSDimitry Andric CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 241*5f757f3fSDimitry Andric MachineInstrBuilder &MIB) 242*5f757f3fSDimitry Andric : X86IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 243*5f757f3fSDimitry Andric 244*5f757f3fSDimitry Andric void markPhysRegUsed(unsigned PhysReg) override { 245*5f757f3fSDimitry Andric MIB.addDef(PhysReg, RegState::Implicit); 246*5f757f3fSDimitry Andric } 247*5f757f3fSDimitry Andric 248*5f757f3fSDimitry Andric protected: 249*5f757f3fSDimitry Andric MachineInstrBuilder &MIB; 250*5f757f3fSDimitry Andric }; 251*5f757f3fSDimitry Andric 252*5f757f3fSDimitry Andric } // end anonymous namespace 253*5f757f3fSDimitry Andric 254*5f757f3fSDimitry Andric bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 255*5f757f3fSDimitry Andric const Function &F, 256*5f757f3fSDimitry Andric ArrayRef<ArrayRef<Register>> VRegs, 257*5f757f3fSDimitry Andric FunctionLoweringInfo &FLI) const { 258*5f757f3fSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 259*5f757f3fSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 260*5f757f3fSDimitry Andric auto DL = MF.getDataLayout(); 261*5f757f3fSDimitry Andric 262*5f757f3fSDimitry Andric SmallVector<ArgInfo, 8> SplitArgs; 263*5f757f3fSDimitry Andric 264*5f757f3fSDimitry Andric if (!FLI.CanLowerReturn) 265*5f757f3fSDimitry Andric insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL); 266*5f757f3fSDimitry Andric 267*5f757f3fSDimitry Andric // TODO: handle variadic function 268*5f757f3fSDimitry Andric if (F.isVarArg()) 269*5f757f3fSDimitry Andric return false; 270*5f757f3fSDimitry Andric 271*5f757f3fSDimitry Andric unsigned Idx = 0; 272*5f757f3fSDimitry Andric for (const auto &Arg : F.args()) { 273*5f757f3fSDimitry Andric // TODO: handle not simple cases. 274*5f757f3fSDimitry Andric if (Arg.hasAttribute(Attribute::ByVal) || 275*5f757f3fSDimitry Andric Arg.hasAttribute(Attribute::InReg) || 276*5f757f3fSDimitry Andric Arg.hasAttribute(Attribute::StructRet) || 277*5f757f3fSDimitry Andric Arg.hasAttribute(Attribute::SwiftSelf) || 278*5f757f3fSDimitry Andric Arg.hasAttribute(Attribute::SwiftError) || 279*5f757f3fSDimitry Andric Arg.hasAttribute(Attribute::Nest) || VRegs[Idx].size() > 1) 280*5f757f3fSDimitry Andric return false; 281*5f757f3fSDimitry Andric 282*5f757f3fSDimitry Andric ArgInfo OrigArg(VRegs[Idx], Arg.getType(), Idx); 283*5f757f3fSDimitry Andric setArgFlags(OrigArg, Idx + AttributeList::FirstArgIndex, DL, F); 284*5f757f3fSDimitry Andric splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 285*5f757f3fSDimitry Andric Idx++; 286*5f757f3fSDimitry Andric } 287*5f757f3fSDimitry Andric 288*5f757f3fSDimitry Andric if (SplitArgs.empty()) 289*5f757f3fSDimitry Andric return true; 290*5f757f3fSDimitry Andric 291*5f757f3fSDimitry Andric MachineBasicBlock &MBB = MIRBuilder.getMBB(); 292*5f757f3fSDimitry Andric if (!MBB.empty()) 293*5f757f3fSDimitry Andric MIRBuilder.setInstr(*MBB.begin()); 294*5f757f3fSDimitry Andric 295*5f757f3fSDimitry Andric X86OutgoingValueAssigner Assigner(CC_X86); 296*5f757f3fSDimitry Andric FormalArgHandler Handler(MIRBuilder, MRI); 297*5f757f3fSDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 298*5f757f3fSDimitry Andric F.getCallingConv(), F.isVarArg())) 299*5f757f3fSDimitry Andric return false; 300*5f757f3fSDimitry Andric 301*5f757f3fSDimitry Andric // Move back to the end of the basic block. 302*5f757f3fSDimitry Andric MIRBuilder.setMBB(MBB); 303*5f757f3fSDimitry Andric 304*5f757f3fSDimitry Andric return true; 305*5f757f3fSDimitry Andric } 306*5f757f3fSDimitry Andric 307*5f757f3fSDimitry Andric bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 308*5f757f3fSDimitry Andric CallLoweringInfo &Info) const { 309*5f757f3fSDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 310*5f757f3fSDimitry Andric const Function &F = MF.getFunction(); 311*5f757f3fSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 312*5f757f3fSDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 313*5f757f3fSDimitry Andric const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); 314*5f757f3fSDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 315*5f757f3fSDimitry Andric const X86RegisterInfo *TRI = STI.getRegisterInfo(); 316*5f757f3fSDimitry Andric 317*5f757f3fSDimitry Andric // Handle only Linux C, X86_64_SysV calling conventions for now. 318*5f757f3fSDimitry Andric if (!STI.isTargetLinux() || !(Info.CallConv == CallingConv::C || 319*5f757f3fSDimitry Andric Info.CallConv == CallingConv::X86_64_SysV)) 320*5f757f3fSDimitry Andric return false; 321*5f757f3fSDimitry Andric 322*5f757f3fSDimitry Andric unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); 323*5f757f3fSDimitry Andric auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown); 324*5f757f3fSDimitry Andric 325*5f757f3fSDimitry Andric // Create a temporarily-floating call instruction so we can add the implicit 326*5f757f3fSDimitry Andric // uses of arg registers. 327*5f757f3fSDimitry Andric bool Is64Bit = STI.is64Bit(); 328*5f757f3fSDimitry Andric unsigned CallOpc = Info.Callee.isReg() 329*5f757f3fSDimitry Andric ? (Is64Bit ? X86::CALL64r : X86::CALL32r) 330*5f757f3fSDimitry Andric : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32); 331*5f757f3fSDimitry Andric 332*5f757f3fSDimitry Andric auto MIB = MIRBuilder.buildInstrNoInsert(CallOpc) 333*5f757f3fSDimitry Andric .add(Info.Callee) 334*5f757f3fSDimitry Andric .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); 335*5f757f3fSDimitry Andric 336*5f757f3fSDimitry Andric SmallVector<ArgInfo, 8> SplitArgs; 337*5f757f3fSDimitry Andric for (const auto &OrigArg : Info.OrigArgs) { 338*5f757f3fSDimitry Andric 339*5f757f3fSDimitry Andric // TODO: handle not simple cases. 340*5f757f3fSDimitry Andric if (OrigArg.Flags[0].isByVal()) 341*5f757f3fSDimitry Andric return false; 342*5f757f3fSDimitry Andric 343*5f757f3fSDimitry Andric if (OrigArg.Regs.size() > 1) 344*5f757f3fSDimitry Andric return false; 345*5f757f3fSDimitry Andric 346*5f757f3fSDimitry Andric splitToValueTypes(OrigArg, SplitArgs, DL, Info.CallConv); 347*5f757f3fSDimitry Andric } 348*5f757f3fSDimitry Andric // Do the actual argument marshalling. 349*5f757f3fSDimitry Andric X86OutgoingValueAssigner Assigner(CC_X86); 350*5f757f3fSDimitry Andric X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB); 351*5f757f3fSDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 352*5f757f3fSDimitry Andric Info.CallConv, Info.IsVarArg)) 353*5f757f3fSDimitry Andric return false; 354*5f757f3fSDimitry Andric 355*5f757f3fSDimitry Andric bool IsFixed = Info.OrigArgs.empty() ? true : Info.OrigArgs.back().IsFixed; 356*5f757f3fSDimitry Andric if (STI.is64Bit() && !IsFixed && !STI.isCallingConvWin64(Info.CallConv)) { 357*5f757f3fSDimitry Andric // From AMD64 ABI document: 358*5f757f3fSDimitry Andric // For calls that may call functions that use varargs or stdargs 359*5f757f3fSDimitry Andric // (prototype-less calls or calls to functions containing ellipsis (...) in 360*5f757f3fSDimitry Andric // the declaration) %al is used as hidden argument to specify the number 361*5f757f3fSDimitry Andric // of SSE registers used. The contents of %al do not need to match exactly 362*5f757f3fSDimitry Andric // the number of registers, but must be an ubound on the number of SSE 363*5f757f3fSDimitry Andric // registers used and is in the range 0 - 8 inclusive. 364*5f757f3fSDimitry Andric 365*5f757f3fSDimitry Andric MIRBuilder.buildInstr(X86::MOV8ri) 366*5f757f3fSDimitry Andric .addDef(X86::AL) 367*5f757f3fSDimitry Andric .addImm(Assigner.getNumXmmRegs()); 368*5f757f3fSDimitry Andric MIB.addUse(X86::AL, RegState::Implicit); 369*5f757f3fSDimitry Andric } 370*5f757f3fSDimitry Andric 371*5f757f3fSDimitry Andric // Now we can add the actual call instruction to the correct basic block. 372*5f757f3fSDimitry Andric MIRBuilder.insertInstr(MIB); 373*5f757f3fSDimitry Andric 374*5f757f3fSDimitry Andric // If Callee is a reg, since it is used by a target specific 375*5f757f3fSDimitry Andric // instruction, it must have a register class matching the 376*5f757f3fSDimitry Andric // constraint of that instruction. 377*5f757f3fSDimitry Andric if (Info.Callee.isReg()) 378*5f757f3fSDimitry Andric MIB->getOperand(0).setReg(constrainOperandRegClass( 379*5f757f3fSDimitry Andric MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(), 380*5f757f3fSDimitry Andric *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Info.Callee, 381*5f757f3fSDimitry Andric 0)); 382*5f757f3fSDimitry Andric 383*5f757f3fSDimitry Andric // Finally we can copy the returned value back into its virtual-register. In 384*5f757f3fSDimitry Andric // symmetry with the arguments, the physical register must be an 385*5f757f3fSDimitry Andric // implicit-define of the call instruction. 386*5f757f3fSDimitry Andric 387*5f757f3fSDimitry Andric if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) { 388*5f757f3fSDimitry Andric if (Info.OrigRet.Regs.size() > 1) 389*5f757f3fSDimitry Andric return false; 390*5f757f3fSDimitry Andric 391*5f757f3fSDimitry Andric SplitArgs.clear(); 392*5f757f3fSDimitry Andric SmallVector<Register, 8> NewRegs; 393*5f757f3fSDimitry Andric 394*5f757f3fSDimitry Andric splitToValueTypes(Info.OrigRet, SplitArgs, DL, Info.CallConv); 395*5f757f3fSDimitry Andric 396*5f757f3fSDimitry Andric X86OutgoingValueAssigner Assigner(RetCC_X86); 397*5f757f3fSDimitry Andric CallReturnHandler Handler(MIRBuilder, MRI, MIB); 398*5f757f3fSDimitry Andric if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 399*5f757f3fSDimitry Andric Info.CallConv, Info.IsVarArg)) 400*5f757f3fSDimitry Andric return false; 401*5f757f3fSDimitry Andric 402*5f757f3fSDimitry Andric if (!NewRegs.empty()) 403*5f757f3fSDimitry Andric MIRBuilder.buildMergeLikeInstr(Info.OrigRet.Regs[0], NewRegs); 404*5f757f3fSDimitry Andric } 405*5f757f3fSDimitry Andric 406*5f757f3fSDimitry Andric CallSeqStart.addImm(Assigner.getStackSize()) 407*5f757f3fSDimitry Andric .addImm(0 /* see getFrameTotalSize */) 408*5f757f3fSDimitry Andric .addImm(0 /* see getFrameAdjustment */); 409*5f757f3fSDimitry Andric 410*5f757f3fSDimitry Andric unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); 411*5f757f3fSDimitry Andric MIRBuilder.buildInstr(AdjStackUp) 412*5f757f3fSDimitry Andric .addImm(Assigner.getStackSize()) 413*5f757f3fSDimitry Andric .addImm(0 /* NumBytesForCalleeToPop */); 414*5f757f3fSDimitry Andric 415*5f757f3fSDimitry Andric if (!Info.CanLowerReturn) 416*5f757f3fSDimitry Andric insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs, 417*5f757f3fSDimitry Andric Info.DemoteRegister, Info.DemoteStackIndex); 418*5f757f3fSDimitry Andric 419*5f757f3fSDimitry Andric return true; 420*5f757f3fSDimitry Andric } 421