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

//
// Find struct fields that are always written to with a constant value, and
// replace gets of them with that value.
//
// For example, if we have a vtable of type T, and we always create it with one
// of the fields containing a ref.func of the same function F, and there is no
// write to that field of a different value (even using a subtype of T), then
// anywhere we see a get of that field we can place a ref.func of F.
//
// A variation of this pass also uses ref.test to optimize. This is riskier, as
// adding a ref.test means we are adding a non-trivial amount of work, and
// whether it helps overall depends on subsequent optimizations, so we do not do
// it by default. In this variation, if we inferred a field has exactly two
// possible values, and we can differentiate between them using a ref.test, then
// we do
//
//   (struct.get $T x (..ref..))
//     =>
//   (select
//     (..constant1..)
//     (..constant2..)
//     (ref.test $U (..ref..))
//   )
//
// This is valid if, of all the subtypes of $T, those that pass the test have
// constant1 in that field, and those that fail the test have constant2. For
// example, a simple case is where $T has two subtypes, $T is never created
// itself, and each of the two subtypes has a different constant value. (Note
// that we do similar things in e.g. GlobalStructInference, where we turn a
// struct.get into a select, but the risk there is much lower since the
// condition for the select is something like a ref.eq - very cheap - while here
// we emit a ref.test which in general is as expensive as a cast.)
//
// FIXME: This pass assumes a closed world. When we start to allow multi-module
//        wasm GC programs we need to check for type escaping.
//

#include <unordered_set>

#include "ir/bits.h"
#include "ir/gc-type-utils.h"
#include "ir/possible-constant.h"
#include "ir/struct-utils.h"
#include "ir/utils.h"
#include "pass.h"
#include "support/hash.h"
#include "support/small_vector.h"
#include "support/unique_deferring_queue.h"
#include "wasm-builder.h"
#include "wasm-traversal.h"
#include "wasm.h"

namespace wasm {

namespace {

// The destination reference type and field index of a copy, as well as whether
// the copy read is signed (in the case of packed fields). This will be used to
// propagate copied values from their sources to destinations in the analysis.
struct CopyInfo {
  HeapType type;
  Exactness exact;
  Index index;
  bool isSigned;

  bool operator==(const CopyInfo& other) const {
    return type == other.type && exact == other.exact && index == other.index &&
           isSigned == other.isSigned;
  }
};

} // anonymous namespace

} // namespace wasm

namespace std {

template<> struct hash<wasm::CopyInfo> {
  size_t operator()(const wasm::CopyInfo& copy) const {
    auto digest = wasm::hash(copy.type);
    wasm::rehash(digest, copy.exact);
    wasm::rehash(digest, copy.index);
    wasm::rehash(digest, copy.isSigned);
    return digest;
  }
};

} // namespace std

namespace wasm {

namespace {

using PCVStructValuesMap = StructUtils::StructValuesMap<PossibleConstantValues>;
using PCVFunctionStructValuesMap =
  StructUtils::FunctionStructValuesMap<PossibleConstantValues>;

using BoolStructValuesMap =
  StructUtils::StructValuesMap<StructUtils::CombinableBool>;
using BoolFunctionStructValuesMap =
  StructUtils::FunctionStructValuesMap<StructUtils::CombinableBool>;

using StructFieldPairs =
  std::unordered_set<std::pair<StructField, StructField>>;

// TODO: Deduplicate with Lattice infrastructure.
template<typename T> struct CombinableSet : std::unordered_set<T> {
  bool combine(const CombinableSet<T>& other) {
    auto originalSize = this->size();
    this->insert(other.begin(), other.end());
    return this->size() != originalSize;
  }
};

// For each field, the set of fields it is copied to.
using CopiesStructValuesMap =
  StructUtils::StructValuesMap<CombinableSet<CopyInfo>>;

using CopiesFunctionStructValuesMap =
  StructUtils::FunctionStructValuesMap<CombinableSet<CopyInfo>>;

// Optimize struct gets based on what we've learned about writes.
//
// TODO Aside from writes, we could use information like whether any struct of
//      this type has even been created (to handle the case of struct.sets but
//      no struct.news).
struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
  bool isFunctionParallel() override { return true; }

