aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-01-21 00:02:16 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-01-21 00:02:16 +0100
commiteed8930cb4ec54047c584afd30f2ac53ff2c3317 (patch)
tree75c451fbc8dbbe1a8cfae00f81e866e2f9a2a382
parent22978b6b1e5e2890bb4cb705a0f6674c2b2b6157 (diff)
parent31c6724f4f32c3367c929b96aa94bc4eee5f6af8 (diff)
downloadsparse-eed8930cb4ec54047c584afd30f2ac53ff2c3317.tar.gz
Merge branch 'arch-spec'
* move arch specificities in their own files * better support of arch specificities
-rw-r--r--Makefile10
-rwxr-xr-xcgcc13
-rw-r--r--lib.c247
-rw-r--r--lib.h3
-rw-r--r--machine.h2
-rw-r--r--symbol.h1
-rw-r--r--target-arm.c36
-rw-r--r--target-arm64.c39
-rw-r--r--target-default.c11
-rw-r--r--target-m68k.c23
-rw-r--r--target-mips.c53
-rw-r--r--target-ppc.c58
-rw-r--r--target-riscv.c53
-rw-r--r--target-s390.c48
-rw-r--r--target-sparc.c66
-rw-r--r--target-x86.c73
-rw-r--r--target.c262
-rw-r--r--target.h48
18 files changed, 673 insertions, 373 deletions
diff --git a/Makefile b/Makefile
index deab4897..e2d3a7de 100644
--- a/Makefile
+++ b/Makefile
@@ -65,6 +65,16 @@ LIB_OBJS += stats.o
LIB_OBJS += storage.o
LIB_OBJS += symbol.o
LIB_OBJS += target.o
+LIB_OBJS += target-arm.o
+LIB_OBJS += target-arm64.o
+LIB_OBJS += target-default.o
+LIB_OBJS += target-m68k.o
+LIB_OBJS += target-mips.o
+LIB_OBJS += target-ppc.o
+LIB_OBJS += target-riscv.o
+LIB_OBJS += target-s390.o
+LIB_OBJS += target-sparc.o
+LIB_OBJS += target-x86.o
LIB_OBJS += tokenize.o
LIB_OBJS += unssa.o
LIB_OBJS += utils.o
diff --git a/cgcc b/cgcc
index f5a8b352..9c6ad883 100755
--- a/cgcc
+++ b/cgcc
@@ -286,14 +286,17 @@ sub add_specs {
return (
' --arch=ppc64' .
&float_types (1, 1, 21, [24,8], [53,11], [113,15]));
- } elsif ($spec eq 'ppc64+be') {
+ } elsif ($spec eq 'ppc64be') {
return &add_specs ('ppc64') . ' -mbig-endian -D_CALL_ELF=1';
- } elsif ($spec eq 'ppc64+le') {
+ } elsif ($spec eq 'ppc64le') {
return &add_specs ('ppc64') . ' -mlittle-endian -D_CALL_ELF=2';
} elsif ($spec eq 's390x') {
return (' -D_BIG_ENDIAN' .
' --arch=s390x' .
&float_types (1, 1, 36, [24,8], [53,11], [113,15]));
+ } elsif ($spec eq 'riscv32') {
+ return (' --arch=riscv32' .
+ &float_types (1, 1, 33, [24,8], [53,11], [53,11]));
} elsif ($spec eq 'riscv64') {
return (' --arch=riscv64' .
&float_types (1, 1, 33, [24,8], [53,11], [113,15]));
@@ -325,7 +328,7 @@ sub add_specs {
} elsif ($gccmachine =~ '^i[23456]86-') {
return &add_specs ('i386');
} elsif ($gccmachine =~ '^(powerpc|ppc)64le-') {
- return &add_specs ('ppc64+le');
+ return &add_specs ('ppc64le');
} elsif ($gccmachine =~ '^s390x-') {
return &add_specs ('s390x');
} elsif ($gccmachine eq 'x86_64-linux-gnux32') {
@@ -350,9 +353,9 @@ sub add_specs {
} elsif ($arch =~ /^(ppc)$/i) {
return &add_specs ('ppc');
} elsif ($arch =~ /^(ppc64)$/i) {
- return &add_specs ('ppc64+be');
+ return &add_specs ('ppc64be');
} elsif ($arch =~ /^(ppc64le)$/i) {
- return &add_specs ('ppc64+le');
+ return &add_specs ('ppc64le');
} elsif ($arch =~ /^(s390x)$/i) {
return &add_specs ('s390x');
} elsif ($arch =~ /^(sparc64)$/i) {
diff --git a/lib.c b/lib.c
index 711e8fbe..40e192a7 100644
--- a/lib.c
+++ b/lib.c
@@ -314,17 +314,16 @@ unsigned long fpasses = ~0UL;
int fpic = 0;
int fpie = 0;
int fshort_wchar = 0;
-int funsigned_char = -1;
+int funsigned_char = 0;
int preprocess_only;
enum standard standard = STANDARD_GNU89;
-static int arch_msize_long = 0;
+int arch_msize_long = 0;
int arch_m64 = ARCH_M64_DEFAULT;
int arch_big_endian = ARCH_BIG_ENDIAN;
int arch_fp_abi = FP_ABI_NATIVE;
-int arch_mach = MACH_NATIVE;
int arch_os = OS_NATIVE;
int arch_cmodel = CMODEL_UNKNOWN;
@@ -714,36 +713,6 @@ static char **handle_switch_m(char *arg, char **next)
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)
{
if (!strcmp (arg, "o")) { // "-o foo"
@@ -1135,65 +1104,14 @@ 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;
+ enum machine mach;
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;
- arch_big_endian = p->big_endian;
- break;
- }
- }
+ mach = target_parse(arg);
+ if (mach != MACH_UNKNOWN)
+ target_config(mach);
return next;
}
@@ -1356,55 +1274,6 @@ static void predefined_ctype(const char *name, struct symbol *type, int flags)
predefined_width(name, bits);
}
-static void predefined_cmodel(void)
-{
- const char *pre, *suf;
- const char *def = NULL;
- switch (arch_mach) {
- case MACH_ARM64:
- pre = "__AARCH64_CMODEL_";
- suf = "__";
- switch (arch_cmodel) {
- case CMODEL_LARGE:
- def = "LARGE";
- break;
- case CMODEL_SMALL:
- def = "SMALL";
- break;
- case CMODEL_TINY:
- def = "TINY";
- break;
- default:
- break;
- }
- break;
- case MACH_RISCV32:
- case MACH_RISCV64:
- pre = "__riscv_cmodel_";
- suf = "";
- switch (arch_cmodel) {
- case CMODEL_MEDLOW:
- def = "medlow";
- break;
- case CMODEL_MEDANY:
- def = "medany";
- break;
- case CMODEL_PIC:
- def = "pic";
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- if (!def)
- return;
- add_pre_buffer("#weak_define %s%s%s 1\n", pre, def, suf);
-}
-
static void predefined_macros(void)
{
predefine("__CHECKER__", 0, "1");
@@ -1480,16 +1349,8 @@ static void predefined_macros(void)
predefined_sizeof("DOUBLE", "", bits_in_double);
predefined_sizeof("LONG_DOUBLE", "", bits_in_longdouble);
- switch (arch_mach) {
- case MACH_ARM64:
- case MACH_MIPS64:
- case MACH_PPC64:
- case MACH_RISCV64:
- case MACH_S390X:
- case MACH_SPARC64:
- case MACH_X86_64:
+ if (arch_target->has_int128)
predefined_sizeof("INT128", "", 128);
- }
predefine("__ORDER_LITTLE_ENDIAN__", 1, "1234");
predefine("__ORDER_BIG_ENDIAN__", 1, "4321");
@@ -1527,91 +1388,6 @@ static void predefined_macros(void)
break;
}
- switch (arch_mach) {
- case MACH_ARM64:
- predefine("__aarch64__", 1, "1");
- 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");
- break;
- case MACH_MIPS64:
- 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);
- predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size);
- break;
- case MACH_PPC64:
- predefine("__powerpc64__", 1, "1");
- predefine("__ppc64__", 1, "1");
- predefine("__PPC64__", 1, "1");
- predefine("_ARCH_PPC64", 1, "1");
- /* fall-through */
- case MACH_PPC32:
- predefine("__powerpc__", 1, "1");
- predefine("__powerpc", 1, "1");
- predefine("__ppc__", 1, "1");
- predefine("__PPC__", 1, "1");
- predefine("__PPC", 1, "1");
- predefine("_ARCH_PPC", 1, "1");
- if (arch_big_endian)
- predefine("_BIG_ENDIAN", 1, "1");
- break;
- case MACH_RISCV64:
- case MACH_RISCV32:
- predefine("__riscv", 1, "1");
- predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size);
- break;
- case MACH_S390X:
- predefine("__zarch__", 1, "1");
- predefine("__s390x__", 1, "1");
- case MACH_S390:
- predefine("__s390__", 1, "1");
- break;
- case MACH_SPARC64:
- predefine("__sparc_v9__", 1, "1");
- predefine("__sparcv9__", 1, "1");
- predefine("__sparcv9", 1, "1");
- predefine("__sparc64__", 1, "1");
- predefine("__arch64__", 1, "1");
- /* fall-through */
- case MACH_SPARC32:
- predefine("__sparc__", 1, "1");
- predefine("__sparc", 1, "1");
- break;
- case MACH_X86_64:
- if (arch_m64 != ARCH_LP32) {
- predefine("__x86_64__", 1, "1");
- predefine("__x86_64", 1, "1");
- predefine("__amd64__", 1, "1");
- predefine("__amd64", 1, "1");
- break;
- }
- /* fall-through */
- case MACH_I386:
- predefine("__i386__", 1, "1");
- predefine("__i386", 1, "1");
- break;
- }
-
if (fpic) {
predefine("__pic__", 0, "%d", fpic);
predefine("__PIC__", 0, "%d", fpic);
@@ -1621,7 +1397,8 @@ static void predefined_macros(void)
predefine("__PIE__", 0, "%d", fpie);
}
- predefined_cmodel();
+ if (arch_target->predefine)
+ arch_target->predefine(arch_target);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1748,6 +1525,9 @@ struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list
// Initialize symbol stream first, so that we can add defines etc
init_symbols();
+ // initialize the default target to the native 'machine'
+ target_config(MACH_NATIVE);
+
args = argv;
for (;;) {
char *arg = *++args;
@@ -1777,8 +1557,7 @@ struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list
list = NULL;
if (filelist) {
// Initialize type system
- init_target();
- handle_arch_finalize();
+ target_init();
init_ctype();
predefined_macros();
diff --git a/lib.h b/lib.h
index 3e565c6f..23623525 100644
--- a/lib.h
+++ b/lib.h
@@ -205,10 +205,10 @@ extern int fpie;
extern int fshort_wchar;
extern int funsigned_char;
+extern int arch_msize_long;
extern int arch_m64;
extern int arch_big_endian;
extern int arch_fp_abi;
-extern int arch_mach;
extern int arch_os;
enum {
@@ -221,6 +221,7 @@ enum {
CMODEL_PIC,
CMODEL_SMALL,
CMODEL_TINY,
+ CMODEL_LAST,
};
extern int arch_cmodel;
diff --git a/machine.h b/machine.h
index 6eba448c..1fe933ce 100644
--- a/machine.h
+++ b/machine.h
@@ -8,7 +8,7 @@
#endif
-enum {
+enum bitness {
ARCH_LP32,
ARCH_X32,
ARCH_LP64,
diff --git a/symbol.h b/symbol.h
index e60d9136..9ef5a886 100644
--- a/symbol.h
+++ b/symbol.h
@@ -310,7 +310,6 @@ extern void init_symbols(void);
extern void init_builtins(int stream);
extern void declare_builtins(void);
extern void init_ctype(void);
-extern void init_target(void);
extern struct symbol *alloc_symbol(struct position, int type);
extern void show_type(struct symbol *);
extern const char *modifier_string(unsigned long mod);
diff --git a/target-arm.c b/target-arm.c
new file mode 100644
index 00000000..0d7c6134
--- /dev/null
+++ b/target-arm.c
@@ -0,0 +1,36 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_arm(const struct target *self)
+{
+ predefine("__arm__", 1, "1");
+ predefine("__VFP_FP__", 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;
+ }
+}
+
+const struct target target_arm = {
+ .mach = MACH_ARM,
+ .bitness = ARCH_LP32,
+ .big_endian = 0,
+ .unsigned_char = 1,
+
+ .wchar = &uint_ctype,
+
+ .bits_in_longdouble = 64,
+ .max_fp_alignment = 8,
+
+ .predefine = predefine_arm,
+};
diff --git a/target-arm64.c b/target-arm64.c
new file mode 100644
index 00000000..d491b65e
--- /dev/null
+++ b/target-arm64.c
@@ -0,0 +1,39 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_arm64(const struct target *self)
+{
+ if (arch_cmodel == CMODEL_UNKNOWN)
+ arch_cmodel = CMODEL_SMALL;
+}
+
+static void predefine_arm64(const struct target *self)
+{
+ static const char *cmodels[CMODEL_LAST] = {
+ [CMODEL_LARGE] = "LARGE",
+ [CMODEL_SMALL] = "SMALL",
+ [CMODEL_TINY] = "TINY",
+ };
+ const char *cmodel = cmodels[arch_cmodel];
+
+ predefine("__aarch64__", 1, "1");
+
+ if (cmodel)
+ add_pre_buffer("#define __AARCH64_CMODEL_%s__ 1\n", cmodel);
+}
+
+const struct target target_arm64 = {
+ .mach = MACH_ARM64,
+ .bitness = ARCH_LP64,
+
+ .big_endian = 0,
+ .unsigned_char = 1,
+ .has_int128 = 1,
+
+ .wchar = &uint_ctype,
+
+ .init = init_arm64,
+ .predefine = predefine_arm64,
+};
diff --git a/target-default.c b/target-default.c
new file mode 100644
index 00000000..3a9e1726
--- /dev/null
+++ b/target-default.c
@@ -0,0 +1,11 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+const struct target target_default = {
+ .mach = MACH_UNKNOWN,
+ .bitness = ARCH_LP64,
+ .big_endian = 0,
+ .unsigned_char = 0,
+};
diff --git a/target-m68k.c b/target-m68k.c
new file mode 100644
index 00000000..ed4a9273
--- /dev/null
+++ b/target-m68k.c
@@ -0,0 +1,23 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_m68k(const struct target *self)
+{
+ predefine("__m68k__", 1, "1");
+}
+
+const struct target target_m68k = {
+ .mach = MACH_M68K,
+ .bitness = ARCH_LP32,
+ .big_endian = 1,
+ .unsigned_char = 0,
+
+ .wchar = &long_ctype,
+
+ .bits_in_longdouble = 96,
+ .max_fp_alignment = 4,
+
+ .predefine = predefine_m68k,
+};
diff --git a/target-mips.c b/target-mips.c
new file mode 100644
index 00000000..3d73236f
--- /dev/null
+++ b/target-mips.c
@@ -0,0 +1,53 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_mips(const struct target *self)
+{
+ 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);
+ predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size);
+}
+
+
+static void predefine_mips32(const struct target *self)
+{
+ predefine_mips(self);
+}
+
+const struct target target_mips32 = {
+ .mach = MACH_MIPS32,
+ .bitness = ARCH_LP32,
+ .big_endian = 1,
+ .unsigned_char = 0,
+
+ .bits_in_longdouble = 64,
+ .max_fp_alignment = 8,
+
+ .target_64bit = &target_mips64,
+
+ .predefine = predefine_mips32,
+};
+
+
+static void predefine_mips64(const struct target *self)
+{
+ predefine("__mips64", 1, "64");
+
+ predefine_mips(self);
+}
+
+const struct target target_mips64 = {
+ .mach = MACH_MIPS64,
+ .bitness = ARCH_LP64,
+ .big_endian = 1,
+ .unsigned_char = 0,
+ .has_int128 = 1,
+
+ .target_32bit = &target_mips32,
+
+ .predefine = predefine_mips64,
+};
diff --git a/target-ppc.c b/target-ppc.c
new file mode 100644
index 00000000..b138635b
--- /dev/null
+++ b/target-ppc.c
@@ -0,0 +1,58 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_ppc(const struct target *self)
+{
+ predefine("__powerpc__", 1, "1");
+ predefine("__powerpc", 1, "1");
+ predefine("__ppc__", 1, "1");
+ predefine("__PPC__", 1, "1");
+ predefine("__PPC", 1, "1");
+ predefine("_ARCH_PPC", 1, "1");
+ if (arch_big_endian)
+ predefine("_BIG_ENDIAN", 1, "1");
+}
+
+
+static void predefine_ppc32(const struct target *self)
+{
+ predefine_ppc(self);
+}
+
+const struct target target_ppc32 = {
+ .mach = MACH_PPC32,
+ .bitness = ARCH_LP32,
+ .big_endian = 1,
+ .unsigned_char = 1,
+
+ .wchar = &long_ctype,
+
+ .target_64bit = &target_ppc64,
+
+ .predefine = predefine_ppc32,
+};
+
+
+static void predefine_ppc64(const struct target *self)
+{
+ predefine("__powerpc64__", 1, "1");
+ predefine("__ppc64__", 1, "1");
+ predefine("__PPC64__", 1, "1");
+ predefine("_ARCH_PPC64", 1, "1");
+
+ predefine_ppc(self);
+}
+
+const struct target target_ppc64 = {
+ .mach = MACH_PPC64,
+ .bitness = ARCH_LP64,
+ .big_endian = 1,
+ .unsigned_char = 1,
+ .has_int128 = 1,
+
+ .target_32bit = &target_ppc32,
+
+ .predefine = predefine_ppc64,
+};
diff --git a/target-riscv.c b/target-riscv.c
new file mode 100644
index 00000000..08d036ca
--- /dev/null
+++ b/target-riscv.c
@@ -0,0 +1,53 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_riscv(const struct target *self)
+{
+ if (arch_cmodel == CMODEL_UNKNOWN)
+ arch_cmodel = CMODEL_MEDLOW;
+ if (fpic)
+ arch_cmodel = CMODEL_PIC;
+}
+
+static void predefine_riscv(const struct target *self)
+{
+ static const char *cmodels[CMODEL_LAST] = {
+ [CMODEL_MEDANY] = "medany",
+ [CMODEL_MEDLOW] = "medlow",
+ [CMODEL_PIC] = "pic",
+ };
+ const char *cmodel = cmodels[arch_cmodel];
+
+ predefine("__riscv", 1, "1");
+ predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size);
+
+ if (cmodel)
+ add_pre_buffer("#define __riscv_cmodel_%s 1\n", cmodel);
+}
+
+const struct target target_riscv32 = {
+ .mach = MACH_RISCV32,
+ .bitness = ARCH_LP32,
+ .big_endian = 0,
+ .unsigned_char = 1,
+
+ .target_64bit = &target_riscv64,
+
+ .init = init_riscv,
+ .predefine = predefine_riscv,
+};
+
+const struct target target_riscv64 = {
+ .mach = MACH_RISCV64,
+ .bitness = ARCH_LP64,
+ .big_endian = 0,
+ .unsigned_char = 1,
+ .has_int128 = 1,
+
+ .target_32bit = &target_riscv32,
+
+ .init = init_riscv,
+ .predefine = predefine_riscv,
+};
diff --git a/target-s390.c b/target-s390.c
new file mode 100644
index 00000000..8fe7d936
--- /dev/null
+++ b/target-s390.c
@@ -0,0 +1,48 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_s390(const struct target *self)
+{
+ predefine("__s390__", 1, "1");
+}
+
+const struct target target_s390 = {
+ .mach = MACH_S390,
+ .bitness = ARCH_LP32,
+ .big_endian = 1,
+ .unsigned_char = 1,
+ .size_t_long = 1,
+
+ .bits_in_longdouble = 64,
+ .max_fp_alignment = 8,
+
+ .target_64bit = &target_s390x,
+
+ .predefine = predefine_s390,
+};
+
+
+static void predefine_s390x(const struct target *self)
+{
+ predefine("__zarch__", 1, "1");
+ predefine("__s390x__", 1, "1");
+
+ predefine_s390(self);
+}
+
+const struct target target_s390x = {
+ .mach = MACH_S390X,
+ .bitness = ARCH_LP64,
+ .big_endian = 1,
+ .unsigned_char = 1,
+ .has_int128 = 1,
+
+ .bits_in_longdouble = 64,
+ .max_fp_alignment = 8,
+
+ .target_32bit = &target_s390,
+
+ .predefine = predefine_s390x,
+};
diff --git a/target-sparc.c b/target-sparc.c
new file mode 100644
index 00000000..70c440c2
--- /dev/null
+++ b/target-sparc.c
@@ -0,0 +1,66 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void predefine_sparc(const struct target *self)
+{
+ predefine("__sparc__", 1, "1");
+ predefine("__sparc", 1, "1");
+}
+
+
+static void init_sparc32(const struct target *target)
+{
+ if (arch_os == OS_SUNOS) {
+ wint_ctype = &long_ctype;
+ wchar_ctype = &long_ctype;
+
+ bits_in_longdouble = 128;
+ max_fp_alignment = 16;
+ }
+}
+
+static void predefine_sparc32(const struct target *self)
+{
+ predefine_sparc(self);
+}
+
+const struct target target_sparc32 = {
+ .mach = MACH_SPARC32,
+ .bitness = ARCH_LP32,
+ .big_endian = 1,
+ .unsigned_char = 0,
+
+ .bits_in_longdouble = 64,
+ .max_fp_alignment = 8,
+
+ .init = init_sparc32,
+ .target_64bit = &target_sparc64,
+
+ .predefine = predefine_sparc32,
+};
+
+
+static void predefine_sparc64(const struct target *self)
+{
+ predefine("__sparc_v9__", 1, "1");
+ predefine("__sparcv9__", 1, "1");
+ predefine("__sparcv9", 1, "1");
+ predefine("__sparc64__", 1, "1");
+ predefine("__arch64__", 1, "1");
+
+ predefine_sparc(self);
+}
+
+const struct target target_sparc64 = {
+ .mach = MACH_SPARC64,
+ .bitness = ARCH_LP64,
+ .big_endian = 1,
+ .unsigned_char = 0,
+ .has_int128 = 1,
+
+ .target_32bit = &target_sparc32,
+
+ .predefine = predefine_sparc64,
+};
diff --git a/target-x86.c b/target-x86.c
new file mode 100644
index 00000000..01d213ef
--- /dev/null
+++ b/target-x86.c
@@ -0,0 +1,73 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_x86(const struct target *target)
+{
+ switch (arch_os) {
+ case OS_CYGWIN:
+ wchar_ctype = &ushort_ctype;
+ break;
+ case OS_DARWIN:
+ int64_ctype = &llong_ctype;
+ uint64_ctype = &ullong_ctype;
+ wint_ctype = &int_ctype;
+ break;
+ case OS_FREEBSD:
+ wint_ctype = &int_ctype;
+ break;
+ case OS_OPENBSD:
+ wchar_ctype = &int_ctype;
+ wint_ctype = &int_ctype;
+ break;
+ }
+}
+
+
+static void predefine_i386(const struct target *self)
+{
+ predefine("__i386__", 1, "1");
+ predefine("__i386", 1, "1");
+}
+
+const struct target target_i386 = {
+ .mach = MACH_I386,
+ .bitness = ARCH_LP32,
+ .big_endian = 0,
+ .unsigned_char = 0,
+
+ .wchar = &long_ctype,
+ .bits_in_longdouble = 96,
+ .max_fp_alignment = 4,
+
+ .init = init_x86,
+ .target_64bit = &target_x86_64,
+
+ .predefine = predefine_i386,
+};
+
+
+static void predefine_x86_64(const struct target *self)
+{
+ predefine("__x86_64__", 1, "1");
+ predefine("__x86_64", 1, "1");
+ predefine("__amd64__", 1, "1");
+ predefine("__amd64", 1, "1");
+}
+
+const struct target target_x86_64 = {
+ .mach = MACH_X86_64,
+ .bitness = ARCH_LP64,
+ .big_endian = 0,
+ .unsigned_char = 0,
+ .has_int128 = 1,
+
+ .bits_in_longdouble = 128,
+ .max_fp_alignment = 16,
+
+ .init = init_x86,
+ .target_32bit = &target_i386,
+
+ .predefine = predefine_x86_64,
+};
diff --git a/target.c b/target.c
index 76cbb954..abfa9756 100644
--- a/target.c
+++ b/target.c
@@ -1,13 +1,14 @@
#include <stdio.h>
+#include <string.h>
#include "symbol.h"
#include "target.h"
#include "machine.h"
-struct symbol *size_t_ctype = &uint_ctype;
-struct symbol *ssize_t_ctype = &int_ctype;
-struct symbol *intmax_ctype = &llong_ctype;
-struct symbol *uintmax_ctype = &ullong_ctype;
+struct symbol *size_t_ctype = &ulong_ctype;
+struct symbol *ssize_t_ctype = &long_ctype;
+struct symbol *intmax_ctype = &long_ctype;
+struct symbol *uintmax_ctype = &ulong_ctype;
struct symbol *int64_ctype = &long_ctype;
struct symbol *uint64_ctype = &ulong_ctype;
struct symbol *int32_ctype = &int_ctype;
@@ -27,11 +28,11 @@ int bits_in_bool = 1;
int bits_in_char = 8;
int bits_in_short = 16;
int bits_in_int = 32;
-int bits_in_long = 32;
+int bits_in_long = 64;
int bits_in_longlong = 64;
int bits_in_longlonglong = 128;
-int max_int_alignment = 4;
+int max_int_alignment = 8;
/*
* Floating point data types
@@ -45,8 +46,8 @@ int max_fp_alignment = 16;
/*
* Pointer data type
*/
-int bits_in_pointer = 32;
-int pointer_alignment = 4;
+int bits_in_pointer = 64;
+int pointer_alignment = 8;
/*
* Enum data types
@@ -55,149 +56,148 @@ int bits_in_enum = 32;
int enum_alignment = 4;
-void init_target(void)
+static const struct target *targets[] = {
+ [MACH_ARM] = &target_arm,
+ [MACH_ARM64] = &target_arm64,
+ [MACH_I386] = &target_i386,
+ [MACH_X86_64] = &target_x86_64,
+ [MACH_MIPS32] = &target_mips32,
+ [MACH_MIPS64] = &target_mips64,
+ [MACH_PPC32] = &target_ppc32,
+ [MACH_PPC64] = &target_ppc64,
+ [MACH_RISCV32] = &target_riscv32,
+ [MACH_RISCV64] = &target_riscv64,
+ [MACH_S390] = &target_s390,
+ [MACH_S390X] = &target_s390x,
+ [MACH_SPARC32] = &target_sparc32,
+ [MACH_SPARC64] = &target_sparc64,
+ [MACH_M68K] = &target_m68k,
+ [MACH_UNKNOWN] = &target_default,
+};
+const struct target *arch_target = &target_default;
+
+enum machine target_parse(const char *name)
{
- 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;
- }
+ static const struct arch {
+ const char *name;
+ enum machine mach;
+ char bits;
+ } archs[] = {
+ { "aarch64", MACH_ARM64, 64, },
+ { "arm64", MACH_ARM64, 64, },
+ { "arm", MACH_ARM, 32, },
+ { "i386", MACH_I386, 32, },
+ { "m68k", MACH_M68K, 32, },
+ { "mips", MACH_MIPS32, 0, },
+ { "powerpc", MACH_PPC32, 0, },
+ { "ppc", MACH_PPC32, 0, },
+ { "riscv", MACH_RISCV32, 0, },
+ { "s390x", MACH_S390X, 64, },
+ { "s390", MACH_S390, 32, },
+ { "sparc", MACH_SPARC32, 0, },
+ { "x86_64", MACH_X86_64, 64, },
+ { "x86-64", MACH_X86_64, 64, },
+ { NULL },
+ };
+ const struct arch *p;
- switch (arch_mach) {
- case MACH_I386:
- wchar_ctype = &long_ctype;
- /* fall through */
- case MACH_X86_64:
- switch (arch_os) {
- case OS_CYGWIN:
- wchar_ctype = &ushort_ctype;
- break;
- case OS_DARWIN:
- int64_ctype = &llong_ctype;
- uint64_ctype = &ullong_ctype;
- wint_ctype = &int_ctype;
- break;
- case OS_FREEBSD:
- wint_ctype = &int_ctype;
- break;
- case OS_OPENBSD:
- wchar_ctype = &int_ctype;
- wint_ctype = &int_ctype;
- break;
- }
- break;
- case MACH_M68K:
- case MACH_PPC32:
- wchar_ctype = &long_ctype;
- break;
- case MACH_ARM:
- case MACH_ARM64:
- wchar_ctype = &uint_ctype;
- break;
- case MACH_SPARC32:
- if (arch_os == OS_SUNOS) {
- wint_ctype = &long_ctype;
- wchar_ctype = &long_ctype;
+ for (p = &archs[0]; p->name; p++) {
+ size_t len = strlen(p->name);
+ if (strncmp(p->name, name, len) == 0) {
+ enum machine mach = p->mach;
+ const char *suf = name + len;
+ int bits = p->bits;
+
+ if (bits == 0) {
+ if (!strcmp(suf, "") || !strcmp(suf, "32")) {
+ ;
+ } else if (!strcmp(suf, "64")) {
+ mach += 1;
+ } else {
+ die("invalid architecture: %s", name);
+ }
+ } else {
+ if (strcmp(suf, ""))
+ die("invalid architecture: %s", name);
+ }
+
+ return mach;
}
- break;
- default:
- break;
}
- if (fshort_wchar)
- wchar_ctype = &ushort_ctype;
- switch (arch_mach) {
- case MACH_SPARC32:
- if (arch_os == OS_SUNOS)
- break;
- /* fall through */
- case MACH_ARM:
- case MACH_MIPS64:
- // FIXME: ABI n32 & (n)64 have 128-bit ldouble
- case MACH_MIPS32:
- case MACH_S390:
- case MACH_S390X:
- bits_in_longdouble = 64;
- max_fp_alignment = 8;
- break;
- case MACH_X86_64:
- if (arch_m64 == ARCH_LP64 || arch_m64 == ARCH_X32)
- break;
- /* fall through */
- case MACH_I386:
- case MACH_M68K:
- bits_in_longdouble = 96;
- max_fp_alignment = 4;
- break;
- default:
- break;
- }
+ return MACH_UNKNOWN;
+}
- switch (arch_mach) {
- case MACH_ARM:
- case MACH_ARM64:
- case MACH_PPC32:
- case MACH_PPC64:
- case MACH_RISCV32:
- case MACH_RISCV64:
- case MACH_S390:
- case MACH_S390X:
- if (funsigned_char == -1)
- funsigned_char = 1;
- break;
- default:
- if (funsigned_char == -1)
- funsigned_char = 0;
- break;
- }
+
+void target_config(enum machine mach)
+{
+ const struct target *target = targets[mach];
+
+ arch_target = target;
+ arch_m64 = target->bitness;
+ arch_big_endian = target->big_endian;
+
+ funsigned_char = target->unsigned_char;
+}
+
+
+void target_init(void)
+{
+ const struct target *target = arch_target;
switch (arch_m64) {
- case ARCH_X32:
- max_int_alignment = 8;
- int64_ctype = &llong_ctype;
- uint64_ctype = &ullong_ctype;
- break;
case ARCH_LP32:
- /* default values */
+ max_int_alignment = 4;
+ /* fallthrough */
+ case ARCH_X32:
+ bits_in_long = 32;
+ bits_in_pointer = 32;
+ pointer_alignment = 4;
+ size_t_ctype = &uint_ctype;
+ ssize_t_ctype = &int_ctype;
int64_ctype = &llong_ctype;
uint64_ctype = &ullong_ctype;
intmax_ctype = &llong_ctype;
uintmax_ctype = &ullong_ctype;
+ if (target->target_32bit)
+ target = target->target_32bit;
break;
- case ARCH_LP64:
- bits_in_long = 64;
- max_int_alignment = 8;
- size_t_ctype = &ulong_ctype;
- ssize_t_ctype = &long_ctype;
- intmax_ctype = &long_ctype;
- uintmax_ctype = &ulong_ctype;
- goto case_64bit_common;
+
case ARCH_LLP64:
bits_in_long = 32;
- max_int_alignment = 8;
size_t_ctype = &ullong_ctype;
ssize_t_ctype = &llong_ctype;
int64_ctype = &llong_ctype;
uint64_ctype = &ullong_ctype;
- goto case_64bit_common;
- case_64bit_common:
- bits_in_pointer = 64;
- pointer_alignment = 8;
+ intmax_ctype = &llong_ctype;
+ uintmax_ctype = &ullong_ctype;
+ /* fallthrough */
+ case ARCH_LP64:
+ if (target->target_64bit)
+ target = target->target_64bit;
break;
}
+ arch_target = target;
+
+ if (fpie > fpic)
+ fpic = fpie;
+
+ if (target->wchar)
+ wchar_ctype = target->wchar;
+ if (target->wint)
+ wint_ctype = target->wint;
+ if (target->bits_in_longdouble)
+ bits_in_longdouble = target->bits_in_longdouble;
+ if (target->max_fp_alignment)
+ max_fp_alignment = target->max_fp_alignment;
+
+ if (target->init)
+ target->init(target);
+
+ if (arch_msize_long || target->size_t_long) {
+ size_t_ctype = &ulong_ctype;
+ ssize_t_ctype = &long_ctype;
+ }
+ if (fshort_wchar)
+ wchar_ctype = &ushort_ctype;
}
diff --git a/target.h b/target.h
index 8bbe494f..a89e21b6 100644
--- a/target.h
+++ b/target.h
@@ -1,6 +1,8 @@
#ifndef TARGET_H
#define TARGET_H
+#include "machine.h"
+
extern struct symbol *size_t_ctype;
extern struct symbol *ssize_t_ctype;
extern struct symbol *intmax_ctype;
@@ -51,6 +53,52 @@ extern int pointer_alignment;
extern int bits_in_enum;
extern int enum_alignment;
+
+struct target {
+ enum machine mach;
+ enum bitness bitness;
+ unsigned int big_endian:1;
+ unsigned int unsigned_char:1;
+ unsigned int size_t_long:1;
+ unsigned int has_int128:1;
+
+ struct symbol *wchar;
+ struct symbol *wint;
+
+ unsigned int bits_in_longdouble;
+ unsigned int max_fp_alignment;
+
+ const struct target *target_32bit;
+ const struct target *target_64bit;
+
+ void (*init)(const struct target *self);
+ void (*predefine)(const struct target *self);
+};
+
+extern const struct target target_default;
+extern const struct target target_arm;
+extern const struct target target_arm64;
+extern const struct target target_m68k;
+extern const struct target target_mips32;
+extern const struct target target_mips64;
+extern const struct target target_ppc32;
+extern const struct target target_ppc64;
+extern const struct target target_riscv32;
+extern const struct target target_riscv64;
+extern const struct target target_s390;
+extern const struct target target_s390x;
+extern const struct target target_sparc32;
+extern const struct target target_sparc64;
+extern const struct target target_i386;
+extern const struct target target_x86_64;
+
+/* target.c */
+extern const struct target *arch_target;
+
+enum machine target_parse(const char *name);
+void target_config(enum machine mach);
+void target_init(void);
+
/*
* Helper functions for converting bits to bytes and vice versa.
*/