/* Generate CTF types and objects from the GCC DWARF.
   Copyright (C) 2021-2025 Free Software Foundation, Inc.

This file is part of GCC.

GCC 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, or (at your option) any later
version.

GCC 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "target.h"
#include "dwarf2out.h"
#include "dwarf2out.h"

#include "dwarf2ctf.h"
#include "ctfc.h"

/* Forward declarations for some routines defined in this file.  */

static ctf_dtdef_ref
gen_ctf_type (ctf_container_ref, dw_die_ref);

/* All the DIE structures we handle come from the DWARF information
   generated by GCC.  However, there are three situations where we need
   to create our own created DIE structures because GCC doesn't
   provide them.

   The DWARF spec suggests using a DIE with DW_TAG_unspecified_type
   and name "void" in order to denote the void type.  But GCC doesn't
   follow this advice.  Still we need a DIE to act as a key for void
   types, we use ctf_void_die.

   Also, if a subrange type corresponding to an array index does not
   specify a type then we assume it is `int'.

   Finally, for types unrepresentable in CTF, we need a DIE to anchor
   them to a CTF type of kind unknown.

   The variables below are initialized in ctf_debug_init and hold
   references to the proper DIEs.  */

static GTY (()) dw_die_ref ctf_void_die;
static GTY (()) dw_die_ref ctf_array_index_die;
static GTY (()) dw_die_ref ctf_unknown_die;

/* Some DIEs have a type description attribute, stored in a DW_AT_type
   attribute.  However, GCC generates no attribute to signify a `void'
   type.

   This can happen in many contexts (return type of a function,
   pointed or qualified type, etc) so we use the `ctf_get_AT_type'
   function below abstracts this.  */

static dw_die_ref
ctf_get_AT_type (dw_die_ref die)
{
  dw_die_ref type_die = get_AT_ref (die, DW_AT_type);
  return (type_die ? type_die : ctf_void_die);
}

/* Some data member DIEs have location specified as a DWARF expression
   (specifically in DWARF2).  Luckily, the expression is a simple
   DW_OP_plus_uconst with one operand set to zero.

   Sometimes the data member location may also be negative.  In yet some other
   cases (specifically union data members), the data member location is
   non-existent.  Handle all these scenarios here to abstract this.  */

static HOST_WIDE_INT
ctf_get_AT_data_member_location (dw_die_ref die)
{
  HOST_WIDE_INT field_location = 0;
  dw_attr_node * attr;

  /* The field location (in bits) can be determined from
     either a DW_AT_data_member_location attribute or a
     DW_AT_data_bit_offset attribute.  */
  if (get_AT (die, DW_AT_data_bit_offset))
    field_location = get_AT_unsigned (die, DW_AT_data_bit_offset);
  else
    {
      attr = get_AT (die, DW_AT_data_member_location);
      if (attr && AT_class (attr) == dw_val_class_loc)
	{
	  dw_loc_descr_ref descr = AT_loc (attr);
	  /* Operand 2 must be zero; the structure is assumed to be on the
	     stack in DWARF2.  */
	  gcc_assert (!descr->dw_loc_oprnd2.v.val_unsigned);
	  gcc_assert (descr->dw_loc_oprnd2.val_class
		      == dw_val_class_unsigned_const);
	  field_location = descr->dw_loc_oprnd1.v.val_unsigned * 8;
	}
      else
	{
	  attr = get_AT (die, DW_AT_data_member_location);
	  if (attr && AT_class (attr) == dw_val_class_const)
	    field_location = AT_int (attr) * 8;
	  else
	    field_location = (get_AT_unsigned (die,
					   DW_AT_data_member_location)
			      * 8);
	}
    }

  return field_location;
}

/* CTF Types' and CTF Variables' Location Information.  CTF section does not
   emit location information, this is provided for BTF CO-RE use-cases.  These
   functions fetch information from DWARF Die directly, as such the location
   information is not buffered in the CTF container.  */

const char *
ctf_get_die_loc_file (dw_die_ref die)
{
  if (!die)
    return NULL;

  struct dwarf_file_data * file;
  file = get_AT_file (die, DW_AT_decl_file);
  if (!file)
    return NULL;

  return file->filename;
}

