/* DWARF CU data structure

   Copyright (C) 2021-2025 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/>.  */

#include "dwarf2/cu.h"
#include "dwarf2/read.h"
#include "objfiles.h"
#include "filenames.h"
#include "producer.h"
#include "gdbsupport/pathstuff.h"

/* Initialize dwarf2_cu to read PER_CU, in the context of PER_OBJFILE.  */

dwarf2_cu::dwarf2_cu (dwarf2_per_cu *per_cu, dwarf2_per_objfile *per_objfile)
  : per_cu (per_cu),
    per_objfile (per_objfile),
    m_mark (false),
    has_loclist (false),
    m_checked_producer (false),
    m_producer_is_gxx_lt_4_6 (false),
    m_producer_is_gcc_lt_4_5 (false),
    m_producer_is_gcc_lt_4_3 (false),
    m_producer_is_gcc_ge_4 (false),
    m_producer_is_gcc_11 (false),
    m_producer_is_gcc (false),
    m_producer_is_icc (false),
    m_producer_is_icc_lt_14 (false),
    m_producer_is_codewarrior (false),
    m_producer_is_clang (false),
    m_producer_is_gas_lt_2_38 (false),
    m_producer_is_gas_2_39 (false),
    m_producer_is_gas_ge_2_40 (false),
    m_producer_is_realview (false),
    m_producer_is_xlc (false),
    m_producer_is_xlc_opencl (false),
    m_producer_is_gf77 (false),
    m_producer_is_ggo (false),
    processing_has_namespace_info (false)
{
}

/* See cu.h.  */

struct type *
dwarf2_cu::addr_sized_int_type (bool unsigned_p) const
{
  int addr_size = this->per_cu->addr_size ();
  struct type *result = objfile_int_type (this->per_objfile->objfile,
					  addr_size, unsigned_p);
  type_allocator alloc (per_objfile->objfile, lang ());
  return alloc.copy_type (result);
}

/* Start a symtab for DWARF.  NAME, COMP_DIR, LOW_PC are passed to the
   buildsym_compunit constructor.  */

struct compunit_symtab *
dwarf2_cu::start_compunit_symtab (const char *name, const char *comp_dir,
				  CORE_ADDR low_pc)
{
  gdb_assert (m_builder == nullptr);

  std::string name_for_id_holder;
  const char *name_for_id = name;

  /* Prepend the compilation directory to the filename if needed (if not
     absolute already) to get the "name for id" for our main symtab.  The name
     for the main file coming from the line table header will be generated using
     the same logic, so will hopefully match what we pass here.  */
  if (!IS_ABSOLUTE_PATH (name) && comp_dir != nullptr)
    {
      name_for_id_holder = path_join (comp_dir, name);
      name_for_id = name_for_id_holder.c_str ();
    }

  m_builder = std::make_unique<buildsym_compunit> (this->per_objfile->objfile,
						   name,
						   comp_dir,
						   name_for_id,
						   lang (),
						   low_pc);

  list_in_scope = get_builder ()->get_file_symbols ();

  /* DWARF versions are restricted to [2, 5], thanks to the check in
     read_comp_unit_head.  */
  gdb_assert (this->header.version >= 2 && this->header.version <= 5);
  static const char *debugformat_strings[] = {
    "DWARF 2",
    "DWARF 3",
    "DWARF 4",
    "DWARF 5",
  };
  const char *debugformat = debugformat_strings[this->header.version - 2];

  get_builder ()->record_debugformat (debugformat);
  get_builder ()->record_producer (m_producer);

  processing_has_namespace_info = false;

  return get_builder ()->get_compunit_symtab ();
}

/* See read.h.  */

struct type *
dwarf2_cu::addr_type () const
{
  struct objfile *objfile = this->per_objfile->objfile;
  struct type *void_type = builtin_type (objfile)->builtin_void;
  struct type *addr_type = lookup_pointer_type (void_type);
  int addr_size = this->per_cu->addr_size ();

  if (addr_type->length () == addr_size)
    return addr_type;

  addr_type = addr_sized_int_type (addr_type->is_unsigned ());
  return addr_type;
}

/* See dwarf2/cu.h.  */

void
dwarf2_cu::mark ()
{
  if (m_mark)
    return;

  m_mark = true;

  for (dwarf2_per_cu *per_cu : m_dependencies)
    {
      /* cu->m_dependencies references may not yet have been ever
	 read if QUIT aborts reading of the chain.  As such
	 dependencies remain valid it is not much useful to track
	 and undo them during QUIT cleanups.  */
      dwarf2_cu *cu = per_objfile->get_cu (per_cu);

      if (cu == nullptr)
	continue;

      cu->mark ();
    }
}

/* See dwarf2/cu.h.  */

buildsym_compunit *
dwarf2_cu::get_builder ()
{
  /* If this CU has a builder associated with it, use that.  */
  if (m_builder != nullptr)
    return m_builder.get ();

  if (per_objfile->sym_cu != nullptr)
    return per_objfile->sym_cu->m_builder.get ();

  gdb_assert_not_reached ("");
}

/* See dwarf2/cu.h.  */

void
dwarf2_cu::set_producer (const char *producer)
{
  gdb_assert (m_producer == nullptr || strcmp (producer, m_producer) == 0);
  m_producer = producer;

  int major, minor;

  if (m_producer == nullptr)
    {
      /* For unknown compilers expect their behavior is DWARF version
	 compliant.

	 GCC started to support .debug_types sections by -gdwarf-4 since
	 gcc-4.5.x.  As the .debug_types sections are missing DW_AT_producer
	 for their space efficiency GDB cannot workaround gcc-4.5.x -gdwarf-4
	 combination.  gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility
	 interpreted incorrectly by GDB now - GCC PR debug/48229.  */
    }
  else if (::producer_is_gcc (m_producer, &major, &minor))
    {
      m_producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
      m_producer_is_gcc_lt_4_5 = major < 4 || (major == 4 && minor < 5);
      m_producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
      m_producer_is_gcc_ge_4 = major >= 4;
      m_producer_is_gcc_11 = major == 11;
      m_producer_is_gcc = true;
    }
  else if (::producer_is_icc (m_producer, &major, &minor))
    {
      m_producer_is_icc = true;
      m_producer_is_icc_lt_14 = major < 14;
    }
  else if (startswith (m_producer, "CodeWarrior S12/L-ISA"))
    m_producer_is_codewarrior = true;
  else if (::producer_is_clang (m_producer, &major, &minor))
    m_producer_is_clang = true;
  else if (::producer_is_gas (m_producer, &major, &minor))
    {
      m_producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38);
      m_producer_is_gas_2_39 = major == 2 && minor == 39;
      m_producer_is_gas_ge_2_40 = major > 2 || (major == 2 && minor >= 40);
    }
  else if (::producer_is_realview (m_producer))
    m_producer_is_realview = true;
  else if (startswith (m_producer, "IBM(R) XL C/C++ Advanced Edition"))
    m_producer_is_xlc = true;
  else if (strstr (m_producer, "IBM XL C for OpenCL") != nullptr)
    m_producer_is_xlc_opencl = true;
  else
    {
      /* For other non-GCC compilers, expect their behavior is DWARF version
	 compliant.  */
    }

  if (m_producer != nullptr)
    {
      if (strstr (m_producer, "GNU F77") != nullptr)
	m_producer_is_gf77 = true;
      else if (strstr (m_producer, "GNU Go ") != nullptr)
	m_producer_is_ggo = true;
    }

  m_checked_producer = true;
}
