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" 16fe6060f1SDimitry Andric #include "PPCISelLowering.h" 17fe6060f1SDimitry Andric #include "PPCSubtarget.h" 18fe6060f1SDimitry Andric #include "PPCTargetMachine.h" 19fe6060f1SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 20fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 21e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 22*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 23fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetCallingConv.h" 24e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 25e8d8bef9SDimitry Andric 26e8d8bef9SDimitry Andric #define DEBUG_TYPE "ppc-call-lowering" 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric using namespace llvm; 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric PPCCallLowering::PPCCallLowering(const PPCTargetLowering &TLI) 31e8d8bef9SDimitry Andric : CallLowering(&TLI) {} 32e8d8bef9SDimitry Andric 33e8d8bef9SDimitry Andric bool PPCCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, 34e8d8bef9SDimitry Andric const Value *Val, ArrayRef<Register> VRegs, 35e8d8bef9SDimitry Andric FunctionLoweringInfo &FLI, 36e8d8bef9SDimitry Andric Register SwiftErrorVReg) const { 37e8d8bef9SDimitry Andric assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && 38e8d8bef9SDimitry Andric "Return value without a vreg"); 39e8d8bef9SDimitry Andric if (VRegs.size() > 0) 40e8d8bef9SDimitry Andric return false; 41e8d8bef9SDimitry Andric 42e8d8bef9SDimitry Andric MIRBuilder.buildInstr(PPC::BLR8); 43e8d8bef9SDimitry Andric return true; 44e8d8bef9SDimitry Andric } 45e8d8bef9SDimitry Andric 46fe6060f1SDimitry Andric bool PPCCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, 47fe6060f1SDimitry Andric CallLoweringInfo &Info) const { 48fe6060f1SDimitry Andric return false; 49fe6060f1SDimitry Andric } 50fe6060f1SDimitry Andric 51e8d8bef9SDimitry Andric bool PPCCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, 52e8d8bef9SDimitry Andric const Function &F, 53e8d8bef9SDimitry Andric ArrayRef<ArrayRef<Register>> VRegs, 54e8d8bef9SDimitry Andric FunctionLoweringInfo &FLI) const { 55fe6060f1SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 56fe6060f1SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 57fe6060f1SDimitry Andric const auto &DL = F.getParent()->getDataLayout(); 58fe6060f1SDimitry Andric auto &TLI = *getTLI<PPCTargetLowering>(); 59e8d8bef9SDimitry Andric 60fe6060f1SDimitry Andric // Loop over each arg, set flags and split to single value types 61fe6060f1SDimitry Andric SmallVector<ArgInfo, 8> SplitArgs; 62fe6060f1SDimitry Andric unsigned I = 0; 63fe6060f1SDimitry Andric for (const auto &Arg : F.args()) { 64fe6060f1SDimitry Andric if (DL.getTypeStoreSize(Arg.getType()).isZero()) 65fe6060f1SDimitry Andric continue; 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric ArgInfo OrigArg{VRegs[I], Arg, I}; 68fe6060f1SDimitry Andric setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F); 69fe6060f1SDimitry Andric splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv()); 70fe6060f1SDimitry Andric ++I; 71e8d8bef9SDimitry Andric } 72e8d8bef9SDimitry Andric 73fe6060f1SDimitry Andric CCAssignFn *AssignFn = 74fe6060f1SDimitry Andric TLI.ccAssignFnForCall(F.getCallingConv(), false, F.isVarArg()); 75fe6060f1SDimitry Andric IncomingValueAssigner ArgAssigner(AssignFn); 76fe6060f1SDimitry Andric FormalArgHandler ArgHandler(MIRBuilder, MRI); 77fe6060f1SDimitry Andric return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs, 78fe6060f1SDimitry Andric MIRBuilder, F.getCallingConv(), 79fe6060f1SDimitry Andric F.isVarArg()); 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric void PPCIncomingValueHandler::assignValueToReg(Register ValVReg, 83fe6060f1SDimitry Andric Register PhysReg, 84349cc55cSDimitry Andric CCValAssign VA) { 85fe6060f1SDimitry Andric markPhysRegUsed(PhysReg); 86fe6060f1SDimitry Andric IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA); 87fe6060f1SDimitry Andric } 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric void PPCIncomingValueHandler::assignValueToAddress(Register ValVReg, 90fe6060f1SDimitry Andric Register Addr, LLT MemTy, 91fe6060f1SDimitry Andric MachinePointerInfo &MPO, 92fe6060f1SDimitry Andric CCValAssign &VA) { 93fe6060f1SDimitry Andric // define a lambda expression to load value 94fe6060f1SDimitry Andric auto BuildLoad = [](MachineIRBuilder &MIRBuilder, MachinePointerInfo &MPO, 95fe6060f1SDimitry Andric LLT MemTy, const DstOp &Res, Register Addr) { 96fe6060f1SDimitry Andric MachineFunction &MF = MIRBuilder.getMF(); 97fe6060f1SDimitry Andric auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy, 98fe6060f1SDimitry Andric inferAlignFromPtrInfo(MF, MPO)); 99fe6060f1SDimitry Andric return MIRBuilder.buildLoad(Res, Addr, *MMO); 100fe6060f1SDimitry Andric }; 101fe6060f1SDimitry Andric 102fe6060f1SDimitry Andric BuildLoad(MIRBuilder, MPO, MemTy, ValVReg, Addr); 103fe6060f1SDimitry Andric } 104fe6060f1SDimitry Andric 105fe6060f1SDimitry Andric Register PPCIncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, 106fe6060f1SDimitry Andric MachinePointerInfo &MPO, 107fe6060f1SDimitry Andric ISD::ArgFlagsTy Flags) { 108fe6060f1SDimitry Andric auto &MFI = MIRBuilder.getMF().getFrameInfo(); 109fe6060f1SDimitry Andric const bool IsImmutable = !Flags.isByVal(); 110fe6060f1SDimitry Andric int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable); 111fe6060f1SDimitry Andric MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric // Build Frame Index based on whether the machine is 32-bit or 64-bit 114fe6060f1SDimitry Andric llvm::LLT FramePtr = LLT::pointer( 115fe6060f1SDimitry Andric 0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits()); 116fe6060f1SDimitry Andric MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI); 117fe6060f1SDimitry Andric StackUsed = std::max(StackUsed, Size + Offset); 118fe6060f1SDimitry Andric return AddrReg.getReg(0); 119fe6060f1SDimitry Andric } 120fe6060f1SDimitry Andric 121fe6060f1SDimitry Andric void FormalArgHandler::markPhysRegUsed(unsigned PhysReg) { 122fe6060f1SDimitry Andric MIRBuilder.getMRI()->addLiveIn(PhysReg); 123fe6060f1SDimitry Andric MIRBuilder.getMBB().addLiveIn(PhysReg); 124e8d8bef9SDimitry Andric } 125