unsigned int
ctf_get_die_loc_line (dw_die_ref die)
{
  if (!die)
    return 0;

  return get_AT_unsigned (die, DW_AT_decl_line);
}

unsigned int
ctf_get_die_loc_col (dw_die_ref die)
{
  if (!die)
    return 0;

  return get_AT_unsigned (die, DW_AT_decl_column);
}

/* Generate CTF for the void type.  */

static ctf_dtdef_ref
gen_ctf_void_type (ctf_container_ref ctfc)
{
  ctf_encoding_t ctf_encoding = {0, 0, 0};

  /* In CTF the void type is encoded as a 0-byte signed integer
     type.  */

  ctf_encoding.cte_bits = 0;
  ctf_encoding.cte_format = CTF_INT_SIGNED;

  gcc_assert (ctf_void_die != NULL);
  return ctf_add_integer (ctfc, CTF_ADD_ROOT, "void",
			  &ctf_encoding, ctf_void_die);
}

/* Generate CTF type of unknown kind.  */

static ctf_dtdef_ref
gen_ctf_unknown_type (ctf_container_ref ctfc)
{
  ctf_dtdef_ref dtd;

  /* In CTF, the unknown type is encoded as a 0 byte sized type with kind
     CTF_K_UNKNOWN.  Create an encoding object merely to reuse the underlying
     ctf_add_encoded interface; the CTF encoding object is not 'used' any more
     than just the generation of size from.  */
  ctf_encoding_t ctf_encoding = {0, 0, 0};

  gcc_assert (ctf_unknown_die != NULL);
  /* Type de-duplication.  */
  if (!ctf_type_exists (ctfc, ctf_unknown_die, &dtd))
    dtd = ctf_add_unknown (ctfc, CTF_ADD_ROOT, "unknown",
			   &ctf_encoding, ctf_unknown_die);

  return dtd;
}

/* Sizes of entities can be given in bytes or bits.  This function
   abstracts this by returning the size in bits of the given entity.
   If no DW_AT_byte_size nor DW_AT_bit_size are defined, this function
   returns 0.  */

static uint32_t
ctf_die_bitsize (dw_die_ref die)
{
  dw_attr_node *attr_byte_size = get_AT (die, DW_AT_byte_size);
  dw_attr_node *attr_bit_size = get_AT (die, DW_AT_bit_size);

  if (attr_bit_size)
    return AT_unsigned (attr_bit_size);
  else if (attr_byte_size)
    return (AT_unsigned (attr_byte_size) * 8);
  else
    return 0;
}

/* Generate CTF for base type (integer, boolean, real, fixed point and complex).
   Important: the caller of this API must make sure that duplicate types are
   not added.  */

