diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2019-01-02 23:23:51 +0000 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2019-01-02 23:23:51 +0000 |
commit | ad72f68501c2c677c5635c2457887a7d85588818 (patch) | |
tree | fe4a14506789dab75de3d825887b2c58bcacabc1 /llvm/lib/Target | |
parent | 33e3b4b9b3b3c2fb5b30bd618c02adbe30d81c0f (diff) | |
download | bcm5719-llvm-ad72f68501c2c677c5635c2457887a7d85588818.tar.gz bcm5719-llvm-ad72f68501c2c677c5635c2457887a7d85588818.zip |
[WebAssembly] made assembler parse block_type
Summary:
This was previously ignored and an incorrect value generated.
Also fixed Disassembler's handling of block_type.
Reviewers: dschuff, aheejin
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D56092
llvm-svn: 350270
Diffstat (limited to 'llvm/lib/Target')
4 files changed, 56 insertions, 21 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index d997190aa36..0a5908f4379 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -301,6 +301,18 @@ 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("except_ref", WebAssembly::ExprType::ExceptRef) + .Case("void", WebAssembly::ExprType::Void) + .Default(WebAssembly::ExprType::Invalid); + } + bool parseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) { while (Lexer.is(AsmToken::Identifier)) { auto Type = parseType(Lexer.getTok().getString()); @@ -351,6 +363,13 @@ public: return false; } + void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc, + WebAssembly::ExprType BT) { + Operands.push_back(make_unique<WebAssemblyOperand>( + WebAssemblyOperand::Integer, NameLoc, NameLoc, + WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)})); + } + bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override { // Note: Name does NOT point into the sourcecode, but to a local, so @@ -387,14 +406,19 @@ public: // If this instruction is part of a control flow structure, ensure // proper nesting. + bool ExpectBlockType = false; if (BaseName == "block") { push(Block); + ExpectBlockType = true; } else if (BaseName == "loop") { push(Loop); + ExpectBlockType = true; } else if (BaseName == "try") { push(Try); + ExpectBlockType = true; } else if (BaseName == "if") { push(If); + ExpectBlockType = true; } else if (BaseName == "else") { if (pop(BaseName, If)) return true; @@ -429,13 +453,23 @@ public: switch (Tok.getKind()) { case AsmToken::Identifier: { auto &Id = Lexer.getTok(); - const MCExpr *Val; - SMLoc End; - if (Parser.parsePrimaryExpr(Val, End)) - return error("Cannot parse symbol: ", Lexer.getTok()); - Operands.push_back(make_unique<WebAssemblyOperand>( - WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(), - WebAssemblyOperand::SymOp{Val})); + if (ExpectBlockType) { + // Assume this identifier is a block_type. + auto BT = parseBlockType(Id.getString()); + if (BT == WebAssembly::ExprType::Invalid) + return error("Unknown block type: ", Id); + addBlockTypeOperand(Operands, NameLoc, BT); + Parser.Lex(); + } else { + // Assume this identifier is a label. + const MCExpr *Val; + SMLoc End; + if (Parser.parsePrimaryExpr(Val, End)) + return error("Cannot parse symbol: ", Lexer.getTok()); + Operands.push_back(make_unique<WebAssemblyOperand>( + WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(), + WebAssemblyOperand::SymOp{Val})); + } break; } case AsmToken::Minus: @@ -482,18 +516,11 @@ public: return true; } } - Parser.Lex(); - - // Block instructions require a signature index, but these are missing in - // assembly, so we add a dummy one explicitly (since we have no control - // over signature tables here, we assume these will be regenerated when - // the wasm module is generated). - if (BaseName == "block" || BaseName == "loop" || BaseName == "try" || - BaseName == "if") { - Operands.push_back(make_unique<WebAssemblyOperand>( - WebAssemblyOperand::Integer, NameLoc, NameLoc, - WebAssemblyOperand::IntOp{-1})); + if (ExpectBlockType && Operands.size() == 1) { + // Support blocks with no operands as default to void. + addBlockTypeOperand(Operands, NameLoc, WebAssembly::ExprType::Void); } + Parser.Lex(); return false; } diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp index c068d6b43d4..369954b88c9 100644 --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -167,12 +167,17 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction( } // SLEB operands: case WebAssembly::OPERAND_I32IMM: - case WebAssembly::OPERAND_I64IMM: - case WebAssembly::OPERAND_SIGNATURE: { + case WebAssembly::OPERAND_I64IMM: { if (!parseLEBImmediate(MI, Size, Bytes, true)) return MCDisassembler::Fail; break; } + // block_type operands (uint8_t). + case WebAssembly::OPERAND_SIGNATURE: { + if (!parseImmediate<uint8_t>(MI, Size, Bytes)) + return MCDisassembler::Fail; + break; + } // FP operands. case WebAssembly::OPERAND_F32IMM: { if (!parseImmediate<float>(MI, Size, Bytes)) diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index eaf9750792b..a2882673060 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -278,6 +278,8 @@ void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI, case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break; + default: + llvm_unreachable("invalid WebAssembly::ExprType"); } } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 4ca20f59368..a111eb51c56 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -346,7 +346,8 @@ enum class ExprType : unsigned { F32 = 0x7D, F64 = 0x7C, V128 = 0x7B, - ExceptRef = 0x68 + ExceptRef = 0x68, + Invalid = 0x00 }; /// Instruction opcodes emitted via means other than CodeGen. |