// Copyright 2019 the V8 project authors. All rights reserved.  Use of
// this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_WASM_WASM_DEBUG_H_
#define V8_WASM_WASM_DEBUG_H_

#include <algorithm>
#include <memory>
#include <vector>

#include "include/v8-internal.h"
#include "src/base/iterator.h"
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/wasm/value-type.h"

namespace v8 {
namespace internal {

template <typename T>
class Handle;
class JSObject;
template <typename T>
class Vector;
class WasmFrame;
class WasmInstanceObject;

namespace wasm {

class DebugInfoImpl;
class LocalNames;
class NativeModule;
class WasmCode;
class WireBytesRef;
class WasmValue;
struct WasmFunction;

// Side table storing information used to inspect Liftoff frames at runtime.
// This table is only created on demand for debugging, so it is not optimized
// for memory size.
class DebugSideTable {
 public:
  class Entry {
   public:
    enum ValueKind : int8_t { kConstant, kRegister, kStack };
    struct Value {
      ValueType type;
      ValueKind kind;
      union {
        int32_t i32_const;  // if kind == kConstant
        int reg_code;       // if kind == kRegister
        int stack_offset;   // if kind == kStack
      };
    };

    Entry(int pc_offset, std::vector<Value> values)
        : pc_offset_(pc_offset), values_(std::move(values)) {}

    // Constructor for map lookups (only initializes the {pc_offset_}).
    explicit Entry(int pc_offset) : pc_offset_(pc_offset) {}

    int pc_offset() const { return pc_offset_; }

    int num_values() const { return static_cast<int>(values_.size()); }
    ValueType value_type(int index) const { return values_[index].type; }

    auto values() const {
      return base::make_iterator_range(values_.begin(), values_.end());
    }

    int stack_offset(int index) const {
      DCHECK_EQ(kStack, values_[index].kind);
      return values_[index].stack_offset;
    }

    bool is_constant(int index) const {
      return values_[index].kind == kConstant;
    }

    bool is_register(int index) const {
      return values_[index].kind == kRegister;
    }

    int32_t i32_constant(int index) const {
      DCHECK_EQ(kConstant, values_[index].kind);
      return values_[index].i32_const;
    }

    int32_t register_code(int index) const {
      DCHECK_EQ(kRegister, values_[index].kind);
      return values_[index].reg_code;
    }

    void Print(std::ostream&) const;

   private:
    int pc_offset_;
    std::vector<Value> values_;
  };

  // Technically it would be fine to copy this class, but there should not be a
  // reason to do so, hence mark it move only.
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(DebugSideTable);

  explicit DebugSideTable(int num_locals, std::vector<Entry> entries)
      : num_locals_(num_locals), entries_(std::move(entries)) {
    DCHECK(
        std::is_sorted(entries_.begin(), entries_.end(), EntryPositionLess{}));
  }

  const Entry* GetEntry(int pc_offset) const {
    auto it = std::lower_bound(entries_.begin(), entries_.end(),
                               Entry{pc_offset}, EntryPositionLess{});
    if (it == entries_.end() || it->pc_offset() != pc_offset) return nullptr;
    DCHECK_LE(num_locals_, it->num_values());
    return &*it;
  }

  auto entries() const {
    return base::make_iterator_range(entries_.begin(), entries_.end());
  }

  int num_locals() const { return num_locals_; }

  void Print(std::ostream&) const;

 private:
  struct EntryPositionLess {
    bool operator()(const Entry& a, const Entry& b) const {
      return a.pc_offset() < b.pc_offset();
    }
  };

  int num_locals_;
  std::vector<Entry> entries_;
};

// Get the module scope for a given instance. This will contain the wasm memory
// (if the instance has a memory) and the values of all globals.
Handle<JSObject> GetModuleScopeObject(Handle<WasmInstanceObject>);

// Debug info per NativeModule, created lazily on demand.
// Implementation in {wasm-debug.cc} using PIMPL.
class V8_EXPORT_PRIVATE DebugInfo {
 public:
  explicit DebugInfo(NativeModule*);
  ~DebugInfo();

  // For the frame inspection methods below:
  // {fp} is the frame pointer of the Liftoff frame, {debug_break_fp} that of
  // the {WasmDebugBreak} frame (if any).
  int GetNumLocals(Address pc);
  WasmValue GetLocalValue(int local, Address pc, Address fp,
                          Address debug_break_fp);
  int GetStackDepth(Address pc);

  const wasm::WasmFunction& GetFunctionAtAddress(Address pc);

  WasmValue GetStackValue(int index, Address pc, Address fp,
                          Address debug_break_fp);

  Handle<JSObject> GetLocalScopeObject(Isolate*, Address pc, Address fp,
                                       Address debug_break_fp);

  Handle<JSObject> GetStackScopeObject(Isolate*, Address pc, Address fp,
                                       Address debug_break_fp);

  WireBytesRef GetLocalName(int func_index, int local_index);

  void SetBreakpoint(int func_index, int offset, Isolate* current_isolate);

  void PrepareStep(Isolate*, StackFrameId);

  void ClearStepping(Isolate*);

  bool IsStepping(WasmFrame*);

  void RemoveBreakpoint(int func_index, int offset, Isolate* current_isolate);

  void RemoveDebugSideTables(Vector<WasmCode* const>);

  // Return the debug side table for the given code object, but only if it has
  // already been created. This will never trigger generation of the table.
  DebugSideTable* GetDebugSideTableIfExists(const WasmCode*) const;

  void RemoveIsolate(Isolate*);

 private:
  std::unique_ptr<DebugInfoImpl> impl_;
};

}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_WASM_DEBUG_H_
