summaryrefslogtreecommitdiff
path: root/src/wast-parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r--src/wast-parser.cc73
1 files changed, 63 insertions, 10 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 6464e657..2e1d1f1d 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -288,6 +288,37 @@ class ResolveFuncTypesExprVisitorDelegate : public ExprVisitor::DelegateNop {
explicit ResolveFuncTypesExprVisitorDelegate(Module* module)
: module_(module) {}
+ void ResolveBlockDeclaration(const Location& loc, BlockDeclaration* decl) {
+ if (decl->GetNumParams() != 0 || decl->GetNumResults() > 1) {
+ ResolveFuncType(loc, module_, decl);
+ }
+ }
+
+ Result BeginBlockExpr(BlockExpr* expr) override {
+ ResolveBlockDeclaration(expr->loc, &expr->block.decl);
+ return Result::Ok;
+ }
+
+ Result BeginIfExpr(IfExpr* expr) override {
+ ResolveBlockDeclaration(expr->loc, &expr->true_.decl);
+ return Result::Ok;
+ }
+
+ Result BeginIfExceptExpr(IfExceptExpr* expr) override {
+ ResolveBlockDeclaration(expr->loc, &expr->true_.decl);
+ return Result::Ok;
+ }
+
+ Result BeginLoopExpr(LoopExpr* expr) override {
+ ResolveBlockDeclaration(expr->loc, &expr->block.decl);
+ return Result::Ok;
+ }
+
+ Result BeginTryExpr(TryExpr* expr) override {
+ ResolveBlockDeclaration(expr->loc, &expr->block.decl);
+ return Result::Ok;
+ }
+
Result OnCallIndirectExpr(CallIndirectExpr* expr) override {
ResolveFuncType(expr->loc, module_, &expr->decl);
return Result::Ok;
@@ -1784,9 +1815,20 @@ Result WastParser::ParseEndLabelOpt(const std::string& begin_label) {
return Result::Ok;
}
+Result WastParser::ParseBlockDeclaration(BlockDeclaration* decl) {
+ WABT_TRACE(ParseBlockDeclaration);
+ FuncDeclaration func_decl;
+ CHECK_RESULT(ParseTypeUseOpt(&func_decl));
+ CHECK_RESULT(ParseUnboundFuncSignature(&func_decl.sig));
+ decl->has_func_type = func_decl.has_func_type;
+ decl->type_var = func_decl.type_var;
+ decl->sig = func_decl.sig;
+ return Result::Ok;
+}
+
Result WastParser::ParseBlock(Block* block) {
WABT_TRACE(ParseBlock);
- CHECK_RESULT(ParseResultList(&block->sig));
+ CHECK_RESULT(ParseBlockDeclaration(&block->decl));
CHECK_RESULT(ParseInstrList(&block->exprs));
block->end_loc = GetLocation();
return Result::Ok;
@@ -1805,22 +1847,33 @@ Result WastParser::ParseIfExceptHeader(IfExceptExpr* expr) {
// 3. if_except $label $except/<num> ...
// 4. if_except (result...) $except/<num> ...
// 5. if_except $label (result...) $except/<num> ...
+ //
+ // With the multi-value proposal, `block_type` can be (param...) (result...),
+ // so there are more forms:
+ //
+ // 6. if_except (param...) $except/<num> ...
+ // 7. if_except (param...) (result...) $except/<num> ...
+ // 8. if_except $label (param...) $except/<num> ...
+ // 9. if_except $label (param...) (result...) $except/<num> ...
+ //
+ // This case is handled by ParseBlockDeclaration, but it means we also need
+ // to check for the `param` token here.
- if (PeekMatchLpar(TokenType::Result)) {
- // Case 4.
- CHECK_RESULT(ParseResultList(&expr->true_.sig));
+ if (PeekMatchLpar(TokenType::Result) || PeekMatchLpar(TokenType::Param)) {
+ // Cases 4, 6, 7.
+ CHECK_RESULT(ParseBlockDeclaration(&expr->true_.decl));
CHECK_RESULT(ParseVar(&expr->except_var));
} else if (PeekMatch(TokenType::Nat)) {
// Case 1.
CHECK_RESULT(ParseVar(&expr->except_var));
} else if (PeekMatch(TokenType::Var)) {
- // Cases 2, 3, 5.
+ // Cases 2, 3, 5, 8, 9.
Var var;
CHECK_RESULT(ParseVar(&var));
- if (PeekMatchLpar(TokenType::Result)) {
- // Case 5.
+ if (PeekMatchLpar(TokenType::Result) || PeekMatchLpar(TokenType::Param)) {
+ // Cases 5, 8, 9.
expr->true_.label = var.name();
- CHECK_RESULT(ParseResultList(&expr->true_.sig));
+ CHECK_RESULT(ParseBlockDeclaration(&expr->true_.decl));
CHECK_RESULT(ParseVar(&expr->except_var));
} else if (ParseVarOpt(&expr->except_var, Var())) {
// Case 3.
@@ -1893,7 +1946,7 @@ Result WastParser::ParseExpr(ExprList* exprs) {
auto expr = MakeUnique<IfExpr>(loc);
CHECK_RESULT(ParseLabelOpt(&expr->true_.label));
- CHECK_RESULT(ParseResultList(&expr->true_.sig));
+ CHECK_RESULT(ParseBlockDeclaration(&expr->true_.decl));
if (PeekMatchExpr()) {
ExprList cond;
@@ -1968,7 +2021,7 @@ Result WastParser::ParseExpr(ExprList* exprs) {
auto expr = MakeUnique<TryExpr>(loc);
CHECK_RESULT(ParseLabelOpt(&expr->block.label));
- CHECK_RESULT(ParseResultList(&expr->block.sig));
+ CHECK_RESULT(ParseBlockDeclaration(&expr->block.decl));
CHECK_RESULT(ParseInstrList(&expr->block.exprs));
expr->block.end_loc = GetLocation();
EXPECT(Lpar);