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