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 | |
| 15 | |
| 16 | #include "llvm/CodeGen/GlobalISel/CallLowering.h" |
| 17 | #include "llvm/CodeGen/MachineOperand.h" |
| 18 | #include "llvm/IR/Instructions.h" |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame^] | 19 | #include "llvm/IR/DataLayout.h" |
| 20 | #include "llvm/IR/Module.h" |
| 21 | #include "llvm/Target/TargetLowering.h" |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 22 | |
| 23 | using namespace llvm; |
| 24 | |
| 25 | bool CallLowering::lowerCall( |
| 26 | MachineIRBuilder &MIRBuilder, const CallInst &CI, unsigned ResReg, |
| 27 | ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const { |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame^] | 28 | auto &DL = CI.getParent()->getParent()->getParent()->getDataLayout(); |
| 29 | |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 30 | // First step is to marshall all the function's parameters into the correct |
| 31 | // physregs and memory locations. Gather the sequence of argument types that |
| 32 | // we'll pass to the assigner function. |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame^] | 33 | SmallVector<ArgInfo, 8> OrigArgs; |
| 34 | unsigned i = 0; |
| 35 | for (auto &Arg : CI.arg_operands()) { |
| 36 | ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}}; |
| 37 | setArgFlags(OrigArg, i + 1, DL, CI); |
| 38 | OrigArgs.push_back(OrigArg); |
| 39 | ++i; |
| 40 | } |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 41 | |
| 42 | MachineOperand Callee = MachineOperand::CreateImm(0); |
| 43 | if (Function *F = CI.getCalledFunction()) |
| 44 | Callee = MachineOperand::CreateGA(F, 0); |
| 45 | else |
| 46 | Callee = MachineOperand::CreateReg(GetCalleeReg(), false); |
| 47 | |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame^] | 48 | ArgInfo OrigRet{ResReg, CI.getType(), ISD::ArgFlagsTy{}}; |
| 49 | if (!OrigRet.Ty->isVoidTy()) |
| 50 | setArgFlags(OrigRet, AttributeSet::ReturnIndex, DL, CI); |
| 51 | |
| 52 | return lowerCall(MIRBuilder, Callee, OrigRet, OrigArgs); |
Tim Northover | fe5f89b | 2016-08-29 19:07:08 +0000 | [diff] [blame] | 53 | } |
Tim Northover | 9a46718 | 2016-09-21 12:57:45 +0000 | [diff] [blame^] | 54 | |
| 55 | template <typename FuncInfoTy> |
| 56 | void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 57 | const DataLayout &DL, |
| 58 | const FuncInfoTy &FuncInfo) const { |
| 59 | const AttributeSet &Attrs = FuncInfo.getAttributes(); |
| 60 | if (Attrs.hasAttribute(OpIdx, Attribute::ZExt)) |
| 61 | Arg.Flags.setZExt(); |
| 62 | if (Attrs.hasAttribute(OpIdx, Attribute::SExt)) |
| 63 | Arg.Flags.setSExt(); |
| 64 | if (Attrs.hasAttribute(OpIdx, Attribute::InReg)) |
| 65 | Arg.Flags.setInReg(); |
| 66 | if (Attrs.hasAttribute(OpIdx, Attribute::StructRet)) |
| 67 | Arg.Flags.setSRet(); |
| 68 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftSelf)) |
| 69 | Arg.Flags.setSwiftSelf(); |
| 70 | if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError)) |
| 71 | Arg.Flags.setSwiftError(); |
| 72 | if (Attrs.hasAttribute(OpIdx, Attribute::ByVal)) |
| 73 | Arg.Flags.setByVal(); |
| 74 | if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca)) |
| 75 | Arg.Flags.setInAlloca(); |
| 76 | |
| 77 | if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) { |
| 78 | Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType(); |
| 79 | Arg.Flags.setByValSize(DL.getTypeAllocSize(ElementTy)); |
| 80 | // For ByVal, alignment should be passed from FE. BE will guess if |
| 81 | // this info is not there but there are cases it cannot get right. |
| 82 | unsigned FrameAlign; |
| 83 | if (FuncInfo.getParamAlignment(OpIdx)) |
| 84 | FrameAlign = FuncInfo.getParamAlignment(OpIdx); |
| 85 | else |
| 86 | FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL); |
| 87 | Arg.Flags.setByValAlign(FrameAlign); |
| 88 | } |
| 89 | if (Attrs.hasAttribute(OpIdx, Attribute::Nest)) |
| 90 | Arg.Flags.setNest(); |
| 91 | Arg.Flags.setOrigAlign(DL.getABITypeAlignment(Arg.Ty)); |
| 92 | } |
| 93 | |
| 94 | template void |
| 95 | CallLowering::setArgFlags<Function>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 96 | const DataLayout &DL, |
| 97 | const Function &FuncInfo) const; |
| 98 | |
| 99 | template void |
| 100 | CallLowering::setArgFlags<CallInst>(CallLowering::ArgInfo &Arg, unsigned OpIdx, |
| 101 | const DataLayout &DL, |
| 102 | const CallInst &FuncInfo) const; |