/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef wasm_ir_effects_h
#define wasm_ir_effects_h

#include <cassert>

#include "ir/intrinsics.h"
#include "pass.h"
#include "support/name.h"
#include "wasm-traversal.h"
#include "wasm-type.h"
#include "wasm.h"

namespace wasm {

// Analyze various possible effects.

class EffectAnalyzer {
public:
  EffectAnalyzer(const PassOptions& passOptions, const Module& module)
    : ignoreImplicitTraps(passOptions.ignoreImplicitTraps),
      trapsNeverHappen(passOptions.trapsNeverHappen), branchesOut(false),
      calls(false), readsMemory(false), writesMemory(false),
      readsSharedMemory(false), writesSharedMemory(false), readsTable(false),
      writesTable(false), readsMutableStruct(false), writesStruct(false),
      readsSharedMutableStruct(false), writesSharedStruct(false),
      readsMutableArray(false), writesArray(false),
      readsSharedMutableArray(false), writesSharedArray(false), trap(false),
      implicitTrap(false), throws_(false), danglingPop(false),
      mayNotReturn(false), hasReturnCallThrow(false), module(module),
      features(module.features) {}

  EffectAnalyzer(const PassOptions& passOptions,
                 const Module& module,
                 Expression* ast)
    : EffectAnalyzer(passOptions, module) {
    walk(ast);
  }

  EffectAnalyzer(const PassOptions& passOptions, Module& module, Function* func)
    : EffectAnalyzer(passOptions, module) {
    walk(func);
  }

  bool ignoreImplicitTraps : 1;
  bool trapsNeverHappen : 1;

  // Definitely branches out of this expression, or does a return, etc.
  // breakTargets tracks individual targets, which we may eventually see are
  // internal, while this is set when we see something that will definitely
  // not be internal, or is otherwise special like an infinite loop (which
  // does not technically branch "out", but it does break the normal assumption
  // of control flow proceeding normally).
  bool branchesOut : 1;

  bool calls : 1;
  bool readsMemory : 1;
  bool writesMemory : 1;
  bool readsSharedMemory : 1;
  bool writesSharedMemory : 1;
  bool readsTable : 1;
  bool writesTable : 1;

  // TODO: More specific type-based alias analysis, and not just at the
  //       struct/array level.
  bool readsMutableStruct : 1;
  bool writesStruct : 1;
  bool readsSharedMutableStruct : 1;
  bool writesSharedStruct : 1;
  bool readsMutableArray : 1;
  bool writesArray : 1;
  bool readsSharedMutableArray : 1;
  bool writesSharedArray : 1;

  // A trap, either from an unreachable instruction, or from an implicit trap
  // that we do not ignore (see below).
  //
  // Note that we ignore trap differences, so it is ok to reorder traps with
  // each other, but it is not ok to remove them or reorder them with other
  // effects in a noticeable way.
  //
  // Note also that we ignore *optional* runtime-specific traps: we only
  // consider as trapping something that will trap in *all* VMs, and *all* the
  // time. For example, a single allocation might trap in a VM in a particular
  // execution, if it happens to run out of memory just there, but that is not
  // enough for us to mark it as having a trap effect. (Note that not marking
  // each allocation as possibly trapping has the nice benefit of making it
  // possible to eliminate an allocation whose result is not captured.) OTOH, we
  // *do* mark a potentially infinite number of allocations as trapping, as all
  // VMs would trap eventually, and the same for potentially infinite recursion,
  // etc.
  bool trap : 1;

  // A trap from an instruction like a load or div/rem, which may trap on corner
  // cases. If we do not ignore implicit traps then these are counted as a trap.
  bool implicitTrap : 1;

  bool throws_ : 1;

  // If this expression contains 'pop's that are not enclosed in 'catch' body.
  // For example, (drop (pop i32)) should set this to true.
  bool danglingPop : 1;

  // Whether this code may "hang" and not eventually complete. An infinite loop,
  // or a continuation that is never continued, are examples of that.
  bool mayNotReturn : 1;

  // Since return calls return out of the body of the function before performing
  // their call, they are indistinguishable from normal returns from the
  // perspective of their surrounding code, and the return-callee's effects only
  // become visible when considering the effects of the whole function
  // containing the return call. To model this correctly, stash the callee's
  // effects on the side and only merge them in after walking a full function
  // body.
  //
  // We currently do this stashing only for the throw effect, but in principle
  // we could do it for all effects if it made a difference. (Only throw is
  // noticeable now because the only thing that can change between doing the
  // call here and doing it outside at the function exit is the scoping of
  // try-catch blocks. If future wasm scoping additions are added, we may need
  // more here.)
  bool hasReturnCallThrow : 1;

  const Module& module;
  FeatureSet features;

  std::set<Index> localsRead;
  std::set<Index> localsWritten;
  std::set<Name> mutableGlobalsRead;
  std::set<Name> globalsWritten;

  // The nested depth of try-catch_all. If an instruction that may throw is
  // inside an inner try-catch_all, we don't mark it as 'throws_', because it
  // will be caught by an inner catch_all. We only count 'try's with a
  // 'catch_all' because instructions within a 'try' without a 'catch_all' can
  // still throw outside of the try.
  size_t tryDepth = 0;
  // The nested depth of catch. This is necessary to track danglng pops.
  size_t catchDepth = 0;

  // The strongest memory orders used to read and write to any shared location
  // (e.g. shared memories, shared GC structs, etc), if any.
  MemoryOrder readOrder = MemoryOrder::Unordered;
  MemoryOrder writeOrder = MemoryOrder::Unordered;

  // Walk an expression and all its children.
  void walk(Expression* ast) {
    InternalAnalyzer(*this).walk(ast);
    post();
  }

  // Visit an expression, without any children.
  void visit(Expression* ast) {
    InternalAnalyzer(*this).visit(ast);
    post();
  }

