From f94c1e3ec6a7769d769c3096cc5224964b0ebbff Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 19 Oct 2016 16:59:08 -0400
Subject: [PATCH 19/20] FIXME: function_reader fixups

---
 gcc/read-rtl-function.c                   | 86 +++++++++++++++++++++++++++++++
 gcc/testsuite/selftests/x86_64/unspec.rtl | 20 +++++++
 2 files changed, 106 insertions(+)
 create mode 100644 gcc/testsuite/selftests/x86_64/unspec.rtl

diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index d882af3..fdb5d24 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -111,6 +111,8 @@ class function_reader : public rtx_reader
   void parse_crtl (file_location loc);
   void create_edges ();
 
+  int parse_enum_value (int num_values, const char *const *strings);
+
   void read_rtx_operand_u (rtx return_rtx, int idx);
   void read_rtx_operand_i_or_n (rtx return_rtx, int idx, char format_char);
   rtx read_rtx_operand_r (rtx return_rtx);
@@ -1004,6 +1006,22 @@ function_reader::read_rtx_operand_u (rtx return_rtx, int idx)
     add_fixup_insn_uid (loc, return_rtx, idx, insn_id);
 }
 
+/* FIXME.  */
+
+int
+function_reader::parse_enum_value (int num_values, const char *const *strings)
+{
+  struct md_name name;
+  read_name (&name);
+  for (int i = 0; i < num_values; i++)
+    {
+      if (strcmp (name.string, strings[i]) == 0)
+	return i;
+    }
+  error ("unrecognized enum value: '%s'", name.string);
+  return 0;
+}
+
 /* Special-cased handling of codes 'i' and 'n' for reading function
    dumps.  */
 
@@ -1035,6 +1053,27 @@ function_reader::read_rtx_operand_i_or_n (rtx return_rtx, int idx,
       return;
     }
 
+  /* Handle UNSPEC and UNSPEC_VOLATILE's operand 1.  */
+#if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
+  if (idx == 1
+      && GET_CODE (return_rtx) == UNSPEC_VOLATILE)
+    {
+      XINT (return_rtx, 1)
+	= parse_enum_value (NUM_UNSPECV_VALUES, unspecv_strings);
+      return;
+    }
+#endif
+#if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
+  if (idx == 1
+      && (GET_CODE (return_rtx) == UNSPEC
+	  || GET_CODE (return_rtx) == UNSPEC_VOLATILE))
+    {
+      XINT (return_rtx, 1)
+	= parse_enum_value (NUM_UNSPEC_VALUES, unspec_strings);
+      return;
+    }
+#endif
+
   struct md_name name;
   read_name (&name);
   int value;
@@ -2264,6 +2303,52 @@ test_loading_bb_index ()
   ASSERT_EQ (42, bb42->index);
 }
 
+/* Verify that the loader copes with UNSPEC and UNSPEC_VOLATILE insns.
+   In particular, verify that it correctly loads the 2nd operand.
+   These are machine-specific operands (and enums), so the relevant
+   parts of the test case are wrapped accordingly.  */
+
+static void
+test_loading_unspec ()
+{
+#ifndef I386_OPTS_H
+  return;
+#endif
+
+  rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/unspec.rtl"));
+
+  ASSERT_STREQ ("test_unspec", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
+
+  ASSERT_TRUE (cfun);
+
+  /* Test of an UNSPEC.  */
+   rtx_insn *insn = get_insns ();
+  ASSERT_EQ (INSN, GET_CODE (insn));
+  rtx set = single_set (insn);
+  ASSERT_NE (NULL, set);
+  rtx dst = SET_DEST (set);
+  ASSERT_EQ (MEM, GET_CODE (dst));
+  rtx src = SET_SRC (set);
+  ASSERT_EQ (UNSPEC, GET_CODE (src));
+  ASSERT_EQ (BLKmode, GET_MODE (src));
+#ifdef I386_OPTS_H
+  ASSERT_EQ (UNSPEC_MEMORY_BLOCKAGE, XINT (src, 1));
+#endif
+
+  /* Test of an UNSPEC_VOLATILE, which has its own enum values.  */
+  insn = NEXT_INSN (insn);
+  ASSERT_EQ (INSN, GET_CODE (insn));
+
+  set = single_set (insn);
+  ASSERT_NE (NULL, set);
+
+  src = SET_SRC (set);
+  ASSERT_EQ (UNSPEC_VOLATILE, GET_CODE (src));
+#ifdef I386_OPTS_H
+  ASSERT_EQ (UNSPECV_RDTSCP, XINT (src, 1));
+#endif
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -2287,6 +2372,7 @@ read_rtl_function_c_tests ()
   test_loading_full_dump_x86_64 ();
   test_loading_cfg ();
   test_loading_bb_index ();
+  test_loading_unspec ();
 }
 
 } // namespace selftest
diff --git a/gcc/testsuite/selftests/x86_64/unspec.rtl b/gcc/testsuite/selftests/x86_64/unspec.rtl
new file mode 100644
index 0000000..892c532
--- /dev/null
+++ b/gcc/testsuite/selftests/x86_64/unspec.rtl
@@ -0,0 +1,20 @@
+(function "test_unspec"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cinsn (set (mem/v:BLK (scratch:DI) [0  A8])
+                    (unspec:BLK [
+                            (mem/v:BLK (scratch:DI) [0  A8])
+                        ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
+                 (nil))
+
+      (cinsn (set (mem/v:BLK (scratch:DI) [0  A8])
+                    (unspec_volatile:BLK [
+                            (mem/v:BLK (scratch:DI) [0  A8])
+                        ] UNSPECV_RDTSCP)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
+                 (nil))
+
+      (edge-to exit (flags "FALLTHRU"))
+    ) ;; block 2
+  ) ;; insn-chain
+) ;; function
-- 
1.8.5.3

