1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "global_tables.h"
17 #include "mir_symbol.h"
18
19 #if MIR_FEATURE_FULL
20 namespace maple {
CreateMirType(uint32 primTypeIdx) const21 MIRType *TypeTable::CreateMirType(uint32 primTypeIdx) const
22 {
23 MIRTypeKind defaultKind = kTypeScalar;
24 auto primType = static_cast<PrimType>(primTypeIdx);
25 auto *mirType = new MIRType(defaultKind, primType);
26 return mirType;
27 }
28
TypeTable()29 TypeTable::TypeTable()
30 {
31 Init();
32 }
33
Init()34 void TypeTable::Init()
35 {
36 // enter the primitve types in type_table_
37 typeTable.push_back(static_cast<MIRType *>(nullptr));
38 DEBUG_ASSERT(typeTable.size() == static_cast<size_t>(PTY_void), "use PTY_void as the first index to type table");
39 uint32 primTypeIdx;
40 for (primTypeIdx = static_cast<uint32>(PTY_begin) + 1; primTypeIdx <= static_cast<uint32>(PTY_end); ++primTypeIdx) {
41 MIRType *type = CreateMirType(primTypeIdx);
42 type->SetTypeIndex(TyIdx {primTypeIdx});
43 typeTable.push_back(type);
44 PutToHashTable(type);
45 }
46 if (voidPtrType == nullptr) {
47 voidPtrType = GetOrCreatePointerType(*GetVoid(), PTY_ptr);
48 }
49 lastDefaultTyIdx.SetIdx(primTypeIdx);
50 }
51
Reset()52 void TypeTable::Reset()
53 {
54 ReleaseTypes();
55 typeHashTable.clear();
56 ptrTypeMap.clear();
57 refTypeMap.clear();
58 typeTable.clear();
59 Init();
60 }
61
ReleaseTypes()62 void TypeTable::ReleaseTypes()
63 {
64 for (auto index = static_cast<uint32>(PTY_void); index < typeTable.size(); ++index) {
65 delete typeTable[index];
66 typeTable[index] = nullptr;
67 }
68 voidPtrType = nullptr;
69 }
70
~TypeTable()71 TypeTable::~TypeTable()
72 {
73 ReleaseTypes();
74 }
75
PutToHashTable(MIRType * mirType)76 void TypeTable::PutToHashTable(MIRType *mirType)
77 {
78 (void)typeHashTable.insert(mirType);
79 }
80
CreateAndUpdateMirTypeNode(MIRType & pType)81 MIRType *TypeTable::CreateAndUpdateMirTypeNode(MIRType &pType)
82 {
83 MIRType *nType = pType.CopyMIRTypeNode();
84 nType->SetTypeIndex(TyIdx(typeTable.size()));
85 typeTable.push_back(nType);
86
87 if (pType.IsMIRPtrType()) {
88 auto &pty = static_cast<MIRPtrType &>(pType);
89 if (pty.GetTypeAttrs() == TypeAttrs()) {
90 if (pty.GetPrimType() != PTY_ref) {
91 ptrTypeMap[pty.GetPointedTyIdx()] = nType->GetTypeIndex();
92 } else {
93 refTypeMap[pty.GetPointedTyIdx()] = nType->GetTypeIndex();
94 }
95 } else {
96 (void)typeHashTable.insert(nType);
97 }
98 } else {
99 (void)typeHashTable.insert(nType);
100 }
101 return nType;
102 }
103
GetOrCreateMIRTypeNode(MIRType & pType)104 MIRType *TypeTable::GetOrCreateMIRTypeNode(MIRType &pType)
105 {
106 if (pType.IsMIRPtrType()) {
107 auto &type = static_cast<MIRPtrType &>(pType);
108 if (type.GetTypeAttrs() == TypeAttrs()) {
109 auto *pMap = (type.GetPrimType() != PTY_ref ? &ptrTypeMap : &refTypeMap);
110 auto *otherPMap = (type.GetPrimType() == PTY_ref ? &ptrTypeMap : &refTypeMap);
111 {
112 std::shared_lock<std::shared_timed_mutex> lock(mtx);
113 const auto it = pMap->find(type.GetPointedTyIdx());
114 if (it != pMap->end()) {
115 return GetTypeFromTyIdx(it->second);
116 }
117 }
118 std::unique_lock<std::shared_timed_mutex> lock(mtx);
119 CHECK_FATAL(!(type.GetPointedTyIdx().GetIdx() >= kPtyDerived && type.GetPrimType() == PTY_ref &&
120 otherPMap->find(type.GetPointedTyIdx()) != otherPMap->end()),
121 "GetOrCreateMIRType: ref pointed-to type %d has previous ptr occurrence",
122 type.GetPointedTyIdx().GetIdx());
123 return CreateAndUpdateMirTypeNode(pType);
124 }
125 }
126 {
127 std::shared_lock<std::shared_timed_mutex> lock(mtx);
128 const auto it = typeHashTable.find(&pType);
129 if (it != typeHashTable.end()) {
130 return *it;
131 }
132 }
133 std::unique_lock<std::shared_timed_mutex> lock(mtx);
134 return CreateAndUpdateMirTypeNode(pType);
135 }
136
137 MIRType *TypeTable::voidPtrType = nullptr;
138 // get or create a type that pointing to pointedTyIdx
GetOrCreatePointerType(const TyIdx & pointedTyIdx,PrimType primType,const TypeAttrs & attrs)139 MIRType *TypeTable::GetOrCreatePointerType(const TyIdx &pointedTyIdx, PrimType primType, const TypeAttrs &attrs)
140 {
141 MIRPtrType type(pointedTyIdx, primType);
142 type.SetTypeAttrs(attrs);
143 TyIdx tyIdx = GetOrCreateMIRType(&type);
144 DEBUG_ASSERT(tyIdx < typeTable.size(), "index out of range in TypeTable::GetOrCreatePointerType");
145 return typeTable.at(tyIdx);
146 }
147
GetOrCreatePointerType(const MIRType & pointTo,PrimType primType,const TypeAttrs & attrs)148 MIRType *TypeTable::GetOrCreatePointerType(const MIRType &pointTo, PrimType primType, const TypeAttrs &attrs)
149 {
150 return GetOrCreatePointerType(pointTo.GetTypeIndex(), primType, attrs);
151 }
152
GetOrCreateFunctionType(const TyIdx & retTyIdx,const std::vector<TyIdx> & vecType,const std::vector<TypeAttrs> & vecAttrs,bool isVarg,const TypeAttrs & retAttrs)153 MIRType *TypeTable::GetOrCreateFunctionType(const TyIdx &retTyIdx, const std::vector<TyIdx> &vecType,
154 const std::vector<TypeAttrs> &vecAttrs, bool isVarg,
155 const TypeAttrs &retAttrs)
156 {
157 MIRFuncType funcType(retTyIdx, vecType, vecAttrs, retAttrs);
158 if (isVarg) {
159 funcType.SetVarArgs();
160 }
161 TyIdx tyIdx = GetOrCreateMIRType(&funcType);
162 DEBUG_ASSERT(tyIdx < typeTable.size(), "index out of range in TypeTable::GetOrCreateFunctionType");
163 return typeTable.at(tyIdx);
164 }
165
PostInit()166 void FPConstTable::PostInit()
167 {
168 MIRType &typeFloat = *GlobalTables::GetTypeTable().GetPrimType(PTY_f32);
169 nanFloatConst = new MIRFloatConst(NAN, typeFloat);
170 infFloatConst = new MIRFloatConst(INFINITY, typeFloat);
171 minusInfFloatConst = new MIRFloatConst(-INFINITY, typeFloat);
172 minusZeroFloatConst = new MIRFloatConst(-0.0, typeFloat);
173 MIRType &typeDouble = *GlobalTables::GetTypeTable().GetPrimType(PTY_f64);
174 nanDoubleConst = new MIRDoubleConst(NAN, typeDouble);
175 infDoubleConst = new MIRDoubleConst(INFINITY, typeDouble);
176 minusInfDoubleConst = new MIRDoubleConst(-INFINITY, typeDouble);
177 minusZeroDoubleConst = new MIRDoubleConst(-0.0, typeDouble);
178 }
179
GetOrCreateIntConst(uint64 val,MIRType & type)180 MIRIntConst *IntConstTable::GetOrCreateIntConst(uint64 val, MIRType &type)
181 {
182 return DoGetOrCreateIntConst(val, type);
183 }
184
DoGetOrCreateIntConst(uint64 val,MIRType & type)185 MIRIntConst *IntConstTable::DoGetOrCreateIntConst(uint64 val, MIRType &type)
186 {
187 IntConstKey key(val, type.GetTypeIndex());
188 if (intConstTable.find(key) != intConstTable.end()) {
189 return intConstTable[key];
190 }
191 intConstTable[key] = new MIRIntConst(val, type);
192 return intConstTable[key];
193 }
194
~IntConstTable()195 IntConstTable::~IntConstTable()
196 {
197 for (auto pair : intConstTable) {
198 delete pair.second;
199 }
200 }
201
GetOrCreateFloatConst(float floatVal)202 MIRFloatConst *FPConstTable::GetOrCreateFloatConst(float floatVal)
203 {
204 if (std::isnan(floatVal)) {
205 return nanFloatConst;
206 }
207 if (std::isinf(floatVal)) {
208 return (floatVal < 0) ? minusInfFloatConst : infFloatConst;
209 }
210 if (floatVal == 0.0 && std::signbit(floatVal)) {
211 return minusZeroFloatConst;
212 }
213 return DoGetOrCreateFloatConst(floatVal);
214 }
215
DoGetOrCreateFloatConst(float floatVal)216 MIRFloatConst *FPConstTable::DoGetOrCreateFloatConst(float floatVal)
217 {
218 const auto it = floatConstTable.find(floatVal);
219 if (it != floatConstTable.cend()) {
220 return it->second;
221 }
222 // create a new one
223 auto *floatConst = new MIRFloatConst(floatVal, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx {PTY_f32}));
224 floatConstTable[floatVal] = floatConst;
225 return floatConst;
226 }
227
GetOrCreateDoubleConst(double doubleVal)228 MIRDoubleConst *FPConstTable::GetOrCreateDoubleConst(double doubleVal)
229 {
230 if (std::isnan(doubleVal)) {
231 return nanDoubleConst;
232 }
233 if (std::isinf(doubleVal)) {
234 return (doubleVal < 0) ? minusInfDoubleConst : infDoubleConst;
235 }
236 if (doubleVal == 0.0 && std::signbit(doubleVal)) {
237 return minusZeroDoubleConst;
238 }
239 return DoGetOrCreateDoubleConst(doubleVal);
240 }
241
DoGetOrCreateDoubleConst(double doubleVal)242 MIRDoubleConst *FPConstTable::DoGetOrCreateDoubleConst(double doubleVal)
243 {
244 const auto it = doubleConstTable.find(doubleVal);
245 if (it != doubleConstTable.cend()) {
246 return it->second;
247 }
248 // create a new one
249 auto *doubleConst =
250 new MIRDoubleConst(doubleVal, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast<TyIdx>(PTY_f64)));
251 doubleConstTable[doubleVal] = doubleConst;
252 return doubleConst;
253 }
254
~FPConstTable()255 FPConstTable::~FPConstTable()
256 {
257 delete nanFloatConst;
258 delete infFloatConst;
259 delete minusInfFloatConst;
260 delete minusZeroFloatConst;
261 delete nanDoubleConst;
262 delete infDoubleConst;
263 delete minusInfDoubleConst;
264 delete minusZeroDoubleConst;
265 for (const auto &floatConst : floatConstTable) {
266 delete floatConst.second;
267 }
268 for (const auto &doubleConst : doubleConstTable) {
269 delete doubleConst.second;
270 }
271 }
272
GSymbolTable()273 GSymbolTable::GSymbolTable()
274 {
275 Init();
276 }
277
Init()278 void GSymbolTable::Init()
279 {
280 symbolTable.push_back(static_cast<MIRSymbol *>(nullptr));
281 }
282
Reset()283 void GSymbolTable::Reset()
284 {
285 ReleaseSymbols();
286 symbolTable.clear();
287 strIdxToStIdxMap.clear();
288 Init();
289 }
290
ReleaseSymbols()291 void GSymbolTable::ReleaseSymbols()
292 {
293 for (MIRSymbol *symbol : symbolTable) {
294 delete symbol;
295 }
296 }
297
~GSymbolTable()298 GSymbolTable::~GSymbolTable()
299 {
300 ReleaseSymbols();
301 }
302
CreateSymbol(uint8 scopeID)303 MIRSymbol *GSymbolTable::CreateSymbol(uint8 scopeID)
304 {
305 auto *st = new MIRSymbol(symbolTable.size(), scopeID);
306 CHECK_FATAL(st != nullptr, "CreateSymbol failure");
307 symbolTable.push_back(st);
308 module->AddSymbol(st);
309 return st;
310 }
311
AddToStringSymbolMap(const MIRSymbol & st)312 bool GSymbolTable::AddToStringSymbolMap(const MIRSymbol &st)
313 {
314 GStrIdx strIdx = st.GetNameStrIdx();
315 if (strIdxToStIdxMap[strIdx].FullIdx() != 0) {
316 return false;
317 }
318 strIdxToStIdxMap[strIdx] = st.GetStIdx();
319 return true;
320 }
321
322 #ifdef ARK_LITECG_DEBUG
Dump(bool isLocal,int32 indent) const323 void GSymbolTable::Dump(bool isLocal, int32 indent) const
324 {
325 for (size_t i = 1; i < symbolTable.size(); ++i) {
326 const MIRSymbol *symbol = symbolTable[i];
327 if (symbol != nullptr) {
328 symbol->Dump(isLocal, indent);
329 }
330 }
331 }
332 #endif
333
334 GlobalTables GlobalTables::globalTables;
GetGlobalTables()335 GlobalTables &GlobalTables::GetGlobalTables()
336 {
337 return globalTables;
338 }
339 } // namespace maple
340 #endif // MIR_FEATURE_FULL
341