diff options
| -rw-r--r-- | ir.c | 24 | ||||
| -rw-r--r-- | ir.h | 13 | ||||
| -rw-r--r-- | irdump.c | 57 | ||||
| -rw-r--r-- | parse.c | 6 | ||||
| -rw-r--r-- | test/hello.c | 5 | ||||
| -rw-r--r-- | test/test.c (renamed from test.c) | 0 | ||||
| -rw-r--r-- | test/test2.c (renamed from test2.c) | 0 |
7 files changed, 85 insertions, 20 deletions
@@ -4,12 +4,12 @@ uchar type2cls[NTYPETAG]; uchar cls2siz[KF8+1]; const uchar siz2intcls[] = { [1] = KI4, [2] = KI4, [4] = KI4, [8] = KI8 }; -static vec_of(struct irdat) dats; struct instr instrtab[1<<14]; static int ninstr; static int instrfreelist; struct calltab calltab; struct phitab phitab; +struct dattab dattab; void irinit(struct function *fn) @@ -59,14 +59,6 @@ addcon(const struct xcon *con) } } -/* union ref -adddat(struct function *fn, const struct irdat *dat) -{ - assert(dats.n < 1u<<29); - vpush(&dats, *dat); - return mkref(RDAT, dats.n - 1); -} */ - static void targwrite2(uchar *d, ushort x) { @@ -163,6 +155,19 @@ mksymref(struct function *fn, const char *s) return mkref(RXCON, addcon(&con)); } +union ref +mkdatref(struct function *fn, uint siz, uint align, const void *bytes, uint n) +{ + struct irdat dat = { align, 0, siz }; + if (siz <= 8) memcpy(dat.sdat, bytes, n < siz ? n : siz); + else { + while (((uchar *)bytes)[n-1] == 0) --n; /* nip trailing zeroes */ + vpushn(&dat.dat, bytes, n); + } + vpush(&dattab, dat); + return mkref(RDAT, dattab.n - 1); +} + struct instr mkalloca(uint siz, uint align) { @@ -220,6 +225,7 @@ insertinstr(struct block *blk, int idx, struct instr ins) else { assert(idx >= 0 && idx < blk->ins.n); vpush_((void **)&blk->ins.p, &blk->ins._cap, &blk->ins.n, sizeof *blk->ins.p); + vresize(&blk->ins, blk->ins.n); for (int i = blk->ins.n++; i > idx; --i) blk->ins.p[i] = blk->ins.p[i - 1]; blk->ins.p[idx] = new; @@ -65,12 +65,13 @@ struct phi { enum refkind { RNONE, - RTMP, /* reference to another instruction's result */ - RPARAM, /* function param */ - RICON, /* small integer constants */ - RXCON, /* other constants (incl. external symbols) */ + RTMP, /* reference to another instruction's result */ + RPARAM, /* function param */ + RICON, /* small integer constants */ + RXCON, /* other constants (incl. external symbols) */ + RDAT, /* reference to irdat */ RMORE, /* reference to extra data for Ocall and Ophi */ - RREG, /* machine register */ + RREG, /* machine register */ }; union ref { @@ -163,6 +164,7 @@ extern const uchar siz2intcls[]; extern struct instr instrtab[]; extern struct calltab {vec_of(struct call);} calltab; extern struct phitab {vec_of(struct phi);} phitab; +extern struct dattab {vec_of(struct irdat);} dattab; #define NOREF ((union ref) {0}) #define mkref(t, x) ((union ref) {{ (t), (x) }}) #define mkzerocon() ((union ref) {{ RICON, 0 }}) @@ -173,6 +175,7 @@ union irtype mkirtype(union type); union ref mkintcon(struct function *, enum irclass, vlong); union ref mkfltcon(struct function *, enum irclass, double); union ref mksymref(struct function *, const char *); +union ref mkdatref(struct function *, uint siz, uint align, const void *, uint n); struct instr mkalloca(uint siz, uint align); void conputdat(struct irdat *, uint off, enum typetag t, const void *dat); union ref mkcallarg(struct function *, bool sret, uint narg, int vararg, union ref *, union irtype *); @@ -1,6 +1,49 @@ #include "ir.h" extern struct xcon conht[]; +static int nextdat; + +#define aisprint(c) in_range(c, ' ', '~') + +static void +pridat(const struct irdat *dat) +{ + efmt("dat ^%d(align %d, size %d):\n\t", dat - dattab.p, dat->align, dat->siz); + assert(!dat->syms); + if (dat->siz <= 8) { + efmt("b "); + for (int i = 0; i < dat->siz; ++i) + efmt("%d,", dat->sdat[i]); + } else { + enum { + MINZERO = 4, + MAXLINE = 60, + }; + int npri = 0; + int nzero = dat->siz - dat->dat.n; + int strbegin = 0, nstr = 0; + for (int i = 0; i < dat->dat.n + (nzero & -(nzero <= MINZERO)); ++i) { + int c = i < dat->dat.n ? dat->dat.p[i] : 0; + if (npri > MAXLINE) { + npri = 0; + efmt("\n\t"); + } + if (aisprint(c)) { + if (!nstr++) strbegin = i; + } else { + if (nstr) { + npri += efmt("asc %'S,", dat->dat.p+strbegin, nstr); + nstr = 0; + efmt("b "); + } + npri += efmt("%d,", c); + } + } + if (nstr) npri += efmt("asc %'S,", dat->dat.p+strbegin, nstr); + if ((nzero -= MINZERO) > 0) efmt("z %d", nzero); + } + efmt("\n"); +} static const char *clsname[] = { "?", "i4", "i8", "ptr", "f4", "f8" @@ -51,6 +94,9 @@ dumpref(enum op o, union ref ref) default: assert(0); } break; + case RDAT: + efmt("$^%d", ref.i); + break; case RMORE: if (o == Ocall || o == Ointrin) { struct call *call = &calltab.p[ref.idx]; @@ -74,7 +120,7 @@ dumpref(enum op o, union ref ref) struct phi *phi = &phitab.p[ref.idx]; for (int i = 0; i < phi->n; ++i) { if (i > 0) efmt(", "); - efmt("[.L%d ", phi->blk[i]->id); + efmt("[@%d ", phi->blk[i]->id); dumpref(0, phi->ref[i]); efmt("]"); } @@ -120,7 +166,7 @@ dumpblk(struct function *fn, struct block *blk) { static const char *jnames[] = { 0, "b", "ret" }; int i; - efmt(" .L%d:\n", blk->id); + efmt(" @%d:\n", blk->id); for (i = 0; i < blk->phi.n; ++i) { dumpinst(&instrtab[blk->phi.p[i]]); } @@ -138,8 +184,8 @@ dumpblk(struct function *fn, struct block *blk) dumpref(0, blk->jmp.arg[i]); } if (i && blk->s1) efmt(", "); - if (blk->s1 && blk->s2) efmt(".L%d, .L%d", blk->s1->id, blk->s2->id); - else if (blk->s1) efmt(".L%d", blk->s1->id); + if (blk->s1 && blk->s2) efmt("@%d, @%d", blk->s1->id, blk->s2->id); + else if (blk->s1) efmt("@%d", blk->s1->id); efmt("\n"); } @@ -148,6 +194,9 @@ irdump(struct function *fn, const char *fname) { struct block *blk; + /* print datas that have never been printed before */ + while (nextdat < dattab.n) pridat(&dattab.p[nextdat++]); + efmt("function %s : %ty\n", fname, fn->fnty); if (fn->abiarg || fn->nabiret) { efmt("abi: ("); @@ -977,7 +977,6 @@ exprvalue(struct function *fn, const struct expr *ex) { return compileexpr(fn, ex, /*discard*/ 0); } - static inline void expreffects(struct function *fn, const struct expr *ex) { @@ -1025,6 +1024,8 @@ expraddr(struct function *fn, const struct expr *ex) assert(0); } break; + case ESTRLIT: + return mkdatref(fn, ex->s.n+1, /*align*/ 1, ex->s.p, ex->s.n); case EDEREF: return exprvalue(fn, ex->sub); case EGETF: @@ -1352,7 +1353,8 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard) sub = ex->sub; if (ex->ty.t != TYVOID && !isscalar(ex->ty)) - /* fn & array designators evaluate to their address; so do aggregates for the purpose of code generation */ + /* fn & array designators evaluate to their address; + * so do aggregates for the purpose of code generation */ return expraddr(fn, ex); switch (ex->t) { case ENUMLIT: diff --git a/test/hello.c b/test/hello.c new file mode 100644 index 0000000..98a93a0 --- /dev/null +++ b/test/hello.c @@ -0,0 +1,5 @@ +int printf(const char *, ...); + +int main() { + printf("hello world\n"); +} |