aboutsummaryrefslogtreecommitdiff
path: root/gcc/json.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-07-20 15:37:23 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-07-20 15:37:23 +0000
commit4a4412b9de23b153481a60cd69abcee71c3e34fb (patch)
treebfca81ed27910bef95adb2304ad0b3e69af27dd2 /gcc/json.cc
parentbf0086f1c8ff9998fb55a27f6606bccbba873e09 (diff)
downloadgcc-4a4412b9de23b153481a60cd69abcee71c3e34fb.zip
gcc-4a4412b9de23b153481a60cd69abcee71c3e34fb.tar.gz
gcc-4a4412b9de23b153481a60cd69abcee71c3e34fb.tar.bz2
Add "-fsave-optimization-record"
This patch implements a -fsave-optimization-record option, which leads to a JSON file being written out, recording the dump_* calls made (via the optinfo infrastructure). The patch includes a minimal version of the JSON patch I posted last year, with just enough support needed for optimization records (I removed all of the parser code, leaving just the code for building in-memory JSON trees and writing them to a pretty_printer). gcc/ChangeLog: * Makefile.in (OBJS): Add json.o and optinfo-emit-json.o. (CFLAGS-optinfo-emit-json.o): Define TARGET_NAME. * common.opt (fsave-optimization-record): New option. * coretypes.h (struct kv_pair): Move here from dumpfile.c. * doc/invoke.texi (-fsave-optimization-record): New option. * dumpfile.c: Include "optinfo-emit-json.h". (struct kv_pair): Move to coretypes.h. (optgroup_options): Make non-static. (dump_context::end_scope): Call optimization_records_maybe_pop_dump_scope. * dumpfile.h (optgroup_options): New decl. * json.cc: New file. * json.h: New file. * optinfo-emit-json.cc: New file. * optinfo-emit-json.h: New file. * optinfo.cc: Include "optinfo-emit-json.h". (optinfo::emit): Call optimization_records_maybe_record_optinfo. (optinfo_enabled_p): Check optimization_records_enabled_p. (optinfo_wants_inlining_info_p): Likewise. * optinfo.h: Update comment. * profile-count.c (profile_quality_as_string): New function. * profile-count.h (profile_quality_as_string): New decl. (profile_count::quality): New accessor. * selftest-run-tests.c (selftest::run_tests): Call json_cc_tests and optinfo_emit_json_cc_tests. * selftest.h (selftest::json_cc_tests): New decl. (selftest::optinfo_emit_json_cc_tests): New decl. * toplev.c: Include "optinfo-emit-json.h". (compile_file): Call optimization_records_finish. (do_compile): Call optimization_records_start. * tree-ssa-live.c: Include optinfo.h. (remove_unused_scope_block_p): Retain inlining information if optinfo_wants_inlining_info_p returns true. From-SVN: r262905
Diffstat (limited to 'gcc/json.cc')
-rw-r--r--gcc/json.cc293
1 files changed, 293 insertions, 0 deletions
diff --git a/gcc/json.cc b/gcc/json.cc
new file mode 100644
index 0000000..3c2aa77
--- /dev/null
+++ b/gcc/json.cc
@@ -0,0 +1,293 @@
+/* JSON trees
+ Copyright (C) 2017-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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "json.h"
+#include "pretty-print.h"
+#include "math.h"
+#include "selftest.h"
+
+using namespace json;
+
+/* class json::value. */
+
+/* Dump this json::value tree to OUTF.
+ No formatting is done. There are no guarantees about the order
+ in which the key/value pairs of json::objects are printed. */
+
+void
+value::dump (FILE *outf) const
+{
+ pretty_printer pp;
+ pp_buffer (&pp)->stream = outf;
+ print (&pp);
+ pp_flush (&pp);
+}
+
+/* class json::object, a subclass of json::value, representing
+ an unordered collection of key/value pairs. */
+
+/* json:object's dtor. */
+
+object::~object ()
+{
+ for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
+ {
+ free (const_cast <char *>((*it).first));
+ delete ((*it).second);
+ }
+}
+
+/* Implementation of json::value::print for json::object. */
+
+void
+object::print (pretty_printer *pp) const
+{
+ /* Note that the order is not guaranteed. */
+ pp_character (pp, '{');
+ for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
+ {
+ if (it != m_map.begin ())
+ pp_string (pp, ", ");
+ const char *key = const_cast <char *>((*it).first);
+ value *value = (*it).second;
+ pp_printf (pp, "\"%s\": ", key); // FIXME: escaping?
+ value->print (pp);
+ }
+ pp_character (pp, '}');
+}
+
+/* Set the json::value * for KEY, taking ownership of VALUE
+ (and taking a copy of KEY if necessary). */
+
+void
+object::set (const char *key, value *v)
+{
+ value **ptr = m_map.get (key);
+ if (ptr)
+ {
+ /* If the key is already present, delete the existing value
+ and overwrite it. */
+ delete *ptr;
+ *ptr = v;
+ }
+ else
+ /* If the key wasn't already present, take a copy of the key,
+ and store the value. */
+ m_map.put (xstrdup (key), v);
+}
+
+/* class json::array, a subclass of json::value, representing
+ an ordered collection of values. */
+
+/* json::array's dtor. */
+
+array::~array ()
+{
+ unsigned i;
+ value *v;
+ FOR_EACH_VEC_ELT (m_elements, i, v)
+ delete v;
+}
+
+/* Implementation of json::value::print for json::array. */
+
+void
+array::print (pretty_printer *pp) const
+{
+ pp_character (pp, '[');
+ unsigned i;
+ value *v;
+ FOR_EACH_VEC_ELT (m_elements, i, v)
+ {
+ if (i)
+ pp_string (pp, ", ");
+ v->print (pp);
+ }
+ pp_character (pp, ']');
+}
+
+/* class json::number, a subclass of json::value, wrapping a double. */
+
+/* Implementation of json::value::print for json::number. */
+
+void
+number::print (pretty_printer *pp) const
+{
+ char tmp[1024];
+ snprintf (tmp, sizeof (tmp), "%g", m_value);
+ pp_string (pp, tmp);
+}
+
+/* class json::string, a subclass of json::value. */
+
+void
+string::print (pretty_printer *pp) const
+{
+ pp_character (pp, '"');
+ for (const char *ptr = m_utf8; *ptr; ptr++)
+ {
+ char ch = *ptr;
+ switch (ch)
+ {
+ case '"':
+ pp_string (pp, "\\\"");
+ break;
+ case '\\':
+ pp_string (pp, "\\n");
+ break;
+ case '\b':
+ pp_string (pp, "\\b");
+ break;
+ case '\f':
+ pp_string (pp, "\\f");
+ break;
+ case '\n':
+ pp_string (pp, "\\n");
+ break;
+ case '\r':
+ pp_string (pp, "\\r");
+ break;
+ case '\t':
+ pp_string (pp, "\\t");
+ break;
+
+ default:
+ pp_character (pp, ch);
+ }
+ }
+ pp_character (pp, '"');
+}
+
+/* class json::literal, a subclass of json::value. */
+
+/* Implementation of json::value::print for json::literal. */
+
+void
+literal::print (pretty_printer *pp) const
+{
+ switch (m_kind)
+ {
+ case JSON_TRUE:
+ pp_string (pp, "true");
+ break;
+ case JSON_FALSE:
+ pp_string (pp, "false");
+ break;
+ case JSON_NULL:
+ pp_string (pp, "null");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests. */
+
+/* Verify that JV->print () prints EXPECTED_JSON. */
+
+static void
+assert_print_eq (const json::value &jv, const char *expected_json)
+{
+ pretty_printer pp;
+ jv.print (&pp);
+ ASSERT_STREQ (expected_json, pp_formatted_text (&pp));
+}
+
+/* Verify that JSON objects are written correctly. We can't test more than
+ one key/value pair, as we don't impose a guaranteed ordering. */
+
+static void
+test_writing_objects ()
+{
+ object obj;
+ obj.set ("foo", new json::string ("bar"));
+ assert_print_eq (obj, "{\"foo\": \"bar\"}");
+}
+
+/* Verify that JSON arrays are written correctly. */
+
+static void
+test_writing_arrays ()
+{
+ array arr;
+ assert_print_eq (arr, "[]");
+
+ arr.append (new json::string ("foo"));
+ assert_print_eq (arr, "[\"foo\"]");
+
+ arr.append (new json::string ("bar"));
+ assert_print_eq (arr, "[\"foo\", \"bar\"]");
+}
+
+/* Verify that JSON numbers are written correctly. */
+
+static void
+test_writing_numbers ()
+{
+ assert_print_eq (number (0), "0");
+ assert_print_eq (number (42), "42");
+ assert_print_eq (number (-100), "-100");
+}
+
+/* Verify that JSON strings are written correctly. */
+
+static void
+test_writing_strings ()
+{
+ string foo ("foo");
+ assert_print_eq (foo, "\"foo\"");
+
+ string contains_quotes ("before \"quoted\" after");
+ assert_print_eq (contains_quotes, "\"before \\\"quoted\\\" after\"");
+}
+
+/* Verify that JSON strings are written correctly. */
+
+static void
+test_writing_literals ()
+{
+ assert_print_eq (literal (JSON_TRUE), "true");
+ assert_print_eq (literal (JSON_FALSE), "false");
+ assert_print_eq (literal (JSON_NULL), "null");
+}
+
+/* Run all of the selftests within this file. */
+
+void
+json_cc_tests ()
+{
+ test_writing_objects ();
+ test_writing_arrays ();
+ test_writing_numbers ();
+ test_writing_strings ();
+ test_writing_literals ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */