/*
 * Copyright 2026 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.
 */

//
// Simple multi-allocation escape analysis, aiming to cleanly separate multiple
// allocations written to a single local.
//
// This pass identifies a simple case of refs not escaping, like Heap2Local, but
// allows more than a single allocation (struct.new), which is better, and
// only handles a far simpler-to-identify situation, which is worse. To see the
// motivation, consider overlapping allocations like this:
//
//    x = new Foo(42);
//    if (condition) x = new Foo(1337);
//    else x.value = -1;
//    bar(x.value, x.value);
//
// Heap2Local cannot optimize this due to the overlapping live ranges (it sees
// some x.value operations are not exclusive to any single allocation). But this
// pass can optimize into this:
//
//    x_value = (new Foo(42)).value;
//    if (condition) x_value = (new Foo(1337)).value;
//    else x_value = -1;
//    bar(x_value, x_value);
//
// Note how we now operate on x_value, a new local with data. Basically, each
// struct.get/struct.set is turned into an operation on that new local. This is
// safe despite the multiple allocations because the local x is always used
// immediately, as data: rather than store a reference, we can just focus on the
// data. That is, each struct.new just writes a bunch of fields, and it all
// could have been unboxed. After verifying that nothing observes x as a
// reference (no ref.eq), and it does not escape, we can optimize this.
// Heap2Local will then see 'untangled' allocations, each one immediately
// consumed, and remove them all.
//
// Note that Heap2Local could safely optimize in this example, even before our
// changes: while the `x.value` operations are not exclusive to allocations, the
// live ranges of the allocations join exactly there - they do not overlap in a
// dangerous way. But here is an example MultiHeap2Local can optimize that
// Heap2Local cannot:
//
//   (local.set $a
//     (struct.new $struct
//       (..value..)
//     )
//   )
//   (struct.get $ref 0
//     (select
//       (local.get $a)
//       (local.tee $a
//         (struct.new_default $struct)
//       )
//       (..condition..)
//     )
//   )
//
// The struct.get at the end may read ..value.. from set at the top, or it may
// read the default value from the tee at the bottom. But here we cannot
// optimize while using a single local `a_value` because of the live range
// overlap: both allocations are alive as the select executes, and it picks
// between them, so we must store both of them somewhere in the interim.
// Detecting such overlaps is not trivial as it involves locals as well as the
// wasm value stack, which is why this pass is useful, as it handles common and
// obviously-optimizable cases.
//

#include "ir/bits.h"
#include "ir/find_all.h"
#include "ir/local-graph.h"
#include "ir/properties.h"
#include "pass.h"
#include "wasm-builder.h"
#include "wasm-traversal.h"
#include "wasm.h"

namespace wasm {

namespace {

struct MultiHeap2Local : public WalkerPass<PostWalker<MultiHeap2Local>> {
  bool isFunctionParallel() override { return true; }

  std::unique_ptr<Pass> create() override {
    return std::make_unique<MultiHeap2Local>();
  }

  // Information about a local index, used to decide whether we can optimize.
  struct LocalInfo {
    // The number of gets for the local, tracked so that we can see if all the
    // local.gets are consumed by struct.get/sets.
    Index numGets = 0;

    // The number of sets for the local, tracked as we only optimize when we see
    // 2 or more local.sets (a single one is trivially optimized by Heap2Local,
    // so we would be doing pointless work).
    Index numSets = 0;

    // The number of tees for the local, tracked for the same reason as gets:
    // they flow out the reference, so we must see them consumed by struct
    // gets/sets.
    Index numTees = 0;

    // All struct.get/struct.set operations that read a get/tee of this local.
    std::vector<Expression*> structOperations;

    // Certain conditions prevent us from optimizing.
    bool unoptimizable = false;
  };

  // For each local index, its info.
  std::vector<LocalInfo> localInfos;

  // Checks if a local index is relevant for us: if it refers to a struct.
  bool isStructLocal(Index index) {
    auto type = getFunction()->getLocalType(index);
    return type.isRef() && type.getHeapType().isStruct();
  }

  void visitLocalGet(LocalGet* curr) {
    if (isStructLocal(curr->index)) {
      localInfos[curr->index].numGets++;
    }
  }

  void visitLocalSet(LocalSet* curr) {
    if (isStructLocal(curr->index)) {
      localInfos[curr->index].numSets++;
      if (curr->isTee()) {
        localInfos[curr->index].numTees++;
      }
      // All sets must write a struct.new, otherwise we cannot analyze this
      // local.
      if (!curr->value->is<StructNew>()) {
        localInfos[curr->index].unoptimizable = true;
      }
    }
  }

