dump-context.h 8.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* Support code for handling the various dump_* calls in dumpfile.h
   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_DUMP_CONTEXT_H
#define GCC_DUMP_CONTEXT_H 1

25
#include "dumpfile.h"
26
#include "pretty-print.h"
27
#include "selftest.h"
28
#include "optinfo.h"
29

30
class optrecord_json_writer;
31
namespace selftest { class temp_dump_context; }
32

33 34 35 36 37 38 39 40 41 42 43
/* A class for handling the various dump_* calls.

   In particular, this class has responsibility for consolidating
   the "dump_*" calls into optinfo instances (delimited by "dump_*_loc"
   calls), and emitting them.

   Putting this in a class (rather than as global state) allows
   for selftesting of this code.  */

class dump_context
{
44 45
  friend class selftest::temp_dump_context;

46 47 48 49 50
 public:
  static dump_context &get () { return *s_current; }

  ~dump_context ();

51 52
  void refresh_dumps_are_enabled ();

53 54 55 56
  void dump_loc (const dump_metadata_t &metadata,
		 const dump_user_location_t &loc);
  void dump_loc_immediate (dump_flags_t dump_kind,
			   const dump_user_location_t &loc);
57

58 59
  void dump_gimple_stmt (const dump_metadata_t &metadata,
			 dump_flags_t extra_dump_flags,
60 61
			 gimple *gs, int spc);

62 63
  void dump_gimple_stmt_loc (const dump_metadata_t &metadata,
			     const dump_user_location_t &loc,
64 65 66
			     dump_flags_t extra_dump_flags,
			     gimple *gs, int spc);

67
  void dump_gimple_expr (const dump_metadata_t &metadata,
68 69 70
			 dump_flags_t extra_dump_flags,
			 gimple *gs, int spc);

71 72 73 74 75
  void dump_gimple_expr_loc (const dump_metadata_t &metadata,
			     const dump_user_location_t &loc,
			     dump_flags_t extra_dump_flags,
			     gimple *gs,
			     int spc);
76

77
  void dump_generic_expr (const dump_metadata_t &metadata,
78 79 80
			  dump_flags_t extra_dump_flags,
			  tree t);

81 82
  void dump_generic_expr_loc (const dump_metadata_t &metadata,
			      const dump_user_location_t &loc,
83 84 85
			      dump_flags_t extra_dump_flags,
			      tree t);

86
  void dump_printf_va (const dump_metadata_t &metadata, const char *format,
87
		       va_list *ap) ATTRIBUTE_GCC_DUMP_PRINTF (3, 0);
88

89 90
  void dump_printf_loc_va (const dump_metadata_t &metadata,
			   const dump_user_location_t &loc,
91 92
			   const char *format, va_list *ap)
    ATTRIBUTE_GCC_DUMP_PRINTF (4, 0);
93 94

  template<unsigned int N, typename C>
95
  void dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value);
96

97
  void dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node);
98 99 100

  /* Managing nested scopes.  */
  unsigned int get_scope_depth () const;
101 102 103
  void begin_scope (const char *name,
		    const dump_user_location_t &user_location,
		    const dump_impl_location_t &impl_location);
104 105
  void end_scope ();

106 107 108 109 110 111
  /* Should optinfo instances be created?
     All creation of optinfos should be guarded by this predicate.
     Return true if any optinfo destinations are active.  */
  bool optinfo_enabled_p () const;

  bool optimization_records_enabled_p () const
112
  {
113
    return m_json_writer != NULL;
114
  }
115 116
  void set_json_writer (optrecord_json_writer *writer);
  void finish_any_json_writer ();
117 118 119

  void end_any_optinfo ();

120
  void emit_optinfo (const optinfo *info);
121 122
  void emit_item (optinfo_item *item, dump_flags_t dump_kind);

123 124
  bool apply_dump_filter_p (dump_flags_t dump_kind, dump_flags_t filter) const;

125
 private:
126 127 128
  optinfo &ensure_pending_optinfo (const dump_metadata_t &metadata);
  optinfo &begin_next_optinfo (const dump_metadata_t &metadata,
			       const dump_user_location_t &loc);
129 130 131 132 133 134 135 136 137

  /* The current nesting depth of dump scopes, for showing nesting
     via indentation).  */
  unsigned int m_scope_depth;

  /* The optinfo currently being accumulated since the last dump_*_loc call,
     if any.  */
  optinfo *m_pending;

138 139 140 141
  /* If -fsave-optimization-record is enabled, the heap-allocated JSON writer
     instance, otherwise NULL.  */
  optrecord_json_writer *m_json_writer;

