This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 3/4] Extract deferred-location handling from jit
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: David Malcolm <dmalcolm at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 6 May 2016 12:36:09 +0200
- Subject: Re: [PATCH 3/4] Extract deferred-location handling from jit
- Authentication-results: sourceware.org; auth=none
- References: <1462394970-55471-1-git-send-email-dmalcolm at redhat dot com> <1462394970-55471-4-git-send-email-dmalcolm at redhat dot com>
On Wed, May 4, 2016 at 10:49 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> In order to faithfully load RTL dumps that contain references to
> source locations, the RTL frontend needs to be able to parse file
> and line information and turn then into location_t values.
>
> Unfortunately, the libcpp API makes it rather fiddly to create
> location_t values from a sequence of arbitrary file/line pairs: the
> API assumes that the locations are created in ascending order as
> if we were parsing the source file, but as we read an RTL dump,
> the insns could be jumping forwards and backwards in lines and
> between files. Also, if we want to support column numbers, the
> presence of a very high column number could exceed the bits available
> in a line_map_ordinary for storing it.
>
> The JIT has some code for handling this, in gcc/jit/jit-playback.[ch],
> (since the JIT support source location information, and doesn't impose
> any ordering requirement on users of the API).
>
> This patch moves the relevant code from
> gcc/jit/jit-playback.[ch]
> into a new pair of files:
> gcc/deferred-locations.[ch]
>
> The idea is that a deferred_locations instances manages these
> "deferred locations"; they are created, and then all of the location_t
> values are created at once by calling
> deferred_locations::add_to_line_table
> After this call, the actual location_t values can be read from out of
> deferred_location instances.
>
> There are some suboptimal parts of the code (some linear searches, and
> the use of gc), but it's mostly a move of existing code from out of the
> jit subdirectory and into "gcc" proper for reuse by the RTL frontend.
>
> This is likely to be useful for the gimple frontend as well.
>
> OK for trunk?
The LTO FE faces similar issues - see lto-streamer-in.c
Richard.
> gcc/ChangeLog:
> * Makefile.in (OBJS): Add deferred-locations.o.
> * deferred-locations.c: New file, adapted from parts of
> jit/jit-playback.c.
> * deferred-locations.h: New file, adapted from parts of
> jit/jit-playback.h.
>
> gcc/jit/ChangeLog:
> * jit-common.h: Include deferred-locations.h.
> (gcc::jit::playback::source_file): Remove forward decl.
> (gcc::jit::playback::source_line): Likewise.
> (gcc::jit::playback::location): Replace forward decl, with
> a typedef, aliasing deferred_location.
> * jit-playback.c (gcc::jit::playback::context::context): Remove
> create call on m_source_files.
> (line_comparator): Move to deferred-locations.c.
> (location_comparator): Likewise.
> (handle_locations): Move logic to deferred-locations.c, as
> deferred_locations::add_to_line_table.
> (get_recording_loc): New function.
> (gcc::jit::playback::context::add_error): Call get_recording_loc
> as a function, rather than as a method.
> (gcc::jit::playback::context::add_error_va): Likewise.
> (gcc::jit::playback::context::get_source_file): Update return type
> to reflect move of source_file to deferred-locations.h.
> Replace body with a call to m_deferred_locations.get_source_file.
> (gcc::jit::playback::source_file::source_file): Move to
> deferred-locations.h, losing the namespaces.
> (gcc::jit::playback::source_file::finalizer): Likewise.
> (gcc::jit::playback::source_file::get_source_line): Likewise.
> (gcc::jit::playback::source_line::source_line): Likewise.
> (gcc::jit::playback::source_line::finalizer): Likewise.
> (gcc::jit::playback::source_line::get_location): Likewise.
> (gcc::jit::playback::location::location): Likewise, renaming to
> deferred_location.
> * jit-playback.h: Include deferred-locations.h.
> (gcc::jit::playback::context::m_source_files): Replace field with
> m_deferred_locations.
> (gcc::jit::playback::source_file): Move to deferred-locations.h,
> losing the namespaces.
> (gcc::jit::playback::source_line): Likewise.
> (gcc::jit::playback::location): Likewise, renaming to
> deferred_location. Eliminate get_recording_loc accessor and
> m_recording_loc field in favor of get_user_data and m_user_data
> respectively.
> ---
> gcc/Makefile.in | 1 +
> gcc/deferred-locations.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++
> gcc/deferred-locations.h | 139 +++++++++++++++++++++++++++
> gcc/jit/jit-common.h | 5 +-
> gcc/jit/jit-playback.c | 194 ++++----------------------------------
> gcc/jit/jit-playback.h | 73 +-------------
> 6 files changed, 402 insertions(+), 250 deletions(-)
> create mode 100644 gcc/deferred-locations.c
> create mode 100644 gcc/deferred-locations.h
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 6c5adc0..c61f303 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1239,6 +1239,7 @@ OBJS = \
> dce.o \
> ddg.o \
> debug.o \
> + deferred-locations.o \
> df-core.o \
> df-problems.o \
> df-scan.o \
> diff --git a/gcc/deferred-locations.c b/gcc/deferred-locations.c
> new file mode 100644
> index 0000000..cd02938
> --- /dev/null
> +++ b/gcc/deferred-locations.c
> @@ -0,0 +1,240 @@
> +/* Dealing with the linemap API.
> + Copyright (C) 2013-2016 Free Software Foundation, Inc.
> +
> +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 "input.h"
> +#include "deferred-locations.h"
> +#include "stringpool.h"
> +#include "tree.h"
> +
> +/* The wrapper subclasses are GC-managed, but can own non-GC memory.
> + Provide this finalization hook for calling then they are collected,
> + which calls the finalizer vfunc. This allows them to call "release"
> + on any vec<> within them. */
> +
> +static void
> +wrapper_finalizer (void *ptr)
> +{
> + wrapper *w = reinterpret_cast <wrapper *> (ptr);
> + w->finalizer ();
> +}
> +
> +/* wrapper subclasses are GC-managed:
> + allocate them using ggc_internal_cleared_alloc. */
> +
> +void *
> +wrapper::operator new (size_t sz)
> +{
> + return ggc_internal_cleared_alloc (sz, wrapper_finalizer, 0, 1);
> +
> +}
> +
> +/* Constructor for source_file. */
> +
> +source_file::source_file (tree filename) :
> + m_source_lines (),
> + m_filename (filename)
> +{
> +}
> +
> +/* Don't leak vec's internal buffer (in non-GC heap) when we are
> + GC-ed. */
> +
> +void
> +source_file::finalizer ()
> +{
> + m_source_lines.release ();
> +}
> +
> +/* Construct a source_line for the given line
> + within this source file, if one doesn't exist already. */
> +
> +source_line *
> +source_file::get_source_line (int line_num)
> +{
> + /* Locate the line.
> + For simplicitly, this is currently a linear search.
> + Replace with a hash if this shows up in the profile. */
> + int i;
> + source_line *line;
> +
> + FOR_EACH_VEC_ELT (m_source_lines, i, line)
> + if (line->get_line_num () == line_num)
> + return line;
> +
> + /* Not found. */
> + line = new source_line (this, line_num);
> + m_source_lines.safe_push (line);
> + return line;
> +}
> +
> +const char *
> +source_file::get_filename () const
> +{
> + return IDENTIFIER_POINTER (m_filename);
> +}
> +
> +/* Constructor for source_line. */
> +
> +source_line::source_line (source_file *file, int line_num) :
> + m_locations (),
> + m_source_file (file),
> + m_line_num (line_num)
> +{
> +}
> +
> +/* Don't leak vec's internal buffer (in non-GC heap) when we are
> + GC-ed. */
> +
> +void
> +source_line::finalizer ()
> +{
> + m_locations.release ();
> +}
> +
> +/* Construct a location for the given column
> + within this line of a specific source file, if one doesn't exist
> + already. */
> +
> +deferred_location *
> +source_line::get_location (void *user_data, int column_num)
> +{
> + int i;
> + deferred_location *loc;
> +
> + /* Another linear search that probably should be a hash table. */
> + FOR_EACH_VEC_ELT (m_locations, i, loc)
> + if (loc->get_column_num () == column_num)
> + return loc;
> +
> + /* Not found. */
> + loc = new deferred_location (user_data, this, column_num);
> + m_locations.safe_push (loc);
> + return loc;
> +}
> +
> +/* Constructor for deferred_location. */
> +deferred_location::deferred_location (void *user_data,
> + source_line *line,
> + int column_num) :
> + m_srcloc (UNKNOWN_LOCATION),
> + m_user_data (user_data),
> + m_line (line),
> + m_column_num(column_num)
> +{
> +}
> +
> +/* qsort comparator for comparing pairs of source_line *,
> + ordering them by line number. */
> +
> +static int
> +line_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 ();
> +}
> +
> +/* qsort comparator for comparing pairs of deferred_location *,
> + ordering them by column number. */
> +
> +static int
> +location_comparator (const void *lhs, const void *rhs)
> +{
> + const deferred_location *loc_lhs = \
> + *static_cast<const deferred_location * const *> (lhs);
> + const deferred_location *loc_rhs = \
> + *static_cast<const deferred_location * const *> (rhs);
> + return loc_lhs->get_column_num () - loc_rhs->get_column_num ();
> +}
> +
> +/* class deferred_locations */
> +
> +deferred_locations::deferred_locations ()
> +{
> + m_source_files.create (0);
> +}
> +
> +/* Construct a source_file for the given source
> + filename, if it doesn't exist already. */
> +
> +source_file *
> +deferred_locations::get_source_file (const char *filename)
> +{
> + /* Locate the file.
> + For simplicitly, this is currently a linear search.
> + Replace with a hash if this shows up in the profile. */
> + int i;
> + source_file *file;
> + tree ident_filename = get_identifier (filename);
> +
> + FOR_EACH_VEC_ELT (m_source_files, i, file)
> + if (file->filename_as_tree () == ident_filename)
> + return file;
> +
> + /* Not found. */
> + file = new source_file (ident_filename);
> + m_source_files.safe_push (file);
> + return file;
> +
> +}
> +
> +void
> +deferred_locations::add_to_line_table ()
> +{
> + int i;
> + source_file *file;
> +
> + FOR_EACH_VEC_ELT (m_source_files, i, file)
> + {
> + linemap_add (line_table, LC_ENTER, false, file->get_filename (), 0);
> +
> + /* Sort lines by ascending line numbers. */
> + file->m_source_lines.qsort (&line_comparator);
> +
> + int j;
> + source_line *line;
> + FOR_EACH_VEC_ELT (file->m_source_lines, j, line)
> + {
> + int k;
> + deferred_location *loc;
> +
> + /* Sort locations in line by ascending column numbers. */
> + line->m_locations.qsort (&location_comparator);
> +
> + /* Determine maximum column within this line. */
> + gcc_assert (line->m_locations.length () > 0);
> + deferred_location *final_column =
> + line->m_locations[line->m_locations.length () - 1];
> + int max_col = final_column->get_column_num ();
> +
> + linemap_line_start (line_table, line->get_line_num (), max_col);
> + FOR_EACH_VEC_ELT (line->m_locations, k, loc)
> + {
> + loc->m_srcloc =
> + linemap_position_for_column (line_table, loc->get_column_num ());
> + }
> + }
> +
> + linemap_add (line_table, LC_LEAVE, false, NULL, 0);
> + }
> +
> +}
> diff --git a/gcc/deferred-locations.h b/gcc/deferred-locations.h
> new file mode 100644
> index 0000000..209cb0d
> --- /dev/null
> +++ b/gcc/deferred-locations.h
> @@ -0,0 +1,139 @@
> +/* Dealing with the linemap API.
> + Copyright (C) 2013-2016 Free Software Foundation, Inc.
> +
> +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 GCC_DEFERRED_LOCATIONS_H
> +#define GCC_DEFERRED_LOCATIONS_H
> +
> +/* 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, whereas the libgccjit API doesn't impose any such constraints:
> + we allow client code to create locations in arbitrary orders.
> +
> + To square this circle, we need to cache all location creation,
> + grouping things up by filename/line, and then creating the linemap
> + entries in a post-processing phase. */
> +
> +/* A temporary wrapper object.
> + These objects are (mostly) only valid during replay.
> + We allocate them on the GC heap, so that they will be cleaned
> + the next time the GC collects. */
> +class wrapper
> +{
> +public:
> + /* Allocate in the GC heap. */
> + void *operator new (size_t sz);
> +
> + /* Some wrapper subclasses contain vec<> and so need to
> + release them when they are GC-ed. */
> + virtual void finalizer () { }
> +};
> +
> +class source_file;
> +class source_line;
> +class deferred_location;
> +
> +/* A set of locations, all sharing a filename */
> +class source_file : public wrapper
> +{
> +public:
> + source_file (tree filename);
> + void finalizer ();
> +
> + source_line *
> + get_source_line (int line_num);
> +
> + tree filename_as_tree () const { return m_filename; }
> +
> + const char *get_filename () const;
> +
> + vec<source_line *> m_source_lines;
> +
> +private:
> + tree m_filename;
> +};
> +
> +/* A source line, with one or more locations of interest. */
> +class source_line : public wrapper
> +{
> +public:
> + source_line (source_file *file, int line_num);
> + void finalizer ();
> +
> + deferred_location *
> + get_location (void *user_data, int column_num);
> +
> + int get_line_num () const { return m_line_num; }
> +
> + vec<deferred_location *> m_locations;
> +
> +private:
> + source_file *m_source_file;
> + int m_line_num;
> +};
> +
> +/* A specific location on a source line. This is what we expose
> + to the JIT client API. */
> +class deferred_location : public wrapper
> +{
> +public:
> + deferred_location (void *user_data, source_line *line, int column_num);
> +
> + int get_column_num () const { return m_column_num; }
> +
> + void *get_user_data () const { return m_user_data; }
> +
> + source_location m_srcloc;
> +
> +private:
> + void *m_user_data;
> + source_line *m_line;
> + int m_column_num;
> +};
> +
> +/* A class for managing the deferred creation of location_t values.
> +
> + Locations are created in two phases:
> +
> + - first phase: creation of source_file instances (via
> + deferred_locations::get_source_file), from which source_line
> + instances can be created (via source_file::get_source_line), from
> + which deferred_location instances can be created (via
> + source_line::get_location).
> +
> + - second phase: call deferred_location::add_to_line_table, which
> + walks all of the above and populates line_table, filling in
> + the various deferred_location instances with source_location
> + (aka location_t) values. */
> +
> +class deferred_locations
> +{
> + public:
> + deferred_locations ();
> +
> + source_file *get_source_file (const char *filename);
> +
> + void add_to_line_table ();
> +
> + private:
> + auto_vec<source_file *> m_source_files;
> +};
> +
> +#endif /* #ifndef GCC_DEFERRED_LOCATIONS_H */
> diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
> index 8a6cd74..0a10cdf 100644
> --- a/gcc/jit/jit-common.h
> +++ b/gcc/jit/jit-common.h
> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
> #include "tree.h"
> #include "inchash.h"
> #include "tree-iterator.h"
> +#include "deferred-locations.h"
>
> #ifdef GCC_VERSION
> #if GCC_VERSION >= 4001
> @@ -146,9 +147,7 @@ namespace playback {
> class rvalue;
> class lvalue;
> class param;
> - class source_file;
> - class source_line;
> - class location;
> + typedef deferred_location location;
> class case_;
>
> /* End of playback types. */
> diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
> index 579230d..f17c55b 100644
> --- a/gcc/jit/jit-playback.c
> +++ b/gcc/jit/jit-playback.c
> @@ -85,7 +85,6 @@ playback::context::context (recording::context *ctxt)
> JIT_LOG_SCOPE (get_logger ());
> m_functions.create (0);
> m_globals.create (0);
> - m_source_files.create (0);
> m_cached_locations.create (0);
> }
>
> @@ -2705,32 +2704,6 @@ get_path_so_file () const
> return m_tempdir->get_path_so_file ();
> }
>
> -/* qsort comparator for comparing pairs of playback::source_line *,
> - ordering them by line number. */
> -
> -static int
> -line_comparator (const void *lhs, const void *rhs)
> -{
> - const playback::source_line *line_lhs = \
> - *static_cast<const playback::source_line * const*> (lhs);
> - const playback::source_line *line_rhs = \
> - *static_cast<const playback::source_line * const*> (rhs);
> - return line_lhs->get_line_num () - line_rhs->get_line_num ();
> -}
> -
> -/* qsort comparator for comparing pairs of playback::location *,
> - ordering them by column number. */
> -
> -static int
> -location_comparator (const void *lhs, const void *rhs)
> -{
> - const playback::location *loc_lhs = \
> - *static_cast<const playback::location * const *> (lhs);
> - const playback::location *loc_rhs = \
> - *static_cast<const playback::location * const *> (rhs);
> - return loc_lhs->get_column_num () - loc_rhs->get_column_num ();
> -}
> -
> /* Our API allows locations to be created in arbitrary orders, but the
> linemap API requires locations to be created in ascending order
> as if we were tokenizing files.
> @@ -2748,47 +2721,13 @@ handle_locations ()
>
> line_table is a global. */
> JIT_LOG_SCOPE (get_logger ());
> - int i;
> - source_file *file;
> -
> - FOR_EACH_VEC_ELT (m_source_files, i, file)
> - {
> - linemap_add (line_table, LC_ENTER, false, file->get_filename (), 0);
> -
> - /* Sort lines by ascending line numbers. */
> - file->m_source_lines.qsort (&line_comparator);
> -
> - int j;
> - source_line *line;
> - FOR_EACH_VEC_ELT (file->m_source_lines, j, line)
> - {
> - int k;
> - location *loc;
> -
> - /* Sort locations in line by ascending column numbers. */
> - line->m_locations.qsort (&location_comparator);
> -
> - /* Determine maximum column within this line. */
> - gcc_assert (line->m_locations.length () > 0);
> - location *final_column =
> - line->m_locations[line->m_locations.length () - 1];
> - int max_col = final_column->get_column_num ();
> -
> - linemap_line_start (line_table, line->get_line_num (), max_col);
> - FOR_EACH_VEC_ELT (line->m_locations, k, loc)
> - {
> - loc->m_srcloc = \
> - linemap_position_for_column (line_table, loc->get_column_num ());
> - }
> - }
> -
> - linemap_add (line_table, LC_LEAVE, false, NULL, 0);
> - }
>
> + m_deferred_locations.add_to_line_table ();
> /* line_table should now be populated; every playback::location should
> now have an m_srcloc. */
>
> /* Now assign them to tree nodes as appropriate. */
> + int i;
> std::pair<tree, location *> *cached_location;
>
> FOR_EACH_VEC_ELT (m_cached_locations, i, cached_location)
> @@ -2808,6 +2747,17 @@ handle_locations ()
> }
> }
>
> +/* Return the recording::location for playback::location LOC.
> + Return NULL if LOC is NULL. */
> +
> +static recording::location *
> +get_recording_loc (playback::location *loc)
> +{
> + if (!loc)
> + return NULL;
> + return reinterpret_cast <recording::location *> (loc->get_user_data ());
> +}
> +
> /* We handle errors on a playback::context by adding them to the
> corresponding recording::context. */
>
> @@ -2817,8 +2767,7 @@ add_error (location *loc, const char *fmt, ...)
> {
> va_list ap;
> va_start (ap, fmt);
> - m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL,
> - fmt, ap);
> + m_recording_ctxt->add_error_va (get_recording_loc (loc), fmt, ap);
> va_end (ap);
> }
>
> @@ -2829,8 +2778,7 @@ void
> playback::context::
> add_error_va (location *loc, const char *fmt, va_list ap)
> {
> - m_recording_ctxt->add_error_va (loc ? loc->get_recording_loc () : NULL,
> - fmt, ap);
> + m_recording_ctxt->add_error_va (get_recording_loc (loc), fmt, ap);
> }
>
> /* Dealing with the linemap API. */
> @@ -2868,120 +2816,14 @@ set_tree_location (tree t, location *loc)
> }
>
>
> -/* Construct a playback::source_file for the given source
> +/* Construct a source_file for the given source
> filename, if it doesn't exist already. */
>
> -playback::source_file *
> +source_file *
> playback::context::
> get_source_file (const char *filename)
> {
> - /* Locate the file.
> - For simplicitly, this is currently a linear search.
> - Replace with a hash if this shows up in the profile. */
> - int i;
> - source_file *file;
> - tree ident_filename = get_identifier (filename);
> -
> - FOR_EACH_VEC_ELT (m_source_files, i, file)
> - if (file->filename_as_tree () == ident_filename)
> - return file;
> -
> - /* Not found. */
> - file = new source_file (ident_filename);
> - m_source_files.safe_push (file);
> - return file;
> -}
> -
> -/* Constructor for gcc::jit::playback::source_file. */
> -
> -playback::source_file::source_file (tree filename) :
> - m_source_lines (),
> - m_filename (filename)
> -{
> -}
> -
> -/* Don't leak vec's internal buffer (in non-GC heap) when we are
> - GC-ed. */
> -
> -void
> -playback::source_file::finalizer ()
> -{
> - m_source_lines.release ();
> -}
> -
> -/* Construct a playback::source_line for the given line
> - within this source file, if one doesn't exist already. */
> -
> -playback::source_line *
> -playback::source_file::
> -get_source_line (int line_num)
> -{
> - /* Locate the line.
> - For simplicitly, this is currently a linear search.
> - Replace with a hash if this shows up in the profile. */
> - int i;
> - source_line *line;
> -
> - FOR_EACH_VEC_ELT (m_source_lines, i, line)
> - if (line->get_line_num () == line_num)
> - return line;
> -
> - /* Not found. */
> - line = new source_line (this, line_num);
> - m_source_lines.safe_push (line);
> - return line;
> -}
> -
> -/* Constructor for gcc::jit::playback::source_line. */
> -
> -playback::source_line::source_line (source_file *file, int line_num) :
> - m_locations (),
> - m_source_file (file),
> - m_line_num (line_num)
> -{
> -}
> -
> -/* Don't leak vec's internal buffer (in non-GC heap) when we are
> - GC-ed. */
> -
> -void
> -playback::source_line::finalizer ()
> -{
> - m_locations.release ();
> -}
> -
> -/* Construct a playback::location for the given column
> - within this line of a specific source file, if one doesn't exist
> - already. */
> -
> -playback::location *
> -playback::source_line::
> -get_location (recording::location *rloc, int column_num)
> -{
> - int i;
> - location *loc;
> -
> - /* Another linear search that probably should be a hash table. */
> - FOR_EACH_VEC_ELT (m_locations, i, loc)
> - if (loc->get_column_num () == column_num)
> - return loc;
> -
> - /* Not found. */
> - loc = new location (rloc, this, column_num);
> - m_locations.safe_push (loc);
> - return loc;
> -}
> -
> -/* Constructor for gcc::jit::playback::location. */
> -
> -playback::location::location (recording::location *loc,
> - source_line *line,
> - int column_num) :
> - m_srcloc (UNKNOWN_LOCATION),
> - m_recording_loc (loc),
> - m_line (line),
> - m_column_num(column_num)
> -{
> + return m_deferred_locations.get_source_file (filename);
> }
>
> /* The active gcc::jit::playback::context instance. This is a singleton,
> diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
> index 7519bc4..86118d9 100644
> --- a/gcc/jit/jit-playback.h
> +++ b/gcc/jit/jit-playback.h
> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
> #include <utility> // for std::pair
>
> #include "timevar.h"
> +#include "deferred-locations.h"
>
> #include "jit-recording.h"
>
> @@ -305,7 +306,7 @@ private:
> tree m_const_char_ptr;
>
> /* Source location handling. */
> - auto_vec<source_file *> m_source_files;
> + deferred_locations m_deferred_locations;
>
> auto_vec<std::pair<tree, location *> > m_cached_locations;
> };
> @@ -603,76 +604,6 @@ public:
> {}
> };
>
> -/* Dealing with the linemap API.
> -
> - It appears that libcpp requires locations to be created as if by
> - a tokenizer, creating them by filename, in ascending order of
> - line/column, whereas our API doesn't impose any such constraints:
> - we allow client code to create locations in arbitrary orders.
> -
> - To square this circle, we need to cache all location creation,
> - grouping things up by filename/line, and then creating the linemap
> - entries in a post-processing phase. */
> -
> -/* A set of locations, all sharing a filename */
> -class source_file : public wrapper
> -{
> -public:
> - source_file (tree filename);
> - void finalizer ();
> -
> - source_line *
> - get_source_line (int line_num);
> -
> - tree filename_as_tree () const { return m_filename; }
> -
> - const char*
> - get_filename () const { return IDENTIFIER_POINTER (m_filename); }
> -
> - vec<source_line *> m_source_lines;
> -
> -private:
> - tree m_filename;
> -};
> -
> -/* A source line, with one or more locations of interest. */
> -class source_line : public wrapper
> -{
> -public:
> - source_line (source_file *file, int line_num);
> - void finalizer ();
> -
> - location *
> - get_location (recording::location *rloc, int column_num);
> -
> - int get_line_num () const { return m_line_num; }
> -
> - vec<location *> m_locations;
> -
> -private:
> - source_file *m_source_file;
> - int m_line_num;
> -};
> -
> -/* A specific location on a source line. This is what we expose
> - to the client API. */
> -class location : public wrapper
> -{
> -public:
> - location (recording::location *loc, source_line *line, int column_num);
> -
> - int get_column_num () const { return m_column_num; }
> -
> - recording::location *get_recording_loc () const { return m_recording_loc; }
> -
> - source_location m_srcloc;
> -
> -private:
> - recording::location *m_recording_loc;
> - source_line *m_line;
> - int m_column_num;
> -};
> -
> } // namespace gcc::jit::playback
>
> extern playback::context *active_playback_ctxt;
> --
> 1.8.5.3
>