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 StringUtils::StartsWith(GetName(), kRegJNITabPrefixStr);
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
IsForcedGlobalFunc() const203 bool MIRSymbol::IsForcedGlobalFunc() const
204 {
205 return StringUtils::StartsWith(GetName(), kJavaLangClassStr) ||
206 StringUtils::StartsWith(GetName(), kReflectionClassesPrefixStr) ||
207 StringUtils::StartsWith(GetName(), "Ljava_2Fnio_2FDirectByteBuffer_3B_7C_3Cinit_3E_7C_28JI_29V");
208 }
209
210 // mrt/maplert/include/mrt_classinfo.h
IsForcedGlobalClassinfo() const211 bool MIRSymbol::IsForcedGlobalClassinfo() const
212 {
213 std::unordered_set<std::string> mrtUse {
214 #include "mrt_direct_classinfo_list.def"
215 };
216 return std::find(mrtUse.begin(), mrtUse.end(), GetName()) != mrtUse.end() ||
217 StringUtils::StartsWith(GetName(), "__cinf_Llibcore_2Freflect_2FGenericSignatureParser_3B");
218 }
219
IsClassInitBridge() const220 bool MIRSymbol::IsClassInitBridge() const
221 {
222 return StringUtils::StartsWith(GetName(), CLASS_INIT_BRIDGE_PREFIX_STR);
223 }
224
IsReflectionHashTabBucket() const225 bool MIRSymbol::IsReflectionHashTabBucket() const
226 {
227 return StringUtils::StartsWith(GetName(), kMuidClassMetadataBucketPrefixStr);
228 }
229
IsReflectionInfo() const230 bool MIRSymbol::IsReflectionInfo() const
231 {
232 return IsReflectionClassInfo() || IsReflectionClassInfoRO() || IsReflectionFieldsInfo() ||
233 IsReflectionFieldsInfoCompact() || IsReflectionMethodsInfo() || IsReflectionPrimitiveClassInfo() ||
234 IsReflectionSuperclassInfo() || IsReflectionMethodsInfoCompact();
235 }
236
IsReflectionFieldsInfo() const237 bool MIRSymbol::IsReflectionFieldsInfo() const
238 {
239 return StringUtils::StartsWith(GetName(), kFieldsInfoPrefixStr);
240 }
241
IsReflectionFieldsInfoCompact() const242 bool MIRSymbol::IsReflectionFieldsInfoCompact() const
243 {
244 return StringUtils::StartsWith(GetName(), kFieldsInfoCompactPrefixStr);
245 }
246
IsReflectionSuperclassInfo() const247 bool MIRSymbol::IsReflectionSuperclassInfo() const
248 {
249 return StringUtils::StartsWith(GetName(), SUPERCLASSINFO_PREFIX_STR);
250 }
251
IsReflectionFieldOffsetData() const252 bool MIRSymbol::IsReflectionFieldOffsetData() const
253 {
254 return StringUtils::StartsWith(GetName(), kFieldOffsetDataPrefixStr);
255 }
256
IsReflectionMethodAddrData() const257 bool MIRSymbol::IsReflectionMethodAddrData() const
258 {
259 return (GetName().find(kMethodAddrDataPrefixStr) == 0);
260 }
261
IsReflectionMethodSignature() const262 bool MIRSymbol::IsReflectionMethodSignature() const
263 {
264 return (GetName().find(kMethodSignaturePrefixStr) == 0);
265 }
266
IsReflectionClassInfo() const267 bool MIRSymbol::IsReflectionClassInfo() const
268 {
269 return StringUtils::StartsWith(GetName(), CLASSINFO_PREFIX_STR);
270 }
271
IsReflectionArrayClassInfo() const272 bool MIRSymbol::IsReflectionArrayClassInfo() const
273 {
274 return StringUtils::StartsWith(GetName(), kArrayClassInfoPrefixStr);
275 }
276
IsReflectionClassInfoPtr() const277 bool MIRSymbol::IsReflectionClassInfoPtr() const
278 {
279 return StringUtils::StartsWith(GetName(), kClassINfoPtrPrefixStr);
280 }
281
IsReflectionClassInfoRO() const282 bool MIRSymbol::IsReflectionClassInfoRO() const
283 {
284 return StringUtils::StartsWith(GetName(), CLASSINFO_RO_PREFIX_STR);
285 }
286
IsITabConflictInfo() const287 bool MIRSymbol::IsITabConflictInfo() const
288 {
289 return StringUtils::StartsWith(GetName(), ITAB_CONFLICT_PREFIX_STR);
290 }
291
IsVTabInfo() const292 bool MIRSymbol::IsVTabInfo() const
293 {
294 return StringUtils::StartsWith(GetName(), VTAB_PREFIX_STR);
295 }
296
IsITabInfo() const297 bool MIRSymbol::IsITabInfo() const
298 {
299 return StringUtils::StartsWith(GetName(), ITAB_PREFIX_STR);
300 }
301
IsReflectionPrimitiveClassInfo() const302 bool MIRSymbol::IsReflectionPrimitiveClassInfo() const
303 {
304 return StringUtils::StartsWith(GetName(), PRIMITIVECLASSINFO_PREFIX_STR);
305 }
306
IsReflectionMethodsInfo() const307 bool MIRSymbol::IsReflectionMethodsInfo() const
308 {
309 return StringUtils::StartsWith(GetName(), kMethodsInfoPrefixStr);
310 }
311
IsReflectionMethodsInfoCompact() const312 bool MIRSymbol::IsReflectionMethodsInfoCompact() const
313 {
314 return StringUtils::StartsWith(GetName(), kMethodsInfoCompactPrefixStr);
315 }
316
IsPrimordialObject() const317 bool MIRSymbol::IsPrimordialObject() const
318 {
319 return IsReflectionClassInfo() || IsReflectionPrimitiveClassInfo();
320 }
321
IsGctibSym() const322 bool MIRSymbol::IsGctibSym() const
323 {
324 return StringUtils::StartsWith(GetName(), GCTIB_PREFIX_STR);
325 }
326
327 // [Note]
328 // Some symbols are ignored by reference counting as they represent objects not managed by us. These include
329 // string-based exact comparison for "current_vptr", "vtabptr", "itabptr", "funcptr", "env_ptr", "retvar_stubfunc".
330 GStrIdx MIRSymbol::reflectClassNameIdx;
331 GStrIdx MIRSymbol::reflectMethodNameIdx;
332 GStrIdx MIRSymbol::reflectFieldNameIdx;
IgnoreRC() const333 bool MIRSymbol::IgnoreRC() const
334 {
335 if (isDeleted || GetAttr(ATTR_rcunowned)) {
336 return true;
337 }
338 const std::string &name = GetName();
339 // ignore %current_vptr, %vtabptr, %itabptr, %funcptr, %env_ptr
340 if (name == "current_vptr" || name == "vtabptr" || name == "itabptr" || name == "funcptr" || name == "env_ptr" ||
341 name == "retvar_stubfunc" || name == "_dummy_stub_object_retval") {
342 return true;
343 }
344 if (IsReflectionInfo() || IsRegJNITab() || IsRegJNIFuncTab()) {
345 return true;
346 }
347 MIRType *type = GetType();
348 // only consider reference
349 if (type == nullptr || type->GetPrimType() != PTY_ref) {
350 return true;
351 }
352 if ((type->GetKind() == kTypeScalar) && (name != "__mapleRC__")) {
353 return true;
354 }
355 // ignore ptr to types Ljava_2Flang_2FClass_3B,
356 // Ljava_2Flang_2Freflect_2FMethod_3B
357 const auto *pType = static_cast<MIRPtrType *>(type);
358 GStrIdx strIdx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pType->GetPointedTyIdx())->GetNameStrIdx();
359 if (reflectClassNameIdx == 0u) {
360 reflectClassNameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(
361 namemangler::GetInternalNameLiteral("Ljava_2Flang_2FClass_3B"));
362 }
363 return strIdx == reflectClassNameIdx;
364 }
365
Dump(bool isLocal,int32 indent,bool suppressInit,const MIRSymbolTable * localsymtab) const366 void MIRSymbol::Dump(bool isLocal, int32 indent, bool suppressInit, const MIRSymbolTable *localsymtab) const
367 {
368 if (sKind == kStVar || sKind == kStFunc) {
369 srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum);
370 }
371 // exclude unused symbols, formal symbols and extern functions
372 if (GetStorageClass() == kScUnused || GetStorageClass() == kScFormal ||
373 (GetStorageClass() == kScExtern && sKind == kStFunc)) {
374 return;
375 }
376 if (GetIsImported() && !GetAppearsInCode()) {
377 return;
378 }
379 if (GetTyIdx() >= GlobalTables::GetTypeTable().GetTypeTable().size()) {
380 FATAL(kLncFatal, "valid maple_ir with illegal type");
381 }
382 if (GetStorageClass() == kScText && GetFunction() != nullptr) {
383 // without body
384 GetFunction()->Dump(true);
385 return;
386 }
387 const char *ids = isLocal ? "%" : "$";
388 PrintIndentation(indent);
389 if (sKind == kStJavaClass) {
390 LogInfo::MapleLogger() << "javaclass ";
391 } else if (sKind == kStJavaInterface) {
392 LogInfo::MapleLogger() << "javainterface ";
393 } else if (isTmp) {
394 LogInfo::MapleLogger() << "tempvar ";
395 } else {
396 LogInfo::MapleLogger() << "var ";
397 }
398 LogInfo::MapleLogger() << ids << GetName() << " ";
399 if (GetStorageClass() == kScFstatic) {
400 LogInfo::MapleLogger() << "fstatic ";
401 } else if (GetStorageClass() == kScPstatic) {
402 LogInfo::MapleLogger() << "pstatic ";
403 } else if (GetStorageClass() == kScExtern) {
404 LogInfo::MapleLogger() << "extern ";
405 }
406 if (GetTyIdx() != 0u) {
407 GlobalTables::GetTypeTable().GetTypeFromTyIdx(GetTyIdx())->Dump(indent + 1);
408 }
409 if (sectionAttr != UStrIdx(0)) {
410 LogInfo::MapleLogger() << " section (";
411 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(sectionAttr));
412 LogInfo::MapleLogger() << " )";
413 }
414 if (asmAttr != UStrIdx(0)) {
415 LogInfo::MapleLogger() << " asmattr (";
416 PrintString(GlobalTables::GetUStrTable().GetStringFromStrIdx(asmAttr));
417 LogInfo::MapleLogger() << " )";
418 }
419 typeAttrs.DumpAttributes();
420 if (sKind == kStJavaClass || sKind == kStJavaInterface || GetStorageClass() == kScTypeInfoName ||
421 GetStorageClass() == kScTypeInfo || GetStorageClass() == kScTypeCxxAbi) {
422 LogInfo::MapleLogger() << '\n';
423 return;
424 }
425 if (IsConst() && !suppressInit && !(IsLiteral() && GetStorageClass() == kScExtern)) {
426 LogInfo::MapleLogger() << " = ";
427 GetKonst()->Dump(localsymtab);
428 }
429 LogInfo::MapleLogger() << '\n';
430 }
431
DumpAsLiteralVar() const432 void MIRSymbol::DumpAsLiteralVar() const
433 {
434 if (IsLiteral()) {
435 LogInfo::MapleLogger() << GetName();
436 }
437 }
438
439 const std::set<std::string> MIRSymbol::staticFinalBlackList {
440 "Ljava_2Flang_2FSystem_3B_7Cout",
441 "Ljava_2Flang_2FSystem_3B_7Cerr",
442 "Ljava_2Flang_2FSystem_3B_7Cin",
443 };
444
Dump(bool isLocal,int32 indent,bool printDeleted,MIRFlavor flavor) const445 void MIRSymbolTable::Dump(bool isLocal, int32 indent, bool printDeleted, MIRFlavor flavor) const
446 {
447 size_t size = symbolTable.size();
448 for (size_t i = 0; i < size; ++i) {
449 MIRSymbol *symbol = symbolTable[i];
450 if (symbol == nullptr) {
451 continue;
452 }
453 if (!printDeleted && symbol->IsDeleted()) {
454 continue;
455 }
456 if (flavor == kFlavorLmbc && symbol->LMBCAllocateOffSpecialReg()) {
457 continue;
458 }
459 symbol->Dump(isLocal, indent, false /* suppressinit */, this);
460 }
461 }
462
CreateLabelWithPrefix(char c)463 LabelIdx MIRLabelTable::CreateLabelWithPrefix(char c)
464 {
465 LabelIdx labelIdx = labelTable.size();
466 std::ostringstream labelNameStream;
467 labelNameStream << "@" << c << labelIdx;
468 std::string labelName = labelNameStream.str();
469 GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(labelName);
470 labelTable.push_back(nameIdx);
471 strIdxToLabIdxMap[nameIdx] = labelIdx;
472 return labelIdx;
473 }
474
GetName(LabelIdx labelIdx) const475 const std::string &MIRLabelTable::GetName(LabelIdx labelIdx) const
476 {
477 CHECK_FATAL(labelIdx < labelTable.size(), "index out of range in MIRLabelTable::GetName");
478 return GlobalTables::GetStrTable().GetStringFromStrIdx(labelTable[labelIdx]);
479 }
480
AddToStringLabelMap(LabelIdx labelIdx)481 void MIRLabelTable::AddToStringLabelMap(LabelIdx labelIdx)
482 {
483 CHECK_FATAL(labelIdx < labelTable.size(), "index out of range in MIRLabelTable::AddToStringLabelMap");
484 if (labelTable[labelIdx] == 0u) {
485 // generate a label name based on lab_idx
486 std::ostringstream labelNameStream;
487 labelNameStream << "@" << labelIdx;
488 std::string labelName = labelNameStream.str();
489 labelTable[labelIdx] = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(labelName);
490 }
491 GStrIdx strIdx = labelTable[labelIdx];
492 strIdxToLabIdxMap[strIdx] = labelIdx;
493 }
494 } // namespace maple
495