MSP430: Add new methods of finding external MCU data file

MCU data file can now be specified with an environment variable or installed
into a toolchain subdirectory.

2019-11-04  Jozef Lawrynowicz  <jozef.l@mittosystems.com>

gcc/
	* config/msp430/driver-msp430.c
	(msp430_get_linker_devices_include_path): New spec function.
	* config/msp430/msp430-devices.c (msp430_dirname): New function.
	(extract_devices_dir_from_exec_prefix): New function.
	(extract_devices_dir_from_collect_gcc): New function.
	(msp430_check_env_var_for_devices): New function.
	(msp430_check_path_for_devices): Use xstrdup instead of ASTRDUP.
	(parse_devices_csv): Call msp430_check_env_var_for_devices if
	devices.csv was not found using other methods.
	* config/msp430/msp430-devices.h (msp430_check_env_var_for_devices):
	New prototype.
	(msp430_dirname): Likewise.
	* config/msp430/msp430.c (msp430_register_pre_includes): New function.
	* config/msp430/msp430.h (EXTRA_SPEC_FUNCTIONS): Add
	msp430_get_linker_devices_include_path.
	(TARGET_EXTRA_PRE_INCLUDES): Define.
	* doc/invoke.texi: Document new ways of searching for support files.

gcc/testsuite/
	* gcc.target/msp430/devices/csv-using-env-var.c: New test.
	* gcc.target/msp430/devices/csv-using-installed.c: New test.
	* gcc.target/msp430/devices/csv-using-option.c: New test.
	* gcc.target/msp430/devices/devices-main.c: New test source file.
	* gcc.target/msp430/devices/msp430-devices.h: New test.
	* gcc.target/msp430/msp430.exp (msp430_device_permutations_runtest):
	Add special cases for csv-using* tests.
	Define TESTING_HARD_DATA when running tests that use hard-coded device
	data.
	(get_installed_device_data_path): New.
	(msp430_hide_installed_devices_data): New.
	(msp430_restore_installed_devices_data): New.
	(msp430_test_installed_device_data): New.
	(msp430_install_device_data): New.

From-SVN: r277772
This commit is contained in:
Jozef Lawrynowicz 2019-11-04 11:01:03 +00:00 committed by Jozef Lawrynowicz
parent b76f4e6c06
commit d7eabfd452
14 changed files with 369 additions and 9 deletions

View File

@ -1,3 +1,23 @@
2019-11-04 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* config/msp430/driver-msp430.c
(msp430_get_linker_devices_include_path): New spec function.
* config/msp430/msp430-devices.c (msp430_dirname): New function.
(extract_devices_dir_from_exec_prefix): New function.
(extract_devices_dir_from_collect_gcc): New function.
(msp430_check_env_var_for_devices): New function.
(msp430_check_path_for_devices): Use xstrdup instead of ASTRDUP.
(parse_devices_csv): Call msp430_check_env_var_for_devices if
devices.csv was not found using other methods.
* config/msp430/msp430-devices.h (msp430_check_env_var_for_devices):
New prototype.
(msp430_dirname): Likewise.
* config/msp430/msp430.c (msp430_register_pre_includes): New function.
* config/msp430/msp430.h (EXTRA_SPEC_FUNCTIONS): Add
msp430_get_linker_devices_include_path.
(TARGET_EXTRA_PRE_INCLUDES): Define.
* doc/invoke.texi: Document new ways of searching for support files.
2019-11-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/92301

View File

@ -150,6 +150,19 @@ msp430_select_hwmult_lib (int argc ATTRIBUTE_UNUSED,
return "-lmul_none";
}
/* Spec function. Used to place the path to the MSP430-GCC support files
on the command line, prefixed with "-L", so the linker finds the linker
scripts in that directory. */
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);
}
/* Spec function. Propagate -m{code,data}-region= to the linker, unless the
lower region has been specified without -muse-lower-region-prefix also being
used. */

View File

