1 //===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===// 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 #include "MipsCCState.h" 11 #include "MipsSubtarget.h" 12 #include "llvm/IR/Module.h" 13 14 using namespace llvm; 15 16 /// This function returns true if CallSym is a long double emulation routine. 17 static bool isF128SoftLibCall(const char *CallSym) { 18 const char *const LibCalls[] = { 19 "__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", 20 "__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti", 21 "__fixunstfdi", "__fixunstfsi", "__fixunstfti", "__floatditf", 22 "__floatsitf", "__floattitf", "__floatunditf", "__floatunsitf", 23 "__floatuntitf", "__getf2", "__gttf2", "__letf2", 24 "__lttf2", "__multf3", "__netf2", "__powitf2", 25 "__subtf3", "__trunctfdf2", "__trunctfsf2", "__unordtf2", 26 "ceill", "copysignl", "cosl", "exp2l", 27 "expl", "floorl", "fmal", "fmodl", 28 "log10l", "log2l", "logl", "nearbyintl", 29 "powl", "rintl", "roundl", "sinl", 30 "sqrtl", "truncl"}; 31 32 // Check that LibCalls is sorted alphabetically. 33 auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; }; 34 assert(std::is_sorted(std::begin(LibCalls), std::end(LibCalls), Comp)); 35 return std::binary_search(std::begin(LibCalls), std::end(LibCalls), 36 CallSym, Comp); 37 } 38 39 /// This function returns true if Ty is fp128, {f128} or i128 which was 40 /// originally a fp128. 41 static bool originalTypeIsF128(const Type *Ty, const char *Func) { 42 if (Ty->isFP128Ty()) 43 return true; 44 45 if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && 46 Ty->getStructElementType(0)->isFP128Ty()) 47 return true; 48 49 // If the Ty is i128 and the function being called is a long double emulation 50 // routine, then the original type is f128. 51 return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func)); 52 } 53 54 /// Return true if the original type was vXfXX. 55 static bool originalEVTTypeIsVectorFloat(EVT Ty) { 56 if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint()) 57 return true; 58 59 return false; 60 } 61 62 /// Return true if the original type was vXfXX / vXfXX. 63 static bool originalTypeIsVectorFloat(const Type * Ty) { 64 if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy()) 65 return true; 66 67 return false; 68 } 69 70 MipsCCState::SpecialCallingConvType 71 MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee, 72 const MipsSubtarget &Subtarget) { 73 MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; 74 if (Subtarget.inMips16HardFloat()) { 75 if (const GlobalAddressSDNode *G = 76 dyn_cast<const GlobalAddressSDNode>(Callee)) { 77 llvm::StringRef Sym = G->getGlobal()->getName(); 78 Function *F = G->getGlobal()->getParent()->getFunction(Sym); 79 if (F && F->hasFnAttribute("__Mips16RetHelper")) { 80 SpecialCallingConv = Mips16RetHelperConv; 81 } 82 } 83 } 84 return SpecialCallingConv; 85 } 86 87 void MipsCCState::PreAnalyzeCallResultForF128( 88 const SmallVectorImpl<ISD::InputArg> &Ins, 89 const Type *RetTy, const char *Call) { 90 for (unsigned i = 0; i < Ins.size(); ++i) { 91 OriginalArgWasF128.push_back( 92 originalTypeIsF128(RetTy, Call)); 93 OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy()); 94 } 95 } 96 97 /// Identify lowered values that originated from f128 or float arguments and 98 /// record this for use by RetCC_MipsN. 99 void MipsCCState::PreAnalyzeReturnForF128( 100 const SmallVectorImpl<ISD::OutputArg> &Outs) { 101 const MachineFunction &MF = getMachineFunction(); 102 for (unsigned i = 0; i < Outs.size(); ++i) { 103 OriginalArgWasF128.push_back( 104 originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); 105 OriginalArgWasFloat.push_back( 106 MF.getFunction()->getReturnType()->isFloatingPointTy()); 107 } 108 } 109 110 /// Identify lower values that originated from vXfXX and record 111 /// this. 112 void MipsCCState::PreAnalyzeCallResultForVectorFloat( 113 const SmallVectorImpl<ISD::InputArg> &Ins, const Type *RetTy) { 114 for (unsigned i = 0; i < Ins.size(); ++i) { 115 OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy)); 116 } 117 } 118 119 /// Identify lowered values that originated from vXfXX arguments and record 120 /// this. 121 void MipsCCState::PreAnalyzeReturnForVectorFloat( 122 const SmallVectorImpl<ISD::OutputArg> &Outs) { 123 for (unsigned i = 0; i < Outs.size(); ++i) { 124 ISD::OutputArg Out = Outs[i]; 125 OriginalRetWasFloatVector.push_back( 126 originalEVTTypeIsVectorFloat(Out.ArgVT)); 127 } 128 } 129 130 /// Identify lowered values that originated from f128, float and sret to vXfXX 131 /// arguments and record this. 132 void MipsCCState::PreAnalyzeCallOperands( 133 const SmallVectorImpl<ISD::OutputArg> &Outs, 134 std::vector<TargetLowering::ArgListEntry> &FuncArgs, 135 const char *Func) { 136 for (unsigned i = 0; i < Outs.size(); ++i) { 137 TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex]; 138 139 OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func)); 140 OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy()); 141 OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy()); 142 CallOperandIsFixed.push_back(Outs[i].IsFixed); 143 } 144 } 145 146 /// Identify lowered values that originated from f128, float and vXfXX arguments 147 /// and record this. 148 void MipsCCState::PreAnalyzeFormalArgumentsForF128( 149 const SmallVectorImpl<ISD::InputArg> &Ins) { 150 const MachineFunction &MF = getMachineFunction(); 151 for (unsigned i = 0; i < Ins.size(); ++i) { 152 Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); 153 154 // SRet arguments cannot originate from f128 or {f128} returns so we just 155 // push false. We have to handle this specially since SRet arguments 156 // aren't mapped to an original argument. 157 if (Ins[i].Flags.isSRet()) { 158 OriginalArgWasF128.push_back(false); 159 OriginalArgWasFloat.push_back(false); 160 OriginalArgWasFloatVector.push_back(false); 161 continue; 162 } 163 164 assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size()); 165 std::advance(FuncArg, Ins[i].getOrigArgIndex()); 166 167 OriginalArgWasF128.push_back( 168 originalTypeIsF128(FuncArg->getType(), nullptr)); 169 OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); 170 171 // The MIPS vector ABI exhibits a corner case of sorts or quirk; if the 172 // first argument is actually an SRet pointer to a vector, then the next 173 // argument slot is $a2. 174 OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy()); 175 } 176 } 177