1 | //===-- PPCCallLowering.h - Call lowering for GlobalISel -------*- C++ -*-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | /// |
9 | /// \file |
10 | /// This file implements the lowering of LLVM calls to machine code calls for |
11 | /// GlobalISel. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "PPCCallLowering.h" |
16 | #include "PPCCallingConv.h" |
17 | #include "PPCISelLowering.h" |
18 | #include "llvm/CodeGen/CallingConvLower.h" |
19 | #include "llvm/CodeGen/GlobalISel/CallLowering.h" |
20 | #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" |
21 | #include "llvm/CodeGen/MachineFrameInfo.h" |
22 | #include "llvm/CodeGen/TargetCallingConv.h" |
23 | |
24 | #define DEBUG_TYPE "ppc-call-lowering" |
25 | |
26 | using namespace llvm; |
27 | |
28 | namespace { |
29 | |
30 | struct OutgoingArgHandler : public CallLowering::OutgoingValueHandler { |
31 | OutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, |
32 | MachineInstrBuilder MIB) |
33 | : OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB) {} |
34 | |
35 | void assignValueToReg(Register ValVReg, Register PhysReg, |
36 | const CCValAssign &VA) override; |
37 | void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy, |
38 | const MachinePointerInfo &MPO, |
39 | const CCValAssign &VA) override; |
40 | Register getStackAddress(uint64_t Size, int64_t Offset, |
41 | MachinePointerInfo &MPO, |
42 | ISD::ArgFlagsTy Flags) override; |
43 | |
44 | MachineInstrBuilder MIB; |
45 | }; |
46 | } // namespace |
47 | |
48 | void OutgoingArgHandler::assignValueToReg(Register ValVReg, Register PhysReg, |
49 | const CCValAssign &VA) { |
50 | MIB.addUse(RegNo: PhysReg, Flags: RegState::Implicit); |
51 | Register ExtReg = extendRegister(ValReg: ValVReg, VA); |
52 | MIRBuilder.buildCopy(Res: PhysReg, Op: ExtReg); |
53 | } |
54 | |
55 | void OutgoingArgHandler::assignValueToAddress(Register ValVReg, Register Addr, |
56 | LLT MemTy, |
57 | const MachinePointerInfo &MPO, |
58 | const CCValAssign &VA) { |
59 | llvm_unreachable("unimplemented" ); |
60 | } |
61 | |
62 | Register OutgoingArgHandler::getStackAddress(uint64_t Size, int64_t Offset, |
63 | MachinePointerInfo &MPO, |
64 | ISD::ArgFlagsTy Flags) { |
65 | llvm_unreachable("unimplemented" ); |
66 | } |
67 | |
68 | PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI) |
69 | : CallLowering(&TLI) {} |
70 | |
71 | bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, |
72 | const Value *Val, ArrayRef<Register> VRegs, |
73 | FunctionLoweringInfo &FLI, |
74 | Register SwiftErrorVReg) const { |
75 | auto MIB = MIRBuilder.buildInstrNoInsert(Opcode: PPC::BLR8); |
76 | bool Success = true; |
77 | MachineFunction &MF = MIRBuilder.getMF(); |
78 | const Function &F = MF.getFunction(); |
79 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
80 | auto &DL = F.getDataLayout(); |
81 | if (!VRegs.empty()) { |
82 | // Setup the information about the return value. |
83 | ArgInfo OrigArg{VRegs, Val->getType(), 0}; |
84 | setArgFlags(Arg&: OrigArg, OpIdx: AttributeList::ReturnIndex, DL, FuncInfo: F); |
85 | |
86 | // Split the return value into consecutive registers if needed. |
87 | SmallVector<ArgInfo, 8> SplitArgs; |
88 | splitToValueTypes(OrigArgInfo: OrigArg, SplitArgs, DL, CallConv: F.getCallingConv()); |
89 | |
90 | // Use the calling convention callback to determine type and location of |
91 | // return value. |
92 | OutgoingValueAssigner ArgAssigner(RetCC_PPC); |
93 | |
94 | // Handler to move the return value into the correct location. |
95 | OutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB); |
96 | |
97 | // Iterate over all return values, and move them to the assigned location. |
98 | Success = determineAndHandleAssignments(Handler&: ArgHandler, Assigner&: ArgAssigner, Args&: SplitArgs, |
99 | MIRBuilder, CallConv: F.getCallingConv(), |
100 | IsVarArg: F.isVarArg()); |
101 | } |
102 | MIRBuilder.insertInstr(MIB); |
103 | return Success; |
104 | } |
105 | |
106 | bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, |
107 | CallLoweringInfo &Info) const { |
108 | return false; |
109 | } |
110 | |
111 | bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, |
112 | const Function &F, |
113 | ArrayRef<ArrayRef<Register>> VRegs, |
114 | FunctionLoweringInfo &FLI) const { |
115 | MachineFunction &MF = MIRBuilder.getMF(); |
116 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
117 | const auto &DL = F.getDataLayout(); |
118 | auto &TLI = *getTLI<PPCTargetLowering>(); |
119 | |
120 | // Loop over each arg, set flags and split to single value types |
121 | SmallVector<ArgInfo, 8> SplitArgs; |
122 | unsigned I = 0; |
123 | for (const auto &Arg : F.args()) { |
124 | if (DL.getTypeStoreSize(Ty: Arg.getType()).isZero()) |
125 | continue; |
126 | |
127 | ArgInfo OrigArg{VRegs[I], Arg, I}; |
128 | setArgFlags(Arg&: OrigArg, OpIdx: I + AttributeList::FirstArgIndex, DL, FuncInfo: F); |
129 | splitToValueTypes(OrigArgInfo: OrigArg, SplitArgs, DL, CallConv: F.getCallingConv()); |
130 | ++I; |
131 | } |
132 | |
133 | CCAssignFn *AssignFn = |
134 | TLI.ccAssignFnForCall(CC: F.getCallingConv(), Return: false, IsVarArg: F.isVarArg()); |
135 | IncomingValueAssigner ArgAssigner(AssignFn); |
136 | FormalArgHandler ArgHandler(MIRBuilder, MRI); |
137 | return determineAndHandleAssignments(Handler&: ArgHandler, Assigner&: ArgAssigner, Args&: SplitArgs, |
138 | MIRBuilder, CallConv: F.getCallingConv(), |
139 | IsVarArg: F.isVarArg()); |
140 | } |
141 | |
142 | void PPCIncomingValueHandler::assignValueToReg(Register ValVReg, |
143 | Register PhysReg, |
144 | const CCValAssign &VA) { |
145 | markPhysRegUsed(PhysReg); |
146 | IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); |
147 | } |
148 | |
149 | void PPCIncomingValueHandler::assignValueToAddress( |
150 | Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO, |
151 | const CCValAssign &VA) { |
152 | // define a lambda expression to load value |
153 | auto BuildLoad = [](MachineIRBuilder &MIRBuilder, |
154 | const MachinePointerInfo &MPO, LLT MemTy, |
155 | const DstOp &Res, Register Addr) { |
156 | MachineFunction &MF = MIRBuilder.getMF(); |
157 | auto *MMO = MF.getMachineMemOperand(PtrInfo: MPO, f: MachineMemOperand::MOLoad, MemTy, |
158 | base_alignment: inferAlignFromPtrInfo(MF, MPO)); |
159 | return MIRBuilder.buildLoad(Res, Addr, MMO&: *MMO); |
160 | }; |
161 | |
162 | BuildLoad(MIRBuilder, MPO, MemTy, ValVReg, Addr); |
163 | } |
164 | |
165 | Register PPCIncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, |
166 | MachinePointerInfo &MPO, |
167 | ISD::ArgFlagsTy Flags) { |
168 | auto &MFI = MIRBuilder.getMF().getFrameInfo(); |
169 | const bool IsImmutable = !Flags.isByVal(); |
170 | int FI = MFI.CreateFixedObject(Size, SPOffset: Offset, IsImmutable); |
171 | MPO = MachinePointerInfo::getFixedStack(MF&: MIRBuilder.getMF(), FI); |
172 | |
173 | // Build Frame Index based on whether the machine is 32-bit or 64-bit |
174 | llvm::LLT FramePtr = LLT::pointer( |
175 | AddressSpace: 0, SizeInBits: MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); |
176 | MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(Res: FramePtr, Idx: FI); |
177 | StackUsed = std::max(a: StackUsed, b: Size + Offset); |
178 | return AddrReg.getReg(Idx: 0); |
179 | } |
180 | |
181 | void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) { |
182 | MIRBuilder.getMRI()->addLiveIn(Reg: PhysReg); |
183 | MIRBuilder.getMBB().addLiveIn(PhysReg); |
184 | } |
185 | |