  void visitStructGet(StructGet* curr) { handleStructOperation(curr); }
  void visitStructSet(StructSet* curr) { handleStructOperation(curr); }

  template<typename T> void handleStructOperation(T* curr) {
    // Avoid unreachable code.
    if (curr->type == Type::unreachable) {
      return;
    }

    // See if the reference is one of the patterns we recognize.
    // TODO fallthrough, but careful of br_if which can escape the value
    if (auto* get = curr->ref->template dynCast<LocalGet>()) {
      localInfos[get->index].structOperations.push_back(curr);

      // Also handle the value for a struct.set: a struct.set has two inputs,
      // and if the value modifies the local, then two allocations can be
      // live at once:
      //
      //   (struct.set
      //     (local.get $x)
      //     (block
      //       (local.set $x ..)
      //       ..
      //
      // Here $x is put on the value stack, but then we write something new into
      // $x before the struct.set, which means the struct.set is writing to the
      // old allocation - one that no struct.get will later read. When we see
      // such live range overlaps, give up.
      if (auto* structSet = curr->template dynCast<StructSet>()) {
        for (auto* localSet : FindAll<LocalSet>(structSet->value).list) {
          if (localSet->index == get->index) {
            localInfos[get->index].unoptimizable = true;
            break;
          }
        }
      }
    } else if (auto* tee = curr->ref->template dynCast<LocalSet>()) {
      // TODO: Handle a tee for struct.set. This is a little complex to handle
      // below, and not really needed, since
      //
      //   (struct.set $A k
      //     (local.tee
      //       (struct.new $A ..)
      //     )
      //     (value)
      //   )
      //
      // can be folded into a single struct.new (that is, we are writing all the
      // fields, then writing an additional one, and other passes make us do
      // them all at once anyhow).
      if (curr->template is<StructSet>()) {
        localInfos[tee->index].unoptimizable = true;
      } else {
        // Otherwise, this is a valid struct operation.
        localInfos[tee->index].structOperations.push_back(curr);
      }
    }
    // TODO: handle more things flowing into struct.get, like an If
  }

  void doWalkFunction(Function* func) {
    localInfos.resize(func->getNumLocals());

    WalkerPass<PostWalker<MultiHeap2Local>>::doWalkFunction(func);

    pickLocalsToOptimize(func);

    if (!optimizedLocals.empty()) {
      optimize(func);
    }
  }

  // For each optimized local, maps each used field index to the new local
  // index that stores that field. Note that the inner map is sorted, both for
  // deterministic ordering when we create new locals, and also because the
  // number of used fields tends to be small (so hashing is overkill).
  std::unordered_map<Index, std::map<Index, Index>> optimizedLocals;

  void pickLocalsToOptimize(Function* func) {
    auto* module = getModule();
    Builder builder(*module);
    LazyLocalGraph localGraph(func, module);

    for (Index localIndex = 0; localIndex < localInfos.size(); ++localIndex) {
      auto& info = localInfos[localIndex];
      if (info.unoptimizable) {
        continue;
      }

      if (info.numSets < 2) {
        // We only care about the case of 2 or more sets for a local: otherwise,
        // Heap2Local can handle things perfectly for a single set.
        continue;
      }

      // Check if each local.get is consumed by a struct.get/set, which is the
      // case if the counts match: the sum of local.gets/local.tees (things
      // that flow out the reference) must match the number of struct.gets/sets
      // (things that consume the reference).
      if (info.numGets + info.numTees != info.structOperations.size()) {
        continue;
      }

      // Finally, if the initial value of the local from the function entry is
      // used, do not optimize. For a var, that means the default of zero, which
      // will trap when accessed, while for params it means an unknown value. We
      // therefore must always check for params, but for vars, if we know the
      // default cannot be accessed, we can skip this (which is the case for
      // a non-nullable local, and if trapsNeverHappen as a trap on the null
      // default can be ignored).
      auto localType = func->getLocalType(localIndex);
      auto canReadDefault =
        localType.isNullableRef() && !getPassOptions().trapsNeverHappen;
      if (func->isParam(localIndex) || canReadDefault) {
        bool ok = true;
        for (auto* op : info.structOperations) {
          Expression* ref;
          if (auto* get = op->dynCast<StructGet>()) {
            ref = get->ref;
          } else if (auto* set = op->dynCast<StructSet>()) {
            ref = set->ref;
          } else {
            WASM_UNREACHABLE("bad op");
          }
          if (auto* get = ref->dynCast<LocalGet>()) {
            if (localGraph.getSets(get).contains(nullptr)) {
              ok = false;
              break;
            }
          }
        }
        if (!ok) {
          continue;
        }
      }

      // We can optimize!

      // Gather all the struct field indexes operated on from this local.
      std::set<Index> usedFields;
      for (auto* op : info.structOperations) {
        usedFields.insert(getFieldIndex(op));
      }

      // Allocate new locals to store each field.
      auto& fields = localType.getHeapType().getStruct().fields;
      for (auto fieldIndex : usedFields) {
        optimizedLocals[localIndex][fieldIndex] =
          builder.addVar(func, fields[fieldIndex].type);
      }
    }
  }

