Home | History | Annotate | Download | only in Mips
      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",        "sinl",          "sqrtl",
     30       "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(Type *Ty, const SDNode *CallNode) {
     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   const ExternalSymbolSDNode *ES =
     50       dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
     51 
     52   // If the Ty is i128 and the function being called is a long double emulation
     53   // routine, then the original type is f128.
     54   return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol()));
     55 }
     56 
     57 MipsCCState::SpecialCallingConvType
     58 MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee,
     59                                             const MipsSubtarget &Subtarget) {
     60   MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv;
     61   if (Subtarget.inMips16HardFloat()) {
     62     if (const GlobalAddressSDNode *G =
     63             dyn_cast<const GlobalAddressSDNode>(Callee)) {
     64       llvm::StringRef Sym = G->getGlobal()->getName();
     65       Function *F = G->getGlobal()->getParent()->getFunction(Sym);
     66       if (F && F->hasFnAttribute("__Mips16RetHelper")) {
     67         SpecialCallingConv = Mips16RetHelperConv;
     68       }
     69     }
     70   }
     71   return SpecialCallingConv;
     72 }
     73 
     74 void MipsCCState::PreAnalyzeCallResultForF128(
     75     const SmallVectorImpl<ISD::InputArg> &Ins,
     76     const TargetLowering::CallLoweringInfo &CLI) {
     77   for (unsigned i = 0; i < Ins.size(); ++i) {
     78     OriginalArgWasF128.push_back(
     79         originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode()));
     80     OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy());
     81   }
     82 }
     83 
     84 /// Identify lowered values that originated from f128 arguments and record
     85 /// this for use by RetCC_MipsN.
     86 void MipsCCState::PreAnalyzeReturnForF128(
     87     const SmallVectorImpl<ISD::OutputArg> &Outs) {
     88   const MachineFunction &MF = getMachineFunction();
     89   for (unsigned i = 0; i < Outs.size(); ++i) {
     90     OriginalArgWasF128.push_back(
     91         originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr));
     92     OriginalArgWasFloat.push_back(
     93         MF.getFunction()->getReturnType()->isFloatingPointTy());
     94   }
     95 }
     96 
     97 /// Identify lowered values that originated from f128 arguments and record
     98 /// this.
     99 void MipsCCState::PreAnalyzeCallOperands(
    100     const SmallVectorImpl<ISD::OutputArg> &Outs,
    101     std::vector<TargetLowering::ArgListEntry> &FuncArgs,
    102     const SDNode *CallNode) {
    103   for (unsigned i = 0; i < Outs.size(); ++i) {
    104     OriginalArgWasF128.push_back(
    105         originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode));
    106     OriginalArgWasFloat.push_back(
    107         FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy());
    108     CallOperandIsFixed.push_back(Outs[i].IsFixed);
    109   }
    110 }
    111 
    112 /// Identify lowered values that originated from f128 arguments and record
    113 /// this.
    114 void MipsCCState::PreAnalyzeFormalArgumentsForF128(
    115     const SmallVectorImpl<ISD::InputArg> &Ins) {
    116   const MachineFunction &MF = getMachineFunction();
    117   for (unsigned i = 0; i < Ins.size(); ++i) {
    118     Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin();
    119 
    120     // SRet arguments cannot originate from f128 or {f128} returns so we just
    121     // push false. We have to handle this specially since SRet arguments
    122     // aren't mapped to an original argument.
    123     if (Ins[i].Flags.isSRet()) {
    124       OriginalArgWasF128.push_back(false);
    125       OriginalArgWasFloat.push_back(false);
    126       continue;
    127     }
    128 
    129     assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size());
    130     std::advance(FuncArg, Ins[i].getOrigArgIndex());
    131 
    132     OriginalArgWasF128.push_back(
    133         originalTypeIsF128(FuncArg->getType(), nullptr));
    134     OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy());
    135   }
    136 }
    137