• 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 #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