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

//
// Implementation of the shell interpreter execution environment
//

#ifndef wasm_shell_interface_h
#define wasm_shell_interface_h

#include "asmjs/shared-constants.h"
#include "ir/module-utils.h"
#include "shared-constants.h"
#include "support/name.h"
#include "support/utilities.h"
#include "wasm-interpreter.h"
#include "wasm.h"

namespace wasm {

// An exception emitted when exit() is called.
struct ExitException {};

// An exception emitted when a wasm trap occurs.
struct TrapException {};

// An exception emitted when a host limitation is hit. (These are not wasm traps
// as they are not in the spec; for example, the spec has no limit on how much
// GC memory may be allocated, but hosts have limits.)
struct HostLimitException {};

struct ShellExternalInterface : ModuleRunner::ExternalInterface {
  // The underlying memory can be accessed through unaligned pointers which
  // isn't well-behaved in C++. WebAssembly nonetheless expects it to behave
  // properly. Avoid emitting unaligned load/store by checking for alignment
  // explicitly, and performing memcpy if unaligned.
  //
  // The allocated memory tries to have the same alignment as the memory being
  // simulated.
  class Memory {
    // Use char because it doesn't run afoul of aliasing rules.
    std::vector<char> memory;
    template<typename T> static bool aligned(const char* address) {
      static_assert(!(sizeof(T) & (sizeof(T) - 1)), "must be a power of 2");
      return 0 == (reinterpret_cast<uintptr_t>(address) & (sizeof(T) - 1));
    }
    Memory(Memory&) = delete;
    Memory& operator=(const Memory&) = delete;

  public:
    Memory() = default;
    void resize(size_t newSize) {
      // Ensure the smallest allocation is large enough that most allocators
      // will provide page-aligned storage. This hopefully allows the
      // interpreter's memory to be as aligned as the memory being simulated,
      // ensuring that the performance doesn't needlessly degrade.
      //
      // The code is optimistic this will work until WG21's p0035r0 happens.
      const size_t minSize = 1 << 12;
      size_t oldSize = memory.size();
      memory.resize(std::max(minSize, newSize));
      if (newSize < oldSize && newSize < minSize) {
        std::memset(&memory[newSize], 0, minSize - newSize);
      }
    }
    template<typename T> void set(size_t address, T value) {
      if (aligned<T>(&memory[address])) {
        *reinterpret_cast<T*>(&memory[address]) = value;
      } else {
        std::memcpy(&memory[address], &value, sizeof(T));
      }
    }
    template<typename T> T get(size_t address) {
      if (aligned<T>(&memory[address])) {
        return *reinterpret_cast<T*>(&memory[address]);
      } else {
        T loaded;
        std::memcpy(&loaded, &memory[address], sizeof(T));
        return loaded;
      }
    }
  } memory;

  std::unordered_map<Name, std::vector<Literal>> tables;
  std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances;

  ShellExternalInterface(
    std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances_ = {})
    : memory() {
    linkedInstances.swap(linkedInstances_);
  }
  virtual ~ShellExternalInterface() = default;

  ModuleRunner* getImportInstance(Importable* import) {
    auto it = linkedInstances.find(import->module);
    if (it == linkedInstances.end()) {
      Fatal() << "importGlobals: unknown import: " << import->module.str << "."
              << import->base.str;
    }
    return it->second.get();
  }

  void init(Module& wasm, ModuleRunner& instance) override {
    if (wasm.memory.exists && !wasm.memory.imported()) {
      memory.resize(wasm.memory.initial * wasm::Memory::kPageSize);
    }
    ModuleUtils::iterDefinedTables(
      wasm, [&](Table* table) { tables[table->name].resize(table->initial); });
  }

