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_symbol.h"
17 #include "mir_function.h"
18 #include "class_init.h"
19 #include "reflection_analysis.h"
20 #include "printing.h"
21 #include "literalstrname.h"
22 #include "string_utils.h"
23
24 namespace maple {
25 using namespace namemangler;
26
27 uint32 MIRSymbol::lastPrintedLineNum = 0;
28 uint16 MIRSymbol::lastPrintedColumnNum = 0;
29
NeedPIC() const30 bool MIRSymbol::NeedPIC() const
31 {
32 return (storageClass == kScGlobal) || (storageClass == kScExtern) ||
33 (sKind == kStFunc && !GetFunction()->IsStatic());
34 }
35
IsTypeVolatile(int fieldID) const36 bool MIRSymbol::IsTypeVolatile(int fieldID) const
37 {
38 const MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetTyIdx());
39 return ty->IsVolatile(fieldID);
40 }
41
SetNameStrIdx(const std::string & name)42 void MIRSymbol::SetNameStrIdx(const std::string &name)
43 {
44 nameStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name);
45 }
46
HasAddrOfValues() const47 bool MIRSymbol::HasAddrOfValues() const
48 {
49 return StringUtils::StartsWith(GetName(), VTAB_PREFIX_STR) || StringUtils::StartsWith(GetName(), ITAB_PREFIX_STR) ||
50 StringUtils::StartsWith(GetName(), kVtabOffsetTabStr) ||
51 StringUtils::StartsWith(GetName(), kDecoupleStaticKeyStr) || IsClassInitBridge() || IsReflectionInfo() ||
52 IsReflectionHashTabBucket() || IsReflectionStrTab() || IsITabConflictInfo() || IsRegJNITab() ||
53 IsRegJNIFuncTab() || IsLiteral();
54 }
55
IsLiteral() const56 bool MIRSymbol::IsLiteral() const
57 {
58 return StringUtils::StartsWith(GetName(), kConstString);
59 }
60
IsLiteralPtr() const61 bool MIRSymbol::IsLiteralPtr() const
62 {
63 return StringUtils::StartsWith(GetName(), kConstStringPtr);
64 }
65
GetType() const66 MIRType *MIRSymbol::GetType() const
67 {
68 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
69 }
70
PointsToConstString() const71 bool MIRSymbol::PointsToConstString() const
72 {
73 MIRType *origType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
74 if (origType->GetKind() == kTypePointer) {
75 return static_cast<MIRPtrType *>(origType)->PointsToConstString();
76 }
77 return false;
78 }
79
IsConstString() const80 bool MIRSymbol::IsConstString() const
81 {
82 return typeAttrs.GetAttr(ATTR_static) && typeAttrs.GetAttr(ATTR_final) && PointsToConstString();
83 }
84
IsReflectionStrTab() const85 bool MIRSymbol::IsReflectionStrTab() const
86 {
87 return StringUtils::StartsWith(GetName(), kReflectionStrtabPrefixStr) ||
88 StringUtils::StartsWith(GetName(), kReflectionStartHotStrtabPrefixStr) ||
89 StringUtils::StartsWith(GetName(), kReflectionBothHotStrTabPrefixStr) ||
90 StringUtils::StartsWith(GetName(), kReflectionRunHotStrtabPrefixStr) ||
91 StringUtils::StartsWith(GetName(), kReflectionNoEmitStrtabPrefixStr);
92 }
93
IsRegJNITab() const94 bool MIRSymbol::IsRegJNITab() const
95 {
96 return false;
97 }
98
IsRegJNIFuncTab() const99 bool MIRSymbol::IsRegJNIFuncTab() const
100 {
101 return StringUtils::StartsWith(GetName(), kRegJNIFuncTabPrefixStr);
102 }
103
IsMuidTab() const104 bool MIRSymbol::IsMuidTab() const
105 {
106 return StringUtils::StartsWith(GetName(), kMuidPrefixStr);
107 }
108
IsMuidRoTab() const109 bool MIRSymbol::IsMuidRoTab() const
110 {
111 return StringUtils::StartsWith(GetName(), kMuidRoPrefixStr);
112 }
113
IsCodeLayoutInfo() const114 bool MIRSymbol::IsCodeLayoutInfo() const
115 {
116 return StringUtils::StartsWith(GetName(), kFunctionLayoutStr);
117 }
118
GetMuidTabName() const119 std::string MIRSymbol::GetMuidTabName() const
120 {
121 if (!IsMuidTab()) {
122 return "";
123 }
124 size_t idx = GetName().find(kFileNameSplitterStr);
125 return (idx != std::string::npos) ? GetName().substr(0, idx) : "";
126 }
127
IsMuidFuncDefTab() const128 bool MIRSymbol::IsMuidFuncDefTab() const
129 {
130 return StringUtils::StartsWith(GetName(), kMuidFuncDefTabPrefixStr);
131 }
132
IsMuidFuncDefOrigTab() const133 bool MIRSymbol::IsMuidFuncDefOrigTab() const
134 {
135 return StringUtils::StartsWith(GetName(), kMuidFuncDefOrigTabPrefixStr);
136 }
137
IsMuidFuncInfTab() const138 bool MIRSymbol::IsMuidFuncInfTab() const
139 {
140 return StringUtils::StartsWith(GetName(), kMuidFuncInfTabPrefixStr);
141 }
142
IsMuidFuncUndefTab() const143 bool MIRSymbol::IsMuidFuncUndefTab() const
144 {
145 return StringUtils::StartsWith(GetName(), kMuidFuncUndefTabPrefixStr);
146 }
147
IsMuidDataDefTab() const148 bool MIRSymbol::IsMuidDataDefTab() const
149 {
150 return StringUtils::StartsWith(GetName(), kMuidDataDefTabPrefixStr);
151 }
152
IsMuidDataDefOrigTab() const153 bool MIRSymbol::IsMuidDataDefOrigTab() const
154 {
155 return StringUtils::StartsWith(GetName(), kMuidDataDefOrigTabPrefixStr);
156 }
157
IsMuidDataUndefTab() const158 bool MIRSymbol::IsMuidDataUndefTab() const
159 {
160 return StringUtils::StartsWith(GetName(), kMuidDataUndefTabPrefixStr);
161 }
162
IsMuidFuncDefMuidTab() const163 bool MIRSymbol::IsMuidFuncDefMuidTab() const
164 {
165 return StringUtils::StartsWith(GetName(), kMuidFuncDefMuidTabPrefixStr);
166 }
167
IsMuidFuncUndefMuidTab() const168 bool MIRSymbol::IsMuidFuncUndefMuidTab() const
169 {
170 return StringUtils::StartsWith(GetName(), kMuidFuncUndefMuidTabPrefixStr);
171 }
172
IsMuidDataDefMuidTab() const173 bool MIRSymbol::IsMuidDataDefMuidTab() const
174 {
175 return StringUtils::StartsWith(GetName(), kMuidDataDefMuidTabPrefixStr);
176 }
177
IsMuidDataUndefMuidTab() const178 bool MIRSymbol::IsMuidDataUndefMuidTab() const
179 {
180 return StringUtils::StartsWith(GetName(), kMuidDataUndefMuidTabPrefixStr);
181 }
182
IsMuidFuncMuidIdxMuidTab() const183 bool MIRSymbol::IsMuidFuncMuidIdxMuidTab() const
184 {
185 return StringUtils::StartsWith(GetName(), kMuidFuncMuidIdxTabPrefixStr);
186 }
187
IsMuidRangeTab() const188 bool MIRSymbol::IsMuidRangeTab() const
189 {
190 return StringUtils::StartsWith(GetName(), kMuidRangeTabPrefixStr);
191 }
192
IsArrayClassCache() const193 bool MIRSymbol::IsArrayClassCache() const
194 {
195 return StringUtils::StartsWith(GetName(), kArrayClassCacheTable);
196 }
197
IsArrayClassCacheName() const198 bool MIRSymbol::IsArrayClassCacheName() const
199 {
200 return StringUtils::StartsWith(GetName(), kArrayClassCacheNameTable);
201 }
202
203 // mrt/maplert/include/mrt_classinfo.h
IsForcedGlobalClassinfo() const204 bool MIRSymbol::IsForcedGlobalClassinfo() const
205 {
206 return StringUtils::StartsWith(GetName(), "__cinf_Llibcore_2Freflect_2FGenericSignatureParser_3B");
207 }
208
IsClassInitBridge() const209 bool MIRSymbol::IsClassInitBridge() const
210 {
211 return StringUtils::StartsWith(GetName(), CLASS_INIT_BRIDGE_PREFIX_STR);
212 }
213
IsReflectionHashTabBucket() const214 bool MIRSymbol::IsReflectionHashTabBucket() const
215 {
216 return StringUtils::StartsWith(GetName(), kMuidClassMetadataBucketPrefixStr);
217 }
218
IsReflectionInfo() const219 bool MIRSymbol::IsReflectionInfo() const
220 {
221 return IsReflectionClassInfo() || IsReflectionClassInfoRO() || IsReflectionFieldsInfo() ||
222 IsReflectionFieldsInfoCompact() || IsReflectionMethodsInfo() || IsReflectionPrimitiveClassInfo() ||
223 IsReflectionSuperclassInfo() || IsReflectionMethodsInfoCompact();
224 }
225
IsReflectionFieldsInfo() const226 bool MIRSymbol::IsReflectionFieldsInfo() const
227 {
228 return StringUtils::StartsWith(GetName(), kFieldsInfoPrefixStr);
229 }
230
IsReflectionFieldsInfoCompact() const231 bool MIRSymbol::IsReflectionFieldsInfoCompact() const
232 {
233 return StringUtils::StartsWith(GetName(), kFieldsInfoCompactPrefixStr);
234 }
235
IsReflectionSuperclassInfo() const236 bool MIRSymbol::IsReflectionSuperclassInfo() const
237 {
238 return StringUtils::StartsWith(GetName(), SUPERCLASSINFO_PREFIX_STR);
239 }
240
IsReflectionFieldOffsetData() const241 bool MIRSymbol::IsReflectionFieldOffsetData() const
242 {
243 return StringUtils::StartsWith(GetName(), kFieldOffsetDataPrefixStr);
244 }
245
IsReflectionMethodAddrData() const246 bool MIRSymbol::IsReflectionMethodAddrData() const
247 {
248 return (GetName().find(kMethodAddrDataPrefixStr) == 0);
249 }
250
IsReflectionMethodSignature() const251 bool MIRSymbol::IsReflectionMethodSignature() const
252 {
253 return (GetName().find(kMethodSignaturePrefixStr) == 0);
254 }
255
IsReflectionClassInfo() const256 bool MIRSymbol::IsReflectionClassInfo() const
257 {
258 return StringUtils::StartsWith(GetName(), CLASSINFO_PREFIX_STR);
259 }
260
IsReflectionArrayClassInfo() const261 bool MIRSymbol::IsReflectionArrayClassInfo() const
262 {
263 return StringUtils::StartsWith(GetName(), kArrayClassInfoPrefixStr);
264 }
265
IsReflectionClassInfoPtr() const266 bool MIRSymbol::IsReflectionClassInfoPtr() const
267 {
268 return StringUtils::StartsWith(GetName(), kClassINfoPtrPrefixStr);
269 }
270
IsReflectionClassInfoRO() const271 bool MIRSymbol::IsReflectionClassInfoRO() const
272 {
273 return StringUtils::StartsWith(GetName(), CLASSINFO_RO_PREFIX_STR);
274 }
275
IsITabConflictInfo() const276 bool MIRSymbol::IsITabConflictInfo() const
277 {
278 return StringUtils::StartsWith(GetName(), ITAB_CONFLICT_PREFIX_STR);
279 }
280
IsVTabInfo() const281 bool MIRSymbol::IsVTabInfo() const
282 {
283 return StringUtils::StartsWith(GetName(), VTAB_PREFIX_STR);
284 }
285
IsITabInfo() const286 bool MIRSymbol::IsITabInfo() const
287 {
288 return StringUtils::StartsWith(GetName(), ITAB_PREFIX_STR);
289 }
290
IsReflectionPrimitiveClassInfo() const291 bool MIRSymbol::IsReflectionPrimitiveClassInfo() const
292 {
293 return StringUtils::StartsWith(GetName(), PRIMITIVECLASSINFO_PREFIX_STR);
294 }
295
IsReflectionMethodsInfo() const296 bool MIRSymbol::IsReflectionMethodsInfo() const
297 {
298 return StringUtils::StartsWith(GetName(), kMethodsInfoPrefixStr);
299 }
300
IsReflectionMethodsInfoCompact() const301 bool MIRSymbol::IsReflectionMethodsInfoCompact() const
302 {
303 return StringUtils::StartsWith(GetName(), kMethodsInfoCompactPrefixStr);
304 }
305
IsPrimordialObject() const306 bool MIRSymbol::IsPrimordialObject() const
307 {
308 return IsReflectionClassInfo() || IsReflectionPrimitiveClassInfo();
309 }
310
IsGctibSym() const311 bool MIRSymbol::IsGctibSym() const
312 {
313 return StringUtils::StartsWith(GetName(), GCTIB_PREFIX_STR);
314 }
315
316 // [Note]
317 // Some symbols are ignored by reference counting as they represent objects not managed by us. These include
318 // string-based exact comparison for "current_vptr", "vtabptr", "itabptr", "funcptr", "env_ptr", "retvar_stubfunc".
319 GStrIdx MIRSymbol::reflectClassNameIdx;
320 GStrIdx MIRSymbol::reflectMethodNameIdx;
321 GStrIdx MIRSymbol::reflectFieldNameIdx;
IgnoreRC() const322 bool MIRSymbol::IgnoreRC() const
323 {
324 if (isDeleted || GetAttr(ATTR_rcunowned)) {
325 return true;
326 }
327 const std::string &name = GetName();
328 // ignore %current_vptr, %vtabptr, %itabptr, %funcptr, %env_ptr
329 if (name == "current_vptr" || name == "vtabptr" || name == "itabptr" || name == "funcptr" || name == "env_ptr" ||
330 name == "retvar_stubfunc" || name == "_dummy_stub_object_retval") {
331 return true;
332 }
333 if (IsReflectionInfo() || IsRegJNITab() || IsRegJNIFuncTab()) {
334 return true;
335 }
336 MIRType *type = GetType();
337 // only consider reference
338 if (type == nullptr || type->GetPrimType() != PTY_ref) {
339 return true;
340 }
341 if ((type->GetKind() == kTypeScalar) && (name != "__mapleRC__")) {
342 return true;
343 }
344 const auto *pType = static_cast<MIRPtrType *>(type);
345 GStrIdx strIdx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pType->GetPointedTyIdx())->GetNameStrIdx();
346 return strIdx == reflectClassNameIdx;
347 }
348
Dump(bool isLocal,int32 indent,bool suppressInit,const MIRSymbolTable * localsymtab) const349 void MIRSymbol::Dump(bool isLocal, int32 indent, bool suppressInit, const MIRSymbolTable *localsymtab) const
350 {
351 if (sKind == kStVar || sKind == kStFunc) {
352 srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
353 }
354 // exclude unused symbols, formal symbols and extern functions
355 if (GetStorageClass() == kScUnused || GetStorageClass() == kScFormal ||
356 (GetStorageClass() == kScExtern && sKind == kStFunc)) {
357 return;
358 }
359 if (GetIsImported() && !GetAppearsInCode()) {
360 return;
361 }
362 if (GetTyIdx() >= GlobalTables::GetTypeTable().GetTypeTable().size()) {
363 FATAL(kLncFatal, "valid maple_ir with illegal type");
364 }
365 if (GetStorageClass() == kScText && GetFunction() != nullptr) {
366 // without body
367 GetFunction()->Dump(true);
368 return;
369 }
370 const char *ids = isLocal ? "%" : "$";
371 PrintIndentation(indent);
372 if (isTmp) {
373 LogInfo::MapleLogger() << "tempvar ";
374 } else {
375 LogInfo::MapleLogger() << "var ";
376 }
377 LogInfo::MapleLogger() << ids << GetName() << " ";
378 if (GetStorageClass() == kScFstatic) {
379 LogInfo::MapleLogger() << "fstatic ";
380 } else if (GetStorageClass() == kScPstatic) {
381 LogInfo::MapleLogger() << "pstatic ";
382 } else if (GetStorageClass() == kScExtern) {
383 LogInfo::MapleLogger() << "extern ";
384 }
385 if (GetTyIdx() != 0u) {
386 GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetTyIdx())->Dump(indent + 1);
387 }
388 if (sectionAttr != UStrIdx(0)) {
389 LogInfo::MapleLogger() << " section (";
390 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(sectionAttr));
391 LogInfo::MapleLogger() << " )";
392 }
393 if (asmAttr != UStrIdx(0)) {
394 LogInfo::MapleLogger() << " asmattr (";
395 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(asmAttr));
396 LogInfo::MapleLogger() << " )";
397 }
398 typeAttrs.DumpAttributes();
399 if (GetStorageClass() == kScTypeInfoName || GetStorageClass() == kScTypeInfo ||
400 GetStorageClass() == kScTypeCxxAbi) {
401 LogInfo::MapleLogger() << '\n';
402 return;
403 }
404 if (IsConst() && !suppressInit && !(IsLiteral() && GetStorageClass() == kScExtern)) {
405 LogInfo::MapleLogger() << " = ";
406 GetKonst()->Dump(localsymtab);
407 }
408 LogInfo::MapleLogger() << '\n';
409 }
410
DumpAsLiteralVar() const411 void MIRSymbol::DumpAsLiteralVar() const
412 {
413 if (IsLiteral()) {
414 LogInfo::MapleLogger() << GetName();
415 }
416 }
417
Dump(bool isLocal,int32 indent,bool printDeleted,MIRFlavor flavor) const418 void MIRSymbolTable::Dump(bool isLocal, int32 indent, bool printDeleted, MIRFlavor flavor) const
419 {
420 size_t size = symbolTable.size();
421 for (size_t i = 0; i < size; ++i) {
422 MIRSymbol *symbol = symbolTable[i];
423 if (symbol == nullptr) {
424 continue;
425 }
426 if (!printDeleted && symbol->IsDeleted()) {
427 continue;
428 }
429 if (flavor == kFlavorLmbc && symbol->LMBCAllocateOffSpecialReg()) {
430 continue;
431 }
432 symbol->Dump(isLocal, indent, false /* suppressinit */, this);
433 }
434 }
435
CreateLabelWithPrefix(char c)436 LabelIdx MIRLabelTable::CreateLabelWithPrefix(char c)
437 {
438 LabelIdx labelIdx = labelTable.size();
439 std::ostringstream labelNameStream;
440 labelNameStream << "@" << c << labelIdx;
441 std::string labelName = labelNameStream.str();
442 GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(labelName);
443 labelTable.push_back(nameIdx);
444 strIdxToLabIdxMap[nameIdx] = labelIdx;
445 return labelIdx;
446 }
447
GetName(LabelIdx labelIdx) const448 const std::string &MIRLabelTable::GetName(LabelIdx labelIdx) const
449 {
450 CHECK_FATAL(labelIdx < labelTable.size(), "index out of range in MIRLabelTable::GetName");
451 return GlobalTables::GetStrTable().GetStringFromStrIdx(labelTable[labelIdx]);
452 }
453
AddToStringLabelMap(LabelIdx labelIdx)454 void MIRLabelTable::AddToStringLabelMap(LabelIdx labelIdx)
455 {
456 CHECK_FATAL(labelIdx < labelTable.size(), "index out of range in MIRLabelTable::AddToStringLabelMap");
457 if (labelTable[labelIdx] == 0u) {
458 // generate a label name based on lab_idx
459 std::ostringstream labelNameStream;
460 labelNameStream << "@" << labelIdx;
461 std::string labelName = labelNameStream.str();
462 labelTable[labelIdx] = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(labelName);
463 }
464 GStrIdx strIdx = labelTable[labelIdx];
465 strIdxToLabIdxMap[strIdx] = labelIdx;
466 }
467 } // namespace maple
468