blob: 8ae22d744f40344fa9c98f2e1ae8c63de8f6a60b [file] [log] [blame]
#include <stdio.h>
#include <string.h>
#include "symbol.h"
#include "target.h"
#include "machine.h"
struct symbol *ptrdiff_ctype;
struct symbol *intptr_ctype;
struct symbol *uintptr_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;
struct symbol *uint32_ctype = &uint_ctype;
struct symbol *wchar_ctype = &int_ctype;
struct symbol *wint_ctype = &uint_ctype;
struct symbol *least8_ctype = &schar_ctype;
struct symbol *uleast8_ctype = &uchar_ctype;
struct symbol *least16_ctype = &short_ctype;
struct symbol *uleast16_ctype = &ushort_ctype;
struct symbol *least32_ctype = &int_ctype;
struct symbol *uleast32_ctype = &uint_ctype;
struct symbol *least64_ctype = &llong_ctype;
struct symbol *uleast64_ctype = &ullong_ctype;
struct symbol *fast8_ctype = &schar_ctype;
struct symbol *ufast8_ctype = &uchar_ctype;
struct symbol *fast16_ctype = &long_ctype;
struct symbol *ufast16_ctype = &ulong_ctype;
struct symbol *fast32_ctype = &long_ctype;
struct symbol *ufast32_ctype = &ulong_ctype;
struct symbol *fast64_ctype = &long_ctype;
struct symbol *ufast64_ctype = &ulong_ctype;
struct symbol *sig_atomic_ctype = &int_ctype;
/*
* For "__attribute__((aligned))"
*/
int max_alignment = 16;
/*
* Integer data types
*/
int bits_in_bool = 1;
int bits_in_char = 8;
int bits_in_short = 16;
int bits_in_int = 32;
int bits_in_long = 64;
int bits_in_longlong = 64;
int bits_in_longlonglong = 128;
int max_int_alignment = 8;
/*
* Floating point data types
*/
int bits_in_float = 32;
int bits_in_double = 64;
int bits_in_longdouble = 128;
int max_fp_alignment = 16;
/*
* Pointer data type
*/
int bits_in_pointer = 64;
int pointer_alignment = 8;
/*
* Enum data types
*/
int bits_in_enum = 32;
int enum_alignment = 4;
static const struct target *targets[] = {
[MACH_ALPHA] = &target_alpha,
[MACH_ARM] = &target_arm,
[MACH_ARM64] = &target_arm64,
[MACH_BFIN] = &target_bfin,
[MACH_H8300] = &target_h8300,
[MACH_I386] = &target_i386,
[MACH_M68K] = &target_m68k,
[MACH_MICROBLAZE] = &target_microblaze,
[MACH_MIPS32] = &target_mips32,
[MACH_MIPS64] = &target_mips64,
[MACH_NDS32] = &target_nds32,
[MACH_NIOS2] = &target_nios2,
[MACH_OPENRISC] = &target_openrisc,
[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_SH] = &target_sh,
[MACH_SPARC32] = &target_sparc32,
[MACH_SPARC64] = &target_sparc64,
[MACH_X86_64] = &target_x86_64,
[MACH_XTENSA] = &target_xtensa,
[MACH_UNKNOWN] = &target_default,
};
const struct target *arch_target = &target_default;
enum machine target_parse(const char *name)
{
static const struct arch {
const char *name;
enum machine mach;
char bits;
} archs[] = {
{ "alpha", MACH_ALPHA, 64, },
{ "aarch64", MACH_ARM64, 64, },
{ "arm64", MACH_ARM64, 64, },
{ "arm", MACH_ARM, 32, },
{ "bfin", MACH_BFIN, 32, },
{ "h8300", MACH_H8300, 32, },
{ "i386", MACH_I386, 32, },
{ "m68k", MACH_M68K, 32, },
{ "microblaze", MACH_MICROBLAZE,32, },
{ "mips", MACH_MIPS32, 0, },
{ "nds32", MACH_NDS32, 32, },
{ "nios2", MACH_NIOS2, 32, },
{ "openrisc", MACH_OPENRISC, 32, },
{ "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, },
{ "sh", MACH_SH, 32, },
{ "xtensa", MACH_XTENSA, 32, },
{ NULL },
};
const struct arch *p;
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;
}
}
return MACH_UNKNOWN;
}
void target_os(const char *name)
{
static const struct os {
const char *name;
int os;
} oses[] = {
{ "cygwin", OS_CYGWIN },
{ "darwin", OS_DARWIN },
{ "freebsd", OS_FREEBSD },
{ "linux", OS_LINUX },
{ "native", OS_NATIVE, },
{ "netbsd", OS_NETBSD },
{ "none", OS_NONE },
{ "openbsd", OS_OPENBSD },
{ "sunos", OS_SUNOS },
{ "unix", OS_UNIX },
{ NULL },
}, *p;
for (p = &oses[0]; p->name; p++) {
if (!strcmp(p->name, name)) {
arch_os = p->os;
return;
}
}
die("invalid os: %s", name);
}
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:
if (target->target_x32bit)
target = target->target_x32bit;
goto case_32bit;
case ARCH_LP32:
max_int_alignment = 4;
if (target->target_32bit)
target = target->target_32bit;
/* fallthrough */
case_32bit:
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;
fast64_ctype = &llong_ctype;
ufast64_ctype = &ullong_ctype;
break;
case ARCH_LLP64:
bits_in_long = 32;
size_t_ctype = &ullong_ctype;
ssize_t_ctype = &llong_ctype;
int64_ctype = &llong_ctype;
uint64_ctype = &ullong_ctype;
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;
}