make Alias.base an int
[qbe.git] / all.h
blob4c3c35ff7d023af830836d4d0afe064b710462da
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <limits.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
8 #define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1]
9 #define die(...) die_(__FILE__, __VA_ARGS__)
11 typedef unsigned char uchar;
12 typedef unsigned int uint;
13 typedef unsigned long ulong;
14 typedef unsigned long long bits;
16 typedef struct BSet BSet;
17 typedef struct Ref Ref;
18 typedef struct Op Op;
19 typedef struct Ins Ins;
20 typedef struct Phi Phi;
21 typedef struct Blk Blk;
22 typedef struct Use Use;
23 typedef struct Alias Alias;
24 typedef struct Tmp Tmp;
25 typedef struct Con Con;
26 typedef struct Addr Mem;
27 typedef struct Fn Fn;
28 typedef struct Typ Typ;
29 typedef struct Field Field;
30 typedef struct Dat Dat;
31 typedef struct Lnk Lnk;
32 typedef struct Target Target;
34 enum {
35 NString = 72,
36 NIns = 1 << 20,
37 NAlign = 3,
38 NField = 32,
39 NBit = CHAR_BIT * sizeof(bits),
42 struct Target {
43 char name[16];
44 char apple;
45 int gpr0; /* first general purpose reg */
46 int ngpr;
47 int fpr0; /* first floating point reg */
48 int nfpr;
49 bits rglob; /* globally live regs (e.g., sp, fp) */
50 int nrglob;
51 int *rsave; /* caller-save */
52 int nrsave[2];
53 bits (*retregs)(Ref, int[2]);
54 bits (*argregs)(Ref, int[2]);
55 int (*memargs)(int);
56 void (*abi0)(Fn *);
57 void (*abi1)(Fn *);
58 void (*isel)(Fn *);
59 void (*emitfn)(Fn *, FILE *);
60 void (*emitfin)(FILE *);
61 char asloc[4];
62 char assym[4];
65 #define BIT(n) ((bits)1 << (n))
67 enum {
68 RXX = 0,
69 Tmp0 = NBit, /* first non-reg temporary */
72 struct BSet {
73 uint nt;
74 bits *t;
77 struct Ref {
78 uint type:3;
79 uint val:29;
82 enum {
83 RTmp,
84 RCon,
85 RType,
86 RSlot,
87 RCall,
88 RMem,
91 #define R (Ref){0, 0}
92 #define TMP(x) (Ref){RTmp, x}
93 #define CON(x) (Ref){RCon, x}
94 #define CON_Z CON(0) /* reserved zero constant */
95 #define SLOT(x) (Ref){RSlot, (x)&0x1fffffff}
96 #define TYPE(x) (Ref){RType, x}
97 #define CALL(x) (Ref){RCall, x}
98 #define MEM(x) (Ref){RMem, x}
100 static inline int req(Ref a, Ref b)
102 return a.type == b.type && a.val == b.val;
105 static inline int rtype(Ref r)
107 if (req(r, R))
108 return -1;
109 return r.type;
112 enum CmpI {
113 Cieq,
114 Cine,
115 Cisge,
116 Cisgt,
117 Cisle,
118 Cislt,
119 Ciuge,
120 Ciugt,
121 Ciule,
122 Ciult,
123 NCmpI,
126 enum CmpF {
127 Cfeq,
128 Cfge,
129 Cfgt,
130 Cfle,
131 Cflt,
132 Cfne,
133 Cfo,
134 Cfuo,
135 NCmpF,
136 NCmp = NCmpI + NCmpF,
139 enum O {
140 Oxxx,
141 #define O(op, x, y) O##op,
142 #include "ops.h"
143 NOp,
146 enum J {
147 Jxxx,
148 #define JMPS(X) \
149 X(retw) X(retl) X(rets) X(retd) \
150 X(retsb) X(retub) X(retsh) X(retuh) \
151 X(retc) X(ret0) X(jmp) X(jnz) \
152 X(jfieq) X(jfine) X(jfisge) X(jfisgt) \
153 X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \
154 X(jfiule) X(jfiult) X(jffeq) X(jffge) \
155 X(jffgt) X(jffle) X(jfflt) X(jffne) \
156 X(jffo) X(jffuo)
157 #define X(j) J##j,
158 JMPS(X)
159 #undef X
160 NJmp
163 enum {
164 Ocmpw = Oceqw,
165 Ocmpw1 = Ocultw,
166 Ocmpl = Oceql,
167 Ocmpl1 = Ocultl,
168 Ocmps = Oceqs,
169 Ocmps1 = Ocuos,
170 Ocmpd = Oceqd,
171 Ocmpd1 = Ocuod,
172 Oalloc = Oalloc4,
173 Oalloc1 = Oalloc16,
174 Oflag = Oflagieq,
175 Oflag1 = Oflagfuo,
176 NPubOp = Onop,
177 Jjf = Jjfieq,
178 Jjf1 = Jjffuo,
181 #define INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */
182 #define isstore(o) INRANGE(o, Ostoreb, Ostored)
183 #define isload(o) INRANGE(o, Oloadsb, Oload)
184 #define isext(o) INRANGE(o, Oextsb, Oextuw)
185 #define ispar(o) INRANGE(o, Opar, Opare)
186 #define isarg(o) INRANGE(o, Oarg, Oargv)
187 #define isret(j) INRANGE(j, Jretw, Jret0)
188 #define isparbh(o) INRANGE(o, Oparsb, Oparuh)
189 #define isargbh(o) INRANGE(o, Oargsb, Oarguh)
190 #define isretbh(j) INRANGE(j, Jretsb, Jretuh)
192 enum {
193 Kx = -1, /* "top" class (see usecheck() and clsmerge()) */
200 #define KWIDE(k) ((k)&1)
201 #define KBASE(k) ((k)>>1)
203 struct Op {
204 char *name;
205 short argcls[2][4];
206 int canfold;
209 struct Ins {
210 uint op:30;
211 uint cls:2;
212 Ref to;
213 Ref arg[2];
216 struct Phi {
217 Ref to;
218 Ref *arg;
219 Blk **blk;
220 uint narg;
221 int cls;
222 Phi *link;
225 struct Blk {
226 Phi *phi;
227 Ins *ins;
228 uint nins;
229 struct {
230 short type;
231 Ref arg;
232 } jmp;
233 Blk *s1;
234 Blk *s2;
235 Blk *link;
237 uint id;
238 uint visit;
240 Blk *idom;
241 Blk *dom, *dlink;
242 Blk **fron;
243 uint nfron;
245 Blk **pred;
246 uint npred;
247 BSet in[1], out[1], gen[1];
248 int nlive[2];
249 int loop;
250 char name[NString];
253 struct Use {
254 enum {
255 UXXX,
256 UPhi,
257 UIns,
258 UJmp,
259 } type;
260 uint bid;
261 union {
262 Ins *ins;
263 Phi *phi;
264 } u;
267 enum {
268 NoAlias,
269 MayAlias,
270 MustAlias
273 struct Alias {
274 enum {
275 ABot = 0,
276 ALoc = 1, /* stack local */
277 ACon = 2,
278 AEsc = 3, /* stack escaping */
279 ASym = 4,
280 AUnk = 6,
281 #define astack(t) ((t) & 1)
282 } type;
283 int base;
284 uint32_t label;
285 int64_t offset;
286 int reloc;
287 Alias *slot;
290 struct Tmp {
291 char name[NString];
292 Ins *ins;
293 Use *use;
294 uint ndef, nuse;
295 uint bid; /* id of a defining block */
296 uint cost;
297 int slot; /* -1 for unset */
298 short cls;
299 struct {
300 int r; /* register or -1 */
301 int w; /* weight */
302 bits m; /* avoid these registers */
303 } hint;
304 int phi;
305 Alias alias;
306 enum {
307 WFull,
308 Wsb, /* must match Oload/Oext order */
309 Wub,
310 Wsh,
311 Wuh,
312 Wsw,
314 } width;
315 int visit;
318 struct Con {
319 enum {
320 CUndef,
321 CBits,
322 CAddr,
323 } type;
324 uint32_t label;
325 union {
326 int64_t i;
327 double d;
328 float s;
329 } bits;
330 enum {
331 RelDef,
332 RelThr,
333 } reloc;
334 char flt; /* 1 to print as s, 2 to print as d */
337 typedef struct Addr Addr;
339 struct Addr { /* amd64 addressing */
340 Con offset;
341 Ref base;
342 Ref index;
343 int scale;
346 struct Lnk {
347 char export;
348 char thread;
349 char align;
350 char *sec;
351 char *secf;
354 struct Fn {
355 Blk *start;
356 Tmp *tmp;
357 Con *con;
358 Mem *mem;
359 int ntmp;
360 int ncon;
361 int nmem;
362 uint nblk;
363 int retty; /* index in typ[], -1 if no aggregate return */
364 Ref retr;
365 Blk **rpo;
366 bits reg;
367 int slot;
368 char vararg;
369 char dynalloc;
370 char name[NString];
371 Lnk lnk;
374 struct Typ {
375 char name[NString];
376 char isdark;
377 char isunion;
378 int align;
379 uint64_t size;
380 uint nunion;
381 struct Field {
382 enum {
383 FEnd,
390 FPad,
391 FTyp,
392 } type;
393 uint len; /* or index in typ[] for FTyp */
394 } (*fields)[NField+1];
397 struct Dat {
398 enum {
399 DStart,
400 DEnd,
406 } type;
407 char *name;
408 Lnk *lnk;
409 union {
410 int64_t num;
411 double fltd;
412 float flts;
413 char *str;
414 struct {
415 char *name;
416 int64_t off;
417 } ref;
418 } u;
419 char isref;
420 char isstr;
423 /* main.c */
424 extern Target T;
425 extern char debug['Z'+1];
427 /* util.c */
428 typedef enum {
429 PHeap, /* free() necessary */
430 PFn, /* discarded after processing the function */
431 } Pool;
433 extern Typ *typ;
434 extern Ins insb[NIns], *curi;
435 uint32_t hash(char *);
436 void die_(char *, char *, ...) __attribute__((noreturn));
437 void *emalloc(size_t);
438 void *alloc(size_t);
439 void freeall(void);
440 void *vnew(ulong, size_t, Pool);
441 void vfree(void *);
442 void vgrow(void *, ulong);
443 uint32_t intern(char *);
444 char *str(uint32_t);
445 int argcls(Ins *, int);
446 int isreg(Ref);
447 int iscmp(int, int *, int *);
448 void emit(int, int, Ref, Ref, Ref);
449 void emiti(Ins);
450 void idup(Ins **, Ins *, ulong);
451 Ins *icpy(Ins *, Ins *, ulong);
452 int cmpop(int);
453 int cmpneg(int);
454 int clsmerge(short *, short);
455 int phicls(int, Tmp *);
456 Ref newtmp(char *, int, Fn *);
457 void chuse(Ref, int, Fn *);
458 Ref newcon(Con *, Fn *);
459 Ref getcon(int64_t, Fn *);
460 int addcon(Con *, Con *);
461 void blit(Ref, uint, Ref, uint, uint, Fn *);
462 void blit0(Ref, Ref, uint, Fn *);
463 void salloc(Ref, Ref, Fn *);
464 void dumpts(BSet *, Tmp *, FILE *);
466 void bsinit(BSet *, uint);
467 void bszero(BSet *);
468 uint bscount(BSet *);
469 void bsset(BSet *, uint);
470 void bsclr(BSet *, uint);
471 void bscopy(BSet *, BSet *);
472 void bsunion(BSet *, BSet *);
473 void bsinter(BSet *, BSet *);
474 void bsdiff(BSet *, BSet *);
475 int bsequal(BSet *, BSet *);
476 int bsiter(BSet *, int *);
478 static inline int
479 bshas(BSet *bs, uint elt)
481 assert(elt < bs->nt * NBit);
482 return (bs->t[elt/NBit] & BIT(elt%NBit)) != 0;
485 /* parse.c */
486 extern Op optab[NOp];
487 void parse(FILE *, char *, void (Dat *), void (Fn *));
488 void printfn(Fn *, FILE *);
489 void printref(Ref, Fn *, FILE *);
490 void err(char *, ...) __attribute__((noreturn));
492 /* abi.c */
493 void elimsb(Fn *);
495 /* cfg.c */
496 Blk *blknew(void);
497 void edgedel(Blk *, Blk **);
498 void fillpreds(Fn *);
499 void fillrpo(Fn *);
500 void filldom(Fn *);
501 int sdom(Blk *, Blk *);
502 int dom(Blk *, Blk *);
503 void fillfron(Fn *);
504 void loopiter(Fn *, void (*)(Blk *, Blk *));
505 void fillloop(Fn *);
506 void simpljmp(Fn *);
508 /* mem.c */
509 void memopt(Fn *);
511 /* alias.c */
512 void fillalias(Fn *);
513 int alias(Ref, int, Ref, int, int *, Fn *);
514 int escapes(Ref, Fn *);
516 /* load.c */
517 int loadsz(Ins *);
518 int storesz(Ins *);
519 void loadopt(Fn *);
521 /* ssa.c */
522 void filluse(Fn *);
523 void fillpreds(Fn *);
524 void fillrpo(Fn *);
525 void ssa(Fn *);
526 void ssacheck(Fn *);
528 /* copy.c */
529 void copy(Fn *);
531 /* fold.c */
532 void fold(Fn *);
534 /* live.c */
535 void liveon(BSet *, Blk *, Blk *);
536 void filllive(Fn *);
538 /* spill.c */
539 void fillcost(Fn *);
540 void spill(Fn *);
542 /* rega.c */
543 void rega(Fn *);
545 /* emit.c */
546 void emitfnlnk(char *, Lnk *, FILE *);
547 void emitdat(Dat *, FILE *);
548 int stashbits(void *, int);
549 void elf_emitfnfin(char *, FILE *);
550 void elf_emitfin(FILE *);
551 void macho_emitfin(FILE *);