1 | //===---- MipsCCState.h - CCState with Mips specific extensions -----------===// |
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 MIPSCCSTATE_H |
10 | #define MIPSCCSTATE_H |
11 | |
12 | #include "MipsISelLowering.h" |
13 | #include "llvm/ADT/SmallVector.h" |
14 | #include "llvm/CodeGen/CallingConvLower.h" |
15 | |
16 | namespace llvm { |
17 | class SDNode; |
18 | class MipsSubtarget; |
19 | |
20 | class MipsCCState : public CCState { |
21 | public: |
22 | enum SpecialCallingConvType { Mips16RetHelperConv, NoSpecialCallingConv }; |
23 | |
24 | /// Determine the SpecialCallingConvType for the given callee |
25 | static SpecialCallingConvType |
26 | getSpecialCallingConvForCallee(const SDNode *Callee, |
27 | const MipsSubtarget &Subtarget); |
28 | |
29 | /// This function returns true if CallSym is a long double emulation routine. |
30 | /// |
31 | /// FIXME: Changing the ABI based on the callee name is unsound. The lib func |
32 | /// address could be captured. |
33 | static bool isF128SoftLibCall(const char *CallSym); |
34 | |
35 | static bool originalTypeIsF128(const Type *Ty, const char *Func); |
36 | static bool originalEVTTypeIsVectorFloat(EVT Ty); |
37 | static bool originalTypeIsVectorFloat(const Type *Ty); |
38 | |
39 | void PreAnalyzeCallOperand(const Type *ArgTy, bool IsFixed, const char *Func); |
40 | |
41 | void PreAnalyzeFormalArgument(const Type *ArgTy, ISD::ArgFlagsTy Flags); |
42 | void PreAnalyzeReturnValue(EVT ArgVT); |
43 | |
44 | private: |
45 | /// Identify lowered values that originated from f128 arguments and record |
46 | /// this for use by RetCC_MipsN. |
47 | void PreAnalyzeCallResultForF128(const SmallVectorImpl<ISD::InputArg> &Ins, |
48 | const Type *RetTy, const char * Func); |
49 | |
50 | /// Identify lowered values that originated from f128 arguments and record |
51 | /// this for use by RetCC_MipsN. |
52 | void PreAnalyzeReturnForF128(const SmallVectorImpl<ISD::OutputArg> &Outs); |
53 | |
54 | /// Identify lowered values that originated from f128 arguments and record |
55 | /// this. |
56 | void |
57 | PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, |
58 | std::vector<TargetLowering::ArgListEntry> &FuncArgs, |
59 | const char *Func); |
60 | |
61 | /// Identify lowered values that originated from f128 arguments and record |
62 | /// this for use by RetCC_MipsN. |
63 | void |
64 | PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl<ISD::InputArg> &Ins); |
65 | |
66 | void |
67 | PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl<ISD::InputArg> &Ins, |
68 | const Type *RetTy); |
69 | |
70 | void PreAnalyzeFormalArgumentsForVectorFloat( |
71 | const SmallVectorImpl<ISD::InputArg> &Ins); |
72 | |
73 | void |
74 | PreAnalyzeReturnForVectorFloat(const SmallVectorImpl<ISD::OutputArg> &Outs); |
75 | |
76 | /// Records whether the value has been lowered from an f128. |
77 | SmallVector<bool, 4> OriginalArgWasF128; |
78 | |
79 | /// Records whether the value has been lowered from float. |
80 | SmallVector<bool, 4> OriginalArgWasFloat; |
81 | |
82 | /// Records whether the value has been lowered from a floating point vector. |
83 | SmallVector<bool, 4> OriginalArgWasFloatVector; |
84 | |
85 | /// Records whether the return value has been lowered from a floating point |
86 | /// vector. |
87 | SmallVector<bool, 4> OriginalRetWasFloatVector; |
88 | |
89 | /// Records whether the value was a fixed argument. |
90 | /// See ISD::OutputArg::IsFixed, |
91 | SmallVector<bool, 4> CallOperandIsFixed; |
92 | |
93 | // Used to handle MIPS16-specific calling convention tweaks. |
94 | // FIXME: This should probably be a fully fledged calling convention. |
95 | SpecialCallingConvType SpecialCallingConv; |
96 | |
97 | public: |
98 | MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, |
99 | SmallVectorImpl<CCValAssign> &locs, LLVMContext &C, |
100 | SpecialCallingConvType SpecialCC = NoSpecialCallingConv) |
101 | : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} |
102 | |
103 | void PreAnalyzeCallOperands( |
104 | const SmallVectorImpl<ISD::OutputArg> &Outs, CCAssignFn Fn, |
105 | std::vector<TargetLowering::ArgListEntry> &FuncArgs, const char *Func) { |
106 | OriginalArgWasF128.clear(); |
107 | OriginalArgWasFloat.clear(); |
108 | OriginalArgWasFloatVector.clear(); |
109 | CallOperandIsFixed.clear(); |
110 | PreAnalyzeCallOperands(Outs, FuncArgs, Func); |
111 | } |
112 | |
113 | void |
114 | AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, |
115 | CCAssignFn Fn, |
116 | std::vector<TargetLowering::ArgListEntry> &FuncArgs, |
117 | const char *Func) { |
118 | PreAnalyzeCallOperands(Outs, Fn, FuncArgs, Func); |
119 | CCState::AnalyzeCallOperands(Outs, Fn); |
120 | } |
121 | |
122 | // The AnalyzeCallOperands in the base class is not usable since we must |
123 | // provide a means of accessing ArgListEntry::IsFixed. Delete them from this |
124 | // class. This doesn't stop them being used via the base class though. |
125 | void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, |
126 | CCAssignFn Fn) = delete; |
127 | void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs, |
128 | SmallVectorImpl<ISD::ArgFlagsTy> &Flags, |
129 | CCAssignFn Fn) = delete; |
130 | |
131 | void PreAnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, |
132 | CCAssignFn Fn) { |
133 | OriginalArgWasFloat.clear(); |
134 | OriginalArgWasF128.clear(); |
135 | OriginalArgWasFloatVector.clear(); |
136 | PreAnalyzeFormalArgumentsForF128(Ins); |
137 | } |
138 | |
139 | void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, |
140 | CCAssignFn Fn) { |
141 | PreAnalyzeFormalArguments(Ins, Fn); |
142 | CCState::AnalyzeFormalArguments(Ins, Fn); |
143 | } |
144 | |
145 | void PreAnalyzeCallResult(const Type *RetTy, const char *Func) { |
146 | OriginalArgWasF128.push_back(Elt: originalTypeIsF128(Ty: RetTy, Func)); |
147 | OriginalArgWasFloat.push_back(Elt: RetTy->isFloatingPointTy()); |
148 | OriginalRetWasFloatVector.push_back(Elt: originalTypeIsVectorFloat(Ty: RetTy)); |
149 | } |
150 | |
151 | void PreAnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, |
152 | CCAssignFn Fn, const Type *RetTy, |
153 | const char *Func) { |
154 | OriginalArgWasFloat.clear(); |
155 | OriginalArgWasF128.clear(); |
156 | OriginalArgWasFloatVector.clear(); |
157 | PreAnalyzeCallResultForF128(Ins, RetTy, Func); |
158 | PreAnalyzeCallResultForVectorFloat(Ins, RetTy); |
159 | } |
160 | |
161 | void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, |
162 | CCAssignFn Fn, const Type *RetTy, |
163 | const char *Func) { |
164 | PreAnalyzeCallResult(Ins, Fn, RetTy, Func); |
165 | CCState::AnalyzeCallResult(Ins, Fn); |
166 | } |
167 | |
168 | void PreAnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, |
169 | CCAssignFn Fn) { |
170 | OriginalArgWasFloat.clear(); |
171 | OriginalArgWasF128.clear(); |
172 | OriginalArgWasFloatVector.clear(); |
173 | PreAnalyzeReturnForF128(Outs); |
174 | PreAnalyzeReturnForVectorFloat(Outs); |
175 | } |
176 | |
177 | void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, |
178 | CCAssignFn Fn) { |
179 | PreAnalyzeReturn(Outs, Fn); |
180 | CCState::AnalyzeReturn(Outs, Fn); |
181 | } |
182 | |
183 | bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags, |
184 | CCAssignFn Fn) { |
185 | PreAnalyzeReturnForF128(Outs: ArgsFlags); |
186 | PreAnalyzeReturnForVectorFloat(Outs: ArgsFlags); |
187 | bool Return = CCState::CheckReturn(Outs: ArgsFlags, Fn); |
188 | OriginalArgWasFloat.clear(); |
189 | OriginalArgWasF128.clear(); |
190 | OriginalArgWasFloatVector.clear(); |
191 | return Return; |
192 | } |
193 | |
194 | bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } |
195 | bool WasOriginalArgFloat(unsigned ValNo) { |
196 | return OriginalArgWasFloat[ValNo]; |
197 | } |
198 | bool WasOriginalArgVectorFloat(unsigned ValNo) const { |
199 | return OriginalArgWasFloatVector[ValNo]; |
200 | } |
201 | bool WasOriginalRetVectorFloat(unsigned ValNo) const { |
202 | return OriginalRetWasFloatVector[ValNo]; |
203 | } |
204 | bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } |
205 | SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } |
206 | }; |
207 | } |
208 | |
209 | #endif |
210 | |