diff mbox series

ping x2 [PATCH 3/3] [MSP430] Search for MCU data file using environment variable and in a toolchain subdirectory

Message ID cf9bda4f-08c9-6b24-f0b6-9f128f0c3a97@mittosystems.com
State New
Headers show
Series ping x2 [PATCH 3/3] [MSP430] Search for MCU data file using environment variable and in a toolchain subdirectory | expand

Commit Message

Jozef Lawrynowicz Oct. 29, 2018, 2:31 p.m. UTC
This patch adds functionality to search for devices.csv in both
the path specified by the environment variable "MSP430_GCC_INCLUDE_DIR", and
the directory "msp430-elf/include/devices" from the toolchain root. These
locations are searched if devices.csv is not found on an include path.
If devices.csv is found using one of these methods, the directory containing
devices.csv is also registered as an include path and linker library path.
diff mbox series

Patch

From cc4dbcb83be19fd55e6dae28ea37a714109bec26 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Mon, 29 Oct 2018 13:52:39 +0000
Subject: [PATCH 3/3] MSP430 - Devices 3 - Add functionality to read device
 data from environment variable

2018-10-29  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

gcc/config/msp430/

	* driver-msp430.c (msp430_select_hwmult_lib): Fix formatting.
	(msp430_get_linker_devices_include_path): New.
	* msp430-devices.c (msp430_dirname): New.
	(canonicalize_path_dirsep): New.
	(process_collect_gcc_into_devices_dir): New.
	(msp430_check_env_var_for_devices): New.
	(parse_devices_csv): Call msp430_check_env_var_for_devices after trying
	other methods.
	* msp430-devices.h (msp430_check_env_var_for_devices): New.
	(msp430_dirname): New.
	* msp430.c (msp430_register_pre_includes): New.
	* msp430.h (EXTRA_SPEC_FUNCTIONS): Add
	msp430_get_linker_devices_include_path.
	(LINK_SPEC): Likewise.
	Define TARGET_EXTRA_PRE_INCLUDES to msp430_register_pre_includes.

gcc/doc/

	* invoke.texi: Document that devices.csv is searched for using an
	environment variable and in a subdirectory of the toolchain
	installation.

gcc/testsuite/gcc.target/msp430/

	* devices/csv_using_env_var.c: New.
	* devices/csv_using_installed.c: New.
	* devices/csv_using_option.c: New.
	* msp430.exp (msp430_device_permutations_runtest): Prepare for
	csv_using_* tests as appropriate.
	(get_installed_device_data_path): New.
	(msp430_hide_installed_devices_data): New.
	(msp430_restore_installed_devices_data): New.
	(msp430_test_installed_device_data): New.
---
 gcc/config/msp430/driver-msp430.c                  | 13 +++-
 gcc/config/msp430/msp430-devices.c                 | 88 +++++++++++++++++++++-
 gcc/config/msp430/msp430-devices.h                 |  2 +
 gcc/config/msp430/msp430.c                         | 16 ++++
 gcc/config/msp430/msp430.h                         | 12 ++-
 gcc/doc/invoke.texi                                | 28 ++++++-
 .../gcc.target/msp430/devices/csv_using_env_var.c  | 10 +++
 .../msp430/devices/csv_using_installed.c           | 11 +++
 .../gcc.target/msp430/devices/csv_using_option.c   | 12 +++
 gcc/testsuite/gcc.target/msp430/msp430.exp         | 70 ++++++++++++++++-
 10 files changed, 255 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/msp430/devices/csv_using_env_var.c
 create mode 100644 gcc/testsuite/gcc.target/msp430/devices/csv_using_installed.c
 create mode 100644 gcc/testsuite/gcc.target/msp430/devices/csv_using_option.c

diff --git a/gcc/config/msp430/driver-msp430.c b/gcc/config/msp430/driver-msp430.c
index 4242274..3facdc2 100644
--- a/gcc/config/msp430/driver-msp430.c
+++ b/gcc/config/msp430/driver-msp430.c
@@ -52,7 +52,8 @@  msp430_select_cpu (int argc, const char ** argv)
 /* Implement spec function `msp430_hwmult_lib´.  */
 
 const char *
-msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED, const char ** argv ATTRIBUTE_UNUSED)
+msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED,
+			  const char ** argv ATTRIBUTE_UNUSED)
 {
   int i;
 
@@ -116,3 +117,13 @@  msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED, const char ** argv ATTRIBUT
   
   return "-lmul_none";
 }
