1 /* Support code for handling the various dump_* calls in dumpfile.h 2 Copyright (C) 2018-2019 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: 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 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 struct stashed_item 170 { 171 stashed_item (const char **buffer_ptr_, optinfo_item *item_) 172 : buffer_ptr (buffer_ptr_), item (item_) {} 173 const char **buffer_ptr; 174 optinfo_item *item; 175 }; 176 177 static bool format_decoder_cb (pretty_printer *pp, text_info *text, 178 const char *spec, int /*precision*/, 179 bool /*wide*/, bool /*set_locus*/, 180 bool /*verbose*/, bool */*quoted*/, 181 const char **buffer_ptr); 182 183 bool decode_format (text_info *text, const char *spec, 184 const char **buffer_ptr); 185 186 void stash_item (const char **buffer_ptr, optinfo_item *item); 187 188 void emit_any_pending_textual_chunks (optinfo *dest); 189 190 void emit_item (optinfo_item *item, optinfo *dest); 191 192 dump_context *m_context; 193 dump_flags_t m_dump_kind; 194 auto_vec<stashed_item> m_stashed_items; 195 }; 196 197 #if CHECKING_P 198 199 namespace selftest { 200 201 /* An RAII-style class for use in selftests for temporarily using a different 202 dump_context. */ 203 204 class temp_dump_context 205 { 206 public: 207 temp_dump_context (bool forcibly_enable_optinfo, 208 bool forcibly_enable_dumping, 209 dump_flags_t test_pp_flags); 210 ~temp_dump_context (); 211 212 /* Support for selftests. */ 213 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 dump_context m_context; 219 dump_context *m_saved; 220 }; 221 222 /* Implementation detail of ASSERT_DUMPED_TEXT_EQ. */ 223 224 extern void verify_dumped_text (const location &loc, 225 temp_dump_context *context, 226 const char *expected_text); 227 228 /* Verify that the text dumped so far in CONTEXT equals 229 EXPECTED_TEXT. 230 As a side-effect, the internal buffer is 0-terminated. */ 231 232 #define ASSERT_DUMPED_TEXT_EQ(CONTEXT, EXPECTED_TEXT) \ 233 SELFTEST_BEGIN_STMT \ 234 verify_dumped_text (SELFTEST_LOCATION, &(CONTEXT), (EXPECTED_TEXT)); \ 235 SELFTEST_END_STMT 236 237 238 /* Verify that ITEM has the expected values. */ 239 240 void 241 verify_item (const location &loc, 242 const optinfo_item *item, 243 enum optinfo_item_kind expected_kind, 244 location_t expected_location, 245 const char *expected_text); 246 247 /* Verify that ITEM is a text item, with EXPECTED_TEXT. */ 248 249 #define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \ 250 SELFTEST_BEGIN_STMT \ 251 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \ 252 UNKNOWN_LOCATION, (EXPECTED_TEXT)); \ 253 SELFTEST_END_STMT 254 255 /* Verify that ITEM is a tree item, with the expected values. */ 256 257 #define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 258 SELFTEST_BEGIN_STMT \ 259 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \ 260 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 261 SELFTEST_END_STMT 262 263 /* Verify that ITEM is a gimple item, with the expected values. */ 264 265 #define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 266 SELFTEST_BEGIN_STMT \ 267 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \ 268 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 269 SELFTEST_END_STMT 270 271 /* Verify that ITEM is a symtab node, with the expected values. */ 272 273 #define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \ 274 SELFTEST_BEGIN_STMT \ 275 verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \ 276 (EXPECTED_LOCATION), (EXPECTED_TEXT)); \ 277 SELFTEST_END_STMT 278 279 } // namespace selftest 280 281 #endif /* CHECKING_P */ 282 283 #endif /* GCC_DUMP_CONTEXT_H */ 284