aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-05 00:09:04 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-05 00:09:04 +0100
commitfdc1539d3c42e114c90805cde8cfabd132cc7944 (patch)
tree278ed0b3ae9de7c327252529021e39990aad3dd2
parent41a1e45b6e9141a1a914f0ffbd5eb18436516159 (diff)
parentfba1931d2c2779b0b84e4837c51187d9d2fe0226 (diff)
downloadsparse-fdc1539d3c42e114c90805cde8cfabd132cc7944.tar.gz
Merge branch 'option-arch'
* add new option, --arch=ARCH, allowing to specify the target arch.
-rwxr-xr-xcgcc67
-rw-r--r--lib.c72
-rw-r--r--machine.h22
-rw-r--r--sparse.18
-rw-r--r--target.c22
-rw-r--r--validation/arch/arm.c27
-rw-r--r--validation/arch/arm64.c23
-rw-r--r--validation/arch/mips32.c29
-rw-r--r--validation/arch/riscv64.c27
9 files changed, 232 insertions, 65 deletions
diff --git a/cgcc b/cgcc
index 122f6e27..8e8c510e 100755
--- a/cgcc
+++ b/cgcc
@@ -148,30 +148,6 @@ sub quote_arg {
# -----------------------------------------------------------------------------
-sub integer_types {
- my ($char,@dummy) = @_;
-
- my %pow2m1 =
- (8 => '127',
- 16 => '32767',
- 32 => '2147483647',
- 64 => '9223372036854775807',
- 128 => '170141183460469231731687303715884105727',
- );
- my @types = (['SCHAR',''], ['SHRT',''], ['INT',''], ['LONG','L'], ['LONG_LONG','LL'], ['LONG_LONG_LONG','LLL']);
-
- my $result = " -D__CHAR_BIT__=$char";
- while (@types && @_) {
- my $bits = shift @_;
- my ($name,$suffix) = @{ shift @types };
- die "$0: weird number of bits." unless exists $pow2m1{$bits};
- $result .= " -D__${name}_MAX__=" . $pow2m1{$bits} . $suffix;
- }
- return $result;
-}
-
-# -----------------------------------------------------------------------------
-
sub float_types {
my ($has_inf,$has_qnan,$dec_dig,@bitsizes) = @_;
my $result = " -D__FLT_RADIX__=2";
@@ -241,14 +217,6 @@ sub float_types {
# -----------------------------------------------------------------------------
-sub define_size_t {
- my ($text) = @_;
- # We have to undef in order to override check's internal definition.
- return ' -U__SIZE_TYPE__ ' . &quote_arg ("-D__SIZE_TYPE__=$text");
-}
-
-# -----------------------------------------------------------------------------
-
sub add_specs {
my ($spec) = @_;
if ($spec eq 'sunos') {
@@ -294,29 +262,26 @@ sub add_specs {
" -D'__declspec(x)=__attribute__((x))'";
} elsif ($spec eq 'i386') {
return (
+ ' --arch=i386' .
&float_types (1, 1, 21, [24,8], [53,11], [64,15]));
} elsif ($spec eq 'sparc') {
return (
- &integer_types (8, 16, 32, $m64 ? 64 : 32, 64) .
- &float_types (1, 1, 33, [24,8], [53,11], [113,15]) .
- &define_size_t ($m64 ? "long unsigned int" : "unsigned int") .
- ' -D__SIZEOF_POINTER__=' . ($m64 ? '8' : '4'));
+ ' --arch=sparc' .
+ &float_types (1, 1, 33, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'sparc64') {
return (
- &integer_types (8, 16, 32, 64, 64, 128) .
- &float_types (1, 1, 33, [24,8], [53,11], [113,15]) .
- &define_size_t ("long unsigned int") .
- ' -D__SIZEOF_POINTER__=8');
+ ' --arch=sparc64' .
+ &float_types (1, 1, 33, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'x86_64') {
- return &float_types (1, 1, 33, [24,8], [53,11], [113,15]);
+ return (' --arch=x86_64' .
+ &float_types (1, 1, 33, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'ppc') {
return (' -D_BIG_ENDIAN -D_STRING_ARCH_unaligned=1' .
- &integer_types (8, 16, 32, $m64 ? 64 : 32, 64) .
- &float_types (1, 1, 21, [24,8], [53,11], [113,15]) .
- &define_size_t ($m64 ? "long unsigned int" : "unsigned int") .
- ' -D__SIZEOF_POINTER__=' . ($m64 ? '8' : '4'));
+ ' --arch=ppc' .
+ &float_types (1, 1, 21, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'ppc64') {
- return (' -D_STRING_ARCH_unaligned=1 -m64' .
+ return (' -D_STRING_ARCH_unaligned=1 ' .
+ ' --arch=ppc64' .
&float_types (1, 1, 21, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'ppc64+be') {
return &add_specs ('ppc64') . ' -mbig-endian -D_CALL_ELF=1';
@@ -324,17 +289,15 @@ sub add_specs {
return &add_specs ('ppc64') . ' -mlittle-endian -D_CALL_ELF=2';
} elsif ($spec eq 's390x') {
return (' -D_BIG_ENDIAN' .
- &integer_types (8, 16, 32, $m64 ? 64 : 32, 64) .
- &float_types (1, 1, 36, [24,8], [53,11], [113,15]) .
- &define_size_t ("long unsigned int") .
- ' -D__SIZEOF_POINTER__=' . ($m64 ? '8' : '4'));
+ ' --arch=s390x' .
+ &float_types (1, 1, 36, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'arm') {
- return (' -m32' .
+ 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';
} elsif ($spec eq 'aarch64') {
- return (' -m64' .
+ return (' --arch=aarch64' .
&float_types (1, 1, 36, [24,8], [53,11], [113,15]));
} elsif ($spec eq 'host_os_specs') {
my $os = `uname -s`;
diff --git a/lib.c b/lib.c
index 84b5be6a..4ecb43c7 100644
--- a/lib.c
+++ b/lib.c
@@ -459,6 +459,8 @@ static char **handle_switch_m(char *arg, char **next)
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")) {
@@ -1094,6 +1096,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);
@@ -1126,6 +1195,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 }
@@ -1428,6 +1498,7 @@ static void predefined_macros(void)
predefine("__mips64", 1, "64");
/* fall-through */
case MACH_MIPS32:
+ predefine("__mips__", 1, "1");
predefine("__mips", 1, "%d", ptr_ctype.bit_size);
predefine("_MIPS_SZINT", 1, "%d", int_ctype.bit_size);
predefine("_MIPS_SZLONG", 1, "%d", long_ctype.bit_size);
@@ -1454,6 +1525,7 @@ static void predefined_macros(void)
case MACH_S390X:
predefine("__zarch__", 1, "1");
predefine("__s390x__", 1, "1");
+ case MACH_S390:
predefine("__s390__", 1, "1");
break;
case MACH_SPARC64:
diff --git a/machine.h b/machine.h
index b46383ac..e24822a7 100644
--- a/machine.h
+++ b/machine.h
@@ -25,20 +25,14 @@ enum {
enum machine {
- MACH_ARM,
- MACH_ARM64,
- MACH_I386,
- MACH_X86_64,
- MACH_MIPS32,
- MACH_MIPS64,
- MACH_PPC32,
- MACH_PPC64,
- MACH_RISCV32,
- MACH_RISCV64,
- MACH_SPARC32,
- MACH_SPARC64,
+ MACH_ARM, MACH_ARM64,
+ MACH_I386, MACH_X86_64,
+ MACH_MIPS32, MACH_MIPS64,
+ MACH_PPC32, MACH_PPC64,
+ MACH_RISCV32, MACH_RISCV64,
+ MACH_SPARC32, MACH_SPARC64,
+ MACH_S390, MACH_S390X,
MACH_M68K,
- MACH_S390X,
MACH_UNKNOWN
};
@@ -70,6 +64,8 @@ enum machine {
#define MACH_NATIVE MACH_M68K
#elif defined(__s390x__) || defined(__zarch__)
#define MACH_NATIVE MACH_S390X
+#elif defined(__s390__)
+#define MACH_NATIVE MACH_S390
#else
#define MACH_NATIVE MACH_UNKNOWN
#endif
diff --git a/sparse.1 b/sparse.1
index beb48442..be38f688 100644
--- a/sparse.1
+++ b/sparse.1
@@ -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/target.c b/target.c
index c2ab5549..90097818 100644
--- a/target.c
+++ b/target.c
@@ -58,6 +58,27 @@ int enum_alignment = 4;
void init_target(void)
{
switch (arch_mach) {
+ case MACH_I386:
+ case MACH_MIPS32:
+ case MACH_PPC32:
+ case MACH_RISCV32:
+ case MACH_SPARC32:
+ case MACH_S390:
+ if (arch_m64 == ARCH_LP64)
+ arch_mach++;
+ break;
+ case MACH_X86_64:
+ case MACH_MIPS64:
+ case MACH_PPC64:
+ case MACH_RISCV64:
+ case MACH_SPARC64:
+ case MACH_S390X:
+ if (arch_m64 == ARCH_LP32)
+ arch_mach--;
+ break;
+ }
+
+ switch (arch_mach) {
case MACH_X86_64:
if (arch_m64 == ARCH_LP64)
break;
@@ -97,6 +118,7 @@ void init_target(void)
switch (arch_mach) {
case MACH_ARM:
case MACH_MIPS32:
+ case MACH_S390:
case MACH_S390X:
case MACH_SPARC32:
bits_in_longdouble = 64;
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
+ */