diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-27 00:25:14 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-27 00:25:14 +0100 |
commit | dbcc589f4577ebb0d6d05e36e2ac1246b56555ed (patch) | |
tree | b6c2d381e8b144e67aa8002ab9a1c3fe5a0c98dd | |
parent | 50438f45934d885aa00b126dd9359895e05fd056 (diff) | |
parent | fd59a5e8d5aca68c417e9d4e19b7df5d99e9c570 (diff) | |
download | sparse-dbcc589f4577ebb0d6d05e36e2ac1246b56555ed.tar.gz |
Merge branch 'arm-hf' into master
-rwxr-xr-x | cgcc | 2 | ||||
-rw-r--r-- | lib.c | 485 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | machine.h | 15 | ||||
-rw-r--r-- | validation/arch/arm-predef-float-abi-hard.c | 8 | ||||
-rw-r--r-- | validation/arch/arm-predef-float-abi-mixed.c | 8 | ||||
-rw-r--r-- | validation/arch/arm-predef-float-abi-soft.c | 8 | ||||
-rw-r--r-- | validation/arch/arm-predef-hard-float.c | 8 | ||||
-rw-r--r-- | validation/arch/arm-predef-soft-float.c | 8 |
9 files changed, 328 insertions, 215 deletions
@@ -295,7 +295,7 @@ sub add_specs { return (' --arch=arm' . &float_types (1, 1, 36, [24,8], [53,11], [53, 11])); } elsif ($spec eq 'arm+hf') { - return &add_specs ('arm') . ' -D__ARM_PCS_VFP=1'; + return &add_specs ('arm') . ' -mfloat-abi=hard'; } elsif ($spec eq 'aarch64') { return (' --arch=aarch64' . &float_types (1, 1, 36, [24,8], [53,11], [113,15])); @@ -330,6 +330,7 @@ static int arch_msize_long = 0; int arch_m64 = ARCH_M64_DEFAULT; int arch_big_endian = ARCH_BIG_ENDIAN; int arch_mach = MACH_NATIVE; +int arch_fp_abi = FP_ABI_NATIVE; int arch_cmodel = CMODEL_UNKNOWN; @@ -356,185 +357,29 @@ void add_pre_buffer(const char *fmt, ...) pre_buffer_end = end; } -static char **handle_switch_D(char *arg, char **next) -{ - const char *name = arg + 1; - const char *value = "1"; +//////////////////////////////////////////////////////////////////////////////// +// Helpers for option parsing - if (!*name) { - arg = *++next; - if (!arg) - die("argument to `-D' is missing"); - name = arg; - } - - for (;;arg++) { - char c; - c = *arg; - if (!c) - break; - if (c == '=') { - *arg = '\0'; - value = arg + 1; - break; - } - } - add_pre_buffer("#define %s %s\n", name, value); - return next; -} - -static char **handle_switch_E(char *arg, char **next) -{ - if (arg[1] == '\0') - preprocess_only = 1; - return next; -} - -static char **handle_switch_I(char *arg, char **next) -{ - char *path = arg+1; - - switch (arg[1]) { - case '-': - add_pre_buffer("#split_include\n"); - break; - - case '\0': /* Plain "-I" */ - path = *++next; - if (!path) - die("missing argument for -I option"); - /* Fall through */ - default: - add_pre_buffer("#add_include \"%s/\"\n", path); - } - return next; -} - -static void add_cmdline_include(char *filename) -{ - if (cmdline_include_nr >= CMDLINE_INCLUDE) - die("too many include files for %s\n", filename); - cmdline_include[cmdline_include_nr++] = filename; -} - -static char **handle_switch_i(char *arg, char **next) -{ - if (*next && !strcmp(arg, "include")) - add_cmdline_include(*++next); - else if (*next && !strcmp(arg, "imacros")) - add_cmdline_include(*++next); - else if (*next && !strcmp(arg, "isystem")) { - char *path = *++next; - if (!path) - die("missing argument for -isystem option"); - add_pre_buffer("#add_isystem \"%s/\"\n", path); - } else if (*next && !strcmp(arg, "idirafter")) { - char *path = *++next; - if (!path) - die("missing argument for -idirafter option"); - add_pre_buffer("#add_dirafter \"%s/\"\n", path); - } - return next; -} - -static char **handle_switch_M(char *arg, char **next) -{ - if (!strcmp(arg, "MF") || !strcmp(arg,"MQ") || !strcmp(arg,"MT")) { - if (!*next) - die("missing argument for -%s option", arg); - return next + 1; - } - return next; -} - -static char **handle_multiarch_dir(char *arg, char **next) -{ - multiarch_dir = *++next; - if (!multiarch_dir) - die("missing argument for -multiarch-dir option"); - return next; -} - -static char **handle_switch_m(char *arg, char **next) -{ - if (!strcmp(arg, "m64")) { - arch_m64 = ARCH_LP64; - } else if (!strcmp(arg, "m32") || !strcmp(arg, "m16")) { - arch_m64 = ARCH_LP32; - } else if (!strcmp(arg, "m31")) { - arch_m64 = ARCH_LP32; - } else if (!strcmp(arg, "mx32")) { - arch_m64 = ARCH_X32; - } else if (!strcmp(arg, "msize-llp64")) { - arch_m64 = ARCH_LLP64; - } else if (!strcmp(arg, "msize-long")) { - arch_msize_long = 1; - } else if (!strcmp(arg, "multiarch-dir")) { - return handle_multiarch_dir(arg, next); - } else if (!strcmp(arg, "mbig-endian")) { - arch_big_endian = 1; - } else if (!strcmp(arg, "mlittle-endian")) { - arch_big_endian = 0; - } else if (!strncmp(arg, "mcmodel", 7)) { - arg += 7; - if (*arg++ != '=') - die("missing argument for -mcmodel"); - else if (!strcmp(arg, "kernel")) - arch_cmodel = CMODEL_KERNEL; - else if (!strcmp(arg, "large")) - arch_cmodel = CMODEL_LARGE; - else if (!strcmp(arg, "medany")) - arch_cmodel = CMODEL_MEDANY; - else if (!strcmp(arg, "medium")) - arch_cmodel = CMODEL_MEDIUM; - else if (!strcmp(arg, "medlow")) - arch_cmodel = CMODEL_MEDLOW; - else if (!strcmp(arg, "small")) - arch_cmodel = CMODEL_SMALL; - else if (!strcmp(arg, "tiny")) - arch_cmodel = CMODEL_TINY; - else - die("invalid argument for -mcmodel=%s", arg); - } - return next; -} - -static void handle_arch_msize_long_finalize(void) -{ - if (arch_msize_long) { - size_t_ctype = &ulong_ctype; - ssize_t_ctype = &long_ctype; - } -} +struct val_map { + const char *name; + int val; +}; -static void handle_arch_finalize(void) +static int handle_subopt_val(const char *opt, const char *arg, const struct val_map *map, int *flag) { - handle_arch_msize_long_finalize(); - - if (fpie > fpic) - fpic = fpie; + const char *name; - switch (arch_mach) { - case MACH_ARM64: - if (arch_cmodel == CMODEL_UNKNOWN) - arch_cmodel = CMODEL_SMALL; - break; - case MACH_RISCV32: - case MACH_RISCV64: - if (arch_cmodel == CMODEL_UNKNOWN) - arch_cmodel = CMODEL_MEDLOW; - if (fpic) - arch_cmodel = CMODEL_PIC; - break; + if (*arg++ != '=') + die("missing argument for option '%s'", opt); + for (;(name = map->name); map++) { + if (strcmp(name, arg) == 0 || strcmp(name, "*") == 0) { + *flag = map->val; + return 1; + } + if (strcmp(name, "?") == 0) + die("invalid argument '%s' in option '%s'", arg, opt); } -} - -static const char *match_option(const char *arg, const char *prefix) -{ - unsigned int n = strlen(prefix); - if (strncmp(arg, prefix, n) == 0) - return arg + n; - return NULL; + return 0; } @@ -589,12 +434,22 @@ end: } +static const char *match_option(const char *arg, const char *prefix) +{ + unsigned int n = strlen(prefix); + if (strncmp(arg, prefix, n) == 0) + return arg + n; + return NULL; +} + #define OPT_INVERSE 1 +#define OPT_VAL 2 struct flag { const char *name; int *flag; int (*fun)(const char *arg, const char *opt, const struct flag *, int options); unsigned long mask; + int val; }; static int handle_switches(const char *ori, const char *opt, const struct flag *flags) @@ -625,6 +480,8 @@ static int handle_switches(const char *ori, const char *opt, const struct flag * // boolean flag if (opt[0] == '\0' && flags->flag) { + if (flags->mask & OPT_VAL) + val = flags->val; if (flags->mask & OPT_INVERSE) val = !val; *flags->flag = val; @@ -668,6 +525,229 @@ static int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag) \ OPT_NUMERIC(ullong, unsigned long long, strtoull) OPT_NUMERIC(uint, unsigned int, strtoul) +enum { + WARNING_OFF, + WARNING_ON, + WARNING_FORCE_OFF +}; + +static char **handle_onoff_switch(char *arg, char **next, const struct flag warnings[], int n) +{ + int flag = WARNING_ON; + char *p = arg + 1; + unsigned i; + + if (!strcmp(p, "sparse-all")) { + for (i = 0; i < n; i++) { + if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Wsparse_error) + *warnings[i].flag = WARNING_ON; + } + return NULL; + } + + // Prefixes "no" and "no-" mean to turn warning off. + if (p[0] == 'n' && p[1] == 'o') { + p += 2; + if (p[0] == '-') + p++; + flag = WARNING_FORCE_OFF; + } + + for (i = 0; i < n; i++) { + if (!strcmp(p,warnings[i].name)) { + *warnings[i].flag = flag; + return next; + } + } + + // Unknown. + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// Option parsing + +static char **handle_switch_D(char *arg, char **next) +{ + const char *name = arg + 1; + const char *value = "1"; + + if (!*name) { + arg = *++next; + if (!arg) + die("argument to `-D' is missing"); + name = arg; + } + + for (;;arg++) { + char c; + c = *arg; + if (!c) + break; + if (c == '=') { + *arg = '\0'; + value = arg + 1; + break; + } + } + add_pre_buffer("#define %s %s\n", name, value); + return next; +} + +static char **handle_switch_E(char *arg, char **next) +{ + if (arg[1] == '\0') + preprocess_only = 1; + return next; +} + +static char **handle_switch_I(char *arg, char **next) +{ + char *path = arg+1; + + switch (arg[1]) { + case '-': + add_pre_buffer("#split_include\n"); + break; + + case '\0': /* Plain "-I" */ + path = *++next; + if (!path) + die("missing argument for -I option"); + /* Fall through */ + default: + add_pre_buffer("#add_include \"%s/\"\n", path); + } + return next; +} + +static void add_cmdline_include(char *filename) +{ + if (cmdline_include_nr >= CMDLINE_INCLUDE) + die("too many include files for %s\n", filename); + cmdline_include[cmdline_include_nr++] = filename; +} + +static char **handle_switch_i(char *arg, char **next) +{ + if (*next && !strcmp(arg, "include")) + add_cmdline_include(*++next); + else if (*next && !strcmp(arg, "imacros")) + add_cmdline_include(*++next); + else if (*next && !strcmp(arg, "isystem")) { + char *path = *++next; + if (!path) + die("missing argument for -isystem option"); + add_pre_buffer("#add_isystem \"%s/\"\n", path); + } else if (*next && !strcmp(arg, "idirafter")) { + char *path = *++next; + if (!path) + die("missing argument for -idirafter option"); + add_pre_buffer("#add_dirafter \"%s/\"\n", path); + } + return next; +} + +static char **handle_switch_M(char *arg, char **next) +{ + if (!strcmp(arg, "MF") || !strcmp(arg,"MQ") || !strcmp(arg,"MT")) { + if (!*next) + die("missing argument for -%s option", arg); + return next + 1; + } + return next; +} + +static char **handle_multiarch_dir(char *arg, char **next) +{ + multiarch_dir = *++next; + if (!multiarch_dir) + die("missing argument for -multiarch-dir option"); + return next; +} + +static int handle_cmodel(const char *opt, const char *arg, const struct flag *flag, int options) +{ + static const struct val_map cmodels[] = { + { "kernel", CMODEL_KERNEL }, + { "large", CMODEL_LARGE }, + { "medany", CMODEL_MEDANY }, + { "medium", CMODEL_MEDIUM }, + { "medlow", CMODEL_MEDLOW }, + { "small", CMODEL_SMALL }, + { "tiny", CMODEL_TINY }, + { }, + }; + return handle_subopt_val(opt, arg, cmodels, flag->flag); +} + +static int handle_float_abi(const char *opt, const char *arg, const struct flag *flag, int options) { + static const struct val_map fp_abis[] = { + { "hard", FP_ABI_HARD }, + { "soft", FP_ABI_SOFT }, + { "softfp", FP_ABI_HYBRID }, + { "?" }, + }; + return handle_subopt_val(opt, arg, fp_abis, flag->flag); +} + +static const struct flag mflags[] = { + { "64", &arch_m64, NULL, OPT_VAL, ARCH_LP64 }, + { "32", &arch_m64, NULL, OPT_VAL, ARCH_LP32 }, + { "31", &arch_m64, NULL, OPT_VAL, ARCH_LP32 }, + { "16", &arch_m64, NULL, OPT_VAL, ARCH_LP32 }, + { "x32",&arch_m64, NULL, OPT_VAL, ARCH_X32 }, + { "size-llp64", &arch_m64, NULL, OPT_VAL, ARCH_LLP64 }, + { "size-long", &arch_msize_long }, + { "big-endian", &arch_big_endian, NULL }, + { "little-endian", &arch_big_endian, NULL, OPT_INVERSE }, + { "cmodel", &arch_cmodel, handle_cmodel }, + { "float-abi", &arch_fp_abi, handle_float_abi }, + { "hard-float", &arch_fp_abi, NULL, OPT_VAL, FP_ABI_HARD }, + { "soft-float", &arch_fp_abi, NULL, OPT_VAL, FP_ABI_SOFT }, + { } +}; + +static char **handle_switch_m(char *arg, char **next) +{ + if (!strcmp(arg, "multiarch-dir")) { + return handle_multiarch_dir(arg, next); + } else { + handle_switches(arg-1, arg+1, mflags); + } + + return next; +} + +static void handle_arch_msize_long_finalize(void) +{ + if (arch_msize_long) { + size_t_ctype = &ulong_ctype; + ssize_t_ctype = &long_ctype; + } +} + +static void handle_arch_finalize(void) +{ + handle_arch_msize_long_finalize(); + + if (fpie > fpic) + fpic = fpie; + + switch (arch_mach) { + case MACH_ARM64: + if (arch_cmodel == CMODEL_UNKNOWN) + arch_cmodel = CMODEL_SMALL; + break; + case MACH_RISCV32: + case MACH_RISCV64: + if (arch_cmodel == CMODEL_UNKNOWN) + arch_cmodel = CMODEL_MEDLOW; + if (fpic) + arch_cmodel = CMODEL_PIC; + break; + } +} static char **handle_switch_o(char *arg, char **next) { @@ -729,46 +809,6 @@ static const struct flag warnings[] = { { "vla", &Wvla }, }; -enum { - WARNING_OFF, - WARNING_ON, - WARNING_FORCE_OFF -}; - - -static char **handle_onoff_switch(char *arg, char **next, const struct flag warnings[], int n) -{ - int flag = WARNING_ON; - char *p = arg + 1; - unsigned i; - - if (!strcmp(p, "sparse-all")) { - for (i = 0; i < n; i++) { - if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Wsparse_error) - *warnings[i].flag = WARNING_ON; - } - return NULL; - } - - // Prefixes "no" and "no-" mean to turn warning off. - if (p[0] == 'n' && p[1] == 'o') { - p += 2; - if (p[0] == '-') - p++; - flag = WARNING_FORCE_OFF; - } - - for (i = 0; i < n; i++) { - if (!strcmp(p,warnings[i].name)) { - *warnings[i].flag = flag; - return next; - } - } - - // Unknown. - return NULL; -} - static char **handle_switch_W(char *arg, char **next) { char ** ret = handle_onoff_switch(arg, next, warnings, ARRAY_SIZE(warnings)); @@ -1247,6 +1287,9 @@ static char **handle_switch(char *arg, char **next) return next; } +//////////////////////////////////////////////////////////////////////////////// +// Predefines + #define PTYPE_SIZEOF (1U << 0) #define PTYPE_T (1U << 1) #define PTYPE_MAX (1U << 2) @@ -1491,6 +1534,18 @@ static void predefined_macros(void) break; case MACH_ARM: predefine("__arm__", 1, "1"); + switch (arch_fp_abi) { + case FP_ABI_HARD: + predefine("__ARM_PCS_VFP", 1, "1"); + break; + case FP_ABI_SOFT: + predefine("__SOFTFP__", 1, "1"); + /* fall-through */ + case FP_ABI_HYBRID: + predefine("__ARM_PCS", 1, "1"); + break; + } + predefine("__VFP_FP__", 1, "1"); break; case MACH_M68K: predefine("__m68k__", 1, "1"); @@ -1570,6 +1625,8 @@ static void predefined_macros(void) predefined_cmodel(); } +//////////////////////////////////////////////////////////////////////////////// + static void create_builtin_stream(void) { // Temporary hack @@ -208,6 +208,7 @@ extern int funsigned_char; extern int arch_m64; extern int arch_big_endian; extern int arch_mach; +extern int arch_fp_abi; enum { CMODEL_UNKNOWN, @@ -70,4 +70,19 @@ enum machine { #define MACH_NATIVE MACH_UNKNOWN #endif + +enum fp_abi { + FP_ABI_HARD, + FP_ABI_SOFT, + FP_ABI_HYBRID, +}; + +#if defined(__ARM_PCS_VFP) +#define FP_ABI_NATIVE FP_ABI_HARD +#elif defined(__ARM_PCS) && !defined(__SOFTFP__) +#define FP_ABI_NATIVE FP_ABI_HYBRID +#else +#define FP_ABI_NATIVE FP_ABI_SOFT +#endif + #endif diff --git a/validation/arch/arm-predef-float-abi-hard.c b/validation/arch/arm-predef-float-abi-hard.c new file mode 100644 index 00000000..b5ad32f2 --- /dev/null +++ b/validation/arch/arm-predef-float-abi-hard.c @@ -0,0 +1,8 @@ +#if !defined(__ARM_PCS_VFP) || defined(__SOFTFP__) || defined(__ARM_PCS) +#error +#endif + +/* + * check-name: arm-predef-float-abi-hard + * check-command: sparse --arch=arm -mfloat-abi=hard $file + */ diff --git a/validation/arch/arm-predef-float-abi-mixed.c b/validation/arch/arm-predef-float-abi-mixed.c new file mode 100644 index 00000000..b401de35 --- /dev/null +++ b/validation/arch/arm-predef-float-abi-mixed.c @@ -0,0 +1,8 @@ +#if defined(__ARM_PCS_VFP) || defined(__SOFTFP__) || !defined(__ARM_PCS) +#error +#endif + +/* + * check-name: arm-predef-float-abi-mixed + * check-command: sparse --arch=arm -mfloat-abi=softfp $file + */ diff --git a/validation/arch/arm-predef-float-abi-soft.c b/validation/arch/arm-predef-float-abi-soft.c new file mode 100644 index 00000000..ee5accd1 --- /dev/null +++ b/validation/arch/arm-predef-float-abi-soft.c @@ -0,0 +1,8 @@ +#if defined(__ARM_PCS_VFP) || !defined(__SOFTFP__) || !defined(__ARM_PCS) +#error +#endif + +/* + * check-name: arm-predef-float-abi-soft + * check-command: sparse --arch=arm -mfloat-abi=soft $file + */ diff --git a/validation/arch/arm-predef-hard-float.c b/validation/arch/arm-predef-hard-float.c new file mode 100644 index 00000000..72c748f0 --- /dev/null +++ b/validation/arch/arm-predef-hard-float.c @@ -0,0 +1,8 @@ +#if !defined(__ARM_PCS_VFP) || defined(__SOFTFP__) || defined(__ARM_PCS) +#error +#endif + +/* + * check-name: arm-predef-hard-float + * check-command: sparse --arch=arm -mhard-float $file + */ diff --git a/validation/arch/arm-predef-soft-float.c b/validation/arch/arm-predef-soft-float.c new file mode 100644 index 00000000..c25a5f1d --- /dev/null +++ b/validation/arch/arm-predef-soft-float.c @@ -0,0 +1,8 @@ +#if defined(__ARM_PCS_VFP) || !defined(__SOFTFP__) || !defined(__ARM_PCS) +#error +#endif + +/* + * check-name: arm-predef-soft-float + * check-command: sparse --arch=arm -msoft-float $file + */ |