• 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 <climits>
17 #include <cstdlib>
18 #include <sstream>
19 #include <fstream>
20 #include "mir_parser.h"
21 #include "mir_scope.h"
22 #include "mir_function.h"
23 #include "namemangler.h"
24 #include "opcode_info.h"
25 #include "mir_pragma.h"
26 #include "bin_mplt.h"
27 #include "option.h"
28 #include "clone.h"
29 #include "string_utils.h"
30 #include "debug_info.h"
31 
32 namespace {
33 using namespace maple;
34 constexpr char kLexerStringSp[] = "SP";
35 constexpr char kLexerStringFp[] = "FP";
36 constexpr char kLexerStringGp[] = "GP";
37 constexpr char kLexerStringThrownval[] = "thrownval";
38 constexpr char kLexerStringRetval[] = "retval";
39 const std::map<std::string, SpecialReg> pregMapIdx = {{kLexerStringSp, kSregSp},
40                                                       {kLexerStringFp, kSregFp},
41                                                       {kLexerStringGp, kSregGp},
42                                                       {kLexerStringThrownval, kSregThrownval},
43                                                       {kLexerStringRetval, kSregRetval0}};
44 
45 const std::map<TokenKind, PragmaKind> tkPragmaKind = {{TK_class, kPragmaClass},
46                                                       {TK_func, kPragmaFunc},
47                                                       {TK_var, kPragmaVar},
48                                                       {TK_param, kPragmaParam},
49                                                       {TK_func_ex, kPragmaFuncExecptioni},
50                                                       {TK_func_var, kPragmaFuncVar}};
51 const std::map<TokenKind, PragmaValueType> tkPragmaValType = {
52     {TK_i8, kValueByte},          {TK_i16, kValueShort},  {TK_u16, kValueChar},    {TK_i32, kValueInt},
53     {TK_i64, kValueLong},         {TK_f32, kValueFloat},  {TK_f64, kValueDouble},  {TK_retype, kValueMethodType},
54     {TK_ref, kValueMethodHandle}, {TK_ptr, kValueString}, {TK_type, kValueType},   {TK_var, kValueField},
55     {TK_func, kValueMethod},      {TK_enum, kValueEnum},  {TK_array, kValueArray}, {TK_annotation, kValueAnnotation},
56     {TK_const, kValueNull},       {TK_u1, kValueBoolean}};
57 }  // namespace
58 
59 namespace maple {
60 
CreateDummyFunction()61 MIRFunction *MIRParser::CreateDummyFunction()
62 {
63     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("__$$__");
64     MIRBuilder mirBuilder(&mod);
65     MIRSymbol *funcSt = mirBuilder.CreateSymbol(TyIdx(0), strIdx, kStFunc, kScUnused, nullptr, kScopeGlobal);
66     CHECK_FATAL(funcSt != nullptr, "Failed to create MIRSymbol");
67     // Don't add the function to the function table.
68     // It appears Storage class kScUnused is not honored.
69     MIRFunction *func = mirBuilder.CreateFunction(funcSt->GetStIdx(), false);
70     CHECK_FATAL(func != nullptr, "Failed to create MIRFunction");
71     func->SetPuidxOrigin(func->GetPuidx());
72     MIRType *returnType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_void));
73     func->SetReturnTyIdx(returnType->GetTypeIndex());
74     func->SetClassTyIdx(0U);
75     func->SetBaseClassFuncNames(strIdx);
76     funcSt->SetFunction(func);
77     return func;
78 }
79 
IsDelimitationTK(TokenKind tk) const80 bool MIRParser::IsDelimitationTK(TokenKind tk) const
81 {
82     switch (tk) {
83         case TK_rparen:
84         case TK_coma:
85             return true;
86         default:
87             return false;
88     }
89 }
90 
IsPowerOf2(uint64 num)91 inline bool IsPowerOf2(uint64 num)
92 {
93     if (num == 0) {
94         return false;
95     }
96     return (~(num - 1) & num) == num;
97 }
98 
GetOpFromToken(TokenKind tk) const99 Opcode MIRParser::GetOpFromToken(TokenKind tk) const
100 {
101     switch (tk) {
102 #define OPCODE(X, Y, Z, S) \
103     case TK_##X:           \
104         return OP_##X;
105 #include "opcodes.def"
106 #undef OPCODE
107         default:
108             return OP_undef;
109     }
110 }
111 
IsStatement(TokenKind tk) const112 bool MIRParser::IsStatement(TokenKind tk) const
113 {
114     if (tk == TK_LOC || tk == TK_ALIAS || tk == TK_SCOPE) {
115         return true;
116     }
117     Opcode op = GetOpFromToken(tk);
118     return kOpcodeInfo.IsStmt(op);
119 }
120 
GetPrimitiveType(TokenKind tk) const121 PrimType MIRParser::GetPrimitiveType(TokenKind tk) const
122 {
123 #define LOAD_ALGO_PRIMARY_TYPE
124     switch (tk) {
125 #define PRIMTYPE(P)                       \
126     case TK_##P: {                        \
127         if (tk == TK_ptr) {               \
128             return GetExactPtrPrimType(); \
129         }                                 \
130         return PTY_##P;                   \
131     }
132 #include "prim_types.def"
133 #undef PRIMTYPE
134         default:
135             return kPtyInvalid;
136     }
137 }
138 
GetIntrinsicID(TokenKind tk) const139 MIRIntrinsicID MIRParser::GetIntrinsicID(TokenKind tk) const
140 {
141     switch (tk) {
142         default:
143 #define DEF_MIR_INTRINSIC(P, NAME, INTRN_CLASS, RETURN_TYPE, ...) \
144     case TK_##P: {                                                \
145         return INTRN_##P;                                         \
146     }
147 #include "intrinsics.def"
148 #undef DEF_MIR_INTRINSIC
149     }
150 }
151 
Error(const std::string & str)152 void MIRParser::Error(const std::string &str)
153 {
154     std::stringstream strStream;
155     const std::string &lexName = lexer.GetName();
156     int curIdx = static_cast<int>(lexer.GetCurIdx()) - static_cast<int>(lexName.length()) + 1;
157     strStream << "line: " << lexer.GetLineNum() << ":" << curIdx << ":";
158     message += strStream.str();
159     message += str;
160     message += ": ";
161     message += "\n";
162     mod.GetDbgInfo()->SetErrPos(lexer.GetLineNum(), lexer.GetCurIdx());
163 }
164 
GetError()165 const std::string &MIRParser::GetError()
166 {
167     if (lexer.GetTokenKind() == TK_invalid) {
168         std::stringstream strStream;
169         strStream << "line: " << lexer.GetLineNum() << ":" << lexer.GetCurIdx() << ":";
170         message += strStream.str();
171         message += " invalid token\n";
172     }
173     return message;
174 }
175 
Warning(const std::string & str)176 void MIRParser::Warning(const std::string &str)
177 {
178     std::stringstream strStream;
179     const std::string &lexName = lexer.GetName();
180     int curIdx = static_cast<int>(lexer.GetCurIdx()) - static_cast<int>(lexName.length()) + 1;
181     strStream << "  >> warning line: " << lexer.GetLineNum() << ":" << curIdx << ":";
182     warningMessage += strStream.str();
183     warningMessage += str;
184     warningMessage += "\n";
185 }
186 
GetWarning() const187 const std::string &MIRParser::GetWarning() const
188 {
189     return warningMessage;
190 }
191 
ParseSpecialReg(PregIdx & pRegIdx)192 bool MIRParser::ParseSpecialReg(PregIdx &pRegIdx)
193 {
194     const std::string &lexName = lexer.GetName();
195     size_t lexSize = lexName.size();
196     size_t retValSize = strlen(kLexerStringRetval);
197     if (strncmp(lexName.c_str(), kLexerStringRetval, retValSize) == 0 && (lexSize > retValSize) &&
198         isdigit(lexName[retValSize])) {
199         int32 retValNo = lexName[retValSize] - '0';
200         for (size_t i = retValSize + 1; (i < lexSize) && isdigit(lexName[i]); ++i) {
201             retValNo = retValNo * 10 + lexName[i] - '0'; // 10 for decimal
202         }
203         pRegIdx = -kSregRetval0 - retValNo;
204         lexer.NextToken();
205         return true;
206     }
207 
208     auto it = pregMapIdx.find(lexName);
209     if (it != pregMapIdx.end()) {
210         pRegIdx = -(it->second);
211         lexer.NextToken();
212         return true;
213     }
214 
215     Error("unrecognized special register ");
216     return false;
217 }
218 
ParsePseudoReg(PrimType primType,PregIdx & pRegIdx)219 bool MIRParser::ParsePseudoReg(PrimType primType, PregIdx &pRegIdx)
220 {
221     uint32 pregNo = static_cast<uint32>(lexer.GetTheIntVal());
222     DEBUG_ASSERT(pregNo <= 0xffff, "preg number must be 16 bits");
223     MIRFunction *curfunc = mod.CurFunction();
224     pRegIdx = curfunc->GetPregTab()->EnterPregNo(pregNo, primType);
225     MIRPreg *preg = curfunc->GetPregTab()->PregFromPregIdx(pRegIdx);
226     if (primType != kPtyInvalid) {
227         if (preg->GetPrimType() != primType) {
228             if (IsAddress(preg->GetPrimType()) && IsAddress(primType)) {
229             } else {
230                 Error("inconsistent preg primitive type at ");
231                 return false;
232             }
233         }
234     }
235 
236     lexer.NextToken();
237     return true;
238 }
239 
CheckPrimAndDerivedType(TokenKind tokenKind,TyIdx & tyIdx)240 bool MIRParser::CheckPrimAndDerivedType(TokenKind tokenKind, TyIdx &tyIdx)
241 {
242     if (IsPrimitiveType(tokenKind)) {
243         return ParsePrimType(tyIdx);
244     }
245     return false;
246 }
247 
ParseType(TyIdx & tyIdx)248 bool MIRParser::ParseType(TyIdx &tyIdx)
249 {
250     TokenKind tk = lexer.GetTokenKind();
251     if (CheckPrimAndDerivedType(tk, tyIdx)) {
252         return true;
253     }
254     Error("token is not a type ");
255     return false;
256 }
257 
ParseFarrayType(TyIdx & arrayTyIdx)258 bool MIRParser::ParseFarrayType(TyIdx &arrayTyIdx)
259 {
260     TokenKind tokenKind = lexer.NextToken();
261     TyIdx tyIdx;
262     if (!CheckPrimAndDerivedType(tokenKind, tyIdx)) {
263         Error("unexpect token parsing flexible array element type ");
264         return false;
265     }
266     DEBUG_ASSERT(tyIdx != 0u, "error encountered parsing flexible array element type ");
267     if (mod.IsCharModule()) {
268         MIRJarrayType jarrayType(tyIdx);
269         arrayTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&jarrayType);
270     } else {
271         MIRFarrayType farrayType(tyIdx);
272         arrayTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&farrayType);
273     }
274     return true;
275 }
276 
ParseArrayType(TyIdx & arrayTyIdx)277 bool MIRParser::ParseArrayType(TyIdx &arrayTyIdx)
278 {
279     TokenKind tokenKind = lexer.GetTokenKind();
280     if (tokenKind != TK_lbrack) {
281         Error("expect [ for array type but get ");
282         return false;
283     }
284     std::vector<uint64> vec;
285     while (tokenKind == TK_lbrack) {
286         tokenKind = lexer.NextToken();
287         if (tokenKind == TK_rbrack && vec.empty()) {
288             break;
289         }
290         if (tokenKind != TK_intconst) {
291             Error("expect int value parsing array type after [ but get ");
292             return false;
293         }
294         int64 val = static_cast<int64>(lexer.GetTheIntVal());
295         if (val < 0) {
296             Error("expect array value >= 0 ");
297             return false;
298         }
299         vec.push_back(val);
300         if (lexer.NextToken() != TK_rbrack) {
301             Error("expect ] after int value parsing array type but get ");
302             return false;
303         }
304         tokenKind = lexer.NextToken();
305     }
306     if (tokenKind == TK_rbrack && vec.empty()) {
307         return ParseFarrayType(arrayTyIdx);
308     }
309     TyIdx tyIdx;
310     if (!CheckPrimAndDerivedType(tokenKind, tyIdx)) {
311         Error("unexpect token parsing array type after ] ");
312         return false;
313     }
314     DEBUG_ASSERT(tyIdx != 0u, "something wrong with parsing element type ");
315     MIRArrayType arrayType(tyIdx, vec);
316     if (!ParseTypeAttrs(arrayType.GetTypeAttrs())) {
317         Error("bad type attribute in pointer type specification");
318         return false;
319     }
320     arrayTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&arrayType);
321     return true;
322 }
323 
ParseBitFieldType(TyIdx & fieldTyIdx)324 bool MIRParser::ParseBitFieldType(TyIdx &fieldTyIdx)
325 {
326     if (lexer.GetTokenKind() != TK_colon) {
327         Error("expect : parsing field type but get ");
328         return false;
329     }
330     if (lexer.NextToken() != TK_intconst) {
331         Error("expect int const val parsing field type but get ");
332         return false;
333     }
334     DEBUG_ASSERT(lexer.GetTheIntVal() <= 0xFFU, "lexer.theIntVal is larger than max uint8 bitsize value.");
335     uint8 bitSize = static_cast<uint8>(lexer.GetTheIntVal()) & 0xFFU;
336     PrimType primType = GetPrimitiveType(lexer.NextToken());
337     if (primType == kPtyInvalid) {
338         Error("expect primitive type but get ");
339         return false;
340     }
341     if (!IsPrimitiveInteger(primType)) {
342         Error("syntax error bit field should be integer type but get ");
343         return false;
344     }
345     MIRBitFieldType bitFieldType(bitSize, primType);
346     fieldTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&bitFieldType);
347     lexer.NextToken();
348     return true;
349 }
350 
ParsePragmaElementForArray(MIRPragmaElement & elem)351 bool MIRParser::ParsePragmaElementForArray(MIRPragmaElement &elem)
352 {
353     TokenKind tk = lexer.GetTokenKind();
354     if (tk != TK_lbrack) {
355         Error("parsing pragma error: expecting [ but get ");
356         return false;
357     }
358     tk = lexer.NextToken();
359     if (tk != TK_intconst) {
360         Error("parsing pragma error: expecting int but get ");
361         return false;
362     }
363     int64 size = static_cast<int64>(lexer.GetTheIntVal());
364     tk = lexer.NextToken();
365     if (tk != TK_coma && size) {
366         Error("parsing pragma error: expecting , but get ");
367         return false;
368     }
369     for (int64 i = 0; i < size; ++i) {
370         auto *e0 = mod.GetMemPool()->New<MIRPragmaElement>(mod);
371         tk = lexer.NextToken();
372         elem.SubElemVecPushBack(e0);
373         tk = lexer.NextToken();
374         if (tk != TK_coma && tk != TK_rbrack) {
375             Error("parsing pragma error: expecting , or ] but get ");
376             return false;
377         }
378     }
379     return true;
380 }
381 
ParseClassType(TyIdx & styidx,const GStrIdx & strIdx)382 bool MIRParser::ParseClassType(TyIdx &styidx, const GStrIdx &strIdx)
383 {
384     MIRTypeKind tkind = (lexer.GetTokenKind() == TK_class) ? kTypeClass : kTypeClassIncomplete;
385     TyIdx parentTypeIdx(0);
386     if (lexer.NextToken() == TK_langle) {
387     }
388     MIRClassType classType(tkind, strIdx);
389     classType.SetParentTyIdx(parentTypeIdx);
390     // Bytecode file create a strtuct type with name, but donot check the type field.
391     MIRType *prevType = nullptr;
392     if (styidx != 0u) {
393         prevType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(styidx);
394     }
395     if (prevType != nullptr && prevType->GetKind() != kTypeByName) {
396         DEBUG_ASSERT(prevType->GetKind() == kTypeClass || prevType->IsIncomplete(), "type kind should be consistent.");
397         if (static_cast<MIRClassType *>(prevType)->IsIncomplete() && !(classType.IsIncomplete())) {
398             classType.SetNameStrIdx(prevType->GetNameStrIdx());
399             classType.SetTypeIndex(styidx);
400             GlobalTables::GetTypeTable().SetTypeWithTyIdx(styidx, *classType.CopyMIRTypeNode());
401         }
402     } else {
403         styidx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&classType);
404         // set up classTyIdx for methods
405         for (size_t i = 0; i < classType.GetMethods().size(); ++i) {
406             StIdx stIdx = classType.GetMethodsElement(i).first;
407             MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx());
408             DEBUG_ASSERT(st != NULL, "st is null");
409             DEBUG_ASSERT(st->GetSKind() == kStFunc, "unexpected st->sKind");
410             st->GetFunction()->SetClassTyIdx(styidx);
411         }
412         mod.AddClass(styidx);
413     }
414     lexer.NextToken();
415     return true;
416 }
417 
ParseInterfaceType(TyIdx & sTyIdx,const GStrIdx & strIdx)418 bool MIRParser::ParseInterfaceType(TyIdx &sTyIdx, const GStrIdx &strIdx)
419 {
420     MIRTypeKind tkind = (lexer.GetTokenKind() == TK_interface) ? kTypeInterface : kTypeInterfaceIncomplete;
421     std::vector<TyIdx> parents;
422     TokenKind tk = lexer.NextToken();
423     while (tk == TK_langle) {
424         TyIdx parentTypeIdx(0);
425         parents.push_back(parentTypeIdx);
426         tk = lexer.GetTokenKind();
427     }
428     MIRInterfaceType interfaceType(tkind, strIdx);
429     interfaceType.SetParentsTyIdx(parents);
430     // Bytecode file create a strtuct type with name, but donot check the type field.
431     if (sTyIdx != 0u) {
432         MIRType *prevType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(sTyIdx);
433         DEBUG_ASSERT(prevType->GetKind() == kTypeInterface || prevType->IsIncomplete(),
434                      "type kind should be consistent.");
435         if (static_cast<MIRInterfaceType *>(prevType)->IsIncomplete() && !(interfaceType.IsIncomplete())) {
436             interfaceType.SetNameStrIdx(prevType->GetNameStrIdx());
437             interfaceType.SetTypeIndex(sTyIdx);
438             GlobalTables::GetTypeTable().SetTypeWithTyIdx(sTyIdx, *interfaceType.CopyMIRTypeNode());
439         }
440     } else {
441         sTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&interfaceType);
442         // set up classTyIdx for methods
443         for (size_t i = 0; i < interfaceType.GetMethods().size(); ++i) {
444             StIdx stIdx = interfaceType.GetMethodsElement(i).first;
445             MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStidx(stIdx.Idx());
446             DEBUG_ASSERT(st != nullptr, "st is null");
447             DEBUG_ASSERT(st->GetSKind() == kStFunc, "unexpected st->sKind");
448             st->GetFunction()->SetClassTyIdx(sTyIdx);
449         }
450         mod.AddClass(sTyIdx);
451     }
452     lexer.NextToken();
453     return true;
454 }
455 
CheckAlignTk()456 bool MIRParser::CheckAlignTk()
457 {
458     if (lexer.NextToken() != TK_lparen) {
459         Error("unexpected token in alignment specification after ");
460         return false;
461     }
462     if (lexer.NextToken() != TK_intconst) {
463         Error("unexpected token in alignment specification after ");
464         return false;
465     }
466     if (!IsPowerOf2(lexer.GetTheIntVal())) {
467         Error("specified alignment must be power of 2 instead of ");
468         return false;
469     }
470     if (lexer.NextToken() != TK_rparen) {
471         Error("unexpected token in alignment specification after ");
472         return false;
473     }
474     return true;
475 }
476 
ParseAlignAttrs(TypeAttrs & tA)477 bool MIRParser::ParseAlignAttrs(TypeAttrs &tA)
478 {
479     if (lexer.GetTokenKind() != TK_align) {
480         Error("wrong TK kind taken from file");
481         return false;
482     }
483     if (!CheckAlignTk()) {
484         return false;
485     }
486     tA.SetAlign(lexer.GetTheIntVal());
487     return true;
488 }
489 
ParsePackAttrs()490 bool MIRParser::ParsePackAttrs()
491 {
492     if (lexer.GetTokenKind() != TK_pack) {
493         Error("wrong TK kind taken from file");
494         return false;
495     }
496     if (!CheckAlignTk()) {
497         return false;
498     }
499     return true;
500 }
501 
502 // for variable declaration type attribute specification
503 // it has also storage-class qualifier.
ParseVarTypeAttrs(MIRSymbol & st)504 bool MIRParser::ParseVarTypeAttrs(MIRSymbol &st)
505 {
506     do {
507         switch (lexer.GetTokenKind()) {
508 // parse attr without no content
509 #define TYPE_ATTR
510 #define NOCONTENT_ATTR
511 #define ATTR(X)               \
512     case TK_##X: {            \
513         st.SetAttr(ATTR_##X); \
514         break;                \
515     }
516 #include "all_attributes.def"
517 #undef ATTR
518 #undef TYPE_ATTR
519 #undef NOCONTENT_ATTR
520                 // parse attr with no content
521             case TK_align: {
522                 if (!ParseAlignAttrs(st.GetAttrs())) {
523                     return false;
524                 }
525                 break;
526             }
527             default:
528                 return true;
529         }  // switch
530         lexer.NextToken();
531     } while (true);
532 }
533 
534 // for non-variable type attribute specification.
ParseTypeAttrs(TypeAttrs & attrs)535 bool MIRParser::ParseTypeAttrs(TypeAttrs &attrs)
536 {
537     do {
538         switch (lexer.GetTokenKind()) {
539 // parse attr without no content
540 #define TYPE_ATTR
541 #define NOCONTENT_ATTR
542 #define ATTR(X)                  \
543     case TK_##X:                 \
544         attrs.SetAttr(ATTR_##X); \
545         break;
546 #include "all_attributes.def"
547 #undef ATTR
548 #undef TYPE_ATTR
549 #undef NOCONTENT_ATTR
550                 // parse attr with no content
551             case TK_align: {
552                 if (!ParseAlignAttrs(attrs)) {
553                     return false;
554                 }
555                 break;
556             }
557             case TK_pack: {
558                 attrs.SetAttr(ATTR_pack);
559                 if (!ParsePackAttrs()) {
560                     return false;
561                 }
562                 attrs.SetPack(static_cast<uint32>(lexer.GetTheIntVal()));
563                 break;
564             }
565             default:
566                 return true;
567         }  // switch
568         lexer.NextToken();
569     } while (true);
570 }
571 
ParseFieldAttrs(FieldAttrs & attrs)572 bool MIRParser::ParseFieldAttrs(FieldAttrs &attrs)
573 {
574     do {
575         switch (lexer.GetTokenKind()) {
576 // parse attr without no content
577 #define FIELD_ATTR
578 #define NOCONTENT_ATTR
579 #define ATTR(X)                     \
580     case TK_##X:                    \
581         attrs.SetAttr(FLDATTR_##X); \
582         break;
583 #include "all_attributes.def"
584 #undef ATTR
585 #undef NOCONTENT_ATTR
586 #undef FIELD_ATTR
587                 // parse attr with no content
588             case TK_align: {
589                 if (!CheckAlignTk()) {
590                     return false;
591                 }
592                 attrs.SetAlign(lexer.GetTheIntVal());
593                 break;
594             }
595             case TK_pack: {
596                 attrs.SetAttr(FLDATTR_pack);
597                 if (!ParsePackAttrs()) {
598                     return false;
599                 }
600                 break;
601             }
602             default:
603                 return true;
604         }  // switch
605         lexer.NextToken();
606     } while (true);
607 }
608 
ParseFuncAttrs(FuncAttrs & attrs)609 bool MIRParser::ParseFuncAttrs(FuncAttrs &attrs)
610 {
611     do {
612         FuncAttrKind attrKind;
613         TokenKind currentToken = lexer.GetTokenKind();
614         switch (currentToken) {
615 #define FUNC_ATTR
616 #define ATTR(X)                  \
617     case TK_##X: {               \
618         attrKind = FUNCATTR_##X; \
619         attrs.SetAttr(attrKind); \
620         break;                   \
621     }
622 #include "all_attributes.def"
623 #undef ATTR
624 #undef FUNC_ATTR
625             default:
626                 return true;
627         }  // switch
628         if (currentToken != TK_alias && currentToken != TK_section && currentToken != TK_constructor_priority &&
629             currentToken != TK_destructor_priority) {
630             lexer.NextToken();
631             continue;
632         }
633         if (lexer.NextToken() != TK_lparen) {
634             return false;
635         }
636         lexer.NextToken();
637         SetAttrContent(attrs, attrKind, lexer);
638         if (lexer.NextToken() != TK_rparen) {
639             return false;
640         }
641         lexer.NextToken();
642     } while (true);
643 }
644 
SetAttrContent(FuncAttrs & attrs,FuncAttrKind x,const MIRLexer & mirLexer)645 void MIRParser::SetAttrContent(FuncAttrs &attrs, FuncAttrKind x, const MIRLexer &mirLexer)
646 {
647     switch (x) {
648         case FUNCATTR_alias: {
649             attrs.SetAliasFuncName(mirLexer.GetName());
650             break;
651         }
652         case FUNCATTR_section: {
653             attrs.SetPrefixSectionName(mirLexer.GetName());
654             break;
655         }
656         case FUNCATTR_constructor_priority: {
657             attrs.SetConstructorPriority(static_cast<int32>(mirLexer.GetTheIntVal()));
658             break;
659         }
660         case FUNCATTR_destructor_priority: {
661             attrs.SetDestructorPriority(static_cast<int32>(mirLexer.GetTheIntVal()));
662             break;
663         }
664         default:
665             break;
666     }
667 }
668 
ParsePrimType(TyIdx & tyIdx)669 bool MIRParser::ParsePrimType(TyIdx &tyIdx)
670 {
671     PrimType primType = GetPrimitiveType(lexer.GetTokenKind());
672     if (primType == kPtyInvalid) {
673         tyIdx = TyIdx(0);
674         Error("ParsePrimType failed, invalid token");
675         return false;
676     }
677     lexer.NextToken();
678     tyIdx = GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(primType))->GetTypeIndex();
679     return true;
680 }
681 
ParseTypeParam(TyIdx & definedTyIdx)682 bool MIRParser::ParseTypeParam(TyIdx &definedTyIdx)
683 {
684     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
685     MIRTypeParam typeParm(strIdx);
686     definedTyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&typeParm);
687     lexer.NextToken();
688     return true;
689 }
690 
691 // parse the generic type instantiation vector enclosed inside braces; syntax
692 // is: { <type-param> = <real-type> [, <type-param> = <real-type>] }
693 // where the contents enclosed in [ and ] can occur 0 or more times
ParseGenericInstantVector(MIRInstantVectorType & insVecType)694 bool MIRParser::ParseGenericInstantVector(MIRInstantVectorType &insVecType)
695 {
696     TokenKind tokenKind;
697     TyIdx typeParmIdx;
698     do {
699         tokenKind = lexer.NextToken();  // skip the lbrace or comma
700         if (!ParseTypeParam(typeParmIdx)) {
701             Error("type parameter incorrectly specified in generic type/function instantiation at ");
702             return false;
703         }
704         tokenKind = lexer.GetTokenKind();
705         if (tokenKind != TK_eqsign) {
706             Error("missing = in generic type/function instantiation at ");
707             return false;
708         }
709         tokenKind = lexer.NextToken();  // skip the =
710         TyIdx realTyIdx;
711         if (!ParseType(realTyIdx)) {
712             Error("error parsing type in generic type/function instantiation at ");
713             return false;
714         }
715         insVecType.AddInstant(TypePair(typeParmIdx, realTyIdx));
716         tokenKind = lexer.GetTokenKind();
717         if (tokenKind == TK_rbrace) {
718             lexer.NextToken();  // skip the rbrace
719             return true;
720         }
721     } while (tokenKind == TK_coma);
722     Error("error parsing generic type/function instantiation at ");
723     return false;
724 }
725 
ParseStorageClass(MIRSymbol & symbol) const726 bool MIRParser::ParseStorageClass(MIRSymbol &symbol) const
727 {
728     TokenKind tk = lexer.GetTokenKind();
729     switch (tk) {
730         case TK_fstatic:
731             symbol.SetStorageClass(kScFstatic);
732             return true;
733         case TK_pstatic:
734             symbol.SetStorageClass(kScPstatic);
735             return true;
736         case TK_extern:
737             symbol.SetStorageClass(kScExtern);
738             return true;
739         default:
740             break;
741     }
742     return false;
743 }
744 
ParseDeclareReg(MIRSymbol & symbol,const MIRFunction & func)745 bool MIRParser::ParseDeclareReg(MIRSymbol &symbol, const MIRFunction &func)
746 {
747     TokenKind tk = lexer.GetTokenKind();
748     // i.e, reg %1 u1
749     if (tk != TK_reg) {  // reg
750         Error("expect reg bug get ");
751         return false;
752     }
753     TokenKind regNumTK = lexer.NextToken();
754     if (regNumTK != TK_preg) {
755         Error("expect preg but get");
756         return false;
757     }
758     uint32 thePRegNO = static_cast<uint32>(lexer.GetTheIntVal());
759     lexer.NextToken();
760     // parse ty
761     TyIdx tyIdx(0);
762     if (!ParseType(tyIdx)) {
763         Error("ParseDeclarePreg failed while parsing the type");
764         return false;
765     }
766     DEBUG_ASSERT(tyIdx > 0u, "parse declare preg failed");
767     if (GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->GetKind() == kTypeByName) {
768         Error("type in var declaration cannot be forward-referenced at ");
769         return false;
770     }
771     symbol.SetTyIdx(tyIdx);
772     MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
773     PregIdx pRegIdx = func.GetPregTab()->EnterPregNo(thePRegNO, mirType->GetPrimType(), mirType);
774     MIRPregTable *pRegTab = func.GetPregTab();
775     MIRPreg *preg = pRegTab->PregFromPregIdx(pRegIdx);
776     preg->SetPrimType(mirType->GetPrimType());
777     symbol.SetPreg(preg);
778     if (!ParseVarTypeAttrs(symbol)) {
779         Error("bad type attribute in variable declaration at ");
780         return false;
781     }
782     if (GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx)->HasTypeParam()) {
783         symbol.SetAttr(ATTR_generic);
784         mod.CurFunction()->SetAttr(FUNCATTR_generic);
785     }
786     return true;
787 }
788 
ParseDeclareVarInitValue(MIRSymbol & symbol)789 bool MIRParser::ParseDeclareVarInitValue(MIRSymbol &symbol)
790 {
791     TokenKind tk = lexer.GetTokenKind();
792     // take a look if there are any initialized values
793     if (tk == TK_eqsign) {
794         // parse initialized values
795         MIRConst *mirConst = nullptr;
796         lexer.NextToken();
797         symbol.SetKonst(mirConst);
798     }
799     return true;
800 }
801 
ParseDeclareFormal(FormalDef & formalDef)802 bool MIRParser::ParseDeclareFormal(FormalDef &formalDef)
803 {
804     TokenKind tk = lexer.GetTokenKind();
805     if (tk != TK_var && tk != TK_reg) {
806         return false;
807     }
808     TokenKind nameTk = lexer.NextToken();
809     if (tk == TK_var) {
810         if (nameTk != TK_lname) {
811             Error("expect local name but get ");
812             return false;
813         }
814         formalDef.formalStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
815     } else {  // tk == TK_reg
816         if (nameTk != TK_preg) {
817             Error("expect preg but get ");
818             return false;
819         }
820         formalDef.formalStrIdx =
821             GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(std::to_string(lexer.GetTheIntVal()));
822     }
823     (void)lexer.NextToken();
824     if (!ParseType(formalDef.formalTyIdx)) {
825         Error("ParseDeclareFormal failed when parsing the type");
826         return false;
827     }
828     if (GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDef.formalTyIdx)->GetKind() == kTypeByName) {
829         Error("type in var declaration cannot be forward-referenced at ");
830         return false;
831     }
832     if (!ParseTypeAttrs(formalDef.formalAttrs)) {
833         Error("ParseDeclareFormal failed when parsing type attributes");
834         return false;
835     }
836     return true;
837 }
838 
ParseFuncInfo()839 bool MIRParser::ParseFuncInfo()
840 {
841     if (lexer.GetTokenKind() != TK_lbrace) {
842         Error("expect left brace after funcinfo but get ");
843         return false;
844     }
845     MIRFunction *func = mod.CurFunction();
846     TokenKind tokenKind = lexer.NextToken();
847     while (tokenKind == TK_label) {
848         GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
849         tokenKind = lexer.NextToken();
850         if (tokenKind == TK_intconst) {
851             uint32 fieldVal = lexer.GetTheIntVal();
852             func->PushbackMIRInfo(MIRInfoPair(strIdx, fieldVal));
853             func->PushbackIsString(false);
854         } else if (tokenKind == TK_string) {
855             GStrIdx literalStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
856             func->PushbackMIRInfo(MIRInfoPair(strIdx, literalStrIdx));
857             func->PushbackIsString(true);
858         } else {
859             Error("illegal value after funcinfo field name at ");
860             return false;
861         }
862         tokenKind = lexer.NextToken();
863         if (tokenKind == TK_rbrace) {
864             lexer.NextToken();
865             return true;
866         }
867         if (tokenKind == TK_coma) {
868             tokenKind = lexer.NextToken();
869         } else {
870             Error("expect comma after funcinfo field value but get ");
871             return false;
872         }
873     }
874     Error("expect field name in funcinfo but get ");
875     return false;
876 }
877 
ParsePosition(SrcPosition & pos)878 bool MIRParser::ParsePosition(SrcPosition &pos)
879 {
880     TokenKind nameTk = lexer.NextToken();
881     if (nameTk != TK_lparen) {
882         Error("expect ( in SrcPos but get ");
883         return false;
884     }
885     nameTk = lexer.NextToken();
886     if (nameTk != TK_intconst) {
887         Error("expect int in SrcPos but get ");
888         return false;
889     }
890     uint32 i = static_cast<uint32>(lexer.GetTheIntVal());
891     pos.SetFileNum(static_cast<uint16>(i));
892     nameTk = lexer.NextToken();
893     if (nameTk != TK_coma) {
894         Error("expect comma in SrcPos but get ");
895         return false;
896     }
897 
898     nameTk = lexer.NextToken();
899     if (nameTk != TK_intconst) {
900         Error("expect int in SrcPos but get ");
901         return false;
902     }
903     i = static_cast<uint32>(lexer.GetTheIntVal());
904     pos.SetLineNum(i);
905     nameTk = lexer.NextToken();
906     if (nameTk != TK_coma) {
907         Error("expect comma in SrcPos but get ");
908         return false;
909     }
910 
911     nameTk = lexer.NextToken();
912     if (nameTk != TK_intconst) {
913         Error("expect int in SrcPos but get ");
914         return false;
915     }
916     i = static_cast<uint32>(lexer.GetTheIntVal());
917     pos.SetColumn(static_cast<uint16>(i));
918     nameTk = lexer.NextToken();
919     if (nameTk != TK_rparen) {
920         Error("expect ) in SrcPos but get ");
921         return false;
922     }
923 
924     return true;
925 }
926 
ParseOneAlias(GStrIdx & strIdx,MIRAliasVars & aliasVar)927 bool MIRParser::ParseOneAlias(GStrIdx &strIdx, MIRAliasVars &aliasVar)
928 {
929     TokenKind nameTk = lexer.GetTokenKind();
930     if (nameTk != TK_ALIAS) {
931         Error("expect ALIAS but get ");
932         return false;
933     }
934     nameTk = lexer.NextToken();
935     if (nameTk != TK_lname) {
936         Error("expect local in ALIAS but get ");
937         return false;
938     }
939     strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
940     nameTk = lexer.NextToken();
941     bool isLocal;
942     if (nameTk == TK_lname) {
943         isLocal = true;
944     } else if (nameTk == TK_gname) {
945         isLocal = false;
946     } else {
947         Error("expect name in ALIAS but get ");
948         return false;
949     }
950     GStrIdx mplStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
951     lexer.NextToken();
952     TyIdx tyIdx(0);
953     if (!ParseType(tyIdx)) {
954         Error("parseType failed when parsing ALIAS ");
955         return false;
956     }
957     GStrIdx signStrIdx(0);
958     if (lexer.GetTokenKind() == TK_string) {
959         signStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
960         lexer.NextToken();
961     }
962     aliasVar.mplStrIdx = mplStrIdx;
963     aliasVar.tyIdx = tyIdx;
964     aliasVar.isLocal = isLocal;
965     aliasVar.sigStrIdx = signStrIdx;
966     return true;
967 }
968 
ParseWordsInfo(uint32 size)969 uint8 *MIRParser::ParseWordsInfo(uint32 size)
970 {
971     lexer.NextToken();
972     if (lexer.GetTokenKind() != TK_eqsign) {
973         Error("expect = after it but get ");
974         return nullptr;
975     }
976     lexer.NextToken();
977     if (lexer.GetTokenKind() != TK_lbrack) {
978         Error("expect [ for it but get ");
979         return nullptr;
980     }
981     uint8 *origp = static_cast<uint8 *>(mod.GetMemPool()->Malloc(BlockSize2BitVectorSize(size)));
982     // initialize it based on the input
983     for (uint32 *p = reinterpret_cast<uint32 *>(origp); lexer.NextToken() == TK_intconst; ++p) {
984         *p = static_cast<uint32>(lexer.GetTheIntVal());
985     }
986     if (lexer.GetTokenKind() != TK_rbrack) {
987         Error("expect ] at end of globalwordstypetagged but get ");
988         return nullptr;
989     }
990     lexer.NextToken();
991     return origp;
992 }
993 
ParseSrcLang(MIRSrcLang & srcLang)994 bool MIRParser::ParseSrcLang(MIRSrcLang &srcLang)
995 {
996     PrepareParsingMIR();
997     bool atEof = false;
998     lexer.NextToken();
999     while (!atEof) {
1000         paramTokenKind = lexer.GetTokenKind();
1001         if (paramTokenKind == TK_eof) {
1002             atEof = true;
1003         } else if (paramTokenKind == TK_srclang) {
1004             lexer.NextToken();
1005             if (lexer.GetTokenKind() != TK_intconst) {
1006                 Error("expect integer after srclang but get ");
1007                 return false;
1008             }
1009             srcLang = static_cast<MIRSrcLang>(lexer.GetTheIntVal());
1010             return true;
1011         } else {
1012             lexer.NextToken();
1013         }
1014     }
1015     return false;
1016 }
1017 
ParseMIRForFunc()1018 bool MIRParser::ParseMIRForFunc()
1019 {
1020     curFunc = nullptr;
1021     // when parsing function in mplt_inline file, set fromMpltInline as true.
1022     if ((this->options & kParseInlineFuncBody) && curFunc) {
1023         curFunc->SetFromMpltInline(true);
1024         return true;
1025     }
1026     if ((this->options & kParseOptFunc) && curFunc) {
1027         curFunc->SetAttr(FUNCATTR_optimized);
1028         mod.AddOptFuncs(curFunc);
1029     }
1030     return true;
1031 }
1032 
TypeCompatible(TyIdx typeIdx1,TyIdx typeIdx2)1033 bool MIRParser::TypeCompatible(TyIdx typeIdx1, TyIdx typeIdx2)
1034 {
1035     if (typeIdx1 == typeIdx2) {
1036         return true;
1037     }
1038     MIRType *type1 = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx1);
1039     MIRType *type2 = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typeIdx2);
1040     if (type1 == nullptr || type2 == nullptr) {
1041         // this means we saw the use of this symbol before def.
1042         return false;
1043     }
1044     while (type1->IsMIRPtrType() || type1->IsMIRArrayType()) {
1045         if (type1->IsMIRPtrType()) {
1046             CHECK_FATAL(type2->IsMIRPtrType(), "Error");
1047             type1 = static_cast<MIRPtrType *>(type1)->GetPointedType();
1048             type2 = static_cast<MIRPtrType *>(type2)->GetPointedType();
1049         } else {
1050             CHECK_FATAL(type2->IsMIRArrayType(), "Error");
1051             auto *arrayType1 = static_cast<MIRArrayType *>(type1);
1052             auto *arrayType2 = static_cast<MIRArrayType *>(type2);
1053             if (arrayType1->IsIncompleteArray() || arrayType2->IsIncompleteArray()) {
1054                 return true;
1055             }
1056             type1 = static_cast<MIRArrayType *>(type1)->GetElemType();
1057             type2 = static_cast<MIRArrayType *>(type2)->GetElemType();
1058         }
1059     }
1060     if (type1 == type2) {
1061         return true;
1062     }
1063     if (type1->IsIncomplete() || type2->IsIncomplete()) {
1064         return true;
1065     }
1066     return false;
1067 }
1068 
IsTypeIncomplete(MIRType * type)1069 bool MIRParser::IsTypeIncomplete(MIRType *type)
1070 {
1071     if (type->IsIncomplete()) {
1072         return true;
1073     }
1074     while (type->IsMIRPtrType() || type->IsMIRArrayType()) {
1075         if (type->IsMIRPtrType()) {
1076             type = static_cast<MIRPtrType *>(type)->GetPointedType();
1077         } else {
1078             auto *arrayType = static_cast<MIRArrayType *>(type);
1079             if (arrayType->IsIncompleteArray()) {
1080                 return true;
1081             }
1082             type = static_cast<MIRArrayType *>(type)->GetElemType();
1083         }
1084     }
1085     return type->IsIncomplete();
1086 }
1087 
ParseMIRForFlavor()1088 bool MIRParser::ParseMIRForFlavor()
1089 {
1090     lexer.NextToken();
1091     if (lexer.GetTokenKind() != TK_intconst) {
1092         Error("expect integer after flavor but get ");
1093         return false;
1094     }
1095     mod.SetFlavor(static_cast<MIRFlavor>(lexer.GetTheIntVal()));
1096     lexer.NextToken();
1097     return true;
1098 }
1099 
ParseMIRForSrcLang()1100 bool MIRParser::ParseMIRForSrcLang()
1101 {
1102     lexer.NextToken();
1103     if (lexer.GetTokenKind() != TK_intconst) {
1104         Error("expect integer after srclang but get ");
1105         return false;
1106     }
1107     mod.SetSrcLang(static_cast<MIRSrcLang>(lexer.GetTheIntVal()));
1108     lexer.NextToken();
1109     return true;
1110 }
1111 
ParseMIRForGlobalMemSize()1112 bool MIRParser::ParseMIRForGlobalMemSize()
1113 {
1114     lexer.NextToken();
1115     if (lexer.GetTokenKind() != TK_intconst) {
1116         Error("expect integer after globalmemsize but get ");
1117         return false;
1118     }
1119     mod.SetGlobalMemSize(lexer.GetTheIntVal());
1120     lexer.NextToken();
1121     return true;
1122 }
1123 
ParseMIRForGlobalMemMap()1124 bool MIRParser::ParseMIRForGlobalMemMap()
1125 {
1126     lexer.NextToken();
1127     if (lexer.GetTokenKind() != TK_eqsign) {
1128         Error("expect = after globalmemmap but get ");
1129         return false;
1130     }
1131     lexer.NextToken();
1132     if (lexer.GetTokenKind() != TK_lbrack) {
1133         Error("expect [ for globalmemmap but get ");
1134         return false;
1135     }
1136     mod.SetGlobalBlockMap(static_cast<uint8 *>(mod.GetMemPool()->Malloc(mod.GetGlobalMemSize())));
1137     // initialize globalblkmap based on the input
1138     for (uint32 *p = reinterpret_cast<uint32 *>(mod.GetGlobalBlockMap()); lexer.NextToken() == TK_intconst; ++p) {
1139         *p = static_cast<uint32>(lexer.GetTheIntVal());
1140     }
1141     if (lexer.GetTokenKind() != TK_rbrack) {
1142         Error("expect ] at end of globalmemmap but get ");
1143         return false;
1144     }
1145     lexer.NextToken();
1146     return true;
1147 }
1148 
ParseMIRForGlobalWordsTypeTagged()1149 bool MIRParser::ParseMIRForGlobalWordsTypeTagged()
1150 {
1151     uint8 *typeAddr = ParseWordsInfo(mod.GetGlobalMemSize());
1152     if (typeAddr == nullptr) {
1153         Error("parser error for globalwordstypetagged");
1154         return false;
1155     }
1156     mod.SetGlobalWordsTypeTagged(typeAddr);
1157     return true;
1158 }
1159 
ParseMIRForGlobalWordsRefCounted()1160 bool MIRParser::ParseMIRForGlobalWordsRefCounted()
1161 {
1162     uint8 *refAddr = ParseWordsInfo(mod.GetGlobalMemSize());
1163     if (refAddr == nullptr) {
1164         Error("parser error for globalwordsrefcounted");
1165         return false;
1166     }
1167     mod.SetGlobalWordsRefCounted(refAddr);
1168     return true;
1169 }
1170 
ParseMIRForID()1171 bool MIRParser::ParseMIRForID()
1172 {
1173     lexer.NextToken();
1174     if (lexer.GetTokenKind() != TK_intconst) {
1175         Error("expect integer after id but get ");
1176         return false;
1177     }
1178     mod.SetID(static_cast<uint16>(lexer.GetTheIntVal()));
1179     lexer.NextToken();
1180     return true;
1181 }
1182 
ParseMIRForNumFuncs()1183 bool MIRParser::ParseMIRForNumFuncs()
1184 {
1185     lexer.NextToken();
1186     if (lexer.GetTokenKind() != TK_intconst) {
1187         Error("expect integer after numfuncs but get ");
1188         return false;
1189     }
1190     mod.SetNumFuncs(lexer.GetTheIntVal());
1191     lexer.NextToken();
1192     return true;
1193 }
1194 
ParseMIRForEntryFunc()1195 bool MIRParser::ParseMIRForEntryFunc()
1196 {
1197     lexer.NextToken();
1198     if (lexer.GetTokenKind() != TK_fname) {
1199         Error("expect function name for func but get ");
1200         return false;
1201     }
1202     mod.SetEntryFuncName(lexer.GetName());
1203     lexer.NextToken();
1204     return true;
1205 }
1206 
ParseMIRForFileInfo()1207 bool MIRParser::ParseMIRForFileInfo()
1208 {
1209     lexer.NextToken();
1210     if (lexer.GetTokenKind() != TK_lbrace) {
1211         Error("expect left brace after fileInfo but get ");
1212         return false;
1213     }
1214     TokenKind tk = lexer.NextToken();
1215     while (tk == TK_label) {
1216         GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
1217         tk = lexer.NextToken();
1218         if (tk == TK_intconst) {
1219             uint32 fieldVal = lexer.GetTheIntVal();
1220             mod.PushFileInfoPair(MIRInfoPair(strIdx, fieldVal));
1221             mod.PushFileInfoIsString(false);
1222         } else if (tk == TK_string) {
1223             GStrIdx litStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
1224             mod.PushFileInfoPair(MIRInfoPair(strIdx, litStrIdx));
1225             mod.PushFileInfoIsString(true);
1226         } else {
1227             Error("illegal value after fileInfo field name at ");
1228             return false;
1229         }
1230         tk = lexer.NextToken();
1231         if (tk == TK_rbrace) {
1232             lexer.NextToken();
1233             return true;
1234         }
1235         if (tk == TK_coma) {
1236             tk = lexer.NextToken();
1237         } else {
1238             Error("expect comma after fileInfo field value but get ");
1239             return false;
1240         }
1241     }
1242     Error("expect field name in fileInfo but get ");
1243     return false;
1244 }
1245 
ParseMIRForFileData()1246 bool MIRParser::ParseMIRForFileData()
1247 {
1248     lexer.NextToken();
1249     if (lexer.GetTokenKind() != TK_lbrace) {
1250         Error("expect left brace after fileData but get ");
1251         return false;
1252     }
1253     TokenKind tk = lexer.NextToken();
1254     while (tk == TK_label) {
1255         GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
1256         tk = lexer.NextToken();
1257         std::vector<uint8> data;
1258         while (tk == TK_intconst) {
1259             uint32 fieldVal = lexer.GetTheIntVal();
1260             data.push_back(fieldVal);
1261             tk = lexer.NextToken();
1262         }
1263         mod.PushbackFileData(MIRDataPair(strIdx, data));
1264         if (tk == TK_coma) {
1265             tk = lexer.NextToken();
1266         } else if (tk == TK_rbrace) {
1267             lexer.NextToken();
1268             return true;
1269         } else {
1270             Error("expect comma after fileData field value but get ");
1271             return false;
1272         }
1273     }
1274     Error("expect field name in fileData but get ");
1275     return false;
1276 }
1277 
ParseMIRForSrcFileInfo()1278 bool MIRParser::ParseMIRForSrcFileInfo()
1279 {
1280     lexer.NextToken();
1281     if (lexer.GetTokenKind() != TK_lbrace) {
1282         Error("expect left brace after fileInfo but get ");
1283         return false;
1284     }
1285     TokenKind tk = lexer.NextToken();
1286     while (tk == TK_intconst) {
1287         uint32 fieldVal = lexer.GetTheIntVal();
1288         tk = lexer.NextToken();
1289         if (tk == TK_string) {
1290             GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
1291             mod.PushbackFileInfo(MIRInfoPair(strIdx, fieldVal));
1292         } else {
1293             Error("illegal value after srcfileinfo field name at ");
1294             return false;
1295         }
1296         tk = lexer.NextToken();
1297         if (tk == TK_rbrace) {
1298             lexer.NextToken();
1299             return true;
1300         }
1301         if (tk == TK_coma) {
1302             tk = lexer.NextToken();
1303         } else {
1304             Error("expect comma after srcfileinfo field value but get ");
1305             return false;
1306         }
1307     }
1308     Error("expect field name in srcfileinfo but get ");
1309     return false;
1310 }
1311 
ParseMIRForImportPath()1312 bool MIRParser::ParseMIRForImportPath()
1313 {
1314     lexer.NextToken();
1315     if (lexer.GetTokenKind() != TK_string) {
1316         Error("expect path string after importpath but get ");
1317         return false;
1318     }
1319     GStrIdx litStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName());
1320     mod.PushbackImportPath(litStrIdx);
1321     lexer.NextToken();
1322     return true;
1323 }
1324 
ParseMIRForAsmdecl()1325 bool MIRParser::ParseMIRForAsmdecl()
1326 {
1327     lexer.NextToken();
1328     if (lexer.GetTokenKind() != TK_string) {
1329         Error("expect asm string after iasm but get ");
1330         return false;
1331     }
1332     mod.GetAsmDecls().emplace_back(MapleString(lexer.GetName(), mod.GetMemPool()));
1333     lexer.NextToken();
1334     return true;
1335 }
1336 
PrepareParsingMIR()1337 void MIRParser::PrepareParsingMIR()
1338 {
1339     dummyFunction = CreateDummyFunction();
1340     mod.SetCurFunction(dummyFunction);
1341     if (mod.IsNeedFile()) {
1342         lexer.PrepareForFile(mod.GetFileName());
1343     } else {
1344         lexer.PrepareForString(mod.GetFileText());
1345     }
1346 }
1347 
PrepareParsingMplt()1348 void MIRParser::PrepareParsingMplt()
1349 {
1350     lexer.PrepareForFile(mod.GetFileName());
1351 }
1352 
ParseTypeFromString(const std::string & src,TyIdx & tyIdx)1353 bool MIRParser::ParseTypeFromString(const std::string &src, TyIdx &tyIdx)
1354 {
1355     lexer.PrepareForString(src);
1356     return ParseType(tyIdx);
1357 }
1358 
ParseMPLT(std::ifstream & mpltFile,const std::string & importFileName)1359 bool MIRParser::ParseMPLT(std::ifstream &mpltFile, const std::string &importFileName)
1360 {
1361     // save relevant values for the main input file
1362     std::ifstream *airFileSave = lexer.GetFile();
1363     int lineNumSave = static_cast<int>(lexer.lineNum);
1364     std::string modFileNameSave = mod.GetFileName();
1365     // set up to read next line from the import file
1366     lexer.curIdx = 0;
1367     lexer.currentLineSize = 0;
1368     lexer.SetFile(mpltFile);
1369     lexer.lineNum = 0;
1370     mod.SetFileName(importFileName);
1371     bool atEof = false;
1372     lexer.NextToken();
1373     while (!atEof) {
1374         TokenKind tokenKind = lexer.GetTokenKind();
1375         switch (tokenKind) {
1376             default: {
1377                 Error("expect func or var but get ");
1378                 return false;
1379             }
1380             case TK_eof:
1381                 atEof = true;
1382                 break;
1383             case TK_type:
1384                 paramParseLocalType = false;
1385                 break;
1386             case TK_var: {
1387                 tokenKind = lexer.NextToken();
1388                 if (tokenKind == TK_gname) {
1389                     std::string literalName = lexer.GetName();
1390                     GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(literalName);
1391                     GlobalTables::GetConstPool().PutLiteralNameAsImported(strIdx);
1392                     lexer.NextToken();
1393                 } else {
1394                     return false;
1395                 }
1396                 break;
1397             }
1398         }
1399     }
1400     // restore old values to continue reading from the main input file
1401     lexer.curIdx = 0;  // to force reading new line
1402     lexer.currentLineSize = 0;
1403     lexer.lineNum = static_cast<size_t>(lineNumSave);
1404     lexer.SetFile(*airFileSave);
1405     mod.SetFileName(modFileNameSave);
1406     return true;
1407 }
1408 
ParsePrototypeRemaining(MIRFunction & func,std::vector<TyIdx> & vecTyIdx,std::vector<TypeAttrs> & vecAttrs,bool & varArgs)1409 bool MIRParser::ParsePrototypeRemaining(MIRFunction &func, std::vector<TyIdx> &vecTyIdx,
1410                                         std::vector<TypeAttrs> &vecAttrs, bool &varArgs)
1411 {
1412     TokenKind pmTk = lexer.GetTokenKind();
1413     while (pmTk != TK_rparen) {
1414         // parse ","
1415         if (pmTk != TK_coma) {
1416             Error("expect , after a declare var/preg but get");
1417             return false;
1418         }
1419         pmTk = lexer.NextToken();
1420         if (pmTk == TK_dotdotdot) {
1421             varArgs = true;
1422             func.SetVarArgs();
1423             pmTk = lexer.NextToken();
1424             if (pmTk != TK_rparen) {
1425                 Error("expect ) after ... but get");
1426                 return false;
1427             }
1428             break;
1429         }
1430         MIRSymbol *symbol = func.GetSymTab()->CreateSymbol(kScopeLocal);
1431         DEBUG_ASSERT(symbol != nullptr, "symbol nullptr check");
1432         symbol->SetStorageClass(kScFormal);
1433         TokenKind loopStTK = lexer.GetTokenKind();
1434         if (loopStTK == TK_reg) {
1435             symbol->SetSKind(kStPreg);
1436             if (!ParseDeclareReg(*symbol, func)) {
1437                 Error("ParseFunction expect scalar value");
1438                 return false;
1439             }
1440         } else {
1441             symbol->SetSKind(kStVar);
1442             (void)func.GetSymTab()->AddToStringSymbolMap(*symbol);
1443             if (!ParseDeclareVarInitValue(*symbol)) {
1444                 return false;
1445             }
1446         }
1447         func.AddArgument(symbol);
1448         vecTyIdx.push_back(symbol->GetTyIdx());
1449         vecAttrs.push_back(symbol->GetAttrs());
1450         pmTk = lexer.GetTokenKind();
1451     }
1452     return true;
1453 }
1454 
EmitError(const std::string & fileName)1455 void MIRParser::EmitError(const std::string &fileName)
1456 {
1457     if (!strlen(GetError().c_str())) {
1458         return;
1459     }
1460     mod.GetDbgInfo()->EmitMsg();
1461     ERR(kLncErr, "%s \n%s", fileName.c_str(), GetError().c_str());
1462 }
1463 
EmitWarning(const std::string & fileName)1464 void MIRParser::EmitWarning(const std::string &fileName)
1465 {
1466     if (!strlen(GetWarning().c_str())) {
1467         return;
1468     }
1469     WARN(kLncWarn, "%s \n%s\n", fileName.c_str(), GetWarning().c_str());
1470 }
1471 }  // namespace maple
1472