diff options
Diffstat (limited to 'src/a_targ.c')
| -rw-r--r-- | src/a_targ.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/a_targ.c b/src/a_targ.c new file mode 100644 index 0000000..fdc11f8 --- /dev/null +++ b/src/a_targ.c @@ -0,0 +1,121 @@ +#include "common.h" +#include "type.h" + +extern const struct mctarg t_x86_64_sysv, t_aarch64_aapcs; +static const struct targ { + struct { enum mcarch arch; uint oss, abis; }; + struct { uchar longsize, vlongsize, ptrsize, valistsize; }; + struct { uchar longalign, vlongalign, doublealign, ptralign; }; + bool charsigned; + uchar sizetype, ptrdifftype, wchartype; + const struct mctarg *mctarg; +} targs[] = { + { {ISx86_64, -1, -1}, {8,8,8,24}, {8,8,8,8}, 1, TYULONG, TYLONG, TYINT, &t_x86_64_sysv }, + { {ISaarch64, -1, -1}, {8,8,8,32}, {8,8,8,8}, 0, TYULONG, TYLONG, TYUINT, &t_aarch64_aapcs }, +}; + +struct targtriple target; +uchar targ_primsizes[TYPTR+1]; +uchar targ_primalign[TYPTR+1]; +uint targ_valistsize; +enum typetag targ_sizetype, targ_ptrdifftype, targ_wchartype; +bool targ_charsigned, targ_bigendian, targ_64bit; +enum mcarch targ_arch; +const struct mctarg *mctarg; + +static bool +matchstr(const char **s, const char *pat) +{ + const char *p; + for (p = *s; *pat; ++p, ++pat) { + if (*pat == '$') { if (*p) return 0; else break; } + else if (*p != *pat) return 0; + } + *s = p; + return 1; +} + +static bool +parsetriple(struct targtriple *trg, const char *str) +{ + if (matchstr(&str, "x86_64-") || matchstr(&str, "amd64-")) + trg->arch = ISx86_64; + else if (matchstr(&str, "aarch64-") || matchstr(&str, "arm64-")) + trg->arch = ISaarch64; + else return 0; + + if (matchstr(&str, "unknown-") || matchstr(&str, "pc-")) {} + + if (matchstr(&str, "linux-")) { + trg->os = OSlinux; + } else if (matchstr(&str, "linux$")) { + trg->os = OSlinux; + trg->abi = ABIgnu; + } else return 0; + + if (matchstr(&str, "gnu")) { + trg->abi = ABIgnu; + } else if (matchstr(&str, "musl")) { + trg->abi = ABImusl; + } else return 0; + + return 1; +} + +#include "hostconfig.h" /* run ./configure */ + +void +targ_init(const char *starg) +{ + const struct targ *t = NULL; + uchar *sizes = targ_primsizes, *align = targ_primalign; + + if (!starg) { + target.arch = HOST_ARCH; + target.os = HOST_OS; + target.abi = HOST_ABI; + } else if (!parsetriple(&target, starg)) { + fatal(NULL, "unrecognized target: %s", starg); + } + + for (size_t i = 0; i < countof(targs); ++i) { + if (targs[i].arch == target.arch) + if (targs[i].oss & (1 << target.os)) + if (targs[i].abis & (1 << target.abi)) { + t = &targs[i]; + break; + } + } + if (!t) fatal(NULL, "unsupported target: %s", starg ? starg : HOST_TRIPLE); + + sizes[TYBOOL] = sizes[TYCHAR] = sizes[TYSCHAR] = sizes[TYUCHAR] = 1; + sizes[TYSHORT] = sizes[TYUSHORT] = 2; + sizes[TYUINT] = sizes[TYINT] = 4; + sizes[TYFLOAT] = 4; + sizes[TYDOUBLE] = 8; + sizes[TYLDOUBLE] = 8; + memcpy(align, sizes, sizeof targ_primalign); + sizes[TYULONG] = sizes[TYLONG] = t->longsize; + sizes[TYUVLONG] = sizes[TYVLONG] = t->vlongsize; + sizes[TYPTR] = t->ptrsize; + align[TYULONG] = align[TYLONG] = t->longalign; + align[TYUVLONG] = align[TYVLONG] = t->vlongalign; + align[TYDOUBLE] = t->doublealign; + align[TYLDOUBLE] = t->doublealign; + align[TYPTR] = t->ptralign; + sizes[TYCOMPLEXF] = sizes[TYFLOAT]*2; + sizes[TYCOMPLEX] = sizes[TYDOUBLE]*2; + sizes[TYCOMPLEXL] = sizes[TYLDOUBLE]*2; + align[TYCOMPLEXF] = align[TYFLOAT]; + align[TYCOMPLEX] = align[TYDOUBLE]; + align[TYCOMPLEXL] = align[TYLDOUBLE]; + targ_valistsize = t->valistsize; + targ_sizetype = t->sizetype; + targ_ptrdifftype = t->ptrdifftype; + targ_wchartype = t->wchartype; + targ_charsigned = t->charsigned; + targ_bigendian = 0; + targ_64bit = t->ptrsize == 8; + mctarg = t->mctarg; + targ_arch = ISx86_64; +} |