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