142 143 144 145 146
  /* For use in selftests: if non-NULL, then items are to be printed
     to this, using the given flags.  */
  pretty_printer *m_test_pp;
  dump_flags_t m_test_pp_flags;

147 148 149 150 151 152 153
  /* The currently active dump_context, for use by the dump_* API calls.  */
  static dump_context *s_current;

  /* The default active context.  */
  static dump_context s_default;
};

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/* A subclass of pretty_printer for implementing dump_context::dump_printf_va.
   In particular, the formatted chunks are captured as optinfo_item instances,
   thus retaining metadata about the entities being dumped (e.g. source
   locations), rather than just as plain text.  */

class dump_pretty_printer : public pretty_printer
{
public:
  dump_pretty_printer (dump_context *context, dump_flags_t dump_kind);

  void emit_items (optinfo *dest);

private:
  /* Information on an optinfo_item that was generated during phase 2 of
     formatting.  */
  struct stashed_item
  {
    stashed_item (const char **buffer_ptr_, optinfo_item *item_)
      : buffer_ptr (buffer_ptr_), item (item_) {}
    const char **buffer_ptr;
    optinfo_item *item;
  };

  static bool format_decoder_cb (pretty_printer *pp, text_info *text,
				 const char *spec, int /*precision*/,
				 bool /*wide*/, bool /*set_locus*/,
				 bool /*verbose*/, bool */*quoted*/,
				 const char **buffer_ptr);

  bool decode_format (text_info *text, const char *spec,
		      const char **buffer_ptr);

  void stash_item (const char **buffer_ptr, optinfo_item *item);

  void emit_any_pending_textual_chunks (optinfo *dest);

  void emit_item (optinfo_item *item, optinfo *dest);

  dump_context *m_context;
  dump_flags_t m_dump_kind;
  auto_vec<stashed_item> m_stashed_items;
};

197 198
#if CHECKING_P

199 200
namespace selftest {

201 202 203 204 205 206
/* An RAII-style class for use in selftests for temporarily using a different
   dump_context.  */

class temp_dump_context
{
 public:
207
  temp_dump_context (bool forcibly_enable_optinfo,
208
		     bool forcibly_enable_dumping,
209
		     dump_flags_t test_pp_flags);
210 211 212 213
  ~temp_dump_context ();

  /* Support for selftests.  */
  optinfo *get_pending_optinfo () const { return m_context.m_pending; }
214
  const char *get_dumped_text ();
215 216

 private:
217
  pretty_printer m_pp;
218 219 220 221
  dump_context m_context;
  dump_context *m_saved;
};

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
/* Implementation detail of ASSERT_DUMPED_TEXT_EQ.  */

extern void verify_dumped_text (const location &loc,
				temp_dump_context *context,
				const char *expected_text);

/* Verify that the text dumped so far in CONTEXT equals
   EXPECTED_TEXT.
   As a side-effect, the internal buffer is 0-terminated.  */

#define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT)			\
  SELFTEST_BEGIN_STMT							\
    verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \
  SELFTEST_END_STMT


/* Verify that ITEM has the expected values.  */

void
verify_item (const location &loc,
	     const optinfo_item *item,
	     enum optinfo_item_kind expected_kind,
	     location_t expected_location,
	     const char *expected_text);

/* Verify that ITEM is a text item, with EXPECTED_TEXT.  */

#define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
  SELFTEST_BEGIN_STMT						    \
    verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
		 UNKNOWN_LOCATION, (EXPECTED_TEXT));		    \
  SELFTEST_END_STMT

/* Verify that ITEM is a tree item, with the expected values.  */

#define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
  SELFTEST_BEGIN_STMT						    \
    verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
		 (EXPECTED_LOCATION), (EXPECTED_TEXT));	    \
  SELFTEST_END_STMT

/* Verify that ITEM is a gimple item, with the expected values.  */

#define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
  SELFTEST_BEGIN_STMT						    \
    verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
		 (EXPECTED_LOCATION), (EXPECTED_TEXT));	    \
  SELFTEST_END_STMT

271 272 273 274 275 276 277 278
/* Verify that ITEM is a symtab node, with the expected values.  */

#define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
  SELFTEST_BEGIN_STMT						    \
    verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \
		 (EXPECTED_LOCATION), (EXPECTED_TEXT));	    \
  SELFTEST_END_STMT

279 280
} // namespace selftest

281 282 283
#endif /* CHECKING_P */

#endif /* GCC_DUMP_CONTEXT_H */