diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-10-01 17:20:31 +0000 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-10-01 17:20:31 +0000 |
commit | 5e090bfe2494e6df912cd4ccf8ec89ea53d5c5c4 (patch) | |
tree | 87708f8532e081626aa4e7d6b693c97ede0e90ca /llvm | |
parent | 9ea0fa2677d3106222addf528070f8a9c4fa7cb4 (diff) |
[WebAssembly] Fixed AsmParser not allowing instructions with /
Summary:
The AsmParser Lexer regards these as a seperate token.
Here we expand the instruction name with them if they are
adjacent (no whitespace).
Tested: the basic-assembly.s test case has one case with a / in it.
The currently are also instructions with : in them, which we intend
to rename rather than fix them here.
Reviewers: tlively, dschuff
Subscribers: sbc100, jgravelle-google, aheejin, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52442
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | 37 | ||||
-rw-r--r-- | llvm/test/MC/WebAssembly/basic-assembly.s | 8 |
2 files changed, 35 insertions, 10 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index f2fcdf60d50..60f82fac5de 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -227,15 +227,34 @@ public: bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name, SMLoc NameLoc, OperandVector &Operands) override { + // Note: Name does NOT point into the sourcecode, but to a local, so + // use NameLoc instead. + Name = StringRef(NameLoc.getPointer(), Name.size()); + // WebAssembly has instructions with / in them, which AsmLexer parses + // as seperate tokens, so if we find such tokens immediately adjacent (no + // whitespace), expand the name to include them: + for (;;) { + auto &Sep = Lexer.getTok(); + if (Sep.getLoc().getPointer() != Name.end() || + Sep.getKind() != AsmToken::Slash) break; + // Extend name with / + Name = StringRef(Name.begin(), Name.size() + Sep.getString().size()); + Parser.Lex(); + // We must now find another identifier, or error. + auto &Id = Lexer.getTok(); + if (Id.getKind() != AsmToken::Identifier || + Id.getLoc().getPointer() != Name.end()) + return Error("Incomplete instruction name: ", Id); + Name = StringRef(Name.begin(), Name.size() + Id.getString().size()); + Parser.Lex(); + } + // Now construct the name as first operand. Operands.push_back(make_unique<WebAssemblyOperand>( - WebAssemblyOperand::Token, NameLoc, - SMLoc::getFromPointer(NameLoc.getPointer() + Name.size()), - WebAssemblyOperand::TokOp{ - StringRef(NameLoc.getPointer(), Name.size())})); + WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()), + WebAssemblyOperand::TokOp{Name})); auto NamePair = Name.split('.'); // If no '.', there is no type prefix. - if (NamePair.second.empty()) - std::swap(NamePair.first, NamePair.second); + auto BaseName = NamePair.second.empty() ? NamePair.first : NamePair.second; while (Lexer.isNot(AsmToken::EndOfStatement)) { auto &Tok = Lexer.getTok(); switch (Tok.getKind()) { @@ -254,11 +273,11 @@ public: Parser.Lex(); if (Lexer.isNot(AsmToken::Integer)) return Error("Expected integer instead got: ", Lexer.getTok()); - if (ParseOperandStartingWithInteger(true, Operands, NamePair.second)) + if (ParseOperandStartingWithInteger(true, Operands, BaseName)) return true; break; case AsmToken::Integer: - if (ParseOperandStartingWithInteger(false, Operands, NamePair.second)) + if (ParseOperandStartingWithInteger(false, Operands, BaseName)) return true; break; case AsmToken::Real: { @@ -284,7 +303,7 @@ public: // 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 (NamePair.second == "block" || NamePair.second == "loop") { + if (BaseName == "block" || BaseName == "loop") { Operands.push_back(make_unique<WebAssemblyOperand>( WebAssemblyOperand::Integer, NameLoc, NameLoc, WebAssemblyOperand::IntOp{-1})); diff --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s index cf52776061b..b7d0dc00487 100644 --- a/llvm/test/MC/WebAssembly/basic-assembly.s +++ b/llvm/test/MC/WebAssembly/basic-assembly.s @@ -1,4 +1,4 @@ -# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+sign_ext,+simd128 < %s | FileCheck %s +# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint < %s | FileCheck %s .text .type test0,@function @@ -42,6 +42,11 @@ test0: get_local 4 get_local 5 f32x4.add + # Test correct parsing of instructions with / and : in them: + # TODO: enable once instruction has been added. + #i32x4.trunc_s/f32x4:sat + i32.trunc_s/f32 + #i32.trunc_s:sat/f32 end_function @@ -81,4 +86,5 @@ test0: # CHECK-NEXT: get_local 4 # CHECK-NEXT: get_local 5 # CHECK-NEXT: f32x4.add +# CHECK-NEXT: i32.trunc_s/f32 # CHECK-NEXT: end_function |