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