  // Walk an entire function body. This will ignore effects that are not
  // noticeable from the perspective of the caller, that is, effects that are
  // only noticeable during the call, but "vanish" when the call stack is
  // unwound.
  //
  // Unlike walking just the body, walking the function will also
  // include the effects of any return calls the function makes. For that
  // reason, it is a bug if a user of this code calls walk(Expression*) and not
  // walk(Function*) if their intention is to scan an entire function body.
  // Putting it another way, a return_call is syntax sugar for a return and a
  // call, where the call executes at the function scope, so there is a
  // meaningful difference between scanning an expression and scanning
  // the entire function body.
  void walk(Function* func) {
    walk(func->body);

    // Effects of return-called functions will be visible to the caller.
    if (hasReturnCallThrow) {
      throws_ = true;
    }

    // We can ignore branching out of the function body - this can only be
    // a return, and that is only noticeable in the function, not outside.
    branchesOut = false;

    // When the function exits, changes to locals cannot be noticed any more.
    localsWritten.clear();
    localsRead.clear();
  }

  // Helper functions to check for various effect types

  bool accessesLocal() const {
    return localsRead.size() + localsWritten.size() > 0;
  }
  bool accessesMutableGlobal() const {
    return globalsWritten.size() + mutableGlobalsRead.size() > 0;
  }
  bool accessesMemory() const { return calls || readsMemory || writesMemory; }
  bool accessesSharedMemory() const {
    return calls || readsSharedMemory || writesSharedMemory;
  }
  bool accessesTable() const { return calls || readsTable || writesTable; }
  bool accessesMutableStruct() const {
    return calls || readsMutableStruct || writesStruct;
  }
  bool accessesSharedMutableStruct() const {
    return calls || readsSharedMutableStruct || writesSharedStruct;
  }
  bool accessesArray() const {
    return calls || readsMutableArray || writesArray;
  }
  bool accessesSharedArray() const {
    return calls || readsSharedMutableArray || writesSharedArray;
  }
  bool throws() const { return throws_ || !delegateTargets.empty(); }
  // Check whether this may transfer control flow to somewhere outside of this
  // expression (aside from just flowing out normally). That includes a break
  // or a throw (if the throw is not known to be caught inside this expression;
  // note that if the throw is not caught in this expression then it might be
  // caught in this function but outside of this expression, or it might not be
  // caught in the function at all, which would mean control flow cannot be
  // transferred inside the function, but this expression does not know that).
  bool transfersControlFlow() const {
    return branchesOut || throws() || hasExternalBreakTargets();
  }

  // Changes something in globally-stored state.
  bool writesGlobalState() const {
    return globalsWritten.size() || writesMemory || writesSharedMemory ||
           writesTable || writesStruct || writesSharedStruct || writesArray ||
           writesSharedArray || calls;
  }
  bool readsMutableGlobalState() const {
    return mutableGlobalsRead.size() || readsMemory || readsSharedMemory ||
           readsTable || readsMutableStruct || readsSharedMutableStruct ||
           readsMutableArray || readsSharedMutableArray || calls;
  }
  bool accessesSharedGlobalState() const {
    return readsSharedMemory || writesSharedMemory ||
           readsSharedMutableStruct || writesSharedStruct ||
           readsSharedMutableArray || writesSharedArray || calls;
  }

  bool hasSynchronization() const {
    return readOrder != MemoryOrder::Unordered ||
           writeOrder != MemoryOrder::Unordered;
  }

  bool hasNonTrapSideEffects() const {
    return localsWritten.size() > 0 || danglingPop || writesGlobalState() ||
           throws() || transfersControlFlow() || hasSynchronization() ||
           mayNotReturn;
  }

  bool hasSideEffects() const { return trap || hasNonTrapSideEffects(); }

  // Check if there are side effects, and they are of a kind that cannot be
  // removed by optimization passes.
  //
  // The difference between this and hasSideEffects is subtle, and only related
  // to trapsNeverHappen - if trapsNeverHappen then any trap we see is removable
  // by optimizations. In general, you should call hasSideEffects, and only call
  // this method if you are certain that it is a place that would not perform an
  // unsafe transformation with a trap. Specifically, if a pass calls this
  // and gets the result that there are no unremovable side effects, then it
  // must either
  //
  //  1. Remove any side effects present, if any, so they no longer exist.
  //  2. Keep the code exactly where it is.
  //
  // If instead of 1&2 a pass kept the side effect and also reordered the code
  // with other things, then that could be bad, as the side effect might have
  // been behind a condition that avoids it occurring.
  //
  // TODO: Go through the optimizer and use this in all places that do not move
  //       code around.
  bool hasUnremovableSideEffects() const {
    return hasNonTrapSideEffects() || (trap && !trapsNeverHappen);
  }

  bool hasAnything() const {
    return hasSideEffects() || accessesLocal() || readsMutableGlobalState();
  }

  // check if we break to anything external from ourselves
  bool hasExternalBreakTargets() const { return !breakTargets.empty(); }

