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