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

#include "ir/memory-utils.h"
#include "support/stdckdint.h"
#include "wasm.h"

namespace wasm::MemoryUtils {

bool isSubType(const Memory& a, const Memory& b) {
  return a.shared == b.shared && a.addressType == b.addressType &&
         a.initial >= b.initial && a.max <= b.max &&
         a.pageSizeLog2 == b.pageSizeLog2;
}

bool flatten(Module& wasm) {
  // If there are no memories then they are already flat, in the empty sense.
  if (wasm.memories.empty()) {
    return true;
  }
  // Flatten does not currently have support for multimemory
  if (wasm.memories.size() != 1) {
    return false;
  }
  // The presence of any instruction that cares about segment identity is a
  // problem because flattening gets rid of that (when it merges them all into
  // one big segment).
  struct Scanner : public WalkerPass<
                     PostWalker<Scanner, UnifiedExpressionVisitor<Scanner>>> {
    std::atomic<bool>& noticesSegmentIdentity;

    Scanner(std::atomic<bool>& noticesSegmentIdentity)
      : noticesSegmentIdentity(noticesSegmentIdentity) {}

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

    void visitExpression(Expression* curr) {
#define DELEGATE_ID curr->_id

#define DELEGATE_START(id) [[maybe_unused]] auto* cast = curr->cast<id>();

#define DELEGATE_GET_FIELD(id, field) cast->field

#define DELEGATE_FIELD_TYPE(id, field)
#define DELEGATE_FIELD_HEAPTYPE(id, field)
#define DELEGATE_FIELD_CHILD(id, field)
#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field)
#define DELEGATE_FIELD_INT(id, field)
#define DELEGATE_FIELD_LITERAL(id, field)
#define DELEGATE_FIELD_NAME(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field)
#define DELEGATE_FIELD_ADDRESS(id, field)

#define DELEGATE_FIELD_NAME_KIND(id, field, kind)                              \
  if (kind == ModuleItemKind::DataSegment) {                                   \
    noticesSegmentIdentity = true;                                             \
  }

#include "wasm-delegations-fields.def"
    }
  };

  std::atomic<bool> noticesSegmentIdentity = false;
  PassRunner runner(&wasm);
  Scanner scanner(noticesSegmentIdentity);
  scanner.setPassRunner(&runner);
  scanner.run(&wasm);
  scanner.runOnModuleCode(&runner, &wasm);
  if (noticesSegmentIdentity) {
    return false;
  }

  auto& dataSegments = wasm.dataSegments;

  if (dataSegments.size() == 0) {
    return true;
  }

  std::vector<char> data;
  for (auto& segment : dataSegments) {
    if (segment->isPassive()) {
      return false;
    }
    auto* offset = segment->offset->dynCast<Const>();
    if (!offset) {
      return false;
    }
  }
  for (auto& segment : dataSegments) {
    auto* offset = segment->offset->dynCast<Const>();
    Index start = offset->value.getInteger();
    Index size = segment->data.size();
    Index end;
    if (std::ckd_add(&end, start, size)) {
      return false;
    }
    if (end > data.size()) {
      data.resize(end);
    }
    std::copy(segment->data.begin(), segment->data.end(), data.begin() + start);
  }
  dataSegments[0]->offset->cast<Const>()->value =
    Literal::makeFromInt32(0, wasm.memories[0]->addressType);
  dataSegments[0]->data.swap(data);
  wasm.removeDataSegments(
    [&](DataSegment* curr) { return curr->name != dataSegments[0]->name; });

  return true;
}

} // namespace wasm::MemoryUtils
