summaryrefslogtreecommitdiff
path: root/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp')
-rw-r--r--lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp100
1 files changed, 68 insertions, 32 deletions
diff --git a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 09628e872dd5..53a96fd6a97d 100644
--- a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -313,16 +313,17 @@ public:
return Optional<wasm::ValType>();
}
- WebAssembly::ExprType parseBlockType(StringRef ID) {
- return StringSwitch<WebAssembly::ExprType>(ID)
- .Case("i32", WebAssembly::ExprType::I32)
- .Case("i64", WebAssembly::ExprType::I64)
- .Case("f32", WebAssembly::ExprType::F32)
- .Case("f64", WebAssembly::ExprType::F64)
- .Case("v128", WebAssembly::ExprType::V128)
- .Case("exnref", WebAssembly::ExprType::Exnref)
- .Case("void", WebAssembly::ExprType::Void)
- .Default(WebAssembly::ExprType::Invalid);
+ WebAssembly::BlockType parseBlockType(StringRef ID) {
+ // Multivalue block types are handled separately in parseSignature
+ return StringSwitch<WebAssembly::BlockType>(ID)
+ .Case("i32", WebAssembly::BlockType::I32)
+ .Case("i64", WebAssembly::BlockType::I64)
+ .Case("f32", WebAssembly::BlockType::F32)
+ .Case("f64", WebAssembly::BlockType::F64)
+ .Case("v128", WebAssembly::BlockType::V128)
+ .Case("exnref", WebAssembly::BlockType::Exnref)
+ .Case("void", WebAssembly::BlockType::Void)
+ .Default(WebAssembly::BlockType::Invalid);
}
bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
@@ -343,7 +344,7 @@ public:
int64_t Val = Int.getIntVal();
if (IsNegative)
Val = -Val;
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
WebAssemblyOperand::IntOp{Val}));
Parser.Lex();
@@ -356,7 +357,7 @@ public:
return error("Cannot parse real: ", Flt);
if (IsNegative)
Val = -Val;
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Float, Flt.getLoc(), Flt.getEndLoc(),
WebAssemblyOperand::FltOp{Val}));
Parser.Lex();
@@ -378,7 +379,7 @@ public:
}
if (IsNegative)
Val = -Val;
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Float, Flt.getLoc(), Flt.getEndLoc(),
WebAssemblyOperand::FltOp{Val}));
Parser.Lex();
@@ -407,7 +408,7 @@ public:
// an opcode until after the assembly matcher, so set a default to fix
// up later.
auto Tok = Lexer.getTok();
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, Tok.getLoc(), Tok.getEndLoc(),
WebAssemblyOperand::IntOp{-1}));
}
@@ -416,8 +417,8 @@ public:
}
void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,
- WebAssembly::ExprType BT) {
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ WebAssembly::BlockType BT) {
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, NameLoc, NameLoc,
WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
}
@@ -449,13 +450,14 @@ public:
}
// Now construct the name as first operand.
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()),
WebAssemblyOperand::TokOp{Name}));
// If this instruction is part of a control flow structure, ensure
// proper nesting.
bool ExpectBlockType = false;
+ bool ExpectFuncType = false;
if (Name == "block") {
push(Block);
ExpectBlockType = true;
@@ -489,9 +491,37 @@ public:
if (pop(Name, Block))
return true;
} else if (Name == "end_function") {
+ ensureLocals(getStreamer());
CurrentState = EndFunction;
if (pop(Name, Function) || ensureEmptyNestingStack())
return true;
+ } else if (Name == "call_indirect" || Name == "return_call_indirect") {
+ ExpectFuncType = true;
+ }
+
+ if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
+ // This has a special TYPEINDEX operand which in text we
+ // represent as a signature, such that we can re-build this signature,
+ // attach it to an anonymous symbol, which is what WasmObjectWriter
+ // expects to be able to recreate the actual unique-ified type indices.
+ auto Loc = Parser.getTok();
+ auto Signature = std::make_unique<wasm::WasmSignature>();
+ if (parseSignature(Signature.get()))
+ return true;
+ // Got signature as block type, don't need more
+ ExpectBlockType = false;
+ auto &Ctx = getStreamer().getContext();
+ // The "true" here will cause this to be a nameless symbol.
+ MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
+ auto *WasmSym = cast<MCSymbolWasm>(Sym);
+ WasmSym->setSignature(Signature.get());
+ addSignature(std::move(Signature));
+ WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+ const MCExpr *Expr = MCSymbolRefExpr::create(
+ WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx);
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
+ WebAssemblyOperand::Symbol, Loc.getLoc(), Loc.getEndLoc(),
+ WebAssemblyOperand::SymOp{Expr}));
}
while (Lexer.isNot(AsmToken::EndOfStatement)) {
@@ -504,7 +534,7 @@ public:
if (ExpectBlockType) {
// Assume this identifier is a block_type.
auto BT = parseBlockType(Id.getString());
- if (BT == WebAssembly::ExprType::Invalid)
+ if (BT == WebAssembly::BlockType::Invalid)
return error("Unknown block type: ", Id);
addBlockTypeOperand(Operands, NameLoc, BT);
Parser.Lex();
@@ -514,7 +544,7 @@ public:
SMLoc End;
if (Parser.parseExpression(Val, End))
return error("Cannot parse symbol: ", Lexer.getTok());
- Operands.push_back(make_unique<WebAssemblyOperand>(
+ Operands.push_back(std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
WebAssemblyOperand::SymOp{Val}));
if (checkForP2AlignIfLoadStore(Operands, Name))
@@ -549,7 +579,7 @@ public:
}
case AsmToken::LCurly: {
Parser.Lex();
- auto Op = make_unique<WebAssemblyOperand>(
+ auto Op = std::make_unique<WebAssemblyOperand>(
WebAssemblyOperand::BrList, Tok.getLoc(), Tok.getEndLoc());
if (!Lexer.is(AsmToken::RCurly))
for (;;) {
@@ -572,7 +602,7 @@ public:
}
if (ExpectBlockType && Operands.size() == 1) {
// Support blocks with no operands as default to void.
- addBlockTypeOperand(Operands, NameLoc, WebAssembly::ExprType::Void);
+ addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
}
Parser.Lex();
return false;
@@ -671,7 +701,7 @@ public:
LastFunctionLabel = LastLabel;
push(Function);
}
- auto Signature = make_unique<wasm::WasmSignature>();
+ auto Signature = std::make_unique<wasm::WasmSignature>();
if (parseSignature(Signature.get()))
return true;
WasmSym->setSignature(Signature.get());
@@ -687,7 +717,7 @@ public:
if (SymName.empty())
return true;
auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
- auto Signature = make_unique<wasm::WasmSignature>();
+ auto Signature = std::make_unique<wasm::WasmSignature>();
if (parseRegTypeList(Signature->Params))
return true;
WasmSym->setSignature(Signature.get());
@@ -737,24 +767,30 @@ public:
return true; // We didn't process this directive.
}
+ // Called either when the first instruction is parsed of the function ends.
+ void ensureLocals(MCStreamer &Out) {
+ if (CurrentState == FunctionStart) {
+ // We haven't seen a .local directive yet. The streamer requires locals to
+ // be encoded as a prelude to the instructions, so emit an empty list of
+ // locals here.
+ auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
+ *Out.getTargetStreamer());
+ TOut.emitLocal(SmallVector<wasm::ValType, 0>());
+ CurrentState = FunctionLocals;
+ }
+ }
+
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override {
MCInst Inst;
+ Inst.setLoc(IDLoc);
unsigned MatchResult =
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch (MatchResult) {
case Match_Success: {
- if (CurrentState == FunctionStart) {
- // This is the first instruction in a function, but we haven't seen
- // a .local directive yet. The streamer requires locals to be encoded
- // as a prelude to the instructions, so emit an empty list of locals
- // here.
- auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
- *Out.getTargetStreamer());
- TOut.emitLocal(SmallVector<wasm::ValType, 0>());
- }
+ ensureLocals(Out);
// Fix unknown p2align operands.
auto Align = WebAssembly::GetDefaultP2AlignAny(Inst.getOpcode());
if (Align != -1U) {