11c3f7f17SFangrui Song //===- llvm/lib/Target/X86/X86CallLowering.cpp - Call lowering ------------===// 21c3f7f17SFangrui Song // 31c3f7f17SFangrui Song // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41c3f7f17SFangrui Song // See https://llvm.org/LICENSE.txt for license information. 51c3f7f17SFangrui Song // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61c3f7f17SFangrui Song // 71c3f7f17SFangrui Song //===----------------------------------------------------------------------===// 81c3f7f17SFangrui Song // 91c3f7f17SFangrui Song /// \file 101c3f7f17SFangrui Song /// This file implements the lowering of LLVM calls to machine code calls for 111c3f7f17SFangrui Song /// GlobalISel. 121c3f7f17SFangrui Song // 131c3f7f17SFangrui Song //===----------------------------------------------------------------------===// 141c3f7f17SFangrui Song 151c3f7f17SFangrui Song #include "X86CallLowering.h" 161c3f7f17SFangrui Song #include "X86CallingConv.h" 171c3f7f17SFangrui Song #include "X86ISelLowering.h" 181c3f7f17SFangrui Song #include "X86InstrInfo.h" 19*b5b0a22eSEvgenii Kudriashov #include "X86MachineFunctionInfo.h" 201c3f7f17SFangrui Song #include "X86RegisterInfo.h" 211c3f7f17SFangrui Song #include "X86Subtarget.h" 221c3f7f17SFangrui Song #include "llvm/ADT/ArrayRef.h" 231c3f7f17SFangrui Song #include "llvm/ADT/SmallVector.h" 241c3f7f17SFangrui Song #include "llvm/CodeGen/Analysis.h" 251c3f7f17SFangrui Song #include "llvm/CodeGen/CallingConvLower.h" 261c3f7f17SFangrui Song #include "llvm/CodeGen/FunctionLoweringInfo.h" 271c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 281c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/Utils.h" 291c3f7f17SFangrui Song #include "llvm/CodeGen/LowLevelTypeUtils.h" 301c3f7f17SFangrui Song #include "llvm/CodeGen/MachineBasicBlock.h" 311c3f7f17SFangrui Song #include "llvm/CodeGen/MachineFrameInfo.h" 321c3f7f17SFangrui Song #include "llvm/CodeGen/MachineFunction.h" 331c3f7f17SFangrui Song #include "llvm/CodeGen/MachineInstrBuilder.h" 341c3f7f17SFangrui Song #include "llvm/CodeGen/MachineMemOperand.h" 351c3f7f17SFangrui Song #include "llvm/CodeGen/MachineOperand.h" 361c3f7f17SFangrui Song #include "llvm/CodeGen/MachineRegisterInfo.h" 371c3f7f17SFangrui Song #include "llvm/CodeGen/TargetInstrInfo.h" 381c3f7f17SFangrui Song #include "llvm/CodeGen/TargetSubtargetInfo.h" 391c3f7f17SFangrui Song #include "llvm/CodeGen/ValueTypes.h" 40184ca395SNico Weber #include "llvm/CodeGenTypes/LowLevelType.h" 41184ca395SNico Weber #include "llvm/CodeGenTypes/MachineValueType.h" 421c3f7f17SFangrui Song #include "llvm/IR/Attributes.h" 431c3f7f17SFangrui Song #include "llvm/IR/DataLayout.h" 441c3f7f17SFangrui Song #include "llvm/IR/Function.h" 451c3f7f17SFangrui Song #include "llvm/IR/Value.h" 461c3f7f17SFangrui Song #include <cassert> 471c3f7f17SFangrui Song #include <cstdint> 481c3f7f17SFangrui Song 491c3f7f17SFangrui Song using namespace llvm; 501c3f7f17SFangrui Song 511c3f7f17SFangrui Song X86CallLowering::X86CallLowering(const X86TargetLowering &TLI) 521c3f7f17SFangrui Song : CallLowering(&TLI) {} 531c3f7f17SFangrui Song 541c3f7f17SFangrui Song namespace { 551c3f7f17SFangrui Song 561c3f7f17SFangrui Song struct X86OutgoingValueAssigner : public CallLowering::OutgoingValueAssigner { 571c3f7f17SFangrui Song private: 581c3f7f17SFangrui Song uint64_t StackSize = 0; 591c3f7f17SFangrui Song unsigned NumXMMRegs = 0; 601c3f7f17SFangrui Song 611c3f7f17SFangrui Song public: 621c3f7f17SFangrui Song uint64_t getStackSize() { return StackSize; } 631c3f7f17SFangrui Song unsigned getNumXmmRegs() { return NumXMMRegs; } 641c3f7f17SFangrui Song 651c3f7f17SFangrui Song X86OutgoingValueAssigner(CCAssignFn *AssignFn_) 661c3f7f17SFangrui Song : CallLowering::OutgoingValueAssigner(AssignFn_) {} 671c3f7f17SFangrui Song 681c3f7f17SFangrui Song bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, 691c3f7f17SFangrui Song CCValAssign::LocInfo LocInfo, 701c3f7f17SFangrui Song const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags, 711c3f7f17SFangrui Song CCState &State) override { 721c3f7f17SFangrui Song bool Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State); 731c3f7f17SFangrui Song StackSize = State.getStackSize(); 741c3f7f17SFangrui Song 751c3f7f17SFangrui Song static const MCPhysReg XMMArgRegs[] = {X86::XMM0, X86::XMM1, X86::XMM2, 761c3f7f17SFangrui Song X86::XMM3, X86::XMM4, X86::XMM5, 771c3f7f17SFangrui Song X86::XMM6, X86::XMM7}; 781c3f7f17SFangrui Song if (!Info.IsFixed) 791c3f7f17SFangrui Song NumXMMRegs = State.getFirstUnallocated(XMMArgRegs); 801c3f7f17SFangrui Song 811c3f7f17SFangrui Song return Res; 821c3f7f17SFangrui Song } 831c3f7f17SFangrui Song }; 841c3f7f17SFangrui Song 851c3f7f17SFangrui Song struct X86OutgoingValueHandler : public CallLowering::OutgoingValueHandler { 861c3f7f17SFangrui Song X86OutgoingValueHandler(MachineIRBuilder &MIRBuilder, 871c3f7f17SFangrui Song MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) 881c3f7f17SFangrui Song : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB), 891c3f7f17SFangrui Song DL(MIRBuilder.getMF().getDataLayout()), 901c3f7f17SFangrui Song STI(MIRBuilder.getMF().getSubtarget<X86Subtarget>()) {} 911c3f7f17SFangrui Song 921c3f7f17SFangrui Song Register getStackAddress(uint64_t Size, int64_t Offset, 931c3f7f17SFangrui Song MachinePointerInfo &MPO, 941c3f7f17SFangrui Song ISD::ArgFlagsTy Flags) override { 951c3f7f17SFangrui Song LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0)); 961c3f7f17SFangrui Song LLT SType = LLT::scalar(DL.getPointerSizeInBits(0)); 971c3f7f17SFangrui Song auto SPReg = 981c3f7f17SFangrui Song MIRBuilder.buildCopy(p0, STI.getRegisterInfo()->getStackRegister()); 991c3f7f17SFangrui Song 1001c3f7f17SFangrui Song auto OffsetReg = MIRBuilder.buildConstant(SType, Offset); 1011c3f7f17SFangrui Song 1021c3f7f17SFangrui Song auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg); 1031c3f7f17SFangrui Song 1041c3f7f17SFangrui Song MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); 1051c3f7f17SFangrui Song return AddrReg.getReg(0); 1061c3f7f17SFangrui Song } 1071c3f7f17SFangrui Song 1081c3f7f17SFangrui Song void assignValueToReg(Register ValVReg, Register PhysReg, 1092f4328e6SCraig Topper const CCValAssign &VA) override { 1101c3f7f17SFangrui Song MIB.addUse(PhysReg, RegState::Implicit); 1111c3f7f17SFangrui Song Register ExtReg = extendRegister(ValVReg, VA); 1121c3f7f17SFangrui Song MIRBuilder.buildCopy(PhysReg, ExtReg); 1131c3f7f17SFangrui Song } 1141c3f7f17SFangrui Song 1151c3f7f17SFangrui Song void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 1169f592cbcSCraig Topper const MachinePointerInfo &MPO, 1179f592cbcSCraig Topper const CCValAssign &VA) override { 1181c3f7f17SFangrui Song MachineFunction &MF = MIRBuilder.getMF(); 1191c3f7f17SFangrui Song Register ExtReg = extendRegister(ValVReg, VA); 1201c3f7f17SFangrui Song 1211c3f7f17SFangrui Song auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy, 1221c3f7f17SFangrui Song inferAlignFromPtrInfo(MF, MPO)); 1231c3f7f17SFangrui Song MIRBuilder.buildStore(ExtReg, Addr, *MMO); 1241c3f7f17SFangrui Song } 1251c3f7f17SFangrui Song 1261c3f7f17SFangrui Song protected: 1271c3f7f17SFangrui Song MachineInstrBuilder &MIB; 1281c3f7f17SFangrui Song const DataLayout &DL; 1291c3f7f17SFangrui Song const X86Subtarget &STI; 1301c3f7f17SFangrui Song }; 1311c3f7f17SFangrui Song 1321c3f7f17SFangrui Song } // end anonymous namespace 1331c3f7f17SFangrui Song 1341c3f7f17SFangrui Song bool X86CallLowering::canLowerReturn( 1351c3f7f17SFangrui Song MachineFunction &MF, CallingConv::ID CallConv, 1361c3f7f17SFangrui Song SmallVectorImpl<CallLowering::BaseArgInfo> &Outs, bool IsVarArg) const { 1371c3f7f17SFangrui Song LLVMContext &Context = MF.getFunction().getContext(); 1381c3f7f17SFangrui Song SmallVector<CCValAssign, 16> RVLocs; 1391c3f7f17SFangrui Song CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); 1401c3f7f17SFangrui Song return checkReturn(CCInfo, Outs, RetCC_X86); 1411c3f7f17SFangrui Song } 1421c3f7f17SFangrui Song 1431c3f7f17SFangrui Song bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 1441c3f7f17SFangrui Song const Value *Val, ArrayRef<Register> VRegs, 1451c3f7f17SFangrui Song FunctionLoweringInfo &FLI) const { 1461c3f7f17SFangrui Song assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && 1471c3f7f17SFangrui Song "Return value without a vreg"); 1481c3f7f17SFangrui Song MachineFunction &MF = MIRBuilder.getMF(); 1491c3f7f17SFangrui Song auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0); 150*b5b0a22eSEvgenii Kudriashov auto FuncInfo = MF.getInfo<X86MachineFunctionInfo>(); 151*b5b0a22eSEvgenii Kudriashov const auto &STI = MF.getSubtarget<X86Subtarget>(); 152*b5b0a22eSEvgenii Kudriashov Register RetReg = STI.is64Bit() ? X86::RAX : X86::EAX; 1531c3f7f17SFangrui Song 1541c3f7f17SFangrui Song if (!FLI.CanLowerReturn) { 1551c3f7f17SFangrui Song insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister); 156*b5b0a22eSEvgenii Kudriashov MIRBuilder.buildCopy(RetReg, FLI.DemoteRegister); 157*b5b0a22eSEvgenii Kudriashov MIB.addReg(RetReg); 158*b5b0a22eSEvgenii Kudriashov } else if (Register Reg = FuncInfo->getSRetReturnReg()) { 159*b5b0a22eSEvgenii Kudriashov MIRBuilder.buildCopy(RetReg, Reg); 160*b5b0a22eSEvgenii Kudriashov MIB.addReg(RetReg); 1611c3f7f17SFangrui Song } else if (!VRegs.empty()) { 1621c3f7f17SFangrui Song const Function &F = MF.getFunction(); 1631c3f7f17SFangrui Song MachineRegisterInfo &MRI = MF.getRegInfo(); 1641c3f7f17SFangrui Song const DataLayout &DL = MF.getDataLayout(); 1651c3f7f17SFangrui Song 1661c3f7f17SFangrui Song ArgInfo OrigRetInfo(VRegs, Val->getType(), 0); 1671c3f7f17SFangrui Song setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F); 1681c3f7f17SFangrui Song 1691c3f7f17SFangrui Song SmallVector<ArgInfo, 4> SplitRetInfos; 1701c3f7f17SFangrui Song splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv()); 1711c3f7f17SFangrui Song 1721c3f7f17SFangrui Song X86OutgoingValueAssigner Assigner(RetCC_X86); 1731c3f7f17SFangrui Song X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB); 1741c3f7f17SFangrui Song if (!determineAndHandleAssignments(Handler, Assigner, SplitRetInfos, 1751c3f7f17SFangrui Song MIRBuilder, F.getCallingConv(), 1761c3f7f17SFangrui Song F.isVarArg())) 1771c3f7f17SFangrui Song return false; 1781c3f7f17SFangrui Song } 1791c3f7f17SFangrui Song 1801c3f7f17SFangrui Song MIRBuilder.insertInstr(MIB); 1811c3f7f17SFangrui Song return true; 1821c3f7f17SFangrui Song } 1831c3f7f17SFangrui Song 1841c3f7f17SFangrui Song namespace { 1851c3f7f17SFangrui Song 1861c3f7f17SFangrui Song struct X86IncomingValueHandler : public CallLowering::IncomingValueHandler { 1871c3f7f17SFangrui Song X86IncomingValueHandler(MachineIRBuilder &MIRBuilder, 1881c3f7f17SFangrui Song MachineRegisterInfo &MRI) 1891c3f7f17SFangrui Song : IncomingValueHandler(MIRBuilder, MRI), 1901c3f7f17SFangrui Song DL(MIRBuilder.getMF().getDataLayout()) {} 1911c3f7f17SFangrui Song 1921c3f7f17SFangrui Song Register getStackAddress(uint64_t Size, int64_t Offset, 1931c3f7f17SFangrui Song MachinePointerInfo &MPO, 1941c3f7f17SFangrui Song ISD::ArgFlagsTy Flags) override { 1951c3f7f17SFangrui Song auto &MFI = MIRBuilder.getMF().getFrameInfo(); 1961c3f7f17SFangrui Song 1971c3f7f17SFangrui Song // Byval is assumed to be writable memory, but other stack passed arguments 1981c3f7f17SFangrui Song // are not. 1991c3f7f17SFangrui Song const bool IsImmutable = !Flags.isByVal(); 2001c3f7f17SFangrui Song 2011c3f7f17SFangrui Song int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 2021c3f7f17SFangrui Song MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 2031c3f7f17SFangrui Song 2041c3f7f17SFangrui Song return MIRBuilder 2051c3f7f17SFangrui Song .buildFrameIndex(LLT::pointer(0, DL.getPointerSizeInBits(0)), FI) 2061c3f7f17SFangrui Song .getReg(0); 2071c3f7f17SFangrui Song } 2081c3f7f17SFangrui Song 2091c3f7f17SFangrui Song void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, 2109f592cbcSCraig Topper const MachinePointerInfo &MPO, 2119f592cbcSCraig Topper const CCValAssign &VA) override { 2121c3f7f17SFangrui Song MachineFunction &MF = MIRBuilder.getMF(); 2131c3f7f17SFangrui Song auto *MMO = MF.getMachineMemOperand( 2141c3f7f17SFangrui Song MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, MemTy, 2151c3f7f17SFangrui Song inferAlignFromPtrInfo(MF, MPO)); 2161c3f7f17SFangrui Song MIRBuilder.buildLoad(ValVReg, Addr, *MMO); 2171c3f7f17SFangrui Song } 2181c3f7f17SFangrui Song 2191c3f7f17SFangrui Song void assignValueToReg(Register ValVReg, Register PhysReg, 2202f4328e6SCraig Topper const CCValAssign &VA) override { 2211c3f7f17SFangrui Song markPhysRegUsed(PhysReg); 2221c3f7f17SFangrui Song IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); 2231c3f7f17SFangrui Song } 2241c3f7f17SFangrui Song 2251c3f7f17SFangrui Song /// How the physical register gets marked varies between formal 2261c3f7f17SFangrui Song /// parameters (it's a basic-block live-in), and a call instruction 2271c3f7f17SFangrui Song /// (it's an implicit-def of the BL). 2281c3f7f17SFangrui Song virtual void markPhysRegUsed(unsigned PhysReg) = 0; 2291c3f7f17SFangrui Song 2301c3f7f17SFangrui Song protected: 2311c3f7f17SFangrui Song const DataLayout &DL; 2321c3f7f17SFangrui Song }; 2331c3f7f17SFangrui Song 2341c3f7f17SFangrui Song struct FormalArgHandler : public X86IncomingValueHandler { 2351c3f7f17SFangrui Song FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) 2361c3f7f17SFangrui Song : X86IncomingValueHandler(MIRBuilder, MRI) {} 2371c3f7f17SFangrui Song 2381c3f7f17SFangrui Song void markPhysRegUsed(unsigned PhysReg) override { 2391c3f7f17SFangrui Song MIRBuilder.getMRI()->addLiveIn(PhysReg); 2401c3f7f17SFangrui Song MIRBuilder.getMBB().addLiveIn(PhysReg); 2411c3f7f17SFangrui Song } 2421c3f7f17SFangrui Song }; 2431c3f7f17SFangrui Song 2441c3f7f17SFangrui Song struct CallReturnHandler : public X86IncomingValueHandler { 2451c3f7f17SFangrui Song CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 2461c3f7f17SFangrui Song MachineInstrBuilder &MIB) 2471c3f7f17SFangrui Song : X86IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} 2481c3f7f17SFangrui Song 2491c3f7f17SFangrui Song void markPhysRegUsed(unsigned PhysReg) override { 2501c3f7f17SFangrui Song MIB.addDef(PhysReg, RegState::Implicit); 2511c3f7f17SFangrui Song } 2521c3f7f17SFangrui Song 2531c3f7f17SFangrui Song protected: 2541c3f7f17SFangrui Song MachineInstrBuilder &MIB; 2551c3f7f17SFangrui Song }; 2561c3f7f17SFangrui Song 2571c3f7f17SFangrui Song } // end anonymous namespace 2581c3f7f17SFangrui Song 2591c3f7f17SFangrui Song bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 2601c3f7f17SFangrui Song const Function &F, 2611c3f7f17SFangrui Song ArrayRef<ArrayRef<Register>> VRegs, 2621c3f7f17SFangrui Song FunctionLoweringInfo &FLI) const { 2631c3f7f17SFangrui Song MachineFunction &MF = MIRBuilder.getMF(); 2641c3f7f17SFangrui Song MachineRegisterInfo &MRI = MF.getRegInfo(); 2651c3f7f17SFangrui Song auto DL = MF.getDataLayout(); 266*b5b0a22eSEvgenii Kudriashov auto FuncInfo = MF.getInfo<X86MachineFunctionInfo>(); 2671c3f7f17SFangrui Song 2681c3f7f17SFangrui Song SmallVector<ArgInfo, 8> SplitArgs; 2691c3f7f17SFangrui Song 2701c3f7f17SFangrui Song if (!FLI.CanLowerReturn) 2711c3f7f17SFangrui Song insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL); 2721c3f7f17SFangrui Song 2731c3f7f17SFangrui Song // TODO: handle variadic function 2741c3f7f17SFangrui Song if (F.isVarArg()) 2751c3f7f17SFangrui Song return false; 2761c3f7f17SFangrui Song 2771c3f7f17SFangrui Song unsigned Idx = 0; 2781c3f7f17SFangrui Song for (const auto &Arg : F.args()) { 2791c3f7f17SFangrui Song // TODO: handle not simple cases. 2801c3f7f17SFangrui Song if (Arg.hasAttribute(Attribute::ByVal) || 2811c3f7f17SFangrui Song Arg.hasAttribute(Attribute::InReg) || 2821c3f7f17SFangrui Song Arg.hasAttribute(Attribute::SwiftSelf) || 2831c3f7f17SFangrui Song Arg.hasAttribute(Attribute::SwiftError) || 2841c3f7f17SFangrui Song Arg.hasAttribute(Attribute::Nest) || VRegs[Idx].size() > 1) 2851c3f7f17SFangrui Song return false; 2861c3f7f17SFangrui Song 287*b5b0a22eSEvgenii Kudriashov if (Arg.hasAttribute(Attribute::StructRet)) { 288*b5b0a22eSEvgenii Kudriashov assert(VRegs[Idx].size() == 1 && 289*b5b0a22eSEvgenii Kudriashov "Unexpected amount of registers for sret argument."); 290*b5b0a22eSEvgenii Kudriashov FuncInfo->setSRetReturnReg(VRegs[Idx][0]); 291*b5b0a22eSEvgenii Kudriashov } 292*b5b0a22eSEvgenii Kudriashov 2931c3f7f17SFangrui Song ArgInfo OrigArg(VRegs[Idx], Arg.getType(), Idx); 2941c3f7f17SFangrui Song setArgFlags(OrigArg, Idx + AttributeList::FirstArgIndex, DL, F); 2951c3f7f17SFangrui Song splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 2961c3f7f17SFangrui Song Idx++; 2971c3f7f17SFangrui Song } 2981c3f7f17SFangrui Song 2991c3f7f17SFangrui Song if (SplitArgs.empty()) 3001c3f7f17SFangrui Song return true; 3011c3f7f17SFangrui Song 3021c3f7f17SFangrui Song MachineBasicBlock &MBB = MIRBuilder.getMBB(); 3031c3f7f17SFangrui Song if (!MBB.empty()) 3041c3f7f17SFangrui Song MIRBuilder.setInstr(*MBB.begin()); 3051c3f7f17SFangrui Song 3061c3f7f17SFangrui Song X86OutgoingValueAssigner Assigner(CC_X86); 3071c3f7f17SFangrui Song FormalArgHandler Handler(MIRBuilder, MRI); 3081c3f7f17SFangrui Song if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 3091c3f7f17SFangrui Song F.getCallingConv(), F.isVarArg())) 3101c3f7f17SFangrui Song return false; 3111c3f7f17SFangrui Song 3121c3f7f17SFangrui Song // Move back to the end of the basic block. 3131c3f7f17SFangrui Song MIRBuilder.setMBB(MBB); 3141c3f7f17SFangrui Song 3151c3f7f17SFangrui Song return true; 3161c3f7f17SFangrui Song } 3171c3f7f17SFangrui Song 3181c3f7f17SFangrui Song bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 3191c3f7f17SFangrui Song CallLoweringInfo &Info) const { 3201c3f7f17SFangrui Song MachineFunction &MF = MIRBuilder.getMF(); 3211c3f7f17SFangrui Song const Function &F = MF.getFunction(); 3221c3f7f17SFangrui Song MachineRegisterInfo &MRI = MF.getRegInfo(); 3239df71d76SNikita Popov const DataLayout &DL = F.getDataLayout(); 3241c3f7f17SFangrui Song const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); 3251c3f7f17SFangrui Song const TargetInstrInfo &TII = *STI.getInstrInfo(); 3261c3f7f17SFangrui Song const X86RegisterInfo *TRI = STI.getRegisterInfo(); 3271c3f7f17SFangrui Song 3281c3f7f17SFangrui Song // Handle only Linux C, X86_64_SysV calling conventions for now. 3291c3f7f17SFangrui Song if (!STI.isTargetLinux() || !(Info.CallConv == CallingConv::C || 3301c3f7f17SFangrui Song Info.CallConv == CallingConv::X86_64_SysV)) 3311c3f7f17SFangrui Song return false; 3321c3f7f17SFangrui Song 3331c3f7f17SFangrui Song unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); 3341c3f7f17SFangrui Song auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown); 3351c3f7f17SFangrui Song 3361c3f7f17SFangrui Song // Create a temporarily-floating call instruction so we can add the implicit 3371c3f7f17SFangrui Song // uses of arg registers. 3381c3f7f17SFangrui Song bool Is64Bit = STI.is64Bit(); 3391c3f7f17SFangrui Song unsigned CallOpc = Info.Callee.isReg() 3401c3f7f17SFangrui Song ? (Is64Bit ? X86::CALL64r : X86::CALL32r) 3411c3f7f17SFangrui Song : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32); 3421c3f7f17SFangrui Song 3431c3f7f17SFangrui Song auto MIB = MIRBuilder.buildInstrNoInsert(CallOpc) 3441c3f7f17SFangrui Song .add(Info.Callee) 3451c3f7f17SFangrui Song .addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); 3461c3f7f17SFangrui Song 3471c3f7f17SFangrui Song SmallVector<ArgInfo, 8> SplitArgs; 3481c3f7f17SFangrui Song for (const auto &OrigArg : Info.OrigArgs) { 3491c3f7f17SFangrui Song 3501c3f7f17SFangrui Song // TODO: handle not simple cases. 3511c3f7f17SFangrui Song if (OrigArg.Flags[0].isByVal()) 3521c3f7f17SFangrui Song return false; 3531c3f7f17SFangrui Song 3541c3f7f17SFangrui Song if (OrigArg.Regs.size() > 1) 3551c3f7f17SFangrui Song return false; 3561c3f7f17SFangrui Song 3571c3f7f17SFangrui Song splitToValueTypes(OrigArg, SplitArgs, DL, Info.CallConv); 3581c3f7f17SFangrui Song } 3591c3f7f17SFangrui Song // Do the actual argument marshalling. 3601c3f7f17SFangrui Song X86OutgoingValueAssigner Assigner(CC_X86); 3611c3f7f17SFangrui Song X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB); 3621c3f7f17SFangrui Song if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 3631c3f7f17SFangrui Song Info.CallConv, Info.IsVarArg)) 3641c3f7f17SFangrui Song return false; 3651c3f7f17SFangrui Song 3661c3f7f17SFangrui Song bool IsFixed = Info.OrigArgs.empty() ? true : Info.OrigArgs.back().IsFixed; 3671c3f7f17SFangrui Song if (STI.is64Bit() && !IsFixed && !STI.isCallingConvWin64(Info.CallConv)) { 3681c3f7f17SFangrui Song // From AMD64 ABI document: 3691c3f7f17SFangrui Song // For calls that may call functions that use varargs or stdargs 3701c3f7f17SFangrui Song // (prototype-less calls or calls to functions containing ellipsis (...) in 3711c3f7f17SFangrui Song // the declaration) %al is used as hidden argument to specify the number 3721c3f7f17SFangrui Song // of SSE registers used. The contents of %al do not need to match exactly 3731c3f7f17SFangrui Song // the number of registers, but must be an ubound on the number of SSE 3741c3f7f17SFangrui Song // registers used and is in the range 0 - 8 inclusive. 3751c3f7f17SFangrui Song 3761c3f7f17SFangrui Song MIRBuilder.buildInstr(X86::MOV8ri) 3771c3f7f17SFangrui Song .addDef(X86::AL) 3781c3f7f17SFangrui Song .addImm(Assigner.getNumXmmRegs()); 3791c3f7f17SFangrui Song MIB.addUse(X86::AL, RegState::Implicit); 3801c3f7f17SFangrui Song } 3811c3f7f17SFangrui Song 3821c3f7f17SFangrui Song // Now we can add the actual call instruction to the correct basic block. 3831c3f7f17SFangrui Song MIRBuilder.insertInstr(MIB); 3841c3f7f17SFangrui Song 3851c3f7f17SFangrui Song // If Callee is a reg, since it is used by a target specific 3861c3f7f17SFangrui Song // instruction, it must have a register class matching the 3871c3f7f17SFangrui Song // constraint of that instruction. 3881c3f7f17SFangrui Song if (Info.Callee.isReg()) 3891c3f7f17SFangrui Song MIB->getOperand(0).setReg(constrainOperandRegClass( 3901c3f7f17SFangrui Song MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(), 3911c3f7f17SFangrui Song *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Info.Callee, 3921c3f7f17SFangrui Song 0)); 3931c3f7f17SFangrui Song 3941c3f7f17SFangrui Song // Finally we can copy the returned value back into its virtual-register. In 3951c3f7f17SFangrui Song // symmetry with the arguments, the physical register must be an 3961c3f7f17SFangrui Song // implicit-define of the call instruction. 3971c3f7f17SFangrui Song 3981c3f7f17SFangrui Song if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) { 3991c3f7f17SFangrui Song if (Info.OrigRet.Regs.size() > 1) 4001c3f7f17SFangrui Song return false; 4011c3f7f17SFangrui Song 4021c3f7f17SFangrui Song SplitArgs.clear(); 4031c3f7f17SFangrui Song SmallVector<Register, 8> NewRegs; 4041c3f7f17SFangrui Song 4051c3f7f17SFangrui Song splitToValueTypes(Info.OrigRet, SplitArgs, DL, Info.CallConv); 4061c3f7f17SFangrui Song 4071c3f7f17SFangrui Song X86OutgoingValueAssigner Assigner(RetCC_X86); 4081c3f7f17SFangrui Song CallReturnHandler Handler(MIRBuilder, MRI, MIB); 4091c3f7f17SFangrui Song if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder, 4101c3f7f17SFangrui Song Info.CallConv, Info.IsVarArg)) 4111c3f7f17SFangrui Song return false; 4121c3f7f17SFangrui Song 4131c3f7f17SFangrui Song if (!NewRegs.empty()) 4141c3f7f17SFangrui Song MIRBuilder.buildMergeLikeInstr(Info.OrigRet.Regs[0], NewRegs); 4151c3f7f17SFangrui Song } 4161c3f7f17SFangrui Song 4171c3f7f17SFangrui Song CallSeqStart.addImm(Assigner.getStackSize()) 4181c3f7f17SFangrui Song .addImm(0 /* see getFrameTotalSize */) 4191c3f7f17SFangrui Song .addImm(0 /* see getFrameAdjustment */); 4201c3f7f17SFangrui Song 4211c3f7f17SFangrui Song unsigned AdjStackUp = TII.getCallFrameDestroyOpcode(); 4221c3f7f17SFangrui Song MIRBuilder.buildInstr(AdjStackUp) 4231c3f7f17SFangrui Song .addImm(Assigner.getStackSize()) 4241c3f7f17SFangrui Song .addImm(0 /* NumBytesForCalleeToPop */); 4251c3f7f17SFangrui Song 4261c3f7f17SFangrui Song if (!Info.CanLowerReturn) 4271c3f7f17SFangrui Song insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs, 4281c3f7f17SFangrui Song Info.DemoteRegister, Info.DemoteStackIndex); 4291c3f7f17SFangrui Song 4301c3f7f17SFangrui Song return true; 4311c3f7f17SFangrui Song } 432