diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-10-27 11:35:09 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-10-30 09:52:14 +0100 |
commit | 2c06f143fa63394dbdfa07f3f9d00b24b7c902c5 (patch) | |
tree | 6c19c53230ab117d2bf82f64b64ea7e50962d1dc | |
parent | 0a35fa5b1ce9be51c0a2f557fdfe75fabdf58a23 (diff) | |
download | sparse-2c06f143fa63394dbdfa07f3f9d00b24b7c902c5.tar.gz |
arch: add an option to specify the desired arch: --arch=<arch>
Sparse is universal in the sense that the same executable can
be used for all architectures. For this, most arch-specific
setting can be set with an option and the default values
are taken from the host machine.
This is working nicely for native targets. However, for cross-
compilation, while seeming to work relatively well (thanks to
the kernel build system using -m32/-m64 for all archs, for example)
things can never work 100% correctly. For example, in the case
an X86-64 host machine is used for an ARM target, the kernel
build system will call sparse with -m32, Sparse will 'autodetect'
the target arch as i386 (x86-64 + -m32) and will then predefine
the macro __i386__. Most of the time this is not a problem (at
least for the kernel) unless, of course, if the code contains
something like:
#ifdef __i386__
...
#elif __arm__
...
So, add an option --arch=<arch> to specify the target architecture.
The native arch is still used if no such flag is given.
Reported-by: Ben Dooks <ben.dooks@codethink.co.uk>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | lib.c | 68 | ||||
-rw-r--r-- | sparse.1 | 8 | ||||
-rw-r--r-- | validation/arch/arm.c | 27 | ||||
-rw-r--r-- | validation/arch/arm64.c | 23 | ||||
-rw-r--r-- | validation/arch/mips32.c | 29 | ||||
-rw-r--r-- | validation/arch/riscv64.c | 27 |
6 files changed, 182 insertions, 0 deletions
@@ -1046,6 +1046,73 @@ static char **handle_switch_x(char *arg, char **next) } +static char **handle_arch(char *arg, char **next) +{ + static const struct arch { + const char *name; + char mach; + char bits; + bool big_endian:1; + } archs[] = { + { "aarch64", MACH_ARM64, 64, 0 }, + { "arm64", MACH_ARM64, 64, 0 }, + { "arm", MACH_ARM, 32, 0 }, + { "i386", MACH_I386, 32, 0 }, + { "m68k", MACH_M68K, 32, 0 }, + { "mips", MACH_MIPS32, 0, 1 }, + { "powerpc", MACH_PPC32, 0, 1 }, + { "ppc", MACH_PPC32, 0, 1 }, + { "riscv", MACH_RISCV32, 0, 0 }, + { "s390x", MACH_S390X, 64, 1 }, + { "s390", MACH_S390, 32, 1 }, + { "sparc", MACH_SPARC32, 0, 1 }, + { "x86_64", MACH_X86_64, 64, 0 }, + { "x86-64", MACH_X86_64, 64, 0 }, + { NULL }, + }; + const struct arch *p; + + if (*arg++ != '=') + die("missing argument for --arch option"); + + for (p = &archs[0]; p->name; p++) { + size_t len = strlen(p->name); + if (strncmp(p->name, arg, len) == 0) { + const char *suf = arg + len; + int bits = p->bits; + + arch_mach = p->mach; + if (bits == 0) { + if (!strcmp(suf, "")) { + bits = 32; + } else if (!strcmp(suf, "32")) { + bits = 32; + } else if (!strcmp(suf, "64")) { + bits = 64; + arch_mach += 1; + } else { + die("invalid architecture: %s", arg); + } + } else { + if (strcmp(suf, "")) + die("invalid architecture: %s", arg); + } + + // adjust the arch size (but keep x32 & llp64) + if (bits == 32) + arch_m64 = ARCH_LP32; + else if (bits == 64 && arch_m64 == ARCH_LP32) + arch_m64 = ARCH_LP64; + if (p->big_endian) + arch_big_endian = 1; + + break; + } + } + + return next; +} + static char **handle_version(char *arg, char **next) { printf("%s\n", SPARSE_VERSION); @@ -1078,6 +1145,7 @@ struct switches { static char **handle_long_options(char *arg, char **next) { static struct switches cmd[] = { + { "arch", handle_arch, 1 }, { "param", handle_param, 1 }, { "version", handle_version }, { NULL, NULL } @@ -423,6 +423,14 @@ Sparse does not issue these warnings by default. . .SH MISC OPTIONS .TP +.B \-\-arch=\fIARCH\fR +Specify the target architecture. +For architectures having both a 32-bit and a 64-bit variant (mips, powerpc, +riscv & sparc) the architecture name can be suffixed with \fI32\fR or \fI64\fR. + +The default architecture & size is the one of the machine used to build Sparse. +. +.TP .B \-gcc-base-dir \fIdir\fR Look for compiler-provided system headers in \fIdir\fR/include/ and \fIdir\fR/include-fixed/. . diff --git a/validation/arch/arm.c b/validation/arch/arm.c new file mode 100644 index 00000000..4eb804de --- /dev/null +++ b/validation/arch/arm.c @@ -0,0 +1,27 @@ +__arm__ +__aarch64__ +__i386__ +__x86_64__ +__LP64__ +__BYTE_ORDER__ +__SIZEOF_INT__ +__SIZEOF_LONG__ +__SIZE_TYPE__ + +/* + * check-name: arch/arm + * check-command: sparse --arch=arm -E $file + * + * check-output-start + +1 +__aarch64__ +__i386__ +__x86_64__ +__LP64__ +1234 +4 +4 +unsigned int + * check-output-end + */ diff --git a/validation/arch/arm64.c b/validation/arch/arm64.c new file mode 100644 index 00000000..12f839cc --- /dev/null +++ b/validation/arch/arm64.c @@ -0,0 +1,23 @@ +__aarch64__ +__x86_64__ +__LP64__ +__BYTE_ORDER__ +__SIZEOF_INT__ +__SIZEOF_LONG__ +__SIZE_TYPE__ + +/* + * check-name: arch/arm64 + * check-command: sparse --arch=arm64 -E $file + * + * check-output-start + +1 +__x86_64__ +1 +1234 +4 +8 +unsigned long + * check-output-end + */ diff --git a/validation/arch/mips32.c b/validation/arch/mips32.c new file mode 100644 index 00000000..339218b6 --- /dev/null +++ b/validation/arch/mips32.c @@ -0,0 +1,29 @@ +__mips__ +__mips +__mips64__ +__i386__ +__x86_64__ +__LP64__ +__BYTE_ORDER__ +__SIZEOF_INT__ +__SIZEOF_LONG__ +__SIZE_TYPE__ + +/* + * check-name: arch/mips32 + * check-command: sparse --arch=mips32 -E $file + * + * check-output-start + +1 +32 +__mips64__ +__i386__ +__x86_64__ +__LP64__ +4321 +4 +4 +unsigned int + * check-output-end + */ diff --git a/validation/arch/riscv64.c b/validation/arch/riscv64.c new file mode 100644 index 00000000..9da7a7de --- /dev/null +++ b/validation/arch/riscv64.c @@ -0,0 +1,27 @@ +__riscv +__riscv_xlen +__i386__ +__x86_64__ +__LP64__ +__BYTE_ORDER__ +__SIZEOF_INT__ +__SIZEOF_LONG__ +__SIZE_TYPE__ + +/* + * check-name: arch/riscv64 + * check-command: sparse --arch=riscv64 -E $file + * + * check-output-start + +1 +64 +__i386__ +__x86_64__ +1 +1234 +4 +8 +unsigned long + * check-output-end + */ |