aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--abi0.c12
-rw-r--r--c.c27
-rw-r--r--intrin.c3
-rw-r--r--test/test2.c5
4 files changed, 36 insertions, 11 deletions
diff --git a/abi0.c b/abi0.c
index 4973b86..82d10a5 100644
--- a/abi0.c
+++ b/abi0.c
@@ -171,7 +171,7 @@ patcharg(struct block *blk, int *icall, struct call *call,
temp = insertinstr(blk, arginst++, ins);
insertinstr(blk, arginst++, mkarginstr(abi[i].ty, temp));
}
- *icall += arginst - (call->narg - argidx);
+ *icall = arginst + (call->narg - argidx - 1);
return nabi;
}
} else /* normal scalar argument */
@@ -196,13 +196,11 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi)
nret = abiret(call->abiret, &abiargs, &ni, call->ret);
if (call->ret.isagg) { /* adjust struct return */
union irtype retty = call->ret;
- struct instr alloca = { .cls = KPTR };
struct typedata *td = &typedata[retty.dat];
- int ialloca ;
+ struct instr alloca = mkalloca(td->siz, td->align);
+ int ialloca;
sretarghidden = ni == 0;
- alloca.op = Oalloca8 + (td->align == 16);
- alloca.l = mkref(RICON, td->align == 16 ? 1 : td->siz / 8);
/* swap alloca and call temps so users of original call point to alloca */
retmem = insertinstr(blk, ialloca = (*curi)++ - call->narg, *ins);
*ins = alloca;
@@ -218,7 +216,9 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi)
/* adjust args */
for (int i = 0, i2 = ni + sretarghidden; i < call->narg; ++i) {
- union irtype pty = ref2type(instrtab[blk->ins.p[*curi - call->narg + i]].l);
+ int arginst = *curi - (call->narg - i);
+ struct instr *arg = &instrtab[blk->ins.p[arginst]];
+ union irtype pty = ref2type(arg->l);
int first = abiargs.n;
int ret = abiarg(&abiargs, &ni, &nf, &ns, pty);
ret = patcharg(blk, curi, call, i, ret, &abiargs.p[first]);
diff --git a/c.c b/c.c
index 03a308f..26765a2 100644
--- a/c.c
+++ b/c.c
@@ -677,6 +677,9 @@ tkprec(int tt)
return ((uint)tt < arraylength(bintab)) ? bintab[tt].prec : 0;
}
+static struct expr initializer(struct comp *cm, union type *ty, enum evalmode ev,
+ bool globl, enum qualifier qual, const char *name);
+
/* parse an expression with the given operator precedence */
/* param ident is a kludge to support block labels without backtracking or extra lookahead
* see stmt() */
@@ -767,6 +770,13 @@ Unary:
struct decl decl = pdecl(&st, cm);
expect(cm, ')', NULL);
assert(decl.ty.t);
+ if ((isagg(decl.ty) || decl.ty.t == TYARRAY) && peek(cm, NULL) == '{') {
+ if (ccopt.cstd < STDC99)
+ warn(&tk.span, "compound literals are a c99 feature");
+ ex = initializer(cm, &decl.ty, (decl.scls & SCSTATIC) ? EVSTATICINI : EVFOLD,
+ /* globl */ 0, decl.qual, NULL);
+ break;
+ }
unops[nunop].span = tk.span;
unops[nunop].ty = decl.ty;
if (++nunop >= arraylength(unops)) {
@@ -1545,7 +1555,6 @@ initializer(struct comp *cm, union type *ty, enum evalmode ev, bool globl,
assert(arraylength(res.zero) == 1);
siz = typesize(*ty);
- memset(res.zero, 0xFF, sizeof res.zero);
if (siz && siz <= 64)
res.zero->u &= ~0ull >> (64 - siz);
@@ -2411,6 +2420,8 @@ mkhiddensym(const char *fnname, const char *name, int id)
return intern(buf);
}
+static void geninit(struct function *fn, union type t, union ref dst, const struct expr *src);
+
static union ref
expraddr(struct function *fn, const struct expr *ex)
{
@@ -2460,6 +2471,11 @@ expraddr(struct function *fn, const struct expr *ex)
case ECALL:
assert(isagg(ex->ty));
return compilecall(fn, ex);
+ case EINIT:
+ /* compound literal, allocate temp */
+ r = addinstr(fn, mkalloca(typesize(ex->ty), typealign(ex->ty)));
+ geninit(fn, ex->ty, r, ex);
+ return r;
default:
assert(!"lvalue?>");
}
@@ -3643,7 +3659,8 @@ localdecl(struct comp *cm, struct function *fn, bool forini)
goto Err;
}
EMITS {
- decl.id = addinstr(fn, mkalloca(typesize(decl.ty), typealign(decl.ty))).i;
+ /*actual alloca filled in later (for inferred array size decls)*/
+ decl.id = addinstr(fn, mkinstr(Oalloca1, KPTR, mkref(RICON, -1))).i;
}
Initz:
if (st.varini) {
@@ -3659,7 +3676,7 @@ localdecl(struct comp *cm, struct function *fn, bool forini)
if (!statik) {
/* fix alloca for actual size, for implicitly sized arrays */
assert(!isincomplete(d->ty));
- instrtab[decl.id].l.i = typesize(d->ty);
+ instrtab[decl.id] = mkalloca(typesize(d->ty), typealign(d->ty));
if (!initcheck(d->ty, &ini)) {
struct span span = decl.span;
@@ -3668,8 +3685,10 @@ localdecl(struct comp *cm, struct function *fn, bool forini)
d->ty, ini.ty);
}
EMITS {
- if (isagg(d->ty) || d->ty.t == TYARRAY)
+ if (ini.t == EINIT || ini.t == ESTRLIT)
geninit(fn, d->ty, mkref(RTMP, decl.id), &ini);
+ else if (isagg(d->ty))
+ structcopy(fn, d->ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
else
genstore(fn, d->ty, mkref(RTMP, decl.id), exprvalue(fn, &ini));
}
diff --git a/intrin.c b/intrin.c
index 70928d4..b7fefec 100644
--- a/intrin.c
+++ b/intrin.c
@@ -69,8 +69,9 @@ lowerintrin(struct function *fn)
else
abi0_call(fn, ins, blk, &i);
vinit(&args, argsbuf, arraylength(argsbuf));
- } else if (ins->op != Omove) assert(args.n == 0);
+ }
}
+ assert(args.n == 0);
} while ((blk = blk->lnext) != fn->entry);
}
diff --git a/test/test2.c b/test/test2.c
index fec9b14..26def98 100644
--- a/test/test2.c
+++ b/test/test2.c
@@ -24,3 +24,8 @@ short s(int a, int b) {
int i() {
return s(1,2);
}
+
+double v2v2() {
+ v2d x = add((v2d){1,2}, (v2d){3,4});
+ return x.x+x.y;
+}