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 #ifndef MAPLE_IR_INCLUDE_GLOBAL_TABLES_H
17 #define MAPLE_IR_INCLUDE_GLOBAL_TABLES_H
18 #include <iostream>
19 #include <memory>
20 #include <functional>
21 #include <mutex>
22 #include <shared_mutex>
23 #include "thread_env.h"
24 #include "mempool.h"
25 #include "mempool_allocator.h"
26 #include "types_def.h"
27 #include "prim_types.h"
28 #include "mir_module.h"
29 #include "namemangler.h"
30 #include "mir_type.h"
31 #include "mir_const.h"
32
33 namespace maple {
34 using TyIdxFieldAttrPair = std::pair<TyIdx, FieldAttrs>;
35 using FieldPair = std::pair<GStrIdx, TyIdxFieldAttrPair>;
36 using FieldVector = std::vector<FieldPair>;
37
38 class BinaryMplImport; // circular dependency exists, no other choice
39
40 // to facilitate the use of unordered_map
41 class TyIdxHash {
42 public:
operator()43 std::size_t operator()(const TyIdx &tyIdx) const
44 {
45 return std::hash<uint32> {}(tyIdx);
46 }
47 };
48
49 // to facilitate the use of unordered_map
50 class GStrIdxHash {
51 public:
operator()52 std::size_t operator()(const GStrIdx &gStrIdx) const
53 {
54 return std::hash<uint32> {}(gStrIdx);
55 }
56 };
57
58 // to facilitate the use of unordered_map
59 class UStrIdxHash {
60 public:
operator()61 std::size_t operator()(const UStrIdx &uStrIdx) const
62 {
63 return std::hash<uint32> {}(uStrIdx);
64 }
65 };
66
67 class IntConstKey {
68 friend class IntConstHash;
69 friend class IntConstCmp;
70
71 public:
IntConstKey(int64 v,TyIdx tyIdx)72 IntConstKey(int64 v, TyIdx tyIdx) : val(v), tyIdx(tyIdx) {}
~IntConstKey()73 virtual ~IntConstKey() {}
74
75 private:
76 int64 val;
77 TyIdx tyIdx;
78 };
79
80 class IntConstHash {
81 public:
operator()82 std::size_t operator()(const IntConstKey &key) const
83 {
84 return std::hash<int64> {}(key.val) ^ (std::hash<uint64> {}(static_cast<uint64>(key.tyIdx)) << 1);
85 }
86 };
87
88 class IntConstCmp {
89 public:
operator()90 bool operator()(const IntConstKey &lkey, const IntConstKey &rkey) const
91 {
92 return lkey.val == rkey.val && lkey.tyIdx == rkey.tyIdx;
93 }
94 };
95
96 class TypeTable {
97 friend BinaryMplImport;
98
99 public:
100 static MIRType *voidPtrType;
101
102 TypeTable();
103 TypeTable(const TypeTable &) = delete;
104 TypeTable &operator=(const TypeTable &) = delete;
105 ~TypeTable();
106
107 void Init();
108 void Reset();
109 void ReleaseTypes();
110
GetTypeTable()111 std::vector<MIRType *> &GetTypeTable()
112 {
113 return typeTable;
114 }
115
GetTypeTable()116 const std::vector<MIRType *> &GetTypeTable() const
117 {
118 return typeTable;
119 }
120
GetTypeHashTable()121 auto &GetTypeHashTable() const
122 {
123 return typeHashTable;
124 }
125
GetPtrTypeMap()126 auto &GetPtrTypeMap() const
127 {
128 return ptrTypeMap;
129 }
130
GetRefTypeMap()131 auto &GetRefTypeMap() const
132 {
133 return refTypeMap;
134 }
135
GetTypeFromTyIdx(TyIdx tyIdx)136 MIRType *GetTypeFromTyIdx(TyIdx tyIdx)
137 {
138 return const_cast<MIRType *>(const_cast<const TypeTable *>(this)->GetTypeFromTyIdx(tyIdx));
139 }
GetTypeFromTyIdx(TyIdx tyIdx)140 const MIRType *GetTypeFromTyIdx(TyIdx tyIdx) const
141 {
142 CHECK_FATAL(tyIdx < typeTable.size(), "array index out of range");
143 return typeTable.at(tyIdx);
144 }
145
GetTypeFromTyIdx(uint32 index)146 MIRType *GetTypeFromTyIdx(uint32 index) const
147 {
148 CHECK_FATAL(index < typeTable.size(), "array index out of range");
149 return typeTable.at(index);
150 }
151
GetPrimTypeFromTyIdx(const TyIdx & tyIdx)152 PrimType GetPrimTypeFromTyIdx(const TyIdx &tyIdx) const
153 {
154 CHECK_FATAL(tyIdx < typeTable.size(), "array index out of range");
155 return typeTable.at(tyIdx)->GetPrimType();
156 }
157
158 void SetTypeWithTyIdx(const TyIdx &tyIdx, MIRType &type);
159 MIRType *GetOrCreateMIRTypeNode(MIRType &ptype);
160
GetOrCreateMIRType(MIRType * pType)161 TyIdx GetOrCreateMIRType(MIRType *pType)
162 {
163 return GetOrCreateMIRTypeNode(*pType)->GetTypeIndex();
164 }
165
GetTypeTableSize()166 uint32 GetTypeTableSize() const
167 {
168 return static_cast<uint32>(typeTable.size());
169 }
170
171 // Get primtive types.
GetPrimType(PrimType primType)172 MIRType *GetPrimType(PrimType primType) const
173 {
174 DEBUG_ASSERT(primType < typeTable.size(), "array index out of range");
175 return typeTable.at(primType);
176 }
177
GetFloat()178 MIRType *GetFloat() const
179 {
180 DEBUG_ASSERT(PTY_f32 < typeTable.size(), "array index out of range");
181 return typeTable.at(PTY_f32);
182 }
183
GetDouble()184 MIRType *GetDouble() const
185 {
186 DEBUG_ASSERT(PTY_f64 < typeTable.size(), "array index out of range");
187 return typeTable.at(PTY_f64);
188 }
189
GetFloat128()190 MIRType *GetFloat128() const
191 {
192 DEBUG_ASSERT(PTY_f128 < typeTable.size(), "array index out of range");
193 return typeTable.at(PTY_f128);
194 }
195
GetUInt1()196 MIRType *GetUInt1() const
197 {
198 DEBUG_ASSERT(PTY_u1 < typeTable.size(), "array index out of range");
199 return typeTable.at(PTY_u1);
200 }
201
GetUInt8()202 MIRType *GetUInt8() const
203 {
204 DEBUG_ASSERT(PTY_u8 < typeTable.size(), "array index out of range");
205 return typeTable.at(PTY_u8);
206 }
207
GetInt8()208 MIRType *GetInt8() const
209 {
210 DEBUG_ASSERT(PTY_i8 < typeTable.size(), "array index out of range");
211 return typeTable.at(PTY_i8);
212 }
213
GetUInt16()214 MIRType *GetUInt16() const
215 {
216 DEBUG_ASSERT(PTY_u16 < typeTable.size(), "array index out of range");
217 return typeTable.at(PTY_u16);
218 }
219
GetInt16()220 MIRType *GetInt16() const
221 {
222 DEBUG_ASSERT(PTY_i16 < typeTable.size(), "array index out of range");
223 return typeTable.at(PTY_i16);
224 }
225
GetInt32()226 MIRType *GetInt32() const
227 {
228 DEBUG_ASSERT(PTY_i32 < typeTable.size(), "array index out of range");
229 return typeTable.at(PTY_i32);
230 }
231
GetUInt32()232 MIRType *GetUInt32() const
233 {
234 DEBUG_ASSERT(PTY_u32 < typeTable.size(), "array index out of range");
235 return typeTable.at(PTY_u32);
236 }
237
GetInt64()238 MIRType *GetInt64() const
239 {
240 DEBUG_ASSERT(PTY_i64 < typeTable.size(), "array index out of range");
241 return typeTable.at(PTY_i64);
242 }
243
GetUInt64()244 MIRType *GetUInt64() const
245 {
246 DEBUG_ASSERT(PTY_u64 < typeTable.size(), "array index out of range");
247 return typeTable.at(PTY_u64);
248 }
249
GetPtr()250 MIRType *GetPtr() const
251 {
252 DEBUG_ASSERT(PTY_ptr < typeTable.size(), "array index out of range");
253 return typeTable.at(PTY_ptr);
254 }
255
256 #ifdef USE_ARM32_MACRO
GetUIntType()257 MIRType *GetUIntType() const
258 {
259 DEBUG_ASSERT(PTY_u32 < typeTable.size(), "array index out of range");
260 return typeTable.at(PTY_u32);
261 }
262
GetPtrType()263 MIRType *GetPtrType() const
264 {
265 DEBUG_ASSERT(PTY_u32 < typeTable.size(), "array index out of range");
266 return typeTable.at(PTY_u32);
267 }
268 #else
GetUIntType()269 MIRType *GetUIntType() const
270 {
271 DEBUG_ASSERT(PTY_u64 < typeTable.size(), "array index out of range");
272 return typeTable.at(PTY_u64);
273 }
274
GetPtrType()275 MIRType *GetPtrType() const
276 {
277 DEBUG_ASSERT(PTY_ptr < typeTable.size(), "array index out of range");
278 return typeTable.at(PTY_ptr);
279 }
280 #endif
281
282 #ifdef USE_32BIT_REF
GetCompactPtr()283 MIRType *GetCompactPtr() const
284 {
285 DEBUG_ASSERT(PTY_u32 < typeTable.size(), "array index out of range");
286 return typeTable.at(PTY_u32);
287 }
288
289 #else
GetCompactPtr()290 MIRType *GetCompactPtr() const
291 {
292 DEBUG_ASSERT(PTY_u64 < typeTable.size(), "array index out of range");
293 return typeTable.at(PTY_u64);
294 }
295
296 #endif
GetRef()297 MIRType *GetRef() const
298 {
299 DEBUG_ASSERT(PTY_ref < typeTable.size(), "array index out of range");
300 return typeTable.at(PTY_ref);
301 }
302
GetAddr32()303 MIRType *GetAddr32() const
304 {
305 DEBUG_ASSERT(PTY_a32 < typeTable.size(), "array index out of range");
306 return typeTable.at(PTY_a32);
307 }
308
GetAddr64()309 MIRType *GetAddr64() const
310 {
311 DEBUG_ASSERT(PTY_a64 < typeTable.size(), "array index out of range");
312 return typeTable.at(PTY_a64);
313 }
314
GetVoid()315 MIRType *GetVoid() const
316 {
317 DEBUG_ASSERT(PTY_void < typeTable.size(), "array index out of range");
318 return typeTable.at(PTY_void);
319 }
320
321 #ifdef DYNAMICLANG
GetDynundef()322 MIRType *GetDynundef() const
323 {
324 DEBUG_ASSERT(PTY_dynundef < typeTable.size(), "array index out of range");
325 return typeTable.at(PTY_dynundef);
326 }
327
GetDynany()328 MIRType *GetDynany() const
329 {
330 DEBUG_ASSERT(PTY_dynany < typeTable.size(), "array index out of range");
331 return typeTable.at(PTY_dynany);
332 }
333
GetDyni32()334 MIRType *GetDyni32() const
335 {
336 DEBUG_ASSERT(PTY_dyni32 < typeTable.size(), "array index out of range");
337 return typeTable.at(PTY_dyni32);
338 }
339
GetDynf64()340 MIRType *GetDynf64() const
341 {
342 DEBUG_ASSERT(PTY_dynf64 < typeTable.size(), "array index out of range");
343 return typeTable.at(PTY_dynf64);
344 }
345
GetDynf32()346 MIRType *GetDynf32() const
347 {
348 DEBUG_ASSERT(PTY_dynf32 < typeTable.size(), "array index out of range");
349 return typeTable.at(PTY_dynf32);
350 }
351
GetDynstr()352 MIRType *GetDynstr() const
353 {
354 DEBUG_ASSERT(PTY_dynstr < typeTable.size(), "array index out of range");
355 return typeTable.at(PTY_dynstr);
356 }
357
GetDynobj()358 MIRType *GetDynobj() const
359 {
360 DEBUG_ASSERT(PTY_dynobj < typeTable.size(), "array index out of range");
361 return typeTable.at(PTY_dynobj);
362 }
363
GetDynbool()364 MIRType *GetDynbool() const
365 {
366 DEBUG_ASSERT(PTY_dynbool < typeTable.size(), "array index out of range");
367 return typeTable.at(PTY_dynbool);
368 }
369
370 #endif
GetUnknown()371 MIRType *GetUnknown() const
372 {
373 DEBUG_ASSERT(PTY_unknown < typeTable.size(), "array index out of range");
374 return typeTable.at(PTY_unknown);
375 }
376 // vector type
GetV4Int32()377 MIRType *GetV4Int32() const
378 {
379 DEBUG_ASSERT(PTY_v4i32 < typeTable.size(), "array index out of range");
380 return typeTable.at(PTY_v4i32);
381 }
382
GetV2Int32()383 MIRType *GetV2Int32() const
384 {
385 DEBUG_ASSERT(PTY_v2i32 < typeTable.size(), "array index out of range");
386 return typeTable.at(PTY_v2i32);
387 }
388
GetV4UInt32()389 MIRType *GetV4UInt32() const
390 {
391 DEBUG_ASSERT(PTY_v4u32 < typeTable.size(), "array index out of range");
392 return typeTable.at(PTY_v4u32);
393 }
GetV2UInt32()394 MIRType *GetV2UInt32() const
395 {
396 DEBUG_ASSERT(PTY_v2u32 < typeTable.size(), "array index out of range");
397 return typeTable.at(PTY_v2u32);
398 }
399
GetV4Int16()400 MIRType *GetV4Int16() const
401 {
402 DEBUG_ASSERT(PTY_v4i16 < typeTable.size(), "array index out of range");
403 return typeTable.at(PTY_v4i16);
404 }
GetV8Int16()405 MIRType *GetV8Int16() const
406 {
407 DEBUG_ASSERT(PTY_v8i16 < typeTable.size(), "array index out of range");
408 return typeTable.at(PTY_v8i16);
409 }
410
GetV4UInt16()411 MIRType *GetV4UInt16() const
412 {
413 DEBUG_ASSERT(PTY_v4u16 < typeTable.size(), "array index out of range");
414 return typeTable.at(PTY_v4u16);
415 }
GetV8UInt16()416 MIRType *GetV8UInt16() const
417 {
418 DEBUG_ASSERT(PTY_v8u16 < typeTable.size(), "array index out of range");
419 return typeTable.at(PTY_v8u16);
420 }
421
GetV8Int8()422 MIRType *GetV8Int8() const
423 {
424 DEBUG_ASSERT(PTY_v8i8 < typeTable.size(), "array index out of range");
425 return typeTable.at(PTY_v8i8);
426 }
GetV16Int8()427 MIRType *GetV16Int8() const
428 {
429 DEBUG_ASSERT(PTY_v16i8 < typeTable.size(), "array index out of range");
430 return typeTable.at(PTY_v16i8);
431 }
432
GetV8UInt8()433 MIRType *GetV8UInt8() const
434 {
435 DEBUG_ASSERT(PTY_v8u8 < typeTable.size(), "array index out of range");
436 return typeTable.at(PTY_v8u8);
437 }
GetV16UInt8()438 MIRType *GetV16UInt8() const
439 {
440 DEBUG_ASSERT(PTY_v16u8 < typeTable.size(), "array index out of range");
441 return typeTable.at(PTY_v16u8);
442 }
GetV2Int64()443 MIRType *GetV2Int64() const
444 {
445 DEBUG_ASSERT(PTY_v2i64 < typeTable.size(), "array index out of range");
446 return typeTable.at(PTY_v2i64);
447 }
GetV2UInt64()448 MIRType *GetV2UInt64() const
449 {
450 DEBUG_ASSERT(PTY_v2u64 < typeTable.size(), "array index out of range");
451 return typeTable.at(PTY_v2u64);
452 }
453
GetV2Float32()454 MIRType *GetV2Float32() const
455 {
456 DEBUG_ASSERT(PTY_v2f32 < typeTable.size(), "array index out of range");
457 return typeTable.at(PTY_v2f32);
458 }
GetV4Float32()459 MIRType *GetV4Float32() const
460 {
461 DEBUG_ASSERT(PTY_v4f32 < typeTable.size(), "array index out of range");
462 return typeTable.at(PTY_v4f32);
463 }
GetV2Float64()464 MIRType *GetV2Float64() const
465 {
466 DEBUG_ASSERT(PTY_v2f64 < typeTable.size(), "array index out of range");
467 return typeTable.at(PTY_v2f64);
468 }
469
470 // Get or Create derived types.
471 MIRType *GetOrCreatePointerType(const TyIdx &pointedTyIdx, PrimType primType = PTY_ptr,
472 const TypeAttrs &attrs = TypeAttrs());
473 MIRType *GetOrCreatePointerType(const MIRType &pointTo, PrimType primType = PTY_ptr,
474 const TypeAttrs &attrs = TypeAttrs());
475 const MIRType *GetPointedTypeIfApplicable(MIRType &type) const;
476 MIRType *GetPointedTypeIfApplicable(MIRType &type);
GetVoidPtr()477 MIRType *GetVoidPtr() const
478 {
479 DEBUG_ASSERT(voidPtrType != nullptr, "voidPtrType should not be null");
480 return voidPtrType;
481 }
482
483 void UpdateMIRType(const MIRType &pType, const TyIdx tyIdx);
484 MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint8 dim, const uint64 *sizeArray,
485 const TypeAttrs &attrs = TypeAttrs());
486 // For one dimention array
487 MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint64 size, const TypeAttrs &attrs = TypeAttrs());
488 MIRType *GetOrCreateFarrayType(const MIRType &elem);
489 MIRType *GetOrCreateJarrayType(const MIRType &elem);
490 MIRType *GetOrCreateFunctionType(const TyIdx &, const std::vector<TyIdx> &, const std::vector<TypeAttrs> &,
491 bool isVarg = false, const TypeAttrs &retAttrs = TypeAttrs());
GetOrCreateStructType(const std::string & name,const FieldVector & fields,const FieldVector & prntFields,MIRModule & module)492 MIRType *GetOrCreateStructType(const std::string &name, const FieldVector &fields, const FieldVector &prntFields,
493 MIRModule &module)
494 {
495 return GetOrCreateStructOrUnion(name, fields, prntFields, module);
496 }
497
GetOrCreateUnionType(const std::string & name,const FieldVector & fields,const FieldVector & parentFields,MIRModule & module)498 MIRType *GetOrCreateUnionType(const std::string &name, const FieldVector &fields, const FieldVector &parentFields,
499 MIRModule &module)
500 {
501 return GetOrCreateStructOrUnion(name, fields, parentFields, module, false);
502 }
503
GetOrCreateClassType(const std::string & name,MIRModule & module)504 MIRType *GetOrCreateClassType(const std::string &name, MIRModule &module)
505 {
506 return GetOrCreateClassOrInterface(name, module, true);
507 }
508
GetOrCreateInterfaceType(const std::string & name,MIRModule & module)509 MIRType *GetOrCreateInterfaceType(const std::string &name, MIRModule &module)
510 {
511 return GetOrCreateClassOrInterface(name, module, false);
512 }
513
514 void PushIntoFieldVector(FieldVector &fields, const std::string &name, const MIRType &type);
515 void AddFieldToStructType(MIRStructType &structType, const std::string &fieldName, const MIRType &fieldType);
516
517 TyIdx lastDefaultTyIdx;
518
519 private:
520 using MIRTypePtr = MIRType *;
521 struct Hash {
operatorHash522 size_t operator()(const MIRTypePtr &ty) const
523 {
524 return ty->GetHashIndex();
525 }
526 };
527
528 struct Equal {
operatorEqual529 bool operator()(const MIRTypePtr &tx, const MIRTypePtr &ty) const
530 {
531 return tx->EqualTo(*ty);
532 }
533 };
534
535 // create an entry in typeTable for the type node
CreateType(const MIRType & oldType)536 MIRType *CreateType(const MIRType &oldType)
537 {
538 MIRType *newType = oldType.CopyMIRTypeNode();
539 newType->SetTypeIndex(TyIdx(typeTable.size()));
540 typeTable.push_back(newType);
541 return newType;
542 }
543
PushNull()544 void PushNull()
545 {
546 typeTable.push_back(nullptr);
547 }
PopBack()548 void PopBack()
549 {
550 typeTable.pop_back();
551 }
552
553 void CreateMirTypeNodeAt(MIRType &pType, TyIdx tyIdxUsed, MIRModule *module, bool isObject, bool isIncomplete);
554 MIRType *CreateAndUpdateMirTypeNode(MIRType &pType);
555 MIRType *GetOrCreateStructOrUnion(const std::string &name, const FieldVector &fields,
556 const FieldVector &printFields, MIRModule &module, bool forStruct = true,
557 const TypeAttrs &attrs = TypeAttrs());
558 MIRType *GetOrCreateClassOrInterface(const std::string &name, MIRModule &module, bool forClass);
559
560 MIRType *CreateMirType(uint32 primTypeIdx) const;
561 void PutToHashTable(MIRType *mirType);
562
563 std::unordered_set<MIRTypePtr, Hash, Equal> typeHashTable;
564 std::unordered_map<TyIdx, TyIdx, TyIdxHash> ptrTypeMap;
565 std::unordered_map<TyIdx, TyIdx, TyIdxHash> refTypeMap;
566 std::vector<MIRType *> typeTable;
567 mutable std::shared_timed_mutex mtx;
568 };
569
570 class StrPtrHash {
571 public:
operator()572 size_t operator()(const std::string *str) const
573 {
574 return std::hash<std::string> {}(*str);
575 }
576
operator()577 size_t operator()(const std::u16string *str) const
578 {
579 return std::hash<std::u16string> {}(*str);
580 }
581 };
582
583 class StrPtrEqual {
584 public:
operator()585 bool operator()(const std::string *str1, const std::string *str2) const
586 {
587 return *str1 == *str2;
588 }
589
operator()590 bool operator()(const std::u16string *str1, const std::u16string *str2) const
591 {
592 return *str1 == *str2;
593 }
594 };
595
596 // T can be std::string or std::u16string
597 // U can be GStrIdx, UStrIdx, or U16StrIdx
598 template <typename T, typename U>
599 class StringTable {
600 public:
601 StringTable() = default;
602 StringTable(const StringTable &) = delete;
603 StringTable &operator=(const StringTable &) = delete;
604
~StringTable()605 ~StringTable()
606 {
607 ReleaseStrings();
608 }
609
Init()610 void Init()
611 {
612 // initialize 0th entry of stringTable with an empty string
613 T *ptr = new T;
614 stringTable.push_back(ptr);
615 }
616
Reset()617 void Reset()
618 {
619 ReleaseStrings();
620 stringTable.clear();
621 Init();
622 }
623
ReleaseStrings()624 void ReleaseStrings()
625 {
626 stringTableMap.clear();
627 for (auto it : stringTable) {
628 delete it;
629 }
630 }
631
GetStrIdxFromName(const T & str)632 U GetStrIdxFromName(const T &str) const
633 {
634 if (ThreadEnv::IsMeParallel()) {
635 std::shared_lock<std::shared_timed_mutex> lock(mtx);
636 auto it = stringTableMap.find(&str);
637 if (it == stringTableMap.end()) {
638 return U(0);
639 }
640 return it->second;
641 }
642 auto it = stringTableMap.find(&str);
643 if (it == stringTableMap.end()) {
644 return U(0);
645 }
646 return it->second;
647 }
648
GetOrCreateStrIdxFromName(const T & str)649 U GetOrCreateStrIdxFromName(const T &str)
650 {
651 U strIdx = GetStrIdxFromName(str);
652 if (strIdx == 0u) {
653 if (ThreadEnv::IsMeParallel()) {
654 std::unique_lock<std::shared_timed_mutex> lock(mtx);
655 strIdx.reset(stringTable.size());
656 T *newStr = new T(str);
657 stringTable.push_back(newStr);
658 stringTableMap[newStr] = strIdx;
659 return strIdx;
660 }
661 strIdx.reset(stringTable.size());
662 T *newStr = new T(str);
663 stringTable.push_back(newStr);
664 stringTableMap[newStr] = strIdx;
665 }
666 return strIdx;
667 }
668
StringTableSize()669 size_t StringTableSize() const
670 {
671 if (ThreadEnv::IsMeParallel()) {
672 std::shared_lock<std::shared_timed_mutex> lock(mtx);
673 return stringTable.size();
674 }
675 return stringTable.size();
676 }
677
GetStringFromStrIdx(U strIdx)678 const T &GetStringFromStrIdx(U strIdx) const
679 {
680 if (ThreadEnv::IsMeParallel()) {
681 std::shared_lock<std::shared_timed_mutex> lock(mtx);
682 DEBUG_ASSERT(strIdx < stringTable.size(), "array index out of range");
683 return *stringTable[strIdx];
684 }
685 DEBUG_ASSERT(strIdx < stringTable.size(), "array index out of range");
686 return *stringTable[strIdx];
687 }
688
GetStringFromStrIdx(uint32 idx)689 const T &GetStringFromStrIdx(uint32 idx) const
690 {
691 DEBUG_ASSERT(idx < stringTable.size(), "array index out of range");
692 return *stringTable[idx];
693 }
694
695 private:
696 std::vector<const T *> stringTable; // index is uint32
697 std::unordered_map<const T *, U, StrPtrHash, StrPtrEqual> stringTableMap;
698 mutable std::shared_timed_mutex mtx;
699 };
700
701 class FPConstTable {
702 public:
703 FPConstTable(const FPConstTable &p) = delete;
704 FPConstTable &operator=(const FPConstTable &p) = delete;
705 ~FPConstTable();
706
707 // get the const from floatConstTable or create a new one
708 MIRFloatConst *GetOrCreateFloatConst(float fval);
709 // get the const from doubleConstTable or create a new one
710 MIRDoubleConst *GetOrCreateDoubleConst(double fval);
711
Create()712 static std::unique_ptr<FPConstTable> Create()
713 {
714 auto p = std::make_unique<FPConstTable>();
715 p->PostInit();
716 return p;
717 }
718
719 private:
FPConstTable()720 FPConstTable() : floatConstTable(), doubleConstTable() {};
721 void PostInit();
722 MIRFloatConst *DoGetOrCreateFloatConst(float);
723 MIRDoubleConst *DoGetOrCreateDoubleConst(double);
724 MIRFloatConst *DoGetOrCreateFloatConstThreadSafe(float);
725 MIRDoubleConst *DoGetOrCreateDoubleConstThreadSafe(double);
726 std::shared_timed_mutex floatMtx;
727 std::shared_timed_mutex doubleMtx;
728 std::unordered_map<float, MIRFloatConst *> floatConstTable; // map float const value to the table;
729 std::unordered_map<double, MIRDoubleConst *> doubleConstTable; // map double const value to the table;
730 MIRFloatConst *nanFloatConst = nullptr;
731 MIRFloatConst *infFloatConst = nullptr;
732 MIRFloatConst *minusInfFloatConst = nullptr;
733 MIRFloatConst *minusZeroFloatConst = nullptr;
734 MIRDoubleConst *nanDoubleConst = nullptr;
735 MIRDoubleConst *infDoubleConst = nullptr;
736 MIRDoubleConst *minusInfDoubleConst = nullptr;
737 MIRDoubleConst *minusZeroDoubleConst = nullptr;
738
739 friend std::unique_ptr<FPConstTable> std::make_unique<FPConstTable>();
740 };
741
742 class IntConstTable {
743 public:
744 IntConstTable(const IntConstTable &p) = delete;
745 IntConstTable &operator=(const IntConstTable &p) = delete;
746 ~IntConstTable();
747
748 MIRIntConst *GetOrCreateIntConst(const IntVal &val, MIRType &type);
749 MIRIntConst *GetOrCreateIntConst(uint64 val, MIRType &type);
750
Create()751 static std::unique_ptr<IntConstTable> Create()
752 {
753 auto p = std::make_unique<IntConstTable>();
754 return p;
755 }
756
757 private:
758 IntConstTable() = default;
759 MIRIntConst *DoGetOrCreateIntConst(uint64 val, MIRType &type);
760 MIRIntConst *DoGetOrCreateIntConstTreadSafe(uint64 val, MIRType &type);
761 std::shared_timed_mutex mtx;
762 std::unordered_map<IntConstKey, MIRIntConst *, IntConstHash, IntConstCmp> intConstTable;
763
764 friend std::unique_ptr<IntConstTable> std::make_unique<IntConstTable>();
765 };
766
767 // STypeNameTable is only used to store class and interface types.
768 // Each module maintains its own MIRTypeNameTable.
769 class STypeNameTable {
770 public:
771 STypeNameTable() = default;
772 virtual ~STypeNameTable() = default;
773
Reset()774 void Reset()
775 {
776 gStrIdxToTyIdxMap.clear();
777 }
778
GetGStridxToTyidxMap()779 const std::unordered_map<GStrIdx, TyIdx, GStrIdxHash> &GetGStridxToTyidxMap() const
780 {
781 return gStrIdxToTyIdxMap;
782 }
783
GetTyIdxFromGStrIdx(GStrIdx idx)784 TyIdx GetTyIdxFromGStrIdx(GStrIdx idx) const
785 {
786 const auto it = gStrIdxToTyIdxMap.find(idx);
787 if (it == gStrIdxToTyIdxMap.cend()) {
788 return TyIdx(0);
789 }
790 return it->second;
791 }
792
SetGStrIdxToTyIdx(GStrIdx gStrIdx,TyIdx tyIdx)793 void SetGStrIdxToTyIdx(GStrIdx gStrIdx, TyIdx tyIdx)
794 {
795 gStrIdxToTyIdxMap[gStrIdx] = tyIdx;
796 }
797
798 private:
799 std::unordered_map<GStrIdx, TyIdx, GStrIdxHash> gStrIdxToTyIdxMap;
800 };
801
802 class FunctionTable {
803 public:
FunctionTable()804 FunctionTable()
805 {
806 Init();
807 }
808
809 virtual ~FunctionTable() = default;
810
Init()811 void Init()
812 {
813 // puIdx 0 is reserved
814 funcTable.push_back(nullptr);
815 }
816
Reset()817 void Reset()
818 {
819 funcTable.clear();
820 Init();
821 }
822
GetFuncTable()823 std::vector<MIRFunction *> &GetFuncTable()
824 {
825 return funcTable;
826 }
827
GetFunctionFromPuidx(PUIdx pIdx)828 MIRFunction *GetFunctionFromPuidx(PUIdx pIdx) const
829 {
830 CHECK_FATAL(pIdx < funcTable.size(), "Invalid puIdx");
831 return funcTable.at(pIdx);
832 }
833
SetFunctionItem(uint32 pIdx,MIRFunction * func)834 void SetFunctionItem(uint32 pIdx, MIRFunction *func)
835 {
836 CHECK_FATAL(pIdx < funcTable.size(), "Invalid puIdx");
837 funcTable[pIdx] = func;
838 }
839
840 private:
841 std::vector<MIRFunction *> funcTable; // index is PUIdx
842 };
843
844 class GSymbolTable {
845 public:
846 GSymbolTable();
847 GSymbolTable(const GSymbolTable &) = delete;
848 GSymbolTable &operator=(const GSymbolTable &) = delete;
849 ~GSymbolTable();
850
851 void Init();
852 void Reset();
853 void ReleaseSymbols();
854
GetModule()855 MIRModule *GetModule()
856 {
857 return module;
858 }
859
SetModule(MIRModule * m)860 void SetModule(MIRModule *m)
861 {
862 module = m;
863 }
864
IsValidIdx(size_t idx)865 bool IsValidIdx(size_t idx) const
866 {
867 return idx < symbolTable.size();
868 }
869
870 MIRSymbol *GetSymbolFromStidx(uint32 idx, bool checkFirst = false) const
871 {
872 if (checkFirst && idx >= symbolTable.size()) {
873 return nullptr;
874 }
875 DEBUG_ASSERT(IsValidIdx(idx), "symbol table index out of range");
876 return symbolTable[idx];
877 }
878
SetStrIdxStIdxMap(GStrIdx strIdx,StIdx stIdx)879 void SetStrIdxStIdxMap(GStrIdx strIdx, StIdx stIdx)
880 {
881 strIdxToStIdxMap[strIdx] = stIdx;
882 }
883
GetStIdxFromStrIdx(GStrIdx idx)884 StIdx GetStIdxFromStrIdx(GStrIdx idx) const
885 {
886 const auto it = strIdxToStIdxMap.find(idx);
887 if (it == strIdxToStIdxMap.cend()) {
888 return StIdx();
889 }
890 return it->second;
891 }
892
893 MIRSymbol *GetSymbolFromStrIdx(GStrIdx idx, bool checkFirst = false) const
894 {
895 return GetSymbolFromStidx(GetStIdxFromStrIdx(idx).Idx(), checkFirst);
896 }
897
GetTable()898 auto &GetTable()
899 {
900 return symbolTable;
901 }
902
GetSymbolTableSize()903 size_t GetSymbolTableSize() const
904 {
905 return symbolTable.size();
906 }
907
GetSymbol(uint32 idx)908 MIRSymbol *GetSymbol(uint32 idx) const
909 {
910 DEBUG_ASSERT(idx < symbolTable.size(), "array index out of range");
911 return symbolTable.at(idx);
912 }
913
914 MIRSymbol *CreateSymbol(uint8 scopeID);
915 bool AddToStringSymbolMap(const MIRSymbol &st);
916 bool RemoveFromStringSymbolMap(const MIRSymbol &st);
917 void Dump(bool isLocal, int32 indent = 0) const;
918
919 private:
920 MIRModule *module = nullptr;
921 // hash table mapping string index to st index
922 std::unordered_map<GStrIdx, StIdx, GStrIdxHash> strIdxToStIdxMap;
923 std::vector<MIRSymbol *> symbolTable; // map symbol idx to symbol node
924 };
925
926 class ConstPool {
927 public:
GetConstU16StringPool()928 std::unordered_map<std::u16string, MIRSymbol *> &GetConstU16StringPool()
929 {
930 return constU16StringPool;
931 }
932
Reset()933 void Reset()
934 {
935 constMap.clear();
936 importedLiteralNames.clear();
937 constU16StringPool.clear();
938 }
939
InsertConstPool(GStrIdx strIdx,MIRConst * cst)940 void InsertConstPool(GStrIdx strIdx, MIRConst *cst)
941 {
942 (void)constMap.emplace(strIdx, cst);
943 }
944
GetConstFromPool(GStrIdx strIdx)945 MIRConst *GetConstFromPool(GStrIdx strIdx)
946 {
947 return constMap[strIdx];
948 }
949
PutLiteralNameAsImported(GStrIdx gIdx)950 void PutLiteralNameAsImported(GStrIdx gIdx)
951 {
952 (void)importedLiteralNames.insert(gIdx);
953 }
954
LookUpLiteralNameFromImported(GStrIdx gIdx)955 bool LookUpLiteralNameFromImported(GStrIdx gIdx)
956 {
957 return importedLiteralNames.find(gIdx) != importedLiteralNames.end();
958 }
959
960 protected:
961 std::unordered_map<GStrIdx, MIRConst *, GStrIdxHash> constMap;
962 std::set<GStrIdx> importedLiteralNames;
963
964 private:
965 std::unordered_map<std::u16string, MIRSymbol *> constU16StringPool;
966 };
967
968 class GlobalTables {
969 public:
970 static GlobalTables &GetGlobalTables();
971
GetStrTable()972 static StringTable<std::string, GStrIdx> &GetStrTable()
973 {
974 return globalTables.gStringTable;
975 }
976
GetUStrTable()977 static StringTable<std::string, UStrIdx> &GetUStrTable()
978 {
979 return globalTables.uStrTable;
980 }
981
GetU16StrTable()982 static StringTable<std::u16string, U16StrIdx> &GetU16StrTable()
983 {
984 return globalTables.u16StringTable;
985 }
986
GetTypeTable()987 static TypeTable &GetTypeTable()
988 {
989 return globalTables.typeTable;
990 }
991
GetFpConstTable()992 static FPConstTable &GetFpConstTable()
993 {
994 return *(globalTables.fpConstTablePtr);
995 }
996
GetTypeNameTable()997 static STypeNameTable &GetTypeNameTable()
998 {
999 return globalTables.typeNameTable;
1000 }
1001
GetFunctionTable()1002 static FunctionTable &GetFunctionTable()
1003 {
1004 return globalTables.functionTable;
1005 }
1006
GetGsymTable()1007 static GSymbolTable &GetGsymTable()
1008 {
1009 return globalTables.gSymbolTable;
1010 }
1011
GetConstPool()1012 static ConstPool &GetConstPool()
1013 {
1014 return globalTables.constPool;
1015 }
1016
GetIntConstTable()1017 static IntConstTable &GetIntConstTable()
1018 {
1019 return *(globalTables.intConstTablePtr);
1020 }
1021
Reset()1022 static void Reset()
1023 {
1024 globalTables.typeTable.Reset();
1025 globalTables.typeNameTable.Reset();
1026 globalTables.functionTable.Reset();
1027 globalTables.gSymbolTable.Reset();
1028 globalTables.constPool.Reset();
1029 globalTables.fpConstTablePtr = FPConstTable::Create();
1030 globalTables.intConstTablePtr = IntConstTable::Create();
1031 globalTables.gStringTable.Reset();
1032 globalTables.uStrTable.Reset();
1033 globalTables.u16StringTable.Reset();
1034 }
1035
1036 GlobalTables(const GlobalTables &globalTables) = delete;
1037 GlobalTables(const GlobalTables &&globalTables) = delete;
1038 GlobalTables &operator=(const GlobalTables &globalTables) = delete;
1039 GlobalTables &operator=(const GlobalTables &&globalTables) = delete;
1040
1041 private:
GlobalTables()1042 GlobalTables() : fpConstTablePtr(FPConstTable::Create()), intConstTablePtr(IntConstTable::Create())
1043 {
1044 gStringTable.Init();
1045 uStrTable.Init();
1046 u16StringTable.Init();
1047 }
1048 virtual ~GlobalTables() = default;
1049 static GlobalTables globalTables;
1050
1051 TypeTable typeTable;
1052 STypeNameTable typeNameTable;
1053 FunctionTable functionTable;
1054 GSymbolTable gSymbolTable;
1055 ConstPool constPool;
1056 std::unique_ptr<FPConstTable> fpConstTablePtr;
1057 std::unique_ptr<IntConstTable> intConstTablePtr;
1058 StringTable<std::string, GStrIdx> gStringTable;
1059 StringTable<std::string, UStrIdx> uStrTable;
1060 StringTable<std::u16string, U16StrIdx> u16StringTable;
1061 };
1062
GetTypeFromTyIdx(TyIdx idx)1063 inline MIRType &GetTypeFromTyIdx(TyIdx idx)
1064 {
1065 return *(GlobalTables::GetTypeTable().GetTypeFromTyIdx(idx));
1066 }
1067 } // namespace maple
1068 #endif // MAPLE_IR_INCLUDE_GLOBAL_TABLES_H
1069