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