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