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