• 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 uint32 *sizeArray,
485                                        const TypeAttrs &attrs = TypeAttrs());
486     // For one dimention array
487     MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint32 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::unique_ptr<FPConstTable>(new 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 
740 class IntConstTable {
741 public:
742     IntConstTable(const IntConstTable &p) = delete;
743     IntConstTable &operator=(const IntConstTable &p) = delete;
744     ~IntConstTable();
745 
746     MIRIntConst *GetOrCreateIntConst(const IntVal &val, MIRType &type);
747     MIRIntConst *GetOrCreateIntConst(uint64 val, MIRType &type);
748 
Create()749     static std::unique_ptr<IntConstTable> Create()
750     {
751         auto p = std::unique_ptr<IntConstTable>(new IntConstTable());
752         return p;
753     }
754 
755 private:
756     IntConstTable() = default;
757     MIRIntConst *DoGetOrCreateIntConst(uint64 val, MIRType &type);
758     MIRIntConst *DoGetOrCreateIntConstTreadSafe(uint64 val, MIRType &type);
759     std::shared_timed_mutex mtx;
760     std::unordered_map<IntConstKey, MIRIntConst *, IntConstHash, IntConstCmp> intConstTable;
761 };
762 
763 // STypeNameTable is only used to store class and interface types.
764 // Each module maintains its own MIRTypeNameTable.
765 class STypeNameTable {
766 public:
767     STypeNameTable() = default;
768     virtual ~STypeNameTable() = default;
769 
Reset()770     void Reset()
771     {
772         gStrIdxToTyIdxMap.clear();
773     }
774 
GetGStridxToTyidxMap()775     const std::unordered_map<GStrIdx, TyIdx, GStrIdxHash> &GetGStridxToTyidxMap() const
776     {
777         return gStrIdxToTyIdxMap;
778     }
779 
GetTyIdxFromGStrIdx(GStrIdx idx)780     TyIdx GetTyIdxFromGStrIdx(GStrIdx idx) const
781     {
782         const auto it = gStrIdxToTyIdxMap.find(idx);
783         if (it == gStrIdxToTyIdxMap.cend()) {
784             return TyIdx(0);
785         }
786         return it->second;
787     }
788 
SetGStrIdxToTyIdx(GStrIdx gStrIdx,TyIdx tyIdx)789     void SetGStrIdxToTyIdx(GStrIdx gStrIdx, TyIdx tyIdx)
790     {
791         gStrIdxToTyIdxMap[gStrIdx] = tyIdx;
792     }
793 
794 private:
795     std::unordered_map<GStrIdx, TyIdx, GStrIdxHash> gStrIdxToTyIdxMap;
796 };
797 
798 class FunctionTable {
799 public:
FunctionTable()800     FunctionTable()
801     {
802         Init();
803     }
804 
805     virtual ~FunctionTable() = default;
806 
Init()807     void Init()
808     {
809         // puIdx 0 is reserved
810         funcTable.push_back(nullptr);
811     }
812 
Reset()813     void Reset()
814     {
815         funcTable.clear();
816         Init();
817     }
818 
GetFuncTable()819     std::vector<MIRFunction *> &GetFuncTable()
820     {
821         return funcTable;
822     }
823 
GetFunctionFromPuidx(PUIdx pIdx)824     MIRFunction *GetFunctionFromPuidx(PUIdx pIdx) const
825     {
826         CHECK_FATAL(pIdx < funcTable.size(), "Invalid puIdx");
827         return funcTable.at(pIdx);
828     }
829 
SetFunctionItem(uint32 pIdx,MIRFunction * func)830     void SetFunctionItem(uint32 pIdx, MIRFunction *func)
831     {
832         CHECK_FATAL(pIdx < funcTable.size(), "Invalid puIdx");
833         funcTable[pIdx] = func;
834     }
835 
836 private:
837     std::vector<MIRFunction *> funcTable;  // index is PUIdx
838 };
839 
840 class GSymbolTable {
841 public:
842     GSymbolTable();
843     GSymbolTable(const GSymbolTable &) = delete;
844     GSymbolTable &operator=(const GSymbolTable &) = delete;
845     ~GSymbolTable();
846 
847     void Init();
848     void Reset();
849     void ReleaseSymbols();
850 
GetModule()851     MIRModule *GetModule()
852     {
853         return module;
854     }
855 
SetModule(MIRModule * m)856     void SetModule(MIRModule *m)
857     {
858         module = m;
859     }
860 
IsValidIdx(size_t idx)861     bool IsValidIdx(size_t idx) const
862     {
863         return idx < symbolTable.size();
864     }
865 
866     MIRSymbol *GetSymbolFromStidx(uint32 idx, bool checkFirst = false) const
867     {
868         if (checkFirst && idx >= symbolTable.size()) {
869             return nullptr;
870         }
871         DEBUG_ASSERT(IsValidIdx(idx), "symbol table index out of range");
872         return symbolTable[idx];
873     }
874 
SetStrIdxStIdxMap(GStrIdx strIdx,StIdx stIdx)875     void SetStrIdxStIdxMap(GStrIdx strIdx, StIdx stIdx)
876     {
877         strIdxToStIdxMap[strIdx] = stIdx;
878     }
879 
GetStIdxFromStrIdx(GStrIdx idx)880     StIdx GetStIdxFromStrIdx(GStrIdx idx) const
881     {
882         const auto it = strIdxToStIdxMap.find(idx);
883         if (it == strIdxToStIdxMap.cend()) {
884             return StIdx();
885         }
886         return it->second;
887     }
888 
889     MIRSymbol *GetSymbolFromStrIdx(GStrIdx idx, bool checkFirst = false) const
890     {
891         return GetSymbolFromStidx(GetStIdxFromStrIdx(idx).Idx(), checkFirst);
892     }
893 
GetTable()894     auto &GetTable()
895     {
896         return symbolTable;
897     }
898 
GetSymbolTableSize()899     size_t GetSymbolTableSize() const
900     {
901         return symbolTable.size();
902     }
903 
GetSymbol(uint32 idx)904     MIRSymbol *GetSymbol(uint32 idx) const
905     {
906         DEBUG_ASSERT(idx < symbolTable.size(), "array index out of range");
907         return symbolTable.at(idx);
908     }
909 
910     MIRSymbol *CreateSymbol(uint8 scopeID);
911     bool AddToStringSymbolMap(const MIRSymbol &st);
912     bool RemoveFromStringSymbolMap(const MIRSymbol &st);
913     void Dump(bool isLocal, int32 indent = 0) const;
914 
915 private:
916     MIRModule *module = nullptr;
917     // hash table mapping string index to st index
918     std::unordered_map<GStrIdx, StIdx, GStrIdxHash> strIdxToStIdxMap;
919     std::vector<MIRSymbol *> symbolTable;  // map symbol idx to symbol node
920 };
921 
922 class ConstPool {
923 public:
GetConstU16StringPool()924     std::unordered_map<std::u16string, MIRSymbol *> &GetConstU16StringPool()
925     {
926         return constU16StringPool;
927     }
928 
Reset()929     void Reset()
930     {
931         constMap.clear();
932         importedLiteralNames.clear();
933         constU16StringPool.clear();
934     }
935 
InsertConstPool(GStrIdx strIdx,MIRConst * cst)936     void InsertConstPool(GStrIdx strIdx, MIRConst *cst)
937     {
938         (void)constMap.emplace(strIdx, cst);
939     }
940 
GetConstFromPool(GStrIdx strIdx)941     MIRConst *GetConstFromPool(GStrIdx strIdx)
942     {
943         return constMap[strIdx];
944     }
945 
PutLiteralNameAsImported(GStrIdx gIdx)946     void PutLiteralNameAsImported(GStrIdx gIdx)
947     {
948         (void)importedLiteralNames.insert(gIdx);
949     }
950 
LookUpLiteralNameFromImported(GStrIdx gIdx)951     bool LookUpLiteralNameFromImported(GStrIdx gIdx)
952     {
953         return importedLiteralNames.find(gIdx) != importedLiteralNames.end();
954     }
955 
956 protected:
957     std::unordered_map<GStrIdx, MIRConst *, GStrIdxHash> constMap;
958     std::set<GStrIdx> importedLiteralNames;
959 
960 private:
961     std::unordered_map<std::u16string, MIRSymbol *> constU16StringPool;
962 };
963 
964 class GlobalTables {
965 public:
966     static GlobalTables &GetGlobalTables();
967 
GetStrTable()968     static StringTable<std::string, GStrIdx> &GetStrTable()
969     {
970         return globalTables.gStringTable;
971     }
972 
GetUStrTable()973     static StringTable<std::string, UStrIdx> &GetUStrTable()
974     {
975         return globalTables.uStrTable;
976     }
977 
GetU16StrTable()978     static StringTable<std::u16string, U16StrIdx> &GetU16StrTable()
979     {
980         return globalTables.u16StringTable;
981     }
982 
GetTypeTable()983     static TypeTable &GetTypeTable()
984     {
985         return globalTables.typeTable;
986     }
987 
GetFpConstTable()988     static FPConstTable &GetFpConstTable()
989     {
990         return *(globalTables.fpConstTablePtr);
991     }
992 
GetTypeNameTable()993     static STypeNameTable &GetTypeNameTable()
994     {
995         return globalTables.typeNameTable;
996     }
997 
GetFunctionTable()998     static FunctionTable &GetFunctionTable()
999     {
1000         return globalTables.functionTable;
1001     }
1002 
GetGsymTable()1003     static GSymbolTable &GetGsymTable()
1004     {
1005         return globalTables.gSymbolTable;
1006     }
1007 
GetConstPool()1008     static ConstPool &GetConstPool()
1009     {
1010         return globalTables.constPool;
1011     }
1012 
GetIntConstTable()1013     static IntConstTable &GetIntConstTable()
1014     {
1015         return *(globalTables.intConstTablePtr);
1016     }
1017 
Reset()1018     static void Reset()
1019     {
1020         globalTables.typeTable.Reset();
1021         globalTables.typeNameTable.Reset();
1022         globalTables.functionTable.Reset();
1023         globalTables.gSymbolTable.Reset();
1024         globalTables.constPool.Reset();
1025         globalTables.fpConstTablePtr = FPConstTable::Create();
1026         globalTables.intConstTablePtr = IntConstTable::Create();
1027         globalTables.gStringTable.Reset();
1028         globalTables.uStrTable.Reset();
1029         globalTables.u16StringTable.Reset();
1030     }
1031 
1032     GlobalTables(const GlobalTables &globalTables) = delete;
1033     GlobalTables(const GlobalTables &&globalTables) = delete;
1034     GlobalTables &operator=(const GlobalTables &globalTables) = delete;
1035     GlobalTables &operator=(const GlobalTables &&globalTables) = delete;
1036 
1037 private:
GlobalTables()1038     GlobalTables() : fpConstTablePtr(FPConstTable::Create()), intConstTablePtr(IntConstTable::Create())
1039     {
1040         gStringTable.Init();
1041         uStrTable.Init();
1042         u16StringTable.Init();
1043     }
1044     virtual ~GlobalTables() = default;
1045     static GlobalTables globalTables;
1046 
1047     TypeTable typeTable;
1048     STypeNameTable typeNameTable;
1049     FunctionTable functionTable;
1050     GSymbolTable gSymbolTable;
1051     ConstPool constPool;
1052     std::unique_ptr<FPConstTable> fpConstTablePtr;
1053     std::unique_ptr<IntConstTable> intConstTablePtr;
1054     StringTable<std::string, GStrIdx> gStringTable;
1055     StringTable<std::string, UStrIdx> uStrTable;
1056     StringTable<std::u16string, U16StrIdx> u16StringTable;
1057 };
1058 
GetTypeFromTyIdx(TyIdx idx)1059 inline MIRType &GetTypeFromTyIdx(TyIdx idx)
1060 {
1061     return *(GlobalTables::GetTypeTable().GetTypeFromTyIdx(idx));
1062 }
1063 }  // namespace maple
1064 #endif  // MAPLE_IR_INCLUDE_GLOBAL_TABLES_H
1065