static ctf_dtdef_ref
gen_ctf_base_type (ctf_container_ref ctfc, dw_die_ref type)
{
  ctf_dtdef_ref dtd = NULL;

  ctf_encoding_t ctf_encoding = {0, 0, 0};

  unsigned int encoding = get_AT_unsigned (type, DW_AT_encoding);
  unsigned int bit_size = ctf_die_bitsize (type);
  const char * name_string = get_AT_string (type, DW_AT_name);

  switch (encoding)
    {
    case DW_ATE_void:

      ctf_encoding.cte_format = CTF_INT_SIGNED;
      ctf_encoding.cte_bits = 0;

      gcc_assert (name_string);
      dtd = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
			     &ctf_encoding, type);

      break;
    case DW_ATE_boolean:

      ctf_encoding.cte_format = CTF_INT_BOOL;
      ctf_encoding.cte_bits = bit_size;

      gcc_assert (name_string);
      dtd = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
			     &ctf_encoding, type);
      break;
    case DW_ATE_float:
      {
	unsigned int float_bit_size
	  = tree_to_uhwi (TYPE_SIZE (float_type_node));
	unsigned int double_bit_size
	  = tree_to_uhwi (TYPE_SIZE (double_type_node));
	unsigned int long_double_bit_size
	  = tree_to_uhwi (TYPE_SIZE (long_double_type_node));

	if (bit_size == float_bit_size)
	  ctf_encoding.cte_format = CTF_FP_SINGLE;
	else if (bit_size == double_bit_size)
	  ctf_encoding.cte_format = CTF_FP_DOUBLE;
	else if (bit_size == long_double_bit_size)
	  ctf_encoding.cte_format = CTF_FP_LDOUBLE;
	else
	  /* CTF does not have representation for other types.  Skip them.  */
	  break;

	ctf_encoding.cte_bits = bit_size;
	dtd = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
				 &ctf_encoding, type);

	break;
      }
    case DW_ATE_signed_char:
      /* FALLTHROUGH */
    case DW_ATE_unsigned_char:
      /* FALLTHROUGH */
    case DW_ATE_signed:
      /* FALLTHROUGH */
    case DW_ATE_unsigned:

      if (encoding == DW_ATE_signed_char
	  || encoding == DW_ATE_unsigned_char)
	ctf_encoding.cte_format |= CTF_INT_CHAR;

      if (encoding == DW_ATE_signed
	  || encoding == DW_ATE_signed_char)
	ctf_encoding.cte_format |= CTF_INT_SIGNED;

      ctf_encoding.cte_bits = bit_size;
      dtd = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
				 &ctf_encoding, type);
      break;

    case DW_ATE_complex_float:
      {
	unsigned int float_bit_size
	  = tree_to_uhwi (TYPE_SIZE (float_type_node));
	unsigned int double_bit_size
	  = tree_to_uhwi (TYPE_SIZE (double_type_node));
	unsigned int long_double_bit_size
	  = tree_to_uhwi (TYPE_SIZE (long_double_type_node));

	if (bit_size == float_bit_size * 2)
	  ctf_encoding.cte_format = CTF_FP_CPLX;
	else if (bit_size == double_bit_size * 2)
	  ctf_encoding.cte_format = CTF_FP_DCPLX;
	else if (bit_size == long_double_bit_size * 2)
	    ctf_encoding.cte_format = CTF_FP_LDCPLX;
	else
	  /* CTF does not have representation for other types.  Skip them.  */
	  break;

	ctf_encoding.cte_bits = bit_size;
	dtd = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
				 &ctf_encoding, type);
	break;
      }
    default:
      /* Ignore.  */
      break;
    }

  return dtd;
}

/* Generate CTF for a pointer type.  */

static ctf_dtdef_ref
gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type)
{
  ctf_dtdef_ref pointed_dtd, pointer_dtd;
  dw_die_ref pointed_type_die = ctf_get_AT_type (ptr_type);

  pointed_dtd = gen_ctf_type (ctfc, pointed_type_die);

  /* Type de-duplication.
     Consult the ctfc_types hash again before adding the CTF pointer type
     because there can be cases where a pointer type may have been added by
     the gen_ctf_type call above.  */
  if (!ctf_type_exists (ctfc, ptr_type, &pointer_dtd))
    pointer_dtd = ctf_add_pointer (ctfc, CTF_ADD_ROOT, pointed_dtd, ptr_type);

  return pointer_dtd;
}

/* Recursively generate CTF for array dimensions starting at DIE C (of type
   DW_TAG_subrange_type) until DIE LAST (of type DW_TAG_subrange_type) is
   reached.  ARRAY_ELEMS_TYPE is the CTF type object for the type of the
   array elements.  */