+
+const char *
+msp430_get_linker_devices_include_path (int argc ATTRIBUTE_UNUSED,
+					const char **argv ATTRIBUTE_UNUSED)
+{
+  char *devices_csv_path;
+  if (msp430_check_env_var_for_devices (&devices_csv_path))
+    return NULL;
+  return concat ("-L", msp430_dirname (devices_csv_path), NULL);
+}
diff --git a/gcc/config/msp430/msp430-devices.c b/gcc/config/msp430/msp430-devices.c
index 2f44861..c37f8dc 100644
--- a/gcc/config/msp430/msp430-devices.c
+++ b/gcc/config/msp430/msp430-devices.c
@@ -23,6 +23,88 @@  char * derived_devices_csv_loc = NULL;
 /* Set to true by msp430_extract_mcu_data if called from the driver.  */
 bool surpress_devices_warn = false;
 
+/* This modifies the string pointed to by path.  */
+char *
+msp430_dirname (char *path)
+{
+  int last_elem = strlen (path) - 1;
+  int i = last_elem - (IS_DIR_SEPARATOR (path[last_elem]) ? 1 : 0);
+  for (; i >= 0; i--)
+    {
+      if (IS_DIR_SEPARATOR (path[i]))
+	{
+	  path[i] = '\0';
+	  return path;
+	}
+    }
+  return path;
+}
+
+/* This is to canonicalize the path.  On Windows we can have a mix of forward
+   and backslashes which leads to issues following paths.  */
+static void
+canonicalize_path_dirsep (char **path)
+{
+  char *t_path = *path;
+  unsigned int i;
+  for (i = 0; i < strlen (t_path); i++)
+    if (IS_DIR_SEPARATOR (t_path[i]))
+      t_path[i] = DIR_SEPARATOR;
+}
+
+static void
+process_collect_gcc_into_devices_dir (char **devices_loc)
+{
+  const char rest_of_devices_path[] = "/msp430-elf/include/devices/";
+  char *t_devices_loc = *devices_loc;
+  /* Go up a directory to the toolchain root.  */
+  t_devices_loc = msp430_dirname (msp430_dirname (t_devices_loc));
+  t_devices_loc = concat (t_devices_loc, rest_of_devices_path, NULL);
+  *devices_loc = t_devices_loc;
+}
+
+int
+msp430_check_env_var_for_devices (char **local_devices_csv_loc)
+{
+  const int num_vars = 2;
+  const char dirsep[2] = { DIR_SEPARATOR, 0 };
+  /* Use the COLLECT_GCC environment variable to find toolchain root directory.
+   */
+  const char *env_vars[num_vars] = { "MSP430_GCC_INCLUDE_DIR", "COLLECT_GCC" };
+  FILE *devices_csv_file = NULL;
+  unsigned int i;
+
+  for (i = 0; i < num_vars; i++)
+    {
+      char *t_devices_loc;
+      char *val = getenv (env_vars[i]);
+      if (val == NULL)
+	continue;
+      t_devices_loc = ASTRDUP (val);
+
+      /* MSP430_GCC_INCLUDE_DIR.  */
+      if (i == 0)
+	{
+	  if (!IS_DIR_SEPARATOR (t_devices_loc[strlen (t_devices_loc) - 1]))
+	    t_devices_loc = concat (t_devices_loc, dirsep, NULL);
+	}
+      /* COLLECT_GCC.  */
+      else if (i == 1)
+	process_collect_gcc_into_devices_dir (&t_devices_loc);
+
+      t_devices_loc = concat (t_devices_loc, "devices.csv", NULL);
+      devices_csv_file = fopen (t_devices_loc,  "r");
+      if (devices_csv_file != NULL)
+	{
+	  fclose (devices_csv_file);
+	  *local_devices_csv_loc = t_devices_loc;
+	  canonicalize_path_dirsep (local_devices_csv_loc);
+	  return 0;
+	}
+    }
+  return 1;
+}
+
 const char *
 msp430_check_path_for_devices (int argc, const char **argv)
 {
@@ -38,6 +120,7 @@  msp430_check_path_for_devices (int argc, const char **argv)
   for (i = 0; i < argc; i++)
     {
       char *inc_path = ASTRDUP (argv[i]);
+      canonicalize_path_dirsep (&inc_path);
       if (!IS_DIR_SEPARATOR (inc_path[strlen (inc_path) - 1]))
 	inc_path = concat (inc_path, dirsep, NULL);
       local_devices_csv_loc = concat (inc_path, "devices.csv", NULL);
@@ -206,7 +289,10 @@  parse_devices_csv (const char * mcu_name)
   /* Otherwise check if the path to devices.csv was found another way.  */
   else if (derived_devices_csv_loc != NULL)
     return parse_devices_csv_1 (derived_devices_csv_loc, mcu_name);
-  return 1;
+  /* Otherwise we need to use environment variables to try and find it.  */
+  else
+    return msp430_check_env_var_for_devices (&derived_devices_csv_loc)
+	    || parse_devices_csv_1 (derived_devices_csv_loc, mcu_name);
 }
 
 /* This function only needs to be executed once, but it can be first called
diff --git a/gcc/config/msp430/msp430-devices.h b/gcc/config/msp430/msp430-devices.h
index 9500115..e92927a 100644
--- a/gcc/config/msp430/msp430-devices.h
+++ b/gcc/config/msp430/msp430-devices.h
@@ -9,3 +9,5 @@  struct t_msp430_mcu_data
 extern struct t_msp430_mcu_data extracted_mcu_data;
 
 void msp430_extract_mcu_data (const char * mcu_name, bool surpress_warn);
+int msp430_check_env_var_for_devices (char **local_devices_csv_loc);
+char * msp430_dirname (char *path);
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index a112b1b..b22d67c 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -46,6 +46,8 @@ 
 #include "builtins.h"
 #include "intl.h"
 #include "msp430-devices.h"
+#include "incpath.h"
+#include "prefix.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -3252,6 +3254,20 @@  msp430_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t)
     return false;
   return true;
 }
+
+void
+msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
+			      const char *iprefix ATTRIBUTE_UNUSED,
+			      int stdinc ATTRIBUTE_UNUSED)
+{
+  char *include_dir;
+  if (msp430_check_env_var_for_devices (&include_dir))
+    return;
+  include_dir = msp430_dirname (include_dir);
+
+  include_dir = update_path (include_dir, "");
+  add_path (include_dir, INC_SYSTEM, false, false);
+}
 
 #undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index a8daf3f..ce94116 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -47,11 +47,14 @@  extern bool msp430x;
 extern const char * msp430_select_hwmult_lib (int, const char **);
 extern const char * msp430_select_cpu (int, const char **);
 extern const char * msp430_check_path_for_devices (int, const char **);
+extern const char * msp430_get_linker_devices_include_path (int, const char **);
 
 # define EXTRA_SPEC_FUNCTIONS				\
   { "msp430_hwmult_lib", msp430_select_hwmult_lib }, \
   { "msp430_select_cpu", msp430_select_cpu }, \
-  { "msp430_check_path_for_devices", msp430_check_path_for_devices },
+  { "msp430_check_path_for_devices", msp430_check_path_for_devices }, \
+  { "msp430_get_linker_devices_include_path", \
+    msp430_get_linker_devices_include_path },
 
 #undef  STARTFILE_SPEC
 #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{minrt:crt0-minrt.o%s}%{!minrt:crt0.o%s}} %{!minrt:crtbegin.o%s}"
@@ -74,7 +77,8 @@  extern const char * msp430_check_path_for_devices (int, const char **);
    are creating a relocatable binary (gc does not work) or debugging
    is enabled  (the GDB testsuite relies upon unused entities not being deleted).  */
 #define LINK_SPEC "%{mrelax:--relax} %{mlarge:%{!r:%{!g:--gc-sections}}} " \
-  "%{mcode-region=*:--code-region=%*} %{mdata-region=*:--data-region=%*}"
+  "%{mcode-region=*:--code-region=%*} %{mdata-region=*:--data-region=%*} " \
+  "%:msp430_get_linker_devices_include_path(%{L*:%*})"
 
 #define DRIVER_SELF_SPECS \
   " %{I*:%:msp430_check_path_for_devices(%{I*:%*})}"       \
@@ -424,5 +428,9 @@  typedef struct
 #undef  USE_SELECT_SECTION_FOR_FUNCTIONS
 #define USE_SELECT_SECTION_FOR_FUNCTIONS 1
 
+void msp430_register_pre_includes (const char *sysroot, const char *iprefix,
+    int stdinc);
+#define TARGET_EXTRA_PRE_INCLUDES msp430_register_pre_includes
+
 #define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN)	\
   msp430_output_aligned_decl_common ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 19f32bc..bc09205 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -22068,8 +22068,32 @@  The ISA and hardware multiply supported for the different MCUs is hard-coded
 into GCC.  However, an external @samp{devices.csv} file can be used to
 extend device support beyond those that have been hard-coded.
 
-GCC searches for the @samp{devices.csv} file on the include paths specified
-with @code{-I}.
+GCC searches for the @samp{devices.csv} file using the following methods in the
+given precedence order, where the first method takes precendence over the
+second which takes precedence over the third.
+
+@table @asis
+@item Include path specified with @code{-I}
+@samp{devices.csv} will be searched for in each of the directories specified by
+include paths.
+@item Path specified by the environment variable @samp{MSP430_GCC_INCLUDE_DIR}
+Define the value of the global environment variable
+@samp{MSP430_GCC_INCLUDE_DIR}
+to the full path to the directory containing devices.csv, and GCC will search
+this directory for devices.csv.  If devices.csv is found, this directory will
+also be registered as an include path, and linker library path.  Header files
+and linker scripts in this directory can therefore be used without manually
+specifying @code{-I} and @code{-L} on the command line.
+@item The @samp{msp430-elf/include/devices} directory
+Finally, GCC will examine @samp{msp430-elf/include/devices} from the
+toolchain root directory.  This directory does not exist in a default
+installation, but if the user has created it and copied @samp{devices.csv}
+there, then the MCU data will be read.  As above, this directory will
+also be registered as an include path, and linker library path.
+
+@end table
+If none of the above search methods find @samp{devices.csv}, then the
+hard-coded MCU data is used.
 
 @item -mwarn-mcu
 @itemx -mno-warn-mcu
diff --git a/gcc/testsuite/gcc.target/msp430/devices/csv_using_env_var.c b/gcc/testsuite/gcc.target/msp430/devices/csv_using_env_var.c
new file mode 100644
index 0000000..506ae74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/devices/csv_using_env_var.c
@@ -0,0 +1,10 @@ 
+/* { dg-do link } */
+/* { dg-msp-options "-mmcu=msp430_28" } */
+/* { dg-warning "supports 430X ISA but -mcpu option is set to 430" "" { target 430_selected } 0 } */
+/* { dg-warning "supports f5series hardware multiply" "" { target msp430_hwmul_not_f5 } 0 } */
+
+/* This tests that the environment variable MSP430_GCC_INCLUDE_DIR can be used
+   to specify the path to the directory containing devices.csv.
+   The variable is set in msp430.exp.  */
+
+#include "../devices-main.c"
diff --git a/gcc/testsuite/gcc.target/msp430/devices/csv_using_installed.c b/gcc/testsuite/gcc.target/msp430/devices/csv_using_installed.c
new file mode 100644
index 0000000..f5d7806
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/devices/csv_using_installed.c
@@ -0,0 +1,11 @@ 
+/* { dg-do link } */
+/* { dg-msp-options "-mmcu=msp430_28" } */
+/* { dg-warning "supports 430X ISA but -mcpu option is set to 430" "" { target 430_selected } 0 } */
+/* { dg-warning "supports f5series hardware multiply" "" { target msp430_hwmul_not_f5 } 0 } */
+
+/* This tests that the devices.csv can be installed into the
+   "$TOOLCHAIN_ROOT/msp430-elf/include/devices/" and used to read device data.
+   msp430.exp will mark this test unsupported if the above directory does not
+   exist.  */
+
+#include "../devices-main.c"
diff --git a/gcc/testsuite/gcc.target/msp430/devices/csv_using_option.c b/gcc/testsuite/gcc.target/msp430/devices/csv_using_option.c
new file mode 100644
index 0000000..c8d7f6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/devices/csv_using_option.c
@@ -0,0 +1,12 @@ 
+/* { dg-do link } */
+/* { dg-msp-options "-mmcu=msp430_28" } */
+/* { dg-warning "supports 430X ISA but -mcpu option is set to 430" "" { target 430_selected } 0 } */
+/* { dg-warning "supports f5series hardware multiply" "" { target msp430_hwmul_not_f5 } 0 } */
+
+/* This tests that the -mdevices-csv-loc option can be used to specify the path
+   to devices.csv.
+   The option is passed in msp430.exp, rather than in the dg-msp-options
+   directive above, as the full path to devices.csv is not known at this
+   point.  */
+
+#include "../devices-main.c"
diff --git a/gcc/testsuite/gcc.target/msp430/msp430.exp b/gcc/testsuite/gcc.target/msp430/msp430.exp
index 2cdf436..fe57469 100644
--- a/gcc/testsuite/gcc.target/msp430/msp430.exp
+++ b/gcc/testsuite/gcc.target/msp430/msp430.exp
@@ -215,6 +215,29 @@  proc msp430_device_permutations_runtest { tests default_cflags } {
 	if { ![runtest_file_p $runtests $test_file] } {
 	    continue
 	}
+ 	# Don't run torture style tests on every method of locating devices.csv
+ 	# The device name passed to -mmcu in the csv_using_* tests do not exist
+ 	# in the hard-coded data, so to ensure the test fails if method can't
+ 	# find the device data.
+ 	if { [file tail $test_file] eq "csv_using_installed.c" } {
+ 	    msp430_test_installed_device_data $test_file $default_cflags
+ 	    continue
+ 	# The path passed to -mdevices-csv-loc is not used to infer an
+ 	# include dir to find msp430.h, so define TESTING_HARD_DATA to prevent
+ 	# msp430.h being included.
+ 	} elseif { [file tail $test_file] eq "csv_using_option.c" } {
+ 	    dg-runtest $test_file \
+ 		"-mdevices-csv-loc=[file dirname $test_file]/devices.csv" \
+ 		"-DTESTING_HARD_DATA $default_cflags"
+ 	    continue
+ 	} elseif { [file tail $test_file] eq "csv_using_env_var.c" } {
+ 	    setenv MSP430_GCC_INCLUDE_DIR [file dirname $test_file]
+ 	    verbose -log "MSP430_GCC_INCLUDE_DIR=[file dirname $test_file]"
+ 	    dg-runtest $test_file "" "$default_cflags"
+ 	    setenv MSP430_GCC_INCLUDE_DIR ""
+ 	    verbose -log "MSP430_GCC_INCLUDE_DIR=\"\""
+ 	    continue
+ 	}
 	foreach { mcu_flags } [msp430_get_supported_opts $test_file] {
 	    if { [string match "csv_*" [file tail $test_file]] } {
 		dg-runtest $test_file "$mcu_flags" "-I[file dirname $test_file] $default_cflags"
@@ -228,6 +251,48 @@  proc msp430_device_permutations_runtest { tests default_cflags } {
     }
 }
 
+# Return $TOOLCHAIN_ROOT/msp430-elf/include/devices/
+proc get_installed_device_data_path { } {
+    set compiler [lindex [regexp -all -inline {\S+} \
+	[board_info [target_info name] compiler]] 0]
+    # $compiler is actually a file, but normalize will still get us the desired
+    # result.
+    return [file normalize \
+	"$compiler/../../msp430-elf/include/devices/devices.csv"]
+}
+
+# If the devices.csv is installed in
+# $TOOLCHAIN_ROOT/msp430-elf/include/devices/, rename it so it doesn't
+# interfere with the hard-coded device data tests.
+proc msp430_hide_installed_devices_data { } {
+    set devices_path [get_installed_device_data_path]
+    if { [file exists $devices_path] } {
+	file rename $devices_path "$devices_path.bak"
+    }
+}
+
+# Restore devices.csv if renamed by msp430_hide_installed_devices_data.
+proc msp430_restore_installed_devices_data { } {
+    set devices_path [get_installed_device_data_path]
+    if { [file exists "$devices_path.bak"] } {
+	file rename "$devices_path.bak" $devices_path 
+    }
+}
+
+proc msp430_test_installed_device_data { name default_cflags } {
+    global subdir
+    msp430_restore_installed_devices_data 
+    set devices_path [get_installed_device_data_path]
+    if { [file exists $devices_path] } {
+	dg-runtest $name "" "$default_cflags"
+    } else {
+	set shorter_name "$subdir/[file tail $name]"
+	verbose -log "$shorter_name not supported, $devices_path doesn't exist."
+	unsupported $shorter_name
+    }
+    msp430_hide_installed_devices_data 
+}
+
 # Load support procs.
 load_lib gcc-dg.exp
 
@@ -245,18 +310,21 @@  if [info exists DEFAULT_CFLAGS] then {
 # Initialize `dg'.
 dg-init
 
-msp430_set_old_board_info_ldflags
+msp430_hide_installed_devices_data
 
 # Main loop.
 dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
     "" "$MSP430_DEFAULT_CFLAGS"
 
+msp430_set_old_board_info_ldflags
+
 msp430_device_permutations_runtest \
     [lsort [glob -nocomplain $srcdir/$subdir/devices/*.\[cCS\]]] \
     "$MSP430_DEFAULT_CFLAGS"
 
 # Reset any possibly changed ldflags by dg-msp-options
 msp430_reset_board_info_ldflags
+msp430_restore_installed_devices_data 
 
 # All done.
 dg-finish
-- 
2.7.4