diff options
Diffstat (limited to 'src')
-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 |
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(); } @@ -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_)); |