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 "mir_pragma.h"
17 #include "mir_nodes.h"
18 #include "mir_function.h"
19 #include "printing.h"
20 #include "maple_string.h"
21
22 namespace {
23 enum Status {
24 kStop = 0,
25 kStartWithSubvec = 1,
26 kNormalTypeStrEndWithSemicolon = 2,
27 kNormalTypeStrEndWithSubvecNeedsSemicolon = 3,
28 kEndWithSubvec = 4,
29 kIgnoreAndContinue = 5
30 };
31 }
32
33 namespace maple {
GetKind(PragmaValueType kind)34 static std::string GetKind(PragmaValueType kind)
35 {
36 switch (kind) {
37 case kValueByte:
38 return "i8";
39 case kValueShort:
40 return "i16";
41 case kValueChar:
42 return "u16";
43 case kValueInt:
44 return "i32";
45 case kValueLong:
46 return "i64";
47 case kValueFloat:
48 return "f32";
49 case kValueDouble:
50 return "f64";
51 case kValueMethodType:
52 return "retype";
53 case kValueMethodHandle:
54 return "ref";
55 case kValueString:
56 return "ptr";
57 case kValueType:
58 return "type";
59 case kValueField:
60 return "var";
61 case kValueMethod:
62 return "func";
63 case kValueEnum:
64 return "enum";
65 case kValueArray:
66 return "array";
67 case kValueAnnotation:
68 return "annotation";
69 case kValueNull:
70 return "const";
71 case kValueBoolean:
72 return "u1";
73 default:
74 return "unknown";
75 }
76 }
77
78 // status: 0 : unexpected char, stop
79 // 1 : < start subvec
80 // 2 : normal type str end with ';'
81 // 3 : normal type str end with '<' -- need append ';'
82 // 4 : > end subvec
83 // 5 : ; ignore and continue
84 //
85 // 2: Lfoofoofoofoo;xx 3: Lfoofoofoofoo<
86 // | | | |
87 // start end start end
GetTypeStr(const std::string & str,uint32 & start,uint32 & end,uint32 & status)88 static void GetTypeStr(const std::string &str, uint32 &start, uint32 &end, uint32 &status)
89 {
90 uint32 i = start;
91 status = kStop;
92 while (str[i] == '[') {
93 ++i;
94 }
95 start = i;
96 end = i;
97 switch (str[i]) {
98 case 'Z':
99 case 'B':
100 case 'S':
101 case 'C':
102 case 'I':
103 case 'J':
104 case 'F':
105 case 'D':
106 case 'V':
107 status = kNormalTypeStrEndWithSemicolon;
108 end = i + 1;
109 break;
110 case 'L':
111 case 'T':
112 while (i < str.length()) {
113 if (str[i] == ';') {
114 status = kNormalTypeStrEndWithSemicolon;
115 end = i + 1;
116 break;
117 } else if (str[i] == '<') {
118 status = kNormalTypeStrEndWithSubvecNeedsSemicolon;
119 end = i;
120 break;
121 } else {
122 ++i;
123 }
124 }
125 break;
126 case '<':
127 status = kStartWithSubvec;
128 end = i + 1;
129 break;
130 case '>':
131 status = kEndWithSubvec;
132 end = i + 1;
133 break;
134 case ';':
135 // continue cases
136 status = kIgnoreAndContinue;
137 end = i + 1;
138 break;
139 default:
140 // termination - reached unexpected char
141 end = i;
142 break;
143 }
144 }
145
GetPragmaElemFromSignature(const std::string & signature)146 MIRPragmaElement *MIRPragma::GetPragmaElemFromSignature(const std::string &signature)
147 {
148 if (signature.empty()) {
149 return nullptr;
150 }
151 std::stack<MIRPragmaElement *> elemStack;
152 MIRPragmaElement *elem = mod->GetMemPool()->New<MIRPragmaElement>(*mod);
153 elem->SetType(kValueArray);
154 elemStack.push(elem);
155 uint32 status = 0;
156 uint32 start = 0;
157 uint32 end = 0;
158 while (1) {
159 if (signature.size() <= start) {
160 break;
161 }
162 GetTypeStr(signature, start, end, status);
163 // status: 0:stop/1:start_subvec/2:normal/3:normal+';'/4:end_subvec/5:ignore_and_continue
164 switch (status) {
165 case kStop:
166 return elem;
167 case kStartWithSubvec: {
168 MIRPragmaElement *etmp = mod->GetMemPool()->New<MIRPragmaElement>(*mod);
169 etmp->SetType(kValueArray);
170 elemStack.top()->SubElemVecPushBack(etmp);
171 elemStack.push(etmp);
172 break;
173 }
174 case kNormalTypeStrEndWithSemicolon: {
175 MIRPragmaElement *etmp = mod->GetMemPool()->New<MIRPragmaElement>(*mod);
176 etmp->SetType(kValueType);
177 std::string typeStr = signature.substr(start, end - start);
178 etmp->SetU64Val(static_cast<uint64>(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(typeStr)));
179 elemStack.top()->SubElemVecPushBack(etmp);
180 break;
181 }
182 case kNormalTypeStrEndWithSubvecNeedsSemicolon: {
183 MIRPragmaElement *etmp = mod->GetMemPool()->New<MIRPragmaElement>(*mod);
184 etmp->SetType(kValueType);
185 std::string typeStr = signature.substr(start, end - start) + ";";
186 etmp->SetU64Val(static_cast<uint64>(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(typeStr)));
187 elemStack.top()->SubElemVecPushBack(etmp);
188 break;
189 }
190 case kEndWithSubvec:
191 if (elemStack.empty()) { // Invalid annotation signature format
192 return nullptr;
193 }
194 elemStack.pop();
195 break;
196 case kIgnoreAndContinue:
197 break;
198 default:
199 DEBUG_ASSERT(false, "unexpected status");
200 break;
201 }
202 start = end;
203 }
204 return elem;
205 }
206
Dump(int indent) const207 void MIRPragmaElement::Dump(int indent) const
208 {
209 constexpr int indentOffset = 2;
210 constexpr int floatPrec = 7;
211 constexpr int doublePrec = 16;
212 GStrIdx gStrIdx;
213 std::string str = GetKind(valueType);
214 switch (valueType) {
215 case kValueByte:
216 LogInfo::MapleLogger() << str << " " << val.i;
217 break;
218 case kValueShort:
219 LogInfo::MapleLogger() << str << " " << val.i;
220 break;
221 case kValueChar:
222 LogInfo::MapleLogger() << str << " " << val.u;
223 break;
224 case kValueInt:
225 LogInfo::MapleLogger() << str << " " << val.i;
226 break;
227 case kValueLong:
228 LogInfo::MapleLogger() << str << " " << val.j;
229 break;
230 case kValueFloat:
231 LogInfo::MapleLogger() << std::setiosflags(std::ios::scientific) << str << " "
232 << std::setprecision(floatPrec) << val.f << "f";
233 break;
234 case kValueDouble:
235 LogInfo::MapleLogger() << std::setiosflags(std::ios::scientific) << str << " "
236 << std::setprecision(doublePrec) << val.d;
237 break;
238 case kValueMethodType:
239 LogInfo::MapleLogger() << str << " $" << std::hex << "0x" << val.u << std::dec;
240 break;
241 case kValueMethodHandle:
242 LogInfo::MapleLogger() << str << " " << std::hex << "0x" << val.u << std::dec;
243 break;
244 case kValueString:
245 gStrIdx.reset(val.u);
246 LogInfo::MapleLogger() << str << " \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx) << "\"";
247 break;
248 case kValueType:
249 gStrIdx.reset(val.u);
250 LogInfo::MapleLogger() << str << " <$" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx) << ">";
251 break;
252 case kValueField:
253 gStrIdx.reset(val.u);
254 LogInfo::MapleLogger() << str << " @" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx);
255 break;
256 case kValueMethod:
257 gStrIdx.reset(val.u);
258 LogInfo::MapleLogger() << str << " &" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx);
259 break;
260 case kValueEnum:
261 gStrIdx.reset(val.u);
262 LogInfo::MapleLogger() << str << " " << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx);
263 break;
264 case kValueArray: {
265 size_t num = subElemVec.size();
266 LogInfo::MapleLogger() << "array [" << num;
267 if (num != 0) {
268 if (num > 1) {
269 LogInfo::MapleLogger() << ",\n";
270 } else {
271 LogInfo::MapleLogger() << ", ";
272 }
273 size_t i = 0;
274 while (i < num) {
275 if (num > 1) {
276 PrintIndentation(indent + indentOffset);
277 }
278 subElemVec[i]->Dump(indent + indentOffset);
279 if (i != num - 1) {
280 LogInfo::MapleLogger() << ",\n";
281 }
282 ++i;
283 }
284 }
285 LogInfo::MapleLogger() << "]";
286 break;
287 }
288 case kValueAnnotation: {
289 size_t num = subElemVec.size();
290 LogInfo::MapleLogger() << "annotation <$";
291 LogInfo::MapleLogger() << GlobalTables::GetStrTable().GetStringFromStrIdx(typeStrIdx) << "> [" << num;
292 if (num) {
293 if (num > 1) {
294 LogInfo::MapleLogger() << ",\n";
295 } else {
296 LogInfo::MapleLogger() << ", ";
297 }
298 size_t i = 0;
299 while (i < num) {
300 if (num > 1) {
301 PrintIndentation(indent + indentOffset);
302 }
303 LogInfo::MapleLogger()
304 << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(subElemVec[i]->nameStrIdx) << " ";
305 subElemVec[i]->Dump(indent + indentOffset);
306 if (i != num - 1) {
307 LogInfo::MapleLogger() << ",\n";
308 }
309 ++i;
310 }
311 }
312 LogInfo::MapleLogger() << "]";
313 break;
314 }
315 case kValueNull:
316 LogInfo::MapleLogger() << str << " nullptr";
317 break;
318 case kValueBoolean:
319 LogInfo::MapleLogger() << str << " " << val.u;
320 break;
321 }
322 }
323
Dump(int indent) const324 void MIRPragma::Dump(int indent) const
325 {
326 LogInfo::MapleLogger() << '\n';
327 PrintIndentation(indent);
328 LogInfo::MapleLogger() << "pragma " << static_cast<int>(visibility) << " ";
329 switch (pragmaKind) {
330 case kPragmaClass:
331 LogInfo::MapleLogger() << "class $";
332 break;
333 case kPragmaFunc:
334 LogInfo::MapleLogger() << "func &";
335 break;
336 case kPragmaField:
337 LogInfo::MapleLogger() << "var @";
338 break;
339 case kPragmaVar:
340 LogInfo::MapleLogger() << "var %";
341 break;
342 case kPragmaParam:
343 LogInfo::MapleLogger() << "param " << paramNum << " &";
344 break;
345 case kPragmaFuncExecptioni:
346 LogInfo::MapleLogger() << "func_ex &";
347 break;
348 case kPragmaFuncVar:
349 LogInfo::MapleLogger() << "func_var &";
350 break;
351 default:
352 DEBUG_ASSERT(false, "unexpected func kind");
353 break;
354 }
355 LogInfo::MapleLogger() << GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx) << " ";
356 GStrIdx gStrIdx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->GetNameStrIdx();
357 LogInfo::MapleLogger() << "<$" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx) << "> ";
358 if (tyIdxEx != 0u) {
359 MIRType *typeEx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdxEx);
360 LogInfo::MapleLogger() << " " << typeEx->GetMplTypeName() << " ";
361 }
362 LogInfo::MapleLogger() << "{";
363 for (size_t j = 0; j < elementVec.size(); ++j) {
364 LogInfo::MapleLogger() << '\n';
365 PrintIndentation(indent + 1);
366 MIRPragmaElement *e = elementVec[j];
367 gStrIdx = e->GetNameStrIdx();
368 LogInfo::MapleLogger() << "@" << GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx) << " ";
369 e->Dump(indent);
370 if (j != elementVec.size() - 1) {
371 LogInfo::MapleLogger() << ",";
372 }
373 }
374 LogInfo::MapleLogger() << "}";
375 }
376 } // namespace maple
377