Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame^] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
| 10 | /// This file describes how to lower LLVM calls to machine code calls. |
| 11 | /// |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H |
| 15 | #define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H |
| 16 | |
| 17 | #include "llvm/ADT/ArrayRef.h" |
| 18 | #include "llvm/CodeGen/CallingConvLower.h" |
| 19 | #include "llvm/CodeGen/TargetCallingConv.h" |
| 20 | #include "llvm/IR/CallSite.h" |
| 21 | #include "llvm/IR/CallingConv.h" |
| 22 | #include "llvm/Support/ErrorHandling.h" |
| 23 | #include "llvm/Support/MachineValueType.h" |
| 24 | #include <cstdint> |
| 25 | #include <functional> |
| 26 | |
| 27 | namespace llvm { |
| 28 | |
| 29 | class DataLayout; |
| 30 | class Function; |
| 31 | class MachineIRBuilder; |
| 32 | class MachineOperand; |
| 33 | struct MachinePointerInfo; |
| 34 | class MachineRegisterInfo; |
| 35 | class TargetLowering; |
| 36 | class Type; |
| 37 | class Value; |
| 38 | |
| 39 | class CallLowering { |
| 40 | const TargetLowering *TLI; |
| 41 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame^] | 42 | virtual void anchor(); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 43 | public: |
| 44 | struct ArgInfo { |
| 45 | unsigned Reg; |
| 46 | Type *Ty; |
| 47 | ISD::ArgFlagsTy Flags; |
| 48 | bool IsFixed; |
| 49 | |
| 50 | ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, |
| 51 | bool IsFixed = true) |
| 52 | : Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {} |
| 53 | }; |
| 54 | |
| 55 | /// Argument handling is mostly uniform between the four places that |
| 56 | /// make these decisions: function formal arguments, call |
| 57 | /// instruction args, call instruction returns and function |
| 58 | /// returns. However, once a decision has been made on where an |
| 59 | /// arugment should go, exactly what happens can vary slightly. This |
| 60 | /// class abstracts the differences. |
| 61 | struct ValueHandler { |
| 62 | ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
| 63 | CCAssignFn *AssignFn) |
| 64 | : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {} |
| 65 | |
| 66 | virtual ~ValueHandler() = default; |
| 67 | |
| 68 | /// Materialize a VReg containing the address of the specified |
| 69 | /// stack-based object. This is either based on a FrameIndex or |
| 70 | /// direct SP manipulation, depending on the context. \p MPO |
| 71 | /// should be initialized to an appropriate description of the |
| 72 | /// address created. |
| 73 | virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, |
| 74 | MachinePointerInfo &MPO) = 0; |
| 75 | |
| 76 | /// The specified value has been assigned to a physical register, |
| 77 | /// handle the appropriate COPY (either to or from) and mark any |
| 78 | /// relevant uses/defines as needed. |
| 79 | virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg, |
| 80 | CCValAssign &VA) = 0; |
| 81 | |
| 82 | /// The specified value has been assigned to a stack |
| 83 | /// location. Load or store it there, with appropriate extension |
| 84 | /// if necessary. |
| 85 | virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, |
| 86 | uint64_t Size, MachinePointerInfo &MPO, |
| 87 | CCValAssign &VA) = 0; |
| 88 | |
| 89 | /// Handle custom values, which may be passed into one or more of \p VAs. |
| 90 | /// \return The number of \p VAs that have been assigned after the first |
| 91 | /// one, and which should therefore be skipped from further |
| 92 | /// processing. |
| 93 | virtual unsigned assignCustomValue(const ArgInfo &Arg, |
| 94 | ArrayRef<CCValAssign> VAs) { |
| 95 | // This is not a pure virtual method because not all targets need to worry |
| 96 | // about custom values. |
| 97 | llvm_unreachable("Custom values not supported"); |
| 98 | } |
| 99 | |
| 100 | unsigned extendRegister(unsigned ValReg, CCValAssign &VA); |
| 101 | |
| 102 | virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, |
| 103 | CCValAssign::LocInfo LocInfo, const ArgInfo &Info, |
| 104 | CCState &State) { |
| 105 | return AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State); |
| 106 | } |
| 107 | |
| 108 | MachineIRBuilder &MIRBuilder; |
| 109 | MachineRegisterInfo &MRI; |
| 110 | CCAssignFn *AssignFn; |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame^] | 111 | |
| 112 | private: |
| 113 | virtual void anchor(); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 114 | }; |
| 115 | |
| 116 | protected: |
| 117 | /// Getter for generic TargetLowering class. |
| 118 | const TargetLowering *getTLI() const { |
| 119 | return TLI; |
| 120 | } |
| 121 | |
| 122 | /// Getter for target specific TargetLowering class. |
| 123 | template <class XXXTargetLowering> |
| 124 | const XXXTargetLowering *getTLI() const { |
| 125 | return static_cast<const XXXTargetLowering *>(TLI); |
| 126 | } |
| 127 | |
| 128 | template <typename FuncInfoTy> |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 129 | void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 130 | const FuncInfoTy &FuncInfo) const; |
| 131 | |
| 132 | /// Invoke Handler::assignArg on each of the given \p Args and then use |
| 133 | /// \p Callback to move them to the assigned locations. |
| 134 | /// |
| 135 | /// \return True if everything has succeeded, false otherwise. |
| 136 | bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 137 | ValueHandler &Handler) const; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 138 | |
| 139 | public: |
| 140 | CallLowering(const TargetLowering *TLI) : TLI(TLI) {} |
| 141 | virtual ~CallLowering() = default; |
| 142 | |
| 143 | /// This hook must be implemented to lower outgoing return values, described |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 144 | /// by \p Val, into the specified virtual registers \p VRegs. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 145 | /// This hook is used by GlobalISel. |
| 146 | /// |
| 147 | /// \return True if the lowering succeeds, false otherwise. |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 148 | virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, |
| 149 | ArrayRef<unsigned> VRegs) const { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 150 | return false; |
| 151 | } |
| 152 | |
| 153 | /// This hook must be implemented to lower the incoming (formal) |
| 154 | /// arguments, described by \p Args, for GlobalISel. Each argument |
| 155 | /// must end up in the related virtual register described by VRegs. |
| 156 | /// In other words, the first argument should end up in VRegs[0], |
| 157 | /// the second in VRegs[1], and so on. |
| 158 | /// \p MIRBuilder is set to the proper insertion for the argument |
| 159 | /// lowering. |
| 160 | /// |
| 161 | /// \return True if the lowering succeeded, false otherwise. |
| 162 | virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, |
| 163 | const Function &F, |
| 164 | ArrayRef<unsigned> VRegs) const { |
| 165 | return false; |
| 166 | } |
| 167 | |
| 168 | /// This hook must be implemented to lower the given call instruction, |
| 169 | /// including argument and return value marshalling. |
| 170 | /// |
| 171 | /// \p CallConv is the calling convention to be used for the call. |
| 172 | /// |
| 173 | /// \p Callee is the destination of the call. It should be either a register, |
| 174 | /// globaladdress, or externalsymbol. |
| 175 | /// |
| 176 | /// \p ResTy is the type returned by the function |
| 177 | /// |
| 178 | /// \p ResReg is the generic virtual register that the returned |
| 179 | /// value should be lowered into. |
| 180 | /// |
| 181 | /// \p ArgTys is a list of the types each member of \p ArgRegs has; used by |
| 182 | /// the target to decide which register/stack slot should be allocated. |
| 183 | /// |
| 184 | /// \p ArgRegs is a list of virtual registers containing each argument that |
| 185 | /// needs to be passed. |
| 186 | /// |
| 187 | /// \return true if the lowering succeeded, false otherwise. |
| 188 | virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, |
| 189 | const MachineOperand &Callee, const ArgInfo &OrigRet, |
| 190 | ArrayRef<ArgInfo> OrigArgs) const { |
| 191 | return false; |
| 192 | } |
| 193 | |
| 194 | /// Lower the given call instruction, including argument and return value |
| 195 | /// marshalling. |
| 196 | /// |
| 197 | /// \p CI is the call/invoke instruction. |
| 198 | /// |
| 199 | /// \p ResReg is a register where the call's return value should be stored (or |
| 200 | /// 0 if there is no return value). |
| 201 | /// |
| 202 | /// \p ArgRegs is a list of virtual registers containing each argument that |
| 203 | /// needs to be passed. |
| 204 | /// |
| 205 | /// \p GetCalleeReg is a callback to materialize a register for the callee if |
| 206 | /// the target determines it cannot jump to the destination based purely on \p |
| 207 | /// CI. This might be because \p CI is indirect, or because of the limited |
| 208 | /// range of an immediate jump. |
| 209 | /// |
| 210 | /// \return true if the lowering succeeded, false otherwise. |
| 211 | bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, |
| 212 | unsigned ResReg, ArrayRef<unsigned> ArgRegs, |
| 213 | std::function<unsigned()> GetCalleeReg) const; |
| 214 | }; |
| 215 | |
| 216 | } // end namespace llvm |
| 217 | |
| 218 | #endif // LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H |