static ctf_dtdef_ref
gen_ctf_subrange_type (ctf_container_ref ctfc, ctf_dtdef_ref array_elems_type,
		       dw_die_ref c, dw_die_ref last)
{
  ctf_arinfo_t arinfo;
  ctf_dtdef_ref array_dtd;

  dw_attr_node *upper_bound_at;
  dw_die_ref array_index_type;
  unsigned HOST_WIDE_INT array_num_elements;

  if (dw_get_die_tag (c) == DW_TAG_subrange_type)
    {
      /* When DW_AT_upper_bound is used to specify the size of an
	 array in DWARF, it is usually an unsigned constant
	 specifying the upper bound index of the array.  However,
	 for unsized arrays, such as foo[] or bar[0],
	 DW_AT_upper_bound is a signed integer constant
	 instead.  */

      upper_bound_at = get_AT (c, DW_AT_upper_bound);
      if (upper_bound_at
	  && AT_class (upper_bound_at) == dw_val_class_unsigned_const)
	/* This is the upper bound index.  */
	array_num_elements = AT_unsigned (get_AT (c, DW_AT_upper_bound)) + 1;
      else if (get_AT (c, DW_AT_count))
	array_num_elements = AT_unsigned (get_AT (c, DW_AT_count));
      else
	{
	  /* This is a VLA of some kind.  */
	  array_num_elements = 0;
	}
    }
  else
    gcc_unreachable ();

  if (array_num_elements > UINT32_MAX)
    {
      /* The array cannot be encoded in CTF.  TBD_CTF_REPRESENTATION_LIMIT.  */
      return gen_ctf_unknown_type (ctfc);
    }

  /* Ok, mount and register the array type.  Note how the array
     type we register here is the type of the elements in
     subsequent "dimensions", if there are any.  */
  arinfo.ctr_nelems = array_num_elements;

  array_index_type = ctf_get_AT_type (c);
  arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type);

  if (c == last)
    arinfo.ctr_contents = array_elems_type;
  else
    arinfo.ctr_contents = gen_ctf_subrange_type (ctfc, array_elems_type,
						 dw_get_die_sib (c), last);

  if (!ctf_type_exists (ctfc, c, &array_dtd))
    array_dtd = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, c);

  return array_dtd;
}

/* Generate CTF for an ARRAY_TYPE.  */

static ctf_dtdef_ref
gen_ctf_array_type (ctf_container_ref ctfc,
		    dw_die_ref array_type)
{
  dw_die_ref first, last, array_elems_type;
  ctf_dtdef_ref array_dtd, elem_dtd;

  int vector_type_p = get_AT_flag (array_type, DW_AT_GNU_vector);
  if (vector_type_p)
    return NULL;

  /* Find the first and last array dimension DIEs.  */
  last = dw_get_die_child (array_type);
  first = dw_get_die_sib (last);

  /* Type de-duplication.
     Consult the ctfc_types before adding CTF type for the first dimension.  */
  if (!ctf_type_exists (ctfc, first, &array_dtd))
    {
      array_elems_type = ctf_get_AT_type (array_type);
      /* First, register the type of the array elements if needed.  */
      elem_dtd = gen_ctf_type (ctfc, array_elems_type);

      array_dtd = gen_ctf_subrange_type (ctfc, elem_dtd, first, last);
    }

  return array_dtd;
}

/* Generate CTF for a typedef.  */

static ctf_dtdef_ref
gen_ctf_typedef (ctf_container_ref ctfc, dw_die_ref tdef)
{
  ctf_dtdef_ref tdef_dtd, dtd;
  const char *tdef_name = get_AT_string (tdef, DW_AT_name);
  dw_die_ref tdef_type = ctf_get_AT_type (tdef);

  dtd = gen_ctf_type (ctfc, tdef_type);

  /* Type de-duplication.
     This is necessary because the ctf for the typedef may have been already
     added due to the gen_ctf_type call above.  */
  if (!ctf_type_exists (ctfc, tdef, &tdef_dtd))
    tdef_dtd = ctf_add_typedef (ctfc, CTF_ADD_ROOT, tdef_name, dtd, tdef);

  return tdef_dtd;
}

/* Generate CTF for a type modifier.

   If the given DIE contains a valid C modifier (like _Atomic), which is not
   supported by CTF, then this function skips the modifier die and continues
   with the underlying type.

   If the modifier is supported by CTF, then this function constructs and
   returns an appropate CTF type representing the modifier.

   For all other cases, this function returns NULL.  */

