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