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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H 10 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZCALLINGCONV_H 11 12 #include "llvm/ADT/SmallVector.h" 13 #include "llvm/CodeGen/CallingConvLower.h" 14 #include "llvm/MC/MCRegisterInfo.h" 15 16 namespace llvm { 17 namespace SystemZ { 18 const unsigned NumArgGPRs = 5; 19 extern const MCPhysReg ArgGPRs[NumArgGPRs]; 20 21 const unsigned NumArgFPRs = 4; 22 extern const MCPhysReg ArgFPRs[NumArgFPRs]; 23 } // end namespace SystemZ 24 25 class SystemZCCState : public CCState { 26 private: 27 /// Records whether the value was a fixed argument. 28 /// See ISD::OutputArg::IsFixed. 29 SmallVector<bool, 4> ArgIsFixed; 30 31 /// Records whether the value was widened from a short vector type. 32 SmallVector<bool, 4> ArgIsShortVector; 33 34 // Check whether ArgVT is a short vector type. 35 bool IsShortVectorType(EVT ArgVT) { 36 return ArgVT.isVector() && ArgVT.getStoreSize() <= 8; 37 } 38 39 public: 40 SystemZCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, 41 SmallVectorImpl<CCValAssign> &locs, LLVMContext &C) 42 : CCState(CC, isVarArg, MF, locs, C) {} 43 44 void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, 45 CCAssignFn Fn) { 46 // Formal arguments are always fixed. 47 ArgIsFixed.clear(); 48 for (unsigned i = 0; i < Ins.size(); ++i) 49 ArgIsFixed.push_back(true); 50 // Record whether the call operand was a short vector. 51 ArgIsShortVector.clear(); 52 for (unsigned i = 0; i < Ins.size(); ++i) 53 ArgIsShortVector.push_back(IsShortVectorType(Ins[i].ArgVT)); 54 55 CCState::AnalyzeFormalArguments(Ins, Fn); 56 } 57 58 void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, 59 CCAssignFn Fn) { 60 // Record whether the call operand was a fixed argument. 61 ArgIsFixed.clear(); 62 for (unsigned i = 0; i < Outs.size(); ++i) 63 ArgIsFixed.push_back(Outs[i].IsFixed); 64 // Record whether the call operand was a short vector. 65 ArgIsShortVector.clear(); 66 for (unsigned i = 0; i < Outs.size(); ++i) 67 ArgIsShortVector.push_back(IsShortVectorType(Outs[i].ArgVT)); 68 69 CCState::AnalyzeCallOperands(Outs, Fn); 70 } 71 72 // This version of AnalyzeCallOperands in the base class is not usable 73 // since we must provide a means of accessing ISD::OutputArg::IsFixed. 74 void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs, 75 SmallVectorImpl<ISD::ArgFlagsTy> &Flags, 76 CCAssignFn Fn) = delete; 77 78 bool IsFixed(unsigned ValNo) { return ArgIsFixed[ValNo]; } 79 bool IsShortVector(unsigned ValNo) { return ArgIsShortVector[ValNo]; } 80 }; 81 82 // Handle i128 argument types. These need to be passed by implicit 83 // reference. This could be as simple as the following .td line: 84 // CCIfType<[i128], CCPassIndirect<i64>>, 85 // except that i128 is not a legal type, and therefore gets split by 86 // common code into a pair of i64 arguments. 87 inline bool CC_SystemZ_I128Indirect(unsigned &ValNo, MVT &ValVT, 88 MVT &LocVT, 89 CCValAssign::LocInfo &LocInfo, 90 ISD::ArgFlagsTy &ArgFlags, 91 CCState &State) { 92 SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs(); 93 94 // ArgFlags.isSplit() is true on the first part of a i128 argument; 95 // PendingMembers.empty() is false on all subsequent parts. 96 if (!ArgFlags.isSplit() && PendingMembers.empty()) 97 return false; 98 99 // Push a pending Indirect value location for each part. 100 LocVT = MVT::i64; 101 LocInfo = CCValAssign::Indirect; 102 PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, 103 LocVT, LocInfo)); 104 if (!ArgFlags.isSplitEnd()) 105 return true; 106 107 // OK, we've collected all parts in the pending list. Allocate 108 // the location (register or stack slot) for the indirect pointer. 109 // (This duplicates the usual i64 calling convention rules.) 110 unsigned Reg = State.AllocateReg(SystemZ::ArgGPRs); 111 unsigned Offset = Reg ? 0 : State.AllocateStack(8, Align(8)); 112 113 // Use that same location for all the pending parts. 114 for (auto &It : PendingMembers) { 115 if (Reg) 116 It.convertToReg(Reg); 117 else 118 It.convertToMem(Offset); 119 State.addLoc(It); 120 } 121 122 PendingMembers.clear(); 123 124 return true; 125 } 126 127 inline bool CC_SystemZ_GHC_Error(unsigned &, MVT &, MVT &, 128 CCValAssign::LocInfo &, ISD::ArgFlagsTy &, 129 CCState &) { 130 report_fatal_error("No registers left in GHC calling convention"); 131 return false; 132 } 133 134 } // end namespace llvm 135 136 #endif 137