static ctf_dtdef_ref
gen_ctf_modifier_type (ctf_container_ref ctfc, dw_die_ref modifier)
{
  uint32_t kind = CTF_K_MAX;
  ctf_dtdef_ref dtd, modifier_dtd;
  dw_die_ref qual_type = ctf_get_AT_type (modifier);

  switch (dw_get_die_tag (modifier))
    {
    case DW_TAG_const_type: kind = CTF_K_CONST; break;
    case DW_TAG_volatile_type: kind = CTF_K_VOLATILE; break;
    case DW_TAG_restrict_type: kind = CTF_K_RESTRICT; break;
    case DW_TAG_atomic_type: break;
    default:
      return NULL;
    }

  /* Register the type for which this modifier applies.  */
  dtd = gen_ctf_type (ctfc, qual_type);

  /* Skip generating a CTF modifier record for _Atomic as there is no
     representation for it.  */
  if (dw_get_die_tag (modifier) == DW_TAG_atomic_type)
    return dtd;

  gcc_assert (kind != CTF_K_MAX);
  /* Now register the modifier itself.  */
  if (!ctf_type_exists (ctfc, modifier, &modifier_dtd))
    modifier_dtd = ctf_add_reftype (ctfc, CTF_ADD_ROOT, dtd, kind, modifier);

  return modifier_dtd;
}

/* Generate CTF for a struct type.  */

static ctf_dtdef_ref
gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, uint32_t kind)
{
  uint32_t bit_size = ctf_die_bitsize (sou);
  int declaration_p = get_AT_flag (sou, DW_AT_declaration);
  const char *sou_name = get_AT_string (sou, DW_AT_name);

  ctf_dtdef_ref sou_dtd;

  /* An incomplete structure or union type is represented in DWARF by
     a structure or union DIE that does not have a size attribute and
     that has a DW_AT_declaration attribute.  This corresponds to a
     CTF forward type with kind CTF_K_STRUCT.  */
  if (bit_size == 0 && declaration_p)
    return ctf_add_forward (ctfc, CTF_ADD_ROOT,
			    sou_name, kind, sou);

  /* This is a complete struct or union type.  Generate a CTF type for
     it if it doesn't exist already.  */
  if (!ctf_type_exists (ctfc, sou, &sou_dtd))
    sou_dtd = ctf_add_sou (ctfc, CTF_ADD_ROOT,
			   sou_name, kind, bit_size / 8,
			   sou);

  /* Now process the struct members.  */
  {
    dw_die_ref c;

    c = dw_get_die_child (sou);
    if (c)
      do
	{
	  const char *field_name;
	  dw_die_ref field_type;
	  HOST_WIDE_INT field_location;
	  ctf_dtdef_ref field_dtd;

	  c = dw_get_die_sib (c);

	  field_name = get_AT_string (c, DW_AT_name);
	  field_type = ctf_get_AT_type (c);
	  field_location = ctf_get_AT_data_member_location (c);

	  /* Generate the field type.  */
	  field_dtd = gen_ctf_type (ctfc, field_type);

	  /* If this is a bit-field, then wrap the field type
	     generated above with a CTF slice.  */
	  if (get_AT (c, DW_AT_bit_offset)
	      || get_AT (c, DW_AT_data_bit_offset))
	    {
	      dw_attr_node *attr;
	      HOST_WIDE_INT bitpos = 0;
	      HOST_WIDE_INT bitsize = ctf_die_bitsize (c);
	      HOST_WIDE_INT bit_offset;

	      /* The bit offset is given in bits and it may be
		 negative.  */
	      attr = get_AT (c, DW_AT_bit_offset);
	      if (attr)
		{
		  if (AT_class (attr) == dw_val_class_unsigned_const)
		    bit_offset = AT_unsigned (attr);
		  else
		    bit_offset = AT_int (attr);

		  if (BYTES_BIG_ENDIAN)
		    bitpos = field_location + bit_offset;
		  else
		    {
		      HOST_WIDE_INT bit_size;

		      attr = get_AT (c, DW_AT_byte_size);
		      if (attr)
			/* Explicit size given in bytes.  */
			bit_size = AT_unsigned (attr) * 8;
		      else
			/* Infer the size from the member type.  */
			bit_size = ctf_die_bitsize (field_type);

		      bitpos = (field_location
				+ bit_size
				- bit_offset
				- bitsize);
		    }
		}

	      /* In DWARF5 a data_bit_offset attribute is given with
		 the offset of the data from the beginning of the
		 struct.  Acknowledge it if present.  */
	      attr = get_AT (c, DW_AT_data_bit_offset);
	      if (attr)
		bitpos += AT_unsigned (attr);

	      /* This is not precisely a TBD_CTF_REPRESENTATION_LIMIT, but
		 surely something to look at for the next format version bump
		 for CTF.  */
	      if (bitsize <= 255 && (bitpos - field_location) <= 255)
		field_dtd = ctf_add_slice (ctfc, CTF_ADD_NONROOT,
					       field_dtd,
					       bitpos - field_location,
					       bitsize, c);
	      else
		field_dtd = gen_ctf_unknown_type (ctfc);
	    }

	  /* Add the field type to the struct or union type.  */
	  ctf_add_member_offset (ctfc, sou,
				 field_name,
				 field_dtd,
				 field_location);
	}
      while (c != dw_get_die_child (sou));
  }

  return sou_dtd;
}

