forked from OSchip/llvm-project
[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 llvm-svn: 343501
This commit is contained in:
parent
0fff5a87ca
commit
0c83c3ff38
|
@ -227,15 +227,34 @@ public:
|
||||||
|
|
||||||
bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
|
bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
|
||||||
SMLoc NameLoc, OperandVector &Operands) override {
|
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>(
|
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||||
WebAssemblyOperand::Token, NameLoc,
|
WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()),
|
||||||
SMLoc::getFromPointer(NameLoc.getPointer() + Name.size()),
|
WebAssemblyOperand::TokOp{Name}));
|
||||||
WebAssemblyOperand::TokOp{
|
|
||||||
StringRef(NameLoc.getPointer(), Name.size())}));
|
|
||||||
auto NamePair = Name.split('.');
|
auto NamePair = Name.split('.');
|
||||||
// If no '.', there is no type prefix.
|
// If no '.', there is no type prefix.
|
||||||
if (NamePair.second.empty())
|
auto BaseName = NamePair.second.empty() ? NamePair.first : NamePair.second;
|
||||||
std::swap(NamePair.first, NamePair.second);
|
|
||||||
while (Lexer.isNot(AsmToken::EndOfStatement)) {
|
while (Lexer.isNot(AsmToken::EndOfStatement)) {
|
||||||
auto &Tok = Lexer.getTok();
|
auto &Tok = Lexer.getTok();
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
|
@ -254,11 +273,11 @@ public:
|
||||||
Parser.Lex();
|
Parser.Lex();
|
||||||
if (Lexer.isNot(AsmToken::Integer))
|
if (Lexer.isNot(AsmToken::Integer))
|
||||||
return Error("Expected integer instead got: ", Lexer.getTok());
|
return Error("Expected integer instead got: ", Lexer.getTok());
|
||||||
if (ParseOperandStartingWithInteger(true, Operands, NamePair.second))
|
if (ParseOperandStartingWithInteger(true, Operands, BaseName))
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case AsmToken::Integer:
|
case AsmToken::Integer:
|
||||||
if (ParseOperandStartingWithInteger(false, Operands, NamePair.second))
|
if (ParseOperandStartingWithInteger(false, Operands, BaseName))
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case AsmToken::Real: {
|
case AsmToken::Real: {
|
||||||
|
@ -284,7 +303,7 @@ public:
|
||||||
// assembly, so we add a dummy one explicitly (since we have no control
|
// assembly, so we add a dummy one explicitly (since we have no control
|
||||||
// over signature tables here, we assume these will be regenerated when
|
// over signature tables here, we assume these will be regenerated when
|
||||||
// the wasm module is generated).
|
// the wasm module is generated).
|
||||||
if (NamePair.second == "block" || NamePair.second == "loop") {
|
if (BaseName == "block" || BaseName == "loop") {
|
||||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||||
WebAssemblyOperand::Integer, NameLoc, NameLoc,
|
WebAssemblyOperand::Integer, NameLoc, NameLoc,
|
||||||
WebAssemblyOperand::IntOp{-1}));
|
WebAssemblyOperand::IntOp{-1}));
|
||||||
|
|
|
@ -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
|
.text
|
||||||
.type test0,@function
|
.type test0,@function
|
||||||
|
@ -42,6 +42,11 @@ test0:
|
||||||
get_local 4
|
get_local 4
|
||||||
get_local 5
|
get_local 5
|
||||||
f32x4.add
|
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
|
end_function
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,4 +86,5 @@ test0:
|
||||||
# CHECK-NEXT: get_local 4
|
# CHECK-NEXT: get_local 4
|
||||||
# CHECK-NEXT: get_local 5
|
# CHECK-NEXT: get_local 5
|
||||||
# CHECK-NEXT: f32x4.add
|
# CHECK-NEXT: f32x4.add
|
||||||
|
# CHECK-NEXT: i32.trunc_s/f32
|
||||||
# CHECK-NEXT: end_function
|
# CHECK-NEXT: end_function
|
||||||
|
|
Loading…
Reference in New Issue