MipsCCState.cpp revision 283526
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