1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "mir_const.h"
17 #include "mir_function.h"
18 #include "global_tables.h"
19 #include "printing.h"
20 #if MIR_FEATURE_FULL
21
22 namespace maple {
Dump(const MIRSymbolTable *) const23 void MIRIntConst::Dump(const MIRSymbolTable *) const
24 {
25 LogInfo::MapleLogger() << value;
26 }
27
operator ==(const MIRConst & rhs) const28 bool MIRIntConst::operator==(const MIRConst &rhs) const
29 {
30 if (&rhs == this) {
31 return true;
32 }
33 if (GetKind() != rhs.GetKind()) {
34 return false;
35 }
36 const auto &intConst = static_cast<const MIRIntConst &>(rhs);
37 return ((&intConst.GetType() == &GetType()) && (intConst.value == value));
38 }
39
GetActualBitWidth() const40 uint8 MIRIntConst::GetActualBitWidth() const
41 {
42 if (value == 0) {
43 return 1;
44 }
45
46 int64 val = GetExtValue();
47 uint64 tmp = val < 0 ? -(val + 1) : val;
48
49 uint8 width = 0;
50 while (tmp != 0) {
51 ++width;
52 tmp = tmp >> 1u;
53 }
54
55 return width;
56 }
57
Dump(const MIRSymbolTable * localSymTab) const58 void MIRAddrofConst::Dump(const MIRSymbolTable *localSymTab) const
59 {
60 LogInfo::MapleLogger() << "addrof " << GetPrimTypeName(PTY_ptr);
61 const MIRSymbol *sym = stIdx.IsGlobal() ? GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx())
62 : localSymTab->GetSymbolFromStIdx(stIdx.Idx());
63 DEBUG_ASSERT(stIdx.IsGlobal() || sym->GetStorageClass() == kScPstatic || sym->GetStorageClass() == kScFstatic,
64 "MIRAddrofConst can only point to a global symbol");
65 CHECK_FATAL(sym != nullptr, "null ptr");
66 LogInfo::MapleLogger() << (stIdx.IsGlobal() ? " $" : " %") << sym->GetName();
67 if (fldID > 0) {
68 LogInfo::MapleLogger() << " " << fldID;
69 }
70 if (offset != 0) {
71 LogInfo::MapleLogger() << " (" << offset << ")";
72 }
73 }
74
operator ==(const MIRConst & rhs) const75 bool MIRAddrofConst::operator==(const MIRConst &rhs) const
76 {
77 if (&rhs == this) {
78 return true;
79 }
80 if (GetKind() != rhs.GetKind()) {
81 return false;
82 }
83 const auto &rhsA = static_cast<const MIRAddrofConst &>(rhs);
84 if (&GetType() != &rhs.GetType()) {
85 return false;
86 }
87 return (stIdx == rhsA.stIdx) && (fldID == rhsA.fldID);
88 }
89
Dump(const MIRSymbolTable *) const90 void MIRAddroffuncConst::Dump(const MIRSymbolTable *) const
91 {
92 LogInfo::MapleLogger() << "addroffunc " << GetPrimTypeName(PTY_ptr);
93 MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
94 CHECK_FATAL(func != nullptr, "null ptr");
95 CHECK_NULL_FATAL(GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx()));
96 LogInfo::MapleLogger() << " &"
97 << GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx())->GetName();
98 }
99
operator ==(const MIRConst & rhs) const100 bool MIRAddroffuncConst::operator==(const MIRConst &rhs) const
101 {
102 if (&rhs == this) {
103 return true;
104 }
105 if (GetKind() != rhs.GetKind()) {
106 return false;
107 }
108 const auto &rhsAf = static_cast<const MIRAddroffuncConst &>(rhs);
109 return (&GetType() == &rhs.GetType()) && (puIdx == rhsAf.puIdx);
110 }
111
Dump(const MIRSymbolTable *) const112 void MIRLblConst::Dump(const MIRSymbolTable *) const
113 {
114 LogInfo::MapleLogger() << "addroflabel " << GetPrimTypeName(PTY_ptr);
115 MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
116 LogInfo::MapleLogger() << " @" << func->GetLabelName(value);
117 }
118
operator ==(const MIRConst & rhs) const119 bool MIRLblConst::operator==(const MIRConst &rhs) const
120 {
121 if (&rhs == this) {
122 return true;
123 }
124 if (GetKind() != rhs.GetKind()) {
125 return false;
126 }
127 const auto &lblConst = static_cast<const MIRLblConst &>(rhs);
128 return (lblConst.value == value);
129 }
130
operator ==(const MIRConst & rhs) const131 bool MIRFloatConst::operator==(const MIRConst &rhs) const
132 {
133 if (&rhs == this) {
134 return true;
135 }
136 if (GetKind() != rhs.GetKind()) {
137 return false;
138 }
139 const auto &floatConst = static_cast<const MIRFloatConst &>(rhs);
140 if (std::isnan(floatConst.value.floatValue)) {
141 return std::isnan(value.floatValue);
142 }
143 if (std::isnan(value.floatValue)) {
144 return std::isnan(floatConst.value.floatValue);
145 }
146 if (floatConst.value.floatValue == 0.0 && value.floatValue == 0.0) {
147 return floatConst.IsNeg() == IsNeg();
148 }
149 // Use bitwise comparison instead of approximate comparison for FP to avoid treating 0.0 and FLT_MIN as equal
150 return (floatConst.value.intValue == value.intValue);
151 }
152
operator ==(const MIRConst & rhs) const153 bool MIRDoubleConst::operator==(const MIRConst &rhs) const
154 {
155 if (&rhs == this) {
156 return true;
157 }
158 if (GetKind() != rhs.GetKind()) {
159 return false;
160 }
161 const auto &floatConst = static_cast<const MIRDoubleConst &>(rhs);
162 if (std::isnan(floatConst.value.dValue)) {
163 return std::isnan(value.dValue);
164 }
165 if (std::isnan(value.dValue)) {
166 return std::isnan(floatConst.value.dValue);
167 }
168 if (floatConst.value.dValue == 0.0 && value.dValue == 0.0) {
169 return floatConst.IsNeg() == IsNeg();
170 }
171 // Use bitwise comparison instead of approximate comparison for FP to avoid treating 0.0 and DBL_MIN as equal
172 return (floatConst.value.intValue == value.intValue);
173 }
174
operator ==(const MIRConst & rhs) const175 bool MIRFloat128Const::operator==(const MIRConst &rhs) const
176 {
177 if (&rhs == this) {
178 return true;
179 }
180 if (GetKind() != rhs.GetKind()) {
181 return false;
182 }
183 const auto &floatConst = static_cast<const MIRFloat128Const &>(rhs);
184 if ((value[0] == floatConst.value[0]) && (value[1] == floatConst.value[1])) {
185 return true;
186 }
187 return false;
188 }
189
operator ==(const MIRConst & rhs) const190 bool MIRAggConst::operator==(const MIRConst &rhs) const
191 {
192 if (&rhs == this) {
193 return true;
194 }
195 if (GetKind() != rhs.GetKind()) {
196 return false;
197 }
198 const auto &aggregateConst = static_cast<const MIRAggConst &>(rhs);
199 if (aggregateConst.constVec.size() != constVec.size()) {
200 return false;
201 }
202 for (size_t i = 0; i < constVec.size(); ++i) {
203 if (!(*aggregateConst.constVec[i] == *constVec[i])) {
204 return false;
205 }
206 }
207 return true;
208 }
209
Dump(const MIRSymbolTable *) const210 void MIRFloatConst::Dump(const MIRSymbolTable *) const
211 {
212 LogInfo::MapleLogger() << std::setprecision(std::numeric_limits<float>::max_digits10) << value.floatValue << "f";
213 }
214
Dump(const MIRSymbolTable *) const215 void MIRDoubleConst::Dump(const MIRSymbolTable *) const
216 {
217 LogInfo::MapleLogger() << std::setprecision(std::numeric_limits<double>::max_digits10) << value.dValue;
218 }
219
Dump(const MIRSymbolTable *) const220 void MIRFloat128Const::Dump(const MIRSymbolTable *) const
221 {
222 constexpr int fieldWidth = 16;
223 std::ios::fmtflags f(LogInfo::MapleLogger().flags());
224 LogInfo::MapleLogger().setf(std::ios::uppercase);
225 LogInfo::MapleLogger() << "0xL" << std::hex << std::setfill('0') << std::setw(fieldWidth) << value[0]
226 << std::setfill('0') << std::setw(fieldWidth) << value[1];
227 LogInfo::MapleLogger().flags(f);
228 }
229
Dump(const MIRSymbolTable * localSymTab) const230 void MIRAggConst::Dump(const MIRSymbolTable *localSymTab) const
231 {
232 LogInfo::MapleLogger() << "[";
233 size_t size = constVec.size();
234 for (size_t i = 0; i < size; ++i) {
235 if (fieldIdVec[i] != 0) {
236 LogInfo::MapleLogger() << fieldIdVec[i] << "= ";
237 }
238 constVec[i]->Dump(localSymTab);
239 if (i != size - 1) {
240 LogInfo::MapleLogger() << ", ";
241 }
242 }
243 LogInfo::MapleLogger() << "]";
244 }
245
MIRStrConst(const std::string & str,MIRType & type)246 MIRStrConst::MIRStrConst(const std::string &str, MIRType &type)
247 : MIRConst(type, kConstStrConst), value(GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str))
248 {
249 }
250
Dump(const MIRSymbolTable *) const251 void MIRStrConst::Dump(const MIRSymbolTable *) const
252 {
253 LogInfo::MapleLogger() << "conststr " << GetPrimTypeName(GetType().GetPrimType());
254 const std::string &dumpStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(value);
255 PrintString(dumpStr);
256 }
257
operator ==(const MIRConst & rhs) const258 bool MIRStrConst::operator==(const MIRConst &rhs) const
259 {
260 if (&rhs == this) {
261 return true;
262 }
263 if (GetKind() != rhs.GetKind()) {
264 return false;
265 }
266 const auto &rhsCs = static_cast<const MIRStrConst &>(rhs);
267 return (&rhs.GetType() == &GetType()) && (value == rhsCs.value);
268 }
269
MIRStr16Const(const std::u16string & str,MIRType & type)270 MIRStr16Const::MIRStr16Const(const std::u16string &str, MIRType &type)
271 : MIRConst(type, kConstStr16Const), value(GlobalTables::GetU16StrTable().GetOrCreateStrIdxFromName(str))
272 {
273 }
274
Dump(const MIRSymbolTable *) const275 void MIRStr16Const::Dump(const MIRSymbolTable *) const
276 {
277 LogInfo::MapleLogger() << "conststr16 " << GetPrimTypeName(GetType().GetPrimType());
278 std::u16string str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(value);
279 // UTF-16 string are dumped as UTF-8 string in mpl to keep the printable chars in ascii form
280 std::string str;
281 (void)namemangler::UTF16ToUTF8(str, str16);
282 PrintString(str);
283 }
284
operator ==(const MIRConst & rhs) const285 bool MIRStr16Const::operator==(const MIRConst &rhs) const
286 {
287 if (&rhs == this) {
288 return true;
289 }
290 if (GetKind() != rhs.GetKind()) {
291 return false;
292 }
293 const auto &rhsCs = static_cast<const MIRStr16Const &>(rhs);
294 return (&GetType() == &rhs.GetType()) && (value == rhsCs.value);
295 }
296
IsDivSafe(const MIRIntConst & dividend,const MIRIntConst & divisor,PrimType pType)297 bool IsDivSafe(const MIRIntConst ÷nd, const MIRIntConst &divisor, PrimType pType)
298 {
299 if (IsUnsignedInteger(pType)) {
300 return divisor.GetValue() != 0;
301 }
302
303 return divisor.GetValue() != 0 && (!dividend.GetValue().IsMinValue() || !divisor.GetValue().AreAllBitsOne());
304 }
305
306 } // namespace maple
307 #endif // MIR_FEATURE_FULL
308