diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | 105 |
1 files changed, 60 insertions, 45 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 1cba0843f891..1e2d3888fe1c 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -15,10 +15,9 @@ #include "AsmParser/WebAssemblyAsmTypeCheck.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h" #include "MCTargetDesc/WebAssemblyTargetStreamer.h" #include "TargetInfo/WebAssemblyTargetInfo.h" -#include "Utils/WebAssemblyTypeUtilities.h" -#include "Utils/WebAssemblyUtilities.h" #include "WebAssembly.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -248,15 +247,14 @@ public: WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII, const MCTargetOptions &Options) : MCTargetAsmParser(Options, STI, MII), Parser(Parser), - Lexer(Parser.getLexer()), - is64(STI.getTargetTriple().isArch64Bit()), + Lexer(Parser.getLexer()), is64(STI.getTargetTriple().isArch64Bit()), TC(Parser, MII, is64), SkipTypeCheck(Options.MCNoTypeCheck) { setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); // Don't type check if this is inline asm, since that is a naked sequence of // instructions without a function/locals decl. auto &SM = Parser.getSourceManager(); auto BufferName = - SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier(); + SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier(); if (BufferName == "<inline asm>") SkipTypeCheck = true; } @@ -323,7 +321,9 @@ public: } } - void push(NestingType NT) { NestingStack.push_back({NT, wasm::WasmSignature()}); } + void push(NestingType NT, wasm::WasmSignature Sig = wasm::WasmSignature()) { + NestingStack.push_back({NT, Sig}); + } bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) { if (NestingStack.empty()) @@ -337,6 +337,19 @@ public: return false; } + // Pop a NestingType and push a new NestingType with the same signature. Used + // for if-else and try-catch(_all). + bool popAndPushWithSameSignature(StringRef Ins, NestingType PopNT, + NestingType PushNT) { + if (NestingStack.empty()) + return error(Twine("End of block construct with no start: ") + Ins); + auto Sig = NestingStack.back().Sig; + if (pop(Ins, PopNT)) + return true; + push(PushNT, Sig); + return false; + } + bool ensureEmptyNestingStack(SMLoc Loc = SMLoc()) { auto Err = !NestingStack.empty(); while (!NestingStack.empty()) { @@ -588,17 +601,14 @@ public: push(If); ExpectBlockType = true; } else if (Name == "else") { - if (pop(Name, If)) + if (popAndPushWithSameSignature(Name, If, Else)) return true; - push(Else); } else if (Name == "catch") { - if (pop(Name, Try)) + if (popAndPushWithSameSignature(Name, Try, Try)) return true; - push(Try); } else if (Name == "catch_all") { - if (pop(Name, Try)) + if (popAndPushWithSameSignature(Name, Try, CatchAll)) return true; - push(CatchAll); } else if (Name == "end_if") { if (pop(Name, If, Else)) return true; @@ -638,10 +648,10 @@ public: if (parseSignature(Signature.get())) return true; // Got signature as block type, don't need more - ExpectBlockType = false; TC.setLastSig(*Signature.get()); if (ExpectBlockType) NestingStack.back().Sig = *Signature.get(); + ExpectBlockType = false; auto &Ctx = getContext(); // The "true" here will cause this to be a nameless symbol. MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true); @@ -691,7 +701,7 @@ public: parseSingleInteger(true, Operands); if (checkForP2AlignIfLoadStore(Operands, Name)) return true; - } else if(Lexer.is(AsmToken::Real)) { + } else if (Lexer.is(AsmToken::Real)) { if (parseSingleFloat(true, Operands)) return true; } else if (!parseSpecialFloatMaybe(true, Operands)) { @@ -775,31 +785,23 @@ public: // This function processes wasm-specific directives streamed to // WebAssemblyTargetStreamer, all others go to the generic parser // (see WasmAsmParser). - bool ParseDirective(AsmToken DirectiveID) override { - // This function has a really weird return value behavior that is different - // from all the other parsing functions: - // - return true && no tokens consumed -> don't know this directive / let - // the generic parser handle it. - // - return true && tokens consumed -> a parsing error occurred. - // - return false -> processed this directive successfully. + ParseStatus parseDirective(AsmToken DirectiveID) override { assert(DirectiveID.getKind() == AsmToken::Identifier); auto &Out = getStreamer(); auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer()); auto &Ctx = Out.getContext(); - // TODO: any time we return an error, at least one token must have been - // consumed, otherwise this will not signal an error to the caller. if (DirectiveID.getString() == ".globaltype") { auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; if (expect(AsmToken::Comma, ",")) - return true; + return ParseStatus::Failure; auto TypeTok = Lexer.getTok(); auto TypeName = expectIdent(); if (TypeName.empty()) - return true; + return ParseStatus::Failure; auto Type = WebAssembly::parseType(TypeName); if (!Type) return error("Unknown type in .globaltype directive: ", TypeTok); @@ -810,6 +812,8 @@ public: if (isNext(AsmToken::Comma)) { TypeTok = Lexer.getTok(); auto Id = expectIdent(); + if (Id.empty()) + return ParseStatus::Failure; if (Id == "immutable") Mutable = false; else @@ -829,14 +833,14 @@ public: // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]] auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; if (expect(AsmToken::Comma, ",")) - return true; + return ParseStatus::Failure; auto ElemTypeTok = Lexer.getTok(); auto ElemTypeName = expectIdent(); if (ElemTypeName.empty()) - return true; + return ParseStatus::Failure; std::optional<wasm::ValType> ElemType = WebAssembly::parseType(ElemTypeName); if (!ElemType) @@ -844,7 +848,7 @@ public: wasm::WasmLimits Limits = DefaultLimits(); if (isNext(AsmToken::Comma) && parseLimits(&Limits)) - return true; + return ParseStatus::Failure; // Now that we have the name and table type, we can actually create the // symbol @@ -864,7 +868,7 @@ public: // parses the locals separately. auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); if (WasmSym->isDefined()) { // We push 'Function' either when a label is parsed or a .functype @@ -880,7 +884,7 @@ public: if (CurrentState != FunctionLabel) { // This .functype indicates a start of a function. if (ensureEmptyNestingStack()) - return true; + return ParseStatus::Failure; push(Function); } CurrentState = FunctionStart; @@ -888,7 +892,7 @@ public: } auto Signature = std::make_unique<wasm::WasmSignature>(); if (parseSignature(Signature.get())) - return true; + return ParseStatus::Failure; TC.funcDecl(*Signature); WasmSym->setSignature(Signature.get()); addSignature(std::move(Signature)); @@ -901,47 +905,56 @@ public: if (DirectiveID.getString() == ".export_name") { auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; if (expect(AsmToken::Comma, ",")) - return true; + return ParseStatus::Failure; auto ExportName = expectIdent(); + if (ExportName.empty()) + return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); WasmSym->setExportName(storeName(ExportName)); TOut.emitExportName(WasmSym, ExportName); + return expect(AsmToken::EndOfStatement, "EOL"); } if (DirectiveID.getString() == ".import_module") { auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; if (expect(AsmToken::Comma, ",")) - return true; + return ParseStatus::Failure; auto ImportModule = expectIdent(); + if (ImportModule.empty()) + return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); WasmSym->setImportModule(storeName(ImportModule)); TOut.emitImportModule(WasmSym, ImportModule); + return expect(AsmToken::EndOfStatement, "EOL"); } if (DirectiveID.getString() == ".import_name") { auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; if (expect(AsmToken::Comma, ",")) - return true; + return ParseStatus::Failure; auto ImportName = expectIdent(); + if (ImportName.empty()) + return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); WasmSym->setImportName(storeName(ImportName)); TOut.emitImportName(WasmSym, ImportName); + return expect(AsmToken::EndOfStatement, "EOL"); } if (DirectiveID.getString() == ".tagtype") { auto SymName = expectIdent(); if (SymName.empty()) - return true; + return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); auto Signature = std::make_unique<wasm::WasmSignature>(); if (parseRegTypeList(Signature->Params)) - return true; + return ParseStatus::Failure; WasmSym->setSignature(Signature.get()); addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG); @@ -956,7 +969,7 @@ public: Lexer.getTok()); SmallVector<wasm::ValType, 4> Locals; if (parseRegTypeList(Locals)) - return true; + return ParseStatus::Failure; TC.localDecl(Locals); TOut.emitLocal(Locals); CurrentState = FunctionLocals; @@ -967,7 +980,8 @@ public: DirectiveID.getString() == ".int16" || DirectiveID.getString() == ".int32" || DirectiveID.getString() == ".int64") { - if (CheckDataSection()) return true; + if (CheckDataSection()) + return ParseStatus::Failure; const MCExpr *Val; SMLoc End; if (Parser.parseExpression(Val, End)) @@ -979,7 +993,8 @@ public: } if (DirectiveID.getString() == ".asciz") { - if (CheckDataSection()) return true; + if (CheckDataSection()) + return ParseStatus::Failure; std::string S; if (Parser.parseEscapedString(S)) return error("Cannot parse string constant: ", Lexer.getTok()); @@ -987,7 +1002,7 @@ public: return expect(AsmToken::EndOfStatement, "EOL"); } - return true; // We didn't process this directive. + return ParseStatus::NoMatch; // We didn't process this directive. } // Called either when the first instruction is parsed of the function ends. |