/* Generate CTF for a function type.  */

static ctf_dtdef_ref
gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref function,
		       bool from_global_func)
{
  const char *function_name = get_AT_string (function, DW_AT_name);
  dw_die_ref return_type = ctf_get_AT_type (function);

  ctf_funcinfo_t func_info;
  uint32_t num_args = 0;
  int linkage = get_AT_flag (function, DW_AT_external);

  ctf_dtdef_ref return_dtd, function_dtd;

  /* First, add the return type.  */
  return_dtd = gen_ctf_type (ctfc, return_type);
  func_info.ctc_return = return_dtd;

  /* Type de-duplication.
     Consult the ctfc_types hash before adding the CTF function type.  */
  if (ctf_type_exists (ctfc, function, &function_dtd))
    return function_dtd;

  /* Do a first pass on the formals to determine the number of
     arguments, and whether the function type gets a varargs.  */
  {
    dw_die_ref c;

    c = dw_get_die_child (function);
    if (c)
      do
	{
	  c = dw_get_die_sib (c);

	  if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
	    num_args += 1;
	  else if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters)
	    {
	      func_info.ctc_flags |= CTF_FUNC_VARARG;
	      num_args += 1;
	    }
	}
      while (c != dw_get_die_child (function));
  }

  /* Note the number of typed arguments _includes_ the vararg.  */
  func_info.ctc_argc = num_args;

  /* Type de-duplication has already been performed by now.  */
  function_dtd = ctf_add_function (ctfc, CTF_ADD_ROOT,
				   function_name,
				   (const ctf_funcinfo_t *)&func_info,
				   function,
				   from_global_func,
				   linkage);

  /* Second pass on formals: generate the CTF types corresponding to
     them and add them as CTF function args.  */
  {
    dw_die_ref c;
    unsigned int i = 0;
    const char *arg_name;
    ctf_dtdef_ref arg_type;

    c = dw_get_die_child (function);
    if (c)
      do
	{
	  c = dw_get_die_sib (c);

	  if (dw_get_die_tag (c) == DW_TAG_unspecified_parameters)
	    {
	      gcc_assert (i == num_args - 1);
	      /* Add an argument with type 0 and no name.  */
	      ctf_add_function_arg (ctfc, function, "", NULL);
	    }
	  else if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
	    {
	      i++;
	      arg_name = get_AT_string (c, DW_AT_name);
	      arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
	      /* Add the argument to the existing CTF function type.  */
	      ctf_add_function_arg (ctfc, function, arg_name, arg_type);
	    }
	  else
	    /* This is a local variable.  Ignore.  */
	    continue;
	}
      while (c != dw_get_die_child (function));
  }

  return function_dtd;
}

/* Generate CTF for an enumeration type.  */

