diff options
author | Alex Crichton <alex@alexcrichton.com> | 2019-02-14 11:07:03 -0600 |
---|---|---|
committer | Ben Smith <binjimin@gmail.com> | 2019-02-14 09:07:03 -0800 |
commit | 2b33a37dc49c033ba9b34f438233f204002415d9 (patch) | |
tree | c7c091542e4287b2e19dfb644e5186ce42235cf0 /src/wast-parser.cc | |
parent | 19191efaf1b5b92b0357b303be1b25cf439be9a2 (diff) | |
download | wabt-2b33a37dc49c033ba9b34f438233f204002415d9.tar.gz wabt-2b33a37dc49c033ba9b34f438233f204002415d9.tar.bz2 wabt-2b33a37dc49c033ba9b34f438233f204002415d9.zip |
Add support for the reference types proposal (#938)
* Add support for the reference types proposal
This commit adds support for the reference types proposal to wabt.
Namely it adds new opcodes like `table.{get,set,grow}` as well as adds a
new `anyref` type. These are plumbed throughout for various operations
in relatively simple fashions, no support was added for a subtyping
relationship between `anyref` and `anyfunc` just yet.
This also raises the restriction that multiple tables are disallowed,
allowing multiple tables to exist when `--enable-reference-types` is
passed.
* Allow nonzero table indices in `call_indirect`
Plumb support throughout for the `call_indirect` instruction (and
`return_call_indirect`) to work with multi-table modules according to
the reference types proposal.
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r-- | src/wast-parser.cc | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc index 66e83a8c..9b4b231d 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -139,8 +139,14 @@ bool IsPlainInstr(TokenType token_type) { case TokenType::TableCopy: case TokenType::ElemDrop: case TokenType::TableInit: + case TokenType::TableGet: + case TokenType::TableSet: + case TokenType::TableGrow: + case TokenType::TableSize: case TokenType::Throw: case TokenType::Rethrow: + case TokenType::RefNull: + case TokenType::RefIsNull: case TokenType::AtomicLoad: case TokenType::AtomicStore: case TokenType::AtomicRmw: @@ -605,7 +611,7 @@ bool WastParser::ParseVarListOpt(VarVector* out_var_list) { Result WastParser::ParseValueType(Type* out_type) { WABT_TRACE(ParseValueType); if (!PeekMatch(TokenType::ValueType)) { - return ErrorExpected({"i32", "i64", "f32", "f64", "v128"}); + return ErrorExpected({"i32", "i64", "f32", "f64", "v128", "anyref"}); } *out_type = Consume().type(); @@ -1000,7 +1006,11 @@ Result WastParser::ParseImportModuleField(Module* module) { ParseBindVarOpt(&name); auto import = MakeUnique<TableImport>(name); CHECK_RESULT(ParseLimits(&import->table.elem_limits)); - EXPECT(Funcref); + if (Match(TokenType::Funcref)) { + import->table.elem_type = Type::Anyfunc; + } else { + CHECK_RESULT(ParseValueType(&import->table.elem_type)); + } EXPECT(Rpar); field = MakeUnique<ImportModuleField>(std::move(import), loc); break; @@ -1126,7 +1136,11 @@ Result WastParser::ParseTableModuleField(Module* module) { auto import = MakeUnique<TableImport>(name); CHECK_RESULT(ParseInlineImport(import.get())); CHECK_RESULT(ParseLimits(&import->table.elem_limits)); - EXPECT(Funcref); + if (Match(TokenType::Funcref)) { + import->table.elem_type = Type::Anyfunc; + } else { + CHECK_RESULT(ParseValueType(&import->table.elem_type)); + } auto field = MakeUnique<ImportModuleField>(std::move(import), GetLocation()); module->AppendField(std::move(field)); @@ -1146,12 +1160,17 @@ Result WastParser::ParseTableModuleField(Module* module) { table_field->table.elem_limits.initial = elem_segment.vars.size(); table_field->table.elem_limits.max = elem_segment.vars.size(); table_field->table.elem_limits.has_max = true; + table_field->table.elem_type = Type::Anyfunc; module->AppendField(std::move(table_field)); module->AppendField(std::move(elem_segment_field)); } else { auto field = MakeUnique<TableModuleField>(loc, name); CHECK_RESULT(ParseLimits(&field->table.elem_limits)); - EXPECT(Funcref); + if (Match(TokenType::Funcref)) { + field->table.elem_type = Type::Anyfunc; + } else { + CHECK_RESULT(ParseValueType(&field->table.elem_type)); + } module->AppendField(std::move(field)); } @@ -1403,6 +1422,7 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) { auto expr = MakeUnique<CallIndirectExpr>(loc); CHECK_RESULT(ParseTypeUseOpt(&expr->decl)); CHECK_RESULT(ParseUnboundFuncSignature(&expr->decl.sig)); + ParseVarOpt(&expr->table, Var(0)); *out_expr = std::move(expr); break; } @@ -1417,6 +1437,7 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) { auto expr = MakeUnique<ReturnCallIndirectExpr>(loc); CHECK_RESULT(ParseTypeUseOpt(&expr->decl)); CHECK_RESULT(ParseUnboundFuncSignature(&expr->decl.sig)); + ParseVarOpt(&expr->table, Var(0)); *out_expr = std::move(expr); break; } @@ -1530,6 +1551,36 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) { CHECK_RESULT(ParsePlainInstrVar<TableInitExpr>(loc, out_expr)); break; + case TokenType::TableGet: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar<TableGetExpr>(loc, out_expr)); + break; + + case TokenType::TableSet: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar<TableSetExpr>(loc, out_expr)); + break; + + case TokenType::TableGrow: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar<TableGrowExpr>(loc, out_expr)); + break; + + case TokenType::TableSize: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar<TableSizeExpr>(loc, out_expr)); + break; + + case TokenType::RefNull: + ErrorUnlessOpcodeEnabled(Consume()); + out_expr->reset(new RefNullExpr(loc)); + break; + + case TokenType::RefIsNull: + ErrorUnlessOpcodeEnabled(Consume()); + out_expr->reset(new RefIsNullExpr(loc)); + break; + case TokenType::Throw: ErrorUnlessOpcodeEnabled(Consume()); CHECK_RESULT(ParsePlainInstrVar<ThrowExpr>(loc, out_expr)); |