diff options
-rw-r--r-- | src/binary-reader-ir.cc | 66 | ||||
-rw-r--r-- | src/ir.h | 3 | ||||
-rw-r--r-- | src/validator.cc | 7 | ||||
-rw-r--r-- | src/wast-parser.cc | 5 | ||||
-rw-r--r-- | test/binary/bad-extra-end.txt | 8 | ||||
-rw-r--r-- | test/binary/bad-op-after-end.txt | 8 | ||||
-rw-r--r-- | test/regress/regress-10.txt | 6 | ||||
-rw-r--r-- | test/regress/regress-11.txt | 6 | ||||
-rw-r--r-- | test/typecheck/bad-nested-br.txt | 6 |
9 files changed, 86 insertions, 29 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 317b669f..030e1e81 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -231,6 +231,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result PopLabel(); Result GetLabelAt(LabelNode** label, Index depth); Result TopLabel(LabelNode** label); + Result TopLabelExpr(LabelNode** label, Expr** expr); Result AppendExpr(std::unique_ptr<Expr> expr); ErrorHandler* error_handler_ = nullptr; @@ -291,6 +292,14 @@ Result BinaryReaderIR::TopLabel(LabelNode** label) { return GetLabelAt(label, 0); } +Result BinaryReaderIR::TopLabelExpr(LabelNode** label, Expr** expr) { + CHECK_RESULT(TopLabel(label)); + LabelNode* parent_label; + CHECK_RESULT(GetLabelAt(&parent_label, 1)); + *expr = &parent_label->exprs->back(); + return Result::Ok; +} + Result BinaryReaderIR::AppendExpr(std::unique_ptr<Expr> expr) { expr->loc = GetLocation(); LabelNode* label; @@ -651,26 +660,59 @@ Result BinaryReaderIR::OnDropExpr() { Result BinaryReaderIR::OnElseExpr() { LabelNode* label; - CHECK_RESULT(TopLabel(&label)); - if (label->label_type != LabelType::If && - label->label_type != LabelType::IfExcept) { - PrintError("else expression without matching if"); - return Result::Error; - } - - LabelNode* parent_label; - CHECK_RESULT(GetLabelAt(&parent_label, 1)); + Expr* expr; + CHECK_RESULT(TopLabelExpr(&label, &expr)); if (label->label_type == LabelType::If) { - label->exprs = &cast<IfExpr>(&parent_label->exprs->back())->false_; + auto* if_expr = cast<IfExpr>(expr); + if_expr->true_.end_loc = GetLocation(); + label->exprs = &if_expr->false_; + label->label_type = LabelType::Else; + } else if (label->label_type == LabelType::IfExcept) { + auto* if_except_expr = cast<IfExceptExpr>(expr); + if_except_expr->true_.end_loc = GetLocation(); + label->exprs = &if_except_expr->false_; + label->label_type = LabelType::IfExceptElse; } else { - label->exprs = &cast<IfExceptExpr>(&parent_label->exprs->back())->false_; + PrintError("else expression without matching if"); + return Result::Error; } - label->label_type = LabelType::Else; + return Result::Ok; } Result BinaryReaderIR::OnEndExpr() { + LabelNode* label; + Expr* expr; + CHECK_RESULT(TopLabelExpr(&label, &expr)); + switch (label->label_type) { + case LabelType::Block: + cast<BlockExpr>(expr)->block.end_loc = GetLocation(); + break; + case LabelType::Loop: + cast<LoopExpr>(expr)->block.end_loc = GetLocation(); + break; + case LabelType::If: + cast<IfExpr>(expr)->true_.end_loc = GetLocation(); + break; + case LabelType::Else: + cast<IfExpr>(expr)->false_end_loc = GetLocation(); + break; + case LabelType::IfExcept: + cast<IfExceptExpr>(expr)->true_.end_loc = GetLocation(); + break; + case LabelType::IfExceptElse: + cast<IfExceptExpr>(expr)->false_end_loc = GetLocation(); + break; + case LabelType::Try: + cast<TryExpr>(expr)->block.end_loc = GetLocation(); + break; + + case LabelType::Func: + case LabelType::Catch: + break; + } + return PopLabel(); } @@ -215,6 +215,7 @@ struct Block { std::string label; BlockSignature sig; ExprList exprs; + Location end_loc; }; class Expr : public intrusive_list_base<Expr> { @@ -332,6 +333,7 @@ class IfExpr : public ExprMixin<ExprType::If> { Block true_; ExprList false_; + Location false_end_loc; }; class IfExceptExpr : public ExprMixin<ExprType::IfExcept> { @@ -341,6 +343,7 @@ class IfExceptExpr : public ExprMixin<ExprType::IfExcept> { Block true_; ExprList false_; + Location false_end_loc; Var except_var; }; diff --git a/src/validator.cc b/src/validator.cc index bd8da8a1..e505855c 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -521,6 +521,7 @@ Result Validator::BeginBlockExpr(BlockExpr* expr) { } Result Validator::EndBlockExpr(BlockExpr* expr) { + expr_loc_ = &expr->block.end_loc; typechecker_.OnEnd(); return Result::Ok; } @@ -623,6 +624,8 @@ Result Validator::AfterIfTrueExpr(IfExpr* expr) { } Result Validator::EndIfExpr(IfExpr* expr) { + expr_loc_ = + expr->false_.empty() ? &expr->true_.end_loc : &expr->false_end_loc; typechecker_.OnEnd(); return Result::Ok; } @@ -647,6 +650,8 @@ Result Validator::AfterIfExceptTrueExpr(IfExceptExpr* expr) { } Result Validator::EndIfExceptExpr(IfExceptExpr* expr) { + expr_loc_ = + expr->false_.empty() ? &expr->true_.end_loc : &expr->false_end_loc; typechecker_.OnEnd(); return Result::Ok; } @@ -668,6 +673,7 @@ Result Validator::BeginLoopExpr(LoopExpr* expr) { } Result Validator::EndLoopExpr(LoopExpr* expr) { + expr_loc_ = &expr->block.end_loc; typechecker_.OnEnd(); return Result::Ok; } @@ -755,6 +761,7 @@ Result Validator::OnCatchExpr(TryExpr* expr) { } Result Validator::EndTryExpr(TryExpr* expr) { + expr_loc_ = &expr->block.end_loc; typechecker_.OnEnd(); return Result::Ok; } diff --git a/src/wast-parser.cc b/src/wast-parser.cc index e0713b0b..6464e657 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1710,6 +1710,7 @@ Result WastParser::ParseBlockInstr(std::unique_ptr<Expr>* out_expr) { if (Match(TokenType::Else)) { CHECK_RESULT(ParseEndLabelOpt(expr->true_.label)); CHECK_RESULT(ParseTerminatingInstrList(&expr->false_)); + expr->false_end_loc = GetLocation(); } EXPECT(End); CHECK_RESULT(ParseEndLabelOpt(expr->true_.label)); @@ -1722,9 +1723,11 @@ Result WastParser::ParseBlockInstr(std::unique_ptr<Expr>* out_expr) { auto expr = MakeUnique<IfExceptExpr>(loc); CHECK_RESULT(ParseIfExceptHeader(expr.get())); CHECK_RESULT(ParseInstrList(&expr->true_.exprs)); + expr->true_.end_loc = GetLocation(); if (Match(TokenType::Else)) { CHECK_RESULT(ParseEndLabelOpt(expr->true_.label)); CHECK_RESULT(ParseTerminatingInstrList(&expr->false_)); + expr->false_end_loc = GetLocation(); } EXPECT(End); CHECK_RESULT(ParseEndLabelOpt(expr->true_.label)); @@ -1785,6 +1788,7 @@ Result WastParser::ParseBlock(Block* block) { WABT_TRACE(ParseBlock); CHECK_RESULT(ParseResultList(&block->sig)); CHECK_RESULT(ParseInstrList(&block->exprs)); + block->end_loc = GetLocation(); return Result::Ok; } @@ -1966,6 +1970,7 @@ Result WastParser::ParseExpr(ExprList* exprs) { CHECK_RESULT(ParseLabelOpt(&expr->block.label)); CHECK_RESULT(ParseResultList(&expr->block.sig)); CHECK_RESULT(ParseInstrList(&expr->block.exprs)); + expr->block.end_loc = GetLocation(); EXPECT(Lpar); EXPECT(Catch); CHECK_RESULT(ParseTerminatingInstrList(&expr->catch_)); diff --git a/test/binary/bad-extra-end.txt b/test/binary/bad-extra-end.txt index 04eb6da5..5de7a526 100644 --- a/test/binary/bad-extra-end.txt +++ b/test/binary/bad-extra-end.txt @@ -12,8 +12,8 @@ section(CODE) { } } (;; STDERR ;;; -error: popping empty label stack -000001a: error: OnEndExpr callback failed -error: popping empty label stack -000001a: error: OnEndExpr callback failed +error: accessing stack depth: 1 >= max: 1 +0000019: error: OnEndExpr callback failed +error: accessing stack depth: 1 >= max: 1 +0000019: error: OnEndExpr callback failed ;;; STDERR ;;) diff --git a/test/binary/bad-op-after-end.txt b/test/binary/bad-op-after-end.txt index dd3662f0..85ae0eae 100644 --- a/test/binary/bad-op-after-end.txt +++ b/test/binary/bad-op-after-end.txt @@ -12,8 +12,8 @@ section(CODE) { } } (;; STDERR ;;; -error: accessing stack depth: 0 >= max: 0 -000001a: error: OnNopExpr callback failed -error: accessing stack depth: 0 >= max: 0 -000001a: error: OnNopExpr callback failed +error: accessing stack depth: 1 >= max: 1 +0000019: error: OnEndExpr callback failed +error: accessing stack depth: 1 >= max: 1 +0000019: error: OnEndExpr callback failed ;;; STDERR ;;) diff --git a/test/regress/regress-10.txt b/test/regress/regress-10.txt index 2a21bf3d..9cd31080 100644 --- a/test/regress/regress-10.txt +++ b/test/regress/regress-10.txt @@ -8,7 +8,7 @@ tee_local 0 end)) (;; STDERR ;;; -out/test/regress/regress-10.txt:8:7: error: type mismatch in block, expected [] but got [i32] - tee_local 0 - ^^^^^^^^^ +out/test/regress/regress-10.txt:9:5: error: type mismatch in block, expected [] but got [i32] + end)) + ^^^ ;;; STDERR ;;) diff --git a/test/regress/regress-11.txt b/test/regress/regress-11.txt index 6dc9cfb7..b8e4cb02 100644 --- a/test/regress/regress-11.txt +++ b/test/regress/regress-11.txt @@ -10,7 +10,7 @@ i32.const 1 end)) (;; STDERR ;;; -out/test/regress/regress-11.txt:8:9: error: type mismatch in block, expected [] but got [i32] - br_if 1 - ^^^^^ +out/test/regress/regress-11.txt:9:7: error: type mismatch in block, expected [] but got [i32] + end + ^^^ ;;; STDERR ;;) diff --git a/test/typecheck/bad-nested-br.txt b/test/typecheck/bad-nested-br.txt index 56f18889..2214d885 100644 --- a/test/typecheck/bad-nested-br.txt +++ b/test/typecheck/bad-nested-br.txt @@ -19,7 +19,7 @@ ;; return statement here, or a value returned from (br $outer). )) (;; STDERR ;;; -out/test/typecheck/bad-nested-br.txt:16:7: error: type mismatch in implicit return, expected [i32] but got [] - return - ^^^^^^ +out/test/typecheck/bad-nested-br.txt:17:5: error: type mismatch in implicit return, expected [i32] but got [] + end + ^^^ ;;; STDERR ;;) |