diff options
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r-- | src/wast-parser.cc | 73 |
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); |