  // Only modifies struct.get operations.
  bool requiresNonNullableLocalFixups() override { return false; }

  // We receive the propagated infos, that is, info about field types in a form
  // that takes into account subtypes for quick computation, and also the raw
  // subtyping and new infos (information about struct.news).
  std::unique_ptr<Pass> create() override {
    return std::make_unique<FunctionOptimizer>(
      propagatedInfos, refTestInfos, subTypes, refTest);
  }

  FunctionOptimizer(const PCVStructValuesMap& propagatedInfos,
                    const PCVStructValuesMap& refTestInfos,
                    const SubTypes& subTypes,
                    bool refTest)
    : propagatedInfos(propagatedInfos), refTestInfos(refTestInfos),
      subTypes(subTypes), refTest(refTest) {}

  template<typename T> std::optional<HeapType> getRelevantHeapType(T* ref) {
    auto type = ref->type;
    if (type == Type::unreachable) {
      return std::nullopt;
    }
    auto heapType = type.getHeapType();
    if (!heapType.isStruct()) {
      return std::nullopt;
    }
    return heapType;
  }

  PossibleConstantValues getInfo(HeapType type, Index index, Exactness exact) {
    if (auto it = propagatedInfos.find({type, exact});
        it != propagatedInfos.end()) {
      // There is information on this type, fetch it.
      return it->second[index];
    }
    return PossibleConstantValues{};
  }

  // Given information about a constant value, and the struct type and
  // StructGet/RMW/Cmpxchg that reads it, create an expression for that value.
  Expression* makeExpression(const PossibleConstantValues& info,
                             HeapType type,
                             Expression* curr) {
    auto* value = info.makeExpression(*getModule());
    if (auto* structGet = curr->dynCast<StructGet>()) {
      auto field = GCTypeUtils::getField(type, structGet->index);
      assert(field);
      // Apply packing, if needed.
      value = Bits::makePackedFieldGet(
        value, *field, structGet->signed_, *getModule());
      // Check if the value makes sense. The analysis below flows values around
      // without considering where they are placed, that is, when we see a
      // parent type can contain a value in a field then we assume a child may
      // as well (which in general it can, e.g., using a reference to the
      // parent, we can write that value to it, but the reference might actually
      // point to a child instance). If we tracked the types of fields then we
      // might avoid flowing values into places they cannot reside, like when a
      // child field is a subtype, and so we could ignore things not refined
      // enough for it (GUFA does a better job at this). For here, just check we
      // do not break validation, and if we do, then we've inferred the only
      // possible value is an impossible one, making the code unreachable.
      if (!Type::isSubType(value->type, field->type)) {
        Builder builder(*getModule());
        value = builder.makeSequence(builder.makeDrop(value),
                                     builder.makeUnreachable());
      }
    }
    return value;
  }

  void visitStructGet(StructGet* curr) {
    optimizeRead(curr, curr->ref, curr->index, curr->order);
  }

  void visitRefGetDesc(RefGetDesc* curr) {
    optimizeRead(curr, curr->ref, StructUtils::DescriptorIndex);

    // RefGetDesc has the interesting property that we can write a value into
    // the field that cannot be read from it: it is valid to write a null, but
    // a null can never be read (it would have trapped on the write). Fix that
    // up as needed to not break validation.
    if (!Type::isSubType(getCurrent()->type, curr->type)) {
      Builder builder(*getModule());
      replaceCurrent(builder.makeRefAs(RefAsNonNull, getCurrent()));
    }
  }

