diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2017-04-08 21:06:33 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2017-04-08 21:56:20 -0400 |
commit | 49a4593c335126ba279f47328824abfef379725e (patch) | |
tree | 2f4cb5e9884ec958ea32a494da302a9aae8ca420 /all.h | |
parent | 9d1c38d69547d835f7228651e71e8a7d744c456d (diff) | |
download | roux-49a4593c335126ba279f47328824abfef379725e.tar.gz |
prepare for multi-target
This big diff does multiple changes to allow the addition of new targets to qbe. The changes are listed below in decreasing order of impact. 1. Add a new Target structure. To add support for a given target, one has to implement all the members of the Target structure. All the source files where changed to use this interface where needed. 2. Single out amd64-specific code. In this commit, the amd64 target T_amd64_sysv is the only target available, it is implemented in the amd64/ directory. All the non-static items in this directory are prefixed with either amd64_ or amd64_sysv (for items that are specific to the System V ABI). 3. Centralize Ops information. There is now a file 'ops.h' that must be used to store all the available operations together with their metadata. The various targets will only select what they need; but it is beneficial that there is only *one* place to change to add a new instruction. One good side effect of this change is that any operation 'xyz' in the IL now as a corresponding 'Oxyz' in the code. 4. Misc fixes. One notable change is that instruction selection now generates generic comparison operations and the lowering to the target's comparisons is done in the emitter. GAS directives for data are the same for many targets, so data emission was extracted in a file 'gas.c'. 5. Modularize the Makefile. The Makefile now has a list of C files that are target-independent (SRC), and one list of C files per target. Each target can also use its own 'all.h' header (for example to define registers).
Diffstat (limited to 'all.h')
-rw-r--r-- | all.h | 334 |
1 files changed, 107 insertions, 227 deletions
diff --git a/all.h b/all.h index 124a8d2..c0e08fe 100644 --- a/all.h +++ b/all.h @@ -8,13 +8,14 @@ #define MAKESURE(what, x) typedef char make_sure_##what[(x)?1:-1] #define die(...) die_(__FILE__, __VA_ARGS__) +typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; typedef unsigned long long bits; typedef struct BSet BSet; typedef struct Ref Ref; -typedef struct OpDesc OpDesc; +typedef struct Op Op; typedef struct Ins Ins; typedef struct Phi Phi; typedef struct Blk Blk; @@ -27,6 +28,7 @@ typedef struct Fn Fn; typedef struct Typ Typ; typedef struct Seg Seg; typedef struct Dat Dat; +typedef struct Target Target; enum { NString = 32, @@ -38,61 +40,29 @@ enum { NBit = CHAR_BIT * sizeof(bits), }; -#define BIT(n) ((bits)1 << (n)) - -enum Reg { - RXX, - - RAX, /* caller-save */ - RCX, - RDX, - RSI, - RDI, - R8, - R9, - R10, - R11, - - RBX, /* callee-save */ - R12, - R13, - R14, - R15, - - RBP, /* globally live */ - RSP, -#define RGLOB (BIT(RBP)|BIT(RSP)) - - XMM0, /* sse */ - XMM1, - XMM2, - XMM3, - XMM4, - XMM5, - XMM6, - XMM7, - XMM8, - XMM9, - XMM10, - XMM11, - XMM12, - XMM13, - XMM14, - XMM15, - - Tmp0, /* first non-reg temporary */ - - NRGlob = 2, - NIReg = R15 - RAX + 1 + NRGlob, - NFReg = XMM14 - XMM0 + 1, /* XMM15 is reserved */ - NISave = R11 - RAX + 1, - NFSave = NFReg, - NRSave = NISave + NFSave, - NRClob = R15 - RBX + 1, +struct Target { + int gpr0; /* first general purpose reg */ + int ngpr; + int fpr0; /* first floating point reg */ + int nfpr; + bits rglob; /* globally live regs (e.g., sp, fp) */ + int nrglob; + int *rsave; /* caller-save */ + int nrsave[2]; + bits (*retregs)(Ref, int[2]); + bits (*argregs)(Ref, int[2]); + int (*memargs)(int); + void (*abi)(Fn *); + void (*isel)(Fn *); + void (*emitfn)(Fn *, FILE *); }; -MAKESURE(NBit_is_enough, NBit >= (int)Tmp0); +#define BIT(n) ((bits)1 << (n)) +enum { + RXX = 0, + Tmp0 = NBit, /* first non-reg temporary */ +}; struct BSet { uint nt; @@ -139,51 +109,81 @@ static inline int isreg(Ref r) return rtype(r) == RTmp && r.val < Tmp0; } -enum ICmp { -#define ICMPS(X) \ - X(ule) \ - X(ult) \ - X(sle) \ - X(slt) \ - X(sgt) \ - X(sge) \ - X(ugt) \ - X(uge) \ - X(eq) \ - X(ne) /* make sure icmpop() below works! */ - -#define X(c) IC##c, - ICMPS(X) -#undef X - NICmp, +enum CmpI { + Cieq, + Cine, + Cisge, + Cisgt, + Cisle, + Cislt, + Ciuge, + Ciugt, + Ciule, + Ciult, + NCmpI, +}; - ICxnp = NICmp, /* x64 specific */ - ICxp, - NXICmp +enum CmpF { + Cfeq, + Cfge, + Cfgt, + Cfle, + Cflt, + Cfne, + Cfo, + Cfuo, + NCmpF, + NCmp = NCmpI + NCmpF, }; -static inline int icmpop(int c) -{ - return c >= ICeq ? c : ICuge - c; -} +enum O { + Oxxx, +#define O(op, x, y) O##op, + #include "ops.h" + NOp, +}; -enum FCmp { -#define FCMPS(X) \ - X(le) \ - X(lt) \ - X(gt) \ - X(ge) \ - X(ne) \ - X(eq) \ - X(o) \ - X(uo) - -#define X(c) FC##c, - FCMPS(X) +enum J { + Jxxx, +#define JMPS(X) \ + X(ret0) X(retw) X(retl) X(rets) \ + X(retd) X(retc) X(jmp) X(jnz) \ + X(jfieq) X(jfine) X(jfisge) X(jfisgt) \ + X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \ + X(jfiule) X(jfiult) X(jffeq) X(jffge) \ + X(jffgt) X(jffle) X(jfflt) X(jffne) \ + X(jffo) X(jffuo) +#define X(j) J##j, + JMPS(X) #undef X - NFCmp + NJmp +}; + +enum { + Ocmpw = Oceqw, + Ocmpw1 = Ocultw, + Ocmpl = Oceql, + Ocmpl1 = Ocultl, + Ocmps = Oceqs, + Ocmps1 = Ocuos, + Ocmpd = Oceqd, + Ocmpd1 = Ocuod, + Oalloc = Oalloc4, + Oalloc1 = Oalloc16, + Oflag = Oflagieq, + Oflag1 = Oflagfuo, + NPubOp = Onop, + Jjf = Jjfieq, + Jjf1 = Jjffuo, }; +#define isstore(o) (Ostoreb <= o && o <= Ostored) +#define isload(o) (Oloadsb <= o && o <= Oload) +#define isext(o) (Oextsb <= o && o <= Oextuw) +#define ispar(o) (Opar <= o && o <= Opare) +#define isarg(o) (Oarg <= o && o <= Oarge) +#define isret(j) (Jret0 <= j && j <= Jretc) + enum Class { Kx = -1, /* "top" class (see usecheck() and clsmerge()) */ Kw, @@ -195,124 +195,10 @@ enum Class { #define KWIDE(k) ((k)&1) #define KBASE(k) ((k)>>1) -enum Op { - Oxxx, - - /* public instructions */ - Oadd, - Osub, - Odiv, - Orem, - Oudiv, - Ourem, - Omul, - Oand, - Oor, - Oxor, - Osar, - Oshr, - Oshl, - Ocmpw, - Ocmpw1 = Ocmpw + NICmp-1, - Ocmpl, - Ocmpl1 = Ocmpl + NICmp-1, - Ocmps, - Ocmps1 = Ocmps + NFCmp-1, - Ocmpd, - Ocmpd1 = Ocmpd + NFCmp-1, - - Ostoreb, - Ostoreh, - Ostorew, - Ostorel, - Ostores, - Ostored, -#define isstore(o) (Ostoreb <= o && o <= Ostored) - Oloadsb, /* must match Oext and Tmp.width */ - Oloadub, - Oloadsh, - Oloaduh, - Oloadsw, - Oloaduw, - Oload, -#define isload(o) (Oloadsb <= o && o <= Oload) - Oextsb, - Oextub, - Oextsh, - Oextuh, - Oextsw, - Oextuw, -#define isext(o) (Oextsb <= o && o <= Oextuw) - - Oexts, - Otruncd, - Ostosi, - Odtosi, - Oswtof, - Osltof, - Ocast, - - Oalloc, - Oalloc1 = Oalloc + NAlign-1, - - Ovastart, - Ovaarg, - - Ocopy, - NPubOp, - - /* function instructions */ - Opar = NPubOp, - Oparc, - Opare, -#define ispar(o) (Opar <= o && o <= Opare) - Oarg, - Oargc, - Oarge, -#define isarg(o) (Oarg <= o && o <= Oarge) - Ocall, - Ovacall, - - /* reserved instructions */ - Onop, - Oaddr, - Oswap, - Osign, - Osalloc, - Oxidiv, - Oxdiv, - Oxcmp, - Oxset, - Oxsetnp = Oxset + ICxnp, - Oxsetp = Oxset + ICxp, - Oxtest, - NOp -}; - -enum Jmp { - Jxxx, - Jret0, - Jretw, - Jretl, - Jrets, - Jretd, - Jretc, -#define isret(j) (Jret0 <= j && j <= Jretc) - Jjmp, - Jjnz, - Jxjc, - Jxjnp = Jxjc + ICxnp, - Jxjp = Jxjc + ICxp, - NJmp -}; - -struct OpDesc { +struct Op { char *name; - int nmem; short argcls[2][4]; - uint sflag:1; /* sets the zero flag */ - uint lflag:1; /* leaves flags */ - uint cfold:1; /* can fold */ + int canfold; }; struct Ins { @@ -437,7 +323,7 @@ struct Con { typedef struct Addr Addr; -struct Addr { /* x64 addressing */ +struct Addr { /* amd64 addressing */ Con offset; Ref base; Ref index; @@ -508,8 +394,8 @@ struct Dat { char export; }; - /* main.c */ +extern Target T; extern char debug['Z'+1]; /* util.c */ @@ -524,6 +410,8 @@ void die_(char *, char *, ...) __attribute__((noreturn)); void *emalloc(size_t); void *alloc(size_t); void freeall(void); +int argcls(Ins *, int); +int iscmp(int, int *, int *); void emit(int, int, Ref, Ref, Ref); void emiti(Ins); void idup(Ins **, Ins *, ulong); @@ -531,12 +419,15 @@ Ins *icpy(Ins *, Ins *, ulong); void *vnew(ulong, size_t, Pool); void vfree(void *); void vgrow(void *, ulong); +int cmpop(int); +int cmpneg(int); int clsmerge(short *, short); int phicls(int, Tmp *); Ref newtmp(char *, int, Fn *); void chuse(Ref, int, Fn *); Ref getcon(int64_t, Fn *); void addcon(Con *, Con *); +void blit(Ref, uint, Ref, uint, Fn *); void dumpts(BSet *, Tmp *, FILE *); void bsinit(BSet *, uint); @@ -559,7 +450,7 @@ bshas(BSet *bs, uint elt) } /* parse.c */ -extern OpDesc opdesc[NOp]; +extern Op optab[NOp]; void parse(FILE *, char *, void (Dat *), void (Fn *)); void printfn(Fn *, FILE *); void printref(Ref, Fn *, FILE *); @@ -611,16 +502,6 @@ void fold(Fn *); void liveon(BSet *, Blk *, Blk *); void filllive(Fn *); -/* abi: sysv.c */ -extern int rsave[/* NRSave */]; -extern int rclob[/* NRClob */]; -bits retregs(Ref, int[2]); -bits argregs(Ref, int[2]); -void abi(Fn *); - -/* isel.c */ -void isel(Fn *); - /* spill.c */ void fillcost(Fn *); void spill(Fn *); @@ -628,10 +509,9 @@ void spill(Fn *); /* rega.c */ void rega(Fn *); -/* emit.c */ -extern char *locprefix; -extern char *symprefix; -void emitfn(Fn *, FILE *); -void emitdat(Dat *, FILE *); -int stashfp(int64_t, int); -void emitfin(FILE *); +/* gas.c */ +extern char *gasloc; +extern char *gassym; +void gasemitdat(Dat *, FILE *); +int gasstashfp(int64_t, int); +void gasemitfin(FILE *); |