aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-05 10:28:57 +0200
committerlemon <lsof@mailbox.org>2023-06-05 10:58:35 +0200
commited47a54958f5bd48dc364d4a0f77f778768696bb (patch)
treec68f7b1426c198964b37238c6195f0569a15ab2b
parentefc0cf8039cbff5e0f0d52fd7414c7186129b6ac (diff)
strlits
-rw-r--r--ir.c24
-rw-r--r--ir.h13
-rw-r--r--irdump.c57
-rw-r--r--parse.c6
-rw-r--r--test/hello.c5
-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
diff --git a/ir.c b/ir.c
index cb4cc27..2f1c622 100644
--- a/ir.c
+++ b/ir.c
@@ -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;
diff --git a/ir.h b/ir.h
index a08bbce..4cce899 100644
--- a/ir.h
+++ b/ir.h
@@ -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 *);
diff --git a/irdump.c b/irdump.c
index aa815e4..1e5302e 100644
--- a/irdump.c
+++ b/irdump.c
@@ -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: (");
diff --git a/parse.c b/parse.c
index 4ed63c7..0dd984d 100644
--- a/parse.c
+++ b/parse.c
@@ -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");
+}
diff --git a/test.c b/test/test.c
index 40b59e6..40b59e6 100644
--- a/test.c
+++ b/test/test.c
diff --git a/test2.c b/test/test2.c
index 7d39164..7d39164 100644
--- a/test2.c
+++ b/test/test2.c