summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binary-reader-ir.cc66
-rw-r--r--src/ir.h3
-rw-r--r--src/validator.cc7
-rw-r--r--src/wast-parser.cc5
-rw-r--r--test/binary/bad-extra-end.txt8
-rw-r--r--test/binary/bad-op-after-end.txt8
-rw-r--r--test/regress/regress-10.txt6
-rw-r--r--test/regress/regress-11.txt6
-rw-r--r--test/typecheck/bad-nested-br.txt6
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();
}
diff --git a/src/ir.h b/src/ir.h
index 563fc1bb..521a250f 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -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 ;;)