aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-27 00:25:14 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-27 00:25:14 +0100
commitdbcc589f4577ebb0d6d05e36e2ac1246b56555ed (patch)
treeb6c2d381e8b144e67aa8002ab9a1c3fe5a0c98dd
parent50438f45934d885aa00b126dd9359895e05fd056 (diff)
parentfd59a5e8d5aca68c417e9d4e19b7df5d99e9c570 (diff)
downloadsparse-dbcc589f4577ebb0d6d05e36e2ac1246b56555ed.tar.gz
Merge branch 'arm-hf' into master
-rwxr-xr-xcgcc2
-rw-r--r--lib.c485
-rw-r--r--lib.h1
-rw-r--r--machine.h15
-rw-r--r--validation/arch/arm-predef-float-abi-hard.c8
-rw-r--r--validation/arch/arm-predef-float-abi-mixed.c8
-rw-r--r--validation/arch/arm-predef-float-abi-soft.c8
-rw-r--r--validation/arch/arm-predef-hard-float.c8
-rw-r--r--validation/arch/arm-predef-soft-float.c8
9 files changed, 328 insertions, 215 deletions
diff --git a/cgcc b/cgcc
index 239f713d..40dea2a0 100755
--- a/cgcc
+++ b/cgcc
@@ -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]));
diff --git a/lib.c b/lib.c
index 47dd7029..569e45ac 100644
--- a/lib.c
+++ b/lib.c
@@ -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
diff --git a/lib.h b/lib.h
index 3d596a52..79040097 100644
--- a/lib.h
+++ b/lib.h
@@ -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,
diff --git a/machine.h b/machine.h
index 22b05d91..b89f0232 100644
--- a/machine.h
+++ b/machine.h
@@ -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
+ */