aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--abi0.c29
-rw-r--r--irdump.c4
-rw-r--r--parse.c7
-rw-r--r--test.c7
4 files changed, 31 insertions, 16 deletions
diff --git a/abi0.c b/abi0.c
index 2703713..2684e39 100644
--- a/abi0.c
+++ b/abi0.c
@@ -291,29 +291,28 @@ abi0(struct function *fn)
int thisi = sretarghidden + ni + nf + ns;
int first = abiargs.n;
int ret = abiarg(&abiargs, &ni, &nf, &ns, pty);
+ union ref argss[2];
+ union irtype typss[2];
+ ret = patcharg(argss, typss, blk, &iinstr, call, i, ret, &abiargs.p[first]);
if (structbyval) {
- union ref argss[2];
- union irtype typss[2];
- assert(structbyval);
- ret = patcharg(argss, typss, blk, &iinstr, call, i, ret, &abiargs.p[first]);
vpushn(&newargs, argss, ret);
vpushn(&newtyps, typss, ret);
- if (call->vararg == i)
- vararg = thisi;
}
+ if (call->vararg == i)
+ vararg = thisi;
}
call->sret = 0;
call->vararg = vararg;
- if (structbyval) {
- if (newargs.n != call->narg) {
- call->args = alloc(&fn->arena, newargs.n * (sizeof *newargs.p + sizeof *newtyps.p), 0);
- call->typs = (union irtype *)((char *)call->args + newargs.n * sizeof *newargs.p);
- }
- memcpy(call->args, newargs.p, newargs.n * sizeof *call->args);
- memcpy(call->typs, newtyps.p, newtyps.n * sizeof *call->typs);
- call->abiargregs = alloc(&fn->arena, abiargs.n * sizeof *call->abiargregs, 0);
- for (int i = 0; i < abiargs.n; ++i) call->abiargregs[i] = abiargs.p[i].reg;
+ if (structbyval && newargs.n != call->narg) {
+ call->args = alloc(&fn->arena, newargs.n * (sizeof *newargs.p + sizeof *newtyps.p), 0);
+ call->typs = (union irtype *)((char *)call->args + newargs.n * sizeof *newargs.p);
}
+ memcpy(call->typs, newtyps.p, newtyps.n * sizeof *call->typs);
+ if (structbyval)
+ memcpy(call->args, newargs.p, newargs.n * sizeof *call->args);
+ call->abiargregs = alloc(&fn->arena, abiargs.n * sizeof *call->abiargregs, 0);
+ for (int i = 0; i < abiargs.n; ++i) call->abiargregs[i] = abiargs.p[i].reg;
+ call->narg = abiargs.n;
vfree(&abiargs);
vfree(&newargs);
vfree(&newtyps);
diff --git a/irdump.c b/irdump.c
index 4ff3f61..27f3edc 100644
--- a/irdump.c
+++ b/irdump.c
@@ -63,6 +63,10 @@ dumpref(enum op o, union ref ref)
if (i > 0 || call->sret) efmt(", ");
if (call->vararg == i)
efmt("..., ");
+ if (call->abiargregs) {
+ short r = call->abiargregs[i];
+ efmt("(%ls) ", r != -1 ? mctarg->rnames[r] : "<stk>");
+ }
prityp(call->typs[i]);
efmt(" ");
dumpref(0, call->args[i]);
diff --git a/parse.c b/parse.c
index dc6717b..9a5d99a 100644
--- a/parse.c
+++ b/parse.c
@@ -1763,7 +1763,12 @@ block(struct parser *pr, struct function *fn)
error(&span, "cannot initialize '%ty' variable with '%ty'",
decl.ty, ini.ty);
}
- EMITS genstore(fn, decl.ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
+ EMITS {
+ if (isagg(decl.ty))
+ structcopy(fn, mkref(RTMP, decl.id), &ini);
+ else
+ genstore(fn, decl.ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
+ }
}
break;
case SCTYPEDEF: break;
diff --git a/test.c b/test.c
index 670c7c6..6d1063e 100644
--- a/test.c
+++ b/test.c
@@ -51,6 +51,13 @@ void silly(struct pair *p, struct quad *q)
*q = quad(1,2,3,4);
}
+void test2(struct big *b) {
+ struct big s = *b;
+ extern void h(int, struct big, float);
+ s.x[5] += 2;
+ h(0, s, 0);
+}
+
struct f2 { float f,g; };
struct f2 f2test(struct f2 *r) {
return *r;