diff options
| author | Quentin Carbonneaux <[email protected]> | 2021-10-18 21:04:10 +0200 |
|---|---|---|
| committer | Quentin Carbonneaux <[email protected]> | 2021-10-22 23:53:25 +0200 |
| commit | fcdef10dae54d7124aca9ccbefe53baa8e67267d (patch) | |
| tree | 1215b60f1f3a31d38ee37228dd37bcc4a6a61f99 /parse.c | |
| parent | 9858a12730717d9c5e5deec4264d7041d75fc947 (diff) | |
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
@@ -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; |
