/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mir_parser.h" #include "mir_function.h" #include "opcode_info.h" namespace maple { std::map MIRParser::funcPtrMapForParseExpr = MIRParser::InitFuncPtrMapForParseExpr(); std::map MIRParser::funcPtrMapForParseStmt = MIRParser::InitFuncPtrMapForParseStmt(); std::map MIRParser::funcPtrMapForParseStmtBlock = MIRParser::InitFuncPtrMapForParseStmtBlock(); bool MIRParser::ParseStmtDassign(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_dassign) { Error("expect dassign but get "); return false; } // parse %i lexer.NextToken(); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect a symbol parsing ParseStmtDassign"); return false; } if (stidx.IsGlobal()) { MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); DEBUG_ASSERT(sym != nullptr, "null ptr check"); sym->SetHasPotentialAssignment(); } auto *assignStmt = mod.CurFuncCodeMemPool()->New(); assignStmt->SetStIdx(stidx); TokenKind nextToken = lexer.NextToken(); // parse field id if (nextToken == TK_intconst) { // may be a field id assignStmt->SetFieldID(lexer.GetTheIntVal()); (void)lexer.NextToken(); } // parse expression like (constval i32 0) BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } assignStmt->SetRHS(expr); stmt = assignStmt; lexer.NextToken(); return true; } bool MIRParser::ParseStmtDassignoff(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_dassignoff) { Error("expect dassignoff but get "); return false; } if (!IsPrimitiveType(lexer.NextToken())) { Error("expect primitive type but get "); return false; } PrimType primType = GetPrimitiveType(lexer.GetTokenKind()); // parse %i lexer.NextToken(); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect a symbol parsing ParseStmtDassign"); return false; } if (stidx.IsGlobal()) { MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); DEBUG_ASSERT(sym != nullptr, "null ptr check"); sym->SetHasPotentialAssignment(); } DassignoffNode *assignStmt = mod.CurFuncCodeMemPool()->New(); assignStmt->SetPrimType(primType); assignStmt->stIdx = stidx; TokenKind nextToken = lexer.NextToken(); // parse offset if (nextToken == TK_intconst) { assignStmt->offset = static_cast(lexer.GetTheIntVal()); (void)lexer.NextToken(); } else { Error("expect integer offset but get "); return false; } // parse expression like (constval i32 0) BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } assignStmt->SetRHS(expr); stmt = assignStmt; lexer.NextToken(); return true; } bool MIRParser::ParseStmtRegassign(StmtNodePtr &stmt) { if (!IsPrimitiveType(lexer.NextToken())) { Error("expect type parsing binary operator but get "); return false; } auto *regAssign = mod.CurFuncCodeMemPool()->New(); regAssign->SetPrimType(GetPrimitiveType(lexer.GetTokenKind())); lexer.NextToken(); if (lexer.GetTokenKind() == TK_specialreg) { PregIdx tempPregIdx = regAssign->GetRegIdx(); bool isSuccess = ParseSpecialReg(tempPregIdx); regAssign->SetRegIdx(tempPregIdx); if (!isSuccess) { return false; } } else if (lexer.GetTokenKind() == TK_preg) { PregIdx tempPregIdx = regAssign->GetRegIdx(); bool isSuccess = ParsePseudoReg(regAssign->GetPrimType(), tempPregIdx); regAssign->SetRegIdx(tempPregIdx); if (!isSuccess) { return false; } } else { Error("expect special or pseudo register but get "); return false; } BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } regAssign->SetOpnd(expr, 0); if (regAssign->GetRegIdx() > 0) { // check type consistenency for the preg MIRPreg *preg = mod.CurFunction()->GetPregTab()->PregFromPregIdx(regAssign->GetRegIdx()); if (preg->GetPrimType() == kPtyInvalid) { preg->SetPrimType(expr->GetPrimType()); } else if (preg->GetPrimType() == PTY_dynany) { if (!IsPrimitiveDynType(expr->GetPrimType())) { Error("inconsistent preg primitive dynamic type at "); return false; } } } stmt = regAssign; lexer.NextToken(); return true; } bool MIRParser::ParseStmtIassign(StmtNodePtr &stmt) { // iAssign <* [10] int> () if (lexer.GetTokenKind() != TK_iassign) { Error("expect iassign but get "); return false; } // expect <> derived type lexer.NextToken(); TyIdx tyIdx(0); if (!ParseDerivedType(tyIdx)) { Error("ParseStmtIassign failed when parsing derived type"); return false; } auto *iAssign = mod.CurFuncCodeMemPool()->New(); iAssign->SetTyIdx(tyIdx); if (lexer.GetTokenKind() == TK_intconst) { iAssign->SetFieldID(lexer.theIntVal); lexer.NextToken(); } BaseNode *addr = nullptr; BaseNode *rhs = nullptr; // parse 2 operands then, #1 is address, the other would be value if (!ParseExprTwoOperand(addr, rhs)) { return false; } iAssign->SetOpnd(addr, 0); iAssign->SetRHS(rhs); lexer.NextToken(); stmt = iAssign; return true; } bool MIRParser::ParseStmtIassignoff(StmtNodePtr &stmt) { if (!IsPrimitiveType(lexer.NextToken())) { Error("expect type parsing binary operator but get "); return false; } // iassign ( , ) auto *iAssignOff = mod.CurFuncCodeMemPool()->New(); iAssignOff->SetPrimType(GetPrimitiveType(lexer.GetTokenKind())); if (lexer.NextToken() != TK_intconst) { Error("expect offset but get "); return false; } iAssignOff->SetOffset(lexer.GetTheIntVal()); lexer.NextToken(); BaseNode *addr = nullptr; BaseNode *rhs = nullptr; if (!ParseExprTwoOperand(addr, rhs)) { return false; } iAssignOff->SetBOpnd(addr, 0); iAssignOff->SetBOpnd(rhs, 1); lexer.NextToken(); stmt = iAssignOff; return true; } bool MIRParser::ParseStmtIassignFPoff(StmtNodePtr &stmt) { Opcode op = lexer.GetTokenKind() == TK_iassignfpoff ? OP_iassignfpoff : OP_iassignspoff; if (!IsPrimitiveType(lexer.NextToken())) { Error("expect type parsing binary operator but get "); return false; } // iassignfpoff ( ) auto *iAssignOff = mod.CurFuncCodeMemPool()->New(op); iAssignOff->SetPrimType(GetPrimitiveType(lexer.GetTokenKind())); if (lexer.NextToken() != TK_intconst) { Error("expect offset but get "); return false; } iAssignOff->SetOffset(lexer.GetTheIntVal()); lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } iAssignOff->SetOpnd(expr, 0); lexer.NextToken(); stmt = iAssignOff; return true; } bool MIRParser::ParseStmtBlkassignoff(StmtNodePtr &stmt) { // blkassignoff (, ) BlkassignoffNode *bassignoff = mod.CurFuncCodeMemPool()->New(); if (lexer.NextToken() != TK_intconst) { Error("expect offset but get "); return false; } bassignoff->offset = static_cast(lexer.GetTheIntVal()); if (lexer.NextToken() != TK_intconst) { Error("expect align but get "); return false; } bassignoff->SetAlign(static_cast(lexer.GetTheIntVal())); if (lexer.NextToken() != TK_intconst) { Error("expect size but get "); return false; } bassignoff->blockSize = static_cast(lexer.GetTheIntVal()); lexer.NextToken(); BaseNode *destAddr = nullptr; BaseNode *srcAddr = nullptr; // parse 2 operands, the dest address followed by src address if (!ParseExprTwoOperand(destAddr, srcAddr)) { return false; } bassignoff->SetOpnd(destAddr, 0); bassignoff->SetOpnd(srcAddr, 1); lexer.NextToken(); stmt = bassignoff; return true; } bool MIRParser::ParseStmtDoloop(StmtNodePtr &stmt) { // syntax: doloop (, , ) { // } auto *doLoopNode = mod.CurFuncCodeMemPool()->New(); stmt = doLoopNode; lexer.NextToken(); if (lexer.GetTokenKind() == TK_preg) { uint32 pregNo = static_cast(lexer.GetTheIntVal()); MIRFunction *mirFunc = mod.CurFunction(); PregIdx pregIdx = mirFunc->GetPregTab()->EnterPregNo(pregNo, kPtyInvalid); doLoopNode->SetIsPreg(true); doLoopNode->SetDoVarStFullIdx(pregIdx); // let other appearances handle the preg primitive type } else { StIdx stIdx; if (!ParseDeclaredSt(stIdx)) { return false; } if (stIdx.FullIdx() == 0) { Error("expect a symbol parsing ParseStmtDoloop"); return false; } if (stIdx.IsGlobal()) { Error("expect local variable for doloop var but get "); return false; } doLoopNode->SetDoVarStIdx(stIdx); } // parse ( if (lexer.NextToken() != TK_lparen) { Error("expect ( but get "); return false; } // parse start expression lexer.NextToken(); BaseNode *start = nullptr; if (!ParseExpression(start)) { Error("ParseStmtDoloop when parsing start expression"); return false; } if (doLoopNode->IsPreg()) { auto regIdx = static_cast(doLoopNode->GetDoVarStIdx().FullIdx()); MIRPreg *mpReg = mod.CurFunction()->GetPregTab()->PregFromPregIdx(regIdx); if (mpReg->GetPrimType() == kPtyInvalid) { CHECK_FATAL(start != nullptr, "null ptr check"); mpReg->SetPrimType(start->GetPrimType()); } } if (lexer.GetTokenKind() != TK_coma) { Error("expect , after start expression but get "); return false; } doLoopNode->SetStartExpr(start); // parse end expression lexer.NextToken(); BaseNode *end = nullptr; if (!ParseExpression(end)) { // here should be a compare expression Error("ParseStmtDoloop when parsing end expression"); return false; } if (lexer.GetTokenKind() != TK_coma) { Error("expect , after condition expression but get "); return false; } doLoopNode->SetContExpr(end); // parse renew induction expression lexer.NextToken(); BaseNode *induction = nullptr; if (!ParseExpression(induction)) { Error("ParseStmtDoloop when parsing induction"); return false; } // parse ) if (lexer.GetTokenKind() != TK_rparen) { Error("expect ) parsing doloop but get "); return false; } doLoopNode->SetIncrExpr(induction); // parse body of the loop lexer.NextToken(); BlockNode *bodyStmt = nullptr; if (!ParseStmtBlock(bodyStmt)) { Error("ParseStmtDoloop when parsing body of the loop"); return false; } doLoopNode->SetDoBody(bodyStmt); return true; } bool MIRParser::ParseStmtForeachelem(StmtNodePtr &stmt) { // syntax: foreachelem { // } auto *forNode = mod.CurFuncCodeMemPool()->New(); stmt = forNode; lexer.NextToken(); // skip foreachelem token StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("error parsing element variable of foreachelem in "); return false; } if (stidx.IsGlobal()) { Error("illegal global scope for element variable for foreachelem in "); return false; } forNode->SetElemStIdx(stidx); lexer.NextToken(); if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("error parsing array/collection variable of foreachelem in "); return false; } forNode->SetArrayStIdx(stidx); lexer.NextToken(); // parse body of the loop BlockNode *bodyStmt = nullptr; if (!ParseStmtBlock(bodyStmt)) { Error("error when parsing body of foreachelem loop in "); return false; } forNode->SetLoopBody(bodyStmt); return true; } bool MIRParser::ParseStmtIf(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_if) { Error("expect if but get "); return false; } auto *ifStmt = mod.CurFuncCodeMemPool()->New(); lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } ifStmt->SetOpnd(expr, 0); if (lexer.NextToken() != TK_lbrace) { Error("expect { begin if body but get "); return false; } BlockNode *thenBlock = nullptr; if (!ParseStmtBlock(thenBlock)) { Error("ParseStmtIf failed when parsing then block"); return false; } ifStmt->SetThenPart(thenBlock); BlockNode *elseBlock = nullptr; if (lexer.GetTokenKind() == TK_else) { // has else part if (lexer.NextToken() != TK_lbrace) { Error("expect { begin if body but get "); return false; } if (!ParseStmtBlock(elseBlock)) { Error("ParseStmtIf failed when parsing else block"); return false; } ifStmt->SetElsePart(elseBlock); } stmt = ifStmt; return true; } bool MIRParser::ParseStmtWhile(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_while) { Error("expect while but get "); return false; } auto *whileStmt = mod.CurFuncCodeMemPool()->New(OP_while); lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } whileStmt->SetOpnd(expr, 0); if (lexer.NextToken() != TK_lbrace) { Error("expect { begin if body but get "); return false; } BlockNode *whileBody = nullptr; if (!ParseStmtBlock(whileBody)) { Error("ParseStmtWhile failed when parse while body"); return false; } whileStmt->SetBody(whileBody); stmt = whileStmt; return true; } bool MIRParser::ParseStmtDowhile(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_dowhile) { Error("expect while but get "); return false; } auto *whileStmt = mod.CurFuncCodeMemPool()->New(OP_dowhile); if (lexer.NextToken() != TK_lbrace) { Error("expect { begin if body but get "); return false; } BlockNode *doWhileBody = nullptr; if (!ParseStmtBlock(doWhileBody)) { Error("ParseStmtDowhile failed when trying to parsing do while body"); return false; } whileStmt->SetBody(doWhileBody); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } whileStmt->SetOpnd(expr, 0); lexer.NextToken(); stmt = whileStmt; return true; } bool MIRParser::ParseStmtLabel(StmtNodePtr &stmt) { GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labIdx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(strIdx); if (labIdx == 0) { labIdx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labIdx, strIdx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labIdx); } else { if (definedLabels.size() > labIdx && definedLabels[labIdx]) { Error("label multiply declared "); return false; } } if (definedLabels.size() <= labIdx) { definedLabels.resize(labIdx + 1); } definedLabels[labIdx] = true; auto *labNode = mod.CurFuncCodeMemPool()->New(); labNode->SetLabelIdx(labIdx); stmt = labNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtGoto(StmtNodePtr &stmt) { if (lexer.GetTokenKind() != TK_goto) { Error("expect goto but get "); return false; } if (lexer.NextToken() != TK_label) { Error("expect label in goto but get "); return false; } GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labIdx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(strIdx); if (labIdx == 0) { labIdx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labIdx, strIdx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labIdx); } auto *gotoNode = mod.CurFuncCodeMemPool()->New(OP_goto); gotoNode->SetOffset(labIdx); stmt = gotoNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtBr(StmtNodePtr &stmt) { TokenKind tk = lexer.GetTokenKind(); if (tk != TK_brtrue && tk != TK_brfalse) { Error("expect brtrue/brfalse but get "); return false; } if (lexer.NextToken() != TK_label) { Error("expect label in goto but get "); return false; } GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labIdx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(strIdx); if (labIdx == 0) { labIdx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labIdx, strIdx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labIdx); } auto *condGoto = mod.CurFuncCodeMemPool()->New(tk == TK_brtrue ? OP_brtrue : OP_brfalse); condGoto->SetOffset(labIdx); lexer.NextToken(); // parse () BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } condGoto->SetOpnd(expr, 0); stmt = condGoto; lexer.NextToken(); return true; } bool MIRParser::ParseSwitchCase(int64 &constVal, LabelIdx &lblIdx) { // syntax : goto if (lexer.GetTokenKind() != TK_intconst) { Error("expect intconst in switch but get "); return false; } constVal = lexer.GetTheIntVal(); if (lexer.NextToken() != TK_colon) { Error("expect : in switch but get "); return false; } if (lexer.NextToken() != TK_goto) { Error("expect goto in switch case but get "); return false; } if (lexer.NextToken() != TK_label) { Error("expect label in switch but get "); return false; } lblIdx = mod.CurFunction()->GetOrCreateLableIdxFromName(lexer.GetName()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtSwitch(StmtNodePtr &stmt) { auto *switchNode = mod.CurFuncCodeMemPool()->New(mod); stmt = switchNode; lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } switchNode->SetSwitchOpnd(expr); if (!IsPrimitiveInteger(expr->GetPrimType())) { Error("expect expression return integer but get "); return false; } if (lexer.NextToken() == TK_label) { switchNode->SetDefaultLabel(mod.CurFunction()->GetOrCreateLableIdxFromName(lexer.GetName())); } else { Error("expect label in switch but get "); return false; } if (lexer.NextToken() != TK_lbrace) { Error("expect { in switch but get "); return false; } // : goto // : goto // ... // : goto TokenKind tk = lexer.NextToken(); std::set casesSet; while (tk != TK_rbrace) { int64 constVal = 0; LabelIdx lbl = 0; if (!ParseSwitchCase(constVal, lbl)) { Error("parse switch case failed "); return false; } if (casesSet.find(constVal) != casesSet.end()) { Error("duplicated switch case "); return false; } switchNode->InsertCasePair(CasePair(constVal, lbl)); (void)casesSet.insert(constVal); tk = lexer.GetTokenKind(); } lexer.NextToken(); return true; } bool MIRParser::ParseStmtRangegoto(StmtNodePtr &stmt) { auto *rangeGotoNode = mod.CurFuncCodeMemPool()->New(mod); stmt = rangeGotoNode; lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } if (!IsPrimitiveInteger(expr->GetPrimType())) { Error("expect expression return integer but get "); return false; } rangeGotoNode->SetOpnd(expr, 0); if (lexer.NextToken() == TK_intconst) { rangeGotoNode->SetTagOffset(static_cast(lexer.GetTheIntVal())); } else { Error("expect tag offset in rangegoto but get "); return false; } if (lexer.NextToken() != TK_lbrace) { Error("expect { in switch but get "); return false; } // : goto // : goto // ... // : goto TokenKind tk = lexer.NextToken(); std::set casesSet; int32 minIdx = UINT16_MAX; int32 maxIdx = 0; while (tk != TK_rbrace) { int64 constVal = 0; LabelIdx lbl = 0; if (!ParseSwitchCase(constVal, lbl)) { Error("parse switch case failed "); return false; } if (constVal > UINT16_MAX || constVal < 0) { Error("rangegoto case tag not within unsigned 16 bits range "); return false; } if (casesSet.find(constVal) != casesSet.end()) { Error("duplicated switch case "); return false; } if (constVal < minIdx) { minIdx = static_cast(constVal); } if (constVal > maxIdx) { maxIdx = static_cast(constVal); } rangeGotoNode->AddRangeGoto(static_cast(constVal), static_cast(lbl)); (void)casesSet.insert(constVal); tk = lexer.GetTokenKind(); } DEBUG_ASSERT(rangeGotoNode->GetNumOpnds() == 1, "Rangegoto is a UnaryOpnd; numOpnds must be 1"); // check there is no gap if (static_cast(static_cast(maxIdx - minIdx) + 1) != casesSet.size()) { Error("gap not allowed in rangegoto case tags "); return false; } lexer.NextToken(); return true; } bool MIRParser::ParseStmtMultiway(StmtNodePtr &stmt) { auto *multiwayNode = mod.CurFuncCodeMemPool()->New(mod); stmt = multiwayNode; lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } multiwayNode->SetMultiWayOpnd(expr); if (lexer.NextToken() == TK_label) { multiwayNode->SetDefaultlabel(mod.CurFunction()->GetOrCreateLableIdxFromName(lexer.GetName())); } else { Error("expect label in multiway but get "); return false; } if (lexer.NextToken() != TK_lbrace) { Error("expect { in switch but get "); return false; } // (): goto // (): goto // ... // (): goto TokenKind tk = lexer.NextToken(); while (tk != TK_rbrace) { BaseNode *x = nullptr; if (!ParseExprOneOperand(x)) { return false; } if (lexer.NextToken() != TK_colon) { Error("expect : parsing multiway case tag specification but get "); return false; } if (lexer.NextToken() != TK_goto) { Error("expect goto in multiway case expression but get "); return false; } if (lexer.NextToken() != TK_label) { Error("expect goto label after multiway case expression but get "); return false; } LabelIdx lblIdx = mod.CurFunction()->GetOrCreateLableIdxFromName(lexer.GetName()); lexer.NextToken(); multiwayNode->AppendElemToMultiWayTable(MCasePair(static_cast(x), lblIdx)); tk = lexer.GetTokenKind(); } const MapleVector &multiWayTable = multiwayNode->GetMultiWayTable(); multiwayNode->SetNumOpnds(multiWayTable.size()); lexer.NextToken(); return true; } // used only when parsing mmpl PUIdx MIRParser::EnterUndeclaredFunction(bool isMcount) { std::string funcName; if (isMcount) { funcName = "_mcount"; } else { funcName = lexer.GetName(); } GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName); MIRSymbol *funcSt = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal); funcSt->SetNameStrIdx(strIdx); (void)GlobalTables::GetGsymTable().AddToStringSymbolMap(*funcSt); funcSt->SetStorageClass(kScText); funcSt->SetSKind(kStFunc); auto *fn = mod.GetMemPool()->New(&mod, funcSt->GetStIdx()); fn->SetPuidx(GlobalTables::GetFunctionTable().GetFuncTable().size()); GlobalTables::GetFunctionTable().GetFuncTable().push_back(fn); funcSt->SetFunction(fn); auto *funcType = mod.GetMemPool()->New(); fn->SetMIRFuncType(funcType); if (isMcount) { MIRType *retType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_void)); fn->SetReturnTyIdx(retType->GetTypeIndex()); } return fn->GetPuidx(); } bool MIRParser::ParseStmtCallMcount(StmtNodePtr &stmt) { // syntax: call (, ..., ) Opcode o = OP_call; PUIdx pIdx = EnterUndeclaredFunction(true); auto *callStmt = mod.CurFuncCodeMemPool()->New(mod, o); callStmt->SetPUIdx(pIdx); MapleVector opndsvec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); callStmt->SetNOpnd(opndsvec); callStmt->SetNumOpnds(opndsvec.size()); stmt = callStmt; return true; } bool MIRParser::ParseStmtCall(StmtNodePtr &stmt) { // syntax: call (, ..., ) TokenKind tk = lexer.GetTokenKind(); Opcode o = GetOpFromToken(tk); DEBUG_ASSERT(kOpcodeInfo.IsCall(o), "ParseStmtCall: not a call opcode"); bool hasAssigned = kOpcodeInfo.IsCallAssigned(o); bool hasInstant = false; bool withType = false; switch (tk) { case TK_polymorphiccall: case TK_polymorphiccallassigned: withType = true; break; case TK_callinstant: case TK_virtualcallinstant: case TK_superclasscallinstant: case TK_interfacecallinstant: case TK_callinstantassigned: case TK_virtualcallinstantassigned: case TK_superclasscallinstantassigned: case TK_interfacecallinstantassigned: hasInstant = true; break; default: break; } TyIdx polymophicTyidx(0); if (o == OP_polymorphiccallassigned || o == OP_polymorphiccall) { TokenKind nextTk = lexer.NextToken(); if (nextTk == TK_langle) { nextTk = lexer.NextToken(); if (nextTk == TK_func) { lexer.NextToken(); if (!ParseFuncType(polymophicTyidx)) { Error("error parsing functype in ParseStmtCall for polymorphiccallassigned at "); return false; } } else { Error("expect func in functype but get "); return false; } } else { Error("expect < in functype but get "); return false; } } TokenKind funcTk = lexer.NextToken(); if (funcTk != TK_fname) { Error("expect func name in call but get "); return false; } PUIdx pIdx; if (!ParseDeclaredFunc(pIdx)) { if (mod.GetFlavor() < kMmpl) { Error("expect .mmpl"); return false; } pIdx = EnterUndeclaredFunction(); } lexer.NextToken(); CallNode *callStmt = nullptr; CallinstantNode *callInstantStmt = nullptr; if (withType) { callStmt = mod.CurFuncCodeMemPool()->New(mod, o); callStmt->SetTyIdx(polymophicTyidx); } else if (hasInstant) { TokenKind langleTk = lexer.GetTokenKind(); if (langleTk != TK_langle) { Error("missing < in generic method instantiation at "); return false; } TokenKind lbraceTk = lexer.NextToken(); if (lbraceTk != TK_lbrace) { Error("missing { in generic method instantiation at "); return false; } MIRInstantVectorType instVecTy; if (!ParseGenericInstantVector(instVecTy)) { Error("error parsing generic method instantiation at "); return false; } TokenKind rangleTk = lexer.GetTokenKind(); if (rangleTk != TK_rangle) { Error("missing > in generic method instantiation at "); return false; } TyIdx tyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&instVecTy); callInstantStmt = mod.CurFuncCodeMemPool()->New(mod, o, tyIdx); callStmt = callInstantStmt; lexer.NextToken(); // skip the > } else { callStmt = mod.CurFuncCodeMemPool()->New(mod, o); } callStmt->SetPUIdx(pIdx); MIRFunction *callee = GlobalTables::GetFunctionTable().GetFuncTable()[pIdx]; callee->GetFuncSymbol()->SetAppearsInCode(true); if (callee->GetName() == "setjmp") { mod.CurFunction()->SetHasSetjmp(); } MapleVector opndsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseExprNaryOperand(opndsVec)) { return false; } callStmt->SetNOpnd(opndsVec); callStmt->SetNumOpnds(opndsVec.size()); if (hasAssigned) { CallReturnVector retsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseCallReturns(retsVec)) { return false; } if (!hasInstant) { DEBUG_ASSERT(callStmt != nullptr, "callstmt is null in MIRParser::ParseStmtCall"); callStmt->SetReturnVec(retsVec); } else { DEBUG_ASSERT(callInstantStmt != nullptr, "callinstantstmt is null in MIRParser::ParseStmtCall"); callInstantStmt->SetReturnVec(retsVec); } } lexer.NextToken(); stmt = callStmt; return true; } bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt, Opcode op) { // syntax: icall (, , ..., ) // icallassigned (, ..., ) { // dassign // dassign // . . . // dassign } // icallproto (, , ..., ) // icallprotoassigned (, , ..., ) { // dassign // dassign // . . . // dassign } IcallNode *iCallStmt = mod.CurFuncCodeMemPool()->New(mod, op); lexer.NextToken(); if (op == OP_icallproto || op == OP_icallprotoassigned) { TyIdx tyIdx(0); if (!ParseDerivedType(tyIdx)) { Error("error parsing type in ParseStmtIcall for icallproto at "); return false; } iCallStmt->SetRetTyIdx(tyIdx); } MapleVector opndsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseExprNaryOperand(opndsVec)) { return false; } iCallStmt->SetNOpnd(opndsVec); iCallStmt->SetNumOpnds(opndsVec.size()); if (op == OP_icallassigned || op == OP_icallprotoassigned) { CallReturnVector retsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseCallReturns(retsVec)) { return false; } iCallStmt->SetReturnVec(retsVec); } lexer.NextToken(); stmt = iCallStmt; return true; } bool MIRParser::ParseStmtIcall(StmtNodePtr &stmt) { return ParseStmtIcall(stmt, OP_icall); } bool MIRParser::ParseStmtIcallassigned(StmtNodePtr &stmt) { return ParseStmtIcall(stmt, OP_icallassigned); } bool MIRParser::ParseStmtIcallproto(StmtNodePtr &stmt) { return ParseStmtIcall(stmt, OP_icallproto); } bool MIRParser::ParseStmtIcallprotoassigned(StmtNodePtr &stmt) { return ParseStmtIcall(stmt, OP_icallprotoassigned); } bool MIRParser::ParseStmtIntrinsiccall(StmtNodePtr &stmt, bool isAssigned) { Opcode o = !isAssigned ? (lexer.GetTokenKind() == TK_intrinsiccall ? OP_intrinsiccall : OP_xintrinsiccall) : (lexer.GetTokenKind() == TK_intrinsiccallassigned ? OP_intrinsiccallassigned : OP_xintrinsiccallassigned); auto *intrnCallNode = mod.CurFuncCodeMemPool()->New(mod, o); lexer.NextToken(); if (o == !isAssigned ? OP_intrinsiccall : OP_intrinsiccallassigned) { intrnCallNode->SetIntrinsic(GetIntrinsicID(lexer.GetTokenKind())); } else { intrnCallNode->SetIntrinsic(static_cast(lexer.GetTheIntVal())); } lexer.NextToken(); MapleVector opndsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseExprNaryOperand(opndsVec)) { return false; } intrnCallNode->SetNOpnd(opndsVec); intrnCallNode->SetNumOpnds(opndsVec.size()); if (isAssigned) { CallReturnVector retsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseCallReturns(retsVec)) { return false; } // store return type of IntrinsiccallNode if (retsVec.size() == 1 && retsVec[0].first.Idx() != 0) { MIRSymbol *retSymbol = curFunc->GetSymTab()->GetSymbolFromStIdx(retsVec[0].first.Idx()); MIRType *retType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(retSymbol->GetTyIdx()); CHECK_FATAL(retType != nullptr, "rettype is null in MIRParser::ParseStmtIntrinsiccallAssigned"); intrnCallNode->SetPrimType(retType->GetPrimType()); } intrnCallNode->SetReturnVec(retsVec); } stmt = intrnCallNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtIntrinsiccall(StmtNodePtr &stmt) { return ParseStmtIntrinsiccall(stmt, false); } bool MIRParser::ParseStmtIntrinsiccallassigned(StmtNodePtr &stmt) { return ParseStmtIntrinsiccall(stmt, true); } bool MIRParser::ParseStmtIntrinsiccallwithtype(StmtNodePtr &stmt, bool isAssigned) { Opcode o = (!isAssigned) ? OP_intrinsiccallwithtype : OP_intrinsiccallwithtypeassigned; IntrinsiccallNode *intrnCallNode = mod.CurFuncCodeMemPool()->New(mod, o); TokenKind tk = lexer.NextToken(); TyIdx tyIdx(0); if (IsPrimitiveType(tk)) { if (!ParsePrimType(tyIdx)) { Error("expect primitive type in ParseStmtIntrinsiccallwithtype but get "); return false; } } else if (!ParseDerivedType(tyIdx)) { Error("error parsing type in ParseStmtIntrinsiccallwithtype at "); return false; } intrnCallNode->SetTyIdx(tyIdx); intrnCallNode->SetIntrinsic(GetIntrinsicID(lexer.GetTokenKind())); lexer.NextToken(); MapleVector opndsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseExprNaryOperand(opndsVec)) { return false; } intrnCallNode->SetNOpnd(opndsVec); intrnCallNode->SetNumOpnds(opndsVec.size()); if (isAssigned) { CallReturnVector retsVec(mod.CurFuncCodeMemPoolAllocator()->Adapter()); if (!ParseCallReturns(retsVec)) { return false; } // store return type of IntrinsiccallNode if (retsVec.size() == 1 && retsVec[0].first.Idx() != 0) { MIRSymbol *retSymbol = curFunc->GetSymTab()->GetSymbolFromStIdx(retsVec[0].first.Idx()); MIRType *retType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(retSymbol->GetTyIdx()); CHECK_FATAL(retType != nullptr, "rettype is null in MIRParser::ParseStmtIntrinsiccallwithtypeAssigned"); intrnCallNode->SetPrimType(retType->GetPrimType()); } intrnCallNode->SetReturnVec(retsVec); } stmt = intrnCallNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtIntrinsiccallwithtype(StmtNodePtr &stmt) { return ParseStmtIntrinsiccallwithtype(stmt, false); } bool MIRParser::ParseStmtIntrinsiccallwithtypeassigned(StmtNodePtr &stmt) { return ParseStmtIntrinsiccallwithtype(stmt, true); } bool MIRParser::ParseCallReturnPair(CallReturnPair &retpair) { bool isst = (lexer.GetTokenKind() == TK_dassign); if (isst) { // parse %i lexer.NextToken(); StIdx stidx; // How to use islocal?? if (!ParseDeclaredSt(stidx)) { return false; } if (lexer.GetTokenKind() == TK_lname) { MIRSymbolTable *lSymTab = mod.CurFunction()->GetSymTab(); MIRSymbol *lSym = lSymTab->GetSymbolFromStIdx(stidx.Idx(), 0); DEBUG_ASSERT(lSym != nullptr, "lsym MIRSymbol is null"); if (lSym->GetName().find("L_STR") == 0) { MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(lSym->GetTyIdx()); auto *ptrTy = static_cast(ty->CopyMIRTypeNode()); DEBUG_ASSERT(ptrTy != nullptr, "null ptr check"); ptrTy->SetPrimType(GetExactPtrPrimType()); TyIdx newTyidx = GlobalTables::GetTypeTable().GetOrCreateMIRType(ptrTy); delete ptrTy; lSym->SetTyIdx(newTyidx); } } if (stidx.FullIdx() == 0) { Error("expect a symbol parsing call return assignment but get"); return false; } uint16 fieldId = 0; TokenKind nextToken = lexer.NextToken(); // parse field id if (nextToken == TK_intconst) { fieldId = lexer.GetTheIntVal(); lexer.NextToken(); } RegFieldPair regFieldPair; regFieldPair.SetFieldID(fieldId); retpair = CallReturnPair(stidx, regFieldPair); } else { // parse type lexer.NextToken(); TyIdx tyidx(0); bool ret = ParsePrimType(tyidx); if (ret != true) { Error("call ParsePrimType failed in ParseCallReturns"); return false; } if (tyidx == 0u) { Error("expect primitive type but get "); return false; } PrimType ptype = GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx); PregIdx pregIdx; if (lexer.GetTokenKind() == TK_specialreg) { if (!ParseSpecialReg(pregIdx)) { Error("expect specialreg parsing callassign CallReturnVector"); return false; } } else if (lexer.GetTokenKind() == TK_preg) { if (!ParsePseudoReg(ptype, pregIdx)) { Error("expect pseudoreg parsing callassign CallReturnVector"); return false; } } else { Error("expect special or pseudo register but get "); return false; } DEBUG_ASSERT(pregIdx > 0, "register number is zero"); DEBUG_ASSERT(pregIdx <= 0xffff, "register number is over 16 bits"); RegFieldPair regFieldPair; regFieldPair.SetPregIdx(pregIdx); retpair = CallReturnPair(StIdx(), regFieldPair); } return true; } bool MIRParser::ParseCallReturns(CallReturnVector &retsvec) { // { // dassign // dassign // . . . // dassign } // OR // { // regassign // regassign // regassign // } if (lexer.NextToken() != TK_lbrace) { Error("expect { parsing call return values. "); return false; } TokenKind tk = lexer.NextToken(); CallReturnPair retpair; while (tk != TK_rbrace) { if (lexer.GetTokenKind() != TK_dassign && lexer.GetTokenKind() != TK_regassign) { Error("expect dassign/regassign but get "); return false; } if (!ParseCallReturnPair(retpair)) { Error("error parsing call returns. "); return false; } retsvec.push_back(retpair); tk = lexer.GetTokenKind(); } return true; } bool MIRParser::ParseStmtAsm(StmtNodePtr &stmt) { AsmNode *asmNode = mod.CurFuncCodeMemPool()->New(&mod.GetCurFuncCodeMPAllocator()); mod.CurFunction()->SetHasAsm(); lexer.NextToken(); // parse qualifiers while (lexer.GetTokenKind() == TK_volatile || lexer.GetTokenKind() == TK_inline || lexer.GetTokenKind() == TK_goto) { AsmQualifierKind qual; switch (lexer.GetTokenKind()) { case TK_volatile: { qual = kASMvolatile; break; } case TK_inline: { qual = kASMinline; break; } case TK_goto: default: { qual = kASMgoto; break; } } asmNode->SetQualifier(qual); lexer.NextToken(); } // parse open brace if (lexer.GetTokenKind() != TK_lbrace) { Error("Open brace not found parsing asm statement."); return false; } lexer.NextToken(); // parse asm string if (lexer.GetTokenKind() != TK_string) { Error("asm string not found parsing asm statement."); return false; } asmNode->asmString = lexer.GetName(); lexer.NextToken(); // parse first colon if (lexer.GetTokenKind() != TK_colon) { Error("first colon not found parsing asm statement."); return false; } lexer.NextToken(); // parse outputs UStrIdx uStrIdx; CallReturnPair retpair; while (lexer.GetTokenKind() == TK_string) { // parse an output constraint string uStrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); lexer.NextToken(); if (!ParseCallReturnPair(retpair)) { Error("error parsing call returns. "); return false; } asmNode->outputConstraints.push_back(uStrIdx); asmNode->asmOutputs.push_back(retpair); if (lexer.GetTokenKind() == TK_coma) { lexer.NextToken(); } } // parse second colon if (lexer.GetTokenKind() != TK_colon) { Error("second colon not found parsing asm statement."); return false; } lexer.NextToken(); // parse inputs while (lexer.GetTokenKind() == TK_string) { // parse an input constraint string uStrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); if (lexer.GetName()[0] == '+') { asmNode->SetHasWriteInputs(); } if (lexer.NextToken() != TK_lparen) { Error("expect ( but get "); return false; } lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExpression(expr)) { Error("ParseExpression failed"); return false; } if (lexer.GetTokenKind() != TK_rparen) { Error("expect ) but get "); return false; } asmNode->inputConstraints.push_back(uStrIdx); asmNode->GetNopnd().push_back(expr); if (lexer.NextToken() == TK_coma) { lexer.NextToken(); } } asmNode->SetNumOpnds(static_cast(asmNode->GetNopndSize())); // parse third colon if (lexer.GetTokenKind() != TK_colon) { Error("third colon not found parsing asm statement."); return false; } lexer.NextToken(); // parse clobber list while (lexer.GetTokenKind() == TK_string) { // parse an input constraint string uStrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); asmNode->clobberList.push_back(uStrIdx); if (lexer.NextToken() == TK_coma) { lexer.NextToken(); } } // parse fourth colon if (lexer.GetTokenKind() != TK_colon) { Error("fourth colon not found parsing asm statement."); return false; } lexer.NextToken(); // parse labels while (lexer.GetTokenKind() == TK_label) { GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labIdx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(strIdx); if (labIdx == 0) { labIdx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labIdx, strIdx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labIdx); } asmNode->gotoLabels.push_back(labIdx); if (lexer.NextToken() == TK_coma) { lexer.NextToken(); } } // parse closing brace if (lexer.GetTokenKind() != TK_rbrace) { Error("Closing brace not found parsing asm statement."); return false; } stmt = asmNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtSafeRegion(StmtNodePtr &stmt) { switch (lexer.GetTokenKind()) { case TK_safe: safeRegionFlag.push(true); break; case TK_unsafe: safeRegionFlag.push(false); break; case TK_endsafe: case TK_endunsafe: safeRegionFlag.pop(); break; default: Error("Only support safe/unsafe/endsafe/endunsafe."); return false; } (void)stmt; lexer.NextToken(); return true; } bool MIRParser::ParseStmtJsTry(StmtNodePtr &stmt) { auto *tryNode = mod.CurFuncCodeMemPool()->New(); lexer.NextToken(); // parse handler label if (lexer.GetTokenKind() == TK_intconst && lexer.GetTheIntVal() == 0) { tryNode->SetCatchOffset(0); } else { if (lexer.GetTokenKind() != TK_label) { Error("expect handler label in try but get "); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labidx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(stridx); if (labidx == 0) { labidx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labidx, stridx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labidx); } tryNode->SetCatchOffset(labidx); } lexer.NextToken(); // parse finally label if (lexer.GetTokenKind() == TK_intconst && lexer.GetTheIntVal() == 0) { tryNode->SetFinallyOffset(0); } else { if (lexer.GetTokenKind() != TK_label) { Error("expect finally label in try but get "); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labidx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(stridx); if (labidx == 0) { labidx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labidx, stridx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labidx); } tryNode->SetFinallyOffset(labidx); } stmt = tryNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtTry(StmtNodePtr &stmt) { auto *tryNode = mod.CurFuncCodeMemPool()->New(mod); lexer.NextToken(); DEBUG_ASSERT(lexer.GetTokenKind() == TK_lbrace, "expect left brace in try but get "); lexer.NextToken(); // parse handler label while (lexer.GetTokenKind() != TK_rbrace) { if (lexer.GetTokenKind() != TK_label) { Error("expect handler label in try but get "); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labidx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(stridx); if (labidx == 0) { labidx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labidx, stridx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labidx); } tryNode->AddOffset(labidx); lexer.NextToken(); } stmt = tryNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtCatch(StmtNodePtr &stmt) { auto *catchNode = mod.CurFuncCodeMemPool()->New(mod); lexer.NextToken(); DEBUG_ASSERT(lexer.GetTokenKind() == TK_lbrace, "expect left brace in catch but get "); lexer.NextToken(); while (lexer.GetTokenKind() != TK_rbrace) { TyIdx tyidx(0); if (!ParseType(tyidx)) { Error("expect type parsing java catch statement"); return false; } catchNode->PushBack(tyidx); } catchNode->SetNumOpnds(0); stmt = catchNode; lexer.NextToken(); return true; } bool MIRParser::ParseUnaryStmt(Opcode op, StmtNodePtr &stmt) { lexer.NextToken(); auto *throwStmt = mod.CurFuncCodeMemPool()->New(op); stmt = throwStmt; BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } throwStmt->SetOpnd(expr, 0); lexer.NextToken(); return true; } bool MIRParser::ParseUnaryStmtThrow(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_throw, stmt); } bool MIRParser::ParseUnaryStmtDecRef(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_decref, stmt); } bool MIRParser::ParseUnaryStmtIncRef(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_incref, stmt); } bool MIRParser::ParseUnaryStmtDecRefReset(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_decrefreset, stmt); } bool MIRParser::ParseUnaryStmtIGoto(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_igoto, stmt); } bool MIRParser::ParseUnaryStmtEval(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_eval, stmt); } bool MIRParser::ParseUnaryStmtFree(StmtNodePtr &stmt) { return ParseUnaryStmt(OP_free, stmt); } bool MIRParser::ParseUnaryStmtCallAssertNonNull(StmtNodePtr &stmt) { std::string funcName; std::string stmtFuncName; int index = 0; if (!ParseCallAssertInfo(funcName, &index, stmtFuncName)) { Error("ParseCallAssertInfo failed"); return false; } lexer.NextToken(); GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName); GStrIdx stmtstridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(stmtFuncName); stmt = mod.CurFuncCodeMemPool()->New(OP_callassertnonnull, stridx, index, stmtstridx); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } stmt->SetOpnd(expr, 0); lexer.NextToken(); return true; } bool MIRParser::ParseAssertInfo(std::string &funcName) { if (lexer.NextToken() != TK_langle) { Error("expect < parsing safey assert check "); return false; } if (lexer.NextToken() != TK_fname) { Error("expect &funcname parsing parsing safey assert check "); return false; } funcName = lexer.GetName(); if (lexer.NextToken() != TK_rangle) { Error("expect > parsing safey assert check "); return false; } return true; } bool MIRParser::ParseUnaryStmtAssertNonNullCheck(Opcode op, StmtNodePtr &stmt) { std::string funcName; if (!ParseAssertInfo(funcName)) { Error("ParseAssertInfo failed"); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName); lexer.NextToken(); stmt = mod.CurFuncCodeMemPool()->New(op, stridx); BaseNode *expr = nullptr; if (!ParseExprOneOperand(expr)) { return false; } stmt->SetOpnd(expr, 0); lexer.NextToken(); return true; } bool MIRParser::ParseUnaryStmtAssertNonNull(StmtNodePtr &stmt) { if (mod.IsCModule()) { return ParseUnaryStmtAssertNonNullCheck(OP_assertnonnull, stmt); } else { return ParseUnaryStmt(OP_assertnonnull, stmt); } } bool MIRParser::ParseUnaryStmtAssignAssertNonNull(StmtNodePtr &stmt) { return ParseUnaryStmtAssertNonNullCheck(OP_assignassertnonnull, stmt); } bool MIRParser::ParseUnaryStmtReturnAssertNonNull(StmtNodePtr &stmt) { return ParseUnaryStmtAssertNonNullCheck(OP_returnassertnonnull, stmt); } bool MIRParser::ParseStmtMarker(StmtNodePtr &stmt) { Opcode op; switch (paramTokenKindForStmt) { case TK_jscatch: op = OP_jscatch; break; case TK_finally: op = OP_finally; break; case TK_cleanuptry: op = OP_cleanuptry; break; case TK_endtry: op = OP_endtry; break; case TK_retsub: op = OP_retsub; break; case TK_membaracquire: op = OP_membaracquire; break; case TK_membarrelease: op = OP_membarrelease; break; case TK_membarstoreload: op = OP_membarstoreload; break; case TK_membarstorestore: op = OP_membarstorestore; break; default: return false; } auto *stmtNode = mod.CurFuncCodeMemPool()->New(op); stmt = stmtNode; lexer.NextToken(); return true; } bool MIRParser::ParseStmtGosub(StmtNodePtr &stmt) { if (lexer.NextToken() != TK_label) { Error("expect finally label in gosub but get "); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); LabelIdx labidx = mod.CurFunction()->GetLabelTab()->GetLabelIdxFromStrIdx(stridx); if (labidx == 0) { labidx = mod.CurFunction()->GetLabelTab()->CreateLabel(); mod.CurFunction()->GetLabelTab()->SetSymbolFromStIdx(labidx, stridx); mod.CurFunction()->GetLabelTab()->AddToStringLabelMap(labidx); } auto *goSubNode = mod.CurFuncCodeMemPool()->New(OP_gosub); goSubNode->SetOffset(labidx); stmt = goSubNode; lexer.NextToken(); return true; } bool MIRParser::ParseBinaryStmt(StmtNodePtr &stmt, Opcode op) { auto *assStmt = mod.CurFuncCodeMemPool()->New(op); lexer.NextToken(); BaseNode *opnd0 = nullptr; BaseNode *opnd1 = nullptr; if (!ParseExprTwoOperand(opnd0, opnd1)) { return false; } assStmt->SetBOpnd(opnd0, 0); assStmt->SetBOpnd(opnd1, 1); stmt = assStmt; lexer.NextToken(); return true; } bool MIRParser::ParseNaryStmtAssert(StmtNodePtr &stmt, Opcode op) { std::string funcName; if (!ParseAssertInfo(funcName)) { Error("ParseAssertInfo failed"); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName); auto *assStmt = mod.CurFuncCodeMemPool()->New(mod, op, stridx); if (!ParseNaryExpr(*assStmt)) { Error("ParseNaryStmtAssert failed"); return false; } assStmt->SetNumOpnds(static_cast(assStmt->GetNopndSize())); stmt = assStmt; lexer.NextToken(); return true; } bool MIRParser::ParseNaryStmtAssertGE(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_assertge); } bool MIRParser::ParseNaryStmtAssertLT(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_assertlt); } bool MIRParser::ParseNaryStmtReturnAssertLE(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_returnassertle); } bool MIRParser::ParseNaryStmtAssignAssertLE(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_assignassertle); } bool MIRParser::ParseNaryStmtCalcassertGE(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_calcassertge); } bool MIRParser::ParseNaryStmtCalcassertLT(StmtNodePtr &stmt) { return ParseNaryStmtAssert(stmt, OP_calcassertlt); } bool MIRParser::ParseCallAssertInfo(std::string &funcName, int *paramIndex, std::string &stmtFuncName) { if (lexer.NextToken() != TK_langle) { Error("expect < parsing safey call check "); return false; } if (lexer.NextToken() != TK_fname) { Error("expect &funcname parsing parsing safey call check "); return false; } funcName = lexer.GetName(); if (lexer.NextToken() != TK_coma) { Error("expect , parsing parsing safey call check "); return false; } if (lexer.NextToken() != TK_intconst) { Error("expect intconst parsing parsing safey call check "); return false; } *paramIndex = static_cast(lexer.GetTheIntVal()); if (lexer.NextToken() != TK_coma) { Error("expect , parsing parsing safey call check "); return false; } if (lexer.NextToken() != TK_fname) { Error("expect &stmtfuncname parsing parsing safey call check "); return false; } stmtFuncName = lexer.GetName(); if (lexer.NextToken() != TK_rangle) { Error("expect > parsing parsing safey call check "); return false; } return true; } bool MIRParser::ParseNaryStmtCallAssertLE(StmtNodePtr &stmt) { std::string funcName; std::string stmtFuncName; int index = 0; if (!ParseCallAssertInfo(funcName, &index, stmtFuncName)) { Error("ParseCallAssertInfo failed"); return false; } GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcName); GStrIdx stmtstridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(stmtFuncName); auto *assStmt = mod.CurFuncCodeMemPool()->New(mod, OP_callassertle, stridx, index, stmtstridx); if (!ParseNaryExpr(*assStmt)) { Error("ParseNaryExpr failed"); return false; } assStmt->SetNumOpnds(static_cast(assStmt->GetNopndSize())); stmt = assStmt; lexer.NextToken(); return true; } bool MIRParser::ParseNaryExpr(NaryStmtNode &stmtNode) { if (lexer.NextToken() != TK_lparen) { Error("expect ( parsing NaryExpr "); return false; } (void)lexer.NextToken(); // skip TK_lparen while (lexer.GetTokenKind() != TK_rparen) { BaseNode *expr = nullptr; if (!ParseExpression(expr)) { Error("ParseStmtReturn failed"); return false; } stmtNode.GetNopnd().push_back(expr); if (lexer.GetTokenKind() != TK_coma && lexer.GetTokenKind() != TK_rparen) { Error("expect , or ) parsing NaryStmt"); return false; } if (lexer.GetTokenKind() == TK_coma) { lexer.NextToken(); } } return true; } bool MIRParser::ParseNaryStmt(StmtNodePtr &stmt, Opcode op) { auto *stmtReturn = mod.CurFuncCodeMemPool()->New(mod, op); if (op == OP_syncenter) { // old code reconstruct later if (lexer.NextToken() != TK_lparen) { Error("expect return with ( but get "); return false; } lexer.NextToken(); BaseNode *expr = nullptr; if (!ParseExpression(expr)) { Error("ParseStmtReturn failed"); return false; } stmtReturn->GetNopnd().push_back(expr); if (lexer.GetTokenKind() == TK_coma) { lexer.NextToken(); BaseNode *exprSync = nullptr; if (!ParseExpression(exprSync)) { Error("ParseStmtReturn failed"); return false; } stmtReturn->GetNopnd().push_back(exprSync); } else { MIRType *intType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(static_cast(PTY_i32)); // default 2 for __sync_enter_fast() MIRIntConst *intConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(2, *intType); ConstvalNode *exprConst = mod.GetMemPool()->New(); exprConst->SetPrimType(PTY_i32); exprConst->SetConstVal(intConst); stmtReturn->GetNopnd().push_back(exprConst); stmtReturn->SetNumOpnds(stmtReturn->GetNopndSize()); } if (lexer.GetTokenKind() != TK_rparen) { Error("expect ) parsing NaryStmt"); return false; } } else if (!ParseNaryExpr(*stmtReturn)) { Error("ParseNaryExpr failed"); return false; } stmtReturn->SetNumOpnds(stmtReturn->GetNopndSize()); stmt = stmtReturn; lexer.NextToken(); return true; } bool MIRParser::ParseNaryStmtReturn(StmtNodePtr &stmt) { return ParseNaryStmt(stmt, OP_return); } bool MIRParser::ParseNaryStmtSyncEnter(StmtNodePtr &stmt) { return ParseNaryStmt(stmt, OP_syncenter); } bool MIRParser::ParseNaryStmtSyncExit(StmtNodePtr &stmt) { return ParseNaryStmt(stmt, OP_syncexit); } bool MIRParser::ParseLoc() { if (lexer.NextToken() != TK_intconst) { Error("expect intconst in LOC but get "); return false; } lastFileNum = lexer.GetTheIntVal(); if (lexer.NextToken() != TK_intconst) { Error("expect intconst in LOC but get "); return false; } lastLineNum = lexer.GetTheIntVal(); if (firstLineNum == 0) { firstLineNum = lastLineNum; } if (lexer.NextToken() == TK_intconst) { // optional column number lastColumnNum = static_cast(lexer.GetTheIntVal()); lexer.NextToken(); } return true; } bool MIRParser::ParseLocStmt(StmtNodePtr &) { return ParseLoc(); } bool MIRParser::ParseStatement(StmtNodePtr &stmt) { paramTokenKindForStmt = lexer.GetTokenKind(); uint32 mplNum = lexer.GetLineNum(); uint32 lnum = lastLineNum; uint32 fnum = lastFileNum; uint16 cnum = lastColumnNum; std::map::iterator itFuncPtr = funcPtrMapForParseStmt.find(paramTokenKindForStmt); if (itFuncPtr != funcPtrMapForParseStmt.end()) { if (!(this->*(itFuncPtr->second))(stmt)) { return false; } } else { return false; } if (stmt && stmt->GetSrcPos().MplLineNum() == 0) { stmt->GetSrcPos().SetFileNum(fnum); stmt->GetSrcPos().SetLineNum(lnum); stmt->GetSrcPos().SetColumn(cnum); stmt->GetSrcPos().SetMplLineNum(mplNum); if (safeRegionFlag.top()) { stmt->SetInSafeRegion(); } } return true; } /* parse the statements enclosed by { and } */ bool MIRParser::ParseStmtBlock(BlockNodePtr &blk) { if (lexer.GetTokenKind() != TK_lbrace) { Error("expect { for func body but get "); return false; } blk = mod.CurFuncCodeMemPool()->New(); MIRFunction *fn = mod.CurFunction(); paramCurrFuncForParseStmtBlock = fn; lexer.NextToken(); // Insert _mcount for PI. if (mod.GetWithProfileInfo()) { StmtNode *stmtt = nullptr; if (!ParseStmtCallMcount(stmtt)) { return false; } blk->AddStatement(stmtt); } while (true) { TokenKind stmtTk = lexer.GetTokenKind(); // calculate the mpl file line number mplNum here to get accurate result uint32 mplNum = lexer.GetLineNum(); if (IsStatement(stmtTk)) { ParseStmtBlockForSeenComment(blk, mplNum); StmtNode *stmt = nullptr; if (!ParseStatement(stmt)) { Error("ParseStmtBlock failed when parsing a statement"); return false; } if (stmt != nullptr) { // stmt is nullptr if it is a LOC blk->AddStatement(stmt); } } else { std::map::iterator itFuncPtr = funcPtrMapForParseStmtBlock.find(stmtTk); if (itFuncPtr == funcPtrMapForParseStmtBlock.end()) { if (stmtTk == TK_rbrace) { ParseStmtBlockForSeenComment(blk, mplNum); lexer.NextToken(); return true; } else { Error("expect } or var or statement for func body but get "); return false; } } else { if (!(this->*(itFuncPtr->second))()) { return false; } } } } } void MIRParser::ParseStmtBlockForSeenComment(BlockNodePtr blk, uint32 mplNum) { if (Options::noComment) { lexer.seenComments.clear(); return; } // collect accumulated comments into comment statement nodes if (!lexer.seenComments.empty()) { for (size_t i = 0; i < lexer.seenComments.size(); ++i) { auto *cmnt = mod.CurFuncCodeMemPool()->New(mod); cmnt->SetComment(lexer.seenComments[i]); SetSrcPos(cmnt->GetSrcPos(), mplNum); blk->AddStatement(cmnt); } lexer.seenComments.clear(); } } bool MIRParser::ParseStmtBlockForVar(TokenKind stmtTK) { MIRFunction *fn = paramCurrFuncForParseStmtBlock; MIRSymbol *st = fn->GetSymTab()->CreateSymbol(kScopeLocal); st->SetStorageClass(kScAuto); st->SetSKind(kStVar); SetSrcPos(st->GetSrcPosition(), lexer.GetLineNum()); if (stmtTK == TK_tempvar) { st->SetIsTmp(true); } if (!ParseDeclareVar(*st)) { return false; } if (!fn->GetSymTab()->AddToStringSymbolMap(*st)) { Error("duplicate declare symbol parse function "); return false; } if (!ParseDeclareVarInitValue(*st)) { return false; } return true; } bool MIRParser::ParseStmtBlockForVar() { return ParseStmtBlockForVar(TK_var); } bool MIRParser::ParseStmtBlockForTempVar() { return ParseStmtBlockForVar(TK_tempvar); } bool MIRParser::ParseStmtBlockForReg() { lexer.NextToken(); if (lexer.GetTokenKind() != TK_preg) { Error("expect %%preg after reg"); return false; } PregIdx pregIdx; if (!ParsePseudoReg(PTY_ref, pregIdx)) { return false; } MIRPreg *preg = mod.CurFunction()->GetPregTab()->PregFromPregIdx(pregIdx); TyIdx tyidx(0); if (!ParseType(tyidx)) { Error("ParseDeclareVar failed when parsing the type"); return false; } DEBUG_ASSERT(tyidx > 0u, "parse declare var failed "); MIRType *mirType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyidx); preg->SetMIRType(mirType); if (lexer.GetTokenKind() == TK_intconst) { int64 theIntVal = lexer.GetTheIntVal(); if (theIntVal != 0 && theIntVal != 1) { Error("parseDeclareReg failed"); return false; } preg->SetNeedRC(theIntVal == 0 ? false : true); } else { Error("parseDeclareReg failed"); return false; } lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForType() { paramParseLocalType = true; if (!ParseTypedef()) { return false; } return true; } bool MIRParser::ParseStmtBlockForFrameSize() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; lexer.NextToken(); if (lexer.GetTokenKind() != TK_intconst) { Error("expect integer after frameSize but get "); return false; } fn->SetFrameSize(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForUpformalSize() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; lexer.NextToken(); if (lexer.GetTokenKind() != TK_intconst) { Error("expect integer after upFormalSize but get "); return false; } fn->SetUpFormalSize(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForModuleID() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; lexer.NextToken(); if (lexer.GetTokenKind() != TK_intconst) { Error("expect integer after moduleid but get "); return false; } fn->SetModuleID(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForFuncSize() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; lexer.NextToken(); if (lexer.GetTokenKind() != TK_intconst) { Error("expect integer after funcSize but get "); return false; } fn->SetFuncSize(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForFuncID() { // funcid is for debugging purpose MIRFunction *fn = paramCurrFuncForParseStmtBlock; lexer.NextToken(); if (lexer.GetTokenKind() != TK_intconst) { Error("expect integer after funcid but get "); return false; } fn->SetPuidxOrigin(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseStmtBlockForFormalWordsTypeTagged() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; uint8 *addr = ParseWordsInfo(fn->GetUpFormalSize()); if (addr == nullptr) { Error("parser error for formalwordstypetagged"); return false; } fn->SetFormalWordsTypeTagged(addr); return true; } bool MIRParser::ParseStmtBlockForLocalWordsTypeTagged() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; uint8 *addr = ParseWordsInfo(fn->GetFrameSize()); if (addr == nullptr) { Error("parser error for localWordsTypeTagged"); return false; } fn->SetLocalWordsTypeTagged(addr); return true; } bool MIRParser::ParseStmtBlockForFormalWordsRefCounted() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; uint8 *addr = ParseWordsInfo(fn->GetUpFormalSize()); if (addr == nullptr) { Error("parser error for formalwordsrefcounted"); return false; } fn->SetFormalWordsRefCounted(addr); return true; } bool MIRParser::ParseStmtBlockForLocalWordsRefCounted() { MIRFunction *fn = paramCurrFuncForParseStmtBlock; uint8 *addr = ParseWordsInfo(fn->GetFrameSize()); if (addr == nullptr) { Error("parser error for localwordsrefcounted"); return false; } fn->SetLocalWordsRefCounted(addr); return true; } bool MIRParser::ParseStmtBlockForFuncInfo() { lexer.NextToken(); if (!ParseFuncInfo()) { return false; } return true; } /* exprparser */ static Opcode GetUnaryOp(TokenKind tk) { switch (tk) { #define UNARYOP(P) \ case TK_##P: \ return OP_##P; #include "unary_op.def" #undef UNARYOP default: return OP_undef; } } static Opcode GetBinaryOp(TokenKind tk) { switch (tk) { #define BINARYOP(P) \ case TK_##P: \ return OP_##P; #include "binary_op.def" #undef BINARYOP default: return OP_undef; } } static Opcode GetConvertOp(TokenKind tk) { switch (tk) { case TK_ceil: return OP_ceil; case TK_cvt: return OP_cvt; case TK_floor: return OP_floor; case TK_round: return OP_round; case TK_trunc: return OP_trunc; default: return OP_undef; } } bool MIRParser::ParseExprOneOperand(BaseNodePtr &expr) { if (lexer.GetTokenKind() != TK_lparen) { Error("expect ( parsing operand parsing unary "); return false; } lexer.NextToken(); if (!ParseExpression(expr)) { Error("expect expression as openrand of unary expression "); return false; } if (lexer.GetTokenKind() != TK_rparen) { Error("expect ) parsing operand parsing unary "); return false; } return true; } bool MIRParser::ParseExprTwoOperand(BaseNodePtr &opnd0, BaseNodePtr &opnd1) { if (lexer.GetTokenKind() != TK_lparen) { Error("expect ( parsing operand parsing unary "); return false; } lexer.NextToken(); if (!ParseExpression(opnd0)) { return false; } if (lexer.GetTokenKind() != TK_coma) { Error("expect , between two operands but get "); return false; } lexer.NextToken(); if (!ParseExpression(opnd1)) { return false; } if (lexer.GetTokenKind() != TK_rparen) { Error("expect ) parsing operand parsing unary "); return false; } return true; } bool MIRParser::ParseExprNaryOperand(MapleVector &opndVec) { if (lexer.GetTokenKind() != TK_lparen) { Error("expect ( parsing operand parsing nary operands "); return false; } TokenKind tk = lexer.NextToken(); while (tk != TK_rparen) { BaseNode *opnd = nullptr; if (!ParseExpression(opnd)) { Error("expect expression parsing nary operands "); return false; } opndVec.push_back(opnd); tk = lexer.GetTokenKind(); if (tk == TK_coma) { tk = lexer.NextToken(); } } return true; } bool MIRParser::ParseDeclaredSt(StIdx &stidx) { TokenKind varTk = lexer.GetTokenKind(); stidx.SetFullIdx(0); GStrIdx stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); if (varTk == TK_gname) { stidx = GlobalTables::GetGsymTable().GetStIdxFromStrIdx(stridx); if (stidx.FullIdx() == 0) { MIRSymbol *st = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal); st->SetNameStrIdx(stridx); st->SetSKind(kStVar); (void)GlobalTables::GetGsymTable().AddToStringSymbolMap(*st); stidx = GlobalTables::GetGsymTable().GetStIdxFromStrIdx(stridx); return true; } } else if (varTk == TK_lname) { stidx = mod.CurFunction()->GetSymTab()->GetStIdxFromStrIdx(stridx); if (stidx.FullIdx() == 0) { Error("local symbol not declared "); return false; } } else { Error("expect global/local name but get "); return false; } return true; } void MIRParser::CreateFuncMIRSymbol(PUIdx &puidx, GStrIdx strIdx) { MIRSymbol *funcSt = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal); funcSt->SetNameStrIdx(strIdx); (void)GlobalTables::GetGsymTable().AddToStringSymbolMap(*funcSt); funcSt->SetStorageClass(kScText); funcSt->SetSKind(kStFunc); funcSt->SetNeedForwDecl(); auto *fn = mod.GetMemPool()->New(&mod, funcSt->GetStIdx()); puidx = static_cast(GlobalTables::GetFunctionTable().GetFuncTable().size()); fn->SetPuidx(puidx); GlobalTables::GetFunctionTable().GetFuncTable().push_back(fn); funcSt->SetFunction(fn); if (options & kParseInlineFuncBody) { funcSt->SetIsTmpUnused(true); } } bool MIRParser::ParseDeclaredFunc(PUIdx &puidx) { GStrIdx stridx = GlobalTables::GetStrTable().GetStrIdxFromName(lexer.GetName()); if (stridx == 0u) { stridx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); } StIdx stidx = GlobalTables::GetGsymTable().GetStIdxFromStrIdx(stridx); if (stidx.FullIdx() == 0) { CreateFuncMIRSymbol(puidx, stridx); return true; } MIRSymbol *st = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); DEBUG_ASSERT(st != nullptr, "null ptr check"); if (st->GetSKind() != kStFunc) { Error("function name not declared as function"); return false; } MIRFunction *func = st->GetFunction(); puidx = func->GetPuidx(); st->SetAppearsInCode(true); return true; } bool MIRParser::ParseExprDread(BaseNodePtr &expr) { if (lexer.GetTokenKind() != TK_dread) { Error("expect dread but get "); return false; } AddrofNode *dexpr = mod.CurFuncCodeMemPool()->New(OP_dread); expr = dexpr; lexer.NextToken(); TyIdx tyidx(0); bool parseRet = ParsePrimType(tyidx); if (tyidx == 0u || !parseRet) { Error("expect primitive type but get "); return false; } expr->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect a symbol ParseExprDread failed"); return false; } dexpr->SetStIdx(stidx); TokenKind endtk = lexer.NextToken(); if (endtk == TK_intconst) { dexpr->SetFieldID(lexer.GetTheIntVal()); lexer.NextToken(); } else if (!IsDelimitationTK(endtk)) { Error("expect , or ) delimitation token but get "); return false; } else { dexpr->SetFieldID(0); } if (!dexpr->CheckNode(mod)) { Error("dread is not legal"); return false; } return true; } bool MIRParser::ParseExprDreadoff(BaseNodePtr &expr) { if (lexer.GetTokenKind() != TK_dreadoff) { Error("expect dreadoff but get "); return false; } DreadoffNode *dexpr = mod.CurFuncCodeMemPool()->New(OP_dreadoff); expr = dexpr; lexer.NextToken(); TyIdx tyidx(0); bool parseRet = ParsePrimType(tyidx); if (tyidx == 0u || !parseRet) { Error("expect primitive type but get "); return false; } expr->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect a symbol ParseExprDread failed"); return false; } dexpr->stIdx = stidx; TokenKind endtk = lexer.NextToken(); if (endtk == TK_intconst) { dexpr->offset = static_cast(lexer.GetTheIntVal()); lexer.NextToken(); } else { Error("expect integer offset but get "); return false; } return true; } bool MIRParser::ParseExprRegread(BaseNodePtr &expr) { auto *regRead = mod.CurFuncCodeMemPool()->New(); expr = regRead; lexer.NextToken(); TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { return false; } if (tyidx == 0u) { Error("expect primitive type but get "); return false; } expr->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); if (lexer.GetTokenKind() == TK_specialreg) { PregIdx tempPregIdx = regRead->GetRegIdx(); bool isSuccess = ParseSpecialReg(tempPregIdx); regRead->SetRegIdx(tempPregIdx); return isSuccess; } if (lexer.GetTokenKind() == TK_preg) { PregIdx tempPregIdx = regRead->GetRegIdx(); bool isSuccess = ParsePseudoReg(regRead->GetPrimType(), tempPregIdx); regRead->SetRegIdx(tempPregIdx); return isSuccess; } Error("expect special or pseudo register but get "); return false; } bool MIRParser::ParseExprConstval(BaseNodePtr &expr) { auto *exprConst = mod.CurFuncCodeMemPool()->New(); TokenKind typeTk = lexer.NextToken(); if (!IsPrimitiveType(typeTk)) { Error("expect type for GetConstVal but get "); return false; } exprConst->SetPrimType(GetPrimitiveType(typeTk)); lexer.NextToken(); MIRConst *constVal = nullptr; if (!ParseScalarValue(constVal, *GlobalTables::GetTypeTable().GetPrimType(exprConst->GetPrimType()))) { Error("expect scalar type but get "); return false; } exprConst->SetConstVal(constVal); expr = exprConst; lexer.NextToken(); return true; } bool MIRParser::ParseExprConststr(BaseNodePtr &expr) { auto *strConst = mod.CurFuncCodeMemPool()->New(); TokenKind tk = lexer.NextToken(); if (!IsPrimitiveType(tk)) { Error("expect primitive type for conststr but get "); return false; } strConst->SetPrimType(GetPrimitiveType(tk)); if (!IsAddress(strConst->GetPrimType())) { Error("expect primitive type for conststr but get "); return false; } tk = lexer.NextToken(); if (tk != TK_string) { Error("expect string literal for conststr but get "); return false; } strConst->SetStrIdx(GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(lexer.GetName())); expr = strConst; lexer.NextToken(); return true; } bool MIRParser::ParseExprConststr16(BaseNodePtr &expr) { auto *str16Const = mod.CurFuncCodeMemPool()->New(); TokenKind tk = lexer.NextToken(); if (!IsPrimitiveType(tk)) { Error("expect primitive type for conststr16 but get "); return false; } str16Const->SetPrimType(GetPrimitiveType(tk)); if (!IsAddress(str16Const->GetPrimType())) { Error("expect primitive type for conststr16 but get "); return false; } tk = lexer.NextToken(); if (tk != TK_string) { Error("expect string literal for conststr16 but get "); return false; } // UTF-16 strings in mpl files are presented as UTF-8 strings // to keep the printable chars in ascii form // so we need to do a UTF8ToUTF16 conversion std::string str = lexer.GetName(); std::u16string str16; (void)namemangler::UTF8ToUTF16(str16, str); str16Const->SetStrIdx(GlobalTables::GetU16StrTable().GetOrCreateStrIdxFromName(str16)); expr = str16Const; lexer.NextToken(); return true; } bool MIRParser::ParseExprSizeoftype(BaseNodePtr &expr) { auto *exprSizeOfType = mod.CurFuncCodeMemPool()->New(); TokenKind typeTk = lexer.NextToken(); if (!IsPrimitiveType(typeTk)) { Error("expect type for GetConstVal but get "); return false; } exprSizeOfType->SetPrimType(GetPrimitiveType(typeTk)); lexer.NextToken(); TyIdx tyidx(0); if (!ParseType(tyidx)) { Error("expect type parsing array but get "); return false; } exprSizeOfType->SetTyIdx(tyidx); expr = exprSizeOfType; return true; } bool MIRParser::ParseExprFieldsDist(BaseNodePtr &expr) { TokenKind typeTk = lexer.NextToken(); if (!IsPrimitiveType(typeTk)) { Error("expect type for GetConstVal but get "); return false; } auto *node = mod.CurFuncCodeMemPool()->New(); node->SetPrimType(GetPrimitiveType(typeTk)); lexer.NextToken(); TyIdx tyIdx(0); if (!ParseType(tyIdx)) { Error("expect type parsing array but get "); return false; } node->SetTyIdx(tyIdx); TokenKind tk = lexer.GetTokenKind(); if (tk != TK_intconst) { Error("expect type int but get"); return false; } node->SetFiledID1(lexer.GetTheIntVal()); tk = lexer.NextToken(); if (tk != TK_intconst) { Error("expect type int but get"); return false; } node->SetFiledID2(lexer.GetTheIntVal()); lexer.NextToken(); expr = node; return true; } bool MIRParser::ParseExprBinary(BaseNodePtr &expr) { Opcode opcode = GetBinaryOp(lexer.GetTokenKind()); if (opcode == OP_undef) { Error("expect add operator but get "); return false; } auto *addExpr = mod.CurFuncCodeMemPool()->New(opcode); if (!IsPrimitiveType(lexer.NextToken())) { Error("expect type parsing binary operator but get "); return false; } addExpr->SetPrimType(GetPrimitiveType(lexer.GetTokenKind())); lexer.NextToken(); BaseNode *opnd0 = nullptr; BaseNode *opnd1 = nullptr; if (!ParseExprTwoOperand(opnd0, opnd1)) { return false; } addExpr->SetBOpnd(opnd0, 0); addExpr->SetBOpnd(opnd1, 1); expr = addExpr; lexer.NextToken(); return true; } bool MIRParser::ParseExprCompare(BaseNodePtr &expr) { Opcode opcode = GetBinaryOp(lexer.GetTokenKind()); auto *addExpr = mod.CurFuncCodeMemPool()->New(opcode); if (!IsPrimitiveType(lexer.NextToken())) { Error("expect type parsing compare operator but get "); return false; } addExpr->SetPrimType(GetPrimitiveType(lexer.GetTokenKind())); if (!IsPrimitiveType(lexer.NextToken())) { Error("expect operand type parsing compare operator but get "); return false; } addExpr->SetOpndType(GetPrimitiveType(lexer.GetTokenKind())); lexer.NextToken(); BaseNode *opnd0 = nullptr; BaseNode *opnd1 = nullptr; if (!ParseExprTwoOperand(opnd0, opnd1)) { return false; } addExpr->SetBOpnd(opnd0, 0); addExpr->SetBOpnd(opnd1, 1); expr = addExpr; lexer.NextToken(); return true; } bool MIRParser::ParseExprDepositbits(BaseNodePtr &expr) { // syntax: depositbits (, ) if (lexer.GetTokenKind() != TK_depositbits) { Error("expect depositbits but get "); return false; } auto *dpsbNode = mod.CurFuncCodeMemPool()->New(); expr = dpsbNode; PrimType ptyp = GetPrimitiveType(lexer.NextToken()); if (!IsPrimitiveInteger(ptyp)) { Error("expect but get "); return false; } dpsbNode->SetPrimType(ptyp); if (lexer.NextToken() != TK_intconst) { Error("expect bOffset but get "); return false; } dpsbNode->SetBitsOffset(lexer.GetTheIntVal()); if (lexer.NextToken() != TK_intconst) { Error("expect bSize but get "); return false; } dpsbNode->SetBitsSize(lexer.GetTheIntVal()); lexer.NextToken(); BaseNode *opnd0 = nullptr; BaseNode *opnd1 = nullptr; if (!ParseExprTwoOperand(opnd0, opnd1)) { Error("ParseExprDepositbits when parsing two operand"); return false; } dpsbNode->SetBOpnd(opnd0, 0); dpsbNode->SetBOpnd(opnd1, 1); lexer.NextToken(); return true; } bool MIRParser::ParseExprIreadIaddrof(IreadNode &expr) { // syntax : iread/iaddrof () if (!IsPrimitiveType(lexer.NextToken())) { Error("expect primitive type but get "); return false; } TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { return false; } expr.SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); tyidx = TyIdx(0); if (!ParseDerivedType(tyidx)) { Error("ParseExprIreadIaddrof failed when paring derived type"); return false; } expr.SetTyIdx(tyidx); if (lexer.GetTokenKind() == TK_intconst) { expr.SetFieldID(lexer.theIntVal); lexer.NextToken(); } BaseNode *opnd0 = nullptr; if (!ParseExprOneOperand(opnd0)) { return false; } expr.SetOpnd(opnd0, 0); lexer.NextToken(); return true; } bool MIRParser::ParseExprIread(BaseNodePtr &expr) { // syntax : iread () auto *iExpr = mod.CurFuncCodeMemPool()->New(OP_iread); if (!ParseExprIreadIaddrof(*iExpr)) { Error("ParseExprIread failed when trying to parse addof"); return false; } expr = iExpr; return true; } bool MIRParser::ParseExprIaddrof(BaseNodePtr &expr) { // syntax : iaddrof () auto *iExpr = mod.CurFuncCodeMemPool()->New(OP_iaddrof); if (!ParseExprIreadIaddrof(*iExpr)) { Error("ParseExprIaddrof failed when trying to parse addof"); return false; } expr = iExpr; return true; } bool MIRParser::ParseExprIreadoff(BaseNodePtr &expr) { // syntax : iread () auto *iReadOff = mod.CurFuncCodeMemPool()->New(); expr = iReadOff; if (!IsPrimitiveType(lexer.NextToken())) { Error("expect primitive type but get "); return false; } TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { return false; } iReadOff->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); if (!IsPrimitiveScalar(iReadOff->GetPrimType())) { Error("only scalar types allowed for ireadoff"); return false; } if (lexer.GetTokenKind() != TK_intconst) { Error("expect offset but get "); return false; } iReadOff->SetOffset(lexer.GetTheIntVal()); lexer.NextToken(); BaseNode *opnd = nullptr; if (!ParseExprOneOperand(opnd)) { Error("ParseExprIreadoff when paring one operand"); return false; } iReadOff->SetOpnd(opnd, 0); lexer.NextToken(); return true; } bool MIRParser::ParseExprIreadFPoff(BaseNodePtr &expr) { // syntax : iread auto *iReadOff = mod.CurFuncCodeMemPool()->New(); expr = iReadOff; if (!IsPrimitiveType(lexer.NextToken())) { Error("expect primitive type but get "); return false; } TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { return false; } iReadOff->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); if (lexer.GetTokenKind() != TK_intconst) { Error("expect offset but get "); return false; } iReadOff->SetOffset(lexer.GetTheIntVal()); lexer.NextToken(); return true; } bool MIRParser::ParseExprAddrof(BaseNodePtr &expr) { // syntax: addrof auto *addrofNode = mod.CurFuncCodeMemPool()->New(OP_addrof); expr = addrofNode; if (lexer.GetTokenKind() != TK_addrof) { Error("expect addrof but get "); return false; } lexer.NextToken(); TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { Error("expect primitive type but get "); return false; } addrofNode->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect symbol ParseExprAddroffunc"); return false; } if (stidx.IsGlobal()) { MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); DEBUG_ASSERT(sym != nullptr, "null ptr check"); sym->SetHasPotentialAssignment(); } addrofNode->SetStIdx(stidx); TokenKind tk = lexer.NextToken(); if (IsDelimitationTK(tk)) { addrofNode->SetFieldID(0); } else if (tk == TK_intconst) { addrofNode->SetFieldID(lexer.GetTheIntVal()); lexer.NextToken(); } else { addrofNode->SetFieldID(0); } return true; } bool MIRParser::ParseExprAddrofoff(BaseNodePtr &expr) { // syntax: addrofoff AddrofoffNode *addrofoffNode = mod.CurFuncCodeMemPool()->New(OP_addrofoff); expr = addrofoffNode; if (lexer.GetTokenKind() != TK_addrofoff) { Error("expect addrofoff but get "); return false; } lexer.NextToken(); TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { Error("expect primitive type but get "); return false; } addrofoffNode->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); StIdx stidx; if (!ParseDeclaredSt(stidx)) { return false; } if (stidx.FullIdx() == 0) { Error("expect symbol ParseExprAddroffunc"); return false; } if (stidx.IsGlobal()) { MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); DEBUG_ASSERT(sym != nullptr, "null ptr check"); sym->SetHasPotentialAssignment(); } addrofoffNode->stIdx = stidx; TokenKind tk = lexer.NextToken(); if (tk == TK_intconst) { addrofoffNode->offset = static_cast(lexer.GetTheIntVal()); lexer.NextToken(); } else { Error("expect integer offset but get "); return false; } return true; } bool MIRParser::ParseExprAddroffunc(BaseNodePtr &expr) { auto *addrOfFuncNode = mod.CurFuncCodeMemPool()->New(); expr = addrOfFuncNode; TokenKind tk = lexer.NextToken(); if (tk != TK_a32 && tk != TK_a64 && tk != TK_ptr) { Error("expect address primitive type but get "); return false; } TyIdx tyidx(0); if (!ParsePrimType(tyidx)) { Error("ParseExprAddroffunc failed when parsing primitive type"); return false; } addrOfFuncNode->SetPrimType(GlobalTables::GetTypeTable().GetPrimTypeFromTyIdx(tyidx)); if (lexer.GetTokenKind() != TK_fname) { Error("expect function name but get "); return false; } PUIdx pidx; if (!ParseDeclaredFunc(pidx)) { if (mod.GetFlavor() < kMmpl) { Error("expect .mmpl file"); return false; } pidx = EnterUndeclaredFunction(); } addrOfFuncNode->SetPUIdx(pidx); lexer.NextToken(); return true; } bool MIRParser::ParseExprAddroflabel(BaseNodePtr &expr) { // syntax: addroflabel