aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/a_targ.c
blob: f094f60d5e74d1b2dfafea07da65c2e6564cffdd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "antcc.h"
#include "c_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 },
};

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(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;
}