diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-01-21 00:02:16 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-01-21 00:02:16 +0100 |
commit | eed8930cb4ec54047c584afd30f2ac53ff2c3317 (patch) | |
tree | 75c451fbc8dbbe1a8cfae00f81e866e2f9a2a382 | |
parent | 22978b6b1e5e2890bb4cb705a0f6674c2b2b6157 (diff) | |
parent | 31c6724f4f32c3367c929b96aa94bc4eee5f6af8 (diff) | |
download | sparse-eed8930cb4ec54047c584afd30f2ac53ff2c3317.tar.gz |
Merge branch 'arch-spec'
* move arch specificities in their own files
* better support of arch specificities
-rw-r--r-- | Makefile | 10 | ||||
-rwxr-xr-x | cgcc | 13 | ||||
-rw-r--r-- | lib.c | 247 | ||||
-rw-r--r-- | lib.h | 3 | ||||
-rw-r--r-- | machine.h | 2 | ||||
-rw-r--r-- | symbol.h | 1 | ||||
-rw-r--r-- | target-arm.c | 36 | ||||
-rw-r--r-- | target-arm64.c | 39 | ||||
-rw-r--r-- | target-default.c | 11 | ||||
-rw-r--r-- | target-m68k.c | 23 | ||||
-rw-r--r-- | target-mips.c | 53 | ||||
-rw-r--r-- | target-ppc.c | 58 | ||||
-rw-r--r-- | target-riscv.c | 53 | ||||
-rw-r--r-- | target-s390.c | 48 | ||||
-rw-r--r-- | target-sparc.c | 66 | ||||
-rw-r--r-- | target-x86.c | 73 | ||||
-rw-r--r-- | target.c | 262 | ||||
-rw-r--r-- | target.h | 48 |
18 files changed, 673 insertions, 373 deletions
@@ -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 @@ -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) { @@ -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(); @@ -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; @@ -8,7 +8,7 @@ #endif -enum { +enum bitness { ARCH_LP32, ARCH_X32, ARCH_LP64, @@ -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, +}; @@ -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; } @@ -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. */ |