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