  // Checks if these effects must remain ordered before another set of effects
  // (e.g., if we write, we must remain ordered before someone that reads).
  //
  // This assumes the things whose effects we are comparing will both execute,
  // at least if neither of them transfers control flow away. That is, we assume
  // that there is no transfer of control flow *between* them: we are comparing
  // things appear after each other, perhaps with some other code in the middle,
  // but that code does not transfer control flow. It is not valid to call this
  // method in other situations, like this:
  //
  //   A
  //   (br_if 0 (local.get 0)) ;; this may transfer control flow away
  //   B
  //
  // Calling this method in that situation is invalid because only A may
  // execute and not B. The following are examples of situations where it is
  // valid to call this method:
  //
  //   A
  //   ;; nothing in between them at all
  //   B
  //
  //   A
  //   (local.set 0 (i32.const 0)) ;; something in between without a possible
  //                               ;; control flow transfer
  //   B
  //
  // That the things being compared both execute only matters in the case of
  // traps-never-happen: in that mode we can move traps but only if doing so
  // would not make them start to appear when they did not. In the second
  // example we can't reorder A and B if B traps, but in the first example we
  // can reorder them even if B traps (even if A has a global effect like a
  // global.set, since we assume B does not trap in traps-never-happen).
  bool orderedBefore(const EffectAnalyzer& other) const {
    // Cannot reorder control flow and side effects.
    if ((transfersControlFlow() && other.hasSideEffects()) ||
        (other.transfersControlFlow() && hasSideEffects())) {
      return true;
    }
    // write-write, write-read, and read-write conflicts on possibly aliasing
    // locations prevent reordering. Calls may access these locations.
    if (((writesMemory || calls) && other.accessesMemory()) ||
        ((other.writesMemory || other.calls) && accessesMemory()) ||
        ((writesSharedMemory || calls) && other.accessesSharedMemory()) ||
        ((other.writesSharedMemory || other.calls) && accessesSharedMemory()) ||
        ((writesTable || calls) && other.accessesTable()) ||
        ((other.writesTable || other.calls) && accessesTable()) ||
        ((writesStruct || calls) && other.accessesMutableStruct()) ||
        ((other.writesStruct || other.calls) && accessesMutableStruct()) ||
        ((writesSharedStruct || calls) &&
         other.accessesSharedMutableStruct()) ||
        ((other.writesSharedStruct || other.calls) &&
         accessesSharedMutableStruct()) ||
        ((writesArray || calls) && other.accessesArray()) ||
        ((other.writesArray || other.calls) && accessesArray()) ||
        ((writesSharedArray || calls) && other.accessesSharedArray()) ||
        ((other.writesSharedArray || other.calls) && accessesSharedArray())) {
      return true;
    }
    // Cannot reorder anything before dangling pops.
    if (danglingPop) {
      return true;
    }
    // Shared location accesses cannot be reordered after (but may be able to be
    // reordered before) release stores.
    if (other.writeOrder >= MemoryOrder::AcqRel &&
        accessesSharedGlobalState()) {
      return true;
    }
    // Shared location accesses cannot be reordered before (but may be able to
    // be reordered after) acquire loads.
    if (readOrder >= MemoryOrder::AcqRel && other.accessesSharedGlobalState()) {
      return true;
    }
    // No shared location accesses may be reordered in either direction around a
    // seqcst operation.
    if (((readOrder == MemoryOrder::SeqCst ||
          writeOrder == MemoryOrder::SeqCst) &&
         other.accessesSharedGlobalState()) ||
        ((other.readOrder == MemoryOrder::SeqCst ||
          other.writeOrder == MemoryOrder::SeqCst) &&
         accessesSharedGlobalState())) {
      return true;
    }
    // write-write, write-read, and read-write conflicts on a local prevent
    // reordering.
    for (auto local : localsWritten) {
      if (other.localsRead.contains(local) ||
          other.localsWritten.contains(local)) {
        return true;
      }
    }
    for (auto local : localsRead) {
      if (other.localsWritten.contains(local)) {
        return true;
      }
    }
    // write-write, write-read, and read-write conflicts on globals prevent
    // reordering. Unlike for locals, calls can access globals.
    if ((other.calls && accessesMutableGlobal()) ||
        (calls && other.accessesMutableGlobal())) {
      return true;
    }
    for (auto global : globalsWritten) {
      if (other.mutableGlobalsRead.contains(global) ||
          other.globalsWritten.contains(global)) {
        return true;
      }
    }
    for (auto global : mutableGlobalsRead) {
      if (other.globalsWritten.contains(global)) {
        return true;
      }
    }
    // Note that the above includes disallowing the reordering of a trap with an
    // exception (as an exception can transfer control flow inside the current
    // function, so transfersControlFlow would be true) - while we allow the
    // reordering of traps with each other, we do not reorder exceptions with
    // anything.
    assert(!((trap && other.throws()) || (throws() && other.trap)));
    // We can't reorder an implicit trap in a way that could alter what global
    // state is modified. However, in trapsNeverHappen mode we assume traps do
    // not occur in practice, which lets us ignore this, at least in the case
    // that the code executes. As mentioned above, we assume that there is no
    // transfer of control flow between the things we are comparing, so all we
    // need to do is check for such transfers in them.
    if (!trapsNeverHappen || transfersControlFlow() ||
        other.transfersControlFlow()) {
      if ((trap && other.writesGlobalState()) ||
          (other.trap && writesGlobalState())) {
        return true;
      }
    }
    return false;
  }

  bool orderedAfter(const EffectAnalyzer& other) {
    return other.orderedBefore(*this);
  }

  // Whether these effects are prevented from moving past the other effects in
  // either direction.
  // TODO: Update users to check order more precisely and remove this.
  bool invalidates(const EffectAnalyzer& other) {
    return orderedBefore(other) || orderedAfter(other);
  }

  void mergeIn(const EffectAnalyzer& other) {
    branchesOut = branchesOut || other.branchesOut;
    calls = calls || other.calls;
    readsMemory = readsMemory || other.readsMemory;
    writesMemory = writesMemory || other.writesMemory;
    readsSharedMemory = readsSharedMemory || other.readsSharedMemory;
    writesSharedMemory = writesSharedMemory || other.writesSharedMemory;
    readsTable = readsTable || other.readsTable;
    writesTable = writesTable || other.writesTable;
    readsMutableStruct = readsMutableStruct || other.readsMutableStruct;
    writesStruct = writesStruct || other.writesStruct;
    readsSharedMutableStruct =
      readsSharedMutableStruct || other.readsSharedMutableStruct;
    writesSharedStruct = writesSharedStruct || other.writesSharedStruct;
    readsMutableArray = readsMutableArray || other.readsMutableArray;
    writesArray = writesArray || other.writesArray;
    readsSharedMutableArray =
      readsSharedMutableArray || other.readsSharedMutableArray;
    writesSharedArray = writesSharedArray || other.writesSharedArray;
    trap = trap || other.trap;
    implicitTrap = implicitTrap || other.implicitTrap;
    trapsNeverHappen = trapsNeverHappen || other.trapsNeverHappen;
    throws_ = throws_ || other.throws_;
    danglingPop = danglingPop || other.danglingPop;
    mayNotReturn = mayNotReturn || other.mayNotReturn;
    hasReturnCallThrow = hasReturnCallThrow || other.hasReturnCallThrow;
    readOrder = std::max(readOrder, other.readOrder);
    writeOrder = std::max(writeOrder, other.writeOrder);

    for (auto i : other.localsRead) {
      localsRead.insert(i);
    }
    for (auto i : other.localsWritten) {
      localsWritten.insert(i);
    }
    for (auto i : other.mutableGlobalsRead) {
      mutableGlobalsRead.insert(i);
    }
    for (auto i : other.globalsWritten) {
      globalsWritten.insert(i);
    }
    for (auto i : other.breakTargets) {
      breakTargets.insert(i);
    }
    for (auto i : other.delegateTargets) {
      delegateTargets.insert(i);
    }
  }

