1321369Sdim//===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim/// 9303231Sdim/// \file 10303231Sdim/// This file describes how to lower LLVM calls to machine code calls. 11303231Sdim/// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14303231Sdim#ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H 15303231Sdim#define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H 16303231Sdim 17321369Sdim#include "llvm/ADT/ArrayRef.h" 18353358Sdim#include "llvm/ADT/SmallVector.h" 19314564Sdim#include "llvm/CodeGen/CallingConvLower.h" 20327952Sdim#include "llvm/CodeGen/TargetCallingConv.h" 21321369Sdim#include "llvm/IR/CallSite.h" 22321369Sdim#include "llvm/IR/CallingConv.h" 23321369Sdim#include "llvm/Support/ErrorHandling.h" 24341825Sdim#include "llvm/Support/MachineValueType.h" 25321369Sdim#include <cstdint> 26321369Sdim#include <functional> 27303231Sdim 28303231Sdimnamespace llvm { 29321369Sdim 30353358Sdimclass CCState; 31321369Sdimclass DataLayout; 32321369Sdimclass Function; 33303231Sdimclass MachineIRBuilder; 34314564Sdimclass MachineOperand; 35321369Sdimstruct MachinePointerInfo; 36321369Sdimclass MachineRegisterInfo; 37303231Sdimclass TargetLowering; 38321369Sdimclass Type; 39303231Sdimclass Value; 40303231Sdim 41303231Sdimclass CallLowering { 42303231Sdim const TargetLowering *TLI; 43321369Sdim 44344779Sdim virtual void anchor(); 45314564Sdimpublic: 46314564Sdim struct ArgInfo { 47353358Sdim SmallVector<Register, 4> Regs; 48360784Sdim // If the argument had to be split into multiple parts according to the 49360784Sdim // target calling convention, then this contains the original vregs 50360784Sdim // if the argument was an incoming arg. 51360784Sdim SmallVector<Register, 2> OrigRegs; 52314564Sdim Type *Ty; 53360784Sdim SmallVector<ISD::ArgFlagsTy, 4> Flags; 54321369Sdim bool IsFixed; 55314564Sdim 56353358Sdim ArgInfo(ArrayRef<Register> Regs, Type *Ty, 57360784Sdim ArrayRef<ISD::ArgFlagsTy> Flags = ArrayRef<ISD::ArgFlagsTy>(), 58360784Sdim bool IsFixed = true) 59360784Sdim : Regs(Regs.begin(), Regs.end()), Ty(Ty), 60360784Sdim Flags(Flags.begin(), Flags.end()), IsFixed(IsFixed) { 61360784Sdim if (!Regs.empty() && Flags.empty()) 62360784Sdim this->Flags.push_back(ISD::ArgFlagsTy()); 63353358Sdim // FIXME: We should have just one way of saying "no register". 64353358Sdim assert((Ty->isVoidTy() == (Regs.empty() || Regs[0] == 0)) && 65353358Sdim "only void types should have no register"); 66353358Sdim } 67360784Sdim 68360784Sdim ArgInfo() : Ty(nullptr), IsFixed(false) {} 69314564Sdim }; 70314564Sdim 71360784Sdim struct CallLoweringInfo { 72360784Sdim /// Calling convention to be used for the call. 73360784Sdim CallingConv::ID CallConv = CallingConv::C; 74360784Sdim 75360784Sdim /// Destination of the call. It should be either a register, globaladdress, 76360784Sdim /// or externalsymbol. 77360784Sdim MachineOperand Callee = MachineOperand::CreateImm(0); 78360784Sdim 79360784Sdim /// Descriptor for the return type of the function. 80360784Sdim ArgInfo OrigRet; 81360784Sdim 82360784Sdim /// List of descriptors of the arguments passed to the function. 83360784Sdim SmallVector<ArgInfo, 8> OrigArgs; 84360784Sdim 85360784Sdim /// Valid if the call has a swifterror inout parameter, and contains the 86360784Sdim /// vreg that the swifterror should be copied into after the call. 87360784Sdim Register SwiftErrorVReg = 0; 88360784Sdim 89360784Sdim MDNode *KnownCallees = nullptr; 90360784Sdim 91360784Sdim /// True if the call must be tail call optimized. 92360784Sdim bool IsMustTailCall = false; 93360784Sdim 94360784Sdim /// True if the call passes all target-independent checks for tail call 95360784Sdim /// optimization. 96360784Sdim bool IsTailCall = false; 97360784Sdim 98360784Sdim /// True if the call was lowered as a tail call. This is consumed by the 99360784Sdim /// legalizer. This allows the legalizer to lower libcalls as tail calls. 100360784Sdim bool LoweredTailCall = false; 101360784Sdim 102360784Sdim /// True if the call is to a vararg function. 103360784Sdim bool IsVarArg = false; 104360784Sdim }; 105360784Sdim 106314564Sdim /// Argument handling is mostly uniform between the four places that 107314564Sdim /// make these decisions: function formal arguments, call 108314564Sdim /// instruction args, call instruction returns and function 109314564Sdim /// returns. However, once a decision has been made on where an 110360784Sdim /// argument should go, exactly what happens can vary slightly. This 111314564Sdim /// class abstracts the differences. 112314564Sdim struct ValueHandler { 113321369Sdim ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 114321369Sdim CCAssignFn *AssignFn) 115321369Sdim : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {} 116321369Sdim 117321369Sdim virtual ~ValueHandler() = default; 118321369Sdim 119360784Sdim /// Returns true if the handler is dealing with incoming arguments, 120360784Sdim /// i.e. those that move values from some physical location to vregs. 121360784Sdim virtual bool isIncomingArgumentHandler() const = 0; 122353358Sdim 123314564Sdim /// Materialize a VReg containing the address of the specified 124314564Sdim /// stack-based object. This is either based on a FrameIndex or 125314564Sdim /// direct SP manipulation, depending on the context. \p MPO 126314564Sdim /// should be initialized to an appropriate description of the 127314564Sdim /// address created. 128353358Sdim virtual Register getStackAddress(uint64_t Size, int64_t Offset, 129314564Sdim MachinePointerInfo &MPO) = 0; 130314564Sdim 131314564Sdim /// The specified value has been assigned to a physical register, 132314564Sdim /// handle the appropriate COPY (either to or from) and mark any 133314564Sdim /// relevant uses/defines as needed. 134353358Sdim virtual void assignValueToReg(Register ValVReg, Register PhysReg, 135314564Sdim CCValAssign &VA) = 0; 136314564Sdim 137314564Sdim /// The specified value has been assigned to a stack 138314564Sdim /// location. Load or store it there, with appropriate extension 139314564Sdim /// if necessary. 140353358Sdim virtual void assignValueToAddress(Register ValVReg, Register Addr, 141314564Sdim uint64_t Size, MachinePointerInfo &MPO, 142314564Sdim CCValAssign &VA) = 0; 143314564Sdim 144321369Sdim /// Handle custom values, which may be passed into one or more of \p VAs. 145321369Sdim /// \return The number of \p VAs that have been assigned after the first 146321369Sdim /// one, and which should therefore be skipped from further 147321369Sdim /// processing. 148321369Sdim virtual unsigned assignCustomValue(const ArgInfo &Arg, 149321369Sdim ArrayRef<CCValAssign> VAs) { 150321369Sdim // This is not a pure virtual method because not all targets need to worry 151321369Sdim // about custom values. 152321369Sdim llvm_unreachable("Custom values not supported"); 153321369Sdim } 154321369Sdim 155353358Sdim Register extendRegister(Register ValReg, CCValAssign &VA); 156314564Sdim 157321369Sdim virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, 158321369Sdim CCValAssign::LocInfo LocInfo, const ArgInfo &Info, 159360784Sdim ISD::ArgFlagsTy Flags, CCState &State) { 160360784Sdim return AssignFn(ValNo, ValVT, LocVT, LocInfo, Flags, State); 161321369Sdim } 162314564Sdim 163314564Sdim MachineIRBuilder &MIRBuilder; 164314564Sdim MachineRegisterInfo &MRI; 165321369Sdim CCAssignFn *AssignFn; 166344779Sdim 167344779Sdim private: 168344779Sdim virtual void anchor(); 169314564Sdim }; 170314564Sdim 171314564Sdimprotected: 172303231Sdim /// Getter for generic TargetLowering class. 173303231Sdim const TargetLowering *getTLI() const { 174303231Sdim return TLI; 175303231Sdim } 176303231Sdim 177303231Sdim /// Getter for target specific TargetLowering class. 178303231Sdim template <class XXXTargetLowering> 179303231Sdim const XXXTargetLowering *getTLI() const { 180303231Sdim return static_cast<const XXXTargetLowering *>(TLI); 181303231Sdim } 182314564Sdim 183314564Sdim template <typename FuncInfoTy> 184341825Sdim void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, 185314564Sdim const FuncInfoTy &FuncInfo) const; 186314564Sdim 187353358Sdim /// Generate instructions for packing \p SrcRegs into one big register 188353358Sdim /// corresponding to the aggregate type \p PackedTy. 189353358Sdim /// 190353358Sdim /// \param SrcRegs should contain one virtual register for each base type in 191353358Sdim /// \p PackedTy, as returned by computeValueLLTs. 192353358Sdim /// 193353358Sdim /// \return The packed register. 194353358Sdim Register packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy, 195353358Sdim MachineIRBuilder &MIRBuilder) const; 196353358Sdim 197353358Sdim /// Generate instructions for unpacking \p SrcReg into the \p DstRegs 198353358Sdim /// corresponding to the aggregate type \p PackedTy. 199353358Sdim /// 200353358Sdim /// \param DstRegs should contain one virtual register for each base type in 201353358Sdim /// \p PackedTy, as returned by computeValueLLTs. 202353358Sdim void unpackRegs(ArrayRef<Register> DstRegs, Register SrcReg, Type *PackedTy, 203353358Sdim MachineIRBuilder &MIRBuilder) const; 204353358Sdim 205321369Sdim /// Invoke Handler::assignArg on each of the given \p Args and then use 206314564Sdim /// \p Callback to move them to the assigned locations. 207314564Sdim /// 208314564Sdim /// \return True if everything has succeeded, false otherwise. 209360784Sdim bool handleAssignments(MachineIRBuilder &MIRBuilder, 210360784Sdim SmallVectorImpl<ArgInfo> &Args, 211341825Sdim ValueHandler &Handler) const; 212353358Sdim bool handleAssignments(CCState &CCState, 213353358Sdim SmallVectorImpl<CCValAssign> &ArgLocs, 214360784Sdim MachineIRBuilder &MIRBuilder, 215360784Sdim SmallVectorImpl<ArgInfo> &Args, 216353358Sdim ValueHandler &Handler) const; 217360784Sdim 218360784Sdim /// Analyze passed or returned values from a call, supplied in \p ArgInfo, 219360784Sdim /// incorporating info about the passed values into \p CCState. 220360784Sdim /// 221360784Sdim /// Used to check if arguments are suitable for tail call lowering. 222360784Sdim bool analyzeArgInfo(CCState &CCState, SmallVectorImpl<ArgInfo> &Args, 223360784Sdim CCAssignFn &AssignFnFixed, 224360784Sdim CCAssignFn &AssignFnVarArg) const; 225360784Sdim 226360784Sdim /// \returns True if the calling convention for a callee and its caller pass 227360784Sdim /// results in the same way. Typically used for tail call eligibility checks. 228360784Sdim /// 229360784Sdim /// \p Info is the CallLoweringInfo for the call. 230360784Sdim /// \p MF is the MachineFunction for the caller. 231360784Sdim /// \p InArgs contains the results of the call. 232360784Sdim /// \p CalleeAssignFnFixed is the CCAssignFn to be used for the callee for 233360784Sdim /// fixed arguments. 234360784Sdim /// \p CalleeAssignFnVarArg is similar, but for varargs. 235360784Sdim /// \p CallerAssignFnFixed is the CCAssignFn to be used for the caller for 236360784Sdim /// fixed arguments. 237360784Sdim /// \p CallerAssignFnVarArg is similar, but for varargs. 238360784Sdim bool resultsCompatible(CallLoweringInfo &Info, MachineFunction &MF, 239360784Sdim SmallVectorImpl<ArgInfo> &InArgs, 240360784Sdim CCAssignFn &CalleeAssignFnFixed, 241360784Sdim CCAssignFn &CalleeAssignFnVarArg, 242360784Sdim CCAssignFn &CallerAssignFnFixed, 243360784Sdim CCAssignFn &CallerAssignFnVarArg) const; 244360784Sdim 245314564Sdimpublic: 246303231Sdim CallLowering(const TargetLowering *TLI) : TLI(TLI) {} 247321369Sdim virtual ~CallLowering() = default; 248303231Sdim 249353358Sdim /// \return true if the target is capable of handling swifterror values that 250353358Sdim /// have been promoted to a specified register. The extended versions of 251353358Sdim /// lowerReturn and lowerCall should be implemented. 252353358Sdim virtual bool supportSwiftError() const { 253353358Sdim return false; 254353358Sdim } 255353358Sdim 256303231Sdim /// This hook must be implemented to lower outgoing return values, described 257344779Sdim /// by \p Val, into the specified virtual registers \p VRegs. 258303231Sdim /// This hook is used by GlobalISel. 259303231Sdim /// 260353358Sdim /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter 261353358Sdim /// that needs to be implicitly returned. 262353358Sdim /// 263303231Sdim /// \return True if the lowering succeeds, false otherwise. 264344779Sdim virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, 265353358Sdim ArrayRef<Register> VRegs, 266353358Sdim Register SwiftErrorVReg) const { 267353358Sdim if (!supportSwiftError()) { 268353358Sdim assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); 269353358Sdim return lowerReturn(MIRBuilder, Val, VRegs); 270353358Sdim } 271303231Sdim return false; 272303231Sdim } 273303231Sdim 274353358Sdim /// This hook behaves as the extended lowerReturn function, but for targets 275353358Sdim /// that do not support swifterror value promotion. 276353358Sdim virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, 277353358Sdim ArrayRef<Register> VRegs) const { 278353358Sdim return false; 279353358Sdim } 280353358Sdim 281303231Sdim /// This hook must be implemented to lower the incoming (formal) 282353358Sdim /// arguments, described by \p VRegs, for GlobalISel. Each argument 283353358Sdim /// must end up in the related virtual registers described by \p VRegs. 284353358Sdim /// In other words, the first argument should end up in \c VRegs[0], 285353358Sdim /// the second in \c VRegs[1], and so on. For each argument, there will be one 286353358Sdim /// register for each non-aggregate type, as returned by \c computeValueLLTs. 287303231Sdim /// \p MIRBuilder is set to the proper insertion for the argument 288303231Sdim /// lowering. 289303231Sdim /// 290303231Sdim /// \return True if the lowering succeeded, false otherwise. 291314564Sdim virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, 292314564Sdim const Function &F, 293353358Sdim ArrayRef<ArrayRef<Register>> VRegs) const { 294303231Sdim return false; 295303231Sdim } 296314564Sdim 297314564Sdim /// This hook must be implemented to lower the given call instruction, 298314564Sdim /// including argument and return value marshalling. 299314564Sdim /// 300321369Sdim /// 301314564Sdim /// \return true if the lowering succeeded, false otherwise. 302360784Sdim virtual bool lowerCall(MachineIRBuilder &MIRBuilder, 303360784Sdim CallLoweringInfo &Info) const { 304353358Sdim return false; 305353358Sdim } 306353358Sdim 307321369Sdim /// Lower the given call instruction, including argument and return value 308321369Sdim /// marshalling. 309314564Sdim /// 310321369Sdim /// \p CI is the call/invoke instruction. 311321369Sdim /// 312353358Sdim /// \p ResRegs are the registers where the call's return value should be 313353358Sdim /// stored (or 0 if there is no return value). There will be one register for 314353358Sdim /// each non-aggregate type, as returned by \c computeValueLLTs. 315314564Sdim /// 316353358Sdim /// \p ArgRegs is a list of lists of virtual registers containing each 317353358Sdim /// argument that needs to be passed (argument \c i should be placed in \c 318353358Sdim /// ArgRegs[i]). For each argument, there will be one register for each 319353358Sdim /// non-aggregate type, as returned by \c computeValueLLTs. 320314564Sdim /// 321353358Sdim /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout 322353358Sdim /// parameter, and contains the vreg that the swifterror should be copied into 323353358Sdim /// after the call. 324353358Sdim /// 325314564Sdim /// \p GetCalleeReg is a callback to materialize a register for the callee if 326314564Sdim /// the target determines it cannot jump to the destination based purely on \p 327314564Sdim /// CI. This might be because \p CI is indirect, or because of the limited 328314564Sdim /// range of an immediate jump. 329314564Sdim /// 330314564Sdim /// \return true if the lowering succeeded, false otherwise. 331321369Sdim bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, 332353358Sdim ArrayRef<Register> ResRegs, 333353358Sdim ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg, 334321369Sdim std::function<unsigned()> GetCalleeReg) const; 335303231Sdim}; 336303231Sdim 337321369Sdim} // end namespace llvm 338321369Sdim 339321369Sdim#endif // LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H 340