/* Traditional frame unwind support, for GDB the GNU Debugger.

   Copyright (C) 2003-2024 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef GDB_TRAD_FRAME_H
#define GDB_TRAD_FRAME_H

#include "frame.h"

class frame_info_ptr;
struct regcache_map_entry;
struct trad_frame_cache;

/* A simple, or traditional frame cache.

   The entire cache is populated in a single pass and then generic
   routines are used to extract the various cache values.  */

struct trad_frame_cache *trad_frame_cache_zalloc (const frame_info_ptr &);

/* This frame's ID.  */
void trad_frame_set_id (struct trad_frame_cache *this_trad_cache,
			struct frame_id this_id);
void trad_frame_get_id (struct trad_frame_cache *this_trad_cache,
			struct frame_id *this_id);
void trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache,
			       CORE_ADDR this_base);
CORE_ADDR trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache);

void trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache,
				 int regnum, int realreg);
void trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache,
			      int regnum, CORE_ADDR addr);
void trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache,
				const struct regcache_map_entry *regmap,
				CORE_ADDR addr, size_t size);
void trad_frame_set_reg_value (struct trad_frame_cache *this_cache,
			       int regnum, LONGEST val);

/* Given the cache in THIS_TRAD_CACHE, set the value of REGNUM to the bytes
   contained in BYTES with size SIZE.  */
void trad_frame_set_reg_value_bytes (struct trad_frame_cache *this_trad_cache,
				     int regnum,
				     gdb::array_view<const gdb_byte> bytes);

struct value *trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
				       const frame_info_ptr &this_frame,
				       int regnum);

/* Describes the kind of encoding a stored register has.  */
enum class trad_frame_saved_reg_kind
{
  /* Register value is unknown.  */
  UNKNOWN = 0,
  /* Register value is a constant.  */
  VALUE,
  /* Register value is in another register.  */
  REALREG,
  /* Register value is at an address.  */
  ADDR,
  /* Register value is a sequence of bytes.  */
  VALUE_BYTES
};

/* A struct that describes a saved register in a frame.  */

struct trad_frame_saved_reg
{
  /* Setters */

  /* Encode that the saved register's value is constant VAL in the
     trad-frame.  */
  void set_value (LONGEST val)
  {
    m_kind = trad_frame_saved_reg_kind::VALUE;
    m_reg.value = val;
  }

  /* Encode that the saved register's value is stored in register REALREG.  */
  void set_realreg (int realreg)
  {
    m_kind = trad_frame_saved_reg_kind::REALREG;
    m_reg.realreg = realreg;
  }

  /* Encode that the saved register's value is stored in memory at ADDR.  */
  void set_addr (LONGEST addr)
  {
    m_kind = trad_frame_saved_reg_kind::ADDR;
    m_reg.addr = addr;
  }

  /* Encode that the saved register's value is unknown.  */
  void set_unknown ()
  {
    m_kind = trad_frame_saved_reg_kind::UNKNOWN;
  }

  /* Encode that the saved register's value is stored as a sequence of bytes.
     This is useful when the value is larger than what primitive types
     can hold.  */
  void set_value_bytes (gdb::array_view<const gdb_byte> bytes)
  {
    /* Allocate the space and copy the data bytes.  */
    gdb_byte *data = FRAME_OBSTACK_CALLOC (bytes.size (), gdb_byte);
    memcpy (data, bytes.data (), bytes.size ());

    m_kind = trad_frame_saved_reg_kind::VALUE_BYTES;
    m_reg.value_bytes = data;
    m_reg.bytes_len = bytes.size ();
  }

  /* Getters */

  LONGEST value () const
  {
    gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE);
    return m_reg.value;
  }

  int realreg () const
  {
    gdb_assert (m_kind == trad_frame_saved_reg_kind::REALREG);
    return m_reg.realreg;
  }

  LONGEST addr () const
  {
    gdb_assert (m_kind == trad_frame_saved_reg_kind::ADDR);
    return m_reg.addr;
  }

  gdb::array_view<const gdb_byte> value_bytes () const
  {
    gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE_BYTES);
    return { m_reg.value_bytes, m_reg.bytes_len };
  }

  /* Convenience functions, return true if the register has been
     encoded as specified.  Return false otherwise.  */
  bool is_value () const
  {
    return m_kind == trad_frame_saved_reg_kind::VALUE;
  }

  bool is_realreg () const
  {
    return m_kind == trad_frame_saved_reg_kind::REALREG;
  }

  bool is_addr () const
  {
    return m_kind == trad_frame_saved_reg_kind::ADDR;
  }

  bool is_unknown () const
  {
    return m_kind == trad_frame_saved_reg_kind::UNKNOWN;
  }

  bool is_value_bytes () const
  {
    return m_kind == trad_frame_saved_reg_kind::VALUE_BYTES;
  }

private:

  trad_frame_saved_reg_kind m_kind;

  union {
    LONGEST value;
    int realreg;
    LONGEST addr;
    struct {
      const gdb_byte *value_bytes;
      size_t bytes_len;
    };
  } m_reg;
};

/* Reset the saved regs cache, setting register values to REALREG.  */
void trad_frame_reset_saved_regs (struct gdbarch *gdbarch,
				  trad_frame_saved_reg *regs);

/* Return a freshly allocated (and initialized) trad_frame array.  */
trad_frame_saved_reg *trad_frame_alloc_saved_regs (const frame_info_ptr &);
trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct gdbarch *);

/* Given the trad_frame info, return the location of the specified
   register.  */
struct value *trad_frame_get_prev_register (const frame_info_ptr &this_frame,
					    trad_frame_saved_reg this_saved_regs[],
					    int regnum);

#endif /* GDB_TRAD_FRAME_H */
