From 5442ac8b6522efe57cab1fb8ed9b5bd1af1a648c Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Mon, 7 Jun 2021 17:19:47 -0700 Subject: [PATCH] Define new OP_asm opcode and its representation and support its input and output in .bpl and .mpl --- src/mapleall/maple_ir/include/mir_nodes.h | 36 +++ src/mapleall/maple_ir/include/mir_parser.h | 2 + src/mapleall/maple_ir/include/opcodes.def | 1 + src/mapleall/maple_ir/src/bin_func_export.cpp | 31 ++ src/mapleall/maple_ir/src/bin_func_import.cpp | 39 +++ src/mapleall/maple_ir/src/mir_nodes.cpp | 153 +++++++++- src/mapleall/maple_ir/src/mir_parser.cpp | 284 +++++++++++++----- 7 files changed, 472 insertions(+), 74 deletions(-) diff --git a/src/mapleall/maple_ir/include/mir_nodes.h b/src/mapleall/maple_ir/include/mir_nodes.h index b26f0254c6..b18eab9c6d 100644 --- a/src/mapleall/maple_ir/include/mir_nodes.h +++ b/src/mapleall/maple_ir/include/mir_nodes.h @@ -3166,6 +3166,42 @@ class CommentNode : public StmtNode { MapleString comment; }; +enum AsmQualifierKind : unsigned { // they are alreadgy Maple IR keywords + kASMvolatile, + kASMinline, + kASMgoto, +}; + +class AsmNode : public NaryStmtNode { + public: + explicit AsmNode(MapleAllocator *alloc) : NaryStmtNode(*alloc, OP_asm), + asmString(alloc->GetMemPool()), inputConstraints(alloc->Adapter()), + asmOutputs(alloc->Adapter()), outputConstraints(alloc->Adapter()), + clobberList(alloc->Adapter()), gotoLabels(alloc->Adapter()), qualifiers(0) {} + + AsmNode(AsmNode &node) = delete; + AsmNode &operator=(const AsmNode &node) = delete; + virtual ~AsmNode() = default; + + void SetQualifier(AsmQualifierKind x) { + qualifiers |= (1U << static_cast(x)); + } + + bool GetQualifier(AsmQualifierKind x) const { + return (qualifiers & (1U << static_cast(x))) != 0; + } + + void Dump(int32 indent) const override; + + MapleString asmString; + MapleVector inputConstraints; // length is numOpnds + CallReturnVector asmOutputs; + MapleVector outputConstraints; // length is returnValues.size() + MapleVector clobberList; + MapleVector gotoLabels; + uint32 qualifiers; +}; + void DumpCallReturns(const MIRModule &mod, CallReturnVector nrets, int32 indent); } // namespace maple diff --git a/src/mapleall/maple_ir/include/mir_parser.h b/src/mapleall/maple_ir/include/mir_parser.h index fe363bb2be..8ba70f49e2 100644 --- a/src/mapleall/maple_ir/include/mir_parser.h +++ b/src/mapleall/maple_ir/include/mir_parser.h @@ -127,6 +127,7 @@ class MIRParser { bool ParseStmtIntrinsiccallwithtype(StmtNodePtr&, bool isAssigned); bool ParseStmtIntrinsiccallwithtype(StmtNodePtr&); bool ParseStmtIntrinsiccallwithtypeassigned(StmtNodePtr&); + bool ParseCallReturnPair(CallReturnPair&); bool ParseCallReturns(CallReturnVector&); bool ParseBinaryStmt(StmtNodePtr&, Opcode op); bool ParseBinaryStmtAssertGE(StmtNodePtr&); @@ -149,6 +150,7 @@ class MIRParser { bool ParseUnaryStmtAssertNonNull(StmtNodePtr&); bool ParseStmtMarker(StmtNodePtr&); bool ParseStmtGosub(StmtNodePtr&); + bool ParseStmtAsm(StmtNodePtr&); // Expression Parser bool ParseExpression(BaseNodePtr &expr); diff --git a/src/mapleall/maple_ir/include/opcodes.def b/src/mapleall/maple_ir/include/opcodes.def index 78a4a68dcf..952f614db0 100644 --- a/src/mapleall/maple_ir/include/opcodes.def +++ b/src/mapleall/maple_ir/include/opcodes.def @@ -200,3 +200,4 @@ // leaf node OPCODE(addroffpc, AddroffPCNode, 0, 0) OPCODE(igoto, UnaryStmtNode, OPCODEISSTMT, 0) + OPCODE(asm, AsmNode, OPCODEISSTMT, 0) diff --git a/src/mapleall/maple_ir/src/bin_func_export.cpp b/src/mapleall/maple_ir/src/bin_func_export.cpp index 545ba053fe..f2ef3c5ff4 100644 --- a/src/mapleall/maple_ir/src/bin_func_export.cpp +++ b/src/mapleall/maple_ir/src/bin_func_export.cpp @@ -584,6 +584,37 @@ void BinaryMplExport::OutputBlockNode(BlockNode *block) { doneWithOpnds = true; break; } + case OP_asm: { + AsmNode *asmNode = static_cast(s); + WriteNum(asmNode->qualifiers); + string str(asmNode->asmString.c_str()); + WriteAsciiStr(str); + // the outputs + size_t count = asmNode->asmOutputs.size(); + WriteNum(count); + for (int32 i = 0; i < count; i++) { + OutputUsrStr(asmNode->outputConstraints[i]); + } + OutputReturnValues(&asmNode->asmOutputs); + // the clobber list + count = asmNode->clobberList.size(); + WriteNum(count); + for (int32 i = 0; i < count; i++) { + OutputUsrStr(asmNode->clobberList[i]); + } + // the labels + count = asmNode->gotoLabels.size(); + WriteNum(count); + for (int32 i = 0; i < count; i++) { + WriteNum(asmNode->gotoLabels[i]); + } + // the inputs + WriteNum(asmNode->NumOpnds()); + for (int32 i = 0; i < asmNode->numOpnds; i++) { + OutputUsrStr(asmNode->inputConstraints[i]); + } + break; + } default: CHECK_FATAL(false, "Unhandled opcode %d", s->GetOpCode()); break; diff --git a/src/mapleall/maple_ir/src/bin_func_import.cpp b/src/mapleall/maple_ir/src/bin_func_import.cpp index d290a34038..41c226782f 100644 --- a/src/mapleall/maple_ir/src/bin_func_import.cpp +++ b/src/mapleall/maple_ir/src/bin_func_import.cpp @@ -773,6 +773,45 @@ BlockNode *BinaryMplImport::ImportBlockNode(MIRFunction *func) { stmt = ImportBlockNode(func); break; } + case OP_asm: { + AsmNode *s = mod.CurFuncCodeMemPool()->New(&mod.GetCurFuncCodeMPAllocator()); + s->qualifiers = ReadNum(); + string str; + ReadAsciiStr(str); + s->asmString = str; + // the outputs + size_t count = ReadNum(); + UStrIdx strIdx; + for (int32 i = 0; i < count; i++) { + strIdx = ImportUsrStr(); + s->outputConstraints.push_back(strIdx); + } + ImportReturnValues(func, &s->asmOutputs); + // the clobber list + count = ReadNum(); + for (int32 i = 0; i < count; i++) { + strIdx = ImportUsrStr(); + s->clobberList.push_back(strIdx); + } + // the labels + count = ReadNum(); + for (int32 i = 0; i < count; i++) { + LabelIdx lidx = ReadNum(); + s->gotoLabels.push_back(lidx); + } + // the inputs + numOpr = ReadNum(); + s->SetNumOpnds(numOpr); + for (int32 i = 0; i < numOpr; i++) { + strIdx = ImportUsrStr(); + s->inputConstraints.push_back(strIdx); + } + for (int32 i = 0; i < numOpr; i++) { + s->GetNopnd().push_back(ImportExpression(func)); + } + stmt = s; + break; + } default: CHECK_FATAL(false, "Unhandled opcode tag %d", tag); break; diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index 05b27f6795..2fe85dad09 100644 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -761,7 +761,7 @@ void TryNode::Dump(int32 indent) const { StmtNode::DumpBase(indent); LogInfo::MapleLogger() << " {"; for (size_t i = 0; i < offsets.size(); ++i) { - int64 offset = offsets[i]; + uint32 offset = offsets[i]; LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName((LabelIdx)offset); } LogInfo::MapleLogger() << " }\n"; @@ -1176,6 +1176,157 @@ void CommentNode::Dump(int32 indent) const { LogInfo::MapleLogger() << "#" << comment << '\n'; } +static void EmitStr(const MapleString *mplStr) { + const char *str = mplStr->c_str(); + size_t len = mplStr->length(); + LogInfo::MapleLogger() << "\""; + + // don't expand special character; convert all \s to \\s in string + for (int i = 0; i < len; i++) { + /* Referred to GNU AS: 3.6.1.1 Strings */ + constexpr int kBufSize = 5; + constexpr int kFirstChar = 0; + constexpr int kSecondChar = 1; + constexpr int kThirdChar = 2; + constexpr int kLastChar = 4; + char buf[kBufSize]; + if (isprint(*str)) { + buf[kFirstChar] = *str; + buf[kSecondChar] = 0; + if (*str == '\\' || *str == '\"') { + buf[kFirstChar] = '\\'; + buf[kSecondChar] = *str; + buf[kThirdChar] = 0; + } + LogInfo::MapleLogger() << buf; + } else if (*str == '\b') { + LogInfo::MapleLogger() << "\\b"; + } else if (*str == '\n') { + LogInfo::MapleLogger() << "\\n"; + } else if (*str == '\r') { + LogInfo::MapleLogger() << "\\r"; + } else if (*str == '\t') { + LogInfo::MapleLogger() << "\\t"; + } else if (*str == '\0') { + buf[kFirstChar] = '\\'; + buf[kSecondChar] = '0'; + buf[kThirdChar] = 0; + LogInfo::MapleLogger() << buf; + } else { + /* all others, print as number */ + int ret = snprintf_s(buf, sizeof(buf), 4, "\\%03o", (*str) & 0xFF); + if (ret < 0) { + FATAL(kLncFatal, "snprintf_s failed"); + } + buf[kLastChar] = '\0'; + LogInfo::MapleLogger() << buf; + } + str++; + } + + LogInfo::MapleLogger() << "\"\n"; +} + +void AsmNode::Dump(int32 indent) const { + if (srcPosition.FileNum() != 0 && srcPosition.LineNum() != 0 && srcPosition.LineNum() != lastPrintedLineNum && + theMIRModule->CurFunction()->WithLocInfo()) { + LogInfo::MapleLogger() << "LOC " << srcPosition.FileNum() << " " << srcPosition.LineNum() << '\n'; + lastPrintedLineNum = srcPosition.LineNum(); + } + PrintIndentation(indent); + LogInfo::MapleLogger() << kOpcodeInfo.GetName(op); + if (GetQualifier(kASMvolatile)) + LogInfo::MapleLogger() << " volatile"; + if (GetQualifier(kASMinline)) + LogInfo::MapleLogger() << " inline"; + if (GetQualifier(kASMgoto)) + LogInfo::MapleLogger() << " goto"; + LogInfo::MapleLogger() << " { "; + EmitStr(&asmString); + // print outputs + PrintIndentation(indent+1); + LogInfo::MapleLogger() << " :"; + size_t numOutputs = asmOutputs.size(); + std::string uStr; + const MIRFunction *mirFunc = theMIRModule->CurFunction(); + if (numOutputs == 0) { + LogInfo::MapleLogger() << '\n'; + } else { + for (size_t i = 0; i < numOutputs; i++) { + if (i != 0) { + PrintIndentation(indent+2); + } + uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(outputConstraints[i]); + PrintString(uStr); + LogInfo::MapleLogger() << " "; + StIdx stIdx = asmOutputs[i].first; + RegFieldPair regFieldPair = asmOutputs[i].second; + if (!regFieldPair.IsReg()) { + FieldID fieldID = regFieldPair.GetFieldID(); + LogInfo::MapleLogger() << "dassign"; + const MIRSymbol *st = mirFunc->GetLocalOrGlobalSymbol(stIdx); + ASSERT(st != nullptr, "st is null"); + LogInfo::MapleLogger() << (stIdx.Islocal() ? " %" : " $"); + LogInfo::MapleLogger() << st->GetName() << " " << fieldID; + } else { + PregIdx16 regIdx = regFieldPair.GetPregIdx(); + const MIRPreg *mirPreg = mirFunc->GetPregItem(static_cast(regIdx)); + ASSERT(mirPreg != nullptr, "mirPreg is null"); + LogInfo::MapleLogger() << "regassign" + << " " << GetPrimTypeName(mirPreg->GetPrimType()); + LogInfo::MapleLogger() << " %" << mirPreg->GetPregNo(); + } + if (i != numOutputs - 1) { + LogInfo::MapleLogger() << ','; + } + LogInfo::MapleLogger() << '\n'; + } + } + // print input operands + PrintIndentation(indent+1); + LogInfo::MapleLogger() << " :"; + if (numOpnds == 0) { + LogInfo::MapleLogger() << '\n'; + } else { + for (size_t i = 0; i < numOpnds; i++) { + if (i != 0) { + PrintIndentation(indent+2); + } + uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(inputConstraints[i]); + PrintString(uStr); + LogInfo::MapleLogger() << " ("; + GetNopndAt(i)->Dump(indent+4); + LogInfo::MapleLogger() << ")"; + if (i != numOpnds - 1) { + LogInfo::MapleLogger() << ','; + } + LogInfo::MapleLogger() << "\n"; + } + } + // print clobber list + PrintIndentation(indent+1); + LogInfo::MapleLogger() << " :"; + for (size_t i = 0; i < clobberList.size(); i++) { + uStr = GlobalTables::GetUStrTable().GetStringFromStrIdx(clobberList[i]); + PrintString(uStr); + if (i != clobberList.size() - 1) { + LogInfo::MapleLogger() << ','; + } + } + LogInfo::MapleLogger() << '\n'; + // print labels + PrintIndentation(indent+1); + LogInfo::MapleLogger() << " :"; + for (size_t i = 0; i < gotoLabels.size(); i++) { + LabelIdx offset = gotoLabels[i]; + LogInfo::MapleLogger() << " @" << theMIRModule->CurFunction()->GetLabelName(offset); + if (i != gotoLabels.size() - 1) { + LogInfo::MapleLogger() << ','; + } + } + LogInfo::MapleLogger() << " }\n"; +} + inline bool IntTypeVerify(PrimType pTyp) { return pTyp == PTY_i32 || pTyp == PTY_u32 || pTyp == PTY_i64 || pTyp == PTY_u64; } diff --git a/src/mapleall/maple_ir/src/mir_parser.cpp b/src/mapleall/maple_ir/src/mir_parser.cpp index beb0442ea0..2bc7f8d157 100644 --- a/src/mapleall/maple_ir/src/mir_parser.cpp +++ b/src/mapleall/maple_ir/src/mir_parser.cpp @@ -971,6 +971,83 @@ 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); + 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()); + ASSERT(ptrTy != nullptr, "null ptr check"); + ptrTy->SetPrimType(PTY_ptr); + 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); + // RegreadNode regreadexpr; + 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; + } + ASSERT(pregIdx > 0, "register number is zero"); + 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 @@ -988,88 +1065,148 @@ bool MIRParser::ParseCallReturns(CallReturnVector &retsvec) { 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; } - bool isst = (lexer.GetTokenKind() == TK_dassign); - if (isst) { - // parse %i + 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()); + 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(); - 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); - 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()); - ASSERT(ptrTy != nullptr, "null ptr check"); - ptrTy->SetPrimType(PTY_ptr); - TyIdx newTyidx = GlobalTables::GetTypeTable().GetOrCreateMIRType(ptrTy); - delete ptrTy; - lSym->SetTyIdx(newTyidx); - } - } - if (stidx.FullIdx() == 0) { - Error("expect a symbol parsing ParseCallAssignedStmts. "); - return false; - } - uint16 fieldId = 0; - TokenKind nextToken = lexer.NextToken(); - // parse field id - if (nextToken == TK_intconst) { - fieldId = lexer.GetTheIntVal(); - } else { - Error("expect a fieldID parsing ParseCallAssignedStmts. "); - } - RegFieldPair regFieldPair; - regFieldPair.SetFieldID(fieldId); - retsvec.push_back(CallReturnPair(stidx, regFieldPair)); - tk = lexer.NextToken(); - } else { - // parse type + } + } + // 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.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(); - TyIdx tyidx(0); - // RegreadNode regreadexpr; - 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; - } - ASSERT(pregIdx > 0, "register number is zero"); - ASSERT(pregIdx <= 0xffff, "register number is over 16 bits"); - RegFieldPair regFieldPair; - regFieldPair.SetPregIdx(pregIdx); - retsvec.push_back(CallReturnPair(StIdx(), regFieldPair)); - tk = lexer.GetTokenKind(); } } + asmNode->SetNumOpnds(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; } @@ -2894,6 +3031,7 @@ std::map MIRParser::InitFuncPtrMapForPar funcPtrMap[TK_label] = &MIRParser::ParseStmtLabel; funcPtrMap[TK_LOC] = &MIRParser::ParseLocStmt; funcPtrMap[TK_ALIAS] = &MIRParser::ParseAlias; + funcPtrMap[TK_asm] = &MIRParser::ParseStmtAsm; return funcPtrMap; } -- Gitee