10b57cec5SDimitry Andric //===---- MipsCCState.h - CCState with Mips specific extensions -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef MIPSCCSTATE_H
100b57cec5SDimitry Andric #define MIPSCCSTATE_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "MipsISelLowering.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric class SDNode;
180b57cec5SDimitry Andric class MipsSubtarget;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric class MipsCCState : public CCState {
210b57cec5SDimitry Andric public:
220b57cec5SDimitry Andric   enum SpecialCallingConvType { Mips16RetHelperConv, NoSpecialCallingConv };
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric   /// Determine the SpecialCallingConvType for the given callee
250b57cec5SDimitry Andric   static SpecialCallingConvType
260b57cec5SDimitry Andric   getSpecialCallingConvForCallee(const SDNode *Callee,
270b57cec5SDimitry Andric                                  const MipsSubtarget &Subtarget);
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   /// This function returns true if CallSym is a long double emulation routine.
300b57cec5SDimitry Andric   ///
310b57cec5SDimitry Andric   /// FIXME: Changing the ABI based on the callee name is unsound. The lib func
320b57cec5SDimitry Andric   /// address could be captured.
330b57cec5SDimitry Andric   static bool isF128SoftLibCall(const char *CallSym);
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric   static bool originalTypeIsF128(const Type *Ty, const char *Func);
360b57cec5SDimitry Andric   static bool originalEVTTypeIsVectorFloat(EVT Ty);
370b57cec5SDimitry Andric   static bool originalTypeIsVectorFloat(const Type *Ty);
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   void PreAnalyzeCallOperand(const Type *ArgTy, bool IsFixed, const char *Func);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   void PreAnalyzeFormalArgument(const Type *ArgTy, ISD::ArgFlagsTy Flags);
420b57cec5SDimitry Andric   void PreAnalyzeReturnValue(EVT ArgVT);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric private:
450b57cec5SDimitry Andric   /// Identify lowered values that originated from f128 arguments and record
460b57cec5SDimitry Andric   /// this for use by RetCC_MipsN.
470b57cec5SDimitry Andric   void PreAnalyzeCallResultForF128(const SmallVectorImpl<ISD::InputArg> &Ins,
480b57cec5SDimitry Andric                                    const Type *RetTy, const char * Func);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// Identify lowered values that originated from f128 arguments and record
510b57cec5SDimitry Andric   /// this for use by RetCC_MipsN.
520b57cec5SDimitry Andric   void PreAnalyzeReturnForF128(const SmallVectorImpl<ISD::OutputArg> &Outs);
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   /// Identify lowered values that originated from f128 arguments and record
550b57cec5SDimitry Andric   /// this.
560b57cec5SDimitry Andric   void
570b57cec5SDimitry Andric   PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
580b57cec5SDimitry Andric                          std::vector<TargetLowering::ArgListEntry> &FuncArgs,
590b57cec5SDimitry Andric                          const char *Func);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   /// Identify lowered values that originated from f128 arguments and record
620b57cec5SDimitry Andric   /// this for use by RetCC_MipsN.
630b57cec5SDimitry Andric   void
640b57cec5SDimitry Andric   PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl<ISD::InputArg> &Ins);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   void
670b57cec5SDimitry Andric   PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl<ISD::InputArg> &Ins,
680b57cec5SDimitry Andric                                      const Type *RetTy);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   void PreAnalyzeFormalArgumentsForVectorFloat(
710b57cec5SDimitry Andric       const SmallVectorImpl<ISD::InputArg> &Ins);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   void
740b57cec5SDimitry Andric   PreAnalyzeReturnForVectorFloat(const SmallVectorImpl<ISD::OutputArg> &Outs);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   /// Records whether the value has been lowered from an f128.
770b57cec5SDimitry Andric   SmallVector<bool, 4> OriginalArgWasF128;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// Records whether the value has been lowered from float.
800b57cec5SDimitry Andric   SmallVector<bool, 4> OriginalArgWasFloat;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /// Records whether the value has been lowered from a floating point vector.
830b57cec5SDimitry Andric   SmallVector<bool, 4> OriginalArgWasFloatVector;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Records whether the return value has been lowered from a floating point
860b57cec5SDimitry Andric   /// vector.
870b57cec5SDimitry Andric   SmallVector<bool, 4> OriginalRetWasFloatVector;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   /// Records whether the value was a fixed argument.
900b57cec5SDimitry Andric   /// See ISD::OutputArg::IsFixed,
910b57cec5SDimitry Andric   SmallVector<bool, 4> CallOperandIsFixed;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   // Used to handle MIPS16-specific calling convention tweaks.
940b57cec5SDimitry Andric   // FIXME: This should probably be a fully fledged calling convention.
950b57cec5SDimitry Andric   SpecialCallingConvType SpecialCallingConv;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric public:
980b57cec5SDimitry Andric   MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
990b57cec5SDimitry Andric               SmallVectorImpl<CCValAssign> &locs, LLVMContext &C,
1000b57cec5SDimitry Andric               SpecialCallingConvType SpecialCC = NoSpecialCallingConv)
CCState(CC,isVarArg,MF,locs,C)1010b57cec5SDimitry Andric       : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {}
1020b57cec5SDimitry Andric 
PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn,std::vector<TargetLowering::ArgListEntry> & FuncArgs,const char * Func)1030b57cec5SDimitry Andric   void PreAnalyzeCallOperands(
1040b57cec5SDimitry Andric       const SmallVectorImpl<ISD::OutputArg> &Outs, CCAssignFn Fn,
1050b57cec5SDimitry Andric       std::vector<TargetLowering::ArgListEntry> &FuncArgs, const char *Func) {
1060b57cec5SDimitry Andric     OriginalArgWasF128.clear();
1070b57cec5SDimitry Andric     OriginalArgWasFloat.clear();
1080b57cec5SDimitry Andric     OriginalArgWasFloatVector.clear();
1090b57cec5SDimitry Andric     CallOperandIsFixed.clear();
1100b57cec5SDimitry Andric     PreAnalyzeCallOperands(Outs, FuncArgs, Func);
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   void
AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn,std::vector<TargetLowering::ArgListEntry> & FuncArgs,const char * Func)1140b57cec5SDimitry Andric   AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
1150b57cec5SDimitry Andric                       CCAssignFn Fn,
1160b57cec5SDimitry Andric                       std::vector<TargetLowering::ArgListEntry> &FuncArgs,
1170b57cec5SDimitry Andric                       const char *Func) {
1180b57cec5SDimitry Andric     PreAnalyzeCallOperands(Outs, Fn, FuncArgs, Func);
1190b57cec5SDimitry Andric     CCState::AnalyzeCallOperands(Outs, Fn);
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // The AnalyzeCallOperands in the base class is not usable since we must
1230b57cec5SDimitry Andric   // provide a means of accessing ArgListEntry::IsFixed. Delete them from this
1240b57cec5SDimitry Andric   // class. This doesn't stop them being used via the base class though.
1250b57cec5SDimitry Andric   void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
1260b57cec5SDimitry Andric                            CCAssignFn Fn) = delete;
1270b57cec5SDimitry Andric   void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs,
1280b57cec5SDimitry Andric                            SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
1290b57cec5SDimitry Andric                            CCAssignFn Fn) = delete;
1300b57cec5SDimitry Andric 
PreAnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn)1310b57cec5SDimitry Andric   void PreAnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
1320b57cec5SDimitry Andric                                  CCAssignFn Fn) {
1330b57cec5SDimitry Andric     OriginalArgWasFloat.clear();
1340b57cec5SDimitry Andric     OriginalArgWasF128.clear();
1350b57cec5SDimitry Andric     OriginalArgWasFloatVector.clear();
1360b57cec5SDimitry Andric     PreAnalyzeFormalArgumentsForF128(Ins);
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn)1390b57cec5SDimitry Andric   void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
1400b57cec5SDimitry Andric                               CCAssignFn Fn) {
1410b57cec5SDimitry Andric     PreAnalyzeFormalArguments(Ins, Fn);
1420b57cec5SDimitry Andric     CCState::AnalyzeFormalArguments(Ins, Fn);
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
PreAnalyzeCallResult(const Type * RetTy,const char * Func)1450b57cec5SDimitry Andric   void PreAnalyzeCallResult(const Type *RetTy, const char *Func) {
1460b57cec5SDimitry Andric     OriginalArgWasF128.push_back(originalTypeIsF128(RetTy, Func));
1470b57cec5SDimitry Andric     OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy());
1480b57cec5SDimitry Andric     OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy));
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
PreAnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn,const Type * RetTy,const char * Func)1510b57cec5SDimitry Andric   void PreAnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
1520b57cec5SDimitry Andric                             CCAssignFn Fn, const Type *RetTy,
1530b57cec5SDimitry Andric                             const char *Func) {
1540b57cec5SDimitry Andric     OriginalArgWasFloat.clear();
1550b57cec5SDimitry Andric     OriginalArgWasF128.clear();
1560b57cec5SDimitry Andric     OriginalArgWasFloatVector.clear();
1570b57cec5SDimitry Andric     PreAnalyzeCallResultForF128(Ins, RetTy, Func);
1580b57cec5SDimitry Andric     PreAnalyzeCallResultForVectorFloat(Ins, RetTy);
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> & Ins,CCAssignFn Fn,const Type * RetTy,const char * Func)1610b57cec5SDimitry Andric   void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
1620b57cec5SDimitry Andric                          CCAssignFn Fn, const Type *RetTy,
1630b57cec5SDimitry Andric                          const char *Func) {
1640b57cec5SDimitry Andric     PreAnalyzeCallResult(Ins, Fn, RetTy, Func);
1650b57cec5SDimitry Andric     CCState::AnalyzeCallResult(Ins, Fn);
1660b57cec5SDimitry Andric   }
167 
PreAnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn)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 
AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> & Outs,CCAssignFn Fn)177   void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
178                      CCAssignFn Fn) {
179     PreAnalyzeReturn(Outs, Fn);
180     CCState::AnalyzeReturn(Outs, Fn);
181   }
182 
CheckReturn(const SmallVectorImpl<ISD::OutputArg> & ArgsFlags,CCAssignFn Fn)183   bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
184                    CCAssignFn Fn) {
185     PreAnalyzeReturnForF128(ArgsFlags);
186     PreAnalyzeReturnForVectorFloat(ArgsFlags);
187     bool Return = CCState::CheckReturn(ArgsFlags, Fn);
188     OriginalArgWasFloat.clear();
189     OriginalArgWasF128.clear();
190     OriginalArgWasFloatVector.clear();
191     return Return;
192   }
193 
WasOriginalArgF128(unsigned ValNo)194   bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; }
WasOriginalArgFloat(unsigned ValNo)195   bool WasOriginalArgFloat(unsigned ValNo) {
196       return OriginalArgWasFloat[ValNo];
197   }
WasOriginalArgVectorFloat(unsigned ValNo)198   bool WasOriginalArgVectorFloat(unsigned ValNo) const {
199     return OriginalArgWasFloatVector[ValNo];
200   }
WasOriginalRetVectorFloat(unsigned ValNo)201   bool WasOriginalRetVectorFloat(unsigned ValNo) const {
202     return OriginalRetWasFloatVector[ValNo];
203   }
IsCallOperandFixed(unsigned ValNo)204   bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; }
getSpecialCallingConv()205   SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; }
206 };
207 }
208 
209 #endif
210