1 /* Support code for handling the various dump_* calls in dumpfile.h 2 Copyright (C) 2018-2020 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 33 /* A class for handling the various dump_* calls. 34 35 In particular, this class has responsibility for consolidating 36 the "dump_*" calls into optinfo instances (delimited by "dump_*_loc" 37 calls), and emitting them. 38 39 Putting this in a class (rather than as global state) allows 40 for selftesting of this code. */ 41 42 class dump_context 43 { 44 friend class selftest::temp_dump_context; 45 46 public: get()47 static dump_context &get () { return *s_current; } 48 49 ~dump_context (); 50 51 void refresh_dumps_are_enabled (); 52 53 void dump_loc (const dump_metadata_t &metadata, 54 const dump_user_location_t &loc); 55 void dump_loc_immediate (dump_flags_t dump_kind, 56 const dump_user_location_t &loc); 57 58 void dump_gimple_stmt (const dump_metadata_t &metadata, 59 dump_flags_t extra_dump_flags, 60 gimple *gs, int spc); 61 62 void dump_gimple_stmt_loc (const dump_metadata_t &metadata, 63 const dump_user_location_t &loc, 64 dump_flags_t extra_dump_flags, 65 gimple *gs, int spc); 66 67 void dump_gimple_expr (const dump_metadata_t &metadata, 68 dump_flags_t extra_dump_flags, 69 gimple *gs, int spc); 70 71 void dump_gimple_expr_loc (const dump_metadata_t &metadata, 72 const dump_user_location_t &loc, 73 dump_flags_t extra_dump_flags, 74 gimple *gs, 75 int spc); 76 77 void dump_generic_expr (const dump_metadata_t &metadata, 78 dump_flags_t extra_dump_flags, 79 tree t); 80 81 void dump_generic_expr_loc (const dump_metadata_t &metadata, 82 const dump_user_location_t &loc, 83 dump_flags_t extra_dump_flags, 84 tree t); 85 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 void dump_printf_loc_va (const dump_metadata_t &metadata, 90 const dump_user_location_t &loc, 91 const char *format, va_list *ap) 92 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 /* Managing nested scopes. */ 100 unsigned int get_scope_depth () const; 101 void begin_scope (const char *name, 102 const dump_user_location_t &user_location, 103 const dump_impl_location_t &impl_location); 104 void end_scope (); 105 106 /* Should optinfo instances be created? 107 All creation of optinfos should be guarded by this predicate. 108 Return true if any optinfo destinations are active. */ 109 bool optinfo_enabled_p () const; 110 optimization_records_enabled_p()111 bool optimization_records_enabled_p () const 112 { 113 return m_json_writer != NULL; 114 } 115 void set_json_writer (optrecord_json_writer *writer); 116 void finish_any_json_writer (); 117 118 void end_any_optinfo (); 119 120 void emit_optinfo (const optinfo *info); 121 void emit_item (optinfo_item *item, dump_flags_t dump_kind); 122 123 bool apply_dump_filter_p (dump_flags_t dump_kind, dump_flags_t filter) const; 124 125 private: 126 optinfo &ensure_pending_optinfo (const dump_metadata_t &metadata); 127 optinfo &begin_next_optinfo (const dump_metadata_t &metadata, 128 const dump_user_location_t &loc); 129 130 /* The current nesting depth of dump scopes, for showing nesting 131 via indentation). */ 132 unsigned int m_scope_depth; 133 134 /* The optinfo currently being accumulated since the last dump_*_loc call, 135 if any. */ 136 optinfo *m_pending; 137 138 /* If -fsave-optimization-record is enabled, the heap-allocated JSON writer 139 instance, otherwise NULL. */ 140 optrecord_json_writer *m_json_writer; 141 142 /* For use in selftests: if non-NULL, then items are to be printed 143 to this, using the given flags. */ 144 pretty_printer *m_test_pp; 145 dump_flags_t m_test_pp_flags; 146 147 /* The currently active dump_context, for use by the dump_* API calls. */ 148 static dump_context *s_current; 149 150 /* The default active context. */ 151 static dump_context s_default; 152 }; 153 154 /* A subclass of pretty_printer for implementing dump_context::dump_printf_va. 155 In particular, the formatted chunks are captured as optinfo_item instances, 156 thus retaining metadata about the entities being dumped (e.g. source 157 locations), rather than just as plain text. */ 158 159 class dump_pretty_printer : public pretty_printer 160 { 161 public: 162 dump_pretty_printer (dump_context *context, dump_flags_t dump_kind); 163 164 void emit_items (optinfo *dest); 165 166 private: 167 /* Information on an optinfo_item that was generated during phase 2 of 168 formatting. */ 169 class stashed_item 170 { 171 public: stashed_item(const char ** buffer_ptr_,optinfo_item * item_)172 stashed_item (const char **buffer_ptr_, optinfo_item *item_) 173 : buffer_ptr (buffer_ptr_), item (item_) {} 174 const char **buffer_ptr; 175 optinfo_item *item; 176 }; 177 178 static bool format_decoder_cb (pretty_printer *pp, text_info *text, 179 const char *spec, int /*precision*/, 180 bool /*wide*/, bool /*set_locus*/, 181 bool /*verbose*/, bool */*quoted*/, 182 const char **buffer_ptr); 183 184 bool decode_format (text_info *text, const char *spec, 185 const char **buffer_ptr); 186 187 void stash_item (const char **buffer_ptr, optinfo_item *item); 188 189 void emit_any_pending_textual_chunks (optinfo *dest); 190 191 void emit_item (optinfo_item *item, optinfo *dest); 192 193 dump_context *m_context; 194 dump_flags_t m_dump_kind; 195 auto_vec<stashed_item> m_stashed_items; 196 }; 197 198 #if CHECKING_P 199 200 namespace selftest { 201 202 /* An RAII-style class for use in selftests for temporarily using a different 203 dump_context. */ 204 205 class temp_dump_context 206 { 207 public: 208 temp_dump_context (bool forcibly_enable_optinfo, 209 bool forcibly_enable_dumping, 210 dump_flags_t test_pp_flags); 211 ~temp_dump_context (); 212 213 /* Support for selftests. */ get_pending_optinfo()214 optinfo *get_pending_optinfo () const { return m_context.m_pending; } 215 const char *get_dumped_text (); 216 217 private: 218 pretty_printer m_pp; 219 dump_context m_context; 220 dump_context *m_saved; 221 }; 222 223 /* Implementation detail of ASSERT_DUMPED_TEXT_EQ. */ 224 225 extern void verify_dumped_text (const location &loc, 226 temp_dump_context *context, 227 const char *expected_text); 228 229 /* Verify that the text dumped so far in CONTEXT equals 230 EXPECTED_TEXT. 231 As a side-effect, the internal buffer is 0-terminated. */ 232 233 #define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT) \ 234 SELFTEST_BEGIN_STMT \ 235 verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \ 236 SELFTEST_END_STMT 237 238 239 /* Verify that ITEM has the expected values. */ 240 241 void 242 verify_item (const location &loc, 243 const optinfo_item *item, 244 enum optinfo_item_kind expected_kind, 245 location_t expected_location, 246 const char *expected_text); 247 248 /* Verify that ITEM is a text item, with EXPECTED_TEXT. */ 249 250 #define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \ 251 SELFTEST_BEGIN_STMT \ 252 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \ 253 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \ 254 SELFTEST_END_STMT 255 256 /* Verify that ITEM is a tree item, with the expected values. */ 257 258 #define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 259 SELFTEST_BEGIN_STMT \ 260 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \ 261 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 262 SELFTEST_END_STMT 263 264 /* Verify that ITEM is a gimple item, with the expected values. */ 265 266 #define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 267 SELFTEST_BEGIN_STMT \ 268 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \ 269 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 270 SELFTEST_END_STMT 271 272 /* Verify that ITEM is a symtab node, with the expected values. */ 273 274 #define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 275 SELFTEST_BEGIN_STMT \ 276 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \ 277 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 278 SELFTEST_END_STMT 279 280 } // namespace selftest 281 282 #endif /* CHECKING_P */ 283 284 #endif /* GCC_DUMP_CONTEXT_H */ 285