Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 1 | //===-- lib/CodeGen/GlobalISel/CallLowering.cpp - Call lowering -----------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | /// |
| 10 | /// \file |
| 11 | /// This file implements some simple delegations needed for call lowering. |
| 12 | /// |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 15 | #include "llvm/CodeGen/GlobalISel/CallLowering.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 | |
| 24 | using namespace llvm; |
| 25 | |
| 26 | bool CallLowering::lowerCall( |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 27 | MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, unsigned ResReg, |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 28 | ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const { |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 29 | auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 30 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 31 | // First step is to marshall all the function's parameters into the correct |
| 32 | // physregs and memory locations. Gather the sequence of argument types that |
| 33 | // we'll pass to the assigner function. |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 34 | SmallVector<ArgInfo, 8> OrigArgs; |
| 35 | unsigned i = 0; |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 36 | unsigned NumFixedArgs = CS.getFunctionType()->getNumParams(); |
| 37 | for (auto &Arg : CS.args()) { |
Tim Northover | d943354 | 2017-01-17 22:30:10 +0000 | [diff] [blame] | 38 | ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}, |
| 39 | i < NumFixedArgs}; |
Reid Kleckner | a0b45f4 | 2017-05-03 18:17:31 +0000 | [diff] [blame] | 40 | setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 41 | OrigArgs.push_back(OrigArg); |
| 42 | ++i; |
| 43 | } |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 44 | |
| 45 | MachineOperand Callee = MachineOperand::CreateImm(0); |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 46 | if (const Function *F = CS.getCalledFunction()) |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 47 | Callee = MachineOperand::CreateGA(F, 0); |
| 48 | else |
| 49 | Callee = MachineOperand::CreateReg(GetCalleeReg(), false); |
| 50 | |
Ahmed Bougacha | d22b84b | 2017-03-10 00:25:44 +0000 | [diff] [blame] | 51 | ArgInfo OrigRet{ResReg, CS.getType(), ISD::ArgFlagsTy{}}; |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 52 | if (!OrigRet.Ty->isVoidTy()) |
Reid Kleckner | b518054 | 2017-03-21 16:57:19 +0000 | [diff] [blame] | 53 | setArgFlags(OrigRet, AttributeList::ReturnIndex, DL, CS); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 54 | |
Diana Picus | d79253a | 2017-03-20 14:40:18 +0000 | [diff] [blame] | 55 | return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs); |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 56 | } |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 57 | |
| 58 | template <typename FuncInfoTy> |
| 59 | void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 60 | const DataLayout &DL, |
| 61 | const FuncInfoTy &FuncInfo) const { |
Reid Kleckner | b518054 | 2017-03-21 16:57:19 +0000 | [diff] [blame] | 62 | const AttributeList &Attrs = FuncInfo.getAttributes(); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 63 | if (Attrs.hasAttribute(OpIdx, Attribute::ZExt)) |
| 64 | Arg.Flags.setZExt(); |
| 65 | if (Attrs.hasAttribute(OpIdx, Attribute::SExt)) |
| 66 | Arg.Flags.setSExt(); |
| 67 | if (Attrs.hasAttribute(OpIdx, Attribute::InReg)) |
| 68 | Arg.Flags.setInReg(); |
| 69 | if (Attrs.hasAttribute(OpIdx, Attribute::StructRet)) |
| 70 | Arg.Flags.setSRet(); |
| 71 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftSelf)) |
| 72 | Arg.Flags.setSwiftSelf(); |
| 73 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError)) |
| 74 | Arg.Flags.setSwiftError(); |
| 75 | if (Attrs.hasAttribute(OpIdx, Attribute::ByVal)) |
| 76 | Arg.Flags.setByVal(); |
| 77 | if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca)) |
| 78 | Arg.Flags.setInAlloca(); |
| 79 | |
| 80 | if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) { |
| 81 | Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType(); |
| 82 | Arg.Flags.setByValSize(DL.getTypeAllocSize(ElementTy)); |
| 83 | // For ByVal, alignment should be passed from FE. BE will guess if |
| 84 | // this info is not there but there are cases it cannot get right. |
| 85 | unsigned FrameAlign; |
Reid Kleckner | ee4930b | 2017-05-02 22:07:37 +0000 | [diff] [blame] | 86 | if (FuncInfo.getParamAlignment(OpIdx - 2)) |
| 87 | FrameAlign = FuncInfo.getParamAlignment(OpIdx - 2); |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame] | 88 | else |
| 89 | FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL); |
| 90 | Arg.Flags.setByValAlign(FrameAlign); |
| 91 | } |
| 92 | if (Attrs.hasAttribute(OpIdx, Attribute::Nest)) |
| 93 | Arg.Flags.setNest(); |
| 94 | Arg.Flags.setOrigAlign(DL.getABITypeAlignment(Arg.Ty)); |
| 95 | } |
| 96 | |
| 97 | template void |
| 98 | CallLowering::setArgFlags<Function>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 99 | const DataLayout &DL, |
| 100 | const Function &FuncInfo) const; |
| 101 | |
| 102 | template void |
| 103 | CallLowering::setArgFlags<CallInst>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 104 | const DataLayout &DL, |
| 105 | const CallInst &FuncInfo) const; |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 106 | |
| 107 | bool CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder, |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 108 | ArrayRef<ArgInfo> Args, |
| 109 | ValueHandler &Handler) const { |
| 110 | MachineFunction &MF = MIRBuilder.getMF(); |
Matthias Braun | f1caa28 | 2017-12-15 22:22:58 +0000 | [diff] [blame] | 111 | const Function &F = MF.getFunction(); |
Tim Northover | c0bd197 | 2016-12-05 22:20:32 +0000 | [diff] [blame] | 112 | const DataLayout &DL = F.getParent()->getDataLayout(); |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 113 | |
| 114 | SmallVector<CCValAssign, 16> ArgLocs; |
| 115 | CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); |
| 116 | |
| 117 | unsigned NumArgs = Args.size(); |
| 118 | for (unsigned i = 0; i != NumArgs; ++i) { |
| 119 | MVT CurVT = MVT::getVT(Args[i].Ty); |
Tim Northover | d943354 | 2017-01-17 22:30:10 +0000 | [diff] [blame] | 120 | if (Handler.assignArg(i, CurVT, CurVT, CCValAssign::Full, Args[i], CCInfo)) |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 121 | return false; |
| 122 | } |
| 123 | |
Diana Picus | ca6a890 | 2017-02-16 07:53:07 +0000 | [diff] [blame] | 124 | for (unsigned i = 0, e = Args.size(), j = 0; i != e; ++i, ++j) { |
| 125 | assert(j < ArgLocs.size() && "Skipped too many arg locs"); |
| 126 | |
| 127 | CCValAssign &VA = ArgLocs[j]; |
| 128 | assert(VA.getValNo() == i && "Location doesn't correspond to current arg"); |
| 129 | |
| 130 | if (VA.needsCustom()) { |
| 131 | j += Handler.assignCustomValue(Args[i], makeArrayRef(ArgLocs).slice(j)); |
| 132 | continue; |
| 133 | } |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 134 | |
| 135 | if (VA.isRegLoc()) |
| 136 | Handler.assignValueToReg(Args[i].Reg, VA.getLocReg(), VA); |
| 137 | else if (VA.isMemLoc()) { |
Tim Northover | c0bd197 | 2016-12-05 22:20:32 +0000 | [diff] [blame] | 138 | unsigned Size = VA.getValVT() == MVT::iPTR |
| 139 | ? DL.getPointerSize() |
Tim Northover | 14ceb45 | 2016-12-06 21:02:19 +0000 | [diff] [blame] | 140 | : alignTo(VA.getValVT().getSizeInBits(), 8) / 8; |
Diana Picus | f11f042 | 2016-12-05 10:40:33 +0000 | [diff] [blame] | 141 | unsigned Offset = VA.getLocMemOffset(); |
| 142 | MachinePointerInfo MPO; |
| 143 | unsigned StackAddr = Handler.getStackAddress(Size, Offset, MPO); |
| 144 | Handler.assignValueToAddress(Args[i].Reg, StackAddr, Size, MPO, VA); |
| 145 | } else { |
| 146 | // FIXME: Support byvals and other weirdness |
| 147 | return false; |
| 148 | } |
| 149 | } |
| 150 | return true; |
| 151 | } |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 152 | |
| 153 | unsigned CallLowering::ValueHandler::extendRegister(unsigned ValReg, |
| 154 | CCValAssign &VA) { |
| 155 | LLT LocTy{VA.getLocVT()}; |
| 156 | switch (VA.getLocInfo()) { |
| 157 | default: break; |
| 158 | case CCValAssign::Full: |
| 159 | case CCValAssign::BCvt: |
| 160 | // FIXME: bitconverting between vector types may or may not be a |
| 161 | // nop in big-endian situations. |
| 162 | return ValReg; |
Aditya Nandakumar | c3bfc81 | 2017-10-09 20:07:43 +0000 | [diff] [blame] | 163 | case CCValAssign::AExt: { |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 164 | assert(!VA.getLocVT().isVector() && "unexpected vector extend"); |
Aditya Nandakumar | c3bfc81 | 2017-10-09 20:07:43 +0000 | [diff] [blame] | 165 | auto MIB = MIRBuilder.buildAnyExt(LocTy, ValReg); |
| 166 | return MIB->getOperand(0).getReg(); |
| 167 | } |
Diana Picus | 2d9adbf | 2016-12-13 10:46:12 +0000 | [diff] [blame] | 168 | case CCValAssign::SExt: { |
| 169 | unsigned NewReg = MRI.createGenericVirtualRegister(LocTy); |
| 170 | MIRBuilder.buildSExt(NewReg, ValReg); |
| 171 | return NewReg; |
| 172 | } |
| 173 | case CCValAssign::ZExt: { |
| 174 | unsigned NewReg = MRI.createGenericVirtualRegister(LocTy); |
| 175 | MIRBuilder.buildZExt(NewReg, ValReg); |
| 176 | return NewReg; |
| 177 | } |
| 178 | } |
| 179 | llvm_unreachable("unable to extend register"); |
| 180 | } |