  void optimize(Function* func) {
    struct Optimizer : PostWalker<Optimizer> {
      MultiHeap2Local& parent;

      Optimizer(MultiHeap2Local& parent) : parent(parent) {}

      void visitLocalSet(LocalSet* curr) {
        if (!curr->isTee() && parent.optimizedLocals.contains(curr->index)) {
          // local.set now stores the used fields (tee is handled below).
          replaceCurrent(makeFieldSets(curr));
        }
      }

      void visitStructGet(StructGet* curr) {
        if (auto* get = curr->ref->dynCast<LocalGet>()) {
          if (parent.optimizedLocals.contains(get->index)) {
            // struct.get of a local.get reads the field from a new local.
            replaceCurrent(
              getFieldFromLocal(get->index, curr->index, curr->signed_));
          }
        } else if (auto* tee = curr->ref->dynCast<LocalSet>()) {
          if (parent.optimizedLocals.contains(tee->index)) {
            // struct.get of a local.tee first writes the fields, then reads.
            replaceCurrent(makeFieldSets(tee, curr));
          }
        }
      }

      void visitStructSet(StructSet* curr) {
        if (auto* get = curr->ref->dynCast<LocalGet>()) {
          if (parent.optimizedLocals.contains(get->index)) {
            // struct.set of a local.get writes the field into a new local.
            replaceCurrent(
              setFieldToLocal(get->index, curr->index, curr->value));
          }
        }
      }

      Expression*
      getFieldFromLocal(Index localIndex, Index fieldIndex, bool signed_) {
        auto& field = getFunction()
                        ->getLocalType(localIndex)
                        .getHeapType()
                        .getStruct()
                        .fields[fieldIndex];
        // Read from the appropriate new local, handling sign extension as
        // needed.
        auto newLocal = parent.optimizedLocals[localIndex][fieldIndex];
        Builder builder(*getModule());
        Expression* ret =
          builder.makeLocalGet(newLocal, getFunction()->getLocalType(newLocal));
        return Bits::makePackedFieldGet(ret, field, signed_, *getModule());
      }

      Expression*
      setFieldToLocal(Index localIndex, Index fieldIndex, Expression* value) {
        // Write to the appropriate new local.
        auto newLocal = parent.optimizedLocals[localIndex][fieldIndex];
        Builder builder(*getModule());
        return builder.makeLocalSet(newLocal, value);
      }

      Expression* makeFieldSets(LocalSet* set, StructGet* teeParent = nullptr) {
        auto localIndex = set->index;
        auto localType = getFunction()->getLocalType(localIndex);
        auto& fields = localType.getHeapType().getStruct().fields;

        // Store the reference, then store struct.gets of all used fields in the
        // new locals.
        Builder builder(*getModule());
        std::vector<Expression*> list = {
          builder.makeLocalSet(localIndex, set->value)};
        for (auto [fieldIndex, newLocal] : parent.optimizedLocals[localIndex]) {
          auto& field = fields[fieldIndex];
          // Note that the sign does not matter here: we just store the bits,
          // and will handle the sign when reading back out (like in
          // Heap2Local).
          auto* sget =
            builder.makeStructGet(fieldIndex,
                                  builder.makeLocalGet(localIndex, localType),
                                  MemoryOrder::Unordered,
                                  field.type,
                                  false);
          list.push_back(builder.makeLocalSet(newLocal, sget));
        }

        // Finally, if this is a tee, then it was consumed by a struct.get, and
        // we can read that field and return it.
        if (teeParent) {
          list.push_back(getFieldFromLocal(
            localIndex, teeParent->index, teeParent->signed_));
        }
        return builder.makeBlock(list);
      }
    } optimizer(*this);
    optimizer.setModule(getModule());
    optimizer.walkFunction(func);
  }

  // Given a struct.get or struct.set, return the field index.
  Index getFieldIndex(Expression* curr) {
    if (auto* get = curr->dynCast<StructGet>()) {
      return get->index;
    } else if (auto* set = curr->dynCast<StructSet>()) {
      return set->index;
    } else {
      WASM_UNREACHABLE("bad op");
    }
  }
};

} // anonymous namespace

Pass* createMultiHeap2LocalPass() { return new MultiHeap2Local(); }

} // namespace wasm
