gcc/ChangeLog:
        * read-md.c (md_reader::read_char): Support filtering
        the input to a subset of line numbers.
        (md_reader::md_reader): Initialize fields
        m_first_line and m_last_line.
        (md_reader::read_file_fragment): New function.
        * read-md.h (md_reader::read_file_fragment): New decl.
        (md_reader::m_first_line): New field.
        (md_reader::m_last_line): New field.
        * read-rtl-function.c (function_reader::create_function): Only
        create cfun if it doesn't already exist.  Set PROP_rtl on cfun's
        curr_properties.  Set DECL_INITIAL to a dummy block.
        (read_rtl_function_body_from_file_range): New function.
        * read-rtl-function.h (read_rtl_function_body_from_file_range):
        New decl.
---
 gcc/read-md.c           | 34 +++++++++++++++++++-
 gcc/read-md.h           |  7 +++++
 gcc/read-rtl-function.c | 83 +++++++++++++++++++++++++++++++++++++++----------
 gcc/read-rtl-function.h |  3 ++
 4 files changed, 109 insertions(+), 18 deletions(-)

diff --git a/gcc/read-md.c b/gcc/read-md.c
index ac28944..4036afa 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -411,6 +411,16 @@ md_reader::read_char (void)
   else
     m_read_md_colno++;
 
+  /* If we're filtering lines, treat everything before the range of
+     interest as a space, and as EOF for everything after.  */
+  if (m_first_line && m_last_line)
+    {
+      if (m_read_md_lineno < m_first_line)
+       return ' ';
+      if (m_read_md_lineno > m_last_line)
+       return EOF;
+    }
+
   return ch;
 }
 
@@ -991,7 +1001,9 @@ md_reader::md_reader (bool compact)
   m_read_md_lineno (0),
   m_read_md_colno (0),
   m_first_dir_md_include (NULL),
-  m_last_dir_md_include_ptr (&m_first_dir_md_include)
+  m_last_dir_md_include_ptr (&m_first_dir_md_include),
+  m_first_line (0),
+  m_last_line (0)
 {
   /* Set the global singleton pointer.  */
   md_reader_ptr = this;
@@ -1314,6 +1326,26 @@ md_reader::read_file (const char *filename)
   return !have_error;
 }
 
+/* Read FILENAME, filtering to just the given lines.  */
+
+bool
+md_reader::read_file_fragment (const char *filename,
+                              int first_line,
+                              int last_line)
+{
+  m_read_md_filename = filename;
+  m_read_md_file = fopen (m_read_md_filename, "r");
+  if (m_read_md_file == 0)
+    {
+      perror (m_read_md_filename);
+      return false;
+    }
+  m_first_line = first_line;
+  m_last_line = last_line;
+  handle_toplevel_file ();
+  return !have_error;
+}
+
 /* class noop_reader : public md_reader */
 
 /* A dummy implementation which skips unknown directives.  */
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 4fcbcb4..fea7011 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -111,6 +111,9 @@ class md_reader
 
   bool read_md_files (int, const char **, bool (*) (const char *));
   bool read_file (const char *filename);
+  bool read_file_fragment (const char *filename,
+                          int first_line,
+                          int last_line);
 
   /* A hook that handles a single .md-file directive, up to but not
      including the closing ')'.  It takes two arguments: the file position
@@ -245,6 +248,10 @@ class md_reader
 
   /* A table of enum_type structures, hashed by name.  */
   htab_t m_enum_types;
+
+  /* If non-zero, filter the input to just this subset of lines.  */
+  int m_first_line;
+  int m_last_line;
 };
 
 /* Global singleton; constrast with rtx_reader_ptr below.  */
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index c5cb3f7..f27e174 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -475,23 +475,38 @@ function_reader::create_function ()
   /* We start in cfgrtl mode, rather than cfglayout mode.  */
   rtl_register_cfg_hooks ();
 
