xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/Mips/MipsCCState.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc 
10*0a6a1f1dSLionel Sambuc #include "MipsCCState.h"
11*0a6a1f1dSLionel Sambuc #include "MipsSubtarget.h"
12*0a6a1f1dSLionel Sambuc #include "llvm/IR/Module.h"
13*0a6a1f1dSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc using namespace llvm;
15*0a6a1f1dSLionel Sambuc 
16*0a6a1f1dSLionel Sambuc /// This function returns true if CallSym is a long double emulation routine.
isF128SoftLibCall(const char * CallSym)17*0a6a1f1dSLionel Sambuc static bool isF128SoftLibCall(const char *CallSym) {
18*0a6a1f1dSLionel Sambuc   const char *const LibCalls[] = {
19*0a6a1f1dSLionel Sambuc       "__addtf3",      "__divtf3",     "__eqtf2",       "__extenddftf2",
20*0a6a1f1dSLionel Sambuc       "__extendsftf2", "__fixtfdi",    "__fixtfsi",     "__fixtfti",
21*0a6a1f1dSLionel Sambuc       "__fixunstfdi",  "__fixunstfsi", "__fixunstfti",  "__floatditf",
22*0a6a1f1dSLionel Sambuc       "__floatsitf",   "__floattitf",  "__floatunditf", "__floatunsitf",
23*0a6a1f1dSLionel Sambuc       "__floatuntitf", "__getf2",      "__gttf2",       "__letf2",
24*0a6a1f1dSLionel Sambuc       "__lttf2",       "__multf3",     "__netf2",       "__powitf2",
25*0a6a1f1dSLionel Sambuc       "__subtf3",      "__trunctfdf2", "__trunctfsf2",  "__unordtf2",
26*0a6a1f1dSLionel Sambuc       "ceill",         "copysignl",    "cosl",          "exp2l",
27*0a6a1f1dSLionel Sambuc       "expl",          "floorl",       "fmal",          "fmodl",
28*0a6a1f1dSLionel Sambuc       "log10l",        "log2l",        "logl",          "nearbyintl",
29*0a6a1f1dSLionel Sambuc       "powl",          "rintl",        "sinl",          "sqrtl",
30*0a6a1f1dSLionel Sambuc       "truncl"};
31*0a6a1f1dSLionel Sambuc 
32*0a6a1f1dSLionel Sambuc   const char *const *End = LibCalls + array_lengthof(LibCalls);
33*0a6a1f1dSLionel Sambuc 
34*0a6a1f1dSLionel Sambuc   // Check that LibCalls is sorted alphabetically.
35*0a6a1f1dSLionel Sambuc   MipsTargetLowering::LTStr Comp;
36*0a6a1f1dSLionel Sambuc 
37*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
38*0a6a1f1dSLionel Sambuc   for (const char *const *I = LibCalls; I < End - 1; ++I)
39*0a6a1f1dSLionel Sambuc     assert(Comp(*I, *(I + 1)));
40*0a6a1f1dSLionel Sambuc #endif
41*0a6a1f1dSLionel Sambuc 
42*0a6a1f1dSLionel Sambuc   return std::binary_search(LibCalls, End, CallSym, Comp);
43*0a6a1f1dSLionel Sambuc }
44*0a6a1f1dSLionel Sambuc 
45*0a6a1f1dSLionel Sambuc /// This function returns true if Ty is fp128, {f128} or i128 which was
46*0a6a1f1dSLionel Sambuc /// originally a fp128.
originalTypeIsF128(const Type * Ty,const SDNode * CallNode)47*0a6a1f1dSLionel Sambuc static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) {
48*0a6a1f1dSLionel Sambuc   if (Ty->isFP128Ty())
49*0a6a1f1dSLionel Sambuc     return true;
50*0a6a1f1dSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc   if (Ty->isStructTy() && Ty->getStructNumElements() == 1 &&
52*0a6a1f1dSLionel Sambuc       Ty->getStructElementType(0)->isFP128Ty())
53*0a6a1f1dSLionel Sambuc     return true;
54*0a6a1f1dSLionel Sambuc 
55*0a6a1f1dSLionel Sambuc   const ExternalSymbolSDNode *ES =
56*0a6a1f1dSLionel Sambuc       dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
57*0a6a1f1dSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc   // If the Ty is i128 and the function being called is a long double emulation
59*0a6a1f1dSLionel Sambuc   // routine, then the original type is f128.
60*0a6a1f1dSLionel Sambuc   return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol()));
61*0a6a1f1dSLionel Sambuc }
62*0a6a1f1dSLionel Sambuc 
63*0a6a1f1dSLionel Sambuc MipsCCState::SpecialCallingConvType
getSpecialCallingConvForCallee(const SDNode * Callee,const MipsSubtarget & Subtarget)64*0a6a1f1dSLionel Sambuc MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee,
65*0a6a1f1dSLionel Sambuc                                             const MipsSubtarget &Subtarget) {
66*0a6a1f1dSLionel Sambuc   MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv;
67*0a6a1f1dSLionel Sambuc   if (Subtarget.inMips16HardFloat()) {
68*0a6a1f1dSLionel Sambuc     if (const GlobalAddressSDNode *G =
69*0a6a1f1dSLionel Sambuc             dyn_cast<const GlobalAddressSDNode>(Callee)) {
70*0a6a1f1dSLionel Sambuc       llvm::StringRef Sym = G->getGlobal()->getName();
71*0a6a1f1dSLionel Sambuc       Function *F = G->getGlobal()->getParent()->getFunction(Sym);
72*0a6a1f1dSLionel Sambuc       if (F && F->hasFnAttribute("__Mips16RetHelper")) {
73*0a6a1f1dSLionel Sambuc         SpecialCallingConv = Mips16RetHelperConv;
74*0a6a1f1dSLionel Sambuc       }
75*0a6a1f1dSLionel Sambuc     }
76*0a6a1f1dSLionel Sambuc   }
77*0a6a1f1dSLionel Sambuc   return SpecialCallingConv;
78*0a6a1f1dSLionel Sambuc }
79*0a6a1f1dSLionel Sambuc 
PreAnalyzeCallResultForF128(const SmallVectorImpl<ISD::InputArg> & Ins,const TargetLowering::CallLoweringInfo & CLI)80*0a6a1f1dSLionel Sambuc void MipsCCState::PreAnalyzeCallResultForF128(
81*0a6a1f1dSLionel Sambuc     const SmallVectorImpl<ISD::InputArg> &Ins,
82*0a6a1f1dSLionel Sambuc     const TargetLowering::CallLoweringInfo &CLI) {
83*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < Ins.size(); ++i) {
84*0a6a1f1dSLionel Sambuc     OriginalArgWasF128.push_back(
85*0a6a1f1dSLionel Sambuc         originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode()));
86*0a6a1f1dSLionel Sambuc     OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy());
87*0a6a1f1dSLionel Sambuc   }
88*0a6a1f1dSLionel Sambuc }
89*0a6a1f1dSLionel Sambuc 
90*0a6a1f1dSLionel Sambuc /// Identify lowered values that originated from f128 arguments and record
91*0a6a1f1dSLionel Sambuc /// this for use by RetCC_MipsN.
PreAnalyzeReturnForF128(const SmallVectorImpl<ISD::OutputArg> & Outs)92*0a6a1f1dSLionel Sambuc void MipsCCState::PreAnalyzeReturnForF128(
93*0a6a1f1dSLionel Sambuc     const SmallVectorImpl<ISD::OutputArg> &Outs) {
94*0a6a1f1dSLionel Sambuc   const MachineFunction &MF = getMachineFunction();
95*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < Outs.size(); ++i) {
96*0a6a1f1dSLionel Sambuc     OriginalArgWasF128.push_back(
97*0a6a1f1dSLionel Sambuc         originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr));
98*0a6a1f1dSLionel Sambuc     OriginalArgWasFloat.push_back(
99*0a6a1f1dSLionel Sambuc         MF.getFunction()->getReturnType()->isFloatingPointTy());
100*0a6a1f1dSLionel Sambuc   }
101*0a6a1f1dSLionel Sambuc }
102*0a6a1f1dSLionel Sambuc 
103*0a6a1f1dSLionel Sambuc /// Identify lowered values that originated from f128 arguments and record
104*0a6a1f1dSLionel Sambuc /// this.
PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> & Outs,std::vector<TargetLowering::ArgListEntry> & FuncArgs,const SDNode * CallNode)105*0a6a1f1dSLionel Sambuc void MipsCCState::PreAnalyzeCallOperands(
106*0a6a1f1dSLionel Sambuc     const SmallVectorImpl<ISD::OutputArg> &Outs,
107*0a6a1f1dSLionel Sambuc     std::vector<TargetLowering::ArgListEntry> &FuncArgs,
108*0a6a1f1dSLionel Sambuc     const SDNode *CallNode) {
109*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < Outs.size(); ++i) {
110*0a6a1f1dSLionel Sambuc     OriginalArgWasF128.push_back(
111*0a6a1f1dSLionel Sambuc         originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode));
112*0a6a1f1dSLionel Sambuc     OriginalArgWasFloat.push_back(
113*0a6a1f1dSLionel Sambuc         FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy());
114*0a6a1f1dSLionel Sambuc     CallOperandIsFixed.push_back(Outs[i].IsFixed);
115*0a6a1f1dSLionel Sambuc   }
116*0a6a1f1dSLionel Sambuc }
117*0a6a1f1dSLionel Sambuc 
118*0a6a1f1dSLionel Sambuc /// Identify lowered values that originated from f128 arguments and record
119*0a6a1f1dSLionel Sambuc /// this.
PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl<ISD::InputArg> & Ins)120*0a6a1f1dSLionel Sambuc void MipsCCState::PreAnalyzeFormalArgumentsForF128(
121*0a6a1f1dSLionel Sambuc     const SmallVectorImpl<ISD::InputArg> &Ins) {
122*0a6a1f1dSLionel Sambuc   const MachineFunction &MF = getMachineFunction();
123*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < Ins.size(); ++i) {
124*0a6a1f1dSLionel Sambuc     Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin();
125*0a6a1f1dSLionel Sambuc 
126*0a6a1f1dSLionel Sambuc     // SRet arguments cannot originate from f128 or {f128} returns so we just
127*0a6a1f1dSLionel Sambuc     // push false. We have to handle this specially since SRet arguments
128*0a6a1f1dSLionel Sambuc     // aren't mapped to an original argument.
129*0a6a1f1dSLionel Sambuc     if (Ins[i].Flags.isSRet()) {
130*0a6a1f1dSLionel Sambuc       OriginalArgWasF128.push_back(false);
131*0a6a1f1dSLionel Sambuc       OriginalArgWasFloat.push_back(false);
132*0a6a1f1dSLionel Sambuc       continue;
133*0a6a1f1dSLionel Sambuc     }
134*0a6a1f1dSLionel Sambuc 
135*0a6a1f1dSLionel Sambuc     assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size());
136*0a6a1f1dSLionel Sambuc     std::advance(FuncArg, Ins[i].getOrigArgIndex());
137*0a6a1f1dSLionel Sambuc 
138*0a6a1f1dSLionel Sambuc     OriginalArgWasF128.push_back(
139*0a6a1f1dSLionel Sambuc         originalTypeIsF128(FuncArg->getType(), nullptr));
140*0a6a1f1dSLionel Sambuc     OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy());
141*0a6a1f1dSLionel Sambuc   }
142*0a6a1f1dSLionel Sambuc }
143