diff options
-rw-r--r-- | all.h | 3 | ||||
-rw-r--r-- | amd64/sysv.c | 34 | ||||
-rw-r--r-- | arm64/abi.c | 17 | ||||
-rw-r--r-- | doc/il.txt | 6 | ||||
-rw-r--r-- | live.c | 2 | ||||
-rw-r--r-- | load.c | 2 | ||||
-rw-r--r-- | ops.h | 2 | ||||
-rw-r--r-- | parse.c | 48 | ||||
-rw-r--r-- | test/_slow.qbe | 10 | ||||
-rw-r--r-- | test/abi5.ssa | 18 | ||||
-rw-r--r-- | test/abi6.ssa | 4 | ||||
-rw-r--r-- | test/echo.ssa | 2 | ||||
-rw-r--r-- | test/vararg2.ssa | 28 |
13 files changed, 101 insertions, 75 deletions
diff --git a/all.h b/all.h index 4b9eb0e..37980d3 100644 --- a/all.h +++ b/all.h @@ -171,12 +171,11 @@ enum { }; #define INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */ -#define iscall(o) INRANGE(o, Ocall, Ovacall) #define isstore(o) INRANGE(o, Ostoreb, Ostored) #define isload(o) INRANGE(o, Oloadsb, Oload) #define isext(o) INRANGE(o, Oextsb, Oextuw) #define ispar(o) INRANGE(o, Opar, Opare) -#define isarg(o) INRANGE(o, Oarg, Oarge) +#define isarg(o) INRANGE(o, Oarg, Oargv) #define isret(j) INRANGE(j, Jret0, Jretc) enum Class { diff --git a/amd64/sysv.c b/amd64/sysv.c index 842f645..2e3e4a8 100644 --- a/amd64/sysv.c +++ b/amd64/sysv.c @@ -153,7 +153,7 @@ selret(Blk *b, Fn *fn) static int argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env) { - int nint, ni, nsse, ns, n, *pn; + int varc, envc, nint, ni, nsse, ns, n, *pn; AClass *a; Ins *i; @@ -162,6 +162,8 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env) else nint = 6; nsse = 8; + varc = 0; + envc = 0; for (i=i0, a=ac; i<i1; i++, a++) switch (i->op - op + Oarg) { case Oarg: @@ -196,14 +198,23 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env) a->inmem = 1; break; case Oarge: + envc = 1; if (op == Opar) *env = i->to; else *env = i->arg[0]; break; + case Oargv: + varc = 1; + break; + default: + die("unreachable"); } - return (!req(R, *env) << 12) | ((6-nint) << 4) | ((8-nsse) << 8); + if (varc && envc) + err("sysv abi does not support variadic env calls"); + + return ((varc|envc) << 12) | ((6-nint) << 4) | ((8-nsse) << 8); } int amd64_sysv_rsave[] = { @@ -290,7 +301,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap) { Ins *i; AClass *ac, *a, aret; - int ca, ni, ns, al, varc, envc; + int ca, ni, ns, al; uint stk, off; Ref r, r1, r2, reg[2], env; RAlloc *ra; @@ -358,22 +369,20 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap) ca += 1 << 2; } } - envc = !req(R, env); - varc = i1->op == Ovacall; - if (varc && envc) - err("sysv abi does not support variadic env calls"); - ca |= varc << 12; /* envc set in argsclass() */ + emit(Ocall, i1->cls, R, i1->arg[0], CALL(ca)); - if (envc) + + if (!req(R, env)) emit(Ocopy, Kl, TMP(RAX), env, R); - if (varc) + else if ((ca >> 12) & 1) /* vararg call */ emit(Ocopy, Kw, TMP(RAX), getcon((ca >> 8) & 15, fn), R); ni = ns = 0; if (ra && aret.inmem) emit(Ocopy, Kl, rarg(Kl, &ni, &ns), ra->i.to, R); /* pass hidden argument */ + for (i=i0, a=ac; i<i1; i++, a++) { - if (a->inmem || i->op == Oarge) + if (i->op >= Oarge || a->inmem) continue; r1 = rarg(a->cls[0], &ni, &ns); if (i->op == Oargc) { @@ -393,7 +402,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap) r = newtmp("abi", Kl, fn); for (i=i0, a=ac, off=0; i<i1; i++, a++) { - if (!a->inmem) + if (i->op >= Oarge || !a->inmem) continue; if (i->op == Oargc) { if (a->align == 4) @@ -676,7 +685,6 @@ amd64_sysv_abi(Fn *fn) emiti(*i); break; case Ocall: - case Ovacall: for (i0=i; i0>b->ins; i0--) if (!isarg((i0-1)->op)) break; diff --git a/arm64/abi.c b/arm64/abi.c index 5fe9553..d38dcf5 100644 --- a/arm64/abi.c +++ b/arm64/abi.c @@ -255,6 +255,10 @@ argsclass(Ins *i0, Ins *i1, Class *carg, Ref *env) case Oarge: *env = i->arg[0]; break; + case Oargv: + break; + default: + die("unreachable"); } return ((gp-gpreg) << 5) | ((fp-fpreg) << 9); @@ -371,10 +375,11 @@ selcall(Fn *fn, Ins *i0, Ins *i1, Insl **ilp) } } + emit(Ocall, 0, R, i1->arg[0], CALL(cty)); + envc = !req(R, env); if (envc) die("todo (arm abi): env calls"); - emit(Ocall, 0, R, i1->arg[0], CALL(cty)); if (cty & (1 << 13)) /* struct return argument */ @@ -383,9 +388,9 @@ selcall(Fn *fn, Ins *i0, Ins *i1, Insl **ilp) for (i=i0, c=ca; i<i1; i++, c++) { if ((c->class & Cstk) != 0) continue; - if (i->op != Oargc) + if (i->op == Oarg) emit(Ocopy, *c->cls, TMP(*c->reg), i->arg[0], R); - else + if (i->op == Oargc) ldregs(c->reg, c->cls, c->nreg, i->arg[1], fn); } @@ -393,11 +398,12 @@ selcall(Fn *fn, Ins *i0, Ins *i1, Insl **ilp) for (i=i0, c=ca; i<i1; i++, c++) { if ((c->class & Cstk) == 0) continue; - if (i->op != Oargc) { + if (i->op == Oarg) { r = newtmp("abi", Kl, fn); emit(Ostorel, 0, R, i->arg[0], r); emit(Oadd, Kl, r, TMP(SP), getcon(off, fn)); - } else + } + if (i->op == Oargc) blit(TMP(SP), off, i->arg[1], c->size, fn); off += c->size; } @@ -675,7 +681,6 @@ arm64_abi(Fn *fn) emiti(*i); break; case Ocall: - case Ovacall: for (i0=i; i0>b->ins; i0--) if (!isarg((i0-1)->op)) break; diff --git a/doc/il.txt b/doc/il.txt index d1ed755..87a4d9f 100644 --- a/doc/il.txt +++ b/doc/il.txt @@ -751,7 +751,7 @@ single-precision floating point number `%f` into `%rs`. ARG := ABITY VAL # Regular argument | 'env' VAL # Environment argument (first) - | '...' # Variadic marker (last) + | '...' # Variadic marker ABITY := BASETY | :IDENT @@ -778,8 +778,8 @@ integer. If the called function does not expect an environment parameter, it will be safely discarded. See the <@ Functions > section for more information about environment parameters. -When the called function is variadic, the last argument -must be `...`. +When the called function is variadic, there must be a `...` +marker separating the named and variadic arguments. ~ Variadic ~~~~~~~~~~ diff --git a/live.c b/live.c index c22e063..4198995 100644 --- a/live.c +++ b/live.c @@ -82,7 +82,7 @@ Again: for (k=0; k<2; k++) b->nlive[k] = nlv[k]; for (i=&b->ins[b->nins]; i!=b->ins;) { - if (iscall((--i)->op) && rtype(i->arg[1]) == RCall) { + if ((--i)->op == Ocall && rtype(i->arg[1]) == RCall) { b->in->t[0] &= ~T.retregs(i->arg[1], m); for (k=0; k<2; k++) { nlv[k] -= m[k]; diff --git a/load.c b/load.c index f3a695b..5d61a6c 100644 --- a/load.c +++ b/load.c @@ -234,7 +234,7 @@ def(Slice sl, bits msk, Blk *b, Ins *i, Loc *il) while (i > b->ins) { --i; if (killsl(i->to, sl) - || (iscall(i->op) && escapes(sl.ref, curf))) + || (i->op == Ocall && escapes(sl.ref, curf))) goto Load; ld = isload(i->op); if (ld) { diff --git a/ops.h b/ops.h index 114310c..535be71 100644 --- a/ops.h +++ b/ops.h @@ -137,8 +137,8 @@ O(pare, T(e,x,e,e, e,x,e,e), 0) X(0, 0, 0) O(arg, T(w,l,s,d, x,x,x,x), 0) X(0, 0, 0) O(argc, T(e,x,e,e, e,l,e,e), 0) X(0, 0, 0) O(arge, T(e,l,e,e, e,x,e,e), 0) X(0, 0, 0) +O(argv, T(x,x,x,x, x,x,x,x), 0) X(0, 0, 0) O(call, T(m,m,m,m, x,x,x,x), 0) X(0, 0, 0) -O(vacall, T(m,m,m,m, x,x,x,x), 0) X(0, 0, 0) /* Flags Setting */ O(flagieq, T(x,x,e,e, x,x,e,e), 0) X(0, 0, 1) 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; diff --git a/test/_slow.qbe b/test/_slow.qbe index 2d107ae..a411e41 100644 --- a/test/_slow.qbe +++ b/test/_slow.qbe @@ -3408,7 +3408,7 @@ function $transparent_crc(l %.1, l %.3, w %.5) { %.9 =l copy $.Lstring.93 %.10 =l loadl %.4 %.11 =l loadl %.2 - %.12 =w call $printf(l %.9, l %.10, l %.11, ...) + %.12 =w call $printf(l %.9, ..., l %.10, l %.11) @if_false.679 %.13 =l loadl $crc32_context %.14 =l loadl %.2 @@ -3461,7 +3461,7 @@ function $transparent_crc_bytes(l %.1, w %.3, l %.5, w %.7) { %.28 =l loadl $crc32_context %.29 =l copy 4294967295 %.30 =l xor %.28, %.29 - %.31 =w call $printf(l %.26, l %.27, l %.30, ...) + %.31 =w call $printf(l %.26, ..., l %.27, l %.30) @if_false.687 ret } @@ -3480,7 +3480,7 @@ function $platform_main_end(l %.1, w %.3) { @if_true.690 %.8 =l copy $.Lstring.97 %.9 =l loadl %.2 - %.10 =w call $printf(l %.8, l %.9, ...) + %.10 =w call $printf(l %.8, ..., l %.9) @if_false.691 ret } @@ -35219,7 +35219,7 @@ function w $main(w %.1, l %.3) { %.53 =w loadsw %.5 %.54 =w loadsw %.6 %.55 =w loadsw %.7 - %.56 =w call $printf(l %.52, w %.53, w %.54, w %.55, ...) + %.56 =w call $printf(l %.52, ..., w %.53, w %.54, w %.55) @if_false.1519 @for_cont.1516 %.57 =w loadsw %.7 @@ -35338,7 +35338,7 @@ function w $main(w %.1, l %.3) { @if_true.1524 %.138 =l copy $.Lstring.129 %.139 =w loadsw %.5 - %.140 =w call $printf(l %.138, w %.139, ...) + %.140 =w call $printf(l %.138, ..., w %.139) @if_false.1525 @for_cont.1522 %.141 =w loadsw %.5 diff --git a/test/abi5.ssa b/test/abi5.ssa index edfda4e..1d823b1 100644 --- a/test/abi5.ssa +++ b/test/abi5.ssa @@ -25,41 +25,41 @@ export function $test() { @start %r1 =:st1 call $t1() - %i1 =w call $printf(l $fmt1, l %r1, ...) + %i1 =w call $printf(l $fmt1, ..., l %r1) %r2 =:st2 call $t2() %w2 =w loadw %r2 - %i2 =w call $printf(l $fmt2, w %w2, ...) + %i2 =w call $printf(l $fmt2, ..., w %w2) %r3 =:st3 call $t3() %s3 =s loads %r3 %r34 =l add %r3, 4 %w3 =w loadw %r34 %p3 =d exts %s3 - %i3 =w call $printf(l $fmt3, d %p3, w %w3, ...) + %i3 =w call $printf(l $fmt3, ..., d %p3, w %w3) %r4 =:st4 call $t4() %w4 =w loadw %r4 %r48 =l add 8, %r4 %d4 =d loadd %r48 - %i4 =w call $printf(l $fmt4, w %w4, d %d4, ...) + %i4 =w call $printf(l $fmt4, ..., w %w4, d %d4) %r5 =:st5 call $t5() %s5 =s loads %r5 %d5 =d exts %s5 %r58 =l add %r5, 8 %l5 =l loadl %r58 - %i5 =w call $printf(l $fmt5, d %d5, l %l5, ...) + %i5 =w call $printf(l $fmt5, ..., d %d5, l %l5) %r6 =:st6 call $t6() - %i6 =w call $printf(l $fmt6, l %r6, ...) + %i6 =w call $printf(l $fmt6, ..., l %r6) %r7 =:st7 call $t7() %s7 =s loads %r7 %d71 =d exts %s7 %r78 =l add %r7, 8 %d72 =d loadd %r78 - %i7 =w call $printf(l $fmt7, d %d71, d %d72, ...) + %i7 =w call $printf(l $fmt7, ..., d %d71, d %d72) %r8 =:st8 call $t8() %r84 =l add 4, %r8 @@ -69,14 +69,14 @@ function $test() { %w82 =w loadw %r84 %w83 =w loadw %r88 %w84 =w loadw %r812 - %i8 =w call $printf(l $fmt8, w %w81, w %w82, w %w83, w %w84, ...) + %i8 =w call $printf(l $fmt8, ..., w %w81, w %w82, w %w83, w %w84) %r9 =:st9 call $t9() %r94 =l add 4, %r9 %w9 =w loadw %r9 %s9 =s loads %r94 %d9 =d exts %s9 - %i9 =w call $printf(l $fmt9, w %w9, d %d9, ...) + %i9 =w call $printf(l $fmt9, ..., w %w9, d %d9) ret } diff --git a/test/abi6.ssa b/test/abi6.ssa index 0870031..da2370c 100644 --- a/test/abi6.ssa +++ b/test/abi6.ssa @@ -13,8 +13,8 @@ function $f(:hfa3 %h1, :hfa3 %h2, d %d1, :hfa3 %h3, d %d2) { call $phfa3(:hfa3 %h1) call $phfa3(:hfa3 %h2) call $phfa3(:hfa3 %h3) - call $printf(l $dfmt, d %d1, ...) - call $printf(l $dfmt, d %d2, ...) + call $printf(l $dfmt, ..., d %d1) + call $printf(l $dfmt, ..., d %d2) ret } diff --git a/test/echo.ssa b/test/echo.ssa index 6010986..5e48b0e 100644 --- a/test/echo.ssa +++ b/test/echo.ssa @@ -20,7 +20,7 @@ function w $main(w %argc, l %argv) { @loop2 %sep =w phi @last 10, @nolast 32 %arg =l loadl %av - %r =w call $printf(l %fmt, l %arg, w %sep, ...) + %r =w call $printf(l %fmt, ..., l %arg, w %sep) %av1 =l add %av, 8 %ac1 =w sub %ac, 1 jmp @loop diff --git a/test/vararg2.ssa b/test/vararg2.ssa index 7e85774..0b2eb53 100644 --- a/test/vararg2.ssa +++ b/test/vararg2.ssa @@ -19,11 +19,11 @@ export function $qbeprint0(l %fmt, ...) { jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -59,11 +59,11 @@ export function $qbeprint1(w %argw0, l %fmt, ...) { jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -99,11 +99,11 @@ export function $qbeprint2(d %argd0, l %fmt, ...) { jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -139,11 +139,11 @@ export function $qbeprint3(w %argw0, w %argw1, w %argw2, w %argw3, l %fmt, ...) jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -179,11 +179,11 @@ export function $qbeprint4(d %argd0, d %argd1, d %argd2, d %argd3, d %argd4, d % jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -219,11 +219,11 @@ export function $qbeprint5(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, d % jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) @@ -259,11 +259,11 @@ export function $qbeprint6(w %argw0, w %argw1, w %argw2, w %argw3, w %argw4, w % jnz %isg, @casef, @cased @casef %dbl =d vaarg %vp - %r =w call $printf(l %fmtdbl, d %dbl, ...) + %r =w call $printf(l %fmtdbl, ..., d %dbl) jmp @loop @cased %int =w vaarg %vp - %r =w call $printf(l %fmtint, w %int, ...) + %r =w call $printf(l %fmtint, ..., w %int) jmp @loop @end %r =w call $puts(l %emptys) |