-  /* Create cfun.  */
-  tree fn_name = get_identifier (m_name ? m_name : "test_1");
-  tree int_type = integer_type_node;
-  tree return_type = int_type;
-  tree arg_types[3] = {int_type, int_type, int_type};
-  tree fn_type = build_function_type_array (return_type, 3, arg_types);
-  tree fndecl = build_decl_stat (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name,
-                                fn_type);
-  tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
-                            return_type);
-  DECL_ARTIFICIAL (resdecl) = 1;
-  DECL_IGNORED_P (resdecl) = 1;
-  DECL_RESULT (fndecl) = resdecl;
-  allocate_struct_function (fndecl, false);
-  /* This sets cfun.  */
-
-  current_function_decl = fndecl;
+  /* When run from selftests or "rtl1", cfun is NULL.
+     When run from "cc1" for a C function tagged with __RTL, cfun is the
+     tagged function.  */
+  if (!cfun)
+    {
+      tree fn_name = get_identifier (m_name ? m_name : "test_1");
+      tree int_type = integer_type_node;
+      tree return_type = int_type;
+      tree arg_types[3] = {int_type, int_type, int_type};
+      tree fn_type = build_function_type_array (return_type, 3, arg_types);
+      tree fndecl = build_decl_stat (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name,
+                                    fn_type);
+      tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
+                                return_type);
+      DECL_ARTIFICIAL (resdecl) = 1;
+      DECL_IGNORED_P (resdecl) = 1;
+      DECL_RESULT (fndecl) = resdecl;
+      allocate_struct_function (fndecl, false);
+      /* This sets cfun.  */
+      current_function_decl = fndecl;
+    }
+
+  gcc_assert (cfun);
+  gcc_assert (current_function_decl);
+  tree fndecl = current_function_decl;
+
+  /* Mark this function as being specified as __RTL.  */
+  cfun->curr_properties |= PROP_rtl;
+
+  /* cc1 normally inits DECL_INITIAL (fndecl) to be error_mark_node.
+     Create a dummy block for it.  */
+  DECL_INITIAL (fndecl) = make_node (BLOCK);
 
   cfun->curr_properties = (PROP_cfg | PROP_rtl);
 
@@ -1583,6 +1598,40 @@ read_rtl_function_body (const char *path)
   return true;
 }
 
+/* Run the RTL dump parser on the range of lines between START_LOC and
+   END_LOC (including those lines).  */
+
+bool
+read_rtl_function_body_from_file_range (location_t start_loc,
+                                       location_t end_loc)
+{
+  expanded_location exploc_start = expand_location (start_loc);
+  expanded_location exploc_end = expand_location (end_loc);
+
+  if (exploc_start.file != exploc_end.file)
+    {
+      error_at (end_loc, "start/end of RTL fragment are in different files");
+      return false;
+    }
+  if (exploc_start.line >= exploc_end.line)
+    {
+      error_at (end_loc,
+               "start of RTL fragment must be on an earlier line than end");
+      return false;
+    }
+
+  initialize_rtl ();
+  init_emit ();
+  init_varasm_status ();
+
+  function_reader reader;
+  if (!reader.read_file_fragment (exploc_start.file, exploc_start.line,
+                                 exploc_end.line - 1))
+    return false;
+
+  return true;
+}
+
 #if CHECKING_P
 
 namespace selftest {
diff --git a/gcc/read-rtl-function.h b/gcc/read-rtl-function.h
index 45ada84..10ceab8 100644
--- a/gcc/read-rtl-function.h
+++ b/gcc/read-rtl-function.h
@@ -22,4 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 
 extern bool read_rtl_function_body (const char *path);
 
+extern bool read_rtl_function_body_from_file_range (location_t start_loc,
+                                                   location_t end_loc);
+
 #endif /* GCC_READ_RTL_FUNCTION_H */
-- 
1.8.5.3

Reply via email to