summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp105
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.