  void optimizeRead(Expression* curr,
                    Expression* ref,
                    Index index,
                    std::optional<MemoryOrder> order = std::nullopt) {
    auto type = getRelevantHeapType(ref);
    if (!type) {
      return;
    }
    auto heapType = *type;

    Builder builder(*getModule());

    // Find the info for this field, and see if we can optimize. First, see if
    // there is any information for this heap type at all. If there isn't, it is
    // as if nothing was ever noted for that field.
    PossibleConstantValues info =
      getInfo(heapType, index, ref->type.getExactness());
    if (!info.hasNoted()) {
      // This field is never written at all. That means that we do not even
      // construct any data of this type, and so it is a logic error to reach
      // this location in the code. (Unless we are in an open-world situation,
      // which we assume we are not in.) Replace this get with a trap. Note that
      // we do not need to care about the nullability of the reference, as if it
      // should have trapped, we are replacing it with another trap, which we
      // allow to reorder (but we do need to care about side effects in the
      // reference, so keep it around). We also do not need to care about
      // synchronization since trapping accesses do not synchronize with other
      // accesses.
      replaceCurrent(
        builder.makeSequence(builder.makeDrop(ref), builder.makeUnreachable()));
      changed = true;
      return;
    }

    if (order && *order != MemoryOrder::Unordered) {
      // The analysis we're basing the optimization on is not precise enough to
      // rule out the field being used to synchronize between a write of the
      // constant value and a subsequent read on another thread. This
      // synchronization is possible even when the write does not change the
      // value of the field. For now, simply avoid optimizing this case.
      // TODO: Track release and acquire operations in the analysis.
      return;
    }

    // If the value is not a constant, then it is unknown and we must give up
    // on simply applying a constant. However, we can try to use a ref.test, if
    // that is allowed.
    if (!info.isConstant()) {
      // Note that if the reference is exact, we never need to use a ref.test
      // because there will not be multiple subtypes to select between.
      if (refTest && !ref->type.isExact()) {
        optimizeUsingRefTest(curr, ref, index);
      }
      return;
    }

    // We can do this! Replace the get with a trap on a null reference using a
    // ref.as_non_null (we need to trap as the get would have done so), plus the
    // constant value. (Leave it to further optimizations to get rid of the
    // ref.)
    auto* value = makeExpression(info, heapType, curr);
    auto* replacement =
      builder.blockify(builder.makeDrop(builder.makeRefAs(RefAsNonNull, ref)));
    replacement->list.push_back(value);
    replacement->type = value->type;
    replaceCurrent(replacement);
    changed = true;
  }

