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 "printing.h"
19 #include <iomanip>
20
21 #if MIR_FEATURE_FULL
22
23 namespace maple {
24 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const25 void MIRIntConst::Dump(const MIRSymbolTable *) const
26 {
27 LogInfo::MapleLogger() << value;
28 }
29 #endif
30
operator ==(const MIRConst & rhs) const31 bool MIRIntConst::operator==(const MIRConst &rhs) const
32 {
33 if (&rhs == this) {
34 return true;
35 }
36 if (GetKind() != rhs.GetKind()) {
37 return false;
38 }
39 const auto &intConst = static_cast<const MIRIntConst &>(rhs);
40 return ((&intConst.GetType() == &GetType()) && (intConst.value == value));
41 }
42
43 #ifdef ARK_LITECG_DEBUG
GetActualBitWidth() const44 uint8 MIRIntConst::GetActualBitWidth() const
45 {
46 if (value == 0) {
47 return 1;
48 }
49
50 int64 val = GetExtValue();
51 uint64 tmp = val < 0 ? -(val + 1) : val;
52
53 uint8 width = 0;
54 while (tmp != 0) {
55 ++width;
56 tmp = tmp >> 1u;
57 }
58
59 return width;
60 }
61
Dump(const MIRSymbolTable * localSymTab) const62 void MIRAddrofConst::Dump(const MIRSymbolTable *localSymTab) const
63 {
64 LogInfo::MapleLogger() << "addrof " << GetPrimTypeName(PTY_ptr);
65 const MIRSymbol *sym = stIdx.IsGlobal() ? GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx())
66 : localSymTab->GetSymbolFromStIdx(stIdx.Idx());
67 DEBUG_ASSERT(stIdx.IsGlobal() || sym->GetStorageClass() == kScPstatic || sym->GetStorageClass() == kScFstatic,
68 "MIRAddrofConst can only point to a global symbol");
69 CHECK_FATAL(sym != nullptr, "null ptr");
70 LogInfo::MapleLogger() << (stIdx.IsGlobal() ? " $" : " %") << sym->GetName();
71 if (fldID > 0) {
72 LogInfo::MapleLogger() << " " << fldID;
73 }
74 if (offset != 0) {
75 LogInfo::MapleLogger() << " (" << offset << ")";
76 }
77 }
78 #endif
79
operator ==(const MIRConst & rhs) const80 bool MIRAddrofConst::operator==(const MIRConst &rhs) const
81 {
82 if (&rhs == this) {
83 return true;
84 }
85 if (GetKind() != rhs.GetKind()) {
86 return false;
87 }
88 const auto &rhsA = static_cast<const MIRAddrofConst &>(rhs);
89 if (&GetType() != &rhs.GetType()) {
90 return false;
91 }
92 return (stIdx == rhsA.stIdx) && (fldID == rhsA.fldID);
93 }
94
95 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const96 void MIRAddroffuncConst::Dump(const MIRSymbolTable *) const
97 {
98 LogInfo::MapleLogger() << "addroffunc " << GetPrimTypeName(PTY_ptr);
99 MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
100 CHECK_FATAL(func != nullptr, "null ptr");
101 CHECK_NULL_FATAL(GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx()));
102 LogInfo::MapleLogger() << " &"
103 << GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx())->GetName();
104 }
105 #endif
106
operator ==(const MIRConst & rhs) const107 bool MIRAddroffuncConst::operator==(const MIRConst &rhs) const
108 {
109 if (&rhs == this) {
110 return true;
111 }
112 if (GetKind() != rhs.GetKind()) {
113 return false;
114 }
115 const auto &rhsAf = static_cast<const MIRAddroffuncConst &>(rhs);
116 return (&GetType() == &rhs.GetType()) && (puIdx == rhsAf.puIdx);
117 }
118
119 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const120 void MIRLblConst::Dump(const MIRSymbolTable *) const
121 {
122 LogInfo::MapleLogger() << "addroflabel " << GetPrimTypeName(PTY_ptr);
123 MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx);
124 LogInfo::MapleLogger() << " @" << func->GetLabelName(value);
125 }
126 #endif
127
operator ==(const MIRConst & rhs) const128 bool MIRLblConst::operator==(const MIRConst &rhs) const
129 {
130 if (&rhs == this) {
131 return true;
132 }
133 if (GetKind() != rhs.GetKind()) {
134 return false;
135 }
136 const auto &lblConst = static_cast<const MIRLblConst &>(rhs);
137 return (lblConst.value == value);
138 }
139
operator ==(const MIRConst & rhs) const140 bool MIRFloatConst::operator==(const MIRConst &rhs) const
141 {
142 if (&rhs == this) {
143 return true;
144 }
145 if (GetKind() != rhs.GetKind()) {
146 return false;
147 }
148 const auto &floatConst = static_cast<const MIRFloatConst &>(rhs);
149 if (std::isnan(floatConst.value.floatValue)) {
150 return std::isnan(value.floatValue);
151 }
152 if (std::isnan(value.floatValue)) {
153 return std::isnan(floatConst.value.floatValue);
154 }
155 if (floatConst.value.floatValue == 0.0 && value.floatValue == 0.0) {
156 return floatConst.IsNeg() == IsNeg();
157 }
158 // Use bitwise comparison instead of approximate comparison for FP to avoid treating 0.0 and FLT_MIN as equal
159 return (floatConst.value.intValue == value.intValue);
160 }
161
operator ==(const MIRConst & rhs) const162 bool MIRDoubleConst::operator==(const MIRConst &rhs) const
163 {
164 if (&rhs == this) {
165 return true;
166 }
167 if (GetKind() != rhs.GetKind()) {
168 return false;
169 }
170 const auto &floatConst = static_cast<const MIRDoubleConst &>(rhs);
171 if (std::isnan(floatConst.value.dValue)) {
172 return std::isnan(value.dValue);
173 }
174 if (std::isnan(value.dValue)) {
175 return std::isnan(floatConst.value.dValue);
176 }
177 if (floatConst.value.dValue == 0.0 && value.dValue == 0.0) {
178 return floatConst.IsNeg() == IsNeg();
179 }
180 // Use bitwise comparison instead of approximate comparison for FP to avoid treating 0.0 and DBL_MIN as equal
181 return (floatConst.value.intValue == value.intValue);
182 }
183
operator ==(const MIRConst & rhs) const184 bool MIRAggConst::operator==(const MIRConst &rhs) const
185 {
186 if (&rhs == this) {
187 return true;
188 }
189 if (GetKind() != rhs.GetKind()) {
190 return false;
191 }
192 const auto &aggregateConst = static_cast<const MIRAggConst &>(rhs);
193 if (aggregateConst.constVec.size() != constVec.size()) {
194 return false;
195 }
196 for (size_t i = 0; i < constVec.size(); ++i) {
197 if (!(*aggregateConst.constVec[i] == *constVec[i])) {
198 return false;
199 }
200 }
201 return true;
202 }
203
204 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const205 void MIRFloatConst::Dump(const MIRSymbolTable *) const
206 {
207 LogInfo::MapleLogger() << std::setprecision(std::numeric_limits<float>::max_digits10) << value.floatValue << "f";
208 }
209
Dump(const MIRSymbolTable *) const210 void MIRDoubleConst::Dump(const MIRSymbolTable *) const
211 {
212 LogInfo::MapleLogger() << std::setprecision(std::numeric_limits<double>::max_digits10) << value.dValue;
213 }
214
Dump(const MIRSymbolTable * localSymTab) const215 void MIRAggConst::Dump(const MIRSymbolTable *localSymTab) const
216 {
217 LogInfo::MapleLogger() << "[";
218 size_t size = constVec.size();
219 for (size_t i = 0; i < size; ++i) {
220 if (fieldIdVec[i] != 0) {
221 LogInfo::MapleLogger() << fieldIdVec[i] << "= ";
222 }
223 constVec[i]->Dump(localSymTab);
224 if (i != size - 1) {
225 LogInfo::MapleLogger() << ", ";
226 }
227 }
228 LogInfo::MapleLogger() << "]";
229 }
230 #endif
231
MIRStrConst(const std::string & str,MIRType & type)232 MIRStrConst::MIRStrConst(const std::string &str, MIRType &type)
233 : MIRConst(type, kConstStrConst), value(GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str))
234 {
235 }
236
237 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const238 void MIRStrConst::Dump(const MIRSymbolTable *) const
239 {
240 LogInfo::MapleLogger() << "conststr " << GetPrimTypeName(GetType().GetPrimType());
241 const std::string &dumpStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(value);
242 PrintString(dumpStr);
243 }
244 #endif
245
operator ==(const MIRConst & rhs) const246 bool MIRStrConst::operator==(const MIRConst &rhs) const
247 {
248 if (&rhs == this) {
249 return true;
250 }
251 if (GetKind() != rhs.GetKind()) {
252 return false;
253 }
254 const auto &rhsCs = static_cast<const MIRStrConst &>(rhs);
255 return (&rhs.GetType() == &GetType()) && (value == rhsCs.value);
256 }
257
MIRStr16Const(const std::u16string & str,MIRType & type)258 MIRStr16Const::MIRStr16Const(const std::u16string &str, MIRType &type)
259 : MIRConst(type, kConstStr16Const), value(GlobalTables::GetU16StrTable().GetOrCreateStrIdxFromName(str))
260 {
261 }
262
263 #ifdef ARK_LITECG_DEBUG
Dump(const MIRSymbolTable *) const264 void MIRStr16Const::Dump(const MIRSymbolTable *) const
265 {
266 LogInfo::MapleLogger() << "conststr16 " << GetPrimTypeName(GetType().GetPrimType());
267 std::u16string str16 = GlobalTables::GetU16StrTable().GetStringFromStrIdx(value);
268 // UTF-16 string are dumped as UTF-8 string in mpl to keep the printable chars in ascii form
269 std::string str;
270 (void)namemangler::UTF16ToUTF8(str, str16);
271 PrintString(str);
272 }
273 #endif
274
operator ==(const MIRConst & rhs) const275 bool MIRStr16Const::operator==(const MIRConst &rhs) const
276 {
277 if (&rhs == this) {
278 return true;
279 }
280 if (GetKind() != rhs.GetKind()) {
281 return false;
282 }
283 const auto &rhsCs = static_cast<const MIRStr16Const &>(rhs);
284 return (&GetType() == &rhs.GetType()) && (value == rhsCs.value);
285 }
286
IsDivSafe(const MIRIntConst & dividend,const MIRIntConst & divisor,PrimType pType)287 bool IsDivSafe(const MIRIntConst ÷nd, const MIRIntConst &divisor, PrimType pType)
288 {
289 if (IsUnsignedInteger(pType)) {
290 return divisor.GetValue() != 0;
291 }
292
293 return divisor.GetValue() != 0 && (!dividend.GetValue().IsMinValue() || !divisor.GetValue().AreAllBitsOne());
294 }
295
296 } // namespace maple
297 #endif // MIR_FEATURE_FULL
298