brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · 332b5e0 Raw
197 lines · cpp
1//===-- PPCCallingConv.cpp - ------------------------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#include "PPCCallingConv.h"10#include "PPCSubtarget.h"11using namespace llvm;12 13inline bool CC_PPC_AnyReg_Error(unsigned &, MVT &, MVT &,14                                CCValAssign::LocInfo &, ISD::ArgFlagsTy &,15                                CCState &) {16  llvm_unreachable("The AnyReg calling convention is only supported by the " \17                   "stackmap and patchpoint intrinsics.");18  // gracefully fallback to PPC C calling convention on Release builds.19  return false;20}21 22// This function handles the shadowing of GPRs for fp and vector types,23// and is a depiction of the algorithm described in the ELFv2 ABI,24// Section 2.2.4.1: Parameter Passing Register Selection Algorithm.25inline bool CC_PPC64_ELF_Shadow_GPR_Regs(unsigned &ValNo, MVT &ValVT,26                                         MVT &LocVT,27                                         CCValAssign::LocInfo &LocInfo,28                                         ISD::ArgFlagsTy &ArgFlags,29                                         CCState &State) {30 31  // The 64-bit ELFv2 ABI-defined parameter passing general purpose registers.32  static const MCPhysReg ELF64ArgGPRs[] = {PPC::X3, PPC::X4, PPC::X5, PPC::X6,33                                           PPC::X7, PPC::X8, PPC::X9, PPC::X10};34  const unsigned ELF64NumArgGPRs = std::size(ELF64ArgGPRs);35 36  unsigned FirstUnallocGPR = State.getFirstUnallocated(ELF64ArgGPRs);37  if (FirstUnallocGPR == ELF64NumArgGPRs)38    return false;39 40  // As described in 2.2.4.1 under the "float" section, shadow a single GPR41  // for single/double precision. ppcf128 gets broken up into two doubles42  // and will also shadow GPRs within this section.43  if (LocVT == MVT::f32 || LocVT == MVT::f64)44    State.AllocateReg(ELF64ArgGPRs);45  else if (LocVT.is128BitVector() || (LocVT == MVT::f128)) {46    // For vector and __float128 (which is represents the "vector" section47    // in 2.2.4.1), shadow two even GPRs (skipping the odd one if it is next48    // in the allocation order). To check if the GPR is even, the specific49    // condition checks if the register allocated is odd, because the even50    // physical registers are odd values.51    if ((State.AllocateReg(ELF64ArgGPRs) - PPC::X3) % 2 == 1)52      State.AllocateReg(ELF64ArgGPRs);53    State.AllocateReg(ELF64ArgGPRs);54  }55  return false;56}57 58static bool CC_PPC32_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT,59                                       CCValAssign::LocInfo &LocInfo,60                                       ISD::ArgFlagsTy &ArgFlags,61                                       CCState &State) {62  return true;63}64 65static bool CC_PPC32_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT,66                                              MVT &LocVT,67                                              CCValAssign::LocInfo &LocInfo,68                                              ISD::ArgFlagsTy &ArgFlags,69                                              CCState &State) {70  static const MCPhysReg ArgRegs[] = {71    PPC::R3, PPC::R4, PPC::R5, PPC::R6,72    PPC::R7, PPC::R8, PPC::R9, PPC::R10,73  };74  const unsigned NumArgRegs = std::size(ArgRegs);75 76  unsigned RegNum = State.getFirstUnallocated(ArgRegs);77 78  // Skip one register if the first unallocated register has an even register79  // number and there are still argument registers available which have not been80  // allocated yet. RegNum is actually an index into ArgRegs, which means we81  // need to skip a register if RegNum is odd.82  if (RegNum != NumArgRegs && RegNum % 2 == 1) {83    State.AllocateReg(ArgRegs[RegNum]);84  }85 86  // Always return false here, as this function only makes sure that the first87  // unallocated register has an odd register number and does not actually88  // allocate a register for the current argument.89  return false;90}91 92static bool CC_PPC32_SVR4_Custom_SkipLastArgRegsPPCF128(93    unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo,94    ISD::ArgFlagsTy &ArgFlags, CCState &State) {95  static const MCPhysReg ArgRegs[] = {96    PPC::R3, PPC::R4, PPC::R5, PPC::R6,97    PPC::R7, PPC::R8, PPC::R9, PPC::R10,98  };99  const unsigned NumArgRegs = std::size(ArgRegs);100 101  unsigned RegNum = State.getFirstUnallocated(ArgRegs);102  int RegsLeft = NumArgRegs - RegNum;103 104  // Skip if there is not enough registers left for long double type (4 gpr regs105  // in soft float mode) and put long double argument on the stack.106  if (RegNum != NumArgRegs && RegsLeft < 4) {107    for (int i = 0; i < RegsLeft; i++) {108      State.AllocateReg(ArgRegs[RegNum + i]);109    }110  }111 112  return false;113}114 115static bool CC_PPC32_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT,116                                                MVT &LocVT,117                                                CCValAssign::LocInfo &LocInfo,118                                                ISD::ArgFlagsTy &ArgFlags,119                                                CCState &State) {120  static const MCPhysReg ArgRegs[] = {121    PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,122    PPC::F8123  };124 125  const unsigned NumArgRegs = std::size(ArgRegs);126 127  unsigned RegNum = State.getFirstUnallocated(ArgRegs);128 129  // If there is only one Floating-point register left we need to put both f64130  // values of a split ppc_fp128 value on the stack.131  if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) {132    State.AllocateReg(ArgRegs[RegNum]);133  }134 135  // Always return false here, as this function only makes sure that the two f64136  // values a ppc_fp128 value is split into are both passed in registers or both137  // passed on the stack and does not actually allocate a register for the138  // current argument.139  return false;140}141 142// Split F64 arguments into two 32-bit consecutive registers.143static bool CC_PPC32_SPE_CustomSplitFP64(unsigned &ValNo, MVT &ValVT,144                                        MVT &LocVT,145                                        CCValAssign::LocInfo &LocInfo,146                                        ISD::ArgFlagsTy &ArgFlags,147                                        CCState &State) {148  static const MCPhysReg HiRegList[] = { PPC::R3, PPC::R5, PPC::R7, PPC::R9 };149  static const MCPhysReg LoRegList[] = { PPC::R4, PPC::R6, PPC::R8, PPC::R10 };150 151  // Try to get the first register.152  MCRegister Reg = State.AllocateReg(HiRegList);153  if (!Reg)154    return false;155 156  unsigned i;157  for (i = 0; i < std::size(HiRegList); ++i)158    if (HiRegList[i] == Reg)159      break;160 161  MCRegister T = State.AllocateReg(LoRegList[i]);162  (void)T;163  assert(T == LoRegList[i] && "Could not allocate register");164 165  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));166  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],167                                         LocVT, LocInfo));168  return true;169}170 171// Same as above, but for return values, so only allocate for R3 and R4172static bool CC_PPC32_SPE_RetF64(unsigned &ValNo, MVT &ValVT,173                               MVT &LocVT,174                               CCValAssign::LocInfo &LocInfo,175                               ISD::ArgFlagsTy &ArgFlags,176                               CCState &State) {177  static const MCPhysReg HiRegList[] = { PPC::R3 };178  static const MCPhysReg LoRegList[] = { PPC::R4 };179 180  // Try to get the first register.181  MCRegister Reg = State.AllocateReg(HiRegList, LoRegList);182  if (!Reg)183    return false;184 185  unsigned i;186  for (i = 0; i < std::size(HiRegList); ++i)187    if (HiRegList[i] == Reg)188      break;189 190  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));191  State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],192                                         LocVT, LocInfo));193  return true;194}195 196#include "PPCGenCallingConv.inc"197