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 14using namespace llvm; 15 16/// This function returns true if CallSym is a long double emulation routine. 17static 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", "sinl", "sqrtl", 30 "truncl"}; 31 32 const char *const *End = LibCalls + array_lengthof(LibCalls); 33 34 // Check that LibCalls is sorted alphabetically. 35 MipsTargetLowering::LTStr Comp; 36 37#ifndef NDEBUG 38 for (const char *const *I = LibCalls; I < End - 1; ++I) 39 assert(Comp(*I, *(I + 1))); 40#endif 41 42 return std::binary_search(LibCalls, End, CallSym, Comp); 43} 44 45/// This function returns true if Ty is fp128, {f128} or i128 which was 46/// originally a fp128. 47static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) { 48 if (Ty->isFP128Ty()) 49 return true; 50 51 if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && 52 Ty->getStructElementType(0)->isFP128Ty()) 53 return true; 54 55 const ExternalSymbolSDNode *ES = 56 dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode); 57 58 // If the Ty is i128 and the function being called is a long double emulation 59 // routine, then the original type is f128. 60 return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol())); 61} 62 63MipsCCState::SpecialCallingConvType 64MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee, 65 const MipsSubtarget &Subtarget) { 66 MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; 67 if (Subtarget.inMips16HardFloat()) { 68 if (const GlobalAddressSDNode *G = 69 dyn_cast<const GlobalAddressSDNode>(Callee)) { 70 llvm::StringRef Sym = G->getGlobal()->getName(); 71 Function *F = G->getGlobal()->getParent()->getFunction(Sym); 72 if (F && F->hasFnAttribute("__Mips16RetHelper")) { 73 SpecialCallingConv = Mips16RetHelperConv; 74 } 75 } 76 } 77 return SpecialCallingConv; 78} 79 80void MipsCCState::PreAnalyzeCallResultForF128( 81 const SmallVectorImpl<ISD::InputArg> &Ins, 82 const TargetLowering::CallLoweringInfo &CLI) { 83 for (unsigned i = 0; i < Ins.size(); ++i) { 84 OriginalArgWasF128.push_back( 85 originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode())); 86 OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy()); 87 } 88} 89 90/// Identify lowered values that originated from f128 arguments and record 91/// this for use by RetCC_MipsN. 92void MipsCCState::PreAnalyzeReturnForF128( 93 const SmallVectorImpl<ISD::OutputArg> &Outs) { 94 const MachineFunction &MF = getMachineFunction(); 95 for (unsigned i = 0; i < Outs.size(); ++i) { 96 OriginalArgWasF128.push_back( 97 originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); 98 OriginalArgWasFloat.push_back( 99 MF.getFunction()->getReturnType()->isFloatingPointTy()); 100 } 101} 102 103/// Identify lowered values that originated from f128 arguments and record 104/// this. 105void MipsCCState::PreAnalyzeCallOperands( 106 const SmallVectorImpl<ISD::OutputArg> &Outs, 107 std::vector<TargetLowering::ArgListEntry> &FuncArgs, 108 const SDNode *CallNode) { 109 for (unsigned i = 0; i < Outs.size(); ++i) { 110 OriginalArgWasF128.push_back( 111 originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode)); 112 OriginalArgWasFloat.push_back( 113 FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy()); 114 CallOperandIsFixed.push_back(Outs[i].IsFixed); 115 } 116} 117 118/// Identify lowered values that originated from f128 arguments and record 119/// this. 120void MipsCCState::PreAnalyzeFormalArgumentsForF128( 121 const SmallVectorImpl<ISD::InputArg> &Ins) { 122 const MachineFunction &MF = getMachineFunction(); 123 for (unsigned i = 0; i < Ins.size(); ++i) { 124 Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); 125 126 // SRet arguments cannot originate from f128 or {f128} returns so we just 127 // push false. We have to handle this specially since SRet arguments 128 // aren't mapped to an original argument. 129 if (Ins[i].Flags.isSRet()) { 130 OriginalArgWasF128.push_back(false); 131 OriginalArgWasFloat.push_back(false); 132 continue; 133 } 134 135 assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size()); 136 std::advance(FuncArg, Ins[i].getOrigArgIndex()); 137 138 OriginalArgWasF128.push_back( 139 originalTypeIsF128(FuncArg->getType(), nullptr)); 140 OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); 141 } 142} 143