13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "tryStatement.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <compiler/core/pandagen.h>
193af6ab5fSopenharmony_ci#include <compiler/core/dynamicContext.h>
203af6ab5fSopenharmony_ci#include <compiler/base/catchTable.h>
213af6ab5fSopenharmony_ci#include <ir/astDump.h>
223af6ab5fSopenharmony_ci#include <ir/base/catchClause.h>
233af6ab5fSopenharmony_ci#include <ir/statements/blockStatement.h>
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_cinamespace panda::es2panda::ir {
263af6ab5fSopenharmony_ci
273af6ab5fSopenharmony_civoid TryStatement::Iterate(const NodeTraverser &cb) const
283af6ab5fSopenharmony_ci{
293af6ab5fSopenharmony_ci    cb(block_);
303af6ab5fSopenharmony_ci
313af6ab5fSopenharmony_ci    if (catchClause_) {
323af6ab5fSopenharmony_ci        cb(catchClause_);
333af6ab5fSopenharmony_ci    }
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ci    if (finalizer_) {
363af6ab5fSopenharmony_ci        cb(finalizer_);
373af6ab5fSopenharmony_ci    }
383af6ab5fSopenharmony_ci}
393af6ab5fSopenharmony_ci
403af6ab5fSopenharmony_civoid TryStatement::Dump(ir::AstDumper *dumper) const
413af6ab5fSopenharmony_ci{
423af6ab5fSopenharmony_ci    dumper->Add({{"type", "TryStatement"},
433af6ab5fSopenharmony_ci                 {"block", block_},
443af6ab5fSopenharmony_ci                 {"handler", AstDumper::Nullable(catchClause_)},
453af6ab5fSopenharmony_ci                 {"finalizer", AstDumper::Nullable(finalizer_)}});
463af6ab5fSopenharmony_ci}
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_civoid TryStatement::CompileFinally(compiler::PandaGen *pg, compiler::TryContext *tryCtx,
493af6ab5fSopenharmony_ci                                  const compiler::TryLabelSet &labelSet) const
503af6ab5fSopenharmony_ci{
513af6ab5fSopenharmony_ci    compiler::RegScope rs(pg);
523af6ab5fSopenharmony_ci    compiler::VReg exception = pg->AllocReg();
533af6ab5fSopenharmony_ci    pg->StoreConst(this, exception, compiler::Constant::JS_HOLE);
543af6ab5fSopenharmony_ci    pg->Branch(this, labelSet.CatchEnd());
553af6ab5fSopenharmony_ci
563af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.CatchBegin());
573af6ab5fSopenharmony_ci    pg->StoreAccumulator(this, exception);
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.CatchEnd());
603af6ab5fSopenharmony_ci
613af6ab5fSopenharmony_ci    compiler::Label *label = pg->AllocLabel();
623af6ab5fSopenharmony_ci    pg->LoadAccumulator(this, tryCtx->FinalizerRun());
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ci    pg->BranchIfNotUndefined(this, label);
653af6ab5fSopenharmony_ci    pg->StoreAccumulator(this, tryCtx->FinalizerRun());
663af6ab5fSopenharmony_ci    tryCtx->EmitFinalizer();
673af6ab5fSopenharmony_ci    pg->SetLabel(this, label);
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    pg->LoadAccumulator(this, exception);
703af6ab5fSopenharmony_ci    pg->EmitRethrow(this);
713af6ab5fSopenharmony_ci}
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_civoid TryStatement::CompileTryCatchFinally(compiler::PandaGen *pg) const
743af6ab5fSopenharmony_ci{
753af6ab5fSopenharmony_ci    ASSERT(catchClause_ && finalizer_);
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci    compiler::TryContext tryCtx(pg, this);
783af6ab5fSopenharmony_ci    const auto &labelSet = tryCtx.LabelSet();
793af6ab5fSopenharmony_ci
803af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryBegin());
813af6ab5fSopenharmony_ci    {
823af6ab5fSopenharmony_ci        compiler::TryContext innerTryCtx(pg, this, false);
833af6ab5fSopenharmony_ci        const auto &innerLabelSet = innerTryCtx.LabelSet();
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.TryBegin());
863af6ab5fSopenharmony_ci        block_->Compile(pg);
873af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.TryEnd());
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_ci        pg->Branch(this, innerLabelSet.CatchEnd());
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.CatchBegin());
923af6ab5fSopenharmony_ci        catchClause_->Compile(pg);
933af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.CatchEnd());
943af6ab5fSopenharmony_ci    }
953af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryEnd());
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_ci    CompileFinally(pg, &tryCtx, labelSet);
983af6ab5fSopenharmony_ci}
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_civoid TryStatement::CompileTryFinally(compiler::PandaGen *pg) const
1013af6ab5fSopenharmony_ci{
1023af6ab5fSopenharmony_ci    ASSERT(!catchClause_ && finalizer_);
1033af6ab5fSopenharmony_ci
1043af6ab5fSopenharmony_ci    compiler::TryContext tryCtx(pg, this);
1053af6ab5fSopenharmony_ci    const auto &labelSet = tryCtx.LabelSet();
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryBegin());
1083af6ab5fSopenharmony_ci    {
1093af6ab5fSopenharmony_ci        compiler::TryContext innerTryCtx(pg, this, false);
1103af6ab5fSopenharmony_ci        const auto &innerLabelSet = innerTryCtx.LabelSet();
1113af6ab5fSopenharmony_ci
1123af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.TryBegin());
1133af6ab5fSopenharmony_ci        block_->Compile(pg);
1143af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.TryEnd());
1153af6ab5fSopenharmony_ci
1163af6ab5fSopenharmony_ci        pg->Branch(this, innerLabelSet.CatchEnd());
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.CatchBegin());
1193af6ab5fSopenharmony_ci        pg->EmitThrow(this);
1203af6ab5fSopenharmony_ci        pg->SetLabel(this, innerLabelSet.CatchEnd());
1213af6ab5fSopenharmony_ci    }
1223af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryEnd());
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    CompileFinally(pg, &tryCtx, labelSet);
1253af6ab5fSopenharmony_ci}
1263af6ab5fSopenharmony_ci
1273af6ab5fSopenharmony_civoid TryStatement::CompileTryCatch(compiler::PandaGen *pg) const
1283af6ab5fSopenharmony_ci{
1293af6ab5fSopenharmony_ci    ASSERT(catchClause_ && !finalizer_);
1303af6ab5fSopenharmony_ci
1313af6ab5fSopenharmony_ci    compiler::TryContext tryCtx(pg, this);
1323af6ab5fSopenharmony_ci    const auto &labelSet = tryCtx.LabelSet();
1333af6ab5fSopenharmony_ci
1343af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryBegin());
1353af6ab5fSopenharmony_ci    block_->Compile(pg);
1363af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.TryEnd());
1373af6ab5fSopenharmony_ci
1383af6ab5fSopenharmony_ci    pg->Branch(this, labelSet.CatchEnd());
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.CatchBegin());
1413af6ab5fSopenharmony_ci    catchClause_->Compile(pg);
1423af6ab5fSopenharmony_ci    pg->SetLabel(this, labelSet.CatchEnd());
1433af6ab5fSopenharmony_ci}
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_civoid TryStatement::Compile(compiler::PandaGen *pg) const
1463af6ab5fSopenharmony_ci{
1473af6ab5fSopenharmony_ci    if (finalizer_) {
1483af6ab5fSopenharmony_ci        if (catchClause_) {
1493af6ab5fSopenharmony_ci            CompileTryCatchFinally(pg);
1503af6ab5fSopenharmony_ci        } else {
1513af6ab5fSopenharmony_ci            CompileTryFinally(pg);
1523af6ab5fSopenharmony_ci        }
1533af6ab5fSopenharmony_ci    } else {
1543af6ab5fSopenharmony_ci        CompileTryCatch(pg);
1553af6ab5fSopenharmony_ci    }
1563af6ab5fSopenharmony_ci}
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_cichecker::Type *TryStatement::Check(checker::Checker *checker) const
1593af6ab5fSopenharmony_ci{
1603af6ab5fSopenharmony_ci    block_->Check(checker);
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_ci    if (catchClause_) {
1633af6ab5fSopenharmony_ci        catchClause_->Check(checker);
1643af6ab5fSopenharmony_ci    }
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci    if (finalizer_) {
1673af6ab5fSopenharmony_ci        finalizer_->Check(checker);
1683af6ab5fSopenharmony_ci    }
1693af6ab5fSopenharmony_ci
1703af6ab5fSopenharmony_ci    return nullptr;
1713af6ab5fSopenharmony_ci}
1723af6ab5fSopenharmony_ci
1733af6ab5fSopenharmony_civoid TryStatement::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder)
1743af6ab5fSopenharmony_ci{
1753af6ab5fSopenharmony_ci    block_ = std::get<ir::AstNode *>(cb(block_))->AsBlockStatement();
1763af6ab5fSopenharmony_ci
1773af6ab5fSopenharmony_ci    if (catchClause_) {
1783af6ab5fSopenharmony_ci        catchClause_ = std::get<ir::AstNode *>(cb(catchClause_))->AsCatchClause();
1793af6ab5fSopenharmony_ci    }
1803af6ab5fSopenharmony_ci
1813af6ab5fSopenharmony_ci    if (finalizer_) {
1823af6ab5fSopenharmony_ci        finalizer_ = std::get<ir::AstNode *>(cb(finalizer_))->AsBlockStatement();
1833af6ab5fSopenharmony_ci    }
1843af6ab5fSopenharmony_ci}
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci}  // namespace panda::es2panda::ir
187