/* Optimization information.
   Copyright (C) 2018 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

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

#ifndef GCC_OPTINFO_H
#define GCC_OPTINFO_H

/* An "optinfo" is a bundle of information describing part of an
   optimization, which can be emitted to zero or more of several
   destinations, such as:

   * saved to a file as an "optimization record"

   They are generated in response to calls to the "dump_*" API in
   dumpfile.h; repeated calls to the "dump_*" API are consolidated
   into a pending optinfo instance, with a "dump_*_loc" starting a new
   optinfo instance.

   The data sent to the dump calls are captured within the pending optinfo
   instance as a sequence of optinfo_items.  For example, given:

      if (dump_enabled_p ())
        {
          dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                           "not vectorized: live stmt not supported: ");
          dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
        }

   the "dump_printf_loc" call begins a new optinfo containing two items:
   (1) a text item containing "not vectorized: live stmt not supported: "
   (2) a gimple item for "stmt"

   Dump destinations are thus able to access rich metadata about the
   items when the optinfo is emitted to them, rather than just having plain
   text.  For example, when saving the above optinfo to a file as an
   "optimization record", the record could capture the source location of
   "stmt" above, rather than just its textual form.

   The currently pending optinfo is emitted and deleted:
   * each time a "dump_*_loc" call occurs (which starts the next optinfo), or
   * when the dump files are changed (at the end of a pass)

   Dumping to an optinfo instance is non-trivial (due to building optinfo_item
   instances), so all usage should be guarded by

     if (optinfo_enabled_p ())

   which is off by default.  */


/* Forward decls.  */
struct opt_pass;
class optinfo_item;

/* Return true if any of the active optinfo destinations make use
   of inlining information.
   (if true, then the information is preserved).  */

extern bool optinfo_wants_inlining_info_p ();

/* The various kinds of optinfo.  */

enum optinfo_kind
{
  OPTINFO_KIND_SUCCESS,
  OPTINFO_KIND_FAILURE,
  OPTINFO_KIND_NOTE,
  OPTINFO_KIND_SCOPE
};

extern const char *optinfo_kind_to_string (enum optinfo_kind kind);

class dump_context;

/* A bundle of information describing part of an optimization.  */

class optinfo
{
  friend class dump_context;

 public:
  optinfo (const dump_location_t &loc,
	   enum optinfo_kind kind,
	   opt_pass *pass)
  : m_loc (loc), m_kind (kind), m_pass (pass), m_items ()
  {}
  ~optinfo ();

  const dump_location_t &
  get_dump_location () const { return m_loc; }

  const dump_user_location_t &
  get_user_location () const { return m_loc.get_user_location (); }

  const dump_impl_location_t &
  get_impl_location () const { return m_loc.get_impl_location (); }

  enum optinfo_kind get_kind () const { return m_kind; }
  opt_pass *get_pass () const { return m_pass; }
  unsigned int num_items () const { return m_items.length (); }
  const optinfo_item *get_item (unsigned int i) const { return m_items[i]; }

  location_t get_location_t () const { return m_loc.get_location_t (); }
  profile_count get_count () const { return m_loc.get_count (); }

  void add_item (optinfo_item *item);

  void emit_for_opt_problem () const;

 private:
  /* Pre-canned ways of manipulating the optinfo, for use by friend class
     dump_context.  */
  void handle_dump_file_kind (dump_flags_t);

 private:
  dump_location_t m_loc;
  enum optinfo_kind m_kind;
  opt_pass *m_pass;
  auto_vec <optinfo_item *> m_items;
};

/* An enum for discriminating between different kinds of optinfo_item.  */

enum optinfo_item_kind
{
  OPTINFO_ITEM_KIND_TEXT,
  OPTINFO_ITEM_KIND_TREE,
  OPTINFO_ITEM_KIND_GIMPLE,
  OPTINFO_ITEM_KIND_SYMTAB_NODE
};

/* An item within an optinfo.  */

class optinfo_item
{
 public:
  optinfo_item (enum optinfo_item_kind kind, location_t location,
		char *text);
  ~optinfo_item ();

  enum optinfo_item_kind get_kind () const { return m_kind; }
  location_t get_location () const { return m_location; }
  const char *get_text () const { return m_text; }

 private:
  /* Metadata (e.g. for optimization records).  */
  enum optinfo_item_kind m_kind;
  location_t m_location;

  /* The textual form of the item, owned by the item.  */
  char *m_text;
};

#endif /* #ifndef GCC_OPTINFO_H */
