Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCCallingConv.cpp
35266 views
//===-- PPCCallingConv.cpp - ------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "PPCRegisterInfo.h"9#include "PPCCallingConv.h"10#include "PPCSubtarget.h"11#include "PPCCCState.h"12using namespace llvm;1314inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &,15CCValAssign::LocInfo &, ISD::ArgFlagsTy &,16CCState &) {17llvm_unreachable("The AnyReg calling convention is only supported by the " \18"stackmap and patchpoint intrinsics.");19// gracefully fallback to PPC C calling convention on Release builds.20return false;21}2223// This function handles the shadowing of GPRs for fp and vector types,24// and is a depiction of the algorithm described in the ELFv2 ABI,25// Section 2.2.4.1: Parameter Passing Register Selection Algorithm.26inline bool CC_PPC64_ELF_Shadow_GPR_Regs(unsigned &ValNo, MVT &ValVT,27MVT &LocVT,28CCValAssign::LocInfo &LocInfo,29ISD::ArgFlagsTy &ArgFlags,30CCState &State) {3132// The 64-bit ELFv2 ABI-defined parameter passing general purpose registers.33static const MCPhysReg ELF64ArgGPRs[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,34PPC::X7, PPC::X8, PPC::X9, PPC::X10};35const unsigned ELF64NumArgGPRs = std::size(ELF64ArgGPRs);3637unsigned FirstUnallocGPR = State.getFirstUnallocated(ELF64ArgGPRs);38if (FirstUnallocGPR == ELF64NumArgGPRs)39return false;4041// As described in 2.2.4.1 under the "float" section, shadow a single GPR42// for single/double precision. ppcf128 gets broken up into two doubles43// and will also shadow GPRs within this section.44if (LocVT == MVT::f32 || LocVT == MVT::f64)45State.AllocateReg(ELF64ArgGPRs);46else if (LocVT.is128BitVector() || (LocVT == MVT::f128)) {47// For vector and __float128 (which is represents the "vector" section48// in 2.2.4.1), shadow two even GPRs (skipping the odd one if it is next49// in the allocation order). To check if the GPR is even, the specific50// condition checks if the register allocated is odd, because the even51// physical registers are odd values.52if ((State.AllocateReg(ELF64ArgGPRs) - PPC::X3) % 2 == 1)53State.AllocateReg(ELF64ArgGPRs);54State.AllocateReg(ELF64ArgGPRs);55}56return false;57}5859static bool CC_PPC32_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT,60CCValAssign::LocInfo &LocInfo,61ISD::ArgFlagsTy &ArgFlags,62CCState &State) {63return true;64}6566static bool CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT,67MVT &LocVT,68CCValAssign::LocInfo &LocInfo,69ISD::ArgFlagsTy &ArgFlags,70CCState &State) {71static const MCPhysReg ArgRegs[] = {72PPC::R3, PPC::R4, PPC::R5, PPC::R6,73PPC::R7, PPC::R8, PPC::R9, PPC::R10,74};75const unsigned NumArgRegs = std::size(ArgRegs);7677unsigned RegNum = State.getFirstUnallocated(ArgRegs);7879// Skip one register if the first unallocated register has an even register80// number and there are still argument registers available which have not been81// allocated yet. RegNum is actually an index into ArgRegs, which means we82// need to skip a register if RegNum is odd.83if (RegNum != NumArgRegs && RegNum % 2 == 1) {84State.AllocateReg(ArgRegs[RegNum]);85}8687// Always return false here, as this function only makes sure that the first88// unallocated register has an odd register number and does not actually89// allocate a register for the current argument.90return false;91}9293static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(94unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo,95ISD::ArgFlagsTy &ArgFlags, CCState &State) {96static const MCPhysReg ArgRegs[] = {97PPC::R3, PPC::R4, PPC::R5, PPC::R6,98PPC::R7, PPC::R8, PPC::R9, PPC::R10,99};100const unsigned NumArgRegs = std::size(ArgRegs);101102unsigned RegNum = State.getFirstUnallocated(ArgRegs);103int RegsLeft = NumArgRegs - RegNum;104105// Skip if there is not enough registers left for long double type (4 gpr regs106// in soft float mode) and put long double argument on the stack.107if (RegNum != NumArgRegs && RegsLeft < 4) {108for (int i = 0; i < RegsLeft; i++) {109State.AllocateReg(ArgRegs[RegNum + i]);110}111}112113return false;114}115116static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT,117MVT &LocVT,118CCValAssign::LocInfo &LocInfo,119ISD::ArgFlagsTy &ArgFlags,120CCState &State) {121static const MCPhysReg ArgRegs[] = {122PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,123PPC::F8124};125126const unsigned NumArgRegs = std::size(ArgRegs);127128unsigned RegNum = State.getFirstUnallocated(ArgRegs);129130// If there is only one Floating-point register left we need to put both f64131// values of a split ppc_fp128 value on the stack.132if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) {133State.AllocateReg(ArgRegs[RegNum]);134}135136// Always return false here, as this function only makes sure that the two f64137// values a ppc_fp128 value is split into are both passed in registers or both138// passed on the stack and does not actually allocate a register for the139// current argument.140return false;141}142143// Split F64 arguments into two 32-bit consecutive registers.144static bool CC_PPC32_SPE_CustomSplitFP64(unsigned &ValNo, MVT &ValVT,145MVT &LocVT,146CCValAssign::LocInfo &LocInfo,147ISD::ArgFlagsTy &ArgFlags,148CCState &State) {149static const MCPhysReg HiRegList[] = { PPC::R3, PPC::R5, PPC::R7, PPC::R9 };150static const MCPhysReg LoRegList[] = { PPC::R4, PPC::R6, PPC::R8, PPC::R10 };151152// Try to get the first register.153unsigned Reg = State.AllocateReg(HiRegList);154if (!Reg)155return false;156157unsigned i;158for (i = 0; i < std::size(HiRegList); ++i)159if (HiRegList[i] == Reg)160break;161162unsigned T = State.AllocateReg(LoRegList[i]);163(void)T;164assert(T == LoRegList[i] && "Could not allocate register");165166State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));167State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],168LocVT, LocInfo));169return true;170}171172// Same as above, but for return values, so only allocate for R3 and R4173static bool CC_PPC32_SPE_RetF64(unsigned &ValNo, MVT &ValVT,174MVT &LocVT,175CCValAssign::LocInfo &LocInfo,176ISD::ArgFlagsTy &ArgFlags,177CCState &State) {178static const MCPhysReg HiRegList[] = { PPC::R3 };179static const MCPhysReg LoRegList[] = { PPC::R4 };180181// Try to get the first register.182unsigned Reg = State.AllocateReg(HiRegList, LoRegList);183if (!Reg)184return false;185186unsigned i;187for (i = 0; i < std::size(HiRegList); ++i)188if (HiRegList[i] == Reg)189break;190191State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));192State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],193LocVT, LocInfo));194return true;195}196197#include "PPCGenCallingConv.inc"198199200