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 MAPLEBE_INCLUDE_BE_BECOMMON_H
17 #define MAPLEBE_INCLUDE_BE_BECOMMON_H
18 /* C++ headers. */
19 #include <cstddef>
20 #include <utility>
21 /* Basic Maple-independent utility functions */
22 #include "common_utils.h"
23 /* MapleIR headers. */
24 #include "mir_nodes.h" /* maple_ir/include, for BaseNode */
25 #include "mir_type.h" /* maple_ir/include, for MIRType */
26 #include "mir_module.h" /* maple_ir/include, for mirModule */
27
28 namespace maplebe {
29 using namespace maple;
30
31 enum BitsPerByte : uint8 { kBitsPerByte = 8, kLog2BitsPerByte = 3 };
32
GetPointerBitSize()33 inline uint32 GetPointerBitSize()
34 {
35 return GetPointerSize() * kBitsPerByte;
36 }
37
38 class JClassFieldInfo {
39 public:
40 /* constructors */
JClassFieldInfo()41 JClassFieldInfo() : isRef(false), isUnowned(false), isWeak(false), offset(0) {}
42
JClassFieldInfo(bool isRef,bool isUnowned,bool isWeak,uint32 offset)43 JClassFieldInfo(bool isRef, bool isUnowned, bool isWeak, uint32 offset)
44 : isRef(isRef), isUnowned(isUnowned), isWeak(isWeak), offset(offset)
45 {
46 }
47
48 ~JClassFieldInfo() = default;
49
IsRef()50 bool IsRef() const
51 {
52 return isRef;
53 }
54
IsUnowned()55 bool IsUnowned() const
56 {
57 return isUnowned;
58 }
59
IsWeak()60 bool IsWeak() const
61 {
62 return isWeak;
63 }
64
GetOffset()65 uint32 GetOffset() const
66 {
67 return offset;
68 }
69
70 private:
71 bool isRef; /* used to generate object-map */
72 bool isUnowned; /* used to mark unowned fields for RC */
73 bool isWeak; /* used to mark weak fields for RC */
74 uint32 offset;
75 };
76
77 using JClassLayout = MapleVector<JClassFieldInfo>;
78
79 class BECommon {
80 public:
81 explicit BECommon(MIRModule &mod);
82
83 ~BECommon() = default;
84
85 void ComputeTypeSizesAligns(MIRType &type, uint8 align = 0);
86
87 void GenFieldOffsetMap(const std::string &className);
88
89 void GenFieldOffsetMap(MIRClassType &classType, FILE &outFile);
90
91 void GenObjSize(const MIRClassType &classType, FILE &outFile);
92
93 std::pair<int32, int32> GetFieldOffset(MIRStructType &structType, FieldID fieldID);
94
95 FieldInfo GetJClassFieldOffset(MIRStructType &classType, FieldID fieldID) const;
96
97 bool IsRefField(MIRStructType &structType, FieldID fieldID) const;
98
99 /* some class may has incomplete type definition. provide an interface to check them. */
HasJClassLayout(MIRClassType & klass)100 bool HasJClassLayout(MIRClassType &klass) const
101 {
102 return (jClassLayoutTable.find(&klass) != jClassLayoutTable.end());
103 }
104
GetJClassLayout(MIRClassType & klass)105 const JClassLayout &GetJClassLayout(MIRClassType &klass) const
106 {
107 return *(jClassLayoutTable.at(&klass));
108 }
109
110 void AddNewTypeAfterBecommon(uint32 oldTypeTableSize, uint32 newTypeTableSize);
111
112 void AddElementToJClassLayout(MIRClassType &klass, JClassFieldInfo info);
113
HasFuncReturnType(MIRFunction & func)114 bool HasFuncReturnType(MIRFunction &func) const
115 {
116 return (funcReturnType.find(&func) != funcReturnType.end());
117 }
118
GetFuncReturnType(MIRFunction & func)119 const TyIdx GetFuncReturnType(MIRFunction &func) const
120 {
121 return (funcReturnType.at(&func));
122 }
123
124 void AddElementToFuncReturnType(MIRFunction &func, const TyIdx tyIdx);
125
126 MIRType *BeGetOrCreatePointerType(const MIRType &pointedType);
127
128 MIRType *BeGetOrCreateFunctionType(TyIdx tyIdx, const std::vector<TyIdx> &vecTy,
129 const std::vector<TypeAttrs> &vecAt);
130
131 BaseNode *GetAddressOfNode(const BaseNode &node);
132
133 bool CallIsOfAttr(FuncAttrKind attr, const StmtNode *narynode) const;
134
GetAddressPrimType()135 PrimType GetAddressPrimType() const
136 {
137 return GetLoweredPtrType();
138 }
139
140 /* update typeSizeTable and typeAlignTable when new type is created */
UpdateTypeTable(MIRType & ty)141 void UpdateTypeTable(MIRType &ty)
142 {
143 if (!TyIsInSizeAlignTable(ty)) {
144 AddAndComputeSizeAlign(ty);
145 }
146 }
147
148 /* Global type table might be updated during lowering for C/C++. */
149 void FinalizeTypeTable(const MIRType &ty);
150
GetFieldIdxIncrement(const MIRType & ty)151 uint32 GetFieldIdxIncrement(const MIRType &ty) const
152 {
153 if (ty.GetKind() == kTypeClass) {
154 /* number of fields + 2 */
155 return static_cast<const MIRClassType &>(ty).GetFieldsSize() + 2;
156 } else if (ty.GetKind() == kTypeStruct) {
157 /* number of fields + 1 */
158 return static_cast<const MIRStructType &>(ty).GetFieldsSize() + 1;
159 }
160 return 1;
161 }
162
GetMIRModule()163 MIRModule &GetMIRModule() const
164 {
165 return mirModule;
166 }
167
GetTypeSize(uint32 idx)168 uint64 GetTypeSize(uint32 idx) const
169 {
170 return typeSizeTable.at(idx);
171 }
GetSizeOfTypeSizeTable()172 uint32 GetSizeOfTypeSizeTable() const
173 {
174 return typeSizeTable.size();
175 }
IsEmptyOfTypeSizeTable()176 bool IsEmptyOfTypeSizeTable() const
177 {
178 return typeSizeTable.empty();
179 }
SetTypeSize(uint32 idx,uint64 value)180 void SetTypeSize(uint32 idx, uint64 value)
181 {
182 typeSizeTable.at(idx) = value;
183 }
AddTypeSize(uint64 value)184 void AddTypeSize(uint64 value)
185 {
186 typeSizeTable.emplace_back(value);
187 }
188
AddTypeSizeAndAlign(const TyIdx tyIdx,uint64 value)189 void AddTypeSizeAndAlign(const TyIdx tyIdx, uint64 value)
190 {
191 if (typeSizeTable.size() == tyIdx) {
192 typeSizeTable.emplace_back(value);
193 typeAlignTable.emplace_back(value);
194 } else {
195 CHECK_FATAL(typeSizeTable.size() > tyIdx, "there are some types haven't set type size and align, %d");
196 }
197 }
198
GetTypeAlign(uint32 idx)199 uint8 GetTypeAlign(uint32 idx) const
200 {
201 return typeAlignTable.at(idx);
202 }
GetSizeOfTypeAlignTable()203 size_t GetSizeOfTypeAlignTable() const
204 {
205 return typeAlignTable.size();
206 }
IsEmptyOfTypeAlignTable()207 bool IsEmptyOfTypeAlignTable() const
208 {
209 return typeAlignTable.empty();
210 }
SetTypeAlign(uint32 idx,uint8 value)211 void SetTypeAlign(uint32 idx, uint8 value)
212 {
213 typeAlignTable.at(idx) = value;
214 }
AddTypeAlign(uint8 value)215 void AddTypeAlign(uint8 value)
216 {
217 typeAlignTable.emplace_back(value);
218 }
219
GetHasFlexibleArray(uint32 idx)220 bool GetHasFlexibleArray(uint32 idx) const
221 {
222 return typeHasFlexibleArray.at(idx);
223 }
SetHasFlexibleArray(uint32 idx,bool value)224 void SetHasFlexibleArray(uint32 idx, bool value)
225 {
226 typeHasFlexibleArray.at(idx) = value;
227 }
228
GetStructFieldCount(uint32 idx)229 FieldID GetStructFieldCount(uint32 idx) const
230 {
231 return structFieldCountTable.at(idx);
232 }
GetSizeOfStructFieldCountTable()233 uint32 GetSizeOfStructFieldCountTable() const
234 {
235 return structFieldCountTable.size();
236 }
SetStructFieldCount(uint32 idx,FieldID value)237 void SetStructFieldCount(uint32 idx, FieldID value)
238 {
239 structFieldCountTable.at(idx) = value;
240 }
AppendStructFieldCount(uint32 idx,FieldID value)241 void AppendStructFieldCount(uint32 idx, FieldID value)
242 {
243 structFieldCountTable.at(idx) += value;
244 }
245
246 private:
247 bool TyIsInSizeAlignTable(const MIRType &) const;
248 void AddAndComputeSizeAlign(MIRType &);
249 void ComputeStructTypeSizesAligns(MIRType &ty, const TyIdx &tyIdx);
250 void ComputeClassTypeSizesAligns(MIRType &ty, const TyIdx &tyIdx, uint8 align = 0);
251 void ComputeArrayTypeSizesAligns(MIRType &ty, const TyIdx &tyIdx);
252 void ComputeFArrayOrJArrayTypeSizesAligns(MIRType &ty, const TyIdx &tyIdx);
253
254 MIRModule &mirModule;
255 MapleVector<uint64> typeSizeTable; /* index is TyIdx */
256 MapleVector<uint8> typeAlignTable; /* index is TyIdx */
257 MapleVector<bool> typeHasFlexibleArray; /* struct with flexible array */
258 /*
259 * gives number of fields inside
260 * each struct inclusive of nested structs, for speeding up
261 * traversal for locating the field for a given fieldID
262 */
263 MapleVector<FieldID> structFieldCountTable;
264 /*
265 * a lookup table for class layout. the vector is indexed by field-id
266 */
267 MapleUnorderedMap<MIRClassType *, JClassLayout *> jClassLayoutTable;
268 MapleUnorderedMap<MIRFunction *, TyIdx> funcReturnType;
269 }; /* class BECommon */
270 } /* namespace maplebe */
271
272 #endif /* MAPLEBE_INCLUDE_BE_BECOMMON_H */
273