diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2021-10-18 21:04:10 +0200 |
---|---|---|
committer | Quentin Carbonneaux <quentin@c9x.me> | 2021-10-22 23:53:25 +0200 |
commit | fcdef10dae54d7124aca9ccbefe53baa8e67267d (patch) | |
tree | 1215b60f1f3a31d38ee37228dd37bcc4a6a61f99 /parse.c | |
parent | 9858a12730717d9c5e5deec4264d7041d75fc947 (diff) | |
download | roux-fcdef10dae54d7124aca9ccbefe53baa8e67267d.tar.gz |
make variadic args explicit
Some abis, like the riscv one, treat arguments differently depending on whether they are variadic or not. To prepare for the upcomming riscv target, we change the variadic call syntax and give meaning to the location of the '...' marker. # new syntax %ret =w call $f(w %regular, ..., w %variadic) By nature of their abis, the change is backwards compatible for existing targets.
Diffstat (limited to 'parse.c')
-rw-r--r-- | parse.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/parse.c b/parse.c index da88f58..104ca1d 100644 --- a/parse.c +++ b/parse.c @@ -450,25 +450,44 @@ parsecls(int *tyn) static int parserefl(int arg) { - int k, ty, env, hasenv; + int k, ty, env, hasenv, vararg; Ref r; hasenv = 0; + vararg = 0; expect(Tlparen); - while (peek() != Trparen && peek() != Tdots) { + while (peek() != Trparen) { if (curi - insb >= NIns) err("too many instructions (1)"); - env = peek() == Tenv; - if (env) { + if (!arg && vararg) + err("no parameters allowed after '...'"); + switch (peek()) { + case Tdots: + if (vararg) + err("only one '...' allowed"); + vararg = 1; + if (arg) { + *curi = (Ins){.op = Oargv}; + curi++; + } + next(); + goto Next; + case Tenv: + if (hasenv) + err("only one environment allowed"); + hasenv = 1; + env = 1; next(); k = Kl; - } else + break; + default: + env = 0; k = parsecls(&ty); + break; + } r = parseref(); if (req(r, R)) err("invalid argument"); - if (hasenv && env) - err("only one environment allowed"); if (!arg && rtype(r) != RTmp) err("invalid function parameter"); if (k == 4) @@ -487,16 +506,13 @@ parserefl(int arg) else *curi = (Ins){Opar, k, r, {R}}; curi++; - hasenv |= env; + Next: if (peek() == Trparen) break; expect(Tcomma); } - if (next() == Tdots) { - expect(Trparen); - return 1; - } - return 0; + expect(Trparen); + return vararg; } static Blk * @@ -621,10 +637,8 @@ DoOp: } if (op == Tcall) { arg[0] = parseref(); - if (parserefl(1)) - op = Ovacall; - else - op = Ocall; + parserefl(1); + op = Ocall; expect(Tnl); if (k == 4) { k = Kl; |