/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/SystemZ/SystemZCallingConv.h
Line | Count | Source |
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 | 15.7k | bool IsShortVectorType(EVT ArgVT) { |
37 | 5.72k | return ArgVT.isVector() && ArgVT.getStoreSize() <= 8; |
38 | 15.7k | } |
39 | | |
40 | | public: |
41 | | SystemZCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, |
42 | | SmallVectorImpl<CCValAssign> &locs, LLVMContext &C) |
43 | 7.03k | : CCState(CC, isVarArg, MF, locs, C) {} |
44 | | |
45 | | void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, |
46 | 6.58k | CCAssignFn Fn) { |
47 | 6.58k | // Formal arguments are always fixed. |
48 | 6.58k | ArgIsFixed.clear(); |
49 | 21.4k | for (unsigned i = 0; i < Ins.size()21.4k ; ++i14.8k ) |
50 | 14.8k | ArgIsFixed.push_back(true); |
51 | 6.58k | // Record whether the call operand was a short vector. |
52 | 6.58k | ArgIsShortVector.clear(); |
53 | 21.4k | for (unsigned i = 0; i < Ins.size()21.4k ; ++i14.8k ) |
54 | 14.8k | ArgIsShortVector.push_back(IsShortVectorType(Ins[i].ArgVT)); |
55 | 6.58k | |
56 | 6.58k | CCState::AnalyzeFormalArguments(Ins, Fn); |
57 | 6.58k | } |
58 | | |
59 | | void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, |
60 | 452 | CCAssignFn Fn) { |
61 | 452 | // Record whether the call operand was a fixed argument. |
62 | 452 | ArgIsFixed.clear(); |
63 | 1.32k | for (unsigned i = 0; i < Outs.size()1.32k ; ++i868 ) |
64 | 868 | ArgIsFixed.push_back(Outs[i].IsFixed); |
65 | 452 | // Record whether the call operand was a short vector. |
66 | 452 | ArgIsShortVector.clear(); |
67 | 1.32k | for (unsigned i = 0; i < Outs.size()1.32k ; ++i868 ) |
68 | 868 | ArgIsShortVector.push_back(IsShortVectorType(Outs[i].ArgVT)); |
69 | 452 | |
70 | 452 | CCState::AnalyzeCallOperands(Outs, Fn); |
71 | 452 | } |
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 | 5.72k | bool IsFixed(unsigned ValNo) { return ArgIsFixed[ValNo]; } |
80 | 1.13k | 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 | 6.15k | CCState &State) { |
93 | 6.15k | SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs(); |
94 | 6.15k | |
95 | 6.15k | // ArgFlags.isSplit() is true on the first part of a i128 argument; |
96 | 6.15k | // PendingMembers.empty() is false on all subsequent parts. |
97 | 6.15k | if (!ArgFlags.isSplit() && 6.15k PendingMembers.empty()6.12k ) |
98 | 6.09k | return false; |
99 | 6.15k | |
100 | 6.15k | // Push a pending Indirect value location for each part. |
101 | 64 | LocVT = MVT::i64; |
102 | 64 | LocInfo = CCValAssign::Indirect; |
103 | 64 | PendingMembers.push_back(CCValAssign::getPending(ValNo, ValVT, |
104 | 64 | LocVT, LocInfo)); |
105 | 64 | if (!ArgFlags.isSplitEnd()) |
106 | 32 | return true; |
107 | 64 | |
108 | 64 | // OK, we've collected all parts in the pending list. Allocate |
109 | 64 | // the location (register or stack slot) for the indirect pointer. |
110 | 64 | // (This duplicates the usual i64 calling convention rules.) |
111 | 32 | unsigned Reg = State.AllocateReg(SystemZ::ArgGPRs); |
112 | 32 | unsigned Offset = Reg ? 027 : State.AllocateStack(8, 8)5 ; |
113 | 32 | |
114 | 32 | // Use that same location for all the pending parts. |
115 | 64 | for (auto &It : PendingMembers) { |
116 | 64 | if (Reg) |
117 | 54 | It.convertToReg(Reg); |
118 | 64 | else |
119 | 10 | It.convertToMem(Offset); |
120 | 64 | State.addLoc(It); |
121 | 64 | } |
122 | 32 | |
123 | 32 | PendingMembers.clear(); |
124 | 32 | |
125 | 32 | return true; |
126 | 6.15k | } |
127 | | |
128 | | } // end namespace llvm |
129 | | |
130 | | #endif |