add extra functions and clean up makefile and readme
This commit is contained in:
parent
d2f4528797
commit
a5741ed125
6 changed files with 44 additions and 814 deletions
36
Makefile
36
Makefile
|
@ -1,8 +1,12 @@
|
|||
.POSIX:
|
||||
.SUFFIXES: .o .c
|
||||
|
||||
LIBRARY = libqbe.a
|
||||
HEADER = libqbe.h
|
||||
|
||||
PREFIX = /usr/local
|
||||
BINDIR = $(PREFIX)/bin
|
||||
LIBDIR = $(PREFIX)/lib
|
||||
INCDIR = $(PREFIX)/include
|
||||
|
||||
COMMOBJ = libqbe.o util.o parse.o abi.o cfg.o mem.o ssa.o alias.o load.o \
|
||||
copy.o fold.o simpl.o live.o spill.o rega.o emit.o
|
||||
|
@ -15,7 +19,7 @@ SRCALL = $(OBJ:.o=.c)
|
|||
|
||||
CC = cc
|
||||
AR = ar
|
||||
CFLAGS = -std=c99 -g -Wall -Wextra -Wpedantic
|
||||
CFLAGS = -std=gnu99 -g -Wall -Wextra -Wpedantic
|
||||
|
||||
libqbe.a: $(OBJ)
|
||||
$(AR) rcs $@ $(OBJ)
|
||||
|
@ -23,13 +27,13 @@ libqbe.a: $(OBJ)
|
|||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJ): all.h ops.h
|
||||
$(OBJ): qbe/all.h qbe/ops.h
|
||||
$(AMD64OBJ): amd64/all.h
|
||||
$(ARM64OBJ): arm64/all.h
|
||||
$(RV64OBJ): rv64/all.h
|
||||
libqbe.o: config.h
|
||||
libqbe.o: qbe/config.h
|
||||
|
||||
config.h:
|
||||
qbe/config.h:
|
||||
@case `uname` in \
|
||||
*Darwin*) \
|
||||
case `uname -m` in \
|
||||
|
@ -56,27 +60,19 @@ config.h:
|
|||
;; \
|
||||
esac > $@
|
||||
|
||||
install: qbe
|
||||
mkdir -p "$(DESTDIR)$(BINDIR)"
|
||||
install -m755 qbe "$(DESTDIR)$(BINDIR)/qbe"
|
||||
install: $(LIBRARY) $(HEADER)
|
||||
mkdir -p "$(DESTDIR)$(LIBDIR)"
|
||||
cp "$(LIBRARY)" "$(DESTDIR)$(LIBDIR)/"
|
||||
cp -r "$(HEADER)" "qbe/" "$(DESTDIR)$(INCDIR)/"
|
||||
|
||||
uninstall:
|
||||
rm -f "$(DESTDIR)$(BINDIR)/qbe"
|
||||
rm -f "$(DESTDIR)$(LIBDIR)/$(LIBRARY)" "$(DESTDIR)$(INCDIR)/$(HEADER)" "$(DESTDIR)$(INCDIR)/qbe"
|
||||
|
||||
clean:
|
||||
rm -f *.o */*.o qbe
|
||||
rm -r *.o */*.o
|
||||
|
||||
clean-gen: clean
|
||||
rm -f config.h
|
||||
|
||||
check: qbe
|
||||
tools/test.sh all
|
||||
|
||||
check-arm64: qbe
|
||||
TARGET=arm64 tools/test.sh all
|
||||
|
||||
check-rv64: qbe
|
||||
TARGET=rv64 tools/test.sh all
|
||||
rm -f qbe/config.h
|
||||
|
||||
src:
|
||||
@echo $(SRCALL)
|
||||
|
|
8
README
8
README
|
@ -1,9 +1,7 @@
|
|||
QBE - Backend Compiler http://c9x.me/compile/
|
||||
|
||||
doc/ Documentation.
|
||||
minic/ An example C frontend for QBE.
|
||||
tools/ Miscellaneous tools (testing).
|
||||
test/ Tests.
|
||||
I did not create QBE, I simply turned it into a C library.
|
||||
|
||||
amd64/
|
||||
arm64/
|
||||
rv64/ Architecture-specific code.
|
||||
|
@ -15,4 +13,4 @@ The LICENSE file applies to all files distributed.
|
|||
Invoke make in this directory to create the executable
|
||||
file qbe. Install using 'make install', the standard
|
||||
DESTDIR and PREFIX environment variables are supported.
|
||||
Alternatively, you may simply copy the qbe binary manually.
|
||||
Alternatively, you may simply copy the libqbe.a and libqbe.h files manually.
|
||||
|
|
585
all.h
585
all.h
|
@ -1,585 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 Op Op;
|
||||
typedef struct Ins Ins;
|
||||
typedef struct Phi Phi;
|
||||
typedef struct Blk Blk;
|
||||
typedef struct Use Use;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Num Num;
|
||||
typedef struct Alias Alias;
|
||||
typedef struct Tmp Tmp;
|
||||
typedef struct Con Con;
|
||||
typedef struct Addr Mem;
|
||||
typedef struct Fn Fn;
|
||||
typedef struct Typ Typ;
|
||||
typedef struct Field Field;
|
||||
typedef struct Dat Dat;
|
||||
typedef struct Lnk Lnk;
|
||||
typedef struct Target Target;
|
||||
|
||||
enum {
|
||||
NString = 80,
|
||||
NIns = 1 << 20,
|
||||
NAlign = 3,
|
||||
NField = 32,
|
||||
NBit = CHAR_BIT * sizeof(bits),
|
||||
};
|
||||
|
||||
struct Target {
|
||||
char name[16];
|
||||
char apple;
|
||||
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 (*abi0)(Fn *);
|
||||
void (*abi1)(Fn *);
|
||||
void (*isel)(Fn *);
|
||||
void (*emitfn)(Fn *, FILE *);
|
||||
void (*emitfin)(FILE *);
|
||||
char asloc[4];
|
||||
char assym[4];
|
||||
};
|
||||
|
||||
#define BIT(n) ((bits)1 << (n))
|
||||
|
||||
enum {
|
||||
RXX = 0,
|
||||
Tmp0 = NBit, /* first non-reg temporary */
|
||||
};
|
||||
|
||||
struct BSet {
|
||||
uint nt;
|
||||
bits *t;
|
||||
};
|
||||
|
||||
struct Ref {
|
||||
uint type:3;
|
||||
uint val:29;
|
||||
};
|
||||
|
||||
enum {
|
||||
RTmp,
|
||||
RCon,
|
||||
RInt,
|
||||
RType, /* last kind to come out of the parser */
|
||||
RSlot,
|
||||
RCall,
|
||||
RMem,
|
||||
};
|
||||
|
||||
#define R (Ref){RTmp, 0}
|
||||
#define UNDEF (Ref){RCon, 0} /* represents uninitialized data */
|
||||
#define CON_Z (Ref){RCon, 1}
|
||||
#define TMP(x) (Ref){RTmp, x}
|
||||
#define CON(x) (Ref){RCon, x}
|
||||
#define SLOT(x) (Ref){RSlot, (x)&0x1fffffff}
|
||||
#define TYPE(x) (Ref){RType, x}
|
||||
#define CALL(x) (Ref){RCall, x}
|
||||
#define MEM(x) (Ref){RMem, x}
|
||||
#define INT(x) (Ref){RInt, (x)&0x1fffffff}
|
||||
|
||||
static inline int req(Ref a, Ref b)
|
||||
{
|
||||
return a.type == b.type && a.val == b.val;
|
||||
}
|
||||
|
||||
static inline int rtype(Ref r)
|
||||
{
|
||||
if (req(r, R))
|
||||
return -1;
|
||||
return r.type;
|
||||
}
|
||||
|
||||
static inline int rsval(Ref r)
|
||||
{
|
||||
return ((int)r.val ^ 0x10000000) - 0x10000000;
|
||||
}
|
||||
|
||||
enum CmpI {
|
||||
Cieq,
|
||||
Cine,
|
||||
Cisge,
|
||||
Cisgt,
|
||||
Cisle,
|
||||
Cislt,
|
||||
Ciuge,
|
||||
Ciugt,
|
||||
Ciule,
|
||||
Ciult,
|
||||
NCmpI,
|
||||
};
|
||||
|
||||
enum CmpF {
|
||||
Cfeq,
|
||||
Cfge,
|
||||
Cfgt,
|
||||
Cfle,
|
||||
Cflt,
|
||||
Cfne,
|
||||
Cfo,
|
||||
Cfuo,
|
||||
NCmpF,
|
||||
NCmp = NCmpI + NCmpF,
|
||||
};
|
||||
|
||||
enum O {
|
||||
Oxxx,
|
||||
#define O(op, x, y) O##op,
|
||||
#include "ops.h"
|
||||
NOp,
|
||||
};
|
||||
|
||||
enum J {
|
||||
Jxxx,
|
||||
#define JMPS(X) \
|
||||
X(retw) X(retl) X(rets) X(retd) \
|
||||
X(retsb) X(retub) X(retsh) X(retuh) \
|
||||
X(retc) X(ret0) 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) X(hlt)
|
||||
#define X(j) J##j,
|
||||
JMPS(X)
|
||||
#undef X
|
||||
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 INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */
|
||||
#define isstore(o) INRANGE(o, Ostoreb, Ostored)
|
||||
#define isload(o) INRANGE(o, Oloadsb, Oload)
|
||||
#define isext(o) INRANGE(o, Oextsb, Oextuw)
|
||||
#define ispar(o) INRANGE(o, Opar, Opare)
|
||||
#define isarg(o) INRANGE(o, Oarg, Oargv)
|
||||
#define isret(j) INRANGE(j, Jretw, Jret0)
|
||||
#define isparbh(o) INRANGE(o, Oparsb, Oparuh)
|
||||
#define isargbh(o) INRANGE(o, Oargsb, Oarguh)
|
||||
#define isretbh(j) INRANGE(j, Jretsb, Jretuh)
|
||||
|
||||
enum {
|
||||
Kx = -1, /* "top" class (see usecheck() and clsmerge()) */
|
||||
Kw,
|
||||
Kl,
|
||||
Ks,
|
||||
Kd
|
||||
};
|
||||
|
||||
#define KWIDE(k) ((k)&1)
|
||||
#define KBASE(k) ((k)>>1)
|
||||
|
||||
struct Op {
|
||||
char *name;
|
||||
short argcls[2][4];
|
||||
uint canfold:1;
|
||||
uint hasid:1;
|
||||
uint idval:1; /* identity value 0/1 */
|
||||
};
|
||||
|
||||
struct Ins {
|
||||
uint op:30;
|
||||
uint cls:2;
|
||||
Ref to;
|
||||
Ref arg[2];
|
||||
};
|
||||
|
||||
struct Phi {
|
||||
Ref to;
|
||||
Ref *arg;
|
||||
Blk **blk;
|
||||
uint narg;
|
||||
int cls;
|
||||
Phi *link;
|
||||
};
|
||||
|
||||
struct Blk {
|
||||
Phi *phi;
|
||||
Ins *ins;
|
||||
uint nins;
|
||||
struct {
|
||||
short type;
|
||||
Ref arg;
|
||||
} jmp;
|
||||
Blk *s1;
|
||||
Blk *s2;
|
||||
Blk *link;
|
||||
|
||||
uint id;
|
||||
uint visit;
|
||||
|
||||
Blk *idom;
|
||||
Blk *dom, *dlink;
|
||||
Blk **fron;
|
||||
uint nfron;
|
||||
|
||||
Blk **pred;
|
||||
uint npred;
|
||||
BSet in[1], out[1], gen[1];
|
||||
int nlive[2];
|
||||
int loop;
|
||||
char name[NString];
|
||||
};
|
||||
|
||||
struct Use {
|
||||
enum {
|
||||
UXXX,
|
||||
UPhi,
|
||||
UIns,
|
||||
UJmp,
|
||||
} type;
|
||||
uint bid;
|
||||
union {
|
||||
Ins *ins;
|
||||
Phi *phi;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct Sym {
|
||||
enum {
|
||||
SGlo,
|
||||
SThr,
|
||||
} type;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct Num {
|
||||
uchar n;
|
||||
uchar nl, nr;
|
||||
Ref l, r;
|
||||
};
|
||||
|
||||
enum {
|
||||
NoAlias,
|
||||
MayAlias,
|
||||
MustAlias
|
||||
};
|
||||
|
||||
struct Alias {
|
||||
enum {
|
||||
ABot = 0,
|
||||
ALoc = 1, /* stack local */
|
||||
ACon = 2,
|
||||
AEsc = 3, /* stack escaping */
|
||||
ASym = 4,
|
||||
AUnk = 6,
|
||||
#define astack(t) ((t) & 1)
|
||||
} type;
|
||||
int base;
|
||||
int64_t offset;
|
||||
union {
|
||||
Sym sym;
|
||||
struct {
|
||||
int sz; /* -1 if > NBit */
|
||||
bits m;
|
||||
} loc;
|
||||
} u;
|
||||
Alias *slot;
|
||||
};
|
||||
|
||||
struct Tmp {
|
||||
char name[NString];
|
||||
Ins *def;
|
||||
Use *use;
|
||||
uint ndef, nuse;
|
||||
uint bid; /* id of a defining block */
|
||||
uint cost;
|
||||
int slot; /* -1 for unset */
|
||||
short cls;
|
||||
struct {
|
||||
int r; /* register or -1 */
|
||||
int w; /* weight */
|
||||
bits m; /* avoid these registers */
|
||||
} hint;
|
||||
int phi;
|
||||
Alias alias;
|
||||
enum {
|
||||
WFull,
|
||||
Wsb, /* must match Oload/Oext order */
|
||||
Wub,
|
||||
Wsh,
|
||||
Wuh,
|
||||
Wsw,
|
||||
Wuw
|
||||
} width;
|
||||
int visit;
|
||||
};
|
||||
|
||||
struct Con {
|
||||
enum {
|
||||
CUndef,
|
||||
CBits,
|
||||
CAddr,
|
||||
} type;
|
||||
Sym sym;
|
||||
union {
|
||||
int64_t i;
|
||||
double d;
|
||||
float s;
|
||||
} bits;
|
||||
char flt; /* 1 to print as s, 2 to print as d */
|
||||
};
|
||||
|
||||
typedef struct Addr Addr;
|
||||
|
||||
struct Addr { /* amd64 addressing */
|
||||
Con offset;
|
||||
Ref base;
|
||||
Ref index;
|
||||
int scale;
|
||||
};
|
||||
|
||||
struct Lnk {
|
||||
char export;
|
||||
char thread;
|
||||
char common;
|
||||
char align;
|
||||
char *sec;
|
||||
char *secf;
|
||||
};
|
||||
|
||||
struct Fn {
|
||||
Blk *start;
|
||||
Tmp *tmp;
|
||||
Con *con;
|
||||
Mem *mem;
|
||||
int ntmp;
|
||||
int ncon;
|
||||
int nmem;
|
||||
uint nblk;
|
||||
int retty; /* index in typ[], -1 if no aggregate return */
|
||||
Ref retr;
|
||||
Blk **rpo;
|
||||
bits reg;
|
||||
int slot;
|
||||
char vararg;
|
||||
char dynalloc;
|
||||
char name[NString];
|
||||
Lnk lnk;
|
||||
};
|
||||
|
||||
struct Typ {
|
||||
char name[NString];
|
||||
char isdark;
|
||||
char isunion;
|
||||
int align;
|
||||
uint64_t size;
|
||||
uint nunion;
|
||||
struct Field {
|
||||
enum {
|
||||
FEnd,
|
||||
Fb,
|
||||
Fh,
|
||||
Fw,
|
||||
Fl,
|
||||
Fs,
|
||||
Fd,
|
||||
FPad,
|
||||
FTyp,
|
||||
} type;
|
||||
uint len; /* or index in typ[] for FTyp */
|
||||
} (*fields)[NField+1];
|
||||
};
|
||||
|
||||
struct Dat {
|
||||
enum {
|
||||
DStart,
|
||||
DEnd,
|
||||
DB,
|
||||
DH,
|
||||
DW,
|
||||
DL,
|
||||
DZ
|
||||
} type;
|
||||
char *name;
|
||||
Lnk *lnk;
|
||||
union {
|
||||
int64_t num;
|
||||
double fltd;
|
||||
float flts;
|
||||
char *str;
|
||||
struct {
|
||||
char *name;
|
||||
int64_t off;
|
||||
} ref;
|
||||
} u;
|
||||
char isref;
|
||||
char isstr;
|
||||
};
|
||||
|
||||
/* main.c */
|
||||
extern Target T;
|
||||
extern char debug['Z'+1];
|
||||
|
||||
/* util.c */
|
||||
typedef enum {
|
||||
PHeap, /* free() necessary */
|
||||
PFn, /* discarded after processing the function */
|
||||
} Pool;
|
||||
|
||||
extern Typ *typ;
|
||||
extern Ins insb[NIns], *curi;
|
||||
uint32_t hash(char *);
|
||||
void die_(char *, char *, ...) __attribute__((noreturn));
|
||||
void *emalloc(size_t);
|
||||
void *alloc(size_t);
|
||||
void freeall(void);
|
||||
void *vnew(ulong, size_t, Pool);
|
||||
void vfree(void *);
|
||||
void vgrow(void *, ulong);
|
||||
void strf(char[NString], char *, ...);
|
||||
uint32_t intern(char *);
|
||||
char *str(uint32_t);
|
||||
int argcls(Ins *, int);
|
||||
int isreg(Ref);
|
||||
int iscmp(int, int *, int *);
|
||||
void emit(int, int, Ref, Ref, Ref);
|
||||
void emiti(Ins);
|
||||
void idup(Ins **, Ins *, ulong);
|
||||
Ins *icpy(Ins *, Ins *, 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 *);
|
||||
int symeq(Sym, Sym);
|
||||
Ref newcon(Con *, Fn *);
|
||||
Ref getcon(int64_t, Fn *);
|
||||
int addcon(Con *, Con *, int);
|
||||
void salloc(Ref, Ref, Fn *);
|
||||
void dumpts(BSet *, Tmp *, FILE *);
|
||||
void runmatch(uchar *, Num *, Ref, Ref *);
|
||||
|
||||
void bsinit(BSet *, uint);
|
||||
void bszero(BSet *);
|
||||
uint bscount(BSet *);
|
||||
void bsset(BSet *, uint);
|
||||
void bsclr(BSet *, uint);
|
||||
void bscopy(BSet *, BSet *);
|
||||
void bsunion(BSet *, BSet *);
|
||||
void bsinter(BSet *, BSet *);
|
||||
void bsdiff(BSet *, BSet *);
|
||||
int bsequal(BSet *, BSet *);
|
||||
int bsiter(BSet *, int *);
|
||||
|
||||
static inline int
|
||||
bshas(BSet *bs, uint elt)
|
||||
{
|
||||
assert(elt < bs->nt * NBit);
|
||||
return (bs->t[elt/NBit] & BIT(elt%NBit)) != 0;
|
||||
}
|
||||
|
||||
/* parse.c */
|
||||
extern Op optab[NOp];
|
||||
void parse(FILE *, char *, void (char *), void (Dat *), void (Fn *));
|
||||
void printfn(Fn *, FILE *);
|
||||
void printref(Ref, Fn *, FILE *);
|
||||
void err(char *, ...) __attribute__((noreturn));
|
||||
|
||||
/* abi.c */
|
||||
void elimsb(Fn *);
|
||||
|
||||
/* cfg.c */
|
||||
Blk *newblk(void);
|
||||
void edgedel(Blk *, Blk **);
|
||||
void fillpreds(Fn *);
|
||||
void fillrpo(Fn *);
|
||||
void filldom(Fn *);
|
||||
int sdom(Blk *, Blk *);
|
||||
int dom(Blk *, Blk *);
|
||||
void fillfron(Fn *);
|
||||
void loopiter(Fn *, void (*)(Blk *, Blk *));
|
||||
void fillloop(Fn *);
|
||||
void simpljmp(Fn *);
|
||||
|
||||
/* mem.c */
|
||||
void promote(Fn *);
|
||||
void coalesce(Fn *);
|
||||
|
||||
/* alias.c */
|
||||
void fillalias(Fn *);
|
||||
void getalias(Alias *, Ref, Fn *);
|
||||
int alias(Ref, int, int, Ref, int, int *, Fn *);
|
||||
int escapes(Ref, Fn *);
|
||||
|
||||
/* load.c */
|
||||
int loadsz(Ins *);
|
||||
int storesz(Ins *);
|
||||
void loadopt(Fn *);
|
||||
|
||||
/* ssa.c */
|
||||
void filluse(Fn *);
|
||||
void ssa(Fn *);
|
||||
void ssacheck(Fn *);
|
||||
|
||||
/* copy.c */
|
||||
void copy(Fn *);
|
||||
|
||||
/* fold.c */
|
||||
void fold(Fn *);
|
||||
|
||||
/* simpl.c */
|
||||
void simpl(Fn *);
|
||||
|
||||
/* live.c */
|
||||
void liveon(BSet *, Blk *, Blk *);
|
||||
void filllive(Fn *);
|
||||
|
||||
/* spill.c */
|
||||
void fillcost(Fn *);
|
||||
void spill(Fn *);
|
||||
|
||||
/* rega.c */
|
||||
void rega(Fn *);
|
||||
|
||||
/* emit.c */
|
||||
void emitfnlnk(char *, Lnk *, FILE *);
|
||||
void emitdat(Dat *, FILE *);
|
||||
void emitdbgfile(char *, FILE *);
|
||||
void emitdbgloc(uint, uint, FILE *);
|
||||
int stashbits(void *, int);
|
||||
void elf_emitfnfin(char *, FILE *);
|
||||
void elf_emitfin(FILE *);
|
||||
void macho_emitfin(FILE *);
|
1
all.h
Symbolic link
1
all.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
qbe/all.h
|
20
libqbe.c
20
libqbe.c
|
@ -1,5 +1,4 @@
|
|||
#include "libqbe.h"
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -100,7 +99,7 @@ dbgfile(char *fn)
|
|||
}
|
||||
|
||||
const char*
|
||||
qbe_emit(Target target, const char* ssa)
|
||||
qbe_gen(Target target, const char* ssa)
|
||||
{
|
||||
T = target;
|
||||
FILE *inf = tmpfile();
|
||||
|
@ -127,3 +126,20 @@ qbe_emit(Target target, const char* ssa)
|
|||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
qbe_emit(const char* filename, const char* assembly) {
|
||||
char cc[255];
|
||||
snprintf(cc, 255, "cc -x assembler -o %s -", filename);
|
||||
|
||||
FILE* cc_pipe = popen(cc, "w");
|
||||
if(fputs(assembly, cc_pipe) == EOF) {
|
||||
perror("fputs");
|
||||
}
|
||||
pclose(cc_pipe);
|
||||
}
|
||||
|
||||
void
|
||||
qbe_gen_and_emit(Target target, const char* filename, const char* ssa) {
|
||||
qbe_emit(filename, qbe_gen(target, ssa));
|
||||
}
|
||||
|
|
8
libqbe.h
8
libqbe.h
|
@ -1,5 +1,5 @@
|
|||
#include "all.h"
|
||||
#include "config.h"
|
||||
#include "qbe/all.h"
|
||||
#include "qbe/config.h"
|
||||
|
||||
#ifndef __LIBQBE_H__
|
||||
#define __LIBQBE_H__
|
||||
|
@ -10,6 +10,8 @@ extern Target T_arm64;
|
|||
extern Target T_arm64_apple;
|
||||
extern Target T_rv64;
|
||||
|
||||
const char* qbe_emit(Target target, const char* ssa);
|
||||
const char* qbe_gen(Target target, const char* ssa);
|
||||
void qbe_emit(const char* filename, const char* assembly);
|
||||
void qbe_gen_and_emit(Target target, const char* filename, const char* ssa);
|
||||
|
||||
#endif
|
||||
|
|
199
ops.h
199
ops.h
|
@ -1,199 +0,0 @@
|
|||
#ifndef X /* amd64 */
|
||||
#define X(NMemArgs, SetsZeroFlag, LeavesFlags)
|
||||
#endif
|
||||
|
||||
#ifndef V /* riscv64 */
|
||||
#define V(Imm)
|
||||
#endif
|
||||
|
||||
#ifndef P
|
||||
#define P(CanFold, HasId, IdVal)
|
||||
#endif
|
||||
|
||||
|
||||
#define T(a,b,c,d,e,f,g,h) { \
|
||||
{[Kw]=K##a, [Kl]=K##b, [Ks]=K##c, [Kd]=K##d}, \
|
||||
{[Kw]=K##e, [Kl]=K##f, [Ks]=K##g, [Kd]=K##h} \
|
||||
}
|
||||
|
||||
|
||||
/*********************/
|
||||
/* PUBLIC OPERATIONS */
|
||||
/*********************/
|
||||
|
||||
/* Arithmetic and Bits */
|
||||
O(add, T(w,l,s,d, w,l,s,d), P(1,1,0)) X(2,1,0) V(1)
|
||||
O(sub, T(w,l,s,d, w,l,s,d), P(1,1,0)) X(2,1,0) V(0)
|
||||
O(neg, T(w,l,s,d, x,x,x,x), P(1,0,0)) X(1,1,0) V(0)
|
||||
O(div, T(w,l,s,d, w,l,s,d), P(1,1,1)) X(0,0,0) V(0)
|
||||
O(rem, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(0,0,0) V(0)
|
||||
O(udiv, T(w,l,e,e, w,l,e,e), P(1,1,1)) X(0,0,0) V(0)
|
||||
O(urem, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(0,0,0) V(0)
|
||||
O(mul, T(w,l,s,d, w,l,s,d), P(1,1,1)) X(2,0,0) V(0)
|
||||
O(and, T(w,l,e,e, w,l,e,e), P(1,0,0)) X(2,1,0) V(1)
|
||||
O(or, T(w,l,e,e, w,l,e,e), P(1,1,0)) X(2,1,0) V(1)
|
||||
O(xor, T(w,l,e,e, w,l,e,e), P(1,1,0)) X(2,1,0) V(1)
|
||||
O(sar, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1)
|
||||
O(shr, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1)
|
||||
O(shl, T(w,l,e,e, w,w,e,e), P(1,1,0)) X(1,1,0) V(1)
|
||||
|
||||
/* Comparisons */
|
||||
O(ceqw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cnew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csgew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csgtw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cslew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csltw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(1)
|
||||
O(cugew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cugtw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(culew, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cultw, T(w,w,e,e, w,w,e,e), P(1,0,0)) X(0,1,0) V(1)
|
||||
|
||||
O(ceql, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cnel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csgel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csgtl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cslel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(csltl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(1)
|
||||
O(cugel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cugtl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(culel, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cultl, T(l,l,e,e, l,l,e,e), P(1,0,0)) X(0,1,0) V(1)
|
||||
|
||||
O(ceqs, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cges, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cgts, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cles, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(clts, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cnes, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cos, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cuos, T(s,s,e,e, s,s,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
|
||||
O(ceqd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cged, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cgtd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cled, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cltd, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cned, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cod, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
O(cuod, T(d,d,e,e, d,d,e,e), P(1,0,0)) X(0,1,0) V(0)
|
||||
|
||||
/* Memory */
|
||||
O(storeb, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(storeh, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(storew, T(w,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(storel, T(l,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(stores, T(s,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(stored, T(d,e,e,e, m,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
|
||||
O(loadsb, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(loadub, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(loadsh, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(loaduh, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(loadsw, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(loaduw, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(load, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,1) V(0)
|
||||
|
||||
/* Extensions and Truncations */
|
||||
O(extsb, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(extub, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(extsh, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(extuh, T(w,w,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(extsw, T(e,w,e,e, e,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(extuw, T(e,w,e,e, e,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
|
||||
O(exts, T(e,e,e,s, e,e,e,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(truncd, T(e,e,d,e, e,e,x,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(stosi, T(s,s,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(stoui, T(s,s,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(dtosi, T(d,d,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(dtoui, T(d,d,e,e, x,x,e,e), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(swtof, T(e,e,w,w, e,e,x,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(uwtof, T(e,e,w,w, e,e,x,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(sltof, T(e,e,l,l, e,e,x,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(ultof, T(e,e,l,l, e,e,x,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
O(cast, T(s,d,w,l, x,x,x,x), P(1,0,0)) X(0,0,1) V(0)
|
||||
|
||||
/* Stack Allocation */
|
||||
O(alloc4, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(alloc8, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(alloc16, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
|
||||
/* Variadic Function Helpers */
|
||||
O(vaarg, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(vastart, T(m,e,e,e, x,e,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
|
||||
O(copy, T(w,l,s,d, x,x,x,x), P(0,0,0)) X(0,0,1) V(0)
|
||||
|
||||
/* Debug */
|
||||
O(dbgloc, T(w,e,e,e, w,e,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
|
||||
/****************************************/
|
||||
/* INTERNAL OPERATIONS (keep nop first) */
|
||||
/****************************************/
|
||||
|
||||
/* Miscellaneous and Architecture-Specific Operations */
|
||||
O(nop, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(addr, T(m,m,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(blit0, T(m,e,e,e, m,e,e,e), P(0,0,0)) X(0,1,0) V(0)
|
||||
O(blit1, T(w,e,e,e, x,e,e,e), P(0,0,0)) X(0,1,0) V(0)
|
||||
O(swap, T(w,l,s,d, w,l,s,d), P(0,0,0)) X(1,0,0) V(0)
|
||||
O(sign, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(salloc, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(xidiv, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(1,0,0) V(0)
|
||||
O(xdiv, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(1,0,0) V(0)
|
||||
O(xcmp, T(w,l,s,d, w,l,s,d), P(0,0,0)) X(1,1,0) V(0)
|
||||
O(xtest, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(1,1,0) V(0)
|
||||
O(acmp, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(acmn, T(w,l,e,e, w,l,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(afcmp, T(e,e,s,d, e,e,s,d), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(reqz, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(rnez, T(w,l,e,e, x,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
|
||||
/* Arguments, Parameters, and Calls */
|
||||
O(par, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(parsb, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(parub, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(parsh, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(paruh, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(parc, T(e,x,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(pare, T(e,x,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(arg, T(w,l,s,d, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(argsb, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(argub, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(argsh, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(arguh, T(w,e,e,e, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(argc, T(e,x,e,e, e,l,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(arge, T(e,l,e,e, e,x,e,e), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(argv, T(x,x,x,x, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
O(call, T(m,m,m,m, x,x,x,x), P(0,0,0)) X(0,0,0) V(0)
|
||||
|
||||
/* Flags Setting */
|
||||
O(flagieq, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagine, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagisge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagisgt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagisle, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagislt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagiuge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagiugt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagiule, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagiult, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfeq, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfge, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfgt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfle, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagflt, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfne, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfo, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
O(flagfuo, T(x,x,e,e, x,x,e,e), P(0,0,0)) X(0,0,1) V(0)
|
||||
|
||||
|
||||
#undef T
|
||||
#undef X
|
||||
#undef V
|
||||
#undef O
|
||||
|
||||
/*
|
||||
| column -t -o ' '
|
||||
*/
|
1
ops.h
Symbolic link
1
ops.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
qbe/ops.h
|
Loading…
Add table
Reference in a new issue