static ctf_dtdef_ref
gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration)
{
  const char *enum_name = get_AT_string (enumeration, DW_AT_name);
  unsigned int bit_size = ctf_die_bitsize (enumeration);
  unsigned int signedness = get_AT_unsigned (enumeration, DW_AT_encoding);
  int declaration_p = get_AT_flag (enumeration, DW_AT_declaration);

  ctf_dtdef_ref enum_dtd;

  /* If this is an incomplete enum, generate a CTF forward for it and
     be done.  */
  if (declaration_p)
    {
      gcc_assert (enum_name);
      return ctf_add_forward (ctfc, CTF_ADD_ROOT, enum_name,
			      CTF_K_ENUM, enumeration);
    }

  /* If the size the enumerators is not specified then use the size of
     the underlying type, which must be a base type.  */
  if (bit_size == 0)
    {
      dw_die_ref type = ctf_get_AT_type (enumeration);
      bit_size = ctf_die_bitsize (type);
    }

  /* Generate a CTF type for the enumeration.  */
  enum_dtd = ctf_add_enum (ctfc, CTF_ADD_ROOT,
			   enum_name, bit_size / 8,
			   (signedness == DW_ATE_unsigned),
			   enumeration);

  /* Process the enumerators.  */
  {
    dw_die_ref c;

    c = dw_get_die_child (enumeration);
    if (c)
      do
	{
	  const char *enumerator_name;
	  dw_attr_node *enumerator_value;
	  HOST_WIDE_INT value_wide_int;

	  c = dw_get_die_sib (c);

	  enumerator_name = get_AT_string (c, DW_AT_name);
	  enumerator_value = get_AT (c, DW_AT_const_value);

	  /* enumerator_value can be either a signed or an unsigned
	     constant value.  */
	  if (AT_class (enumerator_value) == dw_val_class_unsigned_const
	      || (AT_class (enumerator_value)
		  == dw_val_class_unsigned_const_implicit))
	    value_wide_int = AT_unsigned (enumerator_value);
	  else
	    value_wide_int = AT_int (enumerator_value);

	  ctf_add_enumerator (ctfc, enum_dtd,
			      enumerator_name, value_wide_int, enumeration);
	}
      while (c != dw_get_die_child (enumeration));
  }

  return enum_dtd;
}

/* Add a CTF variable record for the given input DWARF DIE.  */

static void
gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
{
  const char *var_name = get_AT_string (die, DW_AT_name);
  dw_die_ref var_type = ctf_get_AT_type (die);
  unsigned int external_vis = get_AT_flag (die, DW_AT_external);
  ctf_dtdef_ref var_dtd;

  /* Avoid duplicates.  */
  if (ctf_dvd_lookup (ctfc, die))
    return;

  /* Do not generate CTF variable records for non-defining incomplete
     declarations.  Such declarations can be known via the DWARF
     DW_AT_specification attribute.  */
  if (ctf_dvd_ignore_lookup (ctfc, die))
    return;

  /* The value of the DW_AT_specification attribute, if present, is a
     reference to the debugging information entry representing the
     non-defining declaration.  */
  dw_die_ref decl = get_AT_ref (die, DW_AT_specification);

  /* Add the type of the variable.  */
  var_dtd = gen_ctf_type (ctfc, var_type);

  /* Generate the new CTF variable and update global counter.  */
  (void) ctf_add_variable (ctfc, var_name, var_dtd, die, external_vis, decl);
  /* Skip updating the number of global objects at this time.  This is updated
     later after pre-processing as some CTF variable records although
     generated now, will not be emitted later.  [PR105089].  */
}

/* Add a CTF function record for the given input DWARF DIE.  */

static void
gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
{
  ctf_dtdef_ref function_dtd;
  /* Type de-duplication.
     Consult the ctfc_types hash before adding the CTF function type.  */
  if (ctf_type_exists (ctfc, die, &function_dtd))
    return;

  /* Add the type of the function and update the global functions
     counter.  Note that DWARF encodes function types in both
     DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
     way.  */
  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
  ctfc->ctfc_num_global_funcs += 1;
}

/* Add CTF type record(s) for the given input DWARF DIE and return its type id.

   If there is already a CTF type corresponding to the given DIE, then
   this function returns the type id of the existing type.

   If the given DIE is not recognized as a type, then this function
   returns NULL.  */

