Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/GISel/X86CallLowering.cpp
35294 views
//===- llvm/lib/Target/X86/X86CallLowering.cpp - Call lowering ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// This file implements the lowering of LLVM calls to machine code calls for10/// GlobalISel.11//12//===----------------------------------------------------------------------===//1314#include "X86CallLowering.h"15#include "X86CallingConv.h"16#include "X86ISelLowering.h"17#include "X86InstrInfo.h"18#include "X86MachineFunctionInfo.h"19#include "X86RegisterInfo.h"20#include "X86Subtarget.h"21#include "llvm/ADT/ArrayRef.h"22#include "llvm/ADT/SmallVector.h"23#include "llvm/CodeGen/Analysis.h"24#include "llvm/CodeGen/CallingConvLower.h"25#include "llvm/CodeGen/FunctionLoweringInfo.h"26#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"27#include "llvm/CodeGen/GlobalISel/Utils.h"28#include "llvm/CodeGen/LowLevelTypeUtils.h"29#include "llvm/CodeGen/MachineBasicBlock.h"30#include "llvm/CodeGen/MachineFrameInfo.h"31#include "llvm/CodeGen/MachineFunction.h"32#include "llvm/CodeGen/MachineInstrBuilder.h"33#include "llvm/CodeGen/MachineMemOperand.h"34#include "llvm/CodeGen/MachineOperand.h"35#include "llvm/CodeGen/MachineRegisterInfo.h"36#include "llvm/CodeGen/TargetInstrInfo.h"37#include "llvm/CodeGen/TargetSubtargetInfo.h"38#include "llvm/CodeGen/ValueTypes.h"39#include "llvm/CodeGenTypes/LowLevelType.h"40#include "llvm/CodeGenTypes/MachineValueType.h"41#include "llvm/IR/Attributes.h"42#include "llvm/IR/DataLayout.h"43#include "llvm/IR/Function.h"44#include "llvm/IR/Value.h"45#include "llvm/MC/MCRegisterInfo.h"46#include <cassert>47#include <cstdint>4849using namespace llvm;5051X86CallLowering::X86CallLowering(const X86TargetLowering &TLI)52: CallLowering(&TLI) {}5354namespace {5556struct X86OutgoingValueAssigner : public CallLowering::OutgoingValueAssigner {57private:58uint64_t StackSize = 0;59unsigned NumXMMRegs = 0;6061public:62uint64_t getStackSize() { return StackSize; }63unsigned getNumXmmRegs() { return NumXMMRegs; }6465X86OutgoingValueAssigner(CCAssignFn *AssignFn_)66: CallLowering::OutgoingValueAssigner(AssignFn_) {}6768bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,69CCValAssign::LocInfo LocInfo,70const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,71CCState &State) override {72bool Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State);73StackSize = State.getStackSize();7475static const MCPhysReg XMMArgRegs[] = {X86::XMM0, X86::XMM1, X86::XMM2,76X86::XMM3, X86::XMM4, X86::XMM5,77X86::XMM6, X86::XMM7};78if (!Info.IsFixed)79NumXMMRegs = State.getFirstUnallocated(XMMArgRegs);8081return Res;82}83};8485struct X86OutgoingValueHandler : public CallLowering::OutgoingValueHandler {86X86OutgoingValueHandler(MachineIRBuilder &MIRBuilder,87MachineRegisterInfo &MRI, MachineInstrBuilder &MIB)88: OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),89DL(MIRBuilder.getMF().getDataLayout()),90STI(MIRBuilder.getMF().getSubtarget<X86Subtarget>()) {}9192Register getStackAddress(uint64_t Size, int64_t Offset,93MachinePointerInfo &MPO,94ISD::ArgFlagsTy Flags) override {95LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));96LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));97auto SPReg =98MIRBuilder.buildCopy(p0, STI.getRegisterInfo()->getStackRegister());99100auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);101102auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);103104MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);105return AddrReg.getReg(0);106}107108void assignValueToReg(Register ValVReg, Register PhysReg,109const CCValAssign &VA) override {110MIB.addUse(PhysReg, RegState::Implicit);111Register ExtReg = extendRegister(ValVReg, VA);112MIRBuilder.buildCopy(PhysReg, ExtReg);113}114115void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,116const MachinePointerInfo &MPO,117const CCValAssign &VA) override {118MachineFunction &MF = MIRBuilder.getMF();119Register ExtReg = extendRegister(ValVReg, VA);120121auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,122inferAlignFromPtrInfo(MF, MPO));123MIRBuilder.buildStore(ExtReg, Addr, *MMO);124}125126protected:127MachineInstrBuilder &MIB;128const DataLayout &DL;129const X86Subtarget &STI;130};131132} // end anonymous namespace133134bool X86CallLowering::canLowerReturn(135MachineFunction &MF, CallingConv::ID CallConv,136SmallVectorImpl<CallLowering::BaseArgInfo> &Outs, bool IsVarArg) const {137LLVMContext &Context = MF.getFunction().getContext();138SmallVector<CCValAssign, 16> RVLocs;139CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);140return checkReturn(CCInfo, Outs, RetCC_X86);141}142143bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,144const Value *Val, ArrayRef<Register> VRegs,145FunctionLoweringInfo &FLI) const {146assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&147"Return value without a vreg");148MachineFunction &MF = MIRBuilder.getMF();149auto MIB = MIRBuilder.buildInstrNoInsert(X86::RET).addImm(0);150auto FuncInfo = MF.getInfo<X86MachineFunctionInfo>();151const auto &STI = MF.getSubtarget<X86Subtarget>();152Register RetReg = STI.is64Bit() ? X86::RAX : X86::EAX;153154if (!FLI.CanLowerReturn) {155insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);156MIRBuilder.buildCopy(RetReg, FLI.DemoteRegister);157MIB.addReg(RetReg);158} else if (Register Reg = FuncInfo->getSRetReturnReg()) {159MIRBuilder.buildCopy(RetReg, Reg);160MIB.addReg(RetReg);161} else if (!VRegs.empty()) {162const Function &F = MF.getFunction();163MachineRegisterInfo &MRI = MF.getRegInfo();164const DataLayout &DL = MF.getDataLayout();165166ArgInfo OrigRetInfo(VRegs, Val->getType(), 0);167setArgFlags(OrigRetInfo, AttributeList::ReturnIndex, DL, F);168169SmallVector<ArgInfo, 4> SplitRetInfos;170splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, F.getCallingConv());171172X86OutgoingValueAssigner Assigner(RetCC_X86);173X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB);174if (!determineAndHandleAssignments(Handler, Assigner, SplitRetInfos,175MIRBuilder, F.getCallingConv(),176F.isVarArg()))177return false;178}179180MIRBuilder.insertInstr(MIB);181return true;182}183184namespace {185186struct X86IncomingValueHandler : public CallLowering::IncomingValueHandler {187X86IncomingValueHandler(MachineIRBuilder &MIRBuilder,188MachineRegisterInfo &MRI)189: IncomingValueHandler(MIRBuilder, MRI),190DL(MIRBuilder.getMF().getDataLayout()) {}191192Register getStackAddress(uint64_t Size, int64_t Offset,193MachinePointerInfo &MPO,194ISD::ArgFlagsTy Flags) override {195auto &MFI = MIRBuilder.getMF().getFrameInfo();196197// Byval is assumed to be writable memory, but other stack passed arguments198// are not.199const bool IsImmutable = !Flags.isByVal();200201int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);202MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);203204return MIRBuilder205.buildFrameIndex(LLT::pointer(0, DL.getPointerSizeInBits(0)), FI)206.getReg(0);207}208209void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,210const MachinePointerInfo &MPO,211const CCValAssign &VA) override {212MachineFunction &MF = MIRBuilder.getMF();213auto *MMO = MF.getMachineMemOperand(214MPO, MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant, MemTy,215inferAlignFromPtrInfo(MF, MPO));216MIRBuilder.buildLoad(ValVReg, Addr, *MMO);217}218219void assignValueToReg(Register ValVReg, Register PhysReg,220const CCValAssign &VA) override {221markPhysRegUsed(PhysReg);222IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);223}224225/// How the physical register gets marked varies between formal226/// parameters (it's a basic-block live-in), and a call instruction227/// (it's an implicit-def of the BL).228virtual void markPhysRegUsed(unsigned PhysReg) = 0;229230protected:231const DataLayout &DL;232};233234struct FormalArgHandler : public X86IncomingValueHandler {235FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)236: X86IncomingValueHandler(MIRBuilder, MRI) {}237238void markPhysRegUsed(unsigned PhysReg) override {239MIRBuilder.getMRI()->addLiveIn(PhysReg);240MIRBuilder.getMBB().addLiveIn(PhysReg);241}242};243244struct CallReturnHandler : public X86IncomingValueHandler {245CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,246MachineInstrBuilder &MIB)247: X86IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}248249void markPhysRegUsed(unsigned PhysReg) override {250MIB.addDef(PhysReg, RegState::Implicit);251}252253protected:254MachineInstrBuilder &MIB;255};256257} // end anonymous namespace258259bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,260const Function &F,261ArrayRef<ArrayRef<Register>> VRegs,262FunctionLoweringInfo &FLI) const {263MachineFunction &MF = MIRBuilder.getMF();264MachineRegisterInfo &MRI = MF.getRegInfo();265auto DL = MF.getDataLayout();266auto FuncInfo = MF.getInfo<X86MachineFunctionInfo>();267268SmallVector<ArgInfo, 8> SplitArgs;269270if (!FLI.CanLowerReturn)271insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL);272273// TODO: handle variadic function274if (F.isVarArg())275return false;276277unsigned Idx = 0;278for (const auto &Arg : F.args()) {279// TODO: handle not simple cases.280if (Arg.hasAttribute(Attribute::ByVal) ||281Arg.hasAttribute(Attribute::InReg) ||282Arg.hasAttribute(Attribute::SwiftSelf) ||283Arg.hasAttribute(Attribute::SwiftError) ||284Arg.hasAttribute(Attribute::Nest) || VRegs[Idx].size() > 1)285return false;286287if (Arg.hasAttribute(Attribute::StructRet)) {288assert(VRegs[Idx].size() == 1 &&289"Unexpected amount of registers for sret argument.");290FuncInfo->setSRetReturnReg(VRegs[Idx][0]);291}292293ArgInfo OrigArg(VRegs[Idx], Arg.getType(), Idx);294setArgFlags(OrigArg, Idx + AttributeList::FirstArgIndex, DL, F);295splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());296Idx++;297}298299if (SplitArgs.empty())300return true;301302MachineBasicBlock &MBB = MIRBuilder.getMBB();303if (!MBB.empty())304MIRBuilder.setInstr(*MBB.begin());305306X86OutgoingValueAssigner Assigner(CC_X86);307FormalArgHandler Handler(MIRBuilder, MRI);308if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder,309F.getCallingConv(), F.isVarArg()))310return false;311312// Move back to the end of the basic block.313MIRBuilder.setMBB(MBB);314315return true;316}317318bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,319CallLoweringInfo &Info) const {320MachineFunction &MF = MIRBuilder.getMF();321const Function &F = MF.getFunction();322MachineRegisterInfo &MRI = MF.getRegInfo();323const DataLayout &DL = F.getDataLayout();324const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();325const TargetInstrInfo &TII = *STI.getInstrInfo();326const X86RegisterInfo *TRI = STI.getRegisterInfo();327328// Handle only Linux C, X86_64_SysV calling conventions for now.329if (!STI.isTargetLinux() || !(Info.CallConv == CallingConv::C ||330Info.CallConv == CallingConv::X86_64_SysV))331return false;332333unsigned AdjStackDown = TII.getCallFrameSetupOpcode();334auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);335336// Create a temporarily-floating call instruction so we can add the implicit337// uses of arg registers.338bool Is64Bit = STI.is64Bit();339unsigned CallOpc = Info.Callee.isReg()340? (Is64Bit ? X86::CALL64r : X86::CALL32r)341: (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);342343auto MIB = MIRBuilder.buildInstrNoInsert(CallOpc)344.add(Info.Callee)345.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));346347SmallVector<ArgInfo, 8> SplitArgs;348for (const auto &OrigArg : Info.OrigArgs) {349350// TODO: handle not simple cases.351if (OrigArg.Flags[0].isByVal())352return false;353354if (OrigArg.Regs.size() > 1)355return false;356357splitToValueTypes(OrigArg, SplitArgs, DL, Info.CallConv);358}359// Do the actual argument marshalling.360X86OutgoingValueAssigner Assigner(CC_X86);361X86OutgoingValueHandler Handler(MIRBuilder, MRI, MIB);362if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder,363Info.CallConv, Info.IsVarArg))364return false;365366bool IsFixed = Info.OrigArgs.empty() ? true : Info.OrigArgs.back().IsFixed;367if (STI.is64Bit() && !IsFixed && !STI.isCallingConvWin64(Info.CallConv)) {368// From AMD64 ABI document:369// For calls that may call functions that use varargs or stdargs370// (prototype-less calls or calls to functions containing ellipsis (...) in371// the declaration) %al is used as hidden argument to specify the number372// of SSE registers used. The contents of %al do not need to match exactly373// the number of registers, but must be an ubound on the number of SSE374// registers used and is in the range 0 - 8 inclusive.375376MIRBuilder.buildInstr(X86::MOV8ri)377.addDef(X86::AL)378.addImm(Assigner.getNumXmmRegs());379MIB.addUse(X86::AL, RegState::Implicit);380}381382// Now we can add the actual call instruction to the correct basic block.383MIRBuilder.insertInstr(MIB);384385// If Callee is a reg, since it is used by a target specific386// instruction, it must have a register class matching the387// constraint of that instruction.388if (Info.Callee.isReg())389MIB->getOperand(0).setReg(constrainOperandRegClass(390MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),391*MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(), Info.Callee,3920));393394// Finally we can copy the returned value back into its virtual-register. In395// symmetry with the arguments, the physical register must be an396// implicit-define of the call instruction.397398if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy()) {399if (Info.OrigRet.Regs.size() > 1)400return false;401402SplitArgs.clear();403SmallVector<Register, 8> NewRegs;404405splitToValueTypes(Info.OrigRet, SplitArgs, DL, Info.CallConv);406407X86OutgoingValueAssigner Assigner(RetCC_X86);408CallReturnHandler Handler(MIRBuilder, MRI, MIB);409if (!determineAndHandleAssignments(Handler, Assigner, SplitArgs, MIRBuilder,410Info.CallConv, Info.IsVarArg))411return false;412413if (!NewRegs.empty())414MIRBuilder.buildMergeLikeInstr(Info.OrigRet.Regs[0], NewRegs);415}416417CallSeqStart.addImm(Assigner.getStackSize())418.addImm(0 /* see getFrameTotalSize */)419.addImm(0 /* see getFrameAdjustment */);420421unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();422MIRBuilder.buildInstr(AdjStackUp)423.addImm(Assigner.getStackSize())424.addImm(0 /* NumBytesForCalleeToPop */);425426if (!Info.CanLowerReturn)427insertSRetLoads(MIRBuilder, Info.OrigRet.Ty, Info.OrigRet.Regs,428Info.DemoteRegister, Info.DemoteStackIndex);429430return true;431}432433434