fix various codegen bugs on arm64
[qbe.git] / all.h
blob97cc41cd33ba350466f680ddd82dac8318ae7cff
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 Sym Sym;
24 typedef struct Num Num;
25 typedef struct Alias Alias;
26 typedef struct Tmp Tmp;
27 typedef struct Con Con;
28 typedef struct Addr Mem;
29 typedef struct Fn Fn;
30 typedef struct Typ Typ;
31 typedef struct Field Field;
32 typedef struct Dat Dat;
33 typedef struct Lnk Lnk;
34 typedef struct Target Target;
36 enum {
37 NString = 80,
38 NIns = 1 << 20,
39 NAlign = 3,
40 NField = 32,
41 NBit = CHAR_BIT * sizeof(bits),
44 struct Target {
45 char name[16];
46 char apple;
47 int gpr0; /* first general purpose reg */
48 int ngpr;
49 int fpr0; /* first floating point reg */
50 int nfpr;
51 bits rglob; /* globally live regs (e.g., sp, fp) */
52 int nrglob;
53 int *rsave; /* caller-save */
54 int nrsave[2];
55 bits (*retregs)(Ref, int[2]);
56 bits (*argregs)(Ref, int[2]);
57 int (*memargs)(int);
58 void (*abi0)(Fn *);
59 void (*abi1)(Fn *);
60 void (*isel)(Fn *);
61 void (*emitfn)(Fn *, FILE *);
62 void (*emitfin)(FILE *);
63 char asloc[4];
64 char assym[4];
67 #define BIT(n) ((bits)1 << (n))
69 enum {
70 RXX = 0,
71 Tmp0 = NBit, /* first non-reg temporary */
74 struct BSet {
75 uint nt;
76 bits *t;
79 struct Ref {
80 uint type:3;
81 uint val:29;
84 enum {
85 RTmp,
86 RCon,
87 RInt,
88 RType, /* last kind to come out of the parser */
89 RSlot,
90 RCall,
91 RMem,
94 #define R (Ref){RTmp, 0}
95 #define UNDEF (Ref){RCon, 0} /* represents uninitialized data */
96 #define CON_Z (Ref){RCon, 1}
97 #define TMP(x) (Ref){RTmp, x}
98 #define CON(x) (Ref){RCon, x}
99 #define SLOT(x) (Ref){RSlot, (x)&0x1fffffff}
100 #define TYPE(x) (Ref){RType, x}
101 #define CALL(x) (Ref){RCall, x}
102 #define MEM(x) (Ref){RMem, x}
103 #define INT(x) (Ref){RInt, (x)&0x1fffffff}
105 static inline int req(Ref a, Ref b)
107 return a.type == b.type && a.val == b.val;
110 static inline int rtype(Ref r)
112 if (req(r, R))
113 return -1;
114 return r.type;
117 static inline int rsval(Ref r)
119 return ((int)r.val ^ 0x10000000) - 0x10000000;
122 enum CmpI {
123 Cieq,
124 Cine,
125 Cisge,
126 Cisgt,
127 Cisle,
128 Cislt,
129 Ciuge,
130 Ciugt,
131 Ciule,
132 Ciult,
133 NCmpI,
136 enum CmpF {
137 Cfeq,
138 Cfge,
139 Cfgt,
140 Cfle,
141 Cflt,
142 Cfne,
143 Cfo,
144 Cfuo,
145 NCmpF,
146 NCmp = NCmpI + NCmpF,
149 enum O {
150 Oxxx,
151 #define O(op, x, y) O##op,
152 #include "ops.h"
153 NOp,
156 enum J {
157 Jxxx,
158 #define JMPS(X) \
159 X(retw) X(retl) X(rets) X(retd) \
160 X(retsb) X(retub) X(retsh) X(retuh) \
161 X(retc) X(ret0) X(jmp) X(jnz) \
162 X(jfieq) X(jfine) X(jfisge) X(jfisgt) \
163 X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \
164 X(jfiule) X(jfiult) X(jffeq) X(jffge) \
165 X(jffgt) X(jffle) X(jfflt) X(jffne) \
166 X(jffo) X(jffuo) X(hlt)
167 #define X(j) J##j,
168 JMPS(X)
169 #undef X
170 NJmp
173 enum {
174 Ocmpw = Oceqw,
175 Ocmpw1 = Ocultw,
176 Ocmpl = Oceql,
177 Ocmpl1 = Ocultl,
178 Ocmps = Oceqs,
179 Ocmps1 = Ocuos,
180 Ocmpd = Oceqd,
181 Ocmpd1 = Ocuod,
182 Oalloc = Oalloc4,
183 Oalloc1 = Oalloc16,
184 Oflag = Oflagieq,
185 Oflag1 = Oflagfuo,
186 NPubOp = Onop,
187 Jjf = Jjfieq,
188 Jjf1 = Jjffuo,
191 #define INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */
192 #define isstore(o) INRANGE(o, Ostoreb, Ostored)
193 #define isload(o) INRANGE(o, Oloadsb, Oload)
194 #define isext(o) INRANGE(o, Oextsb, Oextuw)
195 #define ispar(o) INRANGE(o, Opar, Opare)
196 #define isarg(o) INRANGE(o, Oarg, Oargv)
197 #define isret(j) INRANGE(j, Jretw, Jret0)
198 #define isparbh(o) INRANGE(o, Oparsb, Oparuh)
199 #define isargbh(o) INRANGE(o, Oargsb, Oarguh)
200 #define isretbh(j) INRANGE(j, Jretsb, Jretuh)
202 enum {
203 Kx = -1, /* "top" class (see usecheck() and clsmerge()) */
210 #define KWIDE(k) ((k)&1)
211 #define KBASE(k) ((k)>>1)
213 struct Op {
214 char *name;
215 short argcls[2][4];
216 uint canfold:1;
217 uint hasid:1;
218 uint idval:1; /* identity value 0/1 */
221 struct Ins {
222 uint op:30;
223 uint cls:2;
224 Ref to;
225 Ref arg[2];
228 struct Phi {
229 Ref to;
230 Ref *arg;
231 Blk **blk;
232 uint narg;
233 int cls;
234 Phi *link;
237 struct Blk {
238 Phi *phi;
239 Ins *ins;
240 uint nins;
241 struct {
242 short type;
243 Ref arg;
244 } jmp;
245 Blk *s1;
246 Blk *s2;
247 Blk *link;
249 uint id;
250 uint visit;
252 Blk *idom;
253 Blk *dom, *dlink;
254 Blk **fron;
255 uint nfron;
257 Blk **pred;
258 uint npred;
259 BSet in[1], out[1], gen[1];
260 int nlive[2];
261 int loop;
262 char name[NString];
265 struct Use {
266 enum {
267 UXXX,
268 UPhi,
269 UIns,
270 UJmp,
271 } type;
272 uint bid;
273 union {
274 Ins *ins;
275 Phi *phi;
276 } u;
279 struct Sym {
280 enum {
281 SGlo,
282 SThr,
283 } type;
284 uint32_t id;
287 struct Num {
288 uchar n;
289 uchar nl, nr;
290 Ref l, r;
293 enum {
294 NoAlias,
295 MayAlias,
296 MustAlias
299 struct Alias {
300 enum {
301 ABot = 0,
302 ALoc = 1, /* stack local */
303 ACon = 2,
304 AEsc = 3, /* stack escaping */
305 ASym = 4,
306 AUnk = 6,
307 #define astack(t) ((t) & 1)
308 } type;
309 int base;
310 int64_t offset;
311 union {
312 Sym sym;
313 struct {
314 int sz; /* -1 if > NBit */
315 bits m;
316 } loc;
317 } u;
318 Alias *slot;
321 struct Tmp {
322 char name[NString];
323 Ins *def;
324 Use *use;
325 uint ndef, nuse;
326 uint bid; /* id of a defining block */
327 uint cost;
328 int slot; /* -1 for unset */
329 short cls;
330 struct {
331 int r; /* register or -1 */
332 int w; /* weight */
333 bits m; /* avoid these registers */
334 } hint;
335 int phi;
336 Alias alias;
337 enum {
338 WFull,
339 Wsb, /* must match Oload/Oext order */
340 Wub,
341 Wsh,
342 Wuh,
343 Wsw,
345 } width;
346 int visit;
349 struct Con {
350 enum {
351 CUndef,
352 CBits,
353 CAddr,
354 } type;
355 Sym sym;
356 union {
357 int64_t i;
358 double d;
359 float s;
360 } bits;
361 char flt; /* 1 to print as s, 2 to print as d */
364 typedef struct Addr Addr;
366 struct Addr { /* amd64 addressing */
367 Con offset;
368 Ref base;
369 Ref index;
370 int scale;
373 struct Lnk {
374 char export;
375 char thread;
376 char common;
377 char align;
378 char *sec;
379 char *secf;
382 struct Fn {
383 Blk *start;
384 Tmp *tmp;
385 Con *con;
386 Mem *mem;
387 int ntmp;
388 int ncon;
389 int nmem;
390 uint nblk;
391 int retty; /* index in typ[], -1 if no aggregate return */
392 Ref retr;
393 Blk **rpo;
394 bits reg;
395 int slot;
396 int salign;
397 char vararg;
398 char dynalloc;
399 char leaf;
400 char name[NString];
401 Lnk lnk;
404 struct Typ {
405 char name[NString];
406 char isdark;
407 char isunion;
408 int align;
409 uint64_t size;
410 uint nunion;
411 struct Field {
412 enum {
413 FEnd,
420 FPad,
421 FTyp,
422 } type;
423 uint len; /* or index in typ[] for FTyp */
424 } (*fields)[NField+1];
427 struct Dat {
428 enum {
429 DStart,
430 DEnd,
436 } type;
437 char *name;
438 Lnk *lnk;
439 union {
440 int64_t num;
441 double fltd;
442 float flts;
443 char *str;
444 struct {
445 char *name;
446 int64_t off;
447 } ref;
448 } u;
449 char isref;
450 char isstr;
453 /* main.c */
454 extern Target T;
455 extern char debug['Z'+1];
457 /* util.c */
458 typedef enum {
459 PHeap, /* free() necessary */
460 PFn, /* discarded after processing the function */
461 } Pool;
463 extern Typ *typ;
464 extern Ins insb[NIns], *curi;
465 uint32_t hash(char *);
466 void die_(char *, char *, ...) __attribute__((noreturn));
467 void *emalloc(size_t);
468 void *alloc(size_t);
469 void freeall(void);
470 void *vnew(ulong, size_t, Pool);
471 void vfree(void *);
472 void vgrow(void *, ulong);
473 void strf(char[NString], char *, ...);
474 uint32_t intern(char *);
475 char *str(uint32_t);
476 int argcls(Ins *, int);
477 int isreg(Ref);
478 int iscmp(int, int *, int *);
479 void emit(int, int, Ref, Ref, Ref);
480 void emiti(Ins);
481 void idup(Ins **, Ins *, ulong);
482 Ins *icpy(Ins *, Ins *, ulong);
483 int cmpop(int);
484 int cmpneg(int);
485 int clsmerge(short *, short);
486 int phicls(int, Tmp *);
487 Ref newtmp(char *, int, Fn *);
488 void chuse(Ref, int, Fn *);
489 int symeq(Sym, Sym);
490 Ref newcon(Con *, Fn *);
491 Ref getcon(int64_t, Fn *);
492 int addcon(Con *, Con *, int);
493 void salloc(Ref, Ref, Fn *);
494 void dumpts(BSet *, Tmp *, FILE *);
495 void runmatch(uchar *, Num *, Ref, Ref *);
497 void bsinit(BSet *, uint);
498 void bszero(BSet *);
499 uint bscount(BSet *);
500 void bsset(BSet *, uint);
501 void bsclr(BSet *, uint);
502 void bscopy(BSet *, BSet *);
503 void bsunion(BSet *, BSet *);
504 void bsinter(BSet *, BSet *);
505 void bsdiff(BSet *, BSet *);
506 int bsequal(BSet *, BSet *);
507 int bsiter(BSet *, int *);
509 static inline int
510 bshas(BSet *bs, uint elt)
512 assert(elt < bs->nt * NBit);
513 return (bs->t[elt/NBit] & BIT(elt%NBit)) != 0;
516 /* parse.c */
517 extern Op optab[NOp];
518 void parse(FILE *, char *, void (char *), void (Dat *), void (Fn *));
519 void printfn(Fn *, FILE *);
520 void printref(Ref, Fn *, FILE *);
521 void err(char *, ...) __attribute__((noreturn));
523 /* abi.c */
524 void elimsb(Fn *);
526 /* cfg.c */
527 Blk *newblk(void);
528 void edgedel(Blk *, Blk **);
529 void fillpreds(Fn *);
530 void fillrpo(Fn *);
531 void filldom(Fn *);
532 int sdom(Blk *, Blk *);
533 int dom(Blk *, Blk *);
534 void fillfron(Fn *);
535 void loopiter(Fn *, void (*)(Blk *, Blk *));
536 void fillloop(Fn *);
537 void simpljmp(Fn *);
539 /* mem.c */
540 void promote(Fn *);
541 void coalesce(Fn *);
543 /* alias.c */
544 void fillalias(Fn *);
545 void getalias(Alias *, Ref, Fn *);
546 int alias(Ref, int, int, Ref, int, int *, Fn *);
547 int escapes(Ref, Fn *);
549 /* load.c */
550 int loadsz(Ins *);
551 int storesz(Ins *);
552 void loadopt(Fn *);
554 /* ssa.c */
555 void filluse(Fn *);
556 void ssa(Fn *);
557 void ssacheck(Fn *);
559 /* copy.c */
560 void copy(Fn *);
562 /* fold.c */
563 void fold(Fn *);
565 /* simpl.c */
566 void simpl(Fn *);
568 /* live.c */
569 void liveon(BSet *, Blk *, Blk *);
570 void filllive(Fn *);
572 /* spill.c */
573 void fillcost(Fn *);
574 void spill(Fn *);
576 /* rega.c */
577 void rega(Fn *);
579 /* emit.c */
580 void emitfnlnk(char *, Lnk *, FILE *);
581 void emitdat(Dat *, FILE *);
582 void emitdbgfile(char *, FILE *);
583 void emitdbgloc(uint, uint, FILE *);
584 int stashbits(void *, int);
585 void elf_emitfnfin(char *, FILE *);
586 void elf_emitfin(FILE *);
587 void macho_emitfin(FILE *);