• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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