ref: 9e705ea43749bc219e15e7a4b934690a147dba90
parent: 14ec83e1ab97ee50e0f7686b390f8daba6ee34f9
author: Ori Bernstein <[email protected]>
date: Wed Jun 20 11:26:42 EDT 2012
Add support for returning structs.
--- a/8/asm.h
+++ b/8/asm.h
@@ -74,6 +74,7 @@
char *name;
int isglobl;
size_t stksz;
+ Type *type;
Htab *locs;
Node *ret;
Cfg *cfg;
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -30,7 +30,8 @@
/* return handling */
Node *endlbl;
- Node *retval;
+ Node *ret;
+ int isbigret;
/* pre/postinc handling */
Node **incqueue;
@@ -43,7 +44,6 @@
size_t argsz;
Htab *globls;
Htab *locs;
- Node *ret;
};
static Node *simp(Simp *s, Node *n);
@@ -197,6 +197,7 @@
sz = 0;
switch (t->type) {
case Tyvoid:
+ die("void has no size");
return 1;
case Tybool: case Tychar: case Tyint8:
case Tybyte: case Tyuint8:
@@ -252,23 +253,33 @@
return tysize(t);
}
-static Node *temp(Simp *simp, Node *e)
+static Node *gentemp(Simp *simp, Node *e, Type *ty, Node **dcl)
{
char buf[128];
static int nexttmp;
Node *t, *r, *n;
- assert(e->type == Nexpr);
snprintf(buf, 128, ".t%d", nexttmp++);
n = mkname(e->line, buf);
- t = mkdecl(e->line, n, e->expr.type);
- declarelocal(simp, t);
- r = mkexpr(e->line, Ovar, t, NULL);
+ t = mkdecl(e->line, n, ty);
+ r = mkexpr(e->line, Ovar, n, NULL);
r->expr.type = t->decl.type;
r->expr.did = t->decl.did;
+ if (dcl)
+ *dcl = t;
return r;
}
+static Node *temp(Simp *simp, Node *e)
+{
+ Node *t, *dcl;
+
+ assert(e->type == Nexpr);
+ t = gentemp(simp, e, e->expr.type, &dcl);
+ declarelocal(simp, dcl);
+ return t;
+}
+
static void jmp(Simp *s, Node *lbl)
{
append(s, mkexpr(lbl->line, Ojmp, lbl, NULL));
@@ -539,8 +550,12 @@
if (ispure(n)) {
r = n;
} else {
- r = temp(s, n);
- append(s, store(r, n));
+ if (exprtype(n)->type == Tyvoid) {
+ append(s, n);
+ } else {
+ r = temp(s, n);
+ append(s, store(r, n));
+ }
}
return r;
}
@@ -551,6 +566,7 @@
Node *t, *u, *v; /* temporary nodes */
Type *ty;
Node **args;
+ size_t i;
const Op fusedmap[] = {
[Oaddeq] = Oadd,
[Osubeq] = Osub,
@@ -659,11 +675,14 @@
r = n;
break;
case Oret:
- if (n->expr.args[0]) {
- if (s->ret)
- t = s->ret;
- else
- t = s->ret = temp(s, args[0]);
+ if (s->isbigret) {
+ t = rval(s, args[0]);
+ t = addr(t, exprtype(args[0]));
+ u = word(n->line, size(args[0]));
+ v = mkexpr(n->line, Oblit, s->ret, t, u, NULL);
+ append(s, v);
+ } else if (n->expr.args[0]) {
+ t = s->ret;
t = store(t, rval(s, args[0]));
append(s, t);
}
@@ -682,15 +701,16 @@
}
break;
case Ocall:
- if (size(n) > 4) {
+ if (exprtype(n)->type != Tyvoid && size(n) > 4) {
r = temp(s, n);
ty = mktyptr(n->line, exprtype(r));
linsert(&n->expr.args, &n->expr.nargs, 1, addr(r, exprtype(n)));
- linsert(&args[0]->expr.type->sub, &n->expr.type->nsub, 1, ty);
- args[0]->expr.type->sub[0] = tyvoid;
- n->expr.type = tyvoid;
+ for (i = 0; i < n->expr.nargs; i++)
+ n->expr.args[i] = rval(s, n->expr.args[i]);
+ append(s, n);
+ } else {
+ r = visit(s, n);
}
- r = visit(s, n);
break;
default:
r = visit(s, n);
@@ -769,6 +789,8 @@
static void reduce(Simp *s, Node *f)
{
+ Node *dcl;
+ Type *ty;
size_t i;
assert(f->type == Nfunc);
@@ -775,16 +797,25 @@
s->nstmts = 0;
s->stmts = NULL;
s->endlbl = genlbl();
- s->retval = NULL;
+ s->ret = NULL;
- if (f->type == Nfunc) {
- for (i = 0; i < f->func.nargs; i++) {
- declarearg(s, f->func.args[i]);
- }
- simp(s, f->func.body);
- } else {
- die("Got a non-func (%s) to reduce", nodestr(f->type));
+ assert(f->type == Nfunc);
+
+ ty = f->func.type->sub[0];
+ if (ty->type != Tyvoid && tysize(ty) > 4) {
+ s->isbigret = 1;
+ s->ret = gentemp(s, f, mktyptr(f->line, ty), &dcl);
+ declarearg(s, dcl);
+ } else if (ty->type != Tyvoid) {
+ s->isbigret = 0;
+ s->ret = gentemp(s, f, ty, &dcl);
+ declarelocal(s, dcl);
}
+
+ for (i = 0; i < f->func.nargs; i++) {
+ declarearg(s, f->func.args[i]);
+ }
+ simp(s, f->func.body);
append(s, s->endlbl);
}