@ -37,7 +37,7 @@ extern struct t_msp430_mcu_data hard_msp430_mcu_data[605];
/* Set to the full path to devices.csv if it is found by searching the -I and
-L paths. */
char * derived_devices_csv_loc = NULL;
char *derived_devices_csv_loc = NULL;
/* This is to canonicalize the directory separators in the path.
On Windows we could have a mix of '/' and '\' in the path. */
@ -52,6 +52,128 @@ canonicalize_path_dirsep (char **path)
t_path[i] = DIR_SEPARATOR;
}
/* This function returns the enclosing directory of PATH.
It is inconsequential whether PATH ends in a dirsep or not.
It 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;
}
/* devices.csv path from the toolchain root. */
static const char rest_of_devices_path[] = "/msp430-elf/include/devices/";
/* "The default value of GCC_EXEC_PREFIX is prefix/lib/gcc". Strip lib/gcc
from GCC_EXEC_PREFIX to get the path to the installed toolchain. */
static void
extract_devices_dir_from_exec_prefix (char **devices_loc)
{
const char *temp;
char *gcc_exec_prefix = *devices_loc;
int len = strlen (gcc_exec_prefix);
/* Copied from gcc.c. */
if (len > (int) sizeof ("/lib/gcc/") - 1
&& (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
{
temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
if (IS_DIR_SEPARATOR (*temp)
&& filename_ncmp (temp + 1, "lib", 3) == 0
&& IS_DIR_SEPARATOR (temp[4])
&& filename_ncmp (temp + 5, "gcc", 3) == 0)
{
len -= sizeof ("/lib/gcc/") - 1;
/* Keep the '/' from the beginning of /lib/gcc. */
gcc_exec_prefix[len + 1] = (char) 0;
*devices_loc = concat (gcc_exec_prefix, rest_of_devices_path, NULL);
return;
}
}
}
/* Given the path to the GCC executable, return the path to the installed
device data in "$TOOLCHAIN_ROOT/msp430-elf/include/devices".
Assumes the GCC executable is in "$TOOLCHAIN_ROOT/<somedir>/". */
static void
extract_devices_dir_from_collect_gcc (char **devices_loc)
{
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;
}
/* The path to the MSP430-GCC support files can be specified with the
environment variable "MSP430_GCC_INCLUDE_DIR", or installed into the
toolchain in the msp430-elf/include/devices subdirectory.
We use the GCC_EXEC_PREFIX or COLLECT_GCC environment variables as a starting
point for the location of the toolchain, and work out the path to the
installed device data from there.
Return 0 and set LOCAL_DEVICES_CSV_LOC if we find devices.csv. Return 1
if devices.csv wasn't found. */
int
msp430_check_env_var_for_devices (char **local_devices_csv_loc)
{
const int num_vars = 3;
const char dirsep[2] = { DIR_SEPARATOR, 0 };
/* Both GCC_EXEC_PREFIX and COLLECT_GCC should always be set to the format we
expect, as they are required for correct operation of the toolchain.
So if they are wrong the user will probably have bigger problems.
GCC_EXEC_PREFIX is only defined in the driver, whilst COLLECT_GCC is only
defined in the compiler proper, so we need both. */
const char *env_vars[num_vars] = {
"MSP430_GCC_INCLUDE_DIR", "GCC_EXEC_PREFIX", "COLLECT_GCC" };
enum msp430_include_vars {
MSP430_GCC_INCLUDE_DIR,
GCC_EXEC_PREFIX,
COLLECT_GCC
};
FILE *devices_csv_file = NULL;
int i;
for (i = MSP430_GCC_INCLUDE_DIR; i <= COLLECT_GCC; i++)
{
char *t_devices_loc;
char *val = getenv (env_vars[i]);
if (val == NULL)
continue;
t_devices_loc = xstrdup (val);
if (i == MSP430_GCC_INCLUDE_DIR)
{
if (!IS_DIR_SEPARATOR (t_devices_loc[strlen (t_devices_loc) - 1]))
t_devices_loc = concat (t_devices_loc, dirsep, NULL);
}
else if (i == GCC_EXEC_PREFIX)
extract_devices_dir_from_exec_prefix (&t_devices_loc);
else if (i == COLLECT_GCC)
extract_devices_dir_from_collect_gcc (&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;
}
/* Spec function which searches the paths passed to the -I and -L options for
the "devices.csv" file. If it is found then the -mdevices-csv-loc option is
placed on the command line so the compiler knows the location of the
@ -69,7 +191,7 @@ msp430_check_path_for_devices (int argc, const char **argv)
return NULL;
for (i = 0; i < argc; i++)
{
char *inc_path = ASTRDUP (argv[i]);
char *inc_path = xstrdup (argv[i]);
canonicalize_path_dirsep (&inc_path);
if (!IS_DIR_SEPARATOR (inc_path[strlen (inc_path) - 1]))
inc_path = concat (inc_path, dirsep, NULL);
@ -274,8 +396,11 @@ 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);
/* devices.csv was not found. */
return 2;
/* Otherwise we need to use environment variables to try and find it. */
if (msp430_check_env_var_for_devices (&derived_devices_csv_loc))
/* devices.csv was not found. */
return 2;
return parse_devices_csv_1 (derived_devices_csv_loc, mcu_name);
}
/* Main entry point to load the MCU data for the given -mmcu into

View File

@ -29,3 +29,5 @@ struct t_msp430_mcu_data
extern struct t_msp430_mcu_data extracted_mcu_data;
void msp430_extract_mcu_data (const char * mcu_name);
int msp430_check_env_var_for_devices (char **local_devices_csv_loc);
char *msp430_dirname (char *path);

View File

@ -47,6 +47,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"
@ -3634,6 +3636,27 @@ msp430_incoming_return_addr_rtx (void)
{
return gen_rtx_MEM (Pmode, stack_pointer_rtx);
}
/* If the path to the MSP430-GCC support files has been found by examining
an environment variable (see msp430_check_env_var_for_devices in
msp430-devices.c), or -mdevices-csv-loc=, register this path as an include
directory so the user can #include msp430.h without needing to specify the
path to the support files with -I. */
void
msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
const char *iprefix ATTRIBUTE_UNUSED,
int stdinc ATTRIBUTE_UNUSED)
{
char *include_dir;
if (msp430_devices_csv_loc)
include_dir = xstrdup (msp430_devices_csv_loc);
else 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);
}
/* Instruction generation stuff. */

View File

@ -75,6 +75,7 @@ extern bool msp430x;
"msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
"%{mdata-region=*:--data-region=%:" \
"msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \
"%:msp430_get_linker_devices_include_path()"
#define DRIVER_SELF_SPECS \
" %{!mlarge:%{mcode-region=*:%{mdata-region=*:%e-mcode-region and " \
@ -94,6 +95,7 @@ extern const char * msp430_select_cpu (int, const char **);
extern const char * msp430_set_driver_var (int, const char **);
extern const char * msp430_check_path_for_devices (int, const char **);
extern const char *msp430_propagate_region_opt (int, const char **);
extern const char *msp430_get_linker_devices_include_path (int, const char **);
/* There must be a trailing comma after the last item, see gcc.c
"static_spec_functions". */
@ -102,7 +104,9 @@ extern const char *msp430_propagate_region_opt (int, const char **);
{ "msp430_select_cpu", msp430_select_cpu }, \
{ "msp430_set_driver_var", msp430_set_driver_var }, \
{ "msp430_check_path_for_devices", msp430_check_path_for_devices }, \
{ "msp430_propagate_region_opt", msp430_propagate_region_opt },
{ "msp430_propagate_region_opt", msp430_propagate_region_opt }, \
{ "msp430_get_linker_devices_include_path", \
msp430_get_linker_devices_include_path },
/* Specify the libraries to include on the linker command line.
@ -496,6 +500,12 @@ typedef struct
#define TARGET_HAS_NO_HW_DIVIDE (! TARGET_HWMULT)
void msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED,
const char *iprefix ATTRIBUTE_UNUSED,
int stdinc ATTRIBUTE_UNUSED);
#undef TARGET_EXTRA_PRE_INCLUDES
#define TARGET_EXTRA_PRE_INCLUDES msp430_register_pre_includes
#undef USE_SELECT_SECTION_FOR_FUNCTIONS
#define USE_SELECT_SECTION_FOR_FUNCTIONS 1

View File

@ -23231,8 +23231,33 @@ 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 paths specified
with the @code{-I} and @code{-L} options.
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} and @code{-L}
@samp{devices.csv} will be searched for in each of the directories specified by
include paths and linker library search 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

View File

@ -1,3 +1,20 @@
2019-11-04 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* gcc.target/msp430/devices/csv-using-env-var.c: New test.
* gcc.target/msp430/devices/csv-using-installed.c: New test.
* gcc.target/msp430/devices/csv-using-option.c: New test.
* gcc.target/msp430/devices/devices-main.c: New test source file.
* gcc.target/msp430/devices/msp430-devices.h: New test.
* gcc.target/msp430/msp430.exp (msp430_device_permutations_runtest):
Add special cases for csv-using* tests.
Define TESTING_HARD_DATA when running tests that use hard-coded device
data.
(get_installed_device_data_path): New.
(msp430_hide_installed_devices_data): New.
(msp430_restore_installed_devices_data): New.
(msp430_test_installed_device_data): New.
(msp430_install_device_data): New.
2019-11-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/92301

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-additional-options "-mmcu=msp430_28" } */
/* { dg-warning "supports 430X ISA but '-mcpu' option is set to 430" "" { target msp430_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"

View File

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { dg-additional-options "-mmcu=msp430_28" } */
/* { dg-warning "supports 430X ISA but '-mcpu' option is set to 430" "" { target msp430_430_selected } 0 } */
/* { dg-warning "supports f5series hardware multiply" "" { target msp430_hwmul_not_f5 } 0 } */
/* This tests that devices.csv can be installed into the
"$TOOLCHAIN_ROOT/msp430-elf/include/devices/" and used to read device data. */
#include "devices-main.c"

View File

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { dg-additional-options "-mmcu=msp430_28" } */
/* { dg-warning "supports 430X ISA but '-mcpu' option is set to 430" "" { target msp430_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. */
#include "devices-main.c"

View File

@ -1,3 +1,7 @@
#ifndef TESTING_HARD_DATA
#include <msp430-devices.h>
#endif
int
main (void)
{

View File

@ -0,0 +1,3 @@
#ifndef __MSP430__
#error
#endif

View File

@ -101,6 +101,25 @@ proc msp430_device_permutations_runtest { tests } {
if { ![runtest_file_p $runtests $test_file] } {
continue
}
# The device name passed to -mmcu in the csv-using-* tests do not exist
# in the hard-coded data, to ensure the test fails if the method can't
# find the device data.
if { [file tail $test_file] eq "csv-using-installed.c" } {
msp430_test_installed_device_data $test_file $MSP430_DEFAULT_CFLAGS
continue
} elseif { [file tail $test_file] eq "csv-using-option.c" } {
dg-runtest $test_file \
"-mdevices-csv-loc=[file dirname $test_file]/devices.csv" \
"$MSP430_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 "" "$MSP430_DEFAULT_CFLAGS"
setenv MSP430_GCC_INCLUDE_DIR ""
verbose -log "MSP430_GCC_INCLUDE_DIR=\"\""
continue
}
foreach { mcu_flags } [msp430_get_opts $test_file] {
if { [string match "csv-*" [file tail $test_file]] } {
# Specify the path to devices.csv for devices/csv-* tests with -I.
@ -115,12 +134,76 @@ proc msp430_device_permutations_runtest { tests } {
} elseif { [string match "bad-devices*" [file tail $test_file]] } {
dg-runtest $test_file "$mcu_flags" "-mdevices-csv-loc=[file dirname $test_file]/[file tail $test_file]sv $MSP430_DEFAULT_CFLAGS"
} else {
dg-runtest $test_file "$mcu_flags" "$MSP430_DEFAULT_CFLAGS"
dg-runtest $test_file "$mcu_flags -DTESTING_HARD_DATA" "$MSP430_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
global env
# The initial value for GCC_EXEC_PREFIX set by target-libpath.exp is not
# correct for cross-compilers so fix it here. GCC fixes the value itself,
# but not after spec functions are executed, which can cause a warning
# about missing devices.csv to be emitted.
set compiler [lindex [regexp -all -inline {\S+} \
[board_info [target_info name] compiler]] 0]
set real_exec_prefix "[file normalize "$compiler/../../lib/gcc"]/"
setenv GCC_EXEC_PREFIX $real_exec_prefix
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
}
proc msp430_install_device_data { testsuite_dir } {
set devices_path [get_installed_device_data_path]
if { [file exists $devices_path] } {
return
}
set installed_path [file dirname $devices_path]
file mkdir $installed_path
file copy $testsuite_dir/msp430-devices.h $testsuite_dir/devices.csv $installed_path
}
# Load support procs.
load_lib gcc-dg.exp
@ -138,11 +221,18 @@ if [info exists DEFAULT_CFLAGS] then {
# Initialize `dg'.
dg-init
# Install then hide the devices data now, in case it is already installed. We
# don't want it to interfere with tests until we need it to.
msp430_install_device_data $srcdir/$subdir/devices
msp430_hide_installed_devices_data
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
"" $MSP430_DEFAULT_CFLAGS
msp430_device_permutations_runtest [lsort [glob -nocomplain $srcdir/$subdir/devices/*.\[cCS\]]]
msp430_restore_installed_devices_data
# All done.
dg-finish