  void importGlobals(std::map<Name, Literals>& globals, Module& wasm) override {
    ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
      auto inst = getImportInstance(import);
      auto* exportedGlobal = inst->wasm.getExportOrNull(import->base);
      if (!exportedGlobal) {
        Fatal() << "importGlobals: unknown import: " << import->module.str
                << "." << import->name.str;
      }
      globals[import->name] = inst->globals[exportedGlobal->value];
    });
  }

  Literals callImport(Function* import, Literals& arguments) override {
    if (import->module == SPECTEST && import->base.startsWith(PRINT)) {
      for (auto argument : arguments) {
        std::cout << argument << " : " << argument.type << '\n';
      }
      return {};
    } else if (import->module == ENV && import->base == EXIT) {
      // XXX hack for torture tests
      std::cout << "exit()\n";
      throw ExitException();
    } else if (auto* inst = getImportInstance(import)) {
      return inst->callExport(import->base, arguments);
    }
    Fatal() << "callImport: unknown import: " << import->module.str << "."
            << import->name.str;
  }

  Literals callTable(Name tableName,
                     Index index,
                     HeapType sig,
                     Literals& arguments,
                     Type results,
                     ModuleRunner& instance) override {

    auto it = tables.find(tableName);
    if (it == tables.end()) {
      trap("callTable on non-existing table");
    }

    auto& table = it->second;
    if (index >= table.size()) {
      trap("callTable overflow");
    }
    Function* func = nullptr;
    if (table[index].isFunction() && !table[index].isNull()) {
      func = instance.wasm.getFunctionOrNull(table[index].getFunc());
    }
    if (!func) {
      trap("uninitialized table element");
    }
    if (sig != func->type) {
      trap("callIndirect: function types don't match");
    }
    if (func->getParams().size() != arguments.size()) {
      trap("callIndirect: bad # of arguments");
    }
    size_t i = 0;
    for (const auto& param : func->getParams()) {
      if (!Type::isSubType(arguments[i++].type, param)) {
        trap("callIndirect: bad argument type");
      }
    }
    if (func->getResults() != results) {
      trap("callIndirect: bad result type");
    }
    if (func->imported()) {
      return callImport(func, arguments);
    } else {
      return instance.callFunctionInternal(func->name, arguments);
    }
  }

  int8_t load8s(Address addr) override { return memory.get<int8_t>(addr); }
  uint8_t load8u(Address addr) override { return memory.get<uint8_t>(addr); }
  int16_t load16s(Address addr) override { return memory.get<int16_t>(addr); }
  uint16_t load16u(Address addr) override { return memory.get<uint16_t>(addr); }
  int32_t load32s(Address addr) override { return memory.get<int32_t>(addr); }
  uint32_t load32u(Address addr) override { return memory.get<uint32_t>(addr); }
  int64_t load64s(Address addr) override { return memory.get<int64_t>(addr); }
  uint64_t load64u(Address addr) override { return memory.get<uint64_t>(addr); }
  std::array<uint8_t, 16> load128(Address addr) override {
    return memory.get<std::array<uint8_t, 16>>(addr);
  }

  void store8(Address addr, int8_t value) override {
    memory.set<int8_t>(addr, value);
  }
  void store16(Address addr, int16_t value) override {
    memory.set<int16_t>(addr, value);
  }
  void store32(Address addr, int32_t value) override {
    memory.set<int32_t>(addr, value);
  }
  void store64(Address addr, int64_t value) override {
    memory.set<int64_t>(addr, value);
  }
  void store128(Address addr, const std::array<uint8_t, 16>& value) override {
    memory.set<std::array<uint8_t, 16>>(addr, value);
  }

  Index tableSize(Name tableName) override {
    return (Index)tables[tableName].size();
  }

  void tableStore(Name tableName, Index index, const Literal& entry) override {
    auto& table = tables[tableName];
    if (index >= table.size()) {
      trap("out of bounds table access");
    } else {
      table[index] = entry;
    }
  }

  Literal tableLoad(Name tableName, Index index) override {
    auto it = tables.find(tableName);
    if (it == tables.end()) {
      trap("tableGet on non-existing table");
    }

    auto& table = it->second;
    if (index >= table.size()) {
      trap("out of bounds table access");
    }

    return table[index];
  }

  bool growMemory(Address /*oldSize*/, Address newSize) override {
    // Apply a reasonable limit on memory size, 1GB, to avoid DOS on the
    // interpreter.
    if (newSize > 1024 * 1024 * 1024) {
      return false;
    }
    memory.resize(newSize);
    return true;
  }

  bool growTable(Name name,
                 const Literal& value,
                 Index /*oldSize*/,
                 Index newSize) override {
    // Apply a reasonable limit on table size, 1GB, to avoid DOS on the
    // interpreter.
    if (newSize > 1024 * 1024 * 1024) {
      return false;
    }
    tables[name].resize(newSize, value);
    return true;
  }

  void trap(const char* why) override {
    std::cout << "[trap " << why << "]\n";
    throw TrapException();
  }

  void hostLimit(const char* why) override {
    std::cout << "[host limit " << why << "]\n";
    throw HostLimitException();
  }

  void throwException(const WasmException& exn) override { throw exn; }
};

} // namespace wasm

#endif // wasm_shell_interface_h
