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
@@ -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);
+}
@@ -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
@@ -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);
@@ -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
@@ -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))
@@ -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
new file mode 100644
@@ -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"
new file mode 100644
@@ -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"
new file mode 100644
@@ -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"
@@ -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