  // the checks above happen after the node's children were processed, in the
  // order of execution we must also check for control flow that happens before
  // the children, i.e., loops
  bool checkPre(Expression* curr) {
    if (curr->is<Loop>()) {
      branchesOut = true;
      return true;
    }
    return false;
  }

  bool checkPost(Expression* curr) {
    visit(curr);
    if (curr->is<Loop>()) {
      branchesOut = true;
    }
    return hasAnything();
  }

  std::set<Name> breakTargets;
  std::set<Name> delegateTargets;

private:
  struct InternalAnalyzer
    : public PostWalker<InternalAnalyzer, OverriddenVisitor<InternalAnalyzer>> {

    EffectAnalyzer& parent;

    InternalAnalyzer(EffectAnalyzer& parent) : parent(parent) {}

    static void scan(InternalAnalyzer* self, Expression** currp) {
      Expression* curr = *currp;
      // We need to decrement try depth before catch starts, so handle it
      // separately
      if (curr->is<Try>()) {
        self->pushTask(doVisitTry, currp);
        self->pushTask(doEndCatch, currp);
        auto& catchBodies = curr->cast<Try>()->catchBodies;
        for (int i = int(catchBodies.size()) - 1; i >= 0; i--) {
          self->pushTask(scan, &catchBodies[i]);
        }
        self->pushTask(doStartCatch, currp);
        self->pushTask(scan, &curr->cast<Try>()->body);
        self->pushTask(doStartTry, currp);
        return;
      }
      if (auto* tryTable = curr->dynCast<TryTable>()) {
        // We need to increment try depth before starting.
        self->pushTask(doEndTryTable, currp);
        self->pushTask(doVisitTryTable, currp);
        self->pushTask(scan, &tryTable->body);
        self->pushTask(doStartTryTable, currp);
        return;
      }
      PostWalker<InternalAnalyzer, OverriddenVisitor<InternalAnalyzer>>::scan(
        self, currp);
    }

    static void doStartTry(InternalAnalyzer* self, Expression** currp) {
      Try* curr = (*currp)->cast<Try>();
      // We only count 'try's with a 'catch_all' because instructions within a
      // 'try' without a 'catch_all' can still throw outside of the try.
      if (curr->hasCatchAll()) {
        self->parent.tryDepth++;
      }
    }

    static void doStartCatch(InternalAnalyzer* self, Expression** currp) {
      Try* curr = (*currp)->cast<Try>();
      // This is conservative. When an inner try-delegate targets the current
      // expression, even if the try-delegate's body can't throw, we consider
      // the current expression can throw for simplicity, unless the current
      // expression is not inside a try-catch_all. It is hard to figure out
      // whether the original try-delegate's body throws or not at this point.
      if (curr->name.is()) {
        if (self->parent.delegateTargets.contains(curr->name) &&
            self->parent.tryDepth == 0) {
          self->parent.throws_ = true;
        }
        self->parent.delegateTargets.erase(curr->name);
      }
      // We only count 'try's with a 'catch_all' because instructions within a
      // 'try' without a 'catch_all' can still throw outside of the try.
      if (curr->hasCatchAll()) {
        assert(self->parent.tryDepth > 0 && "try depth cannot be negative");
        self->parent.tryDepth--;
      }
      self->parent.catchDepth++;
    }

    static void doEndCatch(InternalAnalyzer* self, Expression** currp) {
      assert(self->parent.catchDepth > 0 && "catch depth cannot be negative");
      self->parent.catchDepth--;
    }

    static void doStartTryTable(InternalAnalyzer* self, Expression** currp) {
      auto* curr = (*currp)->cast<TryTable>();
      // We only count 'try_table's with a 'catch_all' because instructions
      // within a 'try_table' without a 'catch_all' can still throw outside of
      // the try.
      if (curr->hasCatchAll()) {
        self->parent.tryDepth++;
      }
    }

    static void doEndTryTable(InternalAnalyzer* self, Expression** currp) {
      auto* curr = (*currp)->cast<TryTable>();
      if (curr->hasCatchAll()) {
        assert(self->parent.tryDepth > 0 && "try depth cannot be negative");
        self->parent.tryDepth--;
      }
    }

    void readsMemory(Name memory, MemoryOrder order) {
      if (parent.module.getMemory(memory)->shared) {
        parent.readsSharedMemory = true;
        parent.readOrder = std::max(parent.readOrder, order);
      } else {
        parent.readsMemory = true;
      }
    }

    void writesMemory(Name memory, MemoryOrder order) {
      if (parent.module.getMemory(memory)->shared) {
        parent.writesSharedMemory = true;
        parent.writeOrder = std::max(parent.writeOrder, order);
      } else {
        parent.writesMemory = true;
      }
    }

    void readsStruct(HeapType type, Index index, MemoryOrder order) {
      assert(type.isStruct());
      if (type.getStruct().fields[index].mutable_ == Mutable) {
        if (type.isShared()) {
          parent.readsSharedMutableStruct = true;
          parent.readOrder = std::max(parent.readOrder, order);
        } else {
          parent.readsMutableStruct = true;
        }
      }
    }

    void writesStruct(HeapType type, Index index, MemoryOrder order) {
      assert(type.isStruct());
      if (type.isShared()) {
        parent.writesSharedStruct = true;
        parent.writeOrder = std::max(parent.writeOrder, order);
      } else {
        parent.writesStruct = true;
      }
    }

    void readsArray(HeapType type, MemoryOrder order) {
      assert(type.isArray());
      if (type.getArray().element.mutable_ == Mutable) {
        if (type.isShared()) {
          parent.readsSharedMutableArray = true;
          parent.readOrder = std::max(parent.readOrder, order);
        } else {
          parent.readsMutableArray = true;
        }
      }
    }

    void writesArray(HeapType type, MemoryOrder order) {
      assert(type.isArray());
      if (type.isShared()) {
        parent.writesSharedArray = true;
        parent.writeOrder = std::max(parent.writeOrder, order);
      } else {
        parent.writesArray = true;
      }
    }

    // Handle effects due to an explicit null check of the operands in `exprs`.
    // Returns true iff there is no need to consider further effects.
    bool trapOnNull(std::initializer_list<Expression*> exprs) {
      for (auto* expr : exprs) {
        if (expr && expr->type == Type::unreachable) {
          return true;
        }
      }
      for (auto* expr : exprs) {
        assert(!expr || expr->type.isRef());
        if (expr && expr->type.isNull()) {
          parent.trap = true;
          return true;
        }
      }
      for (auto* expr : exprs) {
        if (expr && expr->type.isNullable()) {
          parent.implicitTrap = true;
          break;
        }
      }
      return false;
    }

    bool trapOnNull(Expression* expr) { return trapOnNull({expr}); }

    void visitBlock(Block* curr) {
      if (curr->name.is()) {
        parent.breakTargets.erase(curr->name); // these were internal breaks
      }
    }
    void visitIf(If* curr) {}
    void visitLoop(Loop* curr) {
      if (curr->name.is() && parent.breakTargets.erase(curr->name) > 0) {
        parent.mayNotReturn = true;
      }
    }
    void visitBreak(Break* curr) { parent.breakTargets.insert(curr->name); }
    void visitSwitch(Switch* curr) {
      for (auto name : curr->targets) {
        parent.breakTargets.insert(name);
      }
      parent.breakTargets.insert(curr->default_);
    }

    void visitCall(Call* curr) {
      // call.without.effects has no effects.
      if (Intrinsics(parent.module).isCallWithoutEffects(curr)) {
        return;
      }

      // Get the target's effects, if they exist. Note that we must handle the
      // case of the function not yet existing (we may be executed in the middle
      // of a pass, which may have built up calls but not the targets of those
      // calls; in such a case, we do not find the targets and therefore assume
      // we know nothing about the effects, which is safe).
      const EffectAnalyzer* targetEffects = nullptr;
      if (auto* target = parent.module.getFunctionOrNull(curr->target)) {
        targetEffects = target->effects.get();
      }

      if (curr->isReturn) {
        parent.branchesOut = true;
        // When EH is enabled, any call can throw.
        if (parent.features.hasExceptionHandling() &&
            (!targetEffects || targetEffects->throws())) {
          parent.hasReturnCallThrow = true;
        }
      }

      if (targetEffects) {
        // We have effect information for this call target, and can just use
        // that. The one change we may want to make is to remove throws_, if the
        // target function throws and we know that will be caught anyhow, the
        // same as the code below for the general path. We can always filter out
        // throws for return calls because they are already more precisely
        // captured by `branchesOut`, which models the return, and
        // `hasReturnCallThrow`, which models the throw that will happen after
        // the return.
        if (targetEffects->throws_ && (parent.tryDepth > 0 || curr->isReturn)) {
          auto filteredEffects = *targetEffects;
          filteredEffects.throws_ = false;
          parent.mergeIn(filteredEffects);
        } else {
          // Just merge in all the effects.
          parent.mergeIn(*targetEffects);
        }
        return;
      }

      parent.calls = true;
      // When EH is enabled, any call can throw. Skip this for return calls
      // because the throw is already more precisely captured by the combination
      // of `hasReturnCallThrow` and `branchesOut`.
      if (parent.features.hasExceptionHandling() && parent.tryDepth == 0 &&
          !curr->isReturn) {
        parent.throws_ = true;
      }
    }
    void visitCallIndirect(CallIndirect* curr) {
      parent.calls = true;
      if (curr->isReturn) {
        parent.branchesOut = true;
        if (parent.features.hasExceptionHandling()) {
          parent.hasReturnCallThrow = true;
        }
      }
      if (parent.features.hasExceptionHandling() &&
          (parent.tryDepth == 0 && !curr->isReturn)) {
        parent.throws_ = true;
      }
    }
    void visitLocalGet(LocalGet* curr) {
      parent.localsRead.insert(curr->index);
    }
    void visitLocalSet(LocalSet* curr) {
      parent.localsWritten.insert(curr->index);
    }
    void visitGlobalGet(GlobalGet* curr) {
      if (parent.module.getGlobal(curr->name)->mutable_ == Mutable) {
        parent.mutableGlobalsRead.insert(curr->name);
      }
    }
    void visitGlobalSet(GlobalSet* curr) {
      parent.globalsWritten.insert(curr->name);
    }
    void visitLoad(Load* curr) {
      readsMemory(curr->memory, curr->order);
      parent.implicitTrap = true;
    }
    void visitStore(Store* curr) {
      writesMemory(curr->memory, curr->order);
      parent.implicitTrap = true;
    }
    void visitAtomicRMW(AtomicRMW* curr) {
      readsMemory(curr->memory, curr->order);
      writesMemory(curr->memory, curr->order);
      parent.implicitTrap = true;
    }
    void visitAtomicCmpxchg(AtomicCmpxchg* curr) {
      readsMemory(curr->memory, curr->order);
      writesMemory(curr->memory, curr->order);
      parent.implicitTrap = true;
    }
    void visitAtomicWait(AtomicWait* curr) {
      // Waits on unshared memories trap.
      if (!parent.module.getMemory(curr->memory)->shared) {
        parent.trap = true;
        return;
      }
      // AtomicWait doesn't strictly write memory, but it does modify the
      // waiters list associated with the specified address, which we can think
      // of as a write.
      parent.readsSharedMemory = true;
      parent.writesSharedMemory = true;
      parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;
      // Traps on unaligned accesses.
      parent.implicitTrap = true;
    }
    void visitAtomicNotify(AtomicNotify* curr) {
      // Notifies on unshared memories just return 0 or trap on unaligned
      // accesses.
      parent.implicitTrap = true;
      if (!parent.module.getMemory(curr->memory)->shared) {
        return;
      }
      // AtomicNotify doesn't strictly write memory, but it does
      // modify the waiters list associated with the specified address, which we
      // can think of as a write.
      parent.readsSharedMemory = true;
      parent.writesSharedMemory = true;
      parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;
    }
    void visitAtomicFence(AtomicFence* curr) {
      // AtomicFence should not be reordered with any shared location accesses,
      // so we set these to true.
      parent.readsSharedMemory = true;
      parent.writesSharedMemory = true;
      parent.readsSharedMutableStruct = true;
      parent.writesSharedStruct = true;
      parent.readsSharedMutableArray = true;
      parent.writesSharedArray = true;
      parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;
    }
    void visitPause(Pause* curr) {
      // We don't want this to be moved out of loops, but it doesn't otherwises
      // matter much how it gets reordered. Say we transfer control as a coarse
      // approximation of this.
      parent.branchesOut = true;
    }
    void visitSIMDExtract(SIMDExtract* curr) {}
    void visitSIMDReplace(SIMDReplace* curr) {}
    void visitSIMDShuffle(SIMDShuffle* curr) {}
    void visitSIMDTernary(SIMDTernary* curr) {}
    void visitSIMDShift(SIMDShift* curr) {}
    void visitSIMDLoad(SIMDLoad* curr) {
      readsMemory(curr->memory, MemoryOrder::Unordered);
      parent.implicitTrap = true;
    }
    void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
      if (curr->isLoad()) {
        readsMemory(curr->memory, MemoryOrder::Unordered);
      } else {
        writesMemory(curr->memory, MemoryOrder::Unordered);
      }
      parent.implicitTrap = true;
    }
    void visitMemoryInit(MemoryInit* curr) {
      writesMemory(curr->memory, MemoryOrder::Unordered);
      parent.implicitTrap = true;
    }
    void visitDataDrop(DataDrop* curr) {
      // data.drop does not actually write memory, but it does alter the size of
      // a segment, which can be noticeable later by memory.init, so we need to
      // mark it as having a global side effect of some kind.
      parent.writesMemory = true;
      parent.implicitTrap = true;
    }
    void visitMemoryCopy(MemoryCopy* curr) {
      readsMemory(curr->sourceMemory, MemoryOrder::Unordered);
      writesMemory(curr->destMemory, MemoryOrder::Unordered);
      parent.implicitTrap = true;
    }
    void visitMemoryFill(MemoryFill* curr) {
      writesMemory(curr->memory, MemoryOrder::Unordered);
      parent.implicitTrap = true;
    }
    void visitConst(Const* curr) {}
    void visitUnary(Unary* curr) {
      switch (curr->op) {
        case TruncSFloat32ToInt32:
        case TruncSFloat32ToInt64:
        case TruncUFloat32ToInt32:
        case TruncUFloat32ToInt64:
        case TruncSFloat64ToInt32:
        case TruncSFloat64ToInt64:
        case TruncUFloat64ToInt32:
        case TruncUFloat64ToInt64: {
          parent.implicitTrap = true;
          break;
        }
        default: {
        }
      }
    }
    void visitBinary(Binary* curr) {
      switch (curr->op) {
        case DivSInt32:
        case DivUInt32:
        case RemSInt32:
        case RemUInt32:
        case DivSInt64:
        case DivUInt64:
        case RemSInt64:
        case RemUInt64: {
          // div and rem may contain implicit trap only if RHS is
          // non-constant or constant which equal zero or -1 for
          // signed divisions. Reminder traps only with zero
          // divider.
          if (auto* c = curr->right->dynCast<Const>()) {
            if (c->value.isZero()) {
              parent.implicitTrap = true;
            } else if ((curr->op == DivSInt32 || curr->op == DivSInt64) &&
                       c->value.getInteger() == -1LL) {
              parent.implicitTrap = true;
            }
          } else {
            parent.implicitTrap = true;
          }
          break;
        }
        default: {
        }
      }
    }
    void visitSelect(Select* curr) {}
    void visitDrop(Drop* curr) {}
    void visitReturn(Return* curr) { parent.branchesOut = true; }
    void visitMemorySize(MemorySize* curr) {
      // memory.size accesses the size of the memory, and thus can be modeled as
      // reading memory. When the memory is shared, this synchronizes with
      // memory.grow on other threads.
      readsMemory(curr->memory, MemoryOrder::SeqCst);
    }
    void visitMemoryGrow(MemoryGrow* curr) {
      // memory.grow technically does a read-modify-write operation on the
      // memory size in the successful case, modifying the set of valid
      // addresses, and just a read operation in the failure case. It
      // synchronizes with memory.size on other threads, but only when operating
      // on shared memories.
      readsMemory(curr->memory, MemoryOrder::SeqCst);
      writesMemory(curr->memory, MemoryOrder::SeqCst);
    }
    void visitRefNull(RefNull* curr) {}
    void visitRefIsNull(RefIsNull* curr) {}
    void visitRefFunc(RefFunc* curr) {}
    void visitRefEq(RefEq* curr) {}
    void visitTableGet(TableGet* curr) {
      parent.readsTable = true;
      parent.implicitTrap = true;
    }
    void visitTableSet(TableSet* curr) {
      parent.writesTable = true;
      parent.implicitTrap = true;
    }
    void visitTableSize(TableSize* curr) { parent.readsTable = true; }
    void visitTableGrow(TableGrow* curr) {
      // table.grow technically does a read-modify-write operation on the
      // table size in the successful case, modifying the set of valid
      // indices, and just a read operation in the failure case
      parent.readsTable = true;
      parent.writesTable = true;
    }
    void visitTableFill(TableFill* curr) {
      parent.writesTable = true;
      parent.implicitTrap = true;
    }
    void visitTableCopy(TableCopy* curr) {
      parent.readsTable = true;
      parent.writesTable = true;
      parent.implicitTrap = true;
    }
    void visitTableInit(TableInit* curr) {
      parent.writesTable = true;
      parent.implicitTrap = true;
    }
    void visitElemDrop(ElemDrop* curr) { parent.writesTable = true; }
    void visitTry(Try* curr) {
      if (curr->delegateTarget.is()) {
        parent.delegateTargets.insert(curr->delegateTarget);
      }
    }
    void visitTryTable(TryTable* curr) {
      for (auto name : curr->catchDests) {
        parent.breakTargets.insert(name);
      }
    }
    void visitThrow(Throw* curr) {
      if (parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
    void visitRethrow(Rethrow* curr) {
      if (parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
    void visitThrowRef(ThrowRef* curr) {
      if (trapOnNull(curr->exnref)) {
        return;
      }
      if (parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
    void visitNop(Nop* curr) {}
    void visitUnreachable(Unreachable* curr) { parent.trap = true; }
    void visitPop(Pop* curr) {
      if (parent.catchDepth == 0) {
        parent.danglingPop = true;
      }
    }
    void visitTupleMake(TupleMake* curr) {}
    void visitTupleExtract(TupleExtract* curr) {}
    void visitRefI31(RefI31* curr) {}
    void visitI31Get(I31Get* curr) { trapOnNull(curr->i31); }
    void visitCallRef(CallRef* curr) {
      if (trapOnNull(curr->target)) {
        return;
      }
      if (curr->isReturn) {
        parent.branchesOut = true;
        if (parent.features.hasExceptionHandling()) {
          parent.hasReturnCallThrow = true;
        }
      }
      parent.calls = true;
      if (parent.features.hasExceptionHandling() &&
          (parent.tryDepth == 0 && !curr->isReturn)) {
        parent.throws_ = true;
      }
    }
    void visitRefTest(RefTest* curr) {}

    void visitRefCast(RefCast* curr) {
      if (trapOnNull(curr->desc)) {
        return;
      }
      // Traps if the cast fails.
      parent.implicitTrap = true;
    }
    void visitRefGetDesc(RefGetDesc* curr) { trapOnNull(curr->ref); }
    void visitBrOn(BrOn* curr) {
      if (trapOnNull(curr->desc)) {
        return;
      }
      parent.breakTargets.insert(curr->name);
    }
    void visitStructNew(StructNew* curr) { trapOnNull(curr->desc); }
    void visitStructGet(StructGet* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      readsStruct(curr->ref->type.getHeapType(), curr->index, curr->order);
    }
    void visitStructSet(StructSet* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      writesStruct(curr->ref->type.getHeapType(), curr->index, curr->order);
    }
    template<typename StructRMWExpr>
    void visitStructRMWExpr(StructRMWExpr* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      auto heapType = curr->ref->type.getHeapType();
      readsStruct(heapType, curr->index, curr->order);
      writesStruct(heapType, curr->index, curr->order);
    }
    void visitStructRMW(StructRMW* curr) { visitStructRMWExpr(curr); }
    void visitStructCmpxchg(StructCmpxchg* curr) { visitStructRMWExpr(curr); }
    void visitStructWait(StructWait* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // StructWait doesn't strictly write a struct, but it does modify the
      // waiters list associated with the waitqueue field, which we can think
      // of as a write.
      parent.readsSharedMutableStruct = true;
      parent.writesSharedStruct = true;
      parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;

      // If the timeout is negative and no-one wakes us.
      parent.mayNotReturn = true;
    }
    void visitStructNotify(StructNotify* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Non-shared notifies just return 0.
      if (curr->ref->type.getHeapType().isShared()) {
        return;
      }
      // AtomicNotify doesn't strictly write the struct, but it does
      // modify the waiters list associated with the waitqueue field, which we
      // can think of as a write.
      parent.readsSharedMutableStruct = true;
      parent.writesSharedStruct = true;
      parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;
    }
    void visitArrayNew(ArrayNew* curr) {}
    void visitArrayNewData(ArrayNewData* curr) {
      // Traps on out of bounds access to segments or access to dropped
      // segments.
      parent.implicitTrap = true;
    }
    void visitArrayNewElem(ArrayNewElem* curr) {
      // Traps on out of bounds access to segments or access to dropped
      // segments.
      parent.implicitTrap = true;
    }
    void visitArrayNewFixed(ArrayNewFixed* curr) {}
    void visitArrayGet(ArrayGet* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      readsArray(curr->ref->type.getHeapType(), curr->order);
    }
    void visitArraySet(ArraySet* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      writesArray(curr->ref->type.getHeapType(), curr->order);
    }
    void visitArrayLoad(ArrayLoad* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      readsArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
    }

    void visitArrayStore(ArrayStore* curr) {
      if (curr->ref->type.isNull()) {
        parent.trap = true;
        return;
      }
      parent.writesArray = true;
      // traps when the arg is null or the index out of bounds
      parent.implicitTrap = true;
    }
    void visitArrayLen(ArrayLen* curr) {
      trapOnNull(curr->ref);
      // No need to model this as reading the array since the length cannot be
      // written, so there can be no conflicts.
    }

    void visitArrayCopy(ArrayCopy* curr) {
      if (trapOnNull({curr->srcRef, curr->destRef})) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      readsArray(curr->srcRef->type.getHeapType(), MemoryOrder::Unordered);
      writesArray(curr->destRef->type.getHeapType(), MemoryOrder::Unordered);
    }
    void visitArrayFill(ArrayFill* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      writesArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
    }
    template<typename ArrayInit> void visitArrayInit(ArrayInit* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      parent.writesArray = true;
      // OOB access to array or element segment.
      parent.implicitTrap = true;
      writesArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
    }
    void visitArrayInitData(ArrayInitData* curr) { visitArrayInit(curr); }
    void visitArrayInitElem(ArrayInitElem* curr) { visitArrayInit(curr); }
    template<typename ArrayRMWExpr> void visitArrayRMWExpr(ArrayRMWExpr* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // Null refs and OOB access.
      parent.implicitTrap = true;
      auto heapType = curr->ref->type.getHeapType();
      readsArray(heapType, curr->order);
      writesArray(heapType, curr->order);
    }
    void visitArrayRMW(ArrayRMW* curr) { visitArrayRMWExpr(curr); }
    void visitArrayCmpxchg(ArrayCmpxchg* curr) { visitArrayRMWExpr(curr); }
    void visitRefAs(RefAs* curr) {
      if (curr->op == AnyConvertExtern || curr->op == ExternConvertAny) {
        // These conversions are infallible.
        return;
      }
      assert(curr->op == RefAsNonNull);
      trapOnNull(curr->value);
    }
    void visitStringNew(StringNew* curr) {
      switch (curr->op) {
        case StringNewLossyUTF8Array:
        case StringNewWTF16Array:
          if (trapOnNull(curr->ref)) {
            return;
          }
          // OOB access to array.
          parent.implicitTrap = true;
          parent.readsMutableArray = true;
          return;
        case StringNewFromCodePoint:
          // Invalid code points.
          parent.implicitTrap = true;
          return;
      }
    }
    void visitStringConst(StringConst* curr) {}
    void visitStringMeasure(StringMeasure* curr) { trapOnNull(curr->ref); }
    void visitStringEncode(StringEncode* curr) {
      if (trapOnNull({curr->str, curr->array})) {
        return;
      }
      // OOB array access.
      parent.implicitTrap = true;
      parent.writesArray = true;
    }
    void visitStringConcat(StringConcat* curr) {
      trapOnNull({curr->left, curr->right});
    }
    void visitStringEq(StringEq* curr) {
      switch (curr->op) {
        case StringEqEqual:
          // Nulls are ok.
          return;
        case StringEqCompare:
          trapOnNull({curr->left, curr->right});
          return;
      }
    }
    void visitStringTest(StringTest* curr) {}
    void visitStringWTF16Get(StringWTF16Get* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // OOB string access.
      parent.implicitTrap = true;
    }
    void visitStringSliceWTF(StringSliceWTF* curr) {
      if (trapOnNull(curr->ref)) {
        return;
      }
      // OOB string access.
      parent.implicitTrap = true;
    }
    void visitContNew(ContNew* curr) { trapOnNull(curr->func); }
    void visitContBind(ContBind* curr) {
      if (trapOnNull(curr->cont)) {
        return;
      }
      // The input continuation is modified, as it will trap if resumed. This is
      // a globally-noticeable effect, which we model as a call for now, but we
      // could in theory use something more refined here (|modifiesContinuation|
      // perhaps, to parallel |writesMemory| etc.).
      parent.calls = true;
    }
    void visitSuspend(Suspend* curr) {
      // Similar to resume/call: Suspending means that we execute arbitrary
      // other code before we may resume here.
      parent.calls = true;
      if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
        parent.throws_ = true;
      }

      // A suspend may go unhandled and therefore trap.
      parent.implicitTrap = true;
    }
    void visitResume(Resume* curr) {
      if (trapOnNull(curr->cont)) {
        return;
      }
      // This acts as a kitchen sink effect.
      parent.calls = true;

      if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
    void visitResumeThrow(ResumeThrow* curr) {
      if (trapOnNull(curr->cont)) {
        return;
      }

      // This acts as a kitchen sink effect.
      parent.calls = true;

      if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
    void visitStackSwitch(StackSwitch* curr) {
      if (trapOnNull(curr->cont)) {
        return;
      }

      // This acts as a kitchen sink effect.
      parent.calls = true;

      if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) {
        parent.throws_ = true;
      }
    }
  };

public:
  // Helpers

  // See comment on orderedBefore() for the assumptions on the inputs here.
  // TODO: Update users so we can check just one direction here.
  static bool canReorder(const PassOptions& passOptions,
                         Module& module,
                         Expression* a,
                         Expression* b) {
    EffectAnalyzer aEffects(passOptions, module, a);
    EffectAnalyzer bEffects(passOptions, module, b);
    return !aEffects.orderedBefore(bEffects) &&
           !bEffects.orderedBefore(aEffects);
  }

  // C-API

  enum SideEffects : uint32_t {
    None = 0,
    Branches = 1 << 0,
    Calls = 1 << 1,
    ReadsLocal = 1 << 2,
    WritesLocal = 1 << 3,
    ReadsGlobal = 1 << 4,
    WritesGlobal = 1 << 5,
    ReadsMemory = 1 << 6,
    WritesMemory = 1 << 7,
    ReadsTable = 1 << 8,
    WritesTable = 1 << 9,
    ImplicitTrap = 1 << 10,
    IsAtomic = 1 << 11,
    Throws = 1 << 12,
    DanglingPop = 1 << 13,
    TrapsNeverHappen = 1 << 14,
    Any = (1 << 15) - 1
  };
  uint32_t getSideEffects() const {
    uint32_t effects = 0;
    if (branchesOut || hasExternalBreakTargets()) {
      effects |= SideEffects::Branches;
    }
    if (calls) {
      effects |= SideEffects::Calls;
    }
    if (localsRead.size() > 0) {
      effects |= SideEffects::ReadsLocal;
    }
    if (localsWritten.size() > 0) {
      effects |= SideEffects::WritesLocal;
    }
    if (mutableGlobalsRead.size()) {
      effects |= SideEffects::ReadsGlobal;
    }
    if (globalsWritten.size() > 0) {
      effects |= SideEffects::WritesGlobal;
    }
    // TODO: Expand the C API to handle shared locations, structs, and arrays.
    if (readsMemory || readsSharedMemory) {
      effects |= SideEffects::ReadsMemory;
    }
    if (writesMemory || writesSharedMemory) {
      effects |= SideEffects::WritesMemory;
    }
    if (readsTable) {
      effects |= SideEffects::ReadsTable;
    }
    if (writesTable) {
      effects |= SideEffects::WritesTable;
    }
    if (implicitTrap) {
      effects |= SideEffects::ImplicitTrap;
    }
    if (trapsNeverHappen) {
      effects |= SideEffects::TrapsNeverHappen;
    }
    // TODO: Expand the C API to handle memory orders.
    if (readOrder != MemoryOrder::Unordered ||
        writeOrder != MemoryOrder::Unordered) {
      effects |= SideEffects::IsAtomic;
    }
    if (throws_) {
      effects |= SideEffects::Throws;
    }
    if (danglingPop) {
      effects |= SideEffects::DanglingPop;
    }
    return effects;
  }

  // Ignores all forms of control flow transfers: breaks, returns, and
  // exceptions. (Note that traps are not considered relevant here - a trap does
  // not just transfer control flow, but can be seen as halting the entire
  // program.)
  //
  // This function matches transfersControlFlow(), that is, after calling this
  // method transfersControlFlow() will always return false.
  void ignoreControlFlowTransfers() {
    branchesOut = false;
    breakTargets.clear();
    throws_ = false;
    delegateTargets.clear();
    assert(!transfersControlFlow());
  }

private:
  void post() {
    assert(tryDepth == 0);

    if (ignoreImplicitTraps) {
      implicitTrap = false;
    } else if (implicitTrap) {
      trap = true;
    }
  }
};

// Calculate effects only on the node itself (shallowly), and not on
// children.
class ShallowEffectAnalyzer : public EffectAnalyzer {
public:
  ShallowEffectAnalyzer(const PassOptions& passOptions,
                        Module& module,
                        Expression* ast = nullptr)
    : EffectAnalyzer(passOptions, module) {
    if (ast) {
      visit(ast);
    }
  }
};

} // namespace wasm

namespace std {
std::ostream& operator<<(std::ostream& o, wasm::EffectAnalyzer& effects);
} // namespace std

#endif // wasm_ir_effects_h
