summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
4 files changed, 69 insertions, 12 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_));