static ctf_dtdef_ref
gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
{
  ctf_dtdef_ref dtd = NULL;
  int unrecog_die = false;

  if (ctf_type_exists (ctfc, die, &dtd))
    return dtd;

  switch (dw_get_die_tag (die))
    {
    case DW_TAG_base_type:
      dtd = gen_ctf_base_type (ctfc, die);
      break;
    case DW_TAG_pointer_type:
      dtd = gen_ctf_pointer_type (ctfc, die);
      break;
    case DW_TAG_typedef:
      dtd = gen_ctf_typedef (ctfc, die);
      break;
    case DW_TAG_array_type:
      dtd = gen_ctf_array_type (ctfc, die);
      break;
    case DW_TAG_structure_type:
      dtd = gen_ctf_sou_type (ctfc, die, CTF_K_STRUCT);
      break;
    case DW_TAG_union_type:
      dtd = gen_ctf_sou_type (ctfc, die, CTF_K_UNION);
      break;
    case DW_TAG_subroutine_type:
      dtd = gen_ctf_function_type (ctfc, die,
				   false /* from_global_func */);
      break;
    case DW_TAG_enumeration_type:
      dtd = gen_ctf_enumeration_type (ctfc, die);
      break;
    case DW_TAG_atomic_type:
      /* FALLTHROUGH */
    case DW_TAG_const_type:
      /* FALLTHROUGH */
    case DW_TAG_restrict_type:
      /* FALLTHROUGH */
    case DW_TAG_volatile_type:
      dtd = gen_ctf_modifier_type (ctfc, die);
      break;
    case DW_TAG_unspecified_type:
      {
	const char *name = get_AT_string (die, DW_AT_name);

	if (name && strcmp (name, "void") == 0)
	  dtd = gen_ctf_void_type (ctfc);
	else
	  dtd = NULL;

	break;
      }
    case DW_TAG_reference_type:
      dtd = NULL;
      break;
    default:
      /* Unrecognized DIE.  */
      unrecog_die = true;
      dtd = NULL;
      break;
    }

  /* For all types unrepresented in CTF, use an explicit CTF type of kind
     CTF_K_UNKNOWN.  */
  if ((dtd == NULL) && (!unrecog_die))
    dtd = gen_ctf_unknown_type (ctfc);

  return dtd;
}

bool
ctf_do_die (dw_die_ref die)
{
  ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();

  /* Note how we tell the caller to continue traversing children DIEs
     if this DIE didn't result in CTF records being added.  */
  if (dw_get_die_tag (die) == DW_TAG_variable)
    {
      gen_ctf_variable (tu_ctfc, die);
      return false;
    }
  else if (dw_get_die_tag (die) == DW_TAG_subprogram)
    {
      gen_ctf_function (tu_ctfc, die);
      return false;
    }
  else
    return (gen_ctf_type (tu_ctfc, die) == NULL);
}

/* Initialize CTF subsystem for CTF debug info generation.  */

void
ctf_debug_init (void)
{
  /* First, initialize the CTF subsystem.  */
  ctf_init ();

  /* Create a couple of DIE structures that we may need.  */
  ctf_void_die = new_die_raw (DW_TAG_unspecified_type);
  add_name_attribute (ctf_void_die, "void");
  ctf_array_index_die
    = base_type_die (integer_type_node, 0 /* reverse */);
  add_name_attribute (ctf_array_index_die, "int");
  ctf_unknown_die = new_die_raw (DW_TAG_unspecified_type);
  add_name_attribute (ctf_unknown_die, "unknown");
}

/* Early finish CTF/BTF debug info.  */

void
ctf_debug_early_finish (const char * filename)
{
  /* Emit the collected CTF information.  */
  if (ctf_debug_info_level > CTFINFO_LEVEL_NONE)
    ctf_output (filename);

  /* If emitting BTF, start translation to BTF.  */
  if (btf_debuginfo_p ())
    {
      btf_early_finish ();

      /* For LTO builds, also emit BTF now.  */
      if (flag_lto && !in_lto_p)
	btf_finish ();
    }
  else
    /* Otherwise, done with the CTF container.  */
    ctf_finalize ();
}

/* Finish CTF/BTF debug info emission.  */

void
ctf_debug_finish ()
{
  /* Emit BTF late, unless this is an LTO build in which case it was
     already done early.  */
  if (btf_debuginfo_p () && !flag_lto)
    btf_finish ();
}

#include "gt-dwarf2ctf.h"
