1 /* Support code for handling the various dump_* calls in dumpfile.h 2 Copyright (C) 2018-2021 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 22 #ifndef GCC_DUMP_CONTEXT_H 23 #define GCC_DUMP_CONTEXT_H 1 24 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 class debug_dump_context; 33 34 /* A class for handling the various dump_* calls. 35 36 In particular, this class has responsibility for consolidating 37 the "dump_*" calls into optinfo instances (delimited by "dump_*_loc" 38 calls), and emitting them. 39 40 Putting this in a class (rather than as global state) allows 41 for selftesting of this code. */ 42 43 class dump_context 44 { 45 friend class selftest::temp_dump_context; 46 friend class debug_dump_context; 47 48 public: get()49 static dump_context &get () { return *s_current; } 50 51 ~dump_context (); 52 53 void refresh_dumps_are_enabled (); 54 55 void dump_loc (const dump_metadata_t &metadata, 56 const dump_user_location_t &loc); 57 void dump_loc_immediate (dump_flags_t dump_kind, 58 const dump_user_location_t &loc); 59 60 void dump_gimple_stmt (const dump_metadata_t &metadata, 61 dump_flags_t extra_dump_flags, 62 gimple *gs, int spc); 63 64 void dump_gimple_stmt_loc (const dump_metadata_t &metadata, 65 const dump_user_location_t &loc, 66 dump_flags_t extra_dump_flags, 67 gimple *gs, int spc); 68 69 void dump_gimple_expr (const dump_metadata_t &metadata, 70 dump_flags_t extra_dump_flags, 71 gimple *gs, int spc); 72 73 void dump_gimple_expr_loc (const dump_metadata_t &metadata, 74 const dump_user_location_t &loc, 75 dump_flags_t extra_dump_flags, 76 gimple *gs, 77 int spc); 78 79 void dump_generic_expr (const dump_metadata_t &metadata, 80 dump_flags_t extra_dump_flags, 81 tree t); 82 83 void dump_generic_expr_loc (const dump_metadata_t &metadata, 84 const dump_user_location_t &loc, 85 dump_flags_t extra_dump_flags, 86 tree t); 87 88 void dump_printf_va (const dump_metadata_t &metadata, const char *format, 89 va_list *ap) ATTRIBUTE_GCC_DUMP_PRINTF (3, 0); 90 91 void dump_printf_loc_va (const dump_metadata_t &metadata, 92 const dump_user_location_t &loc, 93 const char *format, va_list *ap) 94 ATTRIBUTE_GCC_DUMP_PRINTF (4, 0); 95 96 template<unsigned int N, typename C> 97 void dump_dec (const dump_metadata_t &metadata, const poly_int<N, C> &value); 98 99 void dump_symtab_node (const dump_metadata_t &metadata, symtab_node *node); 100 101 /* Managing nested scopes. */ 102 unsigned int get_scope_depth () const; 103 void begin_scope (const char *name, 104 const dump_user_location_t &user_location, 105 const dump_impl_location_t &impl_location); 106 void end_scope (); 107 108 /* Should optinfo instances be created? 109 All creation of optinfos should be guarded by this predicate. 110 Return true if any optinfo destinations are active. */ 111 bool optinfo_enabled_p () const; 112 optimization_records_enabled_p()113 bool optimization_records_enabled_p () const 114 { 115 return m_json_writer != NULL; 116 } 117 void set_json_writer (optrecord_json_writer *writer); 118 void finish_any_json_writer (); 119 120 void end_any_optinfo (); 121 122 void emit_optinfo (const optinfo *info); 123 void emit_item (optinfo_item *item, dump_flags_t dump_kind); 124 125 bool apply_dump_filter_p (dump_flags_t dump_kind, dump_flags_t filter) const; 126 127 private: 128 optinfo &ensure_pending_optinfo (const dump_metadata_t &metadata); 129 optinfo &begin_next_optinfo (const dump_metadata_t &metadata, 130 const dump_user_location_t &loc); 131 132 /* The current nesting depth of dump scopes, for showing nesting 133 via indentation). */ 134 unsigned int m_scope_depth; 135 136 /* The optinfo currently being accumulated since the last dump_*_loc call, 137 if any. */ 138 optinfo *m_pending; 139 140 /* If -fsave-optimization-record is enabled, the heap-allocated JSON writer 141 instance, otherwise NULL. */ 142 optrecord_json_writer *m_json_writer; 143 144 /* For use in selftests: if non-NULL, then items are to be printed 145 to this, using the given flags. */ 146 pretty_printer *m_test_pp; 147 dump_flags_t m_test_pp_flags; 148 149 /* The currently active dump_context, for use by the dump_* API calls. */ 150 static dump_context *s_current; 151 152 /* The default active context. */ 153 static dump_context s_default; 154 }; 155 156 /* A subclass of pretty_printer for implementing dump_context::dump_printf_va. 157 In particular, the formatted chunks are captured as optinfo_item instances, 158 thus retaining metadata about the entities being dumped (e.g. source 159 locations), rather than just as plain text. */ 160 161 class dump_pretty_printer : public pretty_printer 162 { 163 public: 164 dump_pretty_printer (dump_context *context, dump_flags_t dump_kind); 165 166 void emit_items (optinfo *dest); 167 168 private: 169 /* Information on an optinfo_item that was generated during phase 2 of 170 formatting. */ 171 class stashed_item 172 { 173 public: stashed_item(const char ** buffer_ptr_,optinfo_item * item_)174 stashed_item (const char **buffer_ptr_, optinfo_item *item_) 175 : buffer_ptr (buffer_ptr_), item (item_) {} 176 const char **buffer_ptr; 177 optinfo_item *item; 178 }; 179 180 static bool format_decoder_cb (pretty_printer *pp, text_info *text, 181 const char *spec, int /*precision*/, 182 bool /*wide*/, bool /*set_locus*/, 183 bool /*verbose*/, bool */*quoted*/, 184 const char **buffer_ptr); 185 186 bool decode_format (text_info *text, const char *spec, 187 const char **buffer_ptr); 188 189 void stash_item (const char **buffer_ptr, optinfo_item *item); 190 191 void emit_any_pending_textual_chunks (optinfo *dest); 192 193 void emit_item (optinfo_item *item, optinfo *dest); 194 195 dump_context *m_context; 196 dump_flags_t m_dump_kind; 197 auto_vec<stashed_item> m_stashed_items; 198 }; 199 200 /* An RAII-style class for use in debug dumpers for temporarily using a 201 different dump_context. It enables full details and outputs to 202 stderr instead of the currently active dump_file. */ 203 204 class debug_dump_context 205 { 206 public: 207 debug_dump_context (); 208 ~debug_dump_context (); 209 210 private: 211 dump_context m_context; 212 dump_context *m_saved; 213 dump_flags_t m_saved_flags; 214 dump_flags_t m_saved_pflags; 215 FILE *m_saved_file; 216 }; 217 218 219 #if CHECKING_P 220 221 namespace selftest { 222 223 /* An RAII-style class for use in selftests for temporarily using a different 224 dump_context. */ 225 226 class temp_dump_context 227 { 228 public: 229 temp_dump_context (bool forcibly_enable_optinfo, 230 bool forcibly_enable_dumping, 231 dump_flags_t test_pp_flags); 232 ~temp_dump_context (); 233 234 /* Support for selftests. */ get_pending_optinfo()235 optinfo *get_pending_optinfo () const { return m_context.m_pending; } 236 const char *get_dumped_text (); 237 238 private: 239 pretty_printer m_pp; 240 dump_context m_context; 241 dump_context *m_saved; 242 }; 243 244 /* Implementation detail of ASSERT_DUMPED_TEXT_EQ. */ 245 246 extern void verify_dumped_text (const location &loc, 247 temp_dump_context *context, 248 const char *expected_text); 249 250 /* Verify that the text dumped so far in CONTEXT equals 251 EXPECTED_TEXT. 252 As a side-effect, the internal buffer is 0-terminated. */ 253 254 #define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT) \ 255 SELFTEST_BEGIN_STMT \ 256 verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \ 257 SELFTEST_END_STMT 258 259 260 /* Verify that ITEM has the expected values. */ 261 262 void 263 verify_item (const location &loc, 264 const optinfo_item *item, 265 enum optinfo_item_kind expected_kind, 266 location_t expected_location, 267 const char *expected_text); 268 269 /* Verify that ITEM is a text item, with EXPECTED_TEXT. */ 270 271 #define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \ 272 SELFTEST_BEGIN_STMT \ 273 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \ 274 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \ 275 SELFTEST_END_STMT 276 277 /* Verify that ITEM is a tree item, with the expected values. */ 278 279 #define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 280 SELFTEST_BEGIN_STMT \ 281 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \ 282 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 283 SELFTEST_END_STMT 284 285 /* Verify that ITEM is a gimple item, with the expected values. */ 286 287 #define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 288 SELFTEST_BEGIN_STMT \ 289 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \ 290 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 291 SELFTEST_END_STMT 292 293 /* Verify that ITEM is a symtab node, with the expected values. */ 294 295 #define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 296 SELFTEST_BEGIN_STMT \ 297 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \ 298 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 299 SELFTEST_END_STMT 300 301 } // namespace selftest 302 303 #endif /* CHECKING_P */ 304 305 #endif /* GCC_DUMP_CONTEXT_H */ 306