[07/12] Add deferred-locations.h/cc
Commit Message
libcpp requires locations to be created as if by a tokenizer, creating
them by filename, in ascending order of line/column.
This patch adds support classes that allow the creation of locations
in arbitrary orders, by deferring all location creation,
grouping things up by filename/line, and then creating the linemap
entries in a post-processing phase.
gcc/ChangeLog:
* deferred-locations.cc: New file, adapted from code in
jit/jit-playback.cc.
* deferred-locations.h: New file.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
gcc/deferred-locations.cc | 231 ++++++++++++++++++++++++++++++++++++++
gcc/deferred-locations.h | 52 +++++++++
2 files changed, 283 insertions(+)
create mode 100644 gcc/deferred-locations.cc
create mode 100644 gcc/deferred-locations.h
new file mode 100644
@@ -0,0 +1,231 @@
+/* Support for deferred creation of location_t values.
+ Copyright (C) 2013-2022 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 "deferred-locations.h"
+
+/* Concrete implementation for use by deferred_locations. */
+
+class deferred_locations_impl
+{
+public:
+ class source_file;
+ class source_line;
+ class source_location;
+
+ /* A specific location on a source line, with a saved location_t *
+ to write back to. */
+ class source_location
+ {
+ public:
+ source_location (int column_num, location_t *out_loc)
+ : m_column_num (column_num), m_out_loc (out_loc)
+ {
+ }
+
+ int get_column_num () const { return m_column_num; }
+
+ /* qsort comparator for comparing pairs of source_location *,
+ ordering them by column number. */
+
+ static int
+ comparator (const void *lhs, const void *rhs)
+ {
+ const source_location &location_lhs
+ = *static_cast<const source_location *> (lhs);
+ const source_location &location_rhs
+ = *static_cast<const source_location *> (rhs);
+ return location_lhs.m_column_num - location_rhs.m_column_num;
+ }
+
+ void generate_location_t_value () const
+ {
+ *m_out_loc = linemap_position_for_column (line_table, m_column_num);
+ }
+
+ private:
+ int m_column_num;
+ location_t *m_out_loc;
+ };
+
+ /* A source line, with one or more locations of interest. */
+ class source_line
+ {
+ public:
+ source_line (int line_num) : m_line_num (line_num) {}
+
+ source_location *
+ get_location (int column_num, location_t *out_loc);
+
+ int get_line_num () const { return m_line_num; }
+
+ void add_location (const expanded_location &exploc,
+ location_t *out_loc)
+ {
+ m_locations.safe_push (source_location (exploc.column, out_loc));
+ }
+
+ /* qsort comparator for comparing pairs source_line *,
+ ordering them by line number. */
+
+ static int
+ comparator (const void *lhs, const void *rhs)
+ {
+ const source_line *line_lhs
+ = *static_cast<const source_line * const*> (lhs);
+ const source_line *line_rhs
+ = *static_cast<const source_line * const*> (rhs);
+ return line_lhs->get_line_num () - line_rhs->get_line_num ();
+ }
+
+ void generate_location_t_values ()
+ {
+ /* Determine maximum column within this line. */
+ m_locations.qsort (source_location::comparator);
+ gcc_assert (m_locations.length () > 0);
+ source_location *final_column = &m_locations[m_locations.length () - 1];
+ int max_col = final_column->get_column_num ();
+
+ linemap_line_start (line_table, m_line_num, max_col);
+ for (auto loc_iter : m_locations)
+ loc_iter.generate_location_t_value ();
+ }
+
+ private:
+ int m_line_num;
+ auto_vec<source_location> m_locations;
+ };
+
+ /* A set of locations, all sharing a filename */
+ class source_file
+ {
+ public:
+ source_file (const char *filename)
+ : m_filename (xstrdup (filename))
+ {
+ }
+ ~source_file ()
+ {
+ free (m_filename);
+ }
+
+ source_line *
+ get_source_line (int line_num);
+
+ const char*
+ get_filename () const { return m_filename; }
+
+ bool
+ matches (const char *filename)
+ {
+ return ((filename == NULL && m_filename == NULL)
+ || ((filename && m_filename)
+ && 0 == strcmp (filename, m_filename)));
+ }
+
+ void add_location (const expanded_location &exploc,
+ location_t *out_loc)
+ {
+ source_line *line = get_or_create_line (exploc.line);
+ line->add_location (exploc, out_loc);
+ }
+
+ void generate_location_t_values ()
+ {
+ linemap_add (line_table, LC_ENTER, false, xstrdup (m_filename), 0);
+
+ /* Sort lines by ascending line numbers. */
+ m_source_lines.qsort (source_line::comparator);
+
+ for (auto line_iter : m_source_lines)
+ line_iter->generate_location_t_values ();
+
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ }
+
+ private:
+ source_line *get_or_create_line (int line_num)
+ {
+ // FIXME: something better than linear search here?
+ for (auto iter : m_source_lines)
+ if (line_num == iter->get_line_num ())
+ return iter;
+ source_line *line = new source_line (line_num);
+ m_source_lines.safe_push (line);
+ return line;
+ }
+
+ char *m_filename;
+ auto_delete_vec<source_line> m_source_lines;
+ };
+
+ void add_location (const expanded_location &exploc,
+ location_t *out_loc)
+ {
+ source_file *f = get_or_create_file (exploc.file);
+ f->add_location (exploc, out_loc);
+ }
+
+ void generate_location_t_values ()
+ {
+ for (auto file_iter : m_source_files)
+ file_iter->generate_location_t_values ();
+ }
+
+private:
+ source_file *get_or_create_file (const char *filename)
+ {
+ // FIXME: something better than linear search here?
+ for (auto iter : m_source_files)
+ if (iter->matches (filename))
+ return iter;
+ source_file *f = new source_file (filename);
+ m_source_files.safe_push (f);
+ return f;
+ }
+ auto_delete_vec<source_file> m_source_files;
+};
+
+/* class deferred_locations. */
+
+deferred_locations::deferred_locations ()
+: m_pimpl (new deferred_locations_impl ())
+{
+}
+
+deferred_locations::~deferred_locations ()
+{
+ delete m_pimpl;
+}
+
+void
+deferred_locations::add_location (const expanded_location &exploc,
+ location_t *out_loc)
+{
+ m_pimpl->add_location (exploc, out_loc);
+}
+
+void
+deferred_locations::generate_location_t_values ()
+{
+ m_pimpl->generate_location_t_values ();
+}
new file mode 100644
@@ -0,0 +1,52 @@
+/* Support for deferred creation of location_t values.
+ Copyright (C) 2013-2022 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 DEFERRED_LOCATIONS_H
+#define DEFERRED_LOCATIONS_H
+
+class deferred_locations_impl;
+
+/* Dealing with the linemap API.
+
+ libcpp requires locations to be created as if by
+ a tokenizer, creating them by filename, in ascending order of
+ line/column.
+
+ This class is for supporting code that allows the creation of locations
+ in arbitrary orders, by deferring all location creation,
+ grouping things up by filename/line, and then creating the linemap
+ entries in a post-processing phase. */
+
+class deferred_locations
+{
+ public:
+ deferred_locations ();
+ ~deferred_locations ();
+
+ void add_location (const expanded_location &exploc,
+ location_t *loc);
+
+ void generate_location_t_values ();
+
+ private:
+ deferred_locations_impl *m_pimpl;
+};
+
+#endif /* DEFERRED_LOCATIONS_H */