Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 1 | //===-- lib/CodeGen/GlobalISel/CallLowering.cpp - Call lowering -----------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [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 |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
| 10 | /// This file implements some simple delegations needed for call lowering. |
| 11 | /// |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 14 | #include "llvm/CodeGen/GlobalISel/CallLowering.h" |
Diana Picus | c3dbe23 | 2019-06-27 08:54:17 +0000 | [diff] [blame] | 15 | #include "llvm/CodeGen/Analysis.h" |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 16 | #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 17 | #include "llvm/CodeGen/MachineOperand.h" |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 18 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
David Blaikie | b3bde2e | 2017-11-17 01:07:10 +0000 | [diff] [blame] | 19 | #include "llvm/CodeGen/TargetLowering.h" |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 20 | #include "llvm/IR/DataLayout.h" |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 21 | #include "llvm/IR/Instructions.h" |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 22 | #include "llvm/IR/Module.h" |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 23 | |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 24 | #define DEBUG_TYPE "call-lowering" |
| 25 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 26 | using namespace llvm; |
| 27 | |
Richard Trieu | a87b70d | 2018-12-29 02:02:13 +0000 | [diff] [blame] | 28 | void CallLowering::anchor() {} |
| 29 | |
Tim Northover | 3b2157a | 2019-05-24 08:40:13 +0000 | [diff] [blame] | 30 | bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, |
Diana Picus | 8138996 | 2019-06-27 09:15:53 +0000 | [diff] [blame^] | 31 | ArrayRef<Register> ResRegs, |
| 32 | ArrayRef<Register> ArgRegs, |
Matt Arsenault | e3a676e | 2019-06-24 15:50:29 +0000 | [diff] [blame] | 33 | Register SwiftErrorVReg, |
Tim Northover | 3b2157a | 2019-05-24 08:40:13 +0000 | [diff] [blame] | 34 | std::function<unsigned()> GetCalleeReg) const { |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 35 | auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 36 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 37 | // First step is to marshall all the function's parameters into the correct |
| 38 | // physregs and memory locations. Gather the sequence of argument types that |
| 39 | // we'll pass to the assigner function. |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 40 | SmallVector<ArgInfo, 8> OrigArgs; |
| 41 | unsigned i = 0; |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 42 | unsigned NumFixedArgs = CS.getFunctionType()->getNumParams(); |
| 43 | for (auto &Arg : CS.args()) { |
Tim Northover | d943354 | 2017-01-17 22:30:10 +0000 | [diff] [blame] | 44 | ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}, |
| 45 | i < NumFixedArgs}; |
Reid Kleckner | a0b45f4 | 2017-05-03 18:17:31 +0000 | [diff] [blame] | 46 | setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS); |
Tim Northover | 3b2157a | 2019-05-24 08:40:13 +0000 | [diff] [blame] | 47 | // We don't currently support swiftself args. |
| 48 | if (OrigArg.Flags.isSwiftSelf()) |
Amara Emerson | fdd089a | 2018-07-26 01:25:58 +0000 | [diff] [blame] | 49 | return false; |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 50 | OrigArgs.push_back(OrigArg); |
| 51 | ++i; |
| 52 | } |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 53 | |
| 54 | MachineOperand Callee = MachineOperand::CreateImm(0); |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 55 | if (const Function *F = CS.getCalledFunction()) |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 56 | Callee = MachineOperand::CreateGA(F, 0); |
| 57 | else |
| 58 | Callee = MachineOperand::CreateReg(GetCalleeReg(), false); |
| 59 | |
Diana Picus | 8138996 | 2019-06-27 09:15:53 +0000 | [diff] [blame^] | 60 | ArgInfo OrigRet{ResRegs, CS.getType(), ISD::ArgFlagsTy{}}; |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 61 | if (!OrigRet.Ty->isVoidTy()) |
Reid Kleckner | b518054 | 2017-03-21 16:57:19 +0000 | [diff] [blame] | 62 | setArgFlags(OrigRet, AttributeList::ReturnIndex, DL, CS); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 63 | |
Tim Northover | 3b2157a | 2019-05-24 08:40:13 +0000 | [diff] [blame] | 64 | return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs, |
| 65 | SwiftErrorVReg); |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 66 | } |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 67 | |
| 68 | template <typename FuncInfoTy> |
| 69 | void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 70 | const DataLayout &DL, |
| 71 | const FuncInfoTy &FuncInfo) const { |
Reid Kleckner | b518054 | 2017-03-21 16:57:19 +0000 | [diff] [blame] | 72 | const AttributeList &Attrs = FuncInfo.getAttributes(); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 73 | if (Attrs.hasAttribute(OpIdx, Attribute::ZExt)) |
| 74 | Arg.Flags.setZExt(); |
| 75 | if (Attrs.hasAttribute(OpIdx, Attribute::SExt)) |
| 76 | Arg.Flags.setSExt(); |
| 77 | if (Attrs.hasAttribute(OpIdx, Attribute::InReg)) |
| 78 | Arg.Flags.setInReg(); |
| 79 | if (Attrs.hasAttribute(OpIdx, Attribute::StructRet)) |
| 80 | Arg.Flags.setSRet(); |
| 81 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftSelf)) |
| 82 | Arg.Flags.setSwiftSelf(); |
| 83 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError)) |
| 84 | Arg.Flags.setSwiftError(); |
| 85 | if (Attrs.hasAttribute(OpIdx, Attribute::ByVal)) |
| 86 | Arg.Flags.setByVal(); |
| 87 | if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca)) |
| 88 | Arg.Flags.setInAlloca(); |
| 89 | |
| 90 | if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) { |
| 91 | Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType(); |
Tim Northover | b714120 | 2019-05-30 18:48:23 +0000 | [diff] [blame] | 92 | |
| 93 | auto Ty = Attrs.getAttribute(OpIdx, Attribute::ByVal).getValueAsType(); |
| 94 | Arg.Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy)); |
| 95 | |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 96 | // For ByVal, alignment should be passed from FE. BE will guess if |
| 97 | // this info is not there but there are cases it cannot get right. |
| 98 | unsigned FrameAlign; |
Reid Kleckner | ee4930b | 2017-05-02 22:07:37 +0000 | [diff] [blame] | 99 | if (FuncInfo.getParamAlignment(OpIdx - 2)) |
| 100 | FrameAlign = FuncInfo.getParamAlignment(OpIdx - 2); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 101 | else |
| 102 | FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL); |
| 103 | Arg.Flags.setByValAlign(FrameAlign); |
| 104 | } |
| 105 | if (Attrs.hasAttribute(OpIdx, Attribute::Nest)) |
| 106 | Arg.Flags.setNest(); |
| 107 | Arg.Flags.setOrigAlign(DL.getABITypeAlignment(Arg.Ty)); |
| 108 | } |
| 109 | |
| 110 | template void |
| 111 | CallLowering::setArgFlags<Function>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 112 | const DataLayout &DL, |
| 113 | const Function &FuncInfo) const; |
| 114 | |
| 115 | template void |
| 116 | CallLowering::setArgFlags<CallInst>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 117 | const DataLayout &DL, |
| 118 | const CallInst &FuncInfo) const; |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 119 | |
Diana Picus | c3dbe23 | 2019-06-27 08:54:17 +0000 | [diff] [blame] | 120 | Register CallLowering::packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy, |
| 121 | MachineIRBuilder &MIRBuilder) const { |
| 122 | assert(SrcRegs.size() > 1 && "Nothing to pack"); |
| 123 | |
| 124 | const DataLayout &DL = MIRBuilder.getMF().getDataLayout(); |
| 125 | MachineRegisterInfo *MRI = MIRBuilder.getMRI(); |
| 126 | |
| 127 | LLT PackedLLT = getLLTForType(*PackedTy, DL); |
| 128 | |
| 129 | SmallVector<LLT, 8> LLTs; |
| 130 | SmallVector<uint64_t, 8> Offsets; |
| 131 | computeValueLLTs(DL, *PackedTy, LLTs, &Offsets); |
| 132 | assert(LLTs.size() == SrcRegs.size() && "Regs / types mismatch"); |
| 133 | |
| 134 | Register Dst = MRI->createGenericVirtualRegister(PackedLLT); |
| 135 | MIRBuilder.buildUndef(Dst); |
| 136 | for (unsigned i = 0; i < SrcRegs.size(); ++i) { |
| 137 | Register NewDst = MRI->createGenericVirtualRegister(PackedLLT); |
| 138 | MIRBuilder.buildInsert(NewDst, Dst, SrcRegs[i], Offsets[i]); |
| 139 | Dst = NewDst; |
| 140 | } |
| 141 | |
| 142 | return Dst; |
| 143 | } |
| 144 | |
| 145 | void CallLowering::unpackRegs(ArrayRef<Register> DstRegs, Register SrcReg, |
| 146 | Type *PackedTy, |
| 147 | MachineIRBuilder &MIRBuilder) const { |
| 148 | assert(DstRegs.size() > 1 && "Nothing to unpack"); |
| 149 | |
| 150 | const DataLayout &DL = MIRBuilder.getMF().getDataLayout(); |
| 151 | |
| 152 | SmallVector<LLT, 8> LLTs; |
| 153 | SmallVector<uint64_t, 8> Offsets; |
| 154 | computeValueLLTs(DL, *PackedTy, LLTs, &Offsets); |
| 155 | assert(LLTs.size() == DstRegs.size() && "Regs / types mismatch"); |
| 156 | |
| 157 | for (unsigned i = 0; i < DstRegs.size(); ++i) |
| 158 | MIRBuilder.buildExtract(DstRegs[i], SrcReg, Offsets[i]); |
| 159 | } |
| 160 | |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 161 | bool CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder, |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 162 | ArrayRef<ArgInfo> Args, |
| 163 | ValueHandler &Handler) const { |
| 164 | MachineFunction &MF = MIRBuilder.getMF(); |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 165 | const Function &F = MF.getFunction(); |
Tim Northover | c0bd197 | 2016-12-05 22:20:32 +0000 | [diff] [blame] | 166 | const DataLayout &DL = F.getParent()->getDataLayout(); |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 167 | |
| 168 | SmallVector<CCValAssign, 16> ArgLocs; |
| 169 | CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); |
| 170 | |
| 171 | unsigned NumArgs = Args.size(); |
| 172 | for (unsigned i = 0; i != NumArgs; ++i) { |
| 173 | MVT CurVT = MVT::getVT(Args[i].Ty); |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 174 | if (Handler.assignArg(i, CurVT, CurVT, CCValAssign::Full, Args[i], CCInfo)) { |
| 175 | // Try to use the register type if we couldn't assign the VT. |
Amara Emerson | bdb5e4e | 2019-04-12 22:05:46 +0000 | [diff] [blame] | 176 | if (!Handler.isArgumentHandler() || !CurVT.isValid()) |
Matt Arsenault | e3a676e | 2019-06-24 15:50:29 +0000 | [diff] [blame] | 177 | return false; |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 178 | CurVT = TLI->getRegisterTypeForCallingConv( |
| 179 | F.getContext(), F.getCallingConv(), EVT(CurVT)); |
| 180 | if (Handler.assignArg(i, CurVT, CurVT, CCValAssign::Full, Args[i], CCInfo)) |
| 181 | return false; |
| 182 | } |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 183 | } |
| 184 | |
Diana Picus | ca6a890 | 2017-02-16 07:53:07 +0000 | [diff] [blame] | 185 | for (unsigned i = 0, e = Args.size(), j = 0; i != e; ++i, ++j) { |
| 186 | assert(j < ArgLocs.size() && "Skipped too many arg locs"); |
| 187 | |
| 188 | CCValAssign &VA = ArgLocs[j]; |
| 189 | assert(VA.getValNo() == i && "Location doesn't correspond to current arg"); |
| 190 | |
| 191 | if (VA.needsCustom()) { |
| 192 | j += Handler.assignCustomValue(Args[i], makeArrayRef(ArgLocs).slice(j)); |
| 193 | continue; |
| 194 | } |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 195 | |
Diana Picus | 69ce1c13 | 2019-06-27 08:50:53 +0000 | [diff] [blame] | 196 | assert(Args[i].Regs.size() == 1 && |
| 197 | "Can't handle multiple virtual regs yet"); |
| 198 | |
| 199 | // FIXME: Pack registers if we have more than one. |
| 200 | unsigned ArgReg = Args[i].Regs[0]; |
| 201 | |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 202 | if (VA.isRegLoc()) { |
| 203 | MVT OrigVT = MVT::getVT(Args[i].Ty); |
| 204 | MVT VAVT = VA.getValVT(); |
| 205 | if (Handler.isArgumentHandler() && VAVT != OrigVT) { |
| 206 | if (VAVT.getSizeInBits() < OrigVT.getSizeInBits()) |
| 207 | return false; // Can't handle this type of arg yet. |
| 208 | const LLT VATy(VAVT); |
| 209 | unsigned NewReg = |
| 210 | MIRBuilder.getMRI()->createGenericVirtualRegister(VATy); |
| 211 | Handler.assignValueToReg(NewReg, VA.getLocReg(), VA); |
| 212 | // If it's a vector type, we either need to truncate the elements |
| 213 | // or do an unmerge to get the lower block of elements. |
| 214 | if (VATy.isVector() && |
| 215 | VATy.getNumElements() > OrigVT.getVectorNumElements()) { |
| 216 | const LLT OrigTy(OrigVT); |
| 217 | // Just handle the case where the VA type is 2 * original type. |
| 218 | if (VATy.getNumElements() != OrigVT.getVectorNumElements() * 2) { |
| 219 | LLVM_DEBUG(dbgs() |
| 220 | << "Incoming promoted vector arg has too many elts"); |
| 221 | return false; |
| 222 | } |
| 223 | auto Unmerge = MIRBuilder.buildUnmerge({OrigTy, OrigTy}, {NewReg}); |
Diana Picus | 69ce1c13 | 2019-06-27 08:50:53 +0000 | [diff] [blame] | 224 | MIRBuilder.buildCopy(ArgReg, Unmerge.getReg(0)); |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 225 | } else { |
Diana Picus | 69ce1c13 | 2019-06-27 08:50:53 +0000 | [diff] [blame] | 226 | MIRBuilder.buildTrunc(ArgReg, {NewReg}).getReg(0); |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 227 | } |
| 228 | } else { |
Diana Picus | 69ce1c13 | 2019-06-27 08:50:53 +0000 | [diff] [blame] | 229 | Handler.assignValueToReg(ArgReg, VA.getLocReg(), VA); |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 230 | } |
| 231 | } else if (VA.isMemLoc()) { |
| 232 | MVT VT = MVT::getVT(Args[i].Ty); |
| 233 | unsigned Size = VT == MVT::iPTR ? DL.getPointerSize() |
| 234 | : alignTo(VT.getSizeInBits(), 8) / 8; |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 235 | unsigned Offset = VA.getLocMemOffset(); |
| 236 | MachinePointerInfo MPO; |
| 237 | unsigned StackAddr = Handler.getStackAddress(Size, Offset, MPO); |
Diana Picus | 69ce1c13 | 2019-06-27 08:50:53 +0000 | [diff] [blame] | 238 | Handler.assignValueToAddress(ArgReg, StackAddr, Size, MPO, VA); |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 239 | } else { |
| 240 | // FIXME: Support byvals and other weirdness |
| 241 | return false; |
| 242 | } |
| 243 | } |
| 244 | return true; |
| 245 | } |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 246 | |
Matt Arsenault | faeaedf | 2019-06-24 16:16:12 +0000 | [diff] [blame] | 247 | Register CallLowering::ValueHandler::extendRegister(Register ValReg, |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 248 | CCValAssign &VA) { |
| 249 | LLT LocTy{VA.getLocVT()}; |
Amara Emerson | 2b523f8 | 2019-04-09 21:22:33 +0000 | [diff] [blame] | 250 | if (LocTy.getSizeInBits() == MRI.getType(ValReg).getSizeInBits()) |
| 251 | return ValReg; |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 252 | switch (VA.getLocInfo()) { |
| 253 | default: break; |
| 254 | case CCValAssign::Full: |
| 255 | case CCValAssign::BCvt: |
| 256 | // FIXME: bitconverting between vector types may or may not be a |
| 257 | // nop in big-endian situations. |
| 258 | return ValReg; |
Aditya Nandakumar | c3bfc81 | 2017-10-09 20:07:43 +0000 | [diff] [blame] | 259 | case CCValAssign::AExt: { |
Aditya Nandakumar | c3bfc81 | 2017-10-09 20:07:43 +0000 | [diff] [blame] | 260 | auto MIB = MIRBuilder.buildAnyExt(LocTy, ValReg); |
| 261 | return MIB->getOperand(0).getReg(); |
| 262 | } |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 263 | case CCValAssign::SExt: { |
| 264 | unsigned NewReg = MRI.createGenericVirtualRegister(LocTy); |
| 265 | MIRBuilder.buildSExt(NewReg, ValReg); |
| 266 | return NewReg; |
| 267 | } |
| 268 | case CCValAssign::ZExt: { |
| 269 | unsigned NewReg = MRI.createGenericVirtualRegister(LocTy); |
| 270 | MIRBuilder.buildZExt(NewReg, ValReg); |
| 271 | return NewReg; |
| 272 | } |
| 273 | } |
| 274 | llvm_unreachable("unable to extend register"); |
| 275 | } |
Richard Trieu | a87b70d | 2018-12-29 02:02:13 +0000 | [diff] [blame] | 276 | |
| 277 | void CallLowering::ValueHandler::anchor() {} |