Skip to content

Commit 4c1f42a

Browse files
committed
wast-parser: add support for '(module definition ...)'
WASM v3 spec tests added the '(module definition ...)' construct to WAST. This tells the test runner that the module should not be instantiated immediately. The '(module instance ...)' construct (not yet supported in wabt) instructs the test runner to instantiate the module. This change adds an `is_definition` field to ScriptModule. The field reflects whether the `definition` keyword was encountered after the `module` keyword. When WastParser encounters a TextModule in a script command, it now returns a ScriptModule with the corresponding ScriptTextModule if the module is definition-only.
1 parent ed94ed7 commit 4c1f42a

File tree

7 files changed

+709
-585
lines changed

7 files changed

+709
-585
lines changed

include/wabt/ir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,8 @@ class ScriptModule {
13681368
ScriptModuleType type() const { return type_; }
13691369
virtual const Location& location() const = 0;
13701370

1371+
bool is_definition = false;
1372+
13711373
protected:
13721374
explicit ScriptModule(ScriptModuleType type) : type_(type) {}
13731375

include/wabt/token.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ WABT_TOKEN(Bin, "bin")
3434
WABT_TOKEN(Item, "item")
3535
WABT_TOKEN(Data, "data")
3636
WABT_TOKEN(Declare, "declare")
37+
WABT_TOKEN(Definition, "definition")
3738
WABT_TOKEN(Delegate, "delegate")
3839
WABT_TOKEN(Do, "do")
3940
WABT_TOKEN(Either, "either")

include/wabt/wast-parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ class WastParser {
160160
Result Synchronize(SynchronizeFunc);
161161

162162
bool ParseBindVarOpt(std::string* name);
163+
bool ParseDefinitionOpt();
163164
Result ParseVar(Var* out_var);
164165
bool ParseVarOpt(Var* out_var, Var default_var = Var());
165166
Result ParseOffsetExpr(ExprList* out_expr_list);

src/lexer-keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ code, TokenType::Code
4646
data.drop, TokenType::DataDrop, Opcode::DataDrop
4747
data, TokenType::Data
4848
declare, TokenType::Declare
49+
definition, TokenType::Definition
4950
delegate, TokenType::Delegate
5051
do, TokenType::Do
5152
drop, TokenType::Drop, Opcode::Drop

src/prebuilt/lexer-keywords.cc

Lines changed: 656 additions & 581 deletions
Large diffs are not rendered by default.

src/test-wast-parser.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,22 @@ TEST(WastParser, InvalidBinaryModule) {
117117

118118
EXPECT_EQ(expected_data, binary_mod->data);
119119
}
120+
121+
TEST(WastParser, ModuleDefinition) {
122+
std::string text = "(module definition)";
123+
124+
Errors errors;
125+
auto lexer =
126+
WastLexer::CreateBufferLexer("test", text.c_str(), text.size(), &errors);
127+
Features features;
128+
WastParseOptions options(features);
129+
130+
std::unique_ptr<Script> script;
131+
Result result = ParseWastScript(lexer.get(), &script, &errors, &options);
132+
ASSERT_EQ(result, Result::Ok);
133+
ASSERT_EQ(script->commands.size(), 1U);
134+
Command* cmd = script->commands[0].get();
135+
auto* mod_cmd = cast<ScriptModuleCommand>(cmd);
136+
ASSERT_NE(mod_cmd, nullptr);
137+
ASSERT_TRUE(mod_cmd->script_module->is_definition);
138+
}

src/wast-parser.cc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,15 @@ bool WastParser::ParseBindVarOpt(std::string* name) {
749749
return true;
750750
}
751751

752+
bool WastParser::ParseDefinitionOpt() {
753+
WABT_TRACE(ParseDefinitionOpt);
754+
if (!PeekMatch(TokenType::Definition)) {
755+
return false;
756+
}
757+
(void)Consume();
758+
return true;
759+
}
760+
752761
Result WastParser::ParseVar(Var* out_var) {
753762
WABT_TRACE(ParseVar);
754763
if (PeekMatch(TokenType::Nat)) {
@@ -3664,10 +3673,20 @@ Result WastParser::ParseModuleCommand(Script* script, CommandPtr* out_command) {
36643673

36653674
switch (script_module->type()) {
36663675
case ScriptModuleType::Text: {
3667-
auto command = std::make_unique<ModuleCommand>();
3668-
module = &command->module;
3669-
*module = std::move(cast<TextScriptModule>(script_module.get())->module);
3670-
*out_command = std::move(command);
3676+
if (script_module->is_definition) {
3677+
auto command = std::make_unique<ScriptModuleCommand>();
3678+
module = &command->module;
3679+
*module =
3680+
std::move(cast<TextScriptModule>(script_module.get())->module);
3681+
command->script_module = std::move(script_module);
3682+
*out_command = std::move(command);
3683+
} else {
3684+
auto command = std::make_unique<ModuleCommand>();
3685+
module = &command->module;
3686+
*module =
3687+
std::move(cast<TextScriptModule>(script_module.get())->module);
3688+
*out_command = std::move(command);
3689+
}
36713690
break;
36723691
}
36733692

@@ -3852,6 +3871,9 @@ Result WastParser::ParseScriptModule(
38523871
EXPECT(Lpar);
38533872
Location loc = GetLocation();
38543873
EXPECT(Module);
3874+
3875+
bool is_definition = ParseDefinitionOpt();
3876+
38553877
std::string name;
38563878
ParseBindVarOpt(&name);
38573879

@@ -3867,6 +3889,7 @@ Result WastParser::ParseScriptModule(
38673889
bsm->name = name;
38683890
bsm->loc = loc;
38693891
bsm->data = std::move(data);
3892+
bsm->is_definition = is_definition;
38703893
*out_module = std::move(bsm);
38713894
break;
38723895
}
@@ -3882,6 +3905,7 @@ Result WastParser::ParseScriptModule(
38823905
qsm->name = name;
38833906
qsm->loc = loc;
38843907
qsm->data = std::move(data);
3908+
qsm->is_definition = is_definition;
38853909
*out_module = std::move(qsm);
38863910
break;
38873911
}
@@ -3890,6 +3914,7 @@ Result WastParser::ParseScriptModule(
38903914
auto tsm = std::make_unique<TextScriptModule>();
38913915
tsm->module.name = name;
38923916
tsm->module.loc = loc;
3917+
tsm->is_definition = is_definition;
38933918
if (IsModuleField(PeekPair()) || PeekIsCustom()) {
38943919
CHECK_RESULT(ParseModuleFieldList(&tsm->module));
38953920
} else if (!PeekMatch(TokenType::Rpar)) {

0 commit comments

Comments
 (0)