diff options
| author | 2025-10-09 20:10:34 +0200 | |
|---|---|---|
| committer | 2025-10-09 20:10:34 +0200 | |
| commit | ba05bc9089248fc92a2fa12bace04c7f63649b9a (patch) | |
| tree | 9669be6a2fcf645735bb8e49a76da5e4e95c9d28 | |
| parent | 9df18e9b384a56902ef1517bc269b8c345149e12 (diff) | |
compound literals
| -rw-r--r-- | abi0.c | 12 | ||||
| -rw-r--r-- | c.c | 27 | ||||
| -rw-r--r-- | intrin.c | 3 | ||||
| -rw-r--r-- | test/test2.c | 5 |
4 files changed, 36 insertions, 11 deletions
@@ -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]); @@ -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)); } @@ -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; +} |