aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--common.h2
-rw-r--r--mem.c8
-rw-r--r--parse.c26
-rw-r--r--regalloc.c2
-rw-r--r--test.c6
-rw-r--r--test2.c15
6 files changed, 45 insertions, 14 deletions
diff --git a/common.h b/common.h
index 0bdd21a..6246f02 100644
--- a/common.h
+++ b/common.h
@@ -315,6 +315,7 @@ void freearena(struct arena *);
void vinit_(void **p, int *pcap, void *inlbuf, int cap, uint siz);
void vpush_(void **p, int *pcap, uint *pn, uint siz);
void *vpushn_(void **p, int *pcap, uint *pn, uint siz, const void *dat, uint ndat);
+void vresize_(void **p, int *pcap, uint *pn, uint siz, uint N);
extern void free(void *);
#define VINIT(inlbuf, Cap) { (inlbuf), (Cap) }
#define vfree(v) ((v)->_cap < 0 ? free((v)->p) : (void)0, memset((v), 0, sizeof*(v)))
@@ -322,6 +323,7 @@ extern void free(void *);
#define vpush(v, x) (vpush_((void **)&(v)->p, &(v)->_cap, &(v)->n, sizeof *(v)->p), \
(v)->p[(v)->n++] = (x))
#define vpushn(v, xs, N) vpushn_((void **)&(v)->p, &(v)->_cap, &(v)->n, sizeof *(v)->p, xs, N)
+#define vresize(v, N) vresize_((void **)&(v)->p, &(v)->_cap, &(v)->n, sizeof *(v)->p, N)
struct bitset { uvlong u; };
enum { BSNBIT = 8 * sizeof(uvlong) };
diff --git a/mem.c b/mem.c
index 07519d5..3a22a35 100644
--- a/mem.c
+++ b/mem.c
@@ -67,6 +67,14 @@ vpushn_(void **p, int *pcap, uint *pn, uint siz, const void *dat, uint ndat)
return beg;
}
+void
+vresize_(void **p, int *pcap, uint *pn, uint siz, uint N)
+{
+ while (*pcap < N)
+ vpush_(p, pcap, pn, siz);
+ *pn = N;
+}
+
struct arena *
newarena(uint chunksiz)
{
diff --git a/parse.c b/parse.c
index 9a5d99a..dc1b3e5 100644
--- a/parse.c
+++ b/parse.c
@@ -981,13 +981,12 @@ expreffects(struct function *fn, const struct expr *ex)
static void
-structcopy(struct function *fn, union ref dst, const struct expr *src)
+structcopy(struct function *fn, union type ty, union ref dst, union ref src)
{
- union ref srcref = expraddr(fn, src);
- union ref args[2] = { dst, srcref };
- union irtype typ[2] = { mkirtype(src->ty) };
- typ[1] = typ[0];
- addinstr(fn, mkintrin(fn, INstructcopy, 0, 2, args, typ));
+ union ref args[2] = { dst, src };
+ union irtype typs[2] = { mkirtype(ty) };
+ typs[1] = typs[0];
+ addinstr(fn, mkintrin(fn, INstructcopy, 0, 2, args, typs));
}
static union ref
@@ -1034,8 +1033,8 @@ expraddr(struct function *fn, const struct expr *ex)
return addinstr(fn, ins);
case ESET:
assert(isagg(ex->ty));
- r = expraddr(fn, &ex->sub[0]);
- structcopy(fn, r, &ex->sub[1]);
+ r = expraddr(fn, &ex->sub[1]);
+ structcopy(fn, ex->ty, expraddr(fn, &ex->sub[0]), r);
return r;
case ESEQ:
expreffects(fn, &ex->sub[0]);
@@ -1299,11 +1298,14 @@ compilecall(struct function *fn, const struct expr *ex)
ins.cls = type2cls[ex->ty.t];
}
ins.l = exprvalue(fn, &sub[0]);
- for (int i = 0; i < ex->narg; ++i) {
+ vresize(&args, ex->narg);
+ vresize(&typs, ex->narg);
+ /* backwards because of RTL call stack order */
+ for (int i = ex->narg - 1; i >= 0; --i) {
struct expr *arg = &sub[i+1];
union type ty = i < td->nmemb ? td->param[i] : argpromote(arg->ty);
- vpush(&args, cvt(fn, ty.t, arg->ty.t, exprvalue(fn, arg)));
- vpush(&typs, mkirtype(ty));
+ args.p[i] = cvt(fn, ty.t, arg->ty.t, exprvalue(fn, arg));
+ typs.p[i] = mkirtype(ty);
}
if (isagg(ex->ty))
vpush(&typs, mkirtype(ex->ty));
@@ -1765,7 +1767,7 @@ block(struct parser *pr, struct function *fn)
}
EMITS {
if (isagg(decl.ty))
- structcopy(fn, mkref(RTMP, decl.id), &ini);
+ structcopy(fn, decl.ty, mkref(RTMP, decl.id), expraddr(fn, &ini));
else
genstore(fn, decl.ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
}
diff --git a/regalloc.c b/regalloc.c
index 6200d0f..92d2b30 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -39,7 +39,7 @@ use(struct block *blk, enum op op, int hint, union ref *ref)
if (op == Ocall || op == Ointrin) {
struct call *call = &calltab.p[ref->idx];
for (int i = 0; i < call->narg; ++i)
- use(blk, 0, 0, &call->args[i]);
+ use(blk, 0, op == Ocall ? call->abiargregs[i] : -1, &call->args[i]);
} else if (op == Ophi) {
struct phi *phi = &phitab.p[ref->idx];
for (int i = 0; i < phi->n; ++i)
diff --git a/test.c b/test.c
index 6d1063e..388f9f7 100644
--- a/test.c
+++ b/test.c
@@ -69,7 +69,11 @@ void fill(char *p, int c, unsigned long n)
if (n) do t = *p++ = c; while (--n);
}
-main(t) { putc(t); }
+void zero(void *p, unsigned long n) { fill(p,0,n); }
+
+main(t) {
+ putc(t + 1, t + 2);
+}
//
diff --git a/test2.c b/test2.c
new file mode 100644
index 0000000..13ed47c
--- /dev/null
+++ b/test2.c
@@ -0,0 +1,15 @@
+typedef struct v2d { double x,y; } v2d;
+
+
+
+void addp(v2d *a, const v2d *b)
+{
+ a->x += b->x;
+ a->y += b->y;
+}
+
+v2d add(v2d a, v2d b)
+{
+ addp(&a, &b);
+ return a;
+}