brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · f5ffbf5 Raw
180 lines · c
1//===-- SystemZCallingConv.h - Calling conventions for SystemZ --*- 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#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H10#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H11 12#include "SystemZSubtarget.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/CodeGen/CallingConvLower.h"15#include "llvm/MC/MCRegisterInfo.h"16 17namespace llvm {18namespace SystemZ {19  const unsigned ELFNumArgGPRs = 5;20  extern const MCPhysReg ELFArgGPRs[ELFNumArgGPRs];21 22  const unsigned ELFNumArgFPRs = 4;23  extern const MCPhysReg ELFArgFPRs[ELFNumArgFPRs];24 25  const unsigned XPLINK64NumArgGPRs = 3;26  extern const MCPhysReg XPLINK64ArgGPRs[XPLINK64NumArgGPRs];27 28  const unsigned XPLINK64NumArgFPRs = 4;29  extern const MCPhysReg XPLINK64ArgFPRs[XPLINK64NumArgFPRs];30} // end namespace SystemZ31 32// Handle i128 argument types.  These need to be passed by implicit33// reference.  This could be as simple as the following .td line:34//    CCIfType<[i128], CCPassIndirect<i64>>,35// except that i128 is not a legal type, and therefore gets split by36// common code into a pair of i64 arguments.37inline bool CC_SystemZ_I128Indirect(unsigned &ValNo, MVT &ValVT,38                                    MVT &LocVT,39                                    CCValAssign::LocInfo &LocInfo,40                                    ISD::ArgFlagsTy &ArgFlags,41                                    CCState &State) {42  SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();43 44  // ArgFlags.isSplit() is true on the first part of a i128 argument;45  // PendingMembers.empty() is false on all subsequent parts.46  if (!ArgFlags.isSplit() && PendingMembers.empty())47    return false;48 49  // Push a pending Indirect value location for each part.50  LocVT = MVT::i64;51  LocInfo = CCValAssign::Indirect;52  PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT,53                                                   LocVT, LocInfo));54  if (!ArgFlags.isSplitEnd())55    return true;56 57  // OK, we've collected all parts in the pending list.  Allocate58  // the location (register or stack slot) for the indirect pointer.59  // (This duplicates the usual i64 calling convention rules.)60  unsigned Reg;61  const SystemZSubtarget &Subtarget =62      State.getMachineFunction().getSubtarget<SystemZSubtarget>();63  if (Subtarget.isTargetELF())64    Reg = State.AllocateReg(SystemZ::ELFArgGPRs);65  else if (Subtarget.isTargetXPLINK64())66    Reg = State.AllocateReg(SystemZ::XPLINK64ArgGPRs);67  else68    llvm_unreachable("Unknown Calling Convention!");69 70  unsigned Offset = Reg && !Subtarget.isTargetXPLINK64()71                        ? 072                        : State.AllocateStack(8, Align(8));73 74  // Use that same location for all the pending parts.75  for (auto &It : PendingMembers) {76    if (Reg)77      It.convertToReg(Reg);78    else79      It.convertToMem(Offset);80    State.addLoc(It);81  }82 83  PendingMembers.clear();84 85  return true;86}87 88// A pointer in 64bit mode is always passed as 64bit.89inline bool CC_XPLINK64_Pointer(unsigned &ValNo, MVT &ValVT, MVT &LocVT,90                                CCValAssign::LocInfo &LocInfo,91                                ISD::ArgFlagsTy &ArgFlags, CCState &State) {92  if (LocVT != MVT::i64) {93    LocVT = MVT::i64;94    LocInfo = CCValAssign::ZExt;95  }96  return false;97}98 99inline bool CC_XPLINK64_Shadow_Reg(unsigned &ValNo, MVT &ValVT, MVT &LocVT,100                                   CCValAssign::LocInfo &LocInfo,101                                   ISD::ArgFlagsTy &ArgFlags, CCState &State) {102  if (LocVT == MVT::f32 || LocVT == MVT::f64) {103    State.AllocateReg(SystemZ::XPLINK64ArgGPRs);104  }105  if (LocVT == MVT::f128 || LocVT.is128BitVector()) {106    // Shadow next two GPRs, if available.107    State.AllocateReg(SystemZ::XPLINK64ArgGPRs);108    State.AllocateReg(SystemZ::XPLINK64ArgGPRs);109 110    // Quad precision floating point needs to111    // go inside pre-defined FPR pair.112    if (LocVT == MVT::f128) {113      for (unsigned I = 0; I < SystemZ::XPLINK64NumArgFPRs; I += 2)114        if (State.isAllocated(SystemZ::XPLINK64ArgFPRs[I]))115          State.AllocateReg(SystemZ::XPLINK64ArgFPRs[I + 1]);116    }117  }118  return false;119}120 121inline bool CC_XPLINK64_Allocate128BitVararg(unsigned &ValNo, MVT &ValVT,122                                             MVT &LocVT,123                                             CCValAssign::LocInfo &LocInfo,124                                             ISD::ArgFlagsTy &ArgFlags,125                                             CCState &State) {126  // For any C or C++ program, this should always be127  // false, since it is illegal to have a function128  // where the first argument is variadic. Therefore129  // the first fixed argument should already have130  // allocated GPR1 either through shadowing it or131  // using it for parameter passing.132  State.AllocateReg(SystemZ::R1D);133 134  bool AllocGPR2 = State.AllocateReg(SystemZ::R2D);135  bool AllocGPR3 = State.AllocateReg(SystemZ::R3D);136 137  // If GPR2 and GPR3 are available, then we may pass vararg in R2Q.138  // If only GPR3 is available, we need to set custom handling to copy139  // hi bits into GPR3.140  // Either way, we allocate on the stack.141  if (AllocGPR3) {142    // For f128 and vector var arg case, set the bitcast flag to bitcast to143    // i128.144    LocVT = MVT::i128;145    LocInfo = CCValAssign::BCvt;146    auto Offset = State.AllocateStack(16, Align(8));147    if (AllocGPR2)148      State.addLoc(149          CCValAssign::getReg(ValNo, ValVT, SystemZ::R2Q, LocVT, LocInfo));150    else151      State.addLoc(152          CCValAssign::getCustomMem(ValNo, ValVT, Offset, LocVT, LocInfo));153    return true;154  }155 156  return false;157}158 159inline bool RetCC_SystemZ_Error(unsigned &, MVT &, MVT &,160                                CCValAssign::LocInfo &, ISD::ArgFlagsTy &,161                                CCState &) {162  llvm_unreachable("Return value calling convention currently unsupported.");163}164 165inline bool CC_SystemZ_Error(unsigned &, MVT &, MVT &, CCValAssign::LocInfo &,166                             ISD::ArgFlagsTy &, CCState &) {167  llvm_unreachable("Argument calling convention currently unsupported.");168}169 170inline bool CC_SystemZ_GHC_Error(unsigned &, MVT &, MVT &,171                                 CCValAssign::LocInfo &, ISD::ArgFlagsTy &,172                                 CCState &) {173  report_fatal_error("No registers left in GHC calling convention");174  return false;175}176 177} // end namespace llvm178 179#endif180