  void optimizeUsingRefTest(Expression* curr, Expression* ref, Index index) {
    auto refType = ref->type;
    auto refHeapType = refType.getHeapType();

    // We seek two possible constant values. For each we track the constant and
    // the types that have that constant. For example, if we have types A, B, C
    // and A and B have 42 in their field, and C has 1337, then we'd have this:
    //
    //  values = [ { 42, [A, B] }, { 1337, [C] } ];
    struct Value {
      PossibleConstantValues constant;
      // Use a SmallVector as we'll only have 2 Values, and so the stack usage
      // here is fixed.
      SmallVector<HeapType, 10> types;

      // Whether this slot is used. If so, |constant| has a value, and |types|
      // is not empty.
      bool used() const {
        if (constant.hasNoted()) {
          assert(!types.empty());
          return true;
        }
        assert(types.empty());
        return false;
      }
    } values[2];

    // Handle one of the subtypes of the relevant type. We check what value it
    // has for the field, and update |values|. If we hit a problem, we stop
    // early.
    auto handleType = [&](HeapType type, Index depth) {
      auto iter = refTestInfos.find({type, Exact});
      if (iter == refTestInfos.end()) {
        // This type has no allocations, so we can ignore it: it is abstract.
        return true;
      }

      auto value = iter->second[index];
      if (!value.hasNoted()) {
        // Also abstract and ignorable.
        return true;
      }
      if (!value.isConstant()) {
        // The value here is not constant, so give up entirely.
        return false;
      }

      // Consider the constant value compared to previous ones.
      for (Index i = 0; i < 2; i++) {
        if (!values[i].used()) {
          // There is nothing in this slot: place this value there.
          values[i].constant = value;
          values[i].types.push_back(type);
          break;
        }

        // There is something in this slot. If we have the same value, append.
        if (values[i].constant == value) {
          values[i].types.push_back(type);
          break;
        }

        // Otherwise, this value is different than values[i], which is fine:
        // we can add it as the second value in the next loop iteration - at
        // least, we can do that if there is another iteration: If it's already
        // the last, we've failed to find only two values.
        if (i == 1) {
          return false;
        }
      }

      return true;
    };

    // If we stopped early, we hit a problem and failed.
    if (!subTypes.iterSubTypes(refHeapType, handleType)) {
      return;
    }

    // We either filled slot 0, or we did not, and if we did not then cannot
    // have filled slot 1 after it.
    assert(values[0].used() || !values[1].used());

    if (!values[1].used()) {
      // We did not see two constant values (we might have seen just one, or
      // even no constant values at all).
      return;
    }

    // We have exactly two values to pick between. We can pick between those
    // values using a single ref.test if the two sets of types are actually
    // disjoint. In general we could compute the LUB of each set and see if it
    // overlaps with the other, but for efficiency we only want to do this
    // optimization if the type we test on is closed/final, since ref.test on a
    // final type can be fairly fast (perhaps constant time). We therefore look
    // if one of the sets of types contains a single type and it is final, and
    // if so then we'll test on it. (However, see a few lines below on how we
    // test for finality.)
    // TODO: Consider adding a variation on this pass that uses non-final types.
    auto isProperTestType = [&](const Value& value) -> std::optional<HeapType> {
      auto& types = value.types;
      if (types.size() != 1) {
        // Too many types.
        return {};
      }

      auto type = types[0];
      // Do not test finality using isOpen(), as that may only be applied late
      // in the optimization pipeline. We are in closed-world here, so just
      // see if there are subtypes in practice (if not, this can be marked as
      // final later, and we assume optimistically that it will).
      if (!subTypes.getImmediateSubTypes(type).empty()) {
        // There are subtypes.
        return {};
      }

      // Success, we can test on this.
      return type;
    };

    // Look for the index in |values| to test on.
    Index testIndex;
    if (auto test = isProperTestType(values[0])) {
      testIndex = 0;
    } else if (auto test = isProperTestType(values[1])) {
      testIndex = 1;
    } else {
      // We failed to find a simple way to separate the types.
      return;
    }

    // Success! We can replace the struct.get with a select over the two values
    // (and a trap on null) with the proper ref.test.
    Builder builder(*getModule());

    auto& testIndexTypes = values[testIndex].types;
    assert(testIndexTypes.size() == 1);
    auto testType = testIndexTypes[0];

    auto* nnRef = builder.makeRefAs(RefAsNonNull, ref);

    replaceCurrent(builder.makeSelect(
      builder.makeRefTest(nnRef, Type(testType, NonNullable)),
      makeExpression(values[testIndex].constant, refHeapType, curr),
      makeExpression(values[1 - testIndex].constant, refHeapType, curr)));

    changed = true;
  }

  void doWalkFunction(Function* func) {
    WalkerPass<PostWalker<FunctionOptimizer>>::doWalkFunction(func);

    // If we changed anything, we need to update parent types as types may have
    // changed.
    if (changed) {
      ReFinalize().walkFunctionInModule(func, getModule());
    }
  }

private:
  const PCVStructValuesMap& propagatedInfos;
  const PCVStructValuesMap& refTestInfos;
  const SubTypes& subTypes;
  const bool refTest;

  bool changed = false;
};

struct PCVScanner
  : public StructUtils::StructScanner<PossibleConstantValues, PCVScanner> {
  std::unique_ptr<Pass> create() override {
    return std::make_unique<PCVScanner>(
      functionNewInfos, functionSetGetInfos, functionCopyInfos);
  }

  PCVScanner(PCVFunctionStructValuesMap& functionNewInfos,
             PCVFunctionStructValuesMap& functionSetInfos,
             CopiesFunctionStructValuesMap& functionCopyInfos)
    : StructUtils::StructScanner<PossibleConstantValues, PCVScanner>(
        functionNewInfos, functionSetInfos),
      functionCopyInfos(functionCopyInfos) {}

  void noteExpression(Expression* expr,
                      HeapType type,
                      Index index,
                      PossibleConstantValues& info) {
    info.note(expr, *getModule());
    // TODO: For descriptors we can ignore nullable values that are written, as
    //       they trap. That is, if one place writes a null and another writes a
    //       global, only the global is readable, and we can optimize there -
    //       the null is not a second value.
  }

  void noteDefault(Type fieldType,
                   HeapType type,
                   Index index,
                   PossibleConstantValues& info) {
    info.note(Literal::makeZero(fieldType));
  }

  void noteCopy(StructGet* get,
                Type dstType,
                Index dstIndex,
                PossibleConstantValues& dstInfo) {
    auto srcType = get->ref->type.getHeapType();
    auto srcExact = get->ref->type.getExactness();
    auto srcIndex = get->index;
    functionCopyInfos[getFunction()][{srcType, srcExact}][srcIndex].insert(
      {dstType.getHeapType(), dstType.getExactness(), dstIndex, get->signed_});
  }

  void noteRead(HeapType type, Index index, PossibleConstantValues& info) {
    // Reads do not interest us.
  }

  void noteRMW(Expression* expr,
               HeapType type,
               Index index,
               PossibleConstantValues& info) {
    // In general RMWs will modify the value of the field, so there is no single
    // constant value. We could in principle try to recognize no-op RMWs like
    // adds of 0, but we leave that for OptimizeInstructions for simplicity.
    info.noteUnknown();
  }

  CopiesFunctionStructValuesMap& functionCopyInfos;
};

struct ConstantFieldPropagation : public Pass {
  // Only modifies struct.get operations.
  bool requiresNonNullableLocalFixups() override { return false; }

  // Whether we are optimizing using ref.test, see above.
  const bool refTest;

  ConstantFieldPropagation(bool refTest) : refTest(refTest) {}

  void run(Module* module) override {
    if (!module->features.hasGC()) {
      return;
    }

    if (!getPassOptions().closedWorld) {
      Fatal() << "CFP requires --closed-world";
    }

    // Find and analyze all writes inside each function.
    PCVFunctionStructValuesMap functionNewInfos(*module),
      functionSetInfos(*module);
    CopiesFunctionStructValuesMap functionCopyInfos(*module);
    PCVScanner scanner(functionNewInfos, functionSetInfos, functionCopyInfos);
    auto* runner = getPassRunner();
    scanner.run(runner, module);
    scanner.runOnModuleCode(runner, module);

    // Combine the data from the functions.
    PCVStructValuesMap combinedSetInfos;
    functionNewInfos.combineInto(combinedSetInfos);
    functionSetInfos.combineInto(combinedSetInfos);
    CopiesStructValuesMap combinedCopyInfos;
    functionCopyInfos.combineInto(combinedCopyInfos);

    // Perform an analysis to compute the readable values for each triple of
    // heap type, exactness, and field index. The readable values are
    // determined by the written values and copies.
    //
    // Whenever we have a write like this:
    //
    //   (struct.set $super x (... ref ...) (... value ...))
    //
    // The dynamic type of the struct we are writing to may be any subtype of
    // the type of the ref. For example, if the ref has type (ref $super),
    // then the write may go to an object of type (ref $super) or (ref $sub).
    // In contrast, if the ref has an exact type, then we know the write
    // cannot go to an object of type (ref $sub), which is not a subtype of
    // (ref (exact $super)). The set of values that may have been written to a
    // field is therefore the join of all the values we observe being written
    // to that field in all supertypes of the written reference. The written
    // values are propagated down to subtypes.
    //
    // Similarly, whenever we have a read like this:
    //
    //   (struct.get $super x (... ref ...))
    //
    // The dynamic type of the struct we are reading from may be any subtype
    // of the type of the ref. The set of values that we might read from a
    // field is therefore the join of all the values that may have been
    // written to that field in all subtypes of the read reference. The read
    // values are propagated up to supertypes.
    //
    // Copies are interesting because they invert the normal dependence of
    // readable values on written values. A copy is a write of a read, so the
    // writable values depends on the readable values. Because of this cyclic
    // dependency, we must iteratively update our knowledge of the written and
    // readable values until we reach a fixed point.
    SubTypes subTypes(*module);
    StructUtils::TypeHierarchyPropagator<PossibleConstantValues> propagator(
      subTypes);

    PCVStructValuesMap written = std::move(combinedSetInfos);
    propagator.propagateToSubTypes(written);
    PCVStructValuesMap readable = written;
    propagator.propagateToSuperTypes(readable);

    // Now apply copies and propagate the new information until we have a
    // fixed point. We could just join the copied values into `written`,
    // propagate all of `written` down again, and recompute `readable`,
    // but that would do more work than necessary since most fields are not
    // going to be involved in copies. We will handle the propagation manually
    // instead.
    //
    // Since the analysis records untruncated values for packed fields, we must
    // be careful to truncate and sign extend copy source values as necessary.
    // We generally don't truncate values based on their destination because
    // that would regress propagation of globals when they are not copied.
    // TODO: Track truncations in the analysis itself to propagate them through
    // copies, even of globals.
    UniqueDeferredQueue<CopyInfo> work;
    auto applyCopiesTo = [&](auto& dsts, const Field& src, const auto& val) {
      for (auto& dst : dsts) {
        auto packed = val;
        packed.packForField(src, dst.isSigned);
        if (written[{dst.type, dst.exact}][dst.index].combine(packed)) {
          work.push(dst);
        }
      }
    };
    auto applyCopiesFrom =
      [&](HeapType src, Exactness exact, Index index, const auto& val) {
        if (auto it = combinedCopyInfos.find({src, exact});
            it != combinedCopyInfos.end()) {
          const auto& srcField = src.getStruct().fields[index];
          applyCopiesTo(it->second[index], srcField, val);
        }
      };
    // For each copy, take the readable values at its source and join them to
    // the written values at its destination. Record the written values that
    // change so we can propagate the new information afterward.
    for (auto& [src, fields] : combinedCopyInfos) {
      auto [srcType, srcExact] = src;
      for (Index srcField = 0; srcField < fields.size(); ++srcField) {
        const auto& field = srcType.getStruct().fields[srcField];
        applyCopiesTo(fields[srcField], field, readable[src][srcField]);
      }
    }
    while (work.size()) {
      // Propagate down from dst in both written and readable, then
      // propagate up from dst in readable only. Whenever we make a change in
      // readable, see if there are copies to apply. If there are copies and
      // they make changes, then we have more propagation work to do later.
      auto dst = work.pop();
      assert(dst.index != StructUtils::DescriptorIndex);
      auto val = written[{dst.type, dst.exact}][dst.index];
      val.packForField(dst.type.getStruct().fields[dst.index]);
      // Make the copied value readable.
      if (readable[{dst.type, dst.exact}][dst.index].combine(val)) {
        applyCopiesFrom(dst.type, dst.exact, dst.index, val);
      }
      if (dst.exact == Inexact) {
        // Propagate down to subtypes.
        written[{dst.type, Exact}][dst.index].combine(val);
        subTypes.iterSubTypes(dst.type, [&](HeapType sub, Index depth) {
          written[{sub, Inexact}][dst.index].combine(val);
          written[{sub, Exact}][dst.index].combine(val);
          if (readable[{sub, Inexact}][dst.index].combine(val)) {
            applyCopiesFrom(sub, Inexact, dst.index, val);
          }
          if (readable[{sub, Exact}][dst.index].combine(val)) {
            applyCopiesFrom(sub, Exact, dst.index, val);
          }
          return true;
        });
      } else {
        // The copy destination is exact, so there are no subtypes to
        // propagate to, but we do need to propagate up to the inexact type.
        if (readable[{dst.type, Inexact}][dst.index].combine(val)) {
          applyCopiesFrom(dst.type, Inexact, dst.index, val);
        }
      }
      // Propagate up to the supertypes.
      for (auto super = dst.type.getDeclaredSuperType(); super;
           super = super->getDeclaredSuperType()) {
        auto& readableSuperFields = readable[{*super, Inexact}];
        if (dst.index >= readableSuperFields.size()) {
          break;
        }
        if (readableSuperFields[dst.index].combine(val)) {
          applyCopiesFrom(*super, Inexact, dst.index, val);
        }
      }
    }

    // Optimize.
    // TODO: Skip this if we cannot optimize anything.
    FunctionOptimizer(readable, written, subTypes, refTest).run(runner, module);
    return;
  }
};

} // anonymous namespace

Pass* createConstantFieldPropagationPass() {
  return new ConstantFieldPropagation(false);
}

Pass* createConstantFieldPropagationRefTestPass() {
  return new ConstantFieldPropagation(true);
}

} // namespace wasm
