11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/wasm/graph-builder-interface.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/compiler/wasm-compiler.h"
81cb0ef41Sopenharmony_ci#include "src/flags/flags.h"
91cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
101cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
111cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
121cb0ef41Sopenharmony_ci#include "src/wasm/branch-hint-map.h"
131cb0ef41Sopenharmony_ci#include "src/wasm/decoder.h"
141cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder-impl.h"
151cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder.h"
161cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h"
171cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h"
181cb0ef41Sopenharmony_ci#include "src/wasm/wasm-linkage.h"
191cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
201cb0ef41Sopenharmony_ci#include "src/wasm/wasm-opcodes-inl.h"
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace v8 {
231cb0ef41Sopenharmony_cinamespace internal {
241cb0ef41Sopenharmony_cinamespace wasm {
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci// An SsaEnv environment carries the current local variable renaming
291cb0ef41Sopenharmony_ci// as well as the current effect and control dependency in the TF graph.
301cb0ef41Sopenharmony_ci// It maintains a control state that tracks whether the environment
311cb0ef41Sopenharmony_ci// is reachable, has reached a control end, or has been merged.
321cb0ef41Sopenharmony_cistruct SsaEnv : public ZoneObject {
331cb0ef41Sopenharmony_ci  enum State { kUnreachable, kReached, kMerged };
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  State state;
361cb0ef41Sopenharmony_ci  TFNode* control;
371cb0ef41Sopenharmony_ci  TFNode* effect;
381cb0ef41Sopenharmony_ci  compiler::WasmInstanceCacheNodes instance_cache;
391cb0ef41Sopenharmony_ci  ZoneVector<TFNode*> locals;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  SsaEnv(Zone* zone, State state, TFNode* control, TFNode* effect,
421cb0ef41Sopenharmony_ci         uint32_t locals_size)
431cb0ef41Sopenharmony_ci      : state(state),
441cb0ef41Sopenharmony_ci        control(control),
451cb0ef41Sopenharmony_ci        effect(effect),
461cb0ef41Sopenharmony_ci        locals(locals_size, zone) {}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  SsaEnv(const SsaEnv& other) V8_NOEXCEPT = default;
491cb0ef41Sopenharmony_ci  SsaEnv(SsaEnv&& other) V8_NOEXCEPT : state(other.state),
501cb0ef41Sopenharmony_ci                                       control(other.control),
511cb0ef41Sopenharmony_ci                                       effect(other.effect),
521cb0ef41Sopenharmony_ci                                       instance_cache(other.instance_cache),
531cb0ef41Sopenharmony_ci                                       locals(std::move(other.locals)) {
541cb0ef41Sopenharmony_ci    other.Kill();
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  void Kill() {
581cb0ef41Sopenharmony_ci    state = kUnreachable;
591cb0ef41Sopenharmony_ci    for (TFNode*& local : locals) {
601cb0ef41Sopenharmony_ci      local = nullptr;
611cb0ef41Sopenharmony_ci    }
621cb0ef41Sopenharmony_ci    control = nullptr;
631cb0ef41Sopenharmony_ci    effect = nullptr;
641cb0ef41Sopenharmony_ci    instance_cache = {};
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci  void SetNotMerged() {
671cb0ef41Sopenharmony_ci    if (state == kMerged) state = kReached;
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci};
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciclass WasmGraphBuildingInterface {
721cb0ef41Sopenharmony_ci public:
731cb0ef41Sopenharmony_ci  static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
741cb0ef41Sopenharmony_ci  using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
751cb0ef41Sopenharmony_ci  using CheckForNull = compiler::WasmGraphBuilder::CheckForNull;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  struct Value : public ValueBase<validate> {
781cb0ef41Sopenharmony_ci    TFNode* node = nullptr;
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    template <typename... Args>
811cb0ef41Sopenharmony_ci    explicit Value(Args&&... args) V8_NOEXCEPT
821cb0ef41Sopenharmony_ci        : ValueBase(std::forward<Args>(args)...) {}
831cb0ef41Sopenharmony_ci  };
841cb0ef41Sopenharmony_ci  using ValueVector = base::SmallVector<Value, 8>;
851cb0ef41Sopenharmony_ci  using NodeVector = base::SmallVector<TFNode*, 8>;
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  struct TryInfo : public ZoneObject {
881cb0ef41Sopenharmony_ci    SsaEnv* catch_env;
891cb0ef41Sopenharmony_ci    TFNode* exception = nullptr;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci    bool might_throw() const { return exception != nullptr; }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TryInfo);
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci    explicit TryInfo(SsaEnv* c) : catch_env(c) {}
961cb0ef41Sopenharmony_ci  };
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  struct Control : public ControlBase<Value, validate> {
991cb0ef41Sopenharmony_ci    SsaEnv* merge_env = nullptr;  // merge environment for the construct.
1001cb0ef41Sopenharmony_ci    SsaEnv* false_env = nullptr;  // false environment (only for if).
1011cb0ef41Sopenharmony_ci    TryInfo* try_info = nullptr;  // information about try statements.
1021cb0ef41Sopenharmony_ci    int32_t previous_catch = -1;  // previous Control with a catch.
1031cb0ef41Sopenharmony_ci    BitVector* loop_assignments = nullptr;  // locals assigned in this loop.
1041cb0ef41Sopenharmony_ci    TFNode* loop_node = nullptr;            // loop header of this loop.
1051cb0ef41Sopenharmony_ci    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Control);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci    template <typename... Args>
1081cb0ef41Sopenharmony_ci    explicit Control(Args&&... args) V8_NOEXCEPT
1091cb0ef41Sopenharmony_ci        : ControlBase(std::forward<Args>(args)...) {}
1101cb0ef41Sopenharmony_ci  };
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder,
1131cb0ef41Sopenharmony_ci                             int func_index, InlinedStatus inlined_status)
1141cb0ef41Sopenharmony_ci      : builder_(builder),
1151cb0ef41Sopenharmony_ci        func_index_(func_index),
1161cb0ef41Sopenharmony_ci        inlined_status_(inlined_status) {}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  void StartFunction(FullDecoder* decoder) {
1191cb0ef41Sopenharmony_ci    // Get the branch hints map and type feedback for this function (if
1201cb0ef41Sopenharmony_ci    // available).
1211cb0ef41Sopenharmony_ci    if (decoder->module_) {
1221cb0ef41Sopenharmony_ci      auto branch_hints_it = decoder->module_->branch_hints.find(func_index_);
1231cb0ef41Sopenharmony_ci      if (branch_hints_it != decoder->module_->branch_hints.end()) {
1241cb0ef41Sopenharmony_ci        branch_hints_ = &branch_hints_it->second;
1251cb0ef41Sopenharmony_ci      }
1261cb0ef41Sopenharmony_ci      TypeFeedbackStorage& feedbacks = decoder->module_->type_feedback;
1271cb0ef41Sopenharmony_ci      base::MutexGuard mutex_guard(&feedbacks.mutex);
1281cb0ef41Sopenharmony_ci      auto feedback = feedbacks.feedback_for_function.find(func_index_);
1291cb0ef41Sopenharmony_ci      if (feedback != feedbacks.feedback_for_function.end()) {
1301cb0ef41Sopenharmony_ci        type_feedback_ = feedback->second.feedback_vector;
1311cb0ef41Sopenharmony_ci        // We need to keep the feedback in the module to inline later. However,
1321cb0ef41Sopenharmony_ci        // this means we are stuck with it forever.
1331cb0ef41Sopenharmony_ci        // TODO(jkummerow): Reconsider our options here.
1341cb0ef41Sopenharmony_ci      }
1351cb0ef41Sopenharmony_ci    }
1361cb0ef41Sopenharmony_ci    // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
1371cb0ef41Sopenharmony_ci    // instance parameter.
1381cb0ef41Sopenharmony_ci    builder_->Start(static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
1391cb0ef41Sopenharmony_ci    uint32_t num_locals = decoder->num_locals();
1401cb0ef41Sopenharmony_ci    SsaEnv* ssa_env = decoder->zone()->New<SsaEnv>(
1411cb0ef41Sopenharmony_ci        decoder->zone(), SsaEnv::kReached, effect(), control(), num_locals);
1421cb0ef41Sopenharmony_ci    SetEnv(ssa_env);
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci    // Initialize local variables. Parameters are shifted by 1 because of the
1451cb0ef41Sopenharmony_ci    // the instance parameter.
1461cb0ef41Sopenharmony_ci    uint32_t index = 0;
1471cb0ef41Sopenharmony_ci    for (; index < decoder->sig_->parameter_count(); ++index) {
1481cb0ef41Sopenharmony_ci      ssa_env->locals[index] = builder_->Param(index + 1);
1491cb0ef41Sopenharmony_ci    }
1501cb0ef41Sopenharmony_ci    while (index < num_locals) {
1511cb0ef41Sopenharmony_ci      ValueType type = decoder->local_type(index);
1521cb0ef41Sopenharmony_ci      TFNode* node;
1531cb0ef41Sopenharmony_ci      if ((decoder->enabled_.has_nn_locals() ||
1541cb0ef41Sopenharmony_ci           decoder->enabled_.has_unsafe_nn_locals()) &&
1551cb0ef41Sopenharmony_ci          !type.is_defaultable()) {
1561cb0ef41Sopenharmony_ci        DCHECK(type.is_reference());
1571cb0ef41Sopenharmony_ci        // TODO(jkummerow): Consider using "the hole" instead, to make any
1581cb0ef41Sopenharmony_ci        // illegal uses more obvious.
1591cb0ef41Sopenharmony_ci        node = builder_->RefNull();
1601cb0ef41Sopenharmony_ci      } else {
1611cb0ef41Sopenharmony_ci        node = DefaultValue(type);
1621cb0ef41Sopenharmony_ci      }
1631cb0ef41Sopenharmony_ci      while (index < num_locals && decoder->local_type(index) == type) {
1641cb0ef41Sopenharmony_ci        // Do a whole run of like-typed locals at a time.
1651cb0ef41Sopenharmony_ci        ssa_env->locals[index++] = node;
1661cb0ef41Sopenharmony_ci      }
1671cb0ef41Sopenharmony_ci    }
1681cb0ef41Sopenharmony_ci    LoadContextIntoSsa(ssa_env);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm && inlined_status_ == kRegularFunction) {
1711cb0ef41Sopenharmony_ci      builder_->TraceFunctionEntry(decoder->position());
1721cb0ef41Sopenharmony_ci    }
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // Reload the instance cache entries into the Ssa Environment.
1761cb0ef41Sopenharmony_ci  void LoadContextIntoSsa(SsaEnv* ssa_env) {
1771cb0ef41Sopenharmony_ci    if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  void StartFunctionBody(FullDecoder* decoder, Control* block) {}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  void FinishFunction(FullDecoder*) {
1831cb0ef41Sopenharmony_ci    if (inlined_status_ == kRegularFunction) {
1841cb0ef41Sopenharmony_ci      builder_->PatchInStackCheckIfNeeded();
1851cb0ef41Sopenharmony_ci    }
1861cb0ef41Sopenharmony_ci  }
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  void OnFirstError(FullDecoder*) {}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  void NextInstruction(FullDecoder*, WasmOpcode) {}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  void Block(FullDecoder* decoder, Control* block) {
1931cb0ef41Sopenharmony_ci    // The branch environment is the outer environment.
1941cb0ef41Sopenharmony_ci    block->merge_env = ssa_env_;
1951cb0ef41Sopenharmony_ci    SetEnv(Steal(decoder->zone(), ssa_env_));
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  void Loop(FullDecoder* decoder, Control* block) {
1991cb0ef41Sopenharmony_ci    // This is the merge environment at the beginning of the loop.
2001cb0ef41Sopenharmony_ci    SsaEnv* merge_env = Steal(decoder->zone(), ssa_env_);
2011cb0ef41Sopenharmony_ci    block->merge_env = merge_env;
2021cb0ef41Sopenharmony_ci    SetEnv(merge_env);
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci    ssa_env_->state = SsaEnv::kMerged;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci    TFNode* loop_node = builder_->Loop(control());
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci    if (emit_loop_exits()) {
2091cb0ef41Sopenharmony_ci      uint32_t nesting_depth = 0;
2101cb0ef41Sopenharmony_ci      for (uint32_t depth = 1; depth < decoder->control_depth(); depth++) {
2111cb0ef41Sopenharmony_ci        if (decoder->control_at(depth)->is_loop()) {
2121cb0ef41Sopenharmony_ci          nesting_depth++;
2131cb0ef41Sopenharmony_ci        }
2141cb0ef41Sopenharmony_ci      }
2151cb0ef41Sopenharmony_ci      // If this loop is nested, the parent loop's can_be_innermost field needs
2161cb0ef41Sopenharmony_ci      // to be false. If the last loop in loop_infos_ has less depth, it has to
2171cb0ef41Sopenharmony_ci      // be the parent loop. If it does not, it means another loop has been
2181cb0ef41Sopenharmony_ci      // found within the parent loop, and that loop will have set the parent's
2191cb0ef41Sopenharmony_ci      // can_be_innermost to false, so we do not need to do anything.
2201cb0ef41Sopenharmony_ci      if (nesting_depth > 0 &&
2211cb0ef41Sopenharmony_ci          loop_infos_.back().nesting_depth < nesting_depth) {
2221cb0ef41Sopenharmony_ci        loop_infos_.back().can_be_innermost = false;
2231cb0ef41Sopenharmony_ci      }
2241cb0ef41Sopenharmony_ci      loop_infos_.emplace_back(loop_node, nesting_depth, true);
2251cb0ef41Sopenharmony_ci    }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci    builder_->SetControl(loop_node);
2281cb0ef41Sopenharmony_ci    decoder->control_at(0)->loop_node = loop_node;
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci    TFNode* effect_inputs[] = {effect(), control()};
2311cb0ef41Sopenharmony_ci    builder_->SetEffect(builder_->EffectPhi(1, effect_inputs));
2321cb0ef41Sopenharmony_ci    builder_->TerminateLoop(effect(), control());
2331cb0ef41Sopenharmony_ci    // Doing a preprocessing pass to analyze loop assignments seems to pay off
2341cb0ef41Sopenharmony_ci    // compared to reallocating Nodes when rearranging Phis in Goto.
2351cb0ef41Sopenharmony_ci    BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
2361cb0ef41Sopenharmony_ci        decoder, decoder->pc(), decoder->num_locals(), decoder->zone());
2371cb0ef41Sopenharmony_ci    if (decoder->failed()) return;
2381cb0ef41Sopenharmony_ci    int instance_cache_index = decoder->num_locals();
2391cb0ef41Sopenharmony_ci    // If the module has shared memory, the stack guard might reallocate the
2401cb0ef41Sopenharmony_ci    // shared memory. We have to assume the instance cache will be updated.
2411cb0ef41Sopenharmony_ci    if (decoder->module_->has_shared_memory) {
2421cb0ef41Sopenharmony_ci      assigned->Add(instance_cache_index);
2431cb0ef41Sopenharmony_ci    }
2441cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(assigned);
2451cb0ef41Sopenharmony_ci    decoder->control_at(0)->loop_assignments = assigned;
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci    // Only introduce phis for variables assigned in this loop.
2481cb0ef41Sopenharmony_ci    for (int i = decoder->num_locals() - 1; i >= 0; i--) {
2491cb0ef41Sopenharmony_ci      if (!assigned->Contains(i)) continue;
2501cb0ef41Sopenharmony_ci      TFNode* inputs[] = {ssa_env_->locals[i], control()};
2511cb0ef41Sopenharmony_ci      ssa_env_->locals[i] = builder_->Phi(decoder->local_type(i), 1, inputs);
2521cb0ef41Sopenharmony_ci    }
2531cb0ef41Sopenharmony_ci    // Introduce phis for instance cache pointers if necessary.
2541cb0ef41Sopenharmony_ci    if (assigned->Contains(instance_cache_index)) {
2551cb0ef41Sopenharmony_ci      builder_->PrepareInstanceCacheForLoop(&ssa_env_->instance_cache,
2561cb0ef41Sopenharmony_ci                                            control());
2571cb0ef41Sopenharmony_ci    }
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci    // Now we setup a new environment for the inside of the loop.
2601cb0ef41Sopenharmony_ci    SetEnv(Split(decoder->zone(), ssa_env_));
2611cb0ef41Sopenharmony_ci    builder_->StackCheck(decoder->module_->has_shared_memory
2621cb0ef41Sopenharmony_ci                             ? &ssa_env_->instance_cache
2631cb0ef41Sopenharmony_ci                             : nullptr,
2641cb0ef41Sopenharmony_ci                         decoder->position());
2651cb0ef41Sopenharmony_ci    ssa_env_->SetNotMerged();
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci    // Wrap input merge into phis.
2681cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
2691cb0ef41Sopenharmony_ci      Value& val = block->start_merge[i];
2701cb0ef41Sopenharmony_ci      TFNode* inputs[] = {val.node, block->merge_env->control};
2711cb0ef41Sopenharmony_ci      val.node = builder_->Phi(val.type, 1, inputs);
2721cb0ef41Sopenharmony_ci    }
2731cb0ef41Sopenharmony_ci  }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  void Try(FullDecoder* decoder, Control* block) {
2761cb0ef41Sopenharmony_ci    SsaEnv* outer_env = ssa_env_;
2771cb0ef41Sopenharmony_ci    SsaEnv* catch_env = Split(decoder->zone(), outer_env);
2781cb0ef41Sopenharmony_ci    // Mark catch environment as unreachable, since only accessable
2791cb0ef41Sopenharmony_ci    // through catch unwinding (i.e. landing pads).
2801cb0ef41Sopenharmony_ci    catch_env->state = SsaEnv::kUnreachable;
2811cb0ef41Sopenharmony_ci    SsaEnv* try_env = Steal(decoder->zone(), outer_env);
2821cb0ef41Sopenharmony_ci    SetEnv(try_env);
2831cb0ef41Sopenharmony_ci    TryInfo* try_info = decoder->zone()->New<TryInfo>(catch_env);
2841cb0ef41Sopenharmony_ci    block->merge_env = outer_env;
2851cb0ef41Sopenharmony_ci    block->try_info = try_info;
2861cb0ef41Sopenharmony_ci  }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci  void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
2891cb0ef41Sopenharmony_ci    TFNode* if_true = nullptr;
2901cb0ef41Sopenharmony_ci    TFNode* if_false = nullptr;
2911cb0ef41Sopenharmony_ci    WasmBranchHint hint = WasmBranchHint::kNoHint;
2921cb0ef41Sopenharmony_ci    if (branch_hints_) {
2931cb0ef41Sopenharmony_ci      hint = branch_hints_->GetHintFor(decoder->pc_relative_offset());
2941cb0ef41Sopenharmony_ci    }
2951cb0ef41Sopenharmony_ci    switch (hint) {
2961cb0ef41Sopenharmony_ci      case WasmBranchHint::kNoHint:
2971cb0ef41Sopenharmony_ci        builder_->BranchNoHint(cond.node, &if_true, &if_false);
2981cb0ef41Sopenharmony_ci        break;
2991cb0ef41Sopenharmony_ci      case WasmBranchHint::kUnlikely:
3001cb0ef41Sopenharmony_ci        builder_->BranchExpectFalse(cond.node, &if_true, &if_false);
3011cb0ef41Sopenharmony_ci        break;
3021cb0ef41Sopenharmony_ci      case WasmBranchHint::kLikely:
3031cb0ef41Sopenharmony_ci        builder_->BranchExpectTrue(cond.node, &if_true, &if_false);
3041cb0ef41Sopenharmony_ci        break;
3051cb0ef41Sopenharmony_ci    }
3061cb0ef41Sopenharmony_ci    SsaEnv* merge_env = ssa_env_;
3071cb0ef41Sopenharmony_ci    SsaEnv* false_env = Split(decoder->zone(), ssa_env_);
3081cb0ef41Sopenharmony_ci    false_env->control = if_false;
3091cb0ef41Sopenharmony_ci    SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
3101cb0ef41Sopenharmony_ci    true_env->control = if_true;
3111cb0ef41Sopenharmony_ci    if_block->merge_env = merge_env;
3121cb0ef41Sopenharmony_ci    if_block->false_env = false_env;
3131cb0ef41Sopenharmony_ci    SetEnv(true_env);
3141cb0ef41Sopenharmony_ci  }
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci  void FallThruTo(FullDecoder* decoder, Control* c) {
3171cb0ef41Sopenharmony_ci    DCHECK(!c->is_loop());
3181cb0ef41Sopenharmony_ci    MergeValuesInto(decoder, c, &c->end_merge);
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  void PopControl(FullDecoder* decoder, Control* block) {
3221cb0ef41Sopenharmony_ci    // A loop just continues with the end environment. There is no merge.
3231cb0ef41Sopenharmony_ci    // However, if loop unrolling is enabled, we must create a loop exit and
3241cb0ef41Sopenharmony_ci    // wrap the fallthru values on the stack.
3251cb0ef41Sopenharmony_ci    if (block->is_loop()) {
3261cb0ef41Sopenharmony_ci      if (emit_loop_exits() && block->reachable()) {
3271cb0ef41Sopenharmony_ci        BuildLoopExits(decoder, block);
3281cb0ef41Sopenharmony_ci        WrapLocalsAtLoopExit(decoder, block);
3291cb0ef41Sopenharmony_ci        uint32_t arity = block->end_merge.arity;
3301cb0ef41Sopenharmony_ci        if (arity > 0) {
3311cb0ef41Sopenharmony_ci          Value* stack_base = decoder->stack_value(arity);
3321cb0ef41Sopenharmony_ci          for (uint32_t i = 0; i < arity; i++) {
3331cb0ef41Sopenharmony_ci            Value* val = stack_base + i;
3341cb0ef41Sopenharmony_ci            val->node = builder_->LoopExitValue(
3351cb0ef41Sopenharmony_ci                val->node, val->type.machine_representation());
3361cb0ef41Sopenharmony_ci          }
3371cb0ef41Sopenharmony_ci        }
3381cb0ef41Sopenharmony_ci      }
3391cb0ef41Sopenharmony_ci      return;
3401cb0ef41Sopenharmony_ci    }
3411cb0ef41Sopenharmony_ci    // Any other block falls through to the parent block.
3421cb0ef41Sopenharmony_ci    if (block->reachable()) FallThruTo(decoder, block);
3431cb0ef41Sopenharmony_ci    if (block->is_onearmed_if()) {
3441cb0ef41Sopenharmony_ci      // Merge the else branch into the end merge.
3451cb0ef41Sopenharmony_ci      SetEnv(block->false_env);
3461cb0ef41Sopenharmony_ci      DCHECK_EQ(block->start_merge.arity, block->end_merge.arity);
3471cb0ef41Sopenharmony_ci      Value* values =
3481cb0ef41Sopenharmony_ci          block->start_merge.arity > 0 ? &block->start_merge[0] : nullptr;
3491cb0ef41Sopenharmony_ci      MergeValuesInto(decoder, block, &block->end_merge, values);
3501cb0ef41Sopenharmony_ci    }
3511cb0ef41Sopenharmony_ci    // Now continue with the merged environment.
3521cb0ef41Sopenharmony_ci    SetEnv(block->merge_env);
3531cb0ef41Sopenharmony_ci  }
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci  void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
3561cb0ef41Sopenharmony_ci            Value* result) {
3571cb0ef41Sopenharmony_ci    result->node = builder_->Unop(opcode, value.node, decoder->position());
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
3611cb0ef41Sopenharmony_ci             const Value& rhs, Value* result) {
3621cb0ef41Sopenharmony_ci    TFNode* node =
3631cb0ef41Sopenharmony_ci        builder_->Binop(opcode, lhs.node, rhs.node, decoder->position());
3641cb0ef41Sopenharmony_ci    if (result) result->node = node;
3651cb0ef41Sopenharmony_ci  }
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
3681cb0ef41Sopenharmony_ci    result->node = builder_->Int32Constant(value);
3691cb0ef41Sopenharmony_ci  }
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci  void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
3721cb0ef41Sopenharmony_ci    result->node = builder_->Int64Constant(value);
3731cb0ef41Sopenharmony_ci  }
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci  void F32Const(FullDecoder* decoder, Value* result, float value) {
3761cb0ef41Sopenharmony_ci    result->node = builder_->Float32Constant(value);
3771cb0ef41Sopenharmony_ci  }
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  void F64Const(FullDecoder* decoder, Value* result, double value) {
3801cb0ef41Sopenharmony_ci    result->node = builder_->Float64Constant(value);
3811cb0ef41Sopenharmony_ci  }
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  void S128Const(FullDecoder* decoder, const Simd128Immediate<validate>& imm,
3841cb0ef41Sopenharmony_ci                 Value* result) {
3851cb0ef41Sopenharmony_ci    result->node = builder_->Simd128Constant(imm.value);
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
3891cb0ef41Sopenharmony_ci    result->node = builder_->RefNull();
3901cb0ef41Sopenharmony_ci  }
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) {
3931cb0ef41Sopenharmony_ci    result->node = builder_->RefFunc(function_index);
3941cb0ef41Sopenharmony_ci  }
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  void RefAsNonNull(FullDecoder* decoder, const Value& arg, Value* result) {
3971cb0ef41Sopenharmony_ci    result->node = builder_->RefAsNonNull(arg.node, decoder->position());
3981cb0ef41Sopenharmony_ci  }
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  void Drop(FullDecoder* decoder) {}
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  void LocalGet(FullDecoder* decoder, Value* result,
4031cb0ef41Sopenharmony_ci                const IndexImmediate<validate>& imm) {
4041cb0ef41Sopenharmony_ci    result->node = ssa_env_->locals[imm.index];
4051cb0ef41Sopenharmony_ci  }
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci  void LocalSet(FullDecoder* decoder, const Value& value,
4081cb0ef41Sopenharmony_ci                const IndexImmediate<validate>& imm) {
4091cb0ef41Sopenharmony_ci    ssa_env_->locals[imm.index] = value.node;
4101cb0ef41Sopenharmony_ci  }
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  void LocalTee(FullDecoder* decoder, const Value& value, Value* result,
4131cb0ef41Sopenharmony_ci                const IndexImmediate<validate>& imm) {
4141cb0ef41Sopenharmony_ci    result->node = value.node;
4151cb0ef41Sopenharmony_ci    ssa_env_->locals[imm.index] = value.node;
4161cb0ef41Sopenharmony_ci  }
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  void AllocateLocals(FullDecoder* decoder, base::Vector<Value> local_values) {
4191cb0ef41Sopenharmony_ci    ZoneVector<TFNode*>* locals = &ssa_env_->locals;
4201cb0ef41Sopenharmony_ci    locals->insert(locals->begin(), local_values.size(), nullptr);
4211cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < local_values.size(); i++) {
4221cb0ef41Sopenharmony_ci      (*locals)[i] = local_values[i].node;
4231cb0ef41Sopenharmony_ci    }
4241cb0ef41Sopenharmony_ci  }
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  void DeallocateLocals(FullDecoder* decoder, uint32_t count) {
4271cb0ef41Sopenharmony_ci    ZoneVector<TFNode*>* locals = &ssa_env_->locals;
4281cb0ef41Sopenharmony_ci    locals->erase(locals->begin(), locals->begin() + count);
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  void GlobalGet(FullDecoder* decoder, Value* result,
4321cb0ef41Sopenharmony_ci                 const GlobalIndexImmediate<validate>& imm) {
4331cb0ef41Sopenharmony_ci    result->node = builder_->GlobalGet(imm.index);
4341cb0ef41Sopenharmony_ci  }
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  void GlobalSet(FullDecoder* decoder, const Value& value,
4371cb0ef41Sopenharmony_ci                 const GlobalIndexImmediate<validate>& imm) {
4381cb0ef41Sopenharmony_ci    builder_->GlobalSet(imm.index, value.node);
4391cb0ef41Sopenharmony_ci  }
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  void TableGet(FullDecoder* decoder, const Value& index, Value* result,
4421cb0ef41Sopenharmony_ci                const IndexImmediate<validate>& imm) {
4431cb0ef41Sopenharmony_ci    result->node =
4441cb0ef41Sopenharmony_ci        builder_->TableGet(imm.index, index.node, decoder->position());
4451cb0ef41Sopenharmony_ci  }
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  void TableSet(FullDecoder* decoder, const Value& index, const Value& value,
4481cb0ef41Sopenharmony_ci                const IndexImmediate<validate>& imm) {
4491cb0ef41Sopenharmony_ci    builder_->TableSet(imm.index, index.node, value.node, decoder->position());
4501cb0ef41Sopenharmony_ci  }
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci  void Trap(FullDecoder* decoder, TrapReason reason) {
4531cb0ef41Sopenharmony_ci    builder_->Trap(reason, decoder->position());
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  void AssertNull(FullDecoder* decoder, const Value& obj, Value* result) {
4571cb0ef41Sopenharmony_ci    builder_->TrapIfFalse(
4581cb0ef41Sopenharmony_ci        wasm::TrapReason::kTrapIllegalCast,
4591cb0ef41Sopenharmony_ci        builder_->Binop(kExprRefEq, obj.node, builder_->RefNull(),
4601cb0ef41Sopenharmony_ci                        decoder->position()),
4611cb0ef41Sopenharmony_ci        decoder->position());
4621cb0ef41Sopenharmony_ci    result->node = obj.node;
4631cb0ef41Sopenharmony_ci  }
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  void NopForTestingUnsupportedInLiftoff(FullDecoder* decoder) {}
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
4681cb0ef41Sopenharmony_ci              const Value& tval, Value* result) {
4691cb0ef41Sopenharmony_ci    result->node =
4701cb0ef41Sopenharmony_ci      builder_->Select(cond.node, tval.node, fval.node, result->type);
4711cb0ef41Sopenharmony_ci  }
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci  ValueVector CopyStackValues(FullDecoder* decoder, uint32_t count,
4741cb0ef41Sopenharmony_ci                              uint32_t drop_values) {
4751cb0ef41Sopenharmony_ci    Value* stack_base =
4761cb0ef41Sopenharmony_ci        count > 0 ? decoder->stack_value(count + drop_values) : nullptr;
4771cb0ef41Sopenharmony_ci    ValueVector stack_values(count);
4781cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < count; i++) {
4791cb0ef41Sopenharmony_ci      stack_values[i] = stack_base[i];
4801cb0ef41Sopenharmony_ci    }
4811cb0ef41Sopenharmony_ci    return stack_values;
4821cb0ef41Sopenharmony_ci  }
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  void DoReturn(FullDecoder* decoder, uint32_t drop_values) {
4851cb0ef41Sopenharmony_ci    uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
4861cb0ef41Sopenharmony_ci    NodeVector values(ret_count);
4871cb0ef41Sopenharmony_ci    SsaEnv* internal_env = ssa_env_;
4881cb0ef41Sopenharmony_ci    if (emit_loop_exits()) {
4891cb0ef41Sopenharmony_ci      SsaEnv* exit_env = Split(decoder->zone(), ssa_env_);
4901cb0ef41Sopenharmony_ci      SetEnv(exit_env);
4911cb0ef41Sopenharmony_ci      auto stack_values = CopyStackValues(decoder, ret_count, drop_values);
4921cb0ef41Sopenharmony_ci      BuildNestedLoopExits(decoder, decoder->control_depth() - 1, false,
4931cb0ef41Sopenharmony_ci                           stack_values);
4941cb0ef41Sopenharmony_ci      GetNodes(values.begin(), base::VectorOf(stack_values));
4951cb0ef41Sopenharmony_ci    } else {
4961cb0ef41Sopenharmony_ci      Value* stack_base = ret_count == 0
4971cb0ef41Sopenharmony_ci                              ? nullptr
4981cb0ef41Sopenharmony_ci                              : decoder->stack_value(ret_count + drop_values);
4991cb0ef41Sopenharmony_ci      GetNodes(values.begin(), stack_base, ret_count);
5001cb0ef41Sopenharmony_ci    }
5011cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm && inlined_status_ == kRegularFunction) {
5021cb0ef41Sopenharmony_ci      builder_->TraceFunctionExit(base::VectorOf(values), decoder->position());
5031cb0ef41Sopenharmony_ci    }
5041cb0ef41Sopenharmony_ci    builder_->Return(base::VectorOf(values));
5051cb0ef41Sopenharmony_ci    SetEnv(internal_env);
5061cb0ef41Sopenharmony_ci  }
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci  void BrOrRet(FullDecoder* decoder, uint32_t depth, uint32_t drop_values) {
5091cb0ef41Sopenharmony_ci    if (depth == decoder->control_depth() - 1) {
5101cb0ef41Sopenharmony_ci      DoReturn(decoder, drop_values);
5111cb0ef41Sopenharmony_ci    } else {
5121cb0ef41Sopenharmony_ci      Control* target = decoder->control_at(depth);
5131cb0ef41Sopenharmony_ci      if (emit_loop_exits()) {
5141cb0ef41Sopenharmony_ci        SsaEnv* internal_env = ssa_env_;
5151cb0ef41Sopenharmony_ci        SsaEnv* exit_env = Split(decoder->zone(), ssa_env_);
5161cb0ef41Sopenharmony_ci        SetEnv(exit_env);
5171cb0ef41Sopenharmony_ci        uint32_t value_count = target->br_merge()->arity;
5181cb0ef41Sopenharmony_ci        auto stack_values = CopyStackValues(decoder, value_count, drop_values);
5191cb0ef41Sopenharmony_ci        BuildNestedLoopExits(decoder, depth, true, stack_values);
5201cb0ef41Sopenharmony_ci        MergeValuesInto(decoder, target, target->br_merge(),
5211cb0ef41Sopenharmony_ci                        stack_values.data());
5221cb0ef41Sopenharmony_ci        SetEnv(internal_env);
5231cb0ef41Sopenharmony_ci      } else {
5241cb0ef41Sopenharmony_ci        MergeValuesInto(decoder, target, target->br_merge(), drop_values);
5251cb0ef41Sopenharmony_ci      }
5261cb0ef41Sopenharmony_ci    }
5271cb0ef41Sopenharmony_ci  }
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_ci  void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
5301cb0ef41Sopenharmony_ci    SsaEnv* fenv = ssa_env_;
5311cb0ef41Sopenharmony_ci    SsaEnv* tenv = Split(decoder->zone(), fenv);
5321cb0ef41Sopenharmony_ci    fenv->SetNotMerged();
5331cb0ef41Sopenharmony_ci    WasmBranchHint hint = WasmBranchHint::kNoHint;
5341cb0ef41Sopenharmony_ci    if (branch_hints_) {
5351cb0ef41Sopenharmony_ci      hint = branch_hints_->GetHintFor(decoder->pc_relative_offset());
5361cb0ef41Sopenharmony_ci    }
5371cb0ef41Sopenharmony_ci    switch (hint) {
5381cb0ef41Sopenharmony_ci      case WasmBranchHint::kNoHint:
5391cb0ef41Sopenharmony_ci        builder_->BranchNoHint(cond.node, &tenv->control, &fenv->control);
5401cb0ef41Sopenharmony_ci        break;
5411cb0ef41Sopenharmony_ci      case WasmBranchHint::kUnlikely:
5421cb0ef41Sopenharmony_ci        builder_->BranchExpectFalse(cond.node, &tenv->control, &fenv->control);
5431cb0ef41Sopenharmony_ci        break;
5441cb0ef41Sopenharmony_ci      case WasmBranchHint::kLikely:
5451cb0ef41Sopenharmony_ci        builder_->BranchExpectTrue(cond.node, &tenv->control, &fenv->control);
5461cb0ef41Sopenharmony_ci        break;
5471cb0ef41Sopenharmony_ci    }
5481cb0ef41Sopenharmony_ci    builder_->SetControl(fenv->control);
5491cb0ef41Sopenharmony_ci    SetEnv(tenv);
5501cb0ef41Sopenharmony_ci    BrOrRet(decoder, depth, 1);
5511cb0ef41Sopenharmony_ci    SetEnv(fenv);
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
5551cb0ef41Sopenharmony_ci               const Value& key) {
5561cb0ef41Sopenharmony_ci    if (imm.table_count == 0) {
5571cb0ef41Sopenharmony_ci      // Only a default target. Do the equivalent of br.
5581cb0ef41Sopenharmony_ci      uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
5591cb0ef41Sopenharmony_ci      BrOrRet(decoder, target, 1);
5601cb0ef41Sopenharmony_ci      return;
5611cb0ef41Sopenharmony_ci    }
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci    SsaEnv* branch_env = ssa_env_;
5641cb0ef41Sopenharmony_ci    // Build branches to the various blocks based on the table.
5651cb0ef41Sopenharmony_ci    TFNode* sw = builder_->Switch(imm.table_count + 1, key.node);
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci    SsaEnv* copy = Steal(decoder->zone(), branch_env);
5681cb0ef41Sopenharmony_ci    SetEnv(copy);
5691cb0ef41Sopenharmony_ci    BranchTableIterator<validate> iterator(decoder, imm);
5701cb0ef41Sopenharmony_ci    while (iterator.has_next()) {
5711cb0ef41Sopenharmony_ci      uint32_t i = iterator.cur_index();
5721cb0ef41Sopenharmony_ci      uint32_t target = iterator.next();
5731cb0ef41Sopenharmony_ci      SetEnv(Split(decoder->zone(), copy));
5741cb0ef41Sopenharmony_ci      builder_->SetControl(i == imm.table_count ? builder_->IfDefault(sw)
5751cb0ef41Sopenharmony_ci                                                : builder_->IfValue(i, sw));
5761cb0ef41Sopenharmony_ci      BrOrRet(decoder, target, 1);
5771cb0ef41Sopenharmony_ci    }
5781cb0ef41Sopenharmony_ci    DCHECK(decoder->ok());
5791cb0ef41Sopenharmony_ci    SetEnv(branch_env);
5801cb0ef41Sopenharmony_ci  }
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  void Else(FullDecoder* decoder, Control* if_block) {
5831cb0ef41Sopenharmony_ci    if (if_block->reachable()) {
5841cb0ef41Sopenharmony_ci      // Merge the if branch into the end merge.
5851cb0ef41Sopenharmony_ci      MergeValuesInto(decoder, if_block, &if_block->end_merge);
5861cb0ef41Sopenharmony_ci    }
5871cb0ef41Sopenharmony_ci    SetEnv(if_block->false_env);
5881cb0ef41Sopenharmony_ci  }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  void LoadMem(FullDecoder* decoder, LoadType type,
5911cb0ef41Sopenharmony_ci               const MemoryAccessImmediate<validate>& imm, const Value& index,
5921cb0ef41Sopenharmony_ci               Value* result) {
5931cb0ef41Sopenharmony_ci    result->node =
5941cb0ef41Sopenharmony_ci        builder_->LoadMem(type.value_type(), type.mem_type(), index.node,
5951cb0ef41Sopenharmony_ci                          imm.offset, imm.alignment, decoder->position());
5961cb0ef41Sopenharmony_ci  }
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ci  void LoadTransform(FullDecoder* decoder, LoadType type,
5991cb0ef41Sopenharmony_ci                     LoadTransformationKind transform,
6001cb0ef41Sopenharmony_ci                     const MemoryAccessImmediate<validate>& imm,
6011cb0ef41Sopenharmony_ci                     const Value& index, Value* result) {
6021cb0ef41Sopenharmony_ci    result->node = builder_->LoadTransform(type.value_type(), type.mem_type(),
6031cb0ef41Sopenharmony_ci                                           transform, index.node, imm.offset,
6041cb0ef41Sopenharmony_ci                                           imm.alignment, decoder->position());
6051cb0ef41Sopenharmony_ci  }
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci  void LoadLane(FullDecoder* decoder, LoadType type, const Value& value,
6081cb0ef41Sopenharmony_ci                const Value& index, const MemoryAccessImmediate<validate>& imm,
6091cb0ef41Sopenharmony_ci                const uint8_t laneidx, Value* result) {
6101cb0ef41Sopenharmony_ci    result->node = builder_->LoadLane(
6111cb0ef41Sopenharmony_ci        type.value_type(), type.mem_type(), value.node, index.node, imm.offset,
6121cb0ef41Sopenharmony_ci        imm.alignment, laneidx, decoder->position());
6131cb0ef41Sopenharmony_ci  }
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci  void StoreMem(FullDecoder* decoder, StoreType type,
6161cb0ef41Sopenharmony_ci                const MemoryAccessImmediate<validate>& imm, const Value& index,
6171cb0ef41Sopenharmony_ci                const Value& value) {
6181cb0ef41Sopenharmony_ci    builder_->StoreMem(type.mem_rep(), index.node, imm.offset, imm.alignment,
6191cb0ef41Sopenharmony_ci                       value.node, decoder->position(), type.value_type());
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  void StoreLane(FullDecoder* decoder, StoreType type,
6231cb0ef41Sopenharmony_ci                 const MemoryAccessImmediate<validate>& imm, const Value& index,
6241cb0ef41Sopenharmony_ci                 const Value& value, const uint8_t laneidx) {
6251cb0ef41Sopenharmony_ci    builder_->StoreLane(type.mem_rep(), index.node, imm.offset, imm.alignment,
6261cb0ef41Sopenharmony_ci                        value.node, laneidx, decoder->position(),
6271cb0ef41Sopenharmony_ci                        type.value_type());
6281cb0ef41Sopenharmony_ci  }
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
6311cb0ef41Sopenharmony_ci    result->node = builder_->CurrentMemoryPages();
6321cb0ef41Sopenharmony_ci  }
6331cb0ef41Sopenharmony_ci
6341cb0ef41Sopenharmony_ci  void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
6351cb0ef41Sopenharmony_ci    result->node = builder_->MemoryGrow(value.node);
6361cb0ef41Sopenharmony_ci    // Always reload the instance cache after growing memory.
6371cb0ef41Sopenharmony_ci    LoadContextIntoSsa(ssa_env_);
6381cb0ef41Sopenharmony_ci  }
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci  void CallDirect(FullDecoder* decoder,
6411cb0ef41Sopenharmony_ci                  const CallFunctionImmediate<validate>& imm,
6421cb0ef41Sopenharmony_ci                  const Value args[], Value returns[]) {
6431cb0ef41Sopenharmony_ci    if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) {
6441cb0ef41Sopenharmony_ci      DCHECK_LT(feedback_instruction_index_, type_feedback_.size());
6451cb0ef41Sopenharmony_ci      feedback_instruction_index_++;
6461cb0ef41Sopenharmony_ci    }
6471cb0ef41Sopenharmony_ci    DoCall(decoder, CallInfo::CallDirect(imm.index), imm.sig, args, returns);
6481cb0ef41Sopenharmony_ci  }
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci  void ReturnCall(FullDecoder* decoder,
6511cb0ef41Sopenharmony_ci                  const CallFunctionImmediate<validate>& imm,
6521cb0ef41Sopenharmony_ci                  const Value args[]) {
6531cb0ef41Sopenharmony_ci    if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) {
6541cb0ef41Sopenharmony_ci      DCHECK_LT(feedback_instruction_index_, type_feedback_.size());
6551cb0ef41Sopenharmony_ci      feedback_instruction_index_++;
6561cb0ef41Sopenharmony_ci    }
6571cb0ef41Sopenharmony_ci    DoReturnCall(decoder, CallInfo::CallDirect(imm.index), imm.sig, args);
6581cb0ef41Sopenharmony_ci  }
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_ci  void CallIndirect(FullDecoder* decoder, const Value& index,
6611cb0ef41Sopenharmony_ci                    const CallIndirectImmediate<validate>& imm,
6621cb0ef41Sopenharmony_ci                    const Value args[], Value returns[]) {
6631cb0ef41Sopenharmony_ci    DoCall(
6641cb0ef41Sopenharmony_ci        decoder,
6651cb0ef41Sopenharmony_ci        CallInfo::CallIndirect(index, imm.table_imm.index, imm.sig_imm.index),
6661cb0ef41Sopenharmony_ci        imm.sig, args, returns);
6671cb0ef41Sopenharmony_ci  }
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ci  void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
6701cb0ef41Sopenharmony_ci                          const CallIndirectImmediate<validate>& imm,
6711cb0ef41Sopenharmony_ci                          const Value args[]) {
6721cb0ef41Sopenharmony_ci    DoReturnCall(
6731cb0ef41Sopenharmony_ci        decoder,
6741cb0ef41Sopenharmony_ci        CallInfo::CallIndirect(index, imm.table_imm.index, imm.sig_imm.index),
6751cb0ef41Sopenharmony_ci        imm.sig, args);
6761cb0ef41Sopenharmony_ci  }
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  void CallRef(FullDecoder* decoder, const Value& func_ref,
6791cb0ef41Sopenharmony_ci               const FunctionSig* sig, uint32_t sig_index, const Value args[],
6801cb0ef41Sopenharmony_ci               Value returns[]) {
6811cb0ef41Sopenharmony_ci    int maybe_feedback = -1;
6821cb0ef41Sopenharmony_ci    if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) {
6831cb0ef41Sopenharmony_ci      DCHECK_LT(feedback_instruction_index_, type_feedback_.size());
6841cb0ef41Sopenharmony_ci      maybe_feedback =
6851cb0ef41Sopenharmony_ci          type_feedback_[feedback_instruction_index_].function_index;
6861cb0ef41Sopenharmony_ci      feedback_instruction_index_++;
6871cb0ef41Sopenharmony_ci    }
6881cb0ef41Sopenharmony_ci    if (maybe_feedback == -1) {
6891cb0ef41Sopenharmony_ci      DoCall(decoder, CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)),
6901cb0ef41Sopenharmony_ci             sig, args, returns);
6911cb0ef41Sopenharmony_ci      return;
6921cb0ef41Sopenharmony_ci    }
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci    // Check for equality against a function at a specific index, and if
6951cb0ef41Sopenharmony_ci    // successful, just emit a direct call.
6961cb0ef41Sopenharmony_ci    DCHECK_GE(maybe_feedback, 0);
6971cb0ef41Sopenharmony_ci    const uint32_t expected_function_index = maybe_feedback;
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_speculative_inlining) {
7001cb0ef41Sopenharmony_ci      PrintF("[Function #%d call #%d: graph support for inlining target #%d]\n",
7011cb0ef41Sopenharmony_ci             func_index_, feedback_instruction_index_ - 1,
7021cb0ef41Sopenharmony_ci             expected_function_index);
7031cb0ef41Sopenharmony_ci    }
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci    TFNode* success_control;
7061cb0ef41Sopenharmony_ci    TFNode* failure_control;
7071cb0ef41Sopenharmony_ci    builder_->CompareToInternalFunctionAtIndex(
7081cb0ef41Sopenharmony_ci        func_ref.node, expected_function_index, &success_control,
7091cb0ef41Sopenharmony_ci        &failure_control);
7101cb0ef41Sopenharmony_ci    TFNode* initial_effect = effect();
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci    builder_->SetControl(success_control);
7131cb0ef41Sopenharmony_ci    ssa_env_->control = success_control;
7141cb0ef41Sopenharmony_ci    Value* returns_direct =
7151cb0ef41Sopenharmony_ci        decoder->zone()->NewArray<Value>(sig->return_count());
7161cb0ef41Sopenharmony_ci    DoCall(decoder, CallInfo::CallDirect(expected_function_index),
7171cb0ef41Sopenharmony_ci           decoder->module_->signature(sig_index), args, returns_direct);
7181cb0ef41Sopenharmony_ci    TFNode* control_direct = control();
7191cb0ef41Sopenharmony_ci    TFNode* effect_direct = effect();
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci    builder_->SetEffectControl(initial_effect, failure_control);
7221cb0ef41Sopenharmony_ci    ssa_env_->effect = initial_effect;
7231cb0ef41Sopenharmony_ci    ssa_env_->control = failure_control;
7241cb0ef41Sopenharmony_ci    Value* returns_ref = decoder->zone()->NewArray<Value>(sig->return_count());
7251cb0ef41Sopenharmony_ci    DoCall(decoder, CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)),
7261cb0ef41Sopenharmony_ci           sig, args, returns_ref);
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci    TFNode* control_ref = control();
7291cb0ef41Sopenharmony_ci    TFNode* effect_ref = effect();
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci    TFNode* control_args[] = {control_direct, control_ref};
7321cb0ef41Sopenharmony_ci    TFNode* control = builder_->Merge(2, control_args);
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci    TFNode* effect_args[] = {effect_direct, effect_ref, control};
7351cb0ef41Sopenharmony_ci    TFNode* effect = builder_->EffectPhi(2, effect_args);
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci    ssa_env_->control = control;
7381cb0ef41Sopenharmony_ci    ssa_env_->effect = effect;
7391cb0ef41Sopenharmony_ci    builder_->SetEffectControl(effect, control);
7401cb0ef41Sopenharmony_ci
7411cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < sig->return_count(); i++) {
7421cb0ef41Sopenharmony_ci      TFNode* phi_args[] = {returns_direct[i].node, returns_ref[i].node,
7431cb0ef41Sopenharmony_ci                            control};
7441cb0ef41Sopenharmony_ci      returns[i].node = builder_->Phi(sig->GetReturn(i), 2, phi_args);
7451cb0ef41Sopenharmony_ci    }
7461cb0ef41Sopenharmony_ci  }
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci  void ReturnCallRef(FullDecoder* decoder, const Value& func_ref,
7491cb0ef41Sopenharmony_ci                     const FunctionSig* sig, uint32_t sig_index,
7501cb0ef41Sopenharmony_ci                     const Value args[]) {
7511cb0ef41Sopenharmony_ci    int maybe_feedback = -1;
7521cb0ef41Sopenharmony_ci    if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) {
7531cb0ef41Sopenharmony_ci      DCHECK_LT(feedback_instruction_index_, type_feedback_.size());
7541cb0ef41Sopenharmony_ci      maybe_feedback =
7551cb0ef41Sopenharmony_ci          type_feedback_[feedback_instruction_index_].function_index;
7561cb0ef41Sopenharmony_ci      feedback_instruction_index_++;
7571cb0ef41Sopenharmony_ci    }
7581cb0ef41Sopenharmony_ci    if (maybe_feedback == -1) {
7591cb0ef41Sopenharmony_ci      DoReturnCall(decoder,
7601cb0ef41Sopenharmony_ci                   CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)),
7611cb0ef41Sopenharmony_ci                   sig, args);
7621cb0ef41Sopenharmony_ci      return;
7631cb0ef41Sopenharmony_ci    }
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci    // Check for equality against a function at a specific index, and if
7661cb0ef41Sopenharmony_ci    // successful, just emit a direct call.
7671cb0ef41Sopenharmony_ci    DCHECK_GE(maybe_feedback, 0);
7681cb0ef41Sopenharmony_ci    const uint32_t expected_function_index = maybe_feedback;
7691cb0ef41Sopenharmony_ci
7701cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_speculative_inlining) {
7711cb0ef41Sopenharmony_ci      PrintF("[Function #%d call #%d: graph support for inlining target #%d]\n",
7721cb0ef41Sopenharmony_ci             func_index_, feedback_instruction_index_ - 1,
7731cb0ef41Sopenharmony_ci             expected_function_index);
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci    TFNode* success_control;
7771cb0ef41Sopenharmony_ci    TFNode* failure_control;
7781cb0ef41Sopenharmony_ci    builder_->CompareToInternalFunctionAtIndex(
7791cb0ef41Sopenharmony_ci        func_ref.node, expected_function_index, &success_control,
7801cb0ef41Sopenharmony_ci        &failure_control);
7811cb0ef41Sopenharmony_ci    TFNode* initial_effect = effect();
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci    builder_->SetControl(success_control);
7841cb0ef41Sopenharmony_ci    ssa_env_->control = success_control;
7851cb0ef41Sopenharmony_ci    DoReturnCall(decoder, CallInfo::CallDirect(expected_function_index), sig,
7861cb0ef41Sopenharmony_ci                 args);
7871cb0ef41Sopenharmony_ci
7881cb0ef41Sopenharmony_ci    builder_->SetEffectControl(initial_effect, failure_control);
7891cb0ef41Sopenharmony_ci    ssa_env_->effect = initial_effect;
7901cb0ef41Sopenharmony_ci    ssa_env_->control = failure_control;
7911cb0ef41Sopenharmony_ci    DoReturnCall(decoder,
7921cb0ef41Sopenharmony_ci                 CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)), sig,
7931cb0ef41Sopenharmony_ci                 args);
7941cb0ef41Sopenharmony_ci  }
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  void BrOnNull(FullDecoder* decoder, const Value& ref_object, uint32_t depth,
7971cb0ef41Sopenharmony_ci                bool pass_null_along_branch, Value* result_on_fallthrough) {
7981cb0ef41Sopenharmony_ci    SsaEnv* false_env = ssa_env_;
7991cb0ef41Sopenharmony_ci    SsaEnv* true_env = Split(decoder->zone(), false_env);
8001cb0ef41Sopenharmony_ci    false_env->SetNotMerged();
8011cb0ef41Sopenharmony_ci    builder_->BrOnNull(ref_object.node, &true_env->control,
8021cb0ef41Sopenharmony_ci                       &false_env->control);
8031cb0ef41Sopenharmony_ci    builder_->SetControl(false_env->control);
8041cb0ef41Sopenharmony_ci    SetEnv(true_env);
8051cb0ef41Sopenharmony_ci    BrOrRet(decoder, depth, pass_null_along_branch ? 0 : 1);
8061cb0ef41Sopenharmony_ci    SetEnv(false_env);
8071cb0ef41Sopenharmony_ci    result_on_fallthrough->node = ref_object.node;
8081cb0ef41Sopenharmony_ci  }
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci  void BrOnNonNull(FullDecoder* decoder, const Value& ref_object,
8111cb0ef41Sopenharmony_ci                   uint32_t depth) {
8121cb0ef41Sopenharmony_ci    SsaEnv* false_env = ssa_env_;
8131cb0ef41Sopenharmony_ci    SsaEnv* true_env = Split(decoder->zone(), false_env);
8141cb0ef41Sopenharmony_ci    false_env->SetNotMerged();
8151cb0ef41Sopenharmony_ci    builder_->BrOnNull(ref_object.node, &false_env->control,
8161cb0ef41Sopenharmony_ci                       &true_env->control);
8171cb0ef41Sopenharmony_ci    builder_->SetControl(false_env->control);
8181cb0ef41Sopenharmony_ci    SetEnv(true_env);
8191cb0ef41Sopenharmony_ci    BrOrRet(decoder, depth, 0);
8201cb0ef41Sopenharmony_ci    SetEnv(false_env);
8211cb0ef41Sopenharmony_ci  }
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci  void SimdOp(FullDecoder* decoder, WasmOpcode opcode, base::Vector<Value> args,
8241cb0ef41Sopenharmony_ci              Value* result) {
8251cb0ef41Sopenharmony_ci    NodeVector inputs(args.size());
8261cb0ef41Sopenharmony_ci    GetNodes(inputs.begin(), args);
8271cb0ef41Sopenharmony_ci    TFNode* node = builder_->SimdOp(opcode, inputs.begin());
8281cb0ef41Sopenharmony_ci    if (result) result->node = node;
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_ci  void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
8321cb0ef41Sopenharmony_ci                  const SimdLaneImmediate<validate>& imm,
8331cb0ef41Sopenharmony_ci                  base::Vector<Value> inputs, Value* result) {
8341cb0ef41Sopenharmony_ci    NodeVector nodes(inputs.size());
8351cb0ef41Sopenharmony_ci    GetNodes(nodes.begin(), inputs);
8361cb0ef41Sopenharmony_ci    result->node = builder_->SimdLaneOp(opcode, imm.lane, nodes.begin());
8371cb0ef41Sopenharmony_ci  }
8381cb0ef41Sopenharmony_ci
8391cb0ef41Sopenharmony_ci  void Simd8x16ShuffleOp(FullDecoder* decoder,
8401cb0ef41Sopenharmony_ci                         const Simd128Immediate<validate>& imm,
8411cb0ef41Sopenharmony_ci                         const Value& input0, const Value& input1,
8421cb0ef41Sopenharmony_ci                         Value* result) {
8431cb0ef41Sopenharmony_ci    TFNode* input_nodes[] = {input0.node, input1.node};
8441cb0ef41Sopenharmony_ci    result->node = builder_->Simd8x16ShuffleOp(imm.value, input_nodes);
8451cb0ef41Sopenharmony_ci  }
8461cb0ef41Sopenharmony_ci
8471cb0ef41Sopenharmony_ci  void Throw(FullDecoder* decoder, const TagIndexImmediate<validate>& imm,
8481cb0ef41Sopenharmony_ci             const base::Vector<Value>& value_args) {
8491cb0ef41Sopenharmony_ci    int count = value_args.length();
8501cb0ef41Sopenharmony_ci    ZoneVector<TFNode*> args(count, decoder->zone());
8511cb0ef41Sopenharmony_ci    for (int i = 0; i < count; ++i) {
8521cb0ef41Sopenharmony_ci      args[i] = value_args[i].node;
8531cb0ef41Sopenharmony_ci    }
8541cb0ef41Sopenharmony_ci    CheckForException(decoder,
8551cb0ef41Sopenharmony_ci                      builder_->Throw(imm.index, imm.tag, base::VectorOf(args),
8561cb0ef41Sopenharmony_ci                                      decoder->position()));
8571cb0ef41Sopenharmony_ci    builder_->TerminateThrow(effect(), control());
8581cb0ef41Sopenharmony_ci  }
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  void Rethrow(FullDecoder* decoder, Control* block) {
8611cb0ef41Sopenharmony_ci    DCHECK(block->is_try_catchall() || block->is_try_catch());
8621cb0ef41Sopenharmony_ci    TFNode* exception = block->try_info->exception;
8631cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(exception);
8641cb0ef41Sopenharmony_ci    CheckForException(decoder, builder_->Rethrow(exception));
8651cb0ef41Sopenharmony_ci    builder_->TerminateThrow(effect(), control());
8661cb0ef41Sopenharmony_ci  }
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  void CatchException(FullDecoder* decoder,
8691cb0ef41Sopenharmony_ci                      const TagIndexImmediate<validate>& imm, Control* block,
8701cb0ef41Sopenharmony_ci                      base::Vector<Value> values) {
8711cb0ef41Sopenharmony_ci    DCHECK(block->is_try_catch());
8721cb0ef41Sopenharmony_ci    // The catch block is unreachable if no possible throws in the try block
8731cb0ef41Sopenharmony_ci    // exist. We only build a landing pad if some node in the try block can
8741cb0ef41Sopenharmony_ci    // (possibly) throw. Otherwise the catch environments remain empty.
8751cb0ef41Sopenharmony_ci    if (!block->try_info->might_throw()) {
8761cb0ef41Sopenharmony_ci      block->reachability = kSpecOnlyReachable;
8771cb0ef41Sopenharmony_ci      return;
8781cb0ef41Sopenharmony_ci    }
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ci    TFNode* exception = block->try_info->exception;
8811cb0ef41Sopenharmony_ci    SetEnv(block->try_info->catch_env);
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_ci    TFNode* if_catch = nullptr;
8841cb0ef41Sopenharmony_ci    TFNode* if_no_catch = nullptr;
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci    // Get the exception tag and see if it matches the expected one.
8871cb0ef41Sopenharmony_ci    TFNode* caught_tag = builder_->GetExceptionTag(exception);
8881cb0ef41Sopenharmony_ci    TFNode* exception_tag = builder_->LoadTagFromTable(imm.index);
8891cb0ef41Sopenharmony_ci    TFNode* compare = builder_->ExceptionTagEqual(caught_tag, exception_tag);
8901cb0ef41Sopenharmony_ci    builder_->BranchNoHint(compare, &if_catch, &if_no_catch);
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci    // If the tags don't match we continue with the next tag by setting the
8931cb0ef41Sopenharmony_ci    // false environment as the new {TryInfo::catch_env} here.
8941cb0ef41Sopenharmony_ci    SsaEnv* if_no_catch_env = Split(decoder->zone(), ssa_env_);
8951cb0ef41Sopenharmony_ci    if_no_catch_env->control = if_no_catch;
8961cb0ef41Sopenharmony_ci    SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_);
8971cb0ef41Sopenharmony_ci    if_catch_env->control = if_catch;
8981cb0ef41Sopenharmony_ci    block->try_info->catch_env = if_no_catch_env;
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ci    // If the tags match we extract the values from the exception object and
9011cb0ef41Sopenharmony_ci    // push them onto the operand stack using the passed {values} vector.
9021cb0ef41Sopenharmony_ci    SetEnv(if_catch_env);
9031cb0ef41Sopenharmony_ci    NodeVector caught_values(values.size());
9041cb0ef41Sopenharmony_ci    base::Vector<TFNode*> caught_vector = base::VectorOf(caught_values);
9051cb0ef41Sopenharmony_ci    builder_->GetExceptionValues(exception, imm.tag, caught_vector);
9061cb0ef41Sopenharmony_ci    for (size_t i = 0, e = values.size(); i < e; ++i) {
9071cb0ef41Sopenharmony_ci      values[i].node = caught_values[i];
9081cb0ef41Sopenharmony_ci    }
9091cb0ef41Sopenharmony_ci  }
9101cb0ef41Sopenharmony_ci
9111cb0ef41Sopenharmony_ci  void Delegate(FullDecoder* decoder, uint32_t depth, Control* block) {
9121cb0ef41Sopenharmony_ci    DCHECK_EQ(decoder->control_at(0), block);
9131cb0ef41Sopenharmony_ci    DCHECK(block->is_incomplete_try());
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci    if (block->try_info->might_throw()) {
9161cb0ef41Sopenharmony_ci      // Merge the current env into the target handler's env.
9171cb0ef41Sopenharmony_ci      SetEnv(block->try_info->catch_env);
9181cb0ef41Sopenharmony_ci      if (depth == decoder->control_depth() - 1) {
9191cb0ef41Sopenharmony_ci        // We just throw to the caller here, so no need to generate IfSuccess
9201cb0ef41Sopenharmony_ci        // and IfFailure nodes.
9211cb0ef41Sopenharmony_ci        builder_->Rethrow(block->try_info->exception);
9221cb0ef41Sopenharmony_ci        builder_->TerminateThrow(effect(), control());
9231cb0ef41Sopenharmony_ci        return;
9241cb0ef41Sopenharmony_ci      }
9251cb0ef41Sopenharmony_ci      DCHECK(decoder->control_at(depth)->is_try());
9261cb0ef41Sopenharmony_ci      TryInfo* target_try = decoder->control_at(depth)->try_info;
9271cb0ef41Sopenharmony_ci      if (emit_loop_exits()) {
9281cb0ef41Sopenharmony_ci        ValueVector stack_values;
9291cb0ef41Sopenharmony_ci        BuildNestedLoopExits(decoder, depth, true, stack_values,
9301cb0ef41Sopenharmony_ci                             &block->try_info->exception);
9311cb0ef41Sopenharmony_ci      }
9321cb0ef41Sopenharmony_ci      Goto(decoder, target_try->catch_env);
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci      // Create or merge the exception.
9351cb0ef41Sopenharmony_ci      if (target_try->catch_env->state == SsaEnv::kReached) {
9361cb0ef41Sopenharmony_ci        target_try->exception = block->try_info->exception;
9371cb0ef41Sopenharmony_ci      } else {
9381cb0ef41Sopenharmony_ci        DCHECK_EQ(target_try->catch_env->state, SsaEnv::kMerged);
9391cb0ef41Sopenharmony_ci        target_try->exception = builder_->CreateOrMergeIntoPhi(
9401cb0ef41Sopenharmony_ci            MachineRepresentation::kTagged, target_try->catch_env->control,
9411cb0ef41Sopenharmony_ci            target_try->exception, block->try_info->exception);
9421cb0ef41Sopenharmony_ci      }
9431cb0ef41Sopenharmony_ci    }
9441cb0ef41Sopenharmony_ci  }
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ci  void CatchAll(FullDecoder* decoder, Control* block) {
9471cb0ef41Sopenharmony_ci    DCHECK(block->is_try_catchall() || block->is_try_catch());
9481cb0ef41Sopenharmony_ci    DCHECK_EQ(decoder->control_at(0), block);
9491cb0ef41Sopenharmony_ci
9501cb0ef41Sopenharmony_ci    // The catch block is unreachable if no possible throws in the try block
9511cb0ef41Sopenharmony_ci    // exist. We only build a landing pad if some node in the try block can
9521cb0ef41Sopenharmony_ci    // (possibly) throw. Otherwise the catch environments remain empty.
9531cb0ef41Sopenharmony_ci    if (!block->try_info->might_throw()) {
9541cb0ef41Sopenharmony_ci      decoder->SetSucceedingCodeDynamicallyUnreachable();
9551cb0ef41Sopenharmony_ci      return;
9561cb0ef41Sopenharmony_ci    }
9571cb0ef41Sopenharmony_ci
9581cb0ef41Sopenharmony_ci    SetEnv(block->try_info->catch_env);
9591cb0ef41Sopenharmony_ci  }
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ci  void AtomicOp(FullDecoder* decoder, WasmOpcode opcode,
9621cb0ef41Sopenharmony_ci                base::Vector<Value> args,
9631cb0ef41Sopenharmony_ci                const MemoryAccessImmediate<validate>& imm, Value* result) {
9641cb0ef41Sopenharmony_ci    NodeVector inputs(args.size());
9651cb0ef41Sopenharmony_ci    GetNodes(inputs.begin(), args);
9661cb0ef41Sopenharmony_ci    TFNode* node = builder_->AtomicOp(opcode, inputs.begin(), imm.alignment,
9671cb0ef41Sopenharmony_ci                                      imm.offset, decoder->position());
9681cb0ef41Sopenharmony_ci    if (result) result->node = node;
9691cb0ef41Sopenharmony_ci  }
9701cb0ef41Sopenharmony_ci
9711cb0ef41Sopenharmony_ci  void AtomicFence(FullDecoder* decoder) { builder_->AtomicFence(); }
9721cb0ef41Sopenharmony_ci
9731cb0ef41Sopenharmony_ci  void MemoryInit(FullDecoder* decoder,
9741cb0ef41Sopenharmony_ci                  const MemoryInitImmediate<validate>& imm, const Value& dst,
9751cb0ef41Sopenharmony_ci                  const Value& src, const Value& size) {
9761cb0ef41Sopenharmony_ci    builder_->MemoryInit(imm.data_segment.index, dst.node, src.node, size.node,
9771cb0ef41Sopenharmony_ci                         decoder->position());
9781cb0ef41Sopenharmony_ci  }
9791cb0ef41Sopenharmony_ci
9801cb0ef41Sopenharmony_ci  void DataDrop(FullDecoder* decoder, const IndexImmediate<validate>& imm) {
9811cb0ef41Sopenharmony_ci    builder_->DataDrop(imm.index, decoder->position());
9821cb0ef41Sopenharmony_ci  }
9831cb0ef41Sopenharmony_ci
9841cb0ef41Sopenharmony_ci  void MemoryCopy(FullDecoder* decoder,
9851cb0ef41Sopenharmony_ci                  const MemoryCopyImmediate<validate>& imm, const Value& dst,
9861cb0ef41Sopenharmony_ci                  const Value& src, const Value& size) {
9871cb0ef41Sopenharmony_ci    builder_->MemoryCopy(dst.node, src.node, size.node, decoder->position());
9881cb0ef41Sopenharmony_ci  }
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_ci  void MemoryFill(FullDecoder* decoder,
9911cb0ef41Sopenharmony_ci                  const MemoryIndexImmediate<validate>& imm, const Value& dst,
9921cb0ef41Sopenharmony_ci                  const Value& value, const Value& size) {
9931cb0ef41Sopenharmony_ci    builder_->MemoryFill(dst.node, value.node, size.node, decoder->position());
9941cb0ef41Sopenharmony_ci  }
9951cb0ef41Sopenharmony_ci
9961cb0ef41Sopenharmony_ci  void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
9971cb0ef41Sopenharmony_ci                 base::Vector<Value> args) {
9981cb0ef41Sopenharmony_ci    builder_->TableInit(imm.table.index, imm.element_segment.index,
9991cb0ef41Sopenharmony_ci                        args[0].node, args[1].node, args[2].node,
10001cb0ef41Sopenharmony_ci                        decoder->position());
10011cb0ef41Sopenharmony_ci  }
10021cb0ef41Sopenharmony_ci
10031cb0ef41Sopenharmony_ci  void ElemDrop(FullDecoder* decoder, const IndexImmediate<validate>& imm) {
10041cb0ef41Sopenharmony_ci    builder_->ElemDrop(imm.index, decoder->position());
10051cb0ef41Sopenharmony_ci  }
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci  void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
10081cb0ef41Sopenharmony_ci                 base::Vector<Value> args) {
10091cb0ef41Sopenharmony_ci    builder_->TableCopy(imm.table_dst.index, imm.table_src.index, args[0].node,
10101cb0ef41Sopenharmony_ci                        args[1].node, args[2].node, decoder->position());
10111cb0ef41Sopenharmony_ci  }
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci  void TableGrow(FullDecoder* decoder, const IndexImmediate<validate>& imm,
10141cb0ef41Sopenharmony_ci                 const Value& value, const Value& delta, Value* result) {
10151cb0ef41Sopenharmony_ci    result->node = builder_->TableGrow(imm.index, value.node, delta.node);
10161cb0ef41Sopenharmony_ci  }
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_ci  void TableSize(FullDecoder* decoder, const IndexImmediate<validate>& imm,
10191cb0ef41Sopenharmony_ci                 Value* result) {
10201cb0ef41Sopenharmony_ci    result->node = builder_->TableSize(imm.index);
10211cb0ef41Sopenharmony_ci  }
10221cb0ef41Sopenharmony_ci
10231cb0ef41Sopenharmony_ci  void TableFill(FullDecoder* decoder, const IndexImmediate<validate>& imm,
10241cb0ef41Sopenharmony_ci                 const Value& start, const Value& value, const Value& count) {
10251cb0ef41Sopenharmony_ci    builder_->TableFill(imm.index, start.node, value.node, count.node);
10261cb0ef41Sopenharmony_ci  }
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci  void StructNewWithRtt(FullDecoder* decoder,
10291cb0ef41Sopenharmony_ci                        const StructIndexImmediate<validate>& imm,
10301cb0ef41Sopenharmony_ci                        const Value& rtt, const Value args[], Value* result) {
10311cb0ef41Sopenharmony_ci    uint32_t field_count = imm.struct_type->field_count();
10321cb0ef41Sopenharmony_ci    NodeVector arg_nodes(field_count);
10331cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < field_count; i++) {
10341cb0ef41Sopenharmony_ci      arg_nodes[i] = args[i].node;
10351cb0ef41Sopenharmony_ci    }
10361cb0ef41Sopenharmony_ci    result->node = builder_->StructNewWithRtt(
10371cb0ef41Sopenharmony_ci        imm.index, imm.struct_type, rtt.node, base::VectorOf(arg_nodes));
10381cb0ef41Sopenharmony_ci  }
10391cb0ef41Sopenharmony_ci  void StructNewDefault(FullDecoder* decoder,
10401cb0ef41Sopenharmony_ci                        const StructIndexImmediate<validate>& imm,
10411cb0ef41Sopenharmony_ci                        const Value& rtt, Value* result) {
10421cb0ef41Sopenharmony_ci    uint32_t field_count = imm.struct_type->field_count();
10431cb0ef41Sopenharmony_ci    NodeVector arg_nodes(field_count);
10441cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < field_count; i++) {
10451cb0ef41Sopenharmony_ci      arg_nodes[i] = DefaultValue(imm.struct_type->field(i));
10461cb0ef41Sopenharmony_ci    }
10471cb0ef41Sopenharmony_ci    result->node = builder_->StructNewWithRtt(
10481cb0ef41Sopenharmony_ci        imm.index, imm.struct_type, rtt.node, base::VectorOf(arg_nodes));
10491cb0ef41Sopenharmony_ci  }
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  void StructGet(FullDecoder* decoder, const Value& struct_object,
10521cb0ef41Sopenharmony_ci                 const FieldImmediate<validate>& field, bool is_signed,
10531cb0ef41Sopenharmony_ci                 Value* result) {
10541cb0ef41Sopenharmony_ci    result->node = builder_->StructGet(
10551cb0ef41Sopenharmony_ci        struct_object.node, field.struct_imm.struct_type, field.field_imm.index,
10561cb0ef41Sopenharmony_ci        NullCheckFor(struct_object.type), is_signed, decoder->position());
10571cb0ef41Sopenharmony_ci  }
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  void StructSet(FullDecoder* decoder, const Value& struct_object,
10601cb0ef41Sopenharmony_ci                 const FieldImmediate<validate>& field,
10611cb0ef41Sopenharmony_ci                 const Value& field_value) {
10621cb0ef41Sopenharmony_ci    builder_->StructSet(struct_object.node, field.struct_imm.struct_type,
10631cb0ef41Sopenharmony_ci                        field.field_imm.index, field_value.node,
10641cb0ef41Sopenharmony_ci                        NullCheckFor(struct_object.type), decoder->position());
10651cb0ef41Sopenharmony_ci  }
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci  void ArrayNewWithRtt(FullDecoder* decoder,
10681cb0ef41Sopenharmony_ci                       const ArrayIndexImmediate<validate>& imm,
10691cb0ef41Sopenharmony_ci                       const Value& length, const Value& initial_value,
10701cb0ef41Sopenharmony_ci                       const Value& rtt, Value* result) {
10711cb0ef41Sopenharmony_ci    result->node = builder_->ArrayNewWithRtt(imm.index, imm.array_type,
10721cb0ef41Sopenharmony_ci                                             length.node, initial_value.node,
10731cb0ef41Sopenharmony_ci                                             rtt.node, decoder->position());
10741cb0ef41Sopenharmony_ci    // array.new_with_rtt introduces a loop. Therefore, we have to mark the
10751cb0ef41Sopenharmony_ci    // immediately nesting loop (if any) as non-innermost.
10761cb0ef41Sopenharmony_ci    if (!loop_infos_.empty()) loop_infos_.back().can_be_innermost = false;
10771cb0ef41Sopenharmony_ci  }
10781cb0ef41Sopenharmony_ci
10791cb0ef41Sopenharmony_ci  void ArrayNewDefault(FullDecoder* decoder,
10801cb0ef41Sopenharmony_ci                       const ArrayIndexImmediate<validate>& imm,
10811cb0ef41Sopenharmony_ci                       const Value& length, const Value& rtt, Value* result) {
10821cb0ef41Sopenharmony_ci    // This will cause the default value to be chosen automatically based
10831cb0ef41Sopenharmony_ci    // on the element type.
10841cb0ef41Sopenharmony_ci    TFNode* initial_value = nullptr;
10851cb0ef41Sopenharmony_ci    result->node =
10861cb0ef41Sopenharmony_ci        builder_->ArrayNewWithRtt(imm.index, imm.array_type, length.node,
10871cb0ef41Sopenharmony_ci                                  initial_value, rtt.node, decoder->position());
10881cb0ef41Sopenharmony_ci  }
10891cb0ef41Sopenharmony_ci
10901cb0ef41Sopenharmony_ci  void ArrayGet(FullDecoder* decoder, const Value& array_obj,
10911cb0ef41Sopenharmony_ci                const ArrayIndexImmediate<validate>& imm, const Value& index,
10921cb0ef41Sopenharmony_ci                bool is_signed, Value* result) {
10931cb0ef41Sopenharmony_ci    result->node = builder_->ArrayGet(array_obj.node, imm.array_type,
10941cb0ef41Sopenharmony_ci                                      index.node, NullCheckFor(array_obj.type),
10951cb0ef41Sopenharmony_ci                                      is_signed, decoder->position());
10961cb0ef41Sopenharmony_ci  }
10971cb0ef41Sopenharmony_ci
10981cb0ef41Sopenharmony_ci  void ArraySet(FullDecoder* decoder, const Value& array_obj,
10991cb0ef41Sopenharmony_ci                const ArrayIndexImmediate<validate>& imm, const Value& index,
11001cb0ef41Sopenharmony_ci                const Value& value) {
11011cb0ef41Sopenharmony_ci    builder_->ArraySet(array_obj.node, imm.array_type, index.node, value.node,
11021cb0ef41Sopenharmony_ci                       NullCheckFor(array_obj.type), decoder->position());
11031cb0ef41Sopenharmony_ci  }
11041cb0ef41Sopenharmony_ci
11051cb0ef41Sopenharmony_ci  void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) {
11061cb0ef41Sopenharmony_ci    result->node = builder_->ArrayLen(
11071cb0ef41Sopenharmony_ci        array_obj.node, NullCheckFor(array_obj.type), decoder->position());
11081cb0ef41Sopenharmony_ci  }
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  void ArrayCopy(FullDecoder* decoder, const Value& dst, const Value& dst_index,
11111cb0ef41Sopenharmony_ci                 const Value& src, const Value& src_index,
11121cb0ef41Sopenharmony_ci                 const Value& length) {
11131cb0ef41Sopenharmony_ci    builder_->ArrayCopy(dst.node, dst_index.node, NullCheckFor(dst.type),
11141cb0ef41Sopenharmony_ci                        src.node, src_index.node, NullCheckFor(src.type),
11151cb0ef41Sopenharmony_ci                        length.node, decoder->position());
11161cb0ef41Sopenharmony_ci  }
11171cb0ef41Sopenharmony_ci
11181cb0ef41Sopenharmony_ci  void ArrayInit(FullDecoder* decoder, const ArrayIndexImmediate<validate>& imm,
11191cb0ef41Sopenharmony_ci                 const base::Vector<Value>& elements, const Value& rtt,
11201cb0ef41Sopenharmony_ci                 Value* result) {
11211cb0ef41Sopenharmony_ci    NodeVector element_nodes(elements.size());
11221cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < elements.size(); i++) {
11231cb0ef41Sopenharmony_ci      element_nodes[i] = elements[i].node;
11241cb0ef41Sopenharmony_ci    }
11251cb0ef41Sopenharmony_ci    result->node =
11261cb0ef41Sopenharmony_ci        builder_->ArrayInit(imm.array_type, rtt.node, VectorOf(element_nodes));
11271cb0ef41Sopenharmony_ci  }
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_ci  void ArrayInitFromData(FullDecoder* decoder,
11301cb0ef41Sopenharmony_ci                         const ArrayIndexImmediate<validate>& array_imm,
11311cb0ef41Sopenharmony_ci                         const IndexImmediate<validate>& data_segment,
11321cb0ef41Sopenharmony_ci                         const Value& offset, const Value& length,
11331cb0ef41Sopenharmony_ci                         const Value& rtt, Value* result) {
11341cb0ef41Sopenharmony_ci    result->node = builder_->ArrayInitFromData(
11351cb0ef41Sopenharmony_ci        array_imm.array_type, data_segment.index, offset.node, length.node,
11361cb0ef41Sopenharmony_ci        rtt.node, decoder->position());
11371cb0ef41Sopenharmony_ci  }
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci  void I31New(FullDecoder* decoder, const Value& input, Value* result) {
11401cb0ef41Sopenharmony_ci    result->node = builder_->I31New(input.node);
11411cb0ef41Sopenharmony_ci  }
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci  void I31GetS(FullDecoder* decoder, const Value& input, Value* result) {
11441cb0ef41Sopenharmony_ci    result->node = builder_->I31GetS(input.node);
11451cb0ef41Sopenharmony_ci  }
11461cb0ef41Sopenharmony_ci
11471cb0ef41Sopenharmony_ci  void I31GetU(FullDecoder* decoder, const Value& input, Value* result) {
11481cb0ef41Sopenharmony_ci    result->node = builder_->I31GetU(input.node);
11491cb0ef41Sopenharmony_ci  }
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  void RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result) {
11521cb0ef41Sopenharmony_ci    result->node = builder_->RttCanon(type_index);
11531cb0ef41Sopenharmony_ci  }
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci  using StaticKnowledge = compiler::WasmGraphBuilder::ObjectReferenceKnowledge;
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci  StaticKnowledge ComputeStaticKnowledge(ValueType object_type,
11581cb0ef41Sopenharmony_ci                                         ValueType rtt_type,
11591cb0ef41Sopenharmony_ci                                         const WasmModule* module) {
11601cb0ef41Sopenharmony_ci    StaticKnowledge result;
11611cb0ef41Sopenharmony_ci    result.object_can_be_null = object_type.is_nullable();
11621cb0ef41Sopenharmony_ci    DCHECK(object_type.is_object_reference());  // Checked by validation.
11631cb0ef41Sopenharmony_ci    // In the bottom case, the result is irrelevant.
11641cb0ef41Sopenharmony_ci    result.rtt_depth = rtt_type.is_bottom()
11651cb0ef41Sopenharmony_ci                           ? 0 /* unused */
11661cb0ef41Sopenharmony_ci                           : static_cast<uint8_t>(GetSubtypingDepth(
11671cb0ef41Sopenharmony_ci                                 module, rtt_type.ref_index()));
11681cb0ef41Sopenharmony_ci    return result;
11691cb0ef41Sopenharmony_ci  }
11701cb0ef41Sopenharmony_ci
11711cb0ef41Sopenharmony_ci  void RefTest(FullDecoder* decoder, const Value& object, const Value& rtt,
11721cb0ef41Sopenharmony_ci               Value* result) {
11731cb0ef41Sopenharmony_ci    StaticKnowledge config =
11741cb0ef41Sopenharmony_ci        ComputeStaticKnowledge(object.type, rtt.type, decoder->module_);
11751cb0ef41Sopenharmony_ci    result->node = builder_->RefTest(object.node, rtt.node, config);
11761cb0ef41Sopenharmony_ci  }
11771cb0ef41Sopenharmony_ci
11781cb0ef41Sopenharmony_ci  void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt,
11791cb0ef41Sopenharmony_ci               Value* result) {
11801cb0ef41Sopenharmony_ci    StaticKnowledge config =
11811cb0ef41Sopenharmony_ci        ComputeStaticKnowledge(object.type, rtt.type, decoder->module_);
11821cb0ef41Sopenharmony_ci    result->node =
11831cb0ef41Sopenharmony_ci        builder_->RefCast(object.node, rtt.node, config, decoder->position());
11841cb0ef41Sopenharmony_ci  }
11851cb0ef41Sopenharmony_ci
11861cb0ef41Sopenharmony_ci  template <void (compiler::WasmGraphBuilder::*branch_function)(
11871cb0ef41Sopenharmony_ci      TFNode*, TFNode*, StaticKnowledge, TFNode**, TFNode**, TFNode**,
11881cb0ef41Sopenharmony_ci      TFNode**)>
11891cb0ef41Sopenharmony_ci  void BrOnCastAbs(FullDecoder* decoder, const Value& object, const Value& rtt,
11901cb0ef41Sopenharmony_ci                   Value* forwarding_value, uint32_t br_depth,
11911cb0ef41Sopenharmony_ci                   bool branch_on_match) {
11921cb0ef41Sopenharmony_ci    StaticKnowledge config =
11931cb0ef41Sopenharmony_ci        ComputeStaticKnowledge(object.type, rtt.type, decoder->module_);
11941cb0ef41Sopenharmony_ci    SsaEnv* branch_env = Split(decoder->zone(), ssa_env_);
11951cb0ef41Sopenharmony_ci    SsaEnv* no_branch_env = Steal(decoder->zone(), ssa_env_);
11961cb0ef41Sopenharmony_ci    no_branch_env->SetNotMerged();
11971cb0ef41Sopenharmony_ci    SsaEnv* match_env = branch_on_match ? branch_env : no_branch_env;
11981cb0ef41Sopenharmony_ci    SsaEnv* no_match_env = branch_on_match ? no_branch_env : branch_env;
11991cb0ef41Sopenharmony_ci    (builder_->*branch_function)(object.node, rtt.node, config,
12001cb0ef41Sopenharmony_ci                                 &match_env->control, &match_env->effect,
12011cb0ef41Sopenharmony_ci                                 &no_match_env->control, &no_match_env->effect);
12021cb0ef41Sopenharmony_ci    builder_->SetControl(no_branch_env->control);
12031cb0ef41Sopenharmony_ci    SetEnv(branch_env);
12041cb0ef41Sopenharmony_ci    forwarding_value->node = object.node;
12051cb0ef41Sopenharmony_ci    // Currently, br_on_* instructions modify the value stack before calling
12061cb0ef41Sopenharmony_ci    // the interface function, so we don't need to drop any values here.
12071cb0ef41Sopenharmony_ci    BrOrRet(decoder, br_depth, 0);
12081cb0ef41Sopenharmony_ci    SetEnv(no_branch_env);
12091cb0ef41Sopenharmony_ci  }
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_ci  void BrOnCast(FullDecoder* decoder, const Value& object, const Value& rtt,
12121cb0ef41Sopenharmony_ci                Value* value_on_branch, uint32_t br_depth) {
12131cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnCast>(
12141cb0ef41Sopenharmony_ci        decoder, object, rtt, value_on_branch, br_depth, true);
12151cb0ef41Sopenharmony_ci  }
12161cb0ef41Sopenharmony_ci
12171cb0ef41Sopenharmony_ci  void BrOnCastFail(FullDecoder* decoder, const Value& object, const Value& rtt,
12181cb0ef41Sopenharmony_ci                    Value* value_on_fallthrough, uint32_t br_depth) {
12191cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnCast>(
12201cb0ef41Sopenharmony_ci        decoder, object, rtt, value_on_fallthrough, br_depth, false);
12211cb0ef41Sopenharmony_ci  }
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  void RefIsData(FullDecoder* decoder, const Value& object, Value* result) {
12241cb0ef41Sopenharmony_ci    result->node = builder_->RefIsData(object.node, object.type.is_nullable());
12251cb0ef41Sopenharmony_ci  }
12261cb0ef41Sopenharmony_ci
12271cb0ef41Sopenharmony_ci  void RefAsData(FullDecoder* decoder, const Value& object, Value* result) {
12281cb0ef41Sopenharmony_ci    result->node = builder_->RefAsData(object.node, object.type.is_nullable(),
12291cb0ef41Sopenharmony_ci                                       decoder->position());
12301cb0ef41Sopenharmony_ci  }
12311cb0ef41Sopenharmony_ci
12321cb0ef41Sopenharmony_ci  void BrOnData(FullDecoder* decoder, const Value& object,
12331cb0ef41Sopenharmony_ci                Value* value_on_branch, uint32_t br_depth) {
12341cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>(
12351cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
12361cb0ef41Sopenharmony_ci        true);
12371cb0ef41Sopenharmony_ci  }
12381cb0ef41Sopenharmony_ci
12391cb0ef41Sopenharmony_ci  void BrOnNonData(FullDecoder* decoder, const Value& object,
12401cb0ef41Sopenharmony_ci                   Value* value_on_fallthrough, uint32_t br_depth) {
12411cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>(
12421cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
12431cb0ef41Sopenharmony_ci        br_depth, false);
12441cb0ef41Sopenharmony_ci  }
12451cb0ef41Sopenharmony_ci
12461cb0ef41Sopenharmony_ci  void RefIsFunc(FullDecoder* decoder, const Value& object, Value* result) {
12471cb0ef41Sopenharmony_ci    result->node = builder_->RefIsFunc(object.node, object.type.is_nullable());
12481cb0ef41Sopenharmony_ci  }
12491cb0ef41Sopenharmony_ci
12501cb0ef41Sopenharmony_ci  void RefAsFunc(FullDecoder* decoder, const Value& object, Value* result) {
12511cb0ef41Sopenharmony_ci    result->node = builder_->RefAsFunc(object.node, object.type.is_nullable(),
12521cb0ef41Sopenharmony_ci                                       decoder->position());
12531cb0ef41Sopenharmony_ci  }
12541cb0ef41Sopenharmony_ci
12551cb0ef41Sopenharmony_ci  void BrOnFunc(FullDecoder* decoder, const Value& object,
12561cb0ef41Sopenharmony_ci                Value* value_on_branch, uint32_t br_depth) {
12571cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnFunc>(
12581cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
12591cb0ef41Sopenharmony_ci        true);
12601cb0ef41Sopenharmony_ci  }
12611cb0ef41Sopenharmony_ci
12621cb0ef41Sopenharmony_ci  void BrOnNonFunc(FullDecoder* decoder, const Value& object,
12631cb0ef41Sopenharmony_ci                   Value* value_on_fallthrough, uint32_t br_depth) {
12641cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnFunc>(
12651cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
12661cb0ef41Sopenharmony_ci        br_depth, false);
12671cb0ef41Sopenharmony_ci  }
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci  void RefIsArray(FullDecoder* decoder, const Value& object, Value* result) {
12701cb0ef41Sopenharmony_ci    result->node = builder_->RefIsArray(object.node, object.type.is_nullable());
12711cb0ef41Sopenharmony_ci  }
12721cb0ef41Sopenharmony_ci
12731cb0ef41Sopenharmony_ci  void RefAsArray(FullDecoder* decoder, const Value& object, Value* result) {
12741cb0ef41Sopenharmony_ci    result->node = builder_->RefAsArray(object.node, object.type.is_nullable(),
12751cb0ef41Sopenharmony_ci                                        decoder->position());
12761cb0ef41Sopenharmony_ci  }
12771cb0ef41Sopenharmony_ci
12781cb0ef41Sopenharmony_ci  void BrOnArray(FullDecoder* decoder, const Value& object,
12791cb0ef41Sopenharmony_ci                 Value* value_on_branch, uint32_t br_depth) {
12801cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>(
12811cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
12821cb0ef41Sopenharmony_ci        true);
12831cb0ef41Sopenharmony_ci  }
12841cb0ef41Sopenharmony_ci
12851cb0ef41Sopenharmony_ci  void BrOnNonArray(FullDecoder* decoder, const Value& object,
12861cb0ef41Sopenharmony_ci                    Value* value_on_fallthrough, uint32_t br_depth) {
12871cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>(
12881cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
12891cb0ef41Sopenharmony_ci        br_depth, false);
12901cb0ef41Sopenharmony_ci  }
12911cb0ef41Sopenharmony_ci
12921cb0ef41Sopenharmony_ci  void RefIsI31(FullDecoder* decoder, const Value& object, Value* result) {
12931cb0ef41Sopenharmony_ci    result->node = builder_->RefIsI31(object.node);
12941cb0ef41Sopenharmony_ci  }
12951cb0ef41Sopenharmony_ci
12961cb0ef41Sopenharmony_ci  void RefAsI31(FullDecoder* decoder, const Value& object, Value* result) {
12971cb0ef41Sopenharmony_ci    result->node = builder_->RefAsI31(object.node, decoder->position());
12981cb0ef41Sopenharmony_ci  }
12991cb0ef41Sopenharmony_ci
13001cb0ef41Sopenharmony_ci  void BrOnI31(FullDecoder* decoder, const Value& object,
13011cb0ef41Sopenharmony_ci               Value* value_on_branch, uint32_t br_depth) {
13021cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnI31>(
13031cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth,
13041cb0ef41Sopenharmony_ci        true);
13051cb0ef41Sopenharmony_ci  }
13061cb0ef41Sopenharmony_ci
13071cb0ef41Sopenharmony_ci  void BrOnNonI31(FullDecoder* decoder, const Value& object,
13081cb0ef41Sopenharmony_ci                  Value* value_on_fallthrough, uint32_t br_depth) {
13091cb0ef41Sopenharmony_ci    BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnI31>(
13101cb0ef41Sopenharmony_ci        decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough,
13111cb0ef41Sopenharmony_ci        br_depth, false);
13121cb0ef41Sopenharmony_ci  }
13131cb0ef41Sopenharmony_ci
13141cb0ef41Sopenharmony_ci  void Forward(FullDecoder* decoder, const Value& from, Value* to) {
13151cb0ef41Sopenharmony_ci    to->node = from.node;
13161cb0ef41Sopenharmony_ci  }
13171cb0ef41Sopenharmony_ci
13181cb0ef41Sopenharmony_ci  std::vector<compiler::WasmLoopInfo> loop_infos() { return loop_infos_; }
13191cb0ef41Sopenharmony_ci
13201cb0ef41Sopenharmony_ci private:
13211cb0ef41Sopenharmony_ci  SsaEnv* ssa_env_ = nullptr;
13221cb0ef41Sopenharmony_ci  compiler::WasmGraphBuilder* builder_;
13231cb0ef41Sopenharmony_ci  int func_index_;
13241cb0ef41Sopenharmony_ci  const BranchHintMap* branch_hints_ = nullptr;
13251cb0ef41Sopenharmony_ci  // Tracks loop data for loop unrolling.
13261cb0ef41Sopenharmony_ci  std::vector<compiler::WasmLoopInfo> loop_infos_;
13271cb0ef41Sopenharmony_ci  InlinedStatus inlined_status_;
13281cb0ef41Sopenharmony_ci  // The entries in {type_feedback_} are indexed by the position of feedback-
13291cb0ef41Sopenharmony_ci  // consuming instructions (currently only call_ref).
13301cb0ef41Sopenharmony_ci  int feedback_instruction_index_ = 0;
13311cb0ef41Sopenharmony_ci  std::vector<CallSiteFeedback> type_feedback_;
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ci  TFNode* effect() { return builder_->effect(); }
13341cb0ef41Sopenharmony_ci
13351cb0ef41Sopenharmony_ci  TFNode* control() { return builder_->control(); }
13361cb0ef41Sopenharmony_ci
13371cb0ef41Sopenharmony_ci  TryInfo* current_try_info(FullDecoder* decoder) {
13381cb0ef41Sopenharmony_ci    DCHECK_LT(decoder->current_catch(), decoder->control_depth());
13391cb0ef41Sopenharmony_ci    return decoder->control_at(decoder->control_depth_of_current_catch())
13401cb0ef41Sopenharmony_ci        ->try_info;
13411cb0ef41Sopenharmony_ci  }
13421cb0ef41Sopenharmony_ci
13431cb0ef41Sopenharmony_ci  // If {emit_loop_exits()} returns true, we need to emit LoopExit,
13441cb0ef41Sopenharmony_ci  // LoopExitEffect, and LoopExit nodes whenever a control resp. effect resp.
13451cb0ef41Sopenharmony_ci  // value escapes a loop. We emit loop exits in the following cases:
13461cb0ef41Sopenharmony_ci  // - When popping the control of a loop.
13471cb0ef41Sopenharmony_ci  // - At some nodes which connect to the graph's end. We do not always need to
13481cb0ef41Sopenharmony_ci  //   emit loop exits for such nodes, since the wasm loop analysis algorithm
13491cb0ef41Sopenharmony_ci  //   can handle a loop body which connects directly to the graph's end.
13501cb0ef41Sopenharmony_ci  //   However, we need to emit them anyway for nodes that may be rewired to
13511cb0ef41Sopenharmony_ci  //   different nodes during inlining. These are Return and TailCall nodes.
13521cb0ef41Sopenharmony_ci  // - After IfFailure nodes.
13531cb0ef41Sopenharmony_ci  // - When exiting a loop through Delegate.
13541cb0ef41Sopenharmony_ci  bool emit_loop_exits() {
13551cb0ef41Sopenharmony_ci    return FLAG_wasm_loop_unrolling || FLAG_wasm_loop_peeling;
13561cb0ef41Sopenharmony_ci  }
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_ci  void GetNodes(TFNode** nodes, Value* values, size_t count) {
13591cb0ef41Sopenharmony_ci    for (size_t i = 0; i < count; ++i) {
13601cb0ef41Sopenharmony_ci      nodes[i] = values[i].node;
13611cb0ef41Sopenharmony_ci    }
13621cb0ef41Sopenharmony_ci  }
13631cb0ef41Sopenharmony_ci
13641cb0ef41Sopenharmony_ci  void GetNodes(TFNode** nodes, base::Vector<Value> values) {
13651cb0ef41Sopenharmony_ci    GetNodes(nodes, values.begin(), values.size());
13661cb0ef41Sopenharmony_ci  }
13671cb0ef41Sopenharmony_ci
13681cb0ef41Sopenharmony_ci  void SetEnv(SsaEnv* env) {
13691cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_decoder) {
13701cb0ef41Sopenharmony_ci      char state = 'X';
13711cb0ef41Sopenharmony_ci      if (env) {
13721cb0ef41Sopenharmony_ci        switch (env->state) {
13731cb0ef41Sopenharmony_ci          case SsaEnv::kReached:
13741cb0ef41Sopenharmony_ci            state = 'R';
13751cb0ef41Sopenharmony_ci            break;
13761cb0ef41Sopenharmony_ci          case SsaEnv::kUnreachable:
13771cb0ef41Sopenharmony_ci            state = 'U';
13781cb0ef41Sopenharmony_ci            break;
13791cb0ef41Sopenharmony_ci          case SsaEnv::kMerged:
13801cb0ef41Sopenharmony_ci            state = 'M';
13811cb0ef41Sopenharmony_ci            break;
13821cb0ef41Sopenharmony_ci        }
13831cb0ef41Sopenharmony_ci      }
13841cb0ef41Sopenharmony_ci      PrintF("{set_env = %p, state = %c", env, state);
13851cb0ef41Sopenharmony_ci      if (env && env->control) {
13861cb0ef41Sopenharmony_ci        PrintF(", control = ");
13871cb0ef41Sopenharmony_ci        compiler::WasmGraphBuilder::PrintDebugName(env->control);
13881cb0ef41Sopenharmony_ci      }
13891cb0ef41Sopenharmony_ci      PrintF("}\n");
13901cb0ef41Sopenharmony_ci    }
13911cb0ef41Sopenharmony_ci    if (ssa_env_) {
13921cb0ef41Sopenharmony_ci      ssa_env_->control = control();
13931cb0ef41Sopenharmony_ci      ssa_env_->effect = effect();
13941cb0ef41Sopenharmony_ci    }
13951cb0ef41Sopenharmony_ci    ssa_env_ = env;
13961cb0ef41Sopenharmony_ci    builder_->SetEffectControl(env->effect, env->control);
13971cb0ef41Sopenharmony_ci    builder_->set_instance_cache(&env->instance_cache);
13981cb0ef41Sopenharmony_ci  }
13991cb0ef41Sopenharmony_ci
14001cb0ef41Sopenharmony_ci  TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
14011cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(node);
14021cb0ef41Sopenharmony_ci
14031cb0ef41Sopenharmony_ci    // We need to emit IfSuccess/IfException nodes if this node throws and has
14041cb0ef41Sopenharmony_ci    // an exception handler. An exception handler can either be a try-scope
14051cb0ef41Sopenharmony_ci    // around this node, or if this function is being inlined, the IfException
14061cb0ef41Sopenharmony_ci    // output of the inlined Call node.
14071cb0ef41Sopenharmony_ci    const bool inside_try_scope = decoder->current_catch() != -1;
14081cb0ef41Sopenharmony_ci    if (inlined_status_ != kInlinedHandledCall && !inside_try_scope) {
14091cb0ef41Sopenharmony_ci      return node;
14101cb0ef41Sopenharmony_ci    }
14111cb0ef41Sopenharmony_ci
14121cb0ef41Sopenharmony_ci    TFNode* if_success = nullptr;
14131cb0ef41Sopenharmony_ci    TFNode* if_exception = nullptr;
14141cb0ef41Sopenharmony_ci    if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
14151cb0ef41Sopenharmony_ci      return node;
14161cb0ef41Sopenharmony_ci    }
14171cb0ef41Sopenharmony_ci
14181cb0ef41Sopenharmony_ci    SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
14191cb0ef41Sopenharmony_ci    success_env->control = if_success;
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_ci    SsaEnv* exception_env = Split(decoder->zone(), success_env);
14221cb0ef41Sopenharmony_ci    exception_env->control = if_exception;
14231cb0ef41Sopenharmony_ci    exception_env->effect = if_exception;
14241cb0ef41Sopenharmony_ci    SetEnv(exception_env);
14251cb0ef41Sopenharmony_ci
14261cb0ef41Sopenharmony_ci    if (emit_loop_exits()) {
14271cb0ef41Sopenharmony_ci      ValueVector values;
14281cb0ef41Sopenharmony_ci      BuildNestedLoopExits(decoder,
14291cb0ef41Sopenharmony_ci                           inside_try_scope
14301cb0ef41Sopenharmony_ci                               ? decoder->control_depth_of_current_catch()
14311cb0ef41Sopenharmony_ci                               : decoder->control_depth() - 1,
14321cb0ef41Sopenharmony_ci                           true, values, &if_exception);
14331cb0ef41Sopenharmony_ci    }
14341cb0ef41Sopenharmony_ci    if (inside_try_scope) {
14351cb0ef41Sopenharmony_ci      TryInfo* try_info = current_try_info(decoder);
14361cb0ef41Sopenharmony_ci      Goto(decoder, try_info->catch_env);
14371cb0ef41Sopenharmony_ci      if (try_info->exception == nullptr) {
14381cb0ef41Sopenharmony_ci        DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
14391cb0ef41Sopenharmony_ci        try_info->exception = if_exception;
14401cb0ef41Sopenharmony_ci      } else {
14411cb0ef41Sopenharmony_ci        DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
14421cb0ef41Sopenharmony_ci        try_info->exception = builder_->CreateOrMergeIntoPhi(
14431cb0ef41Sopenharmony_ci            MachineRepresentation::kTaggedPointer, try_info->catch_env->control,
14441cb0ef41Sopenharmony_ci            try_info->exception, if_exception);
14451cb0ef41Sopenharmony_ci      }
14461cb0ef41Sopenharmony_ci    } else {
14471cb0ef41Sopenharmony_ci      DCHECK_EQ(inlined_status_, kInlinedHandledCall);
14481cb0ef41Sopenharmony_ci      // Leave the IfException/LoopExit node dangling. We will connect it during
14491cb0ef41Sopenharmony_ci      // inlining to the handler of the inlined call.
14501cb0ef41Sopenharmony_ci      // Note: We have to generate the handler now since we have no way of
14511cb0ef41Sopenharmony_ci      // generating a LoopExit if needed in the inlining code.
14521cb0ef41Sopenharmony_ci    }
14531cb0ef41Sopenharmony_ci
14541cb0ef41Sopenharmony_ci    SetEnv(success_env);
14551cb0ef41Sopenharmony_ci    return node;
14561cb0ef41Sopenharmony_ci  }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci  TFNode* DefaultValue(ValueType type) {
14591cb0ef41Sopenharmony_ci    DCHECK(type.is_defaultable());
14601cb0ef41Sopenharmony_ci    switch (type.kind()) {
14611cb0ef41Sopenharmony_ci      case kI8:
14621cb0ef41Sopenharmony_ci      case kI16:
14631cb0ef41Sopenharmony_ci      case kI32:
14641cb0ef41Sopenharmony_ci        return builder_->Int32Constant(0);
14651cb0ef41Sopenharmony_ci      case kI64:
14661cb0ef41Sopenharmony_ci        return builder_->Int64Constant(0);
14671cb0ef41Sopenharmony_ci      case kF32:
14681cb0ef41Sopenharmony_ci        return builder_->Float32Constant(0);
14691cb0ef41Sopenharmony_ci      case kF64:
14701cb0ef41Sopenharmony_ci        return builder_->Float64Constant(0);
14711cb0ef41Sopenharmony_ci      case kS128:
14721cb0ef41Sopenharmony_ci        return builder_->S128Zero();
14731cb0ef41Sopenharmony_ci      case kOptRef:
14741cb0ef41Sopenharmony_ci        return builder_->RefNull();
14751cb0ef41Sopenharmony_ci      case kRtt:
14761cb0ef41Sopenharmony_ci      case kVoid:
14771cb0ef41Sopenharmony_ci      case kBottom:
14781cb0ef41Sopenharmony_ci      case kRef:
14791cb0ef41Sopenharmony_ci        UNREACHABLE();
14801cb0ef41Sopenharmony_ci    }
14811cb0ef41Sopenharmony_ci  }
14821cb0ef41Sopenharmony_ci
14831cb0ef41Sopenharmony_ci  void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge,
14841cb0ef41Sopenharmony_ci                       Value* values) {
14851cb0ef41Sopenharmony_ci    DCHECK(merge == &c->start_merge || merge == &c->end_merge);
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ci    SsaEnv* target = c->merge_env;
14881cb0ef41Sopenharmony_ci    // This has to be computed before calling Goto().
14891cb0ef41Sopenharmony_ci    const bool first = target->state == SsaEnv::kUnreachable;
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_ci    Goto(decoder, target);
14921cb0ef41Sopenharmony_ci
14931cb0ef41Sopenharmony_ci    if (merge->arity == 0) return;
14941cb0ef41Sopenharmony_ci
14951cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < merge->arity; ++i) {
14961cb0ef41Sopenharmony_ci      Value& val = values[i];
14971cb0ef41Sopenharmony_ci      Value& old = (*merge)[i];
14981cb0ef41Sopenharmony_ci      DCHECK_NOT_NULL(val.node);
14991cb0ef41Sopenharmony_ci      DCHECK(val.type == kWasmBottom || val.type.machine_representation() ==
15001cb0ef41Sopenharmony_ci                                            old.type.machine_representation());
15011cb0ef41Sopenharmony_ci      old.node = first ? val.node
15021cb0ef41Sopenharmony_ci                       : builder_->CreateOrMergeIntoPhi(
15031cb0ef41Sopenharmony_ci                             old.type.machine_representation(), target->control,
15041cb0ef41Sopenharmony_ci                             old.node, val.node);
15051cb0ef41Sopenharmony_ci    }
15061cb0ef41Sopenharmony_ci  }
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci  void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge,
15091cb0ef41Sopenharmony_ci                       uint32_t drop_values = 0) {
15101cb0ef41Sopenharmony_ci#ifdef DEBUG
15111cb0ef41Sopenharmony_ci    uint32_t avail = decoder->stack_size() -
15121cb0ef41Sopenharmony_ci                     decoder->control_at(0)->stack_depth - drop_values;
15131cb0ef41Sopenharmony_ci    DCHECK_GE(avail, merge->arity);
15141cb0ef41Sopenharmony_ci#endif
15151cb0ef41Sopenharmony_ci    Value* stack_values = merge->arity > 0
15161cb0ef41Sopenharmony_ci                              ? decoder->stack_value(merge->arity + drop_values)
15171cb0ef41Sopenharmony_ci                              : nullptr;
15181cb0ef41Sopenharmony_ci    MergeValuesInto(decoder, c, merge, stack_values);
15191cb0ef41Sopenharmony_ci  }
15201cb0ef41Sopenharmony_ci
15211cb0ef41Sopenharmony_ci  void Goto(FullDecoder* decoder, SsaEnv* to) {
15221cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(to);
15231cb0ef41Sopenharmony_ci    switch (to->state) {
15241cb0ef41Sopenharmony_ci      case SsaEnv::kUnreachable: {  // Overwrite destination.
15251cb0ef41Sopenharmony_ci        to->state = SsaEnv::kReached;
15261cb0ef41Sopenharmony_ci        // There might be an offset in the locals due to a 'let'.
15271cb0ef41Sopenharmony_ci        DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals());
15281cb0ef41Sopenharmony_ci        DCHECK_GE(ssa_env_->locals.size(), to->locals.size());
15291cb0ef41Sopenharmony_ci        uint32_t local_count_diff =
15301cb0ef41Sopenharmony_ci            static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size());
15311cb0ef41Sopenharmony_ci        to->locals = ssa_env_->locals;
15321cb0ef41Sopenharmony_ci        to->locals.erase(to->locals.begin(),
15331cb0ef41Sopenharmony_ci                         to->locals.begin() + local_count_diff);
15341cb0ef41Sopenharmony_ci        to->control = control();
15351cb0ef41Sopenharmony_ci        to->effect = effect();
15361cb0ef41Sopenharmony_ci        to->instance_cache = ssa_env_->instance_cache;
15371cb0ef41Sopenharmony_ci        break;
15381cb0ef41Sopenharmony_ci      }
15391cb0ef41Sopenharmony_ci      case SsaEnv::kReached: {  // Create a new merge.
15401cb0ef41Sopenharmony_ci        to->state = SsaEnv::kMerged;
15411cb0ef41Sopenharmony_ci        // Merge control.
15421cb0ef41Sopenharmony_ci        TFNode* controls[] = {to->control, control()};
15431cb0ef41Sopenharmony_ci        TFNode* merge = builder_->Merge(2, controls);
15441cb0ef41Sopenharmony_ci        to->control = merge;
15451cb0ef41Sopenharmony_ci        // Merge effects.
15461cb0ef41Sopenharmony_ci        TFNode* old_effect = effect();
15471cb0ef41Sopenharmony_ci        if (old_effect != to->effect) {
15481cb0ef41Sopenharmony_ci          TFNode* inputs[] = {to->effect, old_effect, merge};
15491cb0ef41Sopenharmony_ci          to->effect = builder_->EffectPhi(2, inputs);
15501cb0ef41Sopenharmony_ci        }
15511cb0ef41Sopenharmony_ci        // Merge locals.
15521cb0ef41Sopenharmony_ci        // There might be an offset in the locals due to a 'let'.
15531cb0ef41Sopenharmony_ci        DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals());
15541cb0ef41Sopenharmony_ci        DCHECK_GE(ssa_env_->locals.size(), to->locals.size());
15551cb0ef41Sopenharmony_ci        uint32_t local_count_diff =
15561cb0ef41Sopenharmony_ci            static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size());
15571cb0ef41Sopenharmony_ci        for (uint32_t i = 0; i < to->locals.size(); i++) {
15581cb0ef41Sopenharmony_ci          TFNode* a = to->locals[i];
15591cb0ef41Sopenharmony_ci          TFNode* b = ssa_env_->locals[i + local_count_diff];
15601cb0ef41Sopenharmony_ci          if (a != b) {
15611cb0ef41Sopenharmony_ci            TFNode* inputs[] = {a, b, merge};
15621cb0ef41Sopenharmony_ci            to->locals[i] = builder_->Phi(
15631cb0ef41Sopenharmony_ci                decoder->local_type(i + local_count_diff), 2, inputs);
15641cb0ef41Sopenharmony_ci          }
15651cb0ef41Sopenharmony_ci        }
15661cb0ef41Sopenharmony_ci        // Start a new merge from the instance cache.
15671cb0ef41Sopenharmony_ci        builder_->NewInstanceCacheMerge(&to->instance_cache,
15681cb0ef41Sopenharmony_ci                                        &ssa_env_->instance_cache, merge);
15691cb0ef41Sopenharmony_ci        break;
15701cb0ef41Sopenharmony_ci      }
15711cb0ef41Sopenharmony_ci      case SsaEnv::kMerged: {
15721cb0ef41Sopenharmony_ci        TFNode* merge = to->control;
15731cb0ef41Sopenharmony_ci        // Extend the existing merge control node.
15741cb0ef41Sopenharmony_ci        builder_->AppendToMerge(merge, control());
15751cb0ef41Sopenharmony_ci        // Merge effects.
15761cb0ef41Sopenharmony_ci        to->effect =
15771cb0ef41Sopenharmony_ci            builder_->CreateOrMergeIntoEffectPhi(merge, to->effect, effect());
15781cb0ef41Sopenharmony_ci        // Merge locals.
15791cb0ef41Sopenharmony_ci        // There might be an offset in the locals due to a 'let'.
15801cb0ef41Sopenharmony_ci        DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals());
15811cb0ef41Sopenharmony_ci        DCHECK_GE(ssa_env_->locals.size(), to->locals.size());
15821cb0ef41Sopenharmony_ci        uint32_t local_count_diff =
15831cb0ef41Sopenharmony_ci            static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size());
15841cb0ef41Sopenharmony_ci        for (uint32_t i = 0; i < to->locals.size(); i++) {
15851cb0ef41Sopenharmony_ci          to->locals[i] = builder_->CreateOrMergeIntoPhi(
15861cb0ef41Sopenharmony_ci              decoder->local_type(i + local_count_diff)
15871cb0ef41Sopenharmony_ci                  .machine_representation(),
15881cb0ef41Sopenharmony_ci              merge, to->locals[i], ssa_env_->locals[i + local_count_diff]);
15891cb0ef41Sopenharmony_ci        }
15901cb0ef41Sopenharmony_ci        // Merge the instance caches.
15911cb0ef41Sopenharmony_ci        builder_->MergeInstanceCacheInto(&to->instance_cache,
15921cb0ef41Sopenharmony_ci                                         &ssa_env_->instance_cache, merge);
15931cb0ef41Sopenharmony_ci        break;
15941cb0ef41Sopenharmony_ci      }
15951cb0ef41Sopenharmony_ci      default:
15961cb0ef41Sopenharmony_ci        UNREACHABLE();
15971cb0ef41Sopenharmony_ci    }
15981cb0ef41Sopenharmony_ci  }
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_ci  // Create a complete copy of {from}.
16011cb0ef41Sopenharmony_ci  SsaEnv* Split(Zone* zone, SsaEnv* from) {
16021cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(from);
16031cb0ef41Sopenharmony_ci    if (from == ssa_env_) {
16041cb0ef41Sopenharmony_ci      ssa_env_->control = control();
16051cb0ef41Sopenharmony_ci      ssa_env_->effect = effect();
16061cb0ef41Sopenharmony_ci    }
16071cb0ef41Sopenharmony_ci    SsaEnv* result = zone->New<SsaEnv>(*from);
16081cb0ef41Sopenharmony_ci    result->state = SsaEnv::kReached;
16091cb0ef41Sopenharmony_ci    return result;
16101cb0ef41Sopenharmony_ci  }
16111cb0ef41Sopenharmony_ci
16121cb0ef41Sopenharmony_ci  // Create a copy of {from} that steals its state and leaves {from}
16131cb0ef41Sopenharmony_ci  // unreachable.
16141cb0ef41Sopenharmony_ci  SsaEnv* Steal(Zone* zone, SsaEnv* from) {
16151cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(from);
16161cb0ef41Sopenharmony_ci    if (from == ssa_env_) {
16171cb0ef41Sopenharmony_ci      ssa_env_->control = control();
16181cb0ef41Sopenharmony_ci      ssa_env_->effect = effect();
16191cb0ef41Sopenharmony_ci    }
16201cb0ef41Sopenharmony_ci    SsaEnv* result = zone->New<SsaEnv>(std::move(*from));
16211cb0ef41Sopenharmony_ci    // Restore the length of {from->locals} after applying move-constructor.
16221cb0ef41Sopenharmony_ci    from->locals.resize(result->locals.size());
16231cb0ef41Sopenharmony_ci    result->state = SsaEnv::kReached;
16241cb0ef41Sopenharmony_ci    return result;
16251cb0ef41Sopenharmony_ci  }
16261cb0ef41Sopenharmony_ci
16271cb0ef41Sopenharmony_ci  class CallInfo {
16281cb0ef41Sopenharmony_ci   public:
16291cb0ef41Sopenharmony_ci    enum CallMode { kCallDirect, kCallIndirect, kCallRef };
16301cb0ef41Sopenharmony_ci
16311cb0ef41Sopenharmony_ci    static CallInfo CallDirect(uint32_t callee_index) {
16321cb0ef41Sopenharmony_ci      return {kCallDirect, callee_index, nullptr, 0,
16331cb0ef41Sopenharmony_ci              CheckForNull::kWithoutNullCheck};
16341cb0ef41Sopenharmony_ci    }
16351cb0ef41Sopenharmony_ci
16361cb0ef41Sopenharmony_ci    static CallInfo CallIndirect(const Value& index_value, uint32_t table_index,
16371cb0ef41Sopenharmony_ci                                 uint32_t sig_index) {
16381cb0ef41Sopenharmony_ci      return {kCallIndirect, sig_index, &index_value, table_index,
16391cb0ef41Sopenharmony_ci              CheckForNull::kWithoutNullCheck};
16401cb0ef41Sopenharmony_ci    }
16411cb0ef41Sopenharmony_ci
16421cb0ef41Sopenharmony_ci    static CallInfo CallRef(const Value& funcref_value,
16431cb0ef41Sopenharmony_ci                            CheckForNull null_check) {
16441cb0ef41Sopenharmony_ci      return {kCallRef, 0, &funcref_value, 0, null_check};
16451cb0ef41Sopenharmony_ci    }
16461cb0ef41Sopenharmony_ci
16471cb0ef41Sopenharmony_ci    CallMode call_mode() { return call_mode_; }
16481cb0ef41Sopenharmony_ci
16491cb0ef41Sopenharmony_ci    uint32_t sig_index() {
16501cb0ef41Sopenharmony_ci      DCHECK_EQ(call_mode_, kCallIndirect);
16511cb0ef41Sopenharmony_ci      return callee_or_sig_index_;
16521cb0ef41Sopenharmony_ci    }
16531cb0ef41Sopenharmony_ci
16541cb0ef41Sopenharmony_ci    uint32_t callee_index() {
16551cb0ef41Sopenharmony_ci      DCHECK_EQ(call_mode_, kCallDirect);
16561cb0ef41Sopenharmony_ci      return callee_or_sig_index_;
16571cb0ef41Sopenharmony_ci    }
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_ci    CheckForNull null_check() {
16601cb0ef41Sopenharmony_ci      DCHECK_EQ(call_mode_, kCallRef);
16611cb0ef41Sopenharmony_ci      return null_check_;
16621cb0ef41Sopenharmony_ci    }
16631cb0ef41Sopenharmony_ci
16641cb0ef41Sopenharmony_ci    const Value* index_or_callee_value() {
16651cb0ef41Sopenharmony_ci      DCHECK_NE(call_mode_, kCallDirect);
16661cb0ef41Sopenharmony_ci      return index_or_callee_value_;
16671cb0ef41Sopenharmony_ci    }
16681cb0ef41Sopenharmony_ci
16691cb0ef41Sopenharmony_ci    uint32_t table_index() {
16701cb0ef41Sopenharmony_ci      DCHECK_EQ(call_mode_, kCallIndirect);
16711cb0ef41Sopenharmony_ci      return table_index_;
16721cb0ef41Sopenharmony_ci    }
16731cb0ef41Sopenharmony_ci
16741cb0ef41Sopenharmony_ci   private:
16751cb0ef41Sopenharmony_ci    CallInfo(CallMode call_mode, uint32_t callee_or_sig_index,
16761cb0ef41Sopenharmony_ci             const Value* index_or_callee_value, uint32_t table_index,
16771cb0ef41Sopenharmony_ci             CheckForNull null_check)
16781cb0ef41Sopenharmony_ci        : call_mode_(call_mode),
16791cb0ef41Sopenharmony_ci          callee_or_sig_index_(callee_or_sig_index),
16801cb0ef41Sopenharmony_ci          index_or_callee_value_(index_or_callee_value),
16811cb0ef41Sopenharmony_ci          table_index_(table_index),
16821cb0ef41Sopenharmony_ci          null_check_(null_check) {}
16831cb0ef41Sopenharmony_ci    CallMode call_mode_;
16841cb0ef41Sopenharmony_ci    uint32_t callee_or_sig_index_;
16851cb0ef41Sopenharmony_ci    const Value* index_or_callee_value_;
16861cb0ef41Sopenharmony_ci    uint32_t table_index_;
16871cb0ef41Sopenharmony_ci    CheckForNull null_check_;
16881cb0ef41Sopenharmony_ci  };
16891cb0ef41Sopenharmony_ci
16901cb0ef41Sopenharmony_ci  void DoCall(FullDecoder* decoder, CallInfo call_info, const FunctionSig* sig,
16911cb0ef41Sopenharmony_ci              const Value args[], Value returns[]) {
16921cb0ef41Sopenharmony_ci    size_t param_count = sig->parameter_count();
16931cb0ef41Sopenharmony_ci    size_t return_count = sig->return_count();
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_ci    // Construct a function signature based on the real function parameters.
16961cb0ef41Sopenharmony_ci    FunctionSig::Builder real_sig_builder(builder_->graph_zone(), return_count,
16971cb0ef41Sopenharmony_ci                                          param_count);
16981cb0ef41Sopenharmony_ci    for (size_t i = 0; i < param_count; i++) {
16991cb0ef41Sopenharmony_ci      real_sig_builder.AddParam(args[i].type);
17001cb0ef41Sopenharmony_ci    }
17011cb0ef41Sopenharmony_ci    for (size_t i = 0; i < return_count; i++) {
17021cb0ef41Sopenharmony_ci      real_sig_builder.AddReturn(sig->GetReturn(i));
17031cb0ef41Sopenharmony_ci    }
17041cb0ef41Sopenharmony_ci    FunctionSig* real_sig = real_sig_builder.Build();
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_ci    NodeVector arg_nodes(param_count + 1);
17071cb0ef41Sopenharmony_ci    base::SmallVector<TFNode*, 1> return_nodes(return_count);
17081cb0ef41Sopenharmony_ci    arg_nodes[0] = (call_info.call_mode() == CallInfo::kCallDirect)
17091cb0ef41Sopenharmony_ci                       ? nullptr
17101cb0ef41Sopenharmony_ci                       : call_info.index_or_callee_value()->node;
17111cb0ef41Sopenharmony_ci
17121cb0ef41Sopenharmony_ci    for (size_t i = 0; i < param_count; ++i) {
17131cb0ef41Sopenharmony_ci      arg_nodes[i + 1] = args[i].node;
17141cb0ef41Sopenharmony_ci    }
17151cb0ef41Sopenharmony_ci    switch (call_info.call_mode()) {
17161cb0ef41Sopenharmony_ci      case CallInfo::kCallIndirect:
17171cb0ef41Sopenharmony_ci        CheckForException(
17181cb0ef41Sopenharmony_ci            decoder, builder_->CallIndirect(
17191cb0ef41Sopenharmony_ci                         call_info.table_index(), call_info.sig_index(),
17201cb0ef41Sopenharmony_ci                         real_sig, base::VectorOf(arg_nodes),
17211cb0ef41Sopenharmony_ci                         base::VectorOf(return_nodes), decoder->position()));
17221cb0ef41Sopenharmony_ci        break;
17231cb0ef41Sopenharmony_ci      case CallInfo::kCallDirect:
17241cb0ef41Sopenharmony_ci        CheckForException(
17251cb0ef41Sopenharmony_ci            decoder, builder_->CallDirect(call_info.callee_index(), real_sig,
17261cb0ef41Sopenharmony_ci                                          base::VectorOf(arg_nodes),
17271cb0ef41Sopenharmony_ci                                          base::VectorOf(return_nodes),
17281cb0ef41Sopenharmony_ci                                          decoder->position()));
17291cb0ef41Sopenharmony_ci        break;
17301cb0ef41Sopenharmony_ci      case CallInfo::kCallRef:
17311cb0ef41Sopenharmony_ci        CheckForException(
17321cb0ef41Sopenharmony_ci            decoder,
17331cb0ef41Sopenharmony_ci            builder_->CallRef(real_sig, base::VectorOf(arg_nodes),
17341cb0ef41Sopenharmony_ci                              base::VectorOf(return_nodes),
17351cb0ef41Sopenharmony_ci                              call_info.null_check(), decoder->position()));
17361cb0ef41Sopenharmony_ci        break;
17371cb0ef41Sopenharmony_ci    }
17381cb0ef41Sopenharmony_ci    for (size_t i = 0; i < return_count; ++i) {
17391cb0ef41Sopenharmony_ci      returns[i].node = return_nodes[i];
17401cb0ef41Sopenharmony_ci    }
17411cb0ef41Sopenharmony_ci    if (decoder->module_->initial_pages != decoder->module_->maximum_pages) {
17421cb0ef41Sopenharmony_ci      // The invoked function could have used grow_memory, so we need to
17431cb0ef41Sopenharmony_ci      // reload mem_size and mem_start.
17441cb0ef41Sopenharmony_ci      LoadContextIntoSsa(ssa_env_);
17451cb0ef41Sopenharmony_ci    }
17461cb0ef41Sopenharmony_ci  }
17471cb0ef41Sopenharmony_ci
17481cb0ef41Sopenharmony_ci  void DoReturnCall(FullDecoder* decoder, CallInfo call_info,
17491cb0ef41Sopenharmony_ci                    const FunctionSig* sig, const Value args[]) {
17501cb0ef41Sopenharmony_ci    size_t arg_count = sig->parameter_count();
17511cb0ef41Sopenharmony_ci
17521cb0ef41Sopenharmony_ci    // Construct a function signature based on the real function parameters.
17531cb0ef41Sopenharmony_ci    FunctionSig::Builder real_sig_builder(builder_->graph_zone(),
17541cb0ef41Sopenharmony_ci                                          sig->return_count(), arg_count);
17551cb0ef41Sopenharmony_ci    for (size_t i = 0; i < arg_count; i++) {
17561cb0ef41Sopenharmony_ci      real_sig_builder.AddParam(args[i].type);
17571cb0ef41Sopenharmony_ci    }
17581cb0ef41Sopenharmony_ci    for (size_t i = 0; i < sig->return_count(); i++) {
17591cb0ef41Sopenharmony_ci      real_sig_builder.AddReturn(sig->GetReturn(i));
17601cb0ef41Sopenharmony_ci    }
17611cb0ef41Sopenharmony_ci    FunctionSig* real_sig = real_sig_builder.Build();
17621cb0ef41Sopenharmony_ci
17631cb0ef41Sopenharmony_ci    ValueVector arg_values(arg_count + 1);
17641cb0ef41Sopenharmony_ci    if (call_info.call_mode() == CallInfo::kCallDirect) {
17651cb0ef41Sopenharmony_ci      arg_values[0].node = nullptr;
17661cb0ef41Sopenharmony_ci    } else {
17671cb0ef41Sopenharmony_ci      arg_values[0] = *call_info.index_or_callee_value();
17681cb0ef41Sopenharmony_ci      // This is not done by copy assignment.
17691cb0ef41Sopenharmony_ci      arg_values[0].node = call_info.index_or_callee_value()->node;
17701cb0ef41Sopenharmony_ci    }
17711cb0ef41Sopenharmony_ci    if (arg_count > 0) {
17721cb0ef41Sopenharmony_ci      std::memcpy(arg_values.data() + 1, args, arg_count * sizeof(Value));
17731cb0ef41Sopenharmony_ci    }
17741cb0ef41Sopenharmony_ci
17751cb0ef41Sopenharmony_ci    if (emit_loop_exits()) {
17761cb0ef41Sopenharmony_ci      BuildNestedLoopExits(decoder, decoder->control_depth(), false,
17771cb0ef41Sopenharmony_ci                           arg_values);
17781cb0ef41Sopenharmony_ci    }
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci    NodeVector arg_nodes(arg_count + 1);
17811cb0ef41Sopenharmony_ci    GetNodes(arg_nodes.data(), base::VectorOf(arg_values));
17821cb0ef41Sopenharmony_ci
17831cb0ef41Sopenharmony_ci    switch (call_info.call_mode()) {
17841cb0ef41Sopenharmony_ci      case CallInfo::kCallIndirect:
17851cb0ef41Sopenharmony_ci        builder_->ReturnCallIndirect(
17861cb0ef41Sopenharmony_ci            call_info.table_index(), call_info.sig_index(), real_sig,
17871cb0ef41Sopenharmony_ci            base::VectorOf(arg_nodes), decoder->position());
17881cb0ef41Sopenharmony_ci        break;
17891cb0ef41Sopenharmony_ci      case CallInfo::kCallDirect:
17901cb0ef41Sopenharmony_ci        builder_->ReturnCall(call_info.callee_index(), real_sig,
17911cb0ef41Sopenharmony_ci                             base::VectorOf(arg_nodes), decoder->position());
17921cb0ef41Sopenharmony_ci        break;
17931cb0ef41Sopenharmony_ci      case CallInfo::kCallRef:
17941cb0ef41Sopenharmony_ci        builder_->ReturnCallRef(real_sig, base::VectorOf(arg_nodes),
17951cb0ef41Sopenharmony_ci                                call_info.null_check(), decoder->position());
17961cb0ef41Sopenharmony_ci        break;
17971cb0ef41Sopenharmony_ci    }
17981cb0ef41Sopenharmony_ci  }
17991cb0ef41Sopenharmony_ci
18001cb0ef41Sopenharmony_ci  void BuildLoopExits(FullDecoder* decoder, Control* loop) {
18011cb0ef41Sopenharmony_ci    builder_->LoopExit(loop->loop_node);
18021cb0ef41Sopenharmony_ci    ssa_env_->control = control();
18031cb0ef41Sopenharmony_ci    ssa_env_->effect = effect();
18041cb0ef41Sopenharmony_ci  }
18051cb0ef41Sopenharmony_ci
18061cb0ef41Sopenharmony_ci  void WrapLocalsAtLoopExit(FullDecoder* decoder, Control* loop) {
18071cb0ef41Sopenharmony_ci    for (uint32_t index = 0; index < decoder->num_locals(); index++) {
18081cb0ef41Sopenharmony_ci      if (loop->loop_assignments->Contains(static_cast<int>(index))) {
18091cb0ef41Sopenharmony_ci        ssa_env_->locals[index] = builder_->LoopExitValue(
18101cb0ef41Sopenharmony_ci            ssa_env_->locals[index],
18111cb0ef41Sopenharmony_ci            decoder->local_type(index).machine_representation());
18121cb0ef41Sopenharmony_ci      }
18131cb0ef41Sopenharmony_ci    }
18141cb0ef41Sopenharmony_ci    if (loop->loop_assignments->Contains(decoder->num_locals())) {
18151cb0ef41Sopenharmony_ci#define WRAP_CACHE_FIELD(field)                                                \
18161cb0ef41Sopenharmony_ci  if (ssa_env_->instance_cache.field != nullptr) {                             \
18171cb0ef41Sopenharmony_ci    ssa_env_->instance_cache.field = builder_->LoopExitValue(                  \
18181cb0ef41Sopenharmony_ci        ssa_env_->instance_cache.field, MachineType::PointerRepresentation()); \
18191cb0ef41Sopenharmony_ci  }
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci      WRAP_CACHE_FIELD(mem_start);
18221cb0ef41Sopenharmony_ci      WRAP_CACHE_FIELD(mem_size);
18231cb0ef41Sopenharmony_ci#undef WRAP_CACHE_FIELD
18241cb0ef41Sopenharmony_ci    }
18251cb0ef41Sopenharmony_ci  }
18261cb0ef41Sopenharmony_ci
18271cb0ef41Sopenharmony_ci  void BuildNestedLoopExits(FullDecoder* decoder, uint32_t depth_limit,
18281cb0ef41Sopenharmony_ci                            bool wrap_exit_values, ValueVector& stack_values,
18291cb0ef41Sopenharmony_ci                            TFNode** exception_value = nullptr) {
18301cb0ef41Sopenharmony_ci    DCHECK(emit_loop_exits());
18311cb0ef41Sopenharmony_ci    Control* control = nullptr;
18321cb0ef41Sopenharmony_ci    // We are only interested in exits from the innermost loop.
18331cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < depth_limit; i++) {
18341cb0ef41Sopenharmony_ci      Control* c = decoder->control_at(i);
18351cb0ef41Sopenharmony_ci      if (c->is_loop()) {
18361cb0ef41Sopenharmony_ci        control = c;
18371cb0ef41Sopenharmony_ci        break;
18381cb0ef41Sopenharmony_ci      }
18391cb0ef41Sopenharmony_ci    }
18401cb0ef41Sopenharmony_ci    if (control != nullptr) {
18411cb0ef41Sopenharmony_ci      BuildLoopExits(decoder, control);
18421cb0ef41Sopenharmony_ci      for (Value& value : stack_values) {
18431cb0ef41Sopenharmony_ci        if (value.node != nullptr) {
18441cb0ef41Sopenharmony_ci          value.node = builder_->LoopExitValue(
18451cb0ef41Sopenharmony_ci              value.node, value.type.machine_representation());
18461cb0ef41Sopenharmony_ci        }
18471cb0ef41Sopenharmony_ci      }
18481cb0ef41Sopenharmony_ci      if (exception_value != nullptr) {
18491cb0ef41Sopenharmony_ci        *exception_value = builder_->LoopExitValue(
18501cb0ef41Sopenharmony_ci            *exception_value, MachineRepresentation::kWord32);
18511cb0ef41Sopenharmony_ci      }
18521cb0ef41Sopenharmony_ci      if (wrap_exit_values) {
18531cb0ef41Sopenharmony_ci        WrapLocalsAtLoopExit(decoder, control);
18541cb0ef41Sopenharmony_ci      }
18551cb0ef41Sopenharmony_ci    }
18561cb0ef41Sopenharmony_ci  }
18571cb0ef41Sopenharmony_ci
18581cb0ef41Sopenharmony_ci  CheckForNull NullCheckFor(ValueType type) {
18591cb0ef41Sopenharmony_ci    DCHECK(type.is_object_reference());
18601cb0ef41Sopenharmony_ci    return (!FLAG_experimental_wasm_skip_null_checks && type.is_nullable())
18611cb0ef41Sopenharmony_ci               ? CheckForNull::kWithNullCheck
18621cb0ef41Sopenharmony_ci               : CheckForNull::kWithoutNullCheck;
18631cb0ef41Sopenharmony_ci  }
18641cb0ef41Sopenharmony_ci};
18651cb0ef41Sopenharmony_ci
18661cb0ef41Sopenharmony_ci}  // namespace
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ciDecodeResult BuildTFGraph(AccountingAllocator* allocator,
18691cb0ef41Sopenharmony_ci                          const WasmFeatures& enabled, const WasmModule* module,
18701cb0ef41Sopenharmony_ci                          compiler::WasmGraphBuilder* builder,
18711cb0ef41Sopenharmony_ci                          WasmFeatures* detected, const FunctionBody& body,
18721cb0ef41Sopenharmony_ci                          std::vector<compiler::WasmLoopInfo>* loop_infos,
18731cb0ef41Sopenharmony_ci                          compiler::NodeOriginTable* node_origins,
18741cb0ef41Sopenharmony_ci                          int func_index, InlinedStatus inlined_status) {
18751cb0ef41Sopenharmony_ci  Zone zone(allocator, ZONE_NAME);
18761cb0ef41Sopenharmony_ci  WasmFullDecoder<Decoder::kFullValidation, WasmGraphBuildingInterface> decoder(
18771cb0ef41Sopenharmony_ci      &zone, module, enabled, detected, body, builder, func_index,
18781cb0ef41Sopenharmony_ci      inlined_status);
18791cb0ef41Sopenharmony_ci  if (node_origins) {
18801cb0ef41Sopenharmony_ci    builder->AddBytecodePositionDecorator(node_origins, &decoder);
18811cb0ef41Sopenharmony_ci  }
18821cb0ef41Sopenharmony_ci  decoder.Decode();
18831cb0ef41Sopenharmony_ci  if (node_origins) {
18841cb0ef41Sopenharmony_ci    builder->RemoveBytecodePositionDecorator();
18851cb0ef41Sopenharmony_ci  }
18861cb0ef41Sopenharmony_ci  *loop_infos = decoder.interface().loop_infos();
18871cb0ef41Sopenharmony_ci
18881cb0ef41Sopenharmony_ci  return decoder.toResult(nullptr);
18891cb0ef41Sopenharmony_ci}
18901cb0ef41Sopenharmony_ci
18911cb0ef41Sopenharmony_ci}  // namespace wasm
18921cb0ef41Sopenharmony_ci}  // namespace internal
18931cb0ef41Sopenharmony_ci}  // namespace v8
1894