diff options
| author | 2022-08-29 23:01:37 +0200 | |
|---|---|---|
| committer | 2022-08-29 23:01:37 +0200 | |
| commit | 34313d801d38aa726d01b7f09690fb7a86ac47dd (patch) | |
| tree | ef891f88562c167e732dc7d7b9a8a656f92da6cd /src | |
| parent | 2f243de6ce9402f880677a07b832c0e56a7f688d (diff) | |
remove ir*.cff; make vararg only with primitive types
Diffstat (limited to 'src')
| -rw-r--r-- | src/asm.cff | 109 | ||||
| -rw-r--r-- | src/cffc.hff | 20 | ||||
| -rw-r--r-- | src/fmt.cff | 14 | ||||
| -rw-r--r-- | src/ir.cff | 10 | ||||
| -rw-r--r-- | src/ir.hff | 80 | ||||
| -rw-r--r-- | src/irdump.cff | 173 | ||||
| -rw-r--r-- | src/irgen.cff | 440 | ||||
| -rw-r--r-- | src/llvm.cff | 350 | ||||
| -rw-r--r-- | src/parse.cff | 95 | ||||
| -rw-r--r-- | src/targ.cff | 2 |
10 files changed, 236 insertions, 1057 deletions
diff --git a/src/asm.cff b/src/asm.cff deleted file mode 100644 index a92e14d..0000000 --- a/src/asm.cff +++ /dev/null @@ -1,109 +0,0 @@ -import "cffc.hff"; -import "common.hff"; - -struct ASM { - outf *FILE, - lastsection enum { none, data, text }, - - fn gen(A *ASM, fmt *const u8, ...) void { - let ap va_list #?; - ap->start(fmt); - fn fmtproc(c u8, fp *void) void { - fputc(c, fp); - } - for let c = *fmt; c != 0; c = *++fmt { - if c != '%' { - fputc(c, A.outf); - continue; - } - switch (c = *++fmt) { - case 's'; - fprintf(A.outf, "%s", ap->arg(*const u8)); - case 'd'; - fprintf(A.outf, "%d", ap->arg(int)); - case 'I'; - fprintf(A.outf, "%lld", as(c_llong) ap->arg(i64)); - case 'f'; - fprintf(A.outf, "%.17f", ap->arg(f64)); - case 'z'; - fprintf(A.outf, "%llu", as(c_ullong) ap->arg(usize)); - case 'S'; - pfmt(&fmtproc, A.outf, "%S", ap->arg([#]const u8)); - case else - assert(#f, "bad fmt '%c'", c); - } - } - ap->end(); - } -} - -fn init(B *Backend, outf *FILE) void { - B.impl = calloc(1, sizeof ASM); - let impl *ASM = B.impl; - impl.outf = outf; -} - -static directive4size []*const u8 = { - [1] = "byte", - [2] = "short", - [4] = "int", - [8] = "quad" -}; - -fn gendata(A *ASM, ty *const Type, ex *Expr) void { - switch ex.u { - case ZeroIni; - A->gen(".fill %z", ty.size); - case IntLit i; - A->gen(".%s %I", directive4size[ty.size], i.i); - case FloLit f; - A->gen(".%s %f", ty.size == 4 ? "single" : "double", f); - case StrLit s; - if ty->is(:Arr) { - A->gen(".ascii %S", s); - } else { - static id int = 0; - A->gen(".%s strlit%d.", directive4size[g_targ.ptrsize], id); - A->gen("\nstrlit%d.:\n\t.ascii %S", id++, s); - } - case else - assert(#f, "NYI data"); - } -} - -fn genstatic(A *ASM, decl *Decl) void { - if decl.u.Static.fwd { - return; - } - if A.lastsection != :data { - A->gen(".section data\n"); - A.lastsection = :data; - } - if decl.externp { - A->gen(".globl %s\n%s:\n", decl.name, decl.name); - } else { - A->gen("%s.s%d:\n", decl.name, decl.u.Static.id); - } - A->gen("\t.align %z\n", decl.u.Static.ty.align); - switch decl.u.Static.ini { - case None; - A->gen("\t.fill %z\n", decl.u.Static.ty.size); - case Some *ex; - A->gen("\t"); - gendata(A, decl.u.Static.ty, ex); - A->gen("\n"); - } -} - -fn bgenstatic(B *Backend, decl *Decl) void { - genstatic(B.impl, decl); -} - -fn bgenfn(B *Backend, Fn *Fn) void { -} - -extern static g_asmbackend Backend = { - .initf: &init, - .genstaticf: &bgenstatic, - .genfnf: &bgenfn, -}; diff --git a/src/cffc.hff b/src/cffc.hff index 11adba6..5eded01 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -130,11 +130,9 @@ struct Type { struct Fn; struct Expan; -struct IRCtx; struct Block; struct Parser { fp *FILE, - irctx *IRCtx, alloc *Allocator, tlalloc *Allocator, curfile *const u8, @@ -378,14 +376,6 @@ struct DeclList { decl Decl, } - -struct Backend { - impl *void, - initf *fn(*Backend, *FILE) void, - genstaticf *fn(*Backend, *Decl) void, - genfnf *fn(*Backend, *Fn) void, -} - struct Targ { name *const u8, ptrsize u8, @@ -400,7 +390,6 @@ struct Targ { charsigned bool, shortenum bool, - B *Backend, triple *const u8, } @@ -511,15 +500,6 @@ extern fn envfree(*Env) void; // fold.cff extern fn fold(*Expr) bool; -// ir*.cff -extern fn mkirctx(*Allocator) *IRCtx; -extern fn ir_genstatic(*IRCtx, *Decl) void; -extern fn ir_genfn(*IRCtx, *Fn) void; -extern fn ir_free(*IRCtx) void; - -// asm.cff -extern static g_asmbackend Backend; - // llvm.cff extern fn llvm_addtype(*const Type) void; extern fn llvm_addglobl(*Decl, staticp bool) void; diff --git a/src/fmt.cff b/src/fmt.cff index 27bfe0e..699777a 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -45,7 +45,7 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) case :bool; ps(tok.u.bool ? "#t" : "#f"); case :str; - pfmt(proc, parg, "%S", tok.u.str); + pfmt(proc, parg, "%S", &tok.u.str); case :chr; let t = bswap64(tok.u.uint); p('\''); @@ -184,7 +184,7 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) case Ty ty; pfmt(proc, parg, "%t", ty); case Val tok; - pfmt(proc, parg, "%T", tok); + pfmt(proc, parg, "%T", &tok); } if i < agg.tpargs.#len - 1 { ps(", "); @@ -275,15 +275,15 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) ps(s); } case 'S'; - let str = ap->arg([#]const u8); + let str = *ap->arg(*[#]const u8); p('"'); foreach(c, i, str) { pch(c); } p('"'); case 'T'; - let tok = ap->arg(Tok); - pritok(proc, parg, quote, &tok); + let tok = ap->arg(*Tok); + pritok(proc, parg, quote, tok); case 'k'; let tokt = ap->arg(TokT); pritokt(proc, parg, tokt); @@ -292,7 +292,7 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) pritype(proc, parg, ap->arg(*const Type)); ps("\e[0m"); case 'l'; - let loc = ap->arg(Loc); + let loc = ap->arg(*Loc); pfmt(proc, parg, "\e[1m%s:%d:%d\e[0m", fileid2path(loc.fileid), loc.line, loc.col); case else assert(#f, "bad fmt '%c'", c); @@ -372,7 +372,7 @@ extern fn vdiag(P *Parser, loc Loc, kind *const u8, fmt *const u8, ap va_list) v for let ep = P.curexpan; ep; ep = ep.prev { if ep.name != #null and (i++ < 8 or ep.prev == #null or ep.prev.prev == #null) { efmt("* while expanding %s `%s' at %l\n", - ep.tepl ? "template" : "macro", ep.name, ep.loc); + ep.tepl ? "template" : "macro", ep.name, &ep.loc); eprifileline(ep.loc); } else if ep.name != #null and i == 8 { efmt(" ... (some expansions omitted)\n"); diff --git a/src/ir.cff b/src/ir.cff deleted file mode 100644 index 8b28746..0000000 --- a/src/ir.cff +++ /dev/null @@ -1,10 +0,0 @@ -import "ir.hff"; - -extern fn mkirctx(alloc *Allocator) *IRCtx { - let ctx *IRCtx = anew(alloc, IRCtx); - ctx.alloc = alloc; - return ctx; -} - -extern fn ir_free(IR *IRCtx) void { -} diff --git a/src/ir.hff b/src/ir.hff deleted file mode 100644 index 2f7b98f..0000000 --- a/src/ir.hff +++ /dev/null @@ -1,80 +0,0 @@ -import "cffc.hff"; - -struct IRCtx { - alloc *Allocator, -} - -struct IRInst; -struct IRFn { - body *IRInst -} - -struct IRValue { - ty *const Type, - u enum union { - IImm i64, - FImm f64, - SImm [#]const u8, - BImm bool, - Null, - Tmp int, - Local *Decl, - Global *Decl, - } -} - -enum union IRArg { - Val IRValue, - Ty *const Type, - Fn *Decl, -} - -enum IRInstT { - nop, - neg, - not, - compl, - fneg, - add, - sub, - mul, - div, - mod, - band, - bor, - xor, - lsl, - lsr, - asr, - fadd, - fsub, - fmul, - fdiv, - eq, - neq, - lt, - lteq, - ftrunc, - itof, - getelem, - pgetelem, - copy, - setvar, - load, - store, - call, - b, - beqz, - ret0, - ret, -} - -struct IRInst { - t IRInstT, - next *IRInst, - branch *IRInst, - call_nargs int, - args [0]IRArg, -} - -extern fn irdump(*IRInst) void; diff --git a/src/irdump.cff b/src/irdump.cff deleted file mode 100644 index 9d31935..0000000 --- a/src/irdump.cff +++ /dev/null @@ -1,173 +0,0 @@ -import "ir.hff"; -import "common.hff"; -import "map.hff"; - -fn dump(fmt *const u8, ...) void { - let ap va_list #?; - ap->start(fmt); - for let c = *fmt; c != 0; c = *++fmt { - if c != '%' { - fputc(c, stderr); - continue; - } - switch (c = *++fmt) { - case '%'; - fputc('%', stderr); - case 'd'; - efmt("%d", ap->arg(int)); - case 'a'; - let arg = ap->arg(IRArg); - switch arg { - case Val val; - switch val.u { - case IImm i; - efmt("%I", i); - case FImm f; - efmt("%f", f); - case SImm s; - efmt("%S", s); - case BImm b; - efmt("%s", b ? "#t" : "#f"); - case Null; - efmt("#null"); - case Tmp t; - efmt("%%%d", t); - case Local l; - efmt("$%s.%d", l.name, l.u.Let.id); - case Global g; - efmt("@%s.%d", g.name, g.u.Static.id); - } - case Ty ty; efmt("%t", ty); - case Fn decl; efmt("@%s", decl.name); - case else assert(#f, "arg? %d", arg.#tag); - } - case 't'; - efmt("%t", ap->arg(*Type)); - case else - assert(#f, "bad fmt %c", c); - } - } - ap->end(); -} - -extern fn irdump(inst *IRInst) void { - let labels Map<*IRInst, int, struct { - fn hash(a *IRInst) u32 { return as(iptrint)a; } - fn eq(a *IRInst, b *IRInst) bool { return a == b; } - }> = {}; - defer labels->clear(); - let labid = 0; - for let a = inst; a; a = a.next { - if a.branch { - let slot = labels->get_slot(a.branch); - if *slot == 0 { - *slot = ++labid; - } - } - } - - - #'dump for ; inst; inst = inst.next { - let label = labels->get(inst); - if label { - dump(".L%d:\t", *label); - } else { - dump("\t"); - } - defmacro exprinst(tag, nam, n) [ - if inst.t == (tag) { - dump("%%%d(%t) = " ## nam ## " ", inst.args[0].Val.u.Tmp, inst.args[0].Val.ty); - for let $i = 1; $i < (n); ++$i { - dump("%a", inst.args[$i]); - if $i < (n) - 1 { - dump(", "); - } - } - dump("\n"); - continue #'dump; - } - ] - defmacro stmtinst(tag, nam, n) [ - if inst.t == (tag) { - dump(nam##" "); - for let $i = 0; $i < (n); ++$i { - dump("%a", inst.args[$i]); - if $i < (n) - 1 { - dump(", "); - } - } - dump("\n"); - continue #'dump; - } - ] - - exprinst(:neg, "neg", 2) - exprinst(:not, "not", 2) - exprinst(:compl, "compl", 2) - exprinst(:fneg, "fneg", 2) - exprinst(:add, "add", 3); - exprinst(:sub, "sub", 3); - exprinst(:mul, "mul", 3); - exprinst(:div, "div", 3); - exprinst(:mod, "mod", 3); - exprinst(:band, "band", 3); - exprinst(:bor, "bor", 3); - exprinst(:xor, "xor", 3); - exprinst(:lsl, "lsl", 3); - exprinst(:lsr, "lsr", 3); - exprinst(:asr, "asr", 3); - exprinst(:eq, "eq", 3); - exprinst(:neq, "neq", 3); - exprinst(:lt, "lt", 3); - exprinst(:lteq, "lteq", 3); - exprinst(:fadd, "fadd", 3); - exprinst(:fsub, "fsub", 3); - exprinst(:fmul, "fmul", 3); - exprinst(:fdiv, "fdiv", 3); - if inst.t == :call { - let fnty = inst.args[1].Fn.u.Fn.ty.u.Fn; - dump("%%%d(%t) = call %a, ", inst.args[0].Val.u.Tmp, inst.args[0].Val.ty, inst.args[1]); - let n = inst.call_nargs; - for let i = 0; i < n; ++i { - dump("%a(%t)", inst.args[i + 2], - i < fnty.params.#len ? fnty.params[i] : inst.args[i + 2].Val.ty); - if i < n - 1 { - dump(", "); - } - } - dump("\n"); - continue #'dump; - } - exprinst(:ftrunc, "ftrunc", 2); - exprinst(:itof, "itof", 2); - exprinst(:getelem, "getelem", 4); - exprinst(:pgetelem, "pgetelem", 4); - - stmtinst(:nop, "nop", 0); - exprinst(:copy, "copy", 2); - if inst.t == :setvar { - dump("set %a, %a\n", inst.args[0], inst.args[1]); - continue #'dump; - } - if inst.t == :load { - dump("%a(%t) = load %a[%a]\n", inst.args[0], inst.args[0].Val.ty, inst.args[1], inst.args[2]); - continue #'dump; - } - if inst.t == :store { - dump("store %a[%a], %a\n", inst.args[0], inst.args[1], inst.args[2]); - continue #'dump; - } - stmtinst(:ret0, "ret", 0); - stmtinst(:ret, "ret", 1); - if inst.t == :beqz { - dump("beqz %a, .L%d\n", inst.args[0], *labels->get(inst.branch)); - continue #'dump; - } - if inst.t == :b { - dump("b .L%d\n", *labels->get(inst.branch)); - continue #'dump; - } - - assert(#f, "inst? %d\n", inst.t); - }; -} diff --git a/src/irgen.cff b/src/irgen.cff deleted file mode 100644 index c0ea1e1..0000000 --- a/src/irgen.cff +++ /dev/null @@ -1,440 +0,0 @@ -import "ir.hff"; -import "common.hff"; -import "map.hff"; - -extern fn ir_genstatic(IR *IRCtx, decl *Decl) void { - g_targ.B.genstaticf(g_targ.B, decl); -} - -struct IntTraits { - fn hash(a int) u32 { return (a * 7128347) + 972183; } - fn eq(a int, b int) bool { return a == b; } -} - -struct InstStream { - IR *IRCtx, - head *IRInst, - tail *IRInst, - loopbrks Map<int, *IRInst, IntTraits>, - loopconts Map<int, *IRInst, IntTraits>, - - fn push(S *InstStream, inst *IRInst) void { - if S.tail { - S.tail.next = inst; - } else { - S.head = inst; - } - S.tail = inst; - } - - fn mkinst(S *InstStream, inst0 IRInst, narg uint) *IRInst { - let inst *IRInst = S.IR.alloc->alloc(sizeof IRInst + (narg * sizeof IRArg), alignof IRInst); - *inst = inst0; - return inst; - } - - fn mkinst1(S *InstStream, inst0 IRInst, a IRArg) *IRInst { - let inst = S->mkinst(inst0, 1); - inst.args[0] = a; - return inst; - } - - fn mkinst2(S *InstStream, inst0 IRInst, a IRArg, b IRArg) *IRInst { - let inst = S->mkinst(inst0, 2); - inst.args[0] = a; - inst.args[1] = b; - return inst; - } - - fn mkinst3(S *InstStream, inst0 IRInst, a IRArg, b IRArg, c IRArg) *IRInst { - let inst = S->mkinst(inst0, 3); - inst.args[0] = a; - inst.args[1] = b; - inst.args[2] = c; - return inst; - } - - fn mkinst4(S *InstStream, inst0 IRInst, a IRArg, b IRArg, c IRArg, d IRArg) *IRInst { - let inst = S->mkinst(inst0, 4); - inst.args[0] = a; - inst.args[1] = b; - inst.args[2] = c; - inst.args[3] = d; - return inst; - } - - fn pushnop(S *InstStream) *IRInst { - S->push(S->mkinst({:nop}, 0)); - return S.tail; - } -} - - -fn genblock(S *InstStream, block Block) void; -fn genexpr(S *InstStream, ex *Expr) IRValue { - static tmpid int = 0; - - fold(ex); - - defmacro genunop(u,t) [ { - let child = genexpr(S, (u).ex); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst2({t}, :Val(res), :Val(child)); - S->push(inst); - return res; - } ] - - defmacro genbinop(b,t) [ { - let lhs = genexpr(S, (b).lhs); - let rhs = genexpr(S, (b).rhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst3({t}, :Val(res), :Val(lhs), :Val(rhs)); - S->push(inst); - return res; - } ] - - switch ex.u { - case IntLit i; return {ex.ty, :IImm(i.i)}; - case FloLit f; return {ex.ty, :FImm(f)}; - case StrLit s; return {ex.ty, :SImm(s)}; - case BoolLit b; return {ex.ty, :BImm(b)}; - case NullLit; return {ex.ty, :Null}; - case UnOp u; - switch u.op { - case :neg; genunop(u, ex.ty->is(:Int) ? :neg : :fneg); - case :not; genunop(u, :not); - case :compl; genunop(u, :compl); - case :deref; - let child = genexpr(S, (u).ex); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst3({:load}, :Val(res), :Val(child), :Val{ty_int,:IImm(0)}); - S->push(inst); - return res; - case :preinc, :predec; - let one = u.op == :preinc ? 1 : -1; - switch u.ex.u { - case Symbol decl; - let ex = genexpr(S, u.ex); - let inced = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let rhs = S->mkinst3({:add}, :Val(inced), - :Val(ex), :Val{ty_int, :IImm(one)}); - S->push(rhs); - let inst = S->mkinst2({:setvar}, :Val(ex), :Val(inced)); - S->push(inst); - return inced; - } - } - case BinOp b; - switch b.op { - case '+'; genbinop(b, !ex.ty->is(:Flo) ? :add : :fadd); - case '-'; genbinop(b, !ex.ty->is(:Flo) ? :sub : :fsub); - case '*'; genbinop(b, !ex.ty->is(:Flo) ? :mul : :fmul); - case '/'; genbinop(b, !ex.ty->is(:Flo) ? :div : :fdiv); - case '%'; genbinop(b, :mod); - case '&'; genbinop(b, :band); - case '|'; genbinop(b, :bor); - case '^'; genbinop(b, :xor); - case '<<'; genbinop(b, :lsl); - case '>>'; genbinop(b, ex.ty.u.Int.sgn ? :asr : :lsr); - case '=='; genbinop(b, :eq); - case '!='; genbinop(b, :neq); - case '<'; genbinop(b, :lt); - case '<='; genbinop(b, :lteq); - case '>'; - let lhs = genexpr(S, (b).lhs); - let rhs = genexpr(S, (b).rhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst3({:lt}, :Val(res), :Val(rhs), :Val(lhs)); - S->push(inst); - return res; - case '>='; - let lhs = genexpr(S, (b).lhs); - let rhs = genexpr(S, (b).rhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst3({:lteq}, :Val(res), :Val(rhs), :Val(lhs)); - S->push(inst); - return res; - case '='; - switch b.lhs.u { // var = ex - case Symbol decl; - let r = genexpr(S, b.rhs); - let inst = S->mkinst2({:setvar}, :Val(genexpr(S, b.lhs)), :Val(r)); - S->push(inst); - return r; - case UnOp u; // *a = ex - assert(u.op == :deref, "deref?? unop="); - let child = genexpr(S, u.ex); - let r = genexpr(S, b.rhs); - let inst = S->mkinst3({:store}, :Val(child), :Val{ty_int,:IImm(0)}, :Val(r)); - S->push(inst); - return r; - case Index index; // a[b] = ex - let indexee = genexpr(S, index.lhs); - let index = genexpr(S, index.rhs); - let newval = genexpr(S, b.rhs); - S->push(S->mkinst3({:store}, :Val(indexee), :Val(index), :Val(newval))); - return newval; - case else - assert(#f, "nyi ="); - } - case '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '<<=', '>>='; - let o IRInstT = b.op == '+=' ? (ex.ty->is(:Flo) ? :fadd : :add) - : b.op == '-=' ? (ex.ty->is(:Flo) ? :fsub : :sub) - : b.op == '*=' ? (ex.ty->is(:Flo) ? :fmul : :mul) - : b.op == '/=' ? (ex.ty->is(:Flo) ? :fdiv : :div) - : b.op == '%=' ? :mod - : b.op == '&=' ? :band - : b.op == '|=' ? :bor - : b.op == '<<=' ? :lsl - : b.op == '>>=' ? (ex.ty.u.Int.sgn ? :asr : :lsr) : :nop; - switch b.lhs.u { - case Symbol decl; // var += ex - let lhs = genexpr(S, b.lhs); - let rhs = genexpr(S, b.rhs); - let new = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - S->push(S->mkinst3({o}, :Val(new), :Val(lhs), :Val(rhs))); - let inst = S->mkinst2({:setvar}, :Val(lhs), :Val(new)); - S->push(inst); - return new; - } - - } - case Cast src; - let src = genexpr(S, src); - let ret = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - switch { - case ex.ty->is(:Int) and src.ty->is(:Flo); - S->push(S->mkinst2({:ftrunc}, :Val(ret), :Val(src))); - - case ex.ty->is(:Flo) and src.ty->is(:Int); - S->push(S->mkinst2({:itof}, :Val(ret), :Val(src))); - - case ex.ty->is(:Int) and src.ty->is(:Int); - S->push(S->mkinst2({:copy}, :Val(ret), :Val(src))); - - case ex.ty->is(:Int) and src.ty->is(:Bool); - S->push(S->mkinst2({:copy}, :Val(ret), :Val(src))); - - case ex.ty->is(:Bool) and src.ty->is(:Int); - S->push(S->mkinst2({:copy}, :Val(ret), :Val(src))); - - case ex.ty->is(:Ptr) and src.ty->is(:Int); - S->push(S->mkinst2({:copy}, :Val(ret), :Val(src))); - - case ex.ty->is(:Int) and src.ty->is(:Ptr); - S->push(S->mkinst2({:copy}, :Val(ret), :Val(src))); - - case else - assert(#f, "bad cast"); - } - return ret; - - case Dot dot; - let lhs = genexpr(S, dot.lhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem}, - :Val(res), :Val(lhs), :Val{ty_usize,:IImm(dot.fld.off)}, :Ty(ex.ty)); - S->push(inst); - return res; - - case SLen lhs; - let lhs = genexpr(S, lhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem}, - :Val(res), :Val(lhs), :Val{ty_usize,:IImm(g_targ.ptrsize)}, - :Ty(ex.ty)); - S->push(inst); - return res; - - case SPtr lhs; - let lhs = genexpr(S, lhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem}, - :Val(res), :Val(lhs), :Val{ty_usize,:IImm(0)}, :Ty(ex.ty)); - S->push(inst); - return res; - - case EUTag lhs; - let lhs = genexpr(S, lhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem}, - :Val(res), :Val(lhs), :Val{ty_usize,:IImm(0)}, :Ty(ex.ty)); - S->push(inst); - return res; - - - case Index idx; - let i = genexpr(S, idx.lhs); - let off = genexpr(S, idx.rhs); - let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; - let inst = S->mkinst3({:load}, :Val(res), :Val(i), :Val(off)); - S->push(inst); - return res; - - case Cond c; - let test = genexpr(S, c.test); - let beqz = S->mkinst1({:beqz}, :Val(test)); - S->push(beqz); - let t = genexpr(S, c.t); - let res = IRValue{ex.ty, :Tmp(tmpid++)}; - let inst = S->mkinst2({:copy}, :Val(res), :Val(t)); - S->push(inst); - let b = S->mkinst({:b}, 0); - S->push(b); - beqz.branch = S->pushnop(); - let f = genexpr(S, c.f); - let inst = S->mkinst2({:copy}, :Val(res), :Val(f)); - S->push(inst); - b.branch = S->pushnop(); - return res; - - case Call c; - let n = c.args.#len; - let inst = S->mkinst({:call, .call_nargs: n}, n + 2); - inst.args[1] = :Fn(c.lhs.u.Symbol); - if c.lhs.u.#tag == :Symbol { - for let i = 0; i < n; ++i { - inst.args[i + 2] = :Val(genexpr(S, &c.args[i])); - } - S->push(inst); - } else { - } - let res = IRValue{ex.ty, :Tmp(tmpid++)}; - inst.args[0] = :Val(res); - return res; - case Symbol decl; - if decl.u.#tag == :Let { - return {ex.ty, :Local(decl)}; - } else { - return {ex.ty, :Global(decl)}; - } - } - - assert(#f, "NYI ex"); -} - -fn genstmt(S *InstStream, stmt *Stmt) void { - switch stmt.u { - case Block block; - genblock(S, block); - - case Expr *ex; - genexpr(S, ex); - - case Decl decl; - if decl.u.#tag == :Let and !decl.u.Let.ini->empty() { - let Let = &decl.u.Let; - let inst = S->mkinst2({:setvar}, :Val{Let.ty, :Local(decl)}, - :Val(genexpr(S, &Let.ini.Some))); - S->push(inst); - } - - case If If; - #{ - %t = <test> - beqz %t, .L0 - <t> - b .L1 - .L0: - <f> - .L1: - } - let t = genexpr(S, &If.test); - let beqz = S->mkinst1({:beqz}, :Val(t)); - S->push(beqz); - genblock(S, If.t); - if If.f.sts.#ptr { - let b = S->mkinst({:b}, 0); - S->push(b); - beqz.branch = S->pushnop(); - genblock(S, If.f); - b.branch = S->pushnop(); - } else { - beqz.branch = S->pushnop(); - } - - case While loop; - #{ - .cont: - %t = <test> - beqz %t, .brk - <body> - b .cont - .brk: - } - let begin = S->pushnop(); - let t = genexpr(S, &loop.test); - let beqz = S->mkinst1({:beqz}, :Val(t)); - let b = S->mkinst({:b}, 0); - let end = S->mkinst({:nop}, 0); - S->push(beqz); - S.loopconts->put(loop.id, begin); - S.loopbrks->put(loop.id, end); - genblock(S, loop.body); - S->push(b); - b.branch = begin; - S->push(end); - beqz.branch = end; - - case For loop; - genblock(S, loop.ini); - let begin = S->pushnop(); - let t = genexpr(S, &loop.test); - let beqz = S->mkinst1({:beqz}, :Val(t)); - let b = S->mkinst({:b}, 0); - let next = S->mkinst({:nop}, 0); - let end = S->mkinst({:nop}, 0); - S->push(beqz); - S.loopconts->put(loop.id, next); - S.loopbrks->put(loop.id, end); - genblock(S, loop.body); - S->push(next); - if !loop.next->empty() { - genexpr(S, &loop.next.Some); - } - S->push(b); - b.branch = begin; - S->push(end); - beqz.branch = end; - - case Break id; - let jumpto = S.loopbrks->get(id); - assert(jumpto != #null, "no brk label %d", id); - S->push(S->mkinst({:b, .branch: *jumpto},0)); - - case Continue id; - let jumpto = S.loopconts->get(id); - assert(jumpto != #null, "no cont label %d", id); - S->push(S->mkinst({:b, .branch: *jumpto},0)); - - case Return *ret; - if ret.ex->empty() { - S->push(S->mkinst({:ret0}, 0)); - } else { - let inst = S->mkinst1({:ret}, :Val(genexpr(S, &ret.ex.Some))); - S->push(inst); - } - - case else - assert(#f, "NYI st"); - } -} - -fn genblock(S *InstStream, block Block) void { - foreach_ptr(st, _, block.sts) { - genstmt(S, st); - } -} - -extern fn ir_genfn(IR *IRCtx, f *Fn) void { - let stream InstStream = {.IR: IR}; - defer stream.loopbrks->clear(); - defer stream.loopconts->clear(); - - genblock(&stream, f.body.Some); - stream->push(stream->mkinst({:ret0}, 0)); - - efmt("----------------------\n"); - efmt("function %s.%d:\n", container_of(f, Decl, u.Fn).name, f.id); - irdump(stream.head); -} diff --git a/src/llvm.cff b/src/llvm.cff index 1a7f24a..1e9eb03 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -23,8 +23,6 @@ struct Value { } } -static ty_i1 Type = {}; // dummy - fn gen(fmt *const u8, ...) void; extern fn genagg(ty *const Type) void { let agg = &ty.u.Agg; @@ -80,15 +78,14 @@ extern fn llvm_addtype(ty *const Type) void { } } - fn gendata(ty *const Type, ex *Expr) void; fn gen(fmt *const u8, ...) void { let ap va_list #?; ap->start(fmt); fn pritype(ty *const Type) void { - if ty == &ty_i1 { - gen("i1"); + if ty == #null { + gen("(nil)"); return; } switch ty.u { @@ -139,7 +136,7 @@ fn gen(fmt *const u8, ...) void { case 's'; fprintf(outfp, "%s", ap->arg(*const u8)); case 'S'; - let str = ap->arg([#]const u8); + let str = *ap->arg(*[#]const u8); fputc('"', outfp); foreach(c, _, str) { extern fn isprint(int) int; @@ -162,7 +159,7 @@ fn gen(fmt *const u8, ...) void { case 'z'; fprintf(outfp, "%zu", ap->arg(usize)); case 'v'; - let val = ap->arg(Value); + let val = ap->arg(*const Value); switch val.u { case IImm i; gen("%I", i); case FImm f; gen(val.ty.size == 4 ? "%f" : "%F", f); @@ -194,7 +191,7 @@ fn gen(fmt *const u8, ...) void { } case StrConstRef id; gen("@.str.%d", id); - case StrLit s; + case StrLit *s; gen("c%S", s); case else assert(#f, "value? %d", val.u.#tag); @@ -222,7 +219,7 @@ fn mktmp(ty *const Type) Value { defmacro gentmp(type, ...rest) [ (do let $tmp = mktmp(type); - gen("\t%v = ", $tmp); + gen("\t%v = ", &$tmp); gen(rest); gen("\n"); $tmp; @@ -267,18 +264,18 @@ fn genref(f *Fn, ex *Expr) Ref { switch idx.lhs.ty.u { case Arr arrty; let arr = genref(f, idx.lhs).Addr; - lhs = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, i32 0, i32 0", idx.lhs.ty, arr.ty, arr); + lhs = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, i32 0, i32 0", idx.lhs.ty, arr.ty, &arr); case Ptr; lhs = genexpr(f, idx.lhs); case Slice child; let tmp = genexpr(f, idx.lhs); - lhs = gentmp(mkptrtype(child), "extractvalue %t %v, 0", tmp.ty, tmp); + lhs = gentmp(mkptrtype(child), "extractvalue %t %v, 0", tmp.ty, &tmp); case else; assert(#f, "index"); } let rhs = genexpr(f, idx.rhs); let addr = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, %t %v", - ex.ty, lhs.ty, lhs, rhs.ty, rhs); + ex.ty, lhs.ty, &lhs, rhs.ty, &rhs); return :Addr(addr); case Dot dot; @@ -297,12 +294,12 @@ fn genref(f *Fn, ex *Expr) Ref { switch lhs.ty.u.Ptr.u.Agg.kind { case :Struct; addr = gentmp(ptrty, "getelementptr %t, %t %v, i32 0, i32 %d", - lhs.ty.u.Ptr, lhs.ty, lhs, idx); + lhs.ty.u.Ptr, lhs.ty, &lhs, idx); case :Union; - addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, lhs, ptrty); + addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, &lhs, ptrty); case else let off int = dot.fld.off; - addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", lhs.ty, lhs, off); + addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", lhs.ty, &lhs, off); } return :Addr(addr); @@ -311,7 +308,7 @@ fn genref(f *Fn, ex *Expr) Ref { case EUTag eex; let lhs = eex.ty->is(:Ptr) ? genexpr(f, eex) : genref(f, eex).Addr; - let addr = gentmp(mkptrtype(ex.ty), "bitcast %t %v to %t", lhs.ty, lhs, mkptrtype(ex.ty)); + let addr = gentmp(mkptrtype(ex.ty), "bitcast %t %v to %t", lhs.ty, &lhs, mkptrtype(ex.ty)); return :Addr(addr); case BitRaw ex; @@ -319,37 +316,39 @@ fn genref(f *Fn, ex *Expr) Ref { case AggIni ini; let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); - gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, tmp.ty, tmp); + gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, tmp.ty, &tmp); foreach(fld, i, ini.flds) { let fex = &ini.exs[i]; let ptr = mktmp(mkptrtype(fex.ty)); let idx int = fld - ex.ty.u.Agg.flds.#ptr; switch ex.ty.u.Agg.kind { case :Struct; - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", ptr, ex.ty, tmp.ty, tmp, idx); + gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ex.ty, tmp.ty, &tmp, idx); case :Union; - gen("\t%v = bitcast %t %v to %t\n", ptr, tmp.ty, tmp, ptr.ty); + gen("\t%v = bitcast %t %v to %t\n", &ptr, tmp.ty, &tmp, ptr.ty); } - gen("\tstore %t %v, %t %v\n", fld.ty, convert(f, fld.ty, fex), ptr.ty, ptr); + let it = convert(f, fld.ty, fex); + gen("\tstore %t %v, %t %v\n", fld.ty, &it, ptr.ty, &ptr); } return :Addr(tmp); case ArrIni ini; let ty = mkarrtype(ini.maxn, #f, ex.ty.u.Arr.child); let tmp = gentmp(mkptrtype(ty), "alloca %t", ty); - gen("\tstore %t zeroinitializer, %t %v\n", ty, tmp.ty, tmp); + gen("\tstore %t zeroinitializer, %t %v\n", ty, tmp.ty, &tmp); foreach(idx, i, ini.idxs) { let fex = &ini.exs[i]; let ptr = mktmp(mkptrtype(fex.ty)); - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", ptr, ty, tmp.ty, tmp, idx); - gen("\tstore %t %v, %t %v\n", fex.ty, convert(f, ty.u.Arr.child, fex), ptr.ty, ptr); + gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ty, tmp.ty, &tmp, idx); + let it = convert(f, ty.u.Arr.child, fex); + gen("\tstore %t %v, %t %v\n", fex.ty, &it, ptr.ty, &ptr); } return :Addr(tmp); case else let it = genexpr(f, ex); let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); - gen("store %t %v, %t %v", it.ty, it, tmp.ty, tmp); + gen("store %t %v, %t %v", it.ty, &it, tmp.ty, &tmp); return :Addr(tmp); } assert(#f, "genref %d", ex.u.#tag); @@ -358,22 +357,22 @@ fn genref(f *Fn, ex *Expr) Ref { fn genload(f *Fn, ref Ref) Value { switch ref { case Addr addr; - return gentmp(addr.ty.u.Ptr, "load %t, %t %v", addr.ty.u.Ptr, addr.ty, addr); + return gentmp(addr.ty.u.Ptr, "load %t, %t %v", addr.ty.u.Ptr, addr.ty, &addr); case BitDot dot; let intty = dot.lhs.ty.u.BitF.intty; let fld = dot.fld; let lhs = genload(f, :Addr(dot.lhs)); - let shifted = fld.off == 0 ? lhs : gentmp(lhs.ty, "lshr %t %v, %d", lhs.ty, lhs, fld.off); - let truncd = gentmp(#null, "trunc %t %v to i%d", shifted.ty, shifted, fld.size); + let shifted = fld.off == 0 ? lhs : gentmp(lhs.ty, "lshr %t %v, %d", lhs.ty, &lhs, fld.off); + let truncd = gentmp(#null, "trunc %t %v to i%d", shifted.ty, &shifted, fld.size); let res = mktmp(fld.ty); switch { case dot.fld.ty->is(:Bool); - let tmp = gentmp(&ty_i1, "icmp ne i%d %v, 0", fld.size, truncd); - gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); + let tmp = gentmp(#null, "icmp ne i%d %v, 0", fld.size, &truncd); + gen("\t%v = zext i1 %v to %t\n", &res, &tmp, res.ty); case dot.fld.ty->is(:Int); - gen("\t%v = %s i%d %v to %t\n", res, - dot.fld.ty.u.Int.sgn ? "sext" : "zext", fld.size, truncd, lhs.ty); + gen("\t%v = %s i%d %v to %t\n", &res, + dot.fld.ty.u.Int.sgn ? "sext" : "zext", fld.size, &truncd, lhs.ty); case else assert(#f, ""); } return res; @@ -382,8 +381,8 @@ fn genload(f *Fn, ref Ref) Value { fn genstore(f *Fn, ref Ref, v Value) void { switch ref { - case Addr addr; - gen("\tstore %t %v, %t %v\n", v.ty, v, addr.ty, addr); + case Addr *addr; + gen("\tstore %t %v, %t %v\n", v.ty, &v, addr.ty, addr); case BitDot dot; let intty = dot.lhs.ty.u.BitF.intty; @@ -391,14 +390,14 @@ fn genstore(f *Fn, ref Ref, v Value) void { let srcmask = fld.size == 64 ? ~0u64 : ((1u64 << fld.size) - 1); let addr = dot.lhs; let src0 = v; - let src = gentmp(intty, "and %t %v, %I", intty, src0, srcmask); - let src = gentmp(intty, "shl %t %v, %d", src.ty, src, fld.off); + let src = gentmp(intty, "and %t %v, %I", intty, &src0, srcmask); + let src = gentmp(intty, "shl %t %v, %d", src.ty, &src, fld.off); let dstmask = ~(srcmask << fld.off); - let lhs = gentmp(intty, "load %t, %t %v", intty, addr.ty, addr); + let lhs = gentmp(intty, "load %t, %t %v", intty, addr.ty, &addr); let lhs = genload(f, :Addr(addr)); - let lhs = gentmp(lhs.ty, "and %t %v, %I", lhs.ty, lhs, dstmask); - let raw = gentmp(lhs.ty, "or %t %v, %v", lhs.ty, lhs, src); - gen("\tstore %t %v, %t %v\n", raw.ty, raw, addr.ty, addr); + let lhs = gentmp(lhs.ty, "and %t %v, %I", lhs.ty, &lhs, dstmask); + let raw = gentmp(lhs.ty, "or %t %v, %v", lhs.ty, &lhs, &src); + gen("\tstore %t %v, %t %v\n", raw.ty, &raw, addr.ty, &addr); } } @@ -411,7 +410,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { defmacro cvt(inst) [ (do let $t = mktmp(to), val = genexpr(f, ex); - gen("\t%v = %s %t %v to %t\n", $t, inst, from, val, to); + gen("\t%v = %s %t %v to %t\n", &$t, inst, from, &val, to); $t; ) ] @@ -449,26 +448,28 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Int) and from->is(:Flo) and to.size < ty_int.size; let t0 = mktmp(ty_int); let val = genexpr(f, ex); - gen("\t%v = fptosi %t %v to %t\n", t0, from, val, ty_int); + gen("\t%v = fptosi %t %v to %t\n", &t0, from, &val, ty_int); let t1 = mktmp(to); - gen("\t%v = trunc %t %v to %t\n", t1, t0.ty, t0, to); + gen("\t%v = trunc %t %v to %t\n", &t1, t0.ty, &t0, to); return t1; case to->is(:Int) and from->is(:Flo); return cvt(to.u.Int.sgn ? "fptosi" : "fptoui"); case to->is(:Int) and from->is(:Bool); - let t0 = mktmp(&ty_i1); - gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); + let t0 = mktmp(#null); + let b = genexpr(f, ex); + gen("\t%v = icmp ne %t %v, 0\n", &t0, ex.ty, &b); let t1 = mktmp(to); - gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = zext %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); return t1; case to->is(:Bool) and from->is(:Int); - let t0 = mktmp(&ty_i1); - gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); + let t0 = mktmp(#null); + let b = genexpr(f, ex); + gen("\t%v = icmp ne %t %v, 0\n", &t0, ex.ty, &b); let t1 = mktmp(to); - gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = zext %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); return t1; case to->is(:Ptr) and from->is(:Ptr); @@ -480,7 +481,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Ptr) and from->is(:Arr); let addr = genref(f, ex).Addr; let t = mktmp(ex.ty); - gen("\t%v = getelementptr %t, %t %v, %t 0, %t 0\n", t, addr.ty.u.Ptr, addr.ty, addr, + gen("\t%v = getelementptr %t, %t %v, %t 0, %t 0\n", &t, addr.ty.u.Ptr, addr.ty, &addr, ty_usize, ty_usize); return t; @@ -493,6 +494,9 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { fn genblock(f *Fn, block Block) Option<Value>; fn llvmbool(f *Fn, ex *Expr) Value; +fn nop() Value { + return gentmp(ty_i8, "bitcast i8 0 to i8 ; NOP"); +} fn genexpr(f *Fn, ex *Expr) Value { fold(ex); @@ -510,7 +514,7 @@ fn genexpr(f *Fn, ex *Expr) Value { let lhs = convert(f, ex.ty, a), rhs = convert(f, ex.ty, b), t = mktmp(ex.ty); - gen("\t%v = %s %t %v, %v\n", t, inst, ex.ty, lhs, rhs); + gen("\t%v = %s %t %v, %v\n", &t, inst, ex.ty, &lhs, &rhs); t; ) ] @@ -520,27 +524,26 @@ fn genexpr(f *Fn, ex *Expr) Value { rhs = convert(f, ty2, b.rhs), t0 = mktmp(ex.ty), t1 = mktmp(ex.ty); - gen("\t%v = %s %s %t %v, %v\n", t0, ty2->is(:Flo) ? "fcmp" : "icmp", op, - ty2, lhs, rhs); - gen("\t%v = zext i1 %v to %t\n", t1, t0, ex.ty); + gen("\t%v = %s %s %t %v, %v\n", &t0, ty2->is(:Flo) ? "fcmp" : "icmp", op, + ty2, &lhs, &rhs); + gen("\t%v = zext i1 %v to %t\n", &t1, &t0, ex.ty); return t1; } ] defmacro genadd(type, lhs, rhs) [ (do let res Value #?; if isnumtype(type) { - let $t = mktmp(type); - gen("\t%v = %s %t %v, %v\n", $t, ex.ty->is(:Flo) ? "fadd" : "add", ex.ty, lhs, rhs); + let $t = gentmp(type, "%s %t %v, %v", ex.ty->is(:Flo) ? "fadd" : "add", ex.ty, &lhs, &rhs); res = $t; } else if lhs.ty->is(:Ptr) { let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, lhs.ty.u.Ptr, lhs.ty, lhs, rhs.ty, rhs); + &$t, lhs.ty.u.Ptr, lhs.ty, &lhs, rhs.ty, &rhs); res = $t; } else if rhs.ty->is(:Ptr) { let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, rhs.ty.u.Ptr, rhs.ty, rhs, rhs.ty, lhs); + &$t, rhs.ty.u.Ptr, rhs.ty, &rhs, rhs.ty, &lhs); res = $t; } else { assert(#f, "bad ad"); @@ -553,20 +556,20 @@ fn genexpr(f *Fn, ex *Expr) Value { let res Value #?; if isnumtype(type) and !lhs.ty->is(:Ptr) { let $t = mktmp(type); - gen("\t%v = %s %t %v, %v\n", $t, ex.ty->is(:Flo) ? "fsub" : "sub", ex.ty, lhs, rhs); + gen("\t%v = %s %t %v, %v\n", &$t, ex.ty->is(:Flo) ? "fsub" : "sub", ex.ty, &lhs, &rhs); res = $t; } else if lhs.ty->is(:Ptr) and rhs.ty->is(:Int) { let $off = mktmp(rhs.ty); - gen("\t%v = sub %t 0, %v\n", $off, rhs.ty, rhs); + gen("\t%v = sub %t 0, %v\n", &$off, rhs.ty, &rhs); let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, lhs.ty.u.Ptr == ty_void ? ty_i8 : lhs.ty.u.Ptr, lhs.ty, lhs, $off.ty, $off); + &$t, lhs.ty.u.Ptr == ty_void ? ty_i8 : lhs.ty.u.Ptr, lhs.ty, &lhs, $off.ty, &$off); res = $t; } else if lhs.ty->is(:Ptr) and rhs.ty->is(:Ptr) { - let $l = gentmp(ty_isize, "ptrtoint ptr %v to %t", lhs, ty_isize); - let $r = gentmp(ty_isize, "ptrtoint ptr %v to %t", rhs, ty_isize); - let $diff = gentmp(ty_isize, "sub %t %v, %v", ty_isize, $l, $r); - let $res = gentmp(ty_isize, "sdiv %t %v, %v", ty_isize, $l, $r); + let $l = gentmp(ty_isize, "ptrtoint ptr %v to %t", &lhs, ty_isize); + let $r = gentmp(ty_isize, "ptrtoint ptr %v to %t", &rhs, ty_isize); + let $diff = gentmp(ty_isize, "sub %t %v, %v", ty_isize, &$l, &$r); + let $res = gentmp(ty_isize, "sdiv %t %v, %v", ty_isize, &$l, &$r); return $res; } else { assert(#f, "bad sub"); @@ -579,7 +582,7 @@ fn genexpr(f *Fn, ex *Expr) Value { let ref = genref(f, a); let rhs = convert(f, a.ty, b); let lhs0 = genload(f, ref); - let tmp = gentmp(ex.ty, "%s %t %v, %v", inst, ex.ty, lhs0, rhs); + let tmp = gentmp(ex.ty, "%s %t %v, %v", inst, ex.ty, &lhs0, &rhs); genstore(f, ref, tmp); genload(f, ref); // load again because value could have overflowed when storing it ) @@ -648,57 +651,57 @@ fn genexpr(f *Fn, ex *Expr) Value { static orid int = {}; let id = orid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, 0\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, 0\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", &cnd, id, id); gen("OrF%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%OrT%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%OrT%d\n", id); gen("OrT%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case 'and'; static andid int = {}; let id = andid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, 0\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%AndT%d, label %%AndF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, 0\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%AndT%d, label %%AndF%d\n", &cnd, id, id); gen("AndT%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%AndF%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%AndF%d\n", id); gen("AndF%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case '??'; static orid int = {}; let id = orid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, null\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, null\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", &cnd, id, id); gen("OrF%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%OrT%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%OrT%d\n", &cnd, id, id); gen("OrT%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case else @@ -708,45 +711,48 @@ fn genexpr(f *Fn, ex *Expr) Value { static condid int = {}; let id = condid++; let lhs = genexpr(f, cond.test); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\t%v = icmp ne %t %v, %s\n", cnd, lhs.ty, lhs, lhs.ty->is(:Ptr) ? "null" : "0"); - gen("\tbr i1 %v, label %%CondT%d, label %%CondF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\t%v = icmp ne %t %v, %s\n", &cnd, lhs.ty, &lhs, lhs.ty->is(:Ptr) ? "null" : "0"); + gen("\tbr i1 %v, label %%CondT%d, label %%CondF%d\n", &cnd, id, id); gen("CondT%d: ", id); let t = convert(f, ex.ty, cond.t); - gen("\tstore %t %v, %t %v\n", ex.ty, t, tmpvar.ty, tmpvar); - gen("\tbr label %%CondFin%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &t, tmpvar.ty, &tmpvar); + gen("\tbr label %%CondFin%d\n", id); gen("CondF%d: ", id); let f = convert(f, ex.ty, cond.f); - gen("\tstore %t %v, %t %v\n", ex.ty, f, tmpvar.ty, tmpvar); - gen("\tbr label %%CondFin%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &f, tmpvar.ty, &tmpvar); + gen("\tbr label %%CondFin%d\n", id); gen("CondFin%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case UnOp un; switch un.op { case :neg; let tmp = mktmp(ex.ty); + let rhs = convert(f, ex.ty, un.ex); if ex.ty->is(:Int) { - gen("\t%v = sub %t 0, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + gen("\t%v = sub %t 0, %v\n", &tmp, ex.ty, &rhs); } else { - gen("\t%v = fsub %t 0.0, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + gen("\t%v = fsub %t 0.0, %v\n", &tmp, ex.ty, &rhs); } return tmp; case :compl; let tmp = mktmp(ex.ty); - gen("\t%v = xor %t -1, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + let rhs = convert(f, ex.ty, un.ex); + gen("\t%v = xor %t -1, %v\n", &tmp, ex.ty, &rhs); return tmp; case :not; - let tmp = mktmp(&ty_i1); - gen("\t%v = xor i1 1, %v\n", tmp, ex.ty, llvmbool(f, un.ex)); + let tmp = mktmp(#null); + let rhs = llvmbool(f, un.ex); + gen("\t%v = xor i1 1, %v\n", &tmp, &rhs); let res = mktmp(ex.ty); - gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); + gen("\t%v = zext i1 %v to %t\n", &res, &tmp, res.ty); return res; case :preinc, :predec; @@ -755,9 +761,9 @@ fn genexpr(f *Fn, ex *Expr) Value { let val = mktmp(ex.ty); let var = genload(f, ref); if ex.ty->is(:Ptr) { - gen("\t%v = getelementptr %t, %t %v, i32 %v\n", val, ex.ty.u.Ptr, ex.ty, var, one); + gen("\t%v = getelementptr %t, %t %v, i32 %v\n", &val, ex.ty.u.Ptr, ex.ty, &var, &one); } else { - gen("\t%v = add %t %v, %v\n", val, ex.ty, var, one); + gen("\t%v = add %t %v, %v\n", &val, ex.ty, &var, &one); } genstore(f, ref, val); return genload(f, ref); // load again because value could have overflowed when storing it @@ -768,9 +774,9 @@ fn genexpr(f *Fn, ex *Expr) Value { let val = mktmp(ex.ty); let var = genload(f, ref); if ex.ty->is(:Ptr) { - gen("\t%v = getelementptr %t, %t %v, i32 %v\n", val, ex.ty.u.Ptr, ex.ty, var, one); + gen("\t%v = getelementptr %t, %t %v, i32 %v\n", &val, ex.ty.u.Ptr, ex.ty, &var, &one); } else { - gen("\t%v = add %t %v, %v\n", val, ex.ty, var, one); + gen("\t%v = add %t %v, %v\n", &val, ex.ty, &var, &one); } genstore(f, ref, val); return var; @@ -778,7 +784,7 @@ fn genexpr(f *Fn, ex *Expr) Value { case :deref; let rhs = genexpr(f, un.ex); let val = mktmp(ex.ty); - gen("\t%v = load %t, %t %v\n", val, ex.ty, rhs.ty, rhs); + gen("\t%v = load %t, %t %v\n", &val, ex.ty, rhs.ty, &rhs); return val; case :addrof; @@ -806,13 +812,13 @@ fn genexpr(f *Fn, ex *Expr) Value { case SPtr sl; let sl = genexpr(f, sl); let ptr = mktmp(mkptrtype(sl.ty.u.Slice)); - gen("\t%v = extractvalue %t %v, 0\n", ptr, sl.ty, sl); + gen("\t%v = extractvalue %t %v, 0\n", &ptr, sl.ty, &sl); return ptr; case SLen sl; let sl = genexpr(f, sl); let len = mktmp(ty_usize); - gen("\t%v = extractvalue %t %v, 1\n", len, sl.ty, sl); + gen("\t%v = extractvalue %t %v, 1\n", &len, sl.ty, &sl); return len; case EUTag; @@ -837,41 +843,41 @@ fn genexpr(f *Fn, ex *Expr) Value { let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } else if sl.lhs.ty.u.#tag == :Ptr { let addr = genexpr(f, sl.lhs); let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } else if sl.lhs.ty.u.#tag == :Slice { let slice = genexpr(f, sl.lhs); let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let addr = mktmp(mkptrtype(slice.ty.u.Slice)); - gen("\t%v = extractvalue %t %v, 0", addr, ex.ty, slice); + gen("\t%v = extractvalue %t %v, 0", &addr, ex.ty, &slice); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } @@ -895,14 +901,14 @@ fn genexpr(f *Fn, ex *Expr) Value { } let t Value = mktmp(ex.ty); if fnty.ret->is(:Void) { - gen("\tcall void %v(", lhs); + gen("\tcall void %v(", &lhs); } else { t = mktmp(ex.ty); - gen("\t%v = call %t %v(", t, call.lhs.ty->is(:Ptr) ? call.lhs.ty.u.Ptr : call.lhs.ty, lhs); + gen("\t%v = call %t %v(", &t, call.lhs.ty->is(:Ptr) ? call.lhs.ty.u.Ptr : call.lhs.ty, &lhs); } foreach_ptr(arg, i, call.args) { let ty = i < fnty.params.#len ? fnty.params[i] : varargpromote(arg.ty); - gen("%t %v", ty, args[i]); + gen("%t %v", ty, &args[i]); if i < call.args.#len - 1 { gen(", "); } @@ -918,37 +924,38 @@ fn genexpr(f *Fn, ex *Expr) Value { let ty = mkarrtype(ini.maxn, #f, ex.ty.u.Arr.child); let tmp = genref(f, ex).Addr; let val = mktmp(ty); - gen("\t%v = load %t, %t %v\n", val, ty, tmp.ty, tmp); + gen("\t%v = load %t, %t %v\n", &val, ty, tmp.ty, &tmp); return val; case EUnionIni ini; let t0 = mktmp(mkptrtype(ex.ty)); let vidx = ini.var - ex.ty.u.Agg.flds.#ptr; - gen("\t%v = alloca %t\n", t0, ex.ty); - gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, t0.ty, t0); - gen("\tstore %t %d, %t %v\n", ex.ty.u.Agg.enumty.u.Enum.intty, vidx, t0.ty, t0); + gen("\t%v = alloca %t\n", &t0, ex.ty); + gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, t0.ty, &t0); + gen("\tstore %t %d, %t %v\n", ex.ty.u.Agg.enumty.u.Enum.intty, vidx, t0.ty, &t0); if ini.var.ty != #null { let tini = convert(f, ini.var.ty, ini.ex); let t1 = mktmp(mkptrtype(ini.var.ty)); - gen("\t%v = bitcast %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = bitcast %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); let t2 = mktmp(t1.ty); - gen("\t%v = getelementptr %t, %t %v, i32 1\n", t2, ini.var.ty, t1.ty, t1); - gen("\tstore %t %v, %t %v\n", tini.ty, tini, t2.ty, t2); + gen("\t%v = getelementptr %t, %t %v, i32 1\n", &t2, ini.var.ty, t1.ty, &t1); + gen("\tstore %t %v, %t %v\n", tini.ty, &tini, t2.ty, &t2); } let res = mktmp(ex.ty); - gen("\t%v = load %t, %t %v\n", res, res.ty, t0.ty, t0); + gen("\t%v = load %t, %t %v\n", &res, res.ty, t0.ty, &t0); return res; case VaStart ap; - gen("\tcall void @llvm.va_start(ptr %v)\n", genref(f, ap).Addr); - return mktmp(ty_void); + // gen("\tcall void @llvm.va_start(ptr %v)\n", genref(f, ap).Addr); + return nop(); case VaArg ap; - return gentmp(ex.ty, "va_arg ptr %v, %t", genref(f, ap).Addr, ex.ty); + let ap = genref(f, ap).Addr; + return gentmp(ex.ty, "va_arg ptr %v, %t", &ap, ex.ty); case VaEnd ap; - gen("\tcall void @llvm.va_end(ptr %v)\n", genref(f, ap).Addr); - return mktmp(ty_void); + // gen("\tcall void @llvm.va_end(ptr %v)\n", genref(f, ap).Addr); + return nop(); case Stmt block; switch genblock(f, block) { @@ -963,19 +970,15 @@ fn genexpr(f *Fn, ex *Expr) Value { fn llvmbool(f *Fn, ex *Expr) Value { let v = genexpr(f, ex); - let t = mktmp(&ty_i1); + let t = mktmp(#null); if v.ty->is(:Bool) or v.ty->is(:Int) { - gen("\t%v = icmp ne %t %v, 0\n", t, v.ty, v); + gen("\t%v = icmp ne %t %v, 0\n", &t, v.ty, &v); } else { - gen("\t%v = icmp ne %t %v, null\n", t, v.ty, v); + gen("\t%v = icmp ne %t %v, null\n", &t, v.ty, &v); } return t; } -fn nop() void { - gen("\t%%t%d = bitcast i8 0 to i8 ; NOP\n", tmpid++); -} - fn genstmt(f *Fn, block *Block, st *Stmt) void { gen(";; line %d\n", st.loc.line); switch st.u { @@ -993,15 +996,16 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\t%%%s.%d = alloca %t\n", nam, var.id, ty); switch var.ini { case Some *ex; + let it = convert(f, ty, ex); gen("\tstore %t %v, %t %%%s.%d\n", - ty, convert(f, ty, ex), mkptrtype(ty), nam, var.id); + ty, &it, mkptrtype(ty), nam, var.id); } } case If *cnd; static ifid int = {}; let id = ifid++; - gen("\tbr i1 %v, label %%IfT%d, label %%IfF%d\n", - llvmbool(f, &cnd.test), id, id); + let test = llvmbool(f, &cnd.test); + gen("\tbr i1 %v, label %%IfT%d, label %%IfF%d\n", &test, id, id); gen("IfT%d:", id); nop(); genblock(f, cnd.t); @@ -1021,8 +1025,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Next%d:", loop.id); nop(); genblock(f, loop.body); @@ -1038,8 +1042,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Brk%d:",loop.id); nop(); @@ -1048,8 +1052,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Next%d:", loop.id); nop(); genblock(f, loop.body); @@ -1077,13 +1081,14 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tret void\n"); case Some *e; let retty = f.ty.u.Fn.ret; - gen("\tret %t %v\n", retty, convert(f, retty, e)); + let it = convert(f, retty, e); + gen("\tret %t %v\n", retty, &it); } case ISwitch *sw; static swid int = {}; let id = swid++; let test = genexpr(f, &sw.ex); - gen("\tswitch %t %v, label %%ISx%d [", test.ty, test, id); + gen("\tswitch %t %v, label %%ISx%d [", test.ty, &test, id); foreach (c, i, sw.cs) { foreach_ptr (ex, _, c.es) { assert(ex.u.#tag == :IntLit or ex.u.#tag == :EnumIni, "case"); @@ -1110,21 +1115,21 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { exaddr = genref(f, &sw.ex).Addr; } else { exaddr = mktmp(mkptrtype(sw.ex.ty)); - gen("\t%v = alloca %t\n", exaddr, exaddr.ty); + gen("\t%v = alloca %t\n", &exaddr, exaddr.ty); let test = genexpr(f, &sw.ex); - gen("\tstore %t %v, %t %v\n", test.ty, test, exaddr.ty, exaddr); + gen("\tstore %t %v, %t %v\n", test.ty, &test, exaddr.ty, &exaddr); } let tag = (do let addr = mktmp(mkptrtype(sw.ex.ty.u.Agg.enumty)); - gen("\t%v = bitcast %t %v to %t\n", addr, exaddr.ty, exaddr, addr.ty); + gen("\t%v = bitcast %t %v to %t\n", &addr, exaddr.ty, &exaddr, addr.ty); let tmp = mktmp(sw.ex.ty.u.Agg.enumty); - gen("\t%v = load %t, %t %v\n", tmp, tmp.ty, addr.ty, addr); + gen("\t%v = load %t, %t %v\n", &tmp, tmp.ty, addr.ty, &addr); tmp; ); - gen("\tswitch %t %v, label %%ESx%d [ ", tag.ty, tag, id); + gen("\tswitch %t %v, label %%ESx%d [ ", tag.ty, &tag, id); foreach (c, i, sw.cs) { let t = Value{tag.ty, :IImm(c.variant)}; - gen(" %t %v, label %%ES%d.%d ", t.ty, t, id, i); + gen(" %t %v, label %%ES%d.%d ", t.ty, &t, id, i); } gen(" ]\n"); foreach (c, i, sw.cs) { @@ -1132,14 +1137,14 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { if c.capt { gen("\t%%%s.%d = alloca %t\n", c.capt, c.captid, c.captty); let valaddr = mktmp(mkptrtype(c.fld.ty)); - gen("\t%v = getelementptr i8, %t %v, i32 %d\n", valaddr, exaddr.ty, exaddr, + gen("\t%v = getelementptr i8, %t %v, i32 %d\n", &valaddr, exaddr.ty, &exaddr, as(int)c.fld.off); if c.captptr { - gen("\tstore %t %v, %t %%%s.%d\n", valaddr.ty, valaddr, mkptrtype(c.captty), c.capt, c.captid); + gen("\tstore %t %v, %t %%%s.%d\n", valaddr.ty, &valaddr, mkptrtype(c.captty), c.capt, c.captid); } else { let val = mktmp(c.captty); - gen("\t%v = load %t, %t %v\n", val, val.ty, valaddr.ty, valaddr); - gen("\tstore %t %v, %t %%%s.%d\n", val.ty, val, mkptrtype(c.captty), c.capt, c.captid); + gen("\t%v = load %t, %t %v\n", &val, val.ty, valaddr.ty, &valaddr); + gen("\tstore %t %v, %t %%%s.%d\n", val.ty, &val, mkptrtype(c.captty), c.capt, c.captid); } } genblock(f, c.t); @@ -1161,7 +1166,7 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { } foreach (c, i, sw.cs) { let t = llvmbool(f, &c.test); - gen("\tbr i1 %v, label %%CST%d.%d, label %%CSF%d.%d\n", t, id, i, id, i); + gen("\tbr i1 %v, label %%CST%d.%d, label %%CSF%d.%d\n", &t, id, i, id, i); gen("CST%d.%d: ", id, i); genblock(f, c.t); gen("\tbr label %%CSe%d\n", id); @@ -1281,7 +1286,6 @@ struct IntTraits<T> { } fn gendata(ty *const Type, ex *Expr) void { - fn dataaddr(ex *Expr) void { switch ex.u { case Symbol decl; @@ -1306,11 +1310,11 @@ fn gendata(ty *const Type, ex *Expr) void { case BoolLit b; return gen("%d", b); case NullLit; return gen("null"); case ZeroIni; return gen("zeroinitializer"); - case StrLit s; + case StrLit *s; if ty->is(:Arr) { return gen("c%S", s); } else { - strs->push(s); + strs->push(*s); return gen("@.str.%z", strs.len - 1); } case UnOp un; @@ -1390,7 +1394,7 @@ extern fn llvm_fini() void { gen("declare void @llvm.va_copy(ptr, ptr)\n"); gen("declare void @llvm.va_end(ptr)\n"); vec_each(s, i, strs) { - gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, s); + gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, &s); } map_each(g, k, globls) { if g.t != :Decl { diff --git a/src/parse.cff b/src/parse.cff index 3be70cf..aad88d1 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -584,9 +584,9 @@ fn lexexpects(P *Parser, t TokT, what *const u8) Tok { let tok = Tok {}; if !lexmatch(P, &tok, t) { if what { - fatal(P, tok.loc, "expected %s (near %qT)", what, tok); + fatal(P, tok.loc, "expected %s (near %qT)", what, &tok); } else { - fatal(P, tok.loc, "expected %qk (near %qT)", t, tok); + fatal(P, tok.loc, "expected %qk (near %qT)", t, &tok); } } return tok; @@ -626,7 +626,7 @@ fn putdecl(P *Parser, eloc Loc, decl Decl) *Decl { let d0 *const Decl; let d = envput(P.curenv, decl, &d0); if d == #null { - fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc); + fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc); } return d; } @@ -638,7 +638,7 @@ fn putdecl_alloc(P *Parser, alloc *Allocator, eloc Loc, decl Decl) *Decl { let d0 *const Decl; let d = envput_alloc(P.curenv, alloc, decl, &d0); if d == #null { - fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, d0.loc); + fatal(P, eloc, "attempt to redefine `%s' (previously defined at %l)", decl.name, &d0.loc); } return d; } @@ -1160,7 +1160,7 @@ fn parsetype(P *Parser) *const Type { return parsebitfield(P, #{name} #null); case else; - fatal(P, tok.loc, "expected type (near %qT)", tok); + fatal(P, tok.loc, "expected type (near %qT)", &tok); } } @@ -1185,7 +1185,7 @@ fn parseaggini(P *Parser, loc Loc, ty *const Type) Expr { fld = findaggfield(ty, (tok = lexexpects(P, :ident, "field name")).u.ident); lexexpect(P, ':'); if fld == #null { - fatal(P, tok.loc, "%t has no such field %qT", ty, tok); + fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } iota = (fld - ty.u.Agg.flds.#ptr) + 1; } else { @@ -1384,7 +1384,7 @@ fn pexprimary(P *Parser) Expr { fn resolvedecl(P *Parser, tok Tok, decl *Decl, ex *Expr) void { let fakedecl Decl #?; if decl == #null { - fatal(P, tok.loc, "%qT is not defined", tok); + fatal(P, tok.loc, "%qT is not defined", &tok); } while #t { switch decl.u { @@ -1409,7 +1409,7 @@ fn pexprimary(P *Parser) Expr { let name = (tok = lexexpect(P, :ident)).u.ident; decl = envfind_noparent(ty.u.Agg.decls, name); if decl == #null { - fatal(P, tok.loc, "%t has no such decl %qT", ty, tok); + fatal(P, tok.loc, "%t has no such decl %qT", ty, &tok); } continue; } else if !ty->is(:Agg) and !ty->is(:Enum) { @@ -1502,7 +1502,7 @@ fn pexprimary(P *Parser) Expr { let name = (tok = lexexpect(P, :ident)).u.ident; let fld = findaggfield(ty, name); if fld == #null { - fatal(P, tok.loc, "%t has no such field %qT", ty, tok); + fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } off += fld.off; ty = fld.ty; @@ -1545,27 +1545,27 @@ fn pexprimary(P *Parser) Expr { break #'search; } } - fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok); } while #f; ex = { tok.loc, ty, :EnumIni(i) }; } else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion { let name = (tok = lexexpects(P, :ident, "variant name")).u.ident; let fld = findaggfield(ty, name); if fld == #null { - fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", ty, &tok); } let iex *Expr = #null; if lexpeek(P).t == '(' or lexpeek(P).t == '{' { P.targty = fld.ty; iex = exprdup(P.alloc, parseexpr(P)); if fld.ty == #null { - fatal(P, iex.loc, "%t variant %qT is empty", ty, tok); + fatal(P, iex.loc, "%t variant %qT is empty", ty, &tok); } if !typematchestarg(fld.ty, iex.ty) { fatal(P, iex.loc, "bad enum union initializer (%t, expected %t)", iex.ty, fld.ty); } } else if fld.ty { - fatal(P, tok.loc, "%t variant %qT must be initialized", ty, tok); + fatal(P, tok.loc, "%t variant %qT must be initialized", ty, &tok); } ex = { tok.loc, ty, :EUnionIni { fld, iex }}; } else { @@ -1590,7 +1590,7 @@ fn pexprimary(P *Parser) Expr { } } case else; - fatal(P, tok.loc, "expected expression (near %qT)", tok); + fatal(P, tok.loc, "expected expression (near %qT)", &tok); } P.targty = #null; return ex; @@ -1614,10 +1614,13 @@ fn pexpostfix(P *Parser) Expr { while !lexmatch(P, #null, ')') { P.targty = args.len + 1 <= params.#len ? *param : #null; let ex = parseexpr(P); - args->push(ex); if args.len > params.#len and !Fn.variadic { fatal(P, ex.loc, "too many args (%z, expected %z)", args.len, params.#len); } + if args.len >= params.#len and (ex.ty->is(:Agg) or ex.ty->is(:Slice) or ex.ty->is(:VaList)) { + err(P, ex.loc, "cannot pass aggregate value as variadic argument"); + } + args->push(ex); if args.len <= params.#len and !typematchestarg(*param, ex.ty) { err(P, ex.loc, "function call argument type mismatch (%t, expected %t)", ex.ty, *param); @@ -1663,13 +1666,13 @@ fn pexpostfix(P *Parser) Expr { } case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--'); if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !islvalue(&ex) { - err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok); + err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok); } if ex.ty.konst { - err(P, ex.loc, "left operand to prefix %qT operator is const", tok); + err(P, ex.loc, "left operand to prefix %qT operator is const", &tok); } ex = { tok.loc, ex.ty, .u: :UnOp { @@ -1694,8 +1697,8 @@ fn pexpostfix(P *Parser) Expr { break; } } - if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); } - if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", tok); } + if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } + if fld.ty == #null { fatal(P, tok.loc, "field %qT has no type", &tok); } ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :Dot { exprdup(P.alloc, ex), fld }}; case BitF *bitf; let fld *BitFField = #null; @@ -1705,7 +1708,7 @@ fn pexpostfix(P *Parser) Expr { break; } } - if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, tok); } + if fld == #null { fatal(P, tok.loc, "%t has no such field %qT", ty, &tok); } ex = { tok.loc, konst ? constify(fld.ty) : fld.ty, :BitDot { exprdup(P.alloc, ex), fld }}; case else fatal(P, tok.loc, "left-hand-side is not an aggregate (%t)", ty); @@ -1774,7 +1777,7 @@ fn pexpostfix(P *Parser) Expr { case Agg *agg; let decl *Decl = agg.decls ? envfind_noparent(agg.decls, name) : #null; if decl == #null { - fatal(P, tok.loc, "%t has no such method %qT", ty, tok); + fatal(P, tok.loc, "%t has no such method %qT", ty, &tok); } lexexpect(P, '('); switch decl.u { @@ -1859,6 +1862,9 @@ fn pexpostfix(P *Parser) Expr { let type = parsetype(P); lexmatch(P, #null, ','); lexexpect(P, ')'); + if type->is(:Agg) { + err(P, tok.loc, "unsupported use of variadic arg of aggregate type"); + } ex = { tok.loc, type, :VaArg(exprdup(P.alloc, ex)) }; case streq(name, "end"); @@ -1889,10 +1895,10 @@ fn pexprefix(P *Parser) Expr { let ex = pexprefix(P); let ty = typeof2(ex.ty, ty_int); if ty == #null { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !ty->is(:Int) and tok.t == '~' { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } return { tok.loc, ty, .u: :UnOp { @@ -1902,13 +1908,13 @@ fn pexprefix(P *Parser) Expr { case lexmatch(P, &tok, '++') or lexmatch(P, &tok, '--'); let ex = pexprefix(P); if !isnumtype(ex.ty) and !ex.ty->is(:Ptr) { - fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + fatal(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } if !islvalue(&ex) { - err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", tok); + err(P, ex.loc, "left operand to prefix %qT operator is not lvalue", &tok); } if ex.ty.konst { - err(P, ex.loc, "left operand to prefix %qT operator is const", tok); + err(P, ex.loc, "left operand to prefix %qT operator is const", &tok); } return { tok.loc, ex.ty, .u: :UnOp { @@ -1918,7 +1924,7 @@ fn pexprefix(P *Parser) Expr { case lexmatch(P, &tok, '!'); let ex = pexprefix(P); if !ex.ty->is(:Bool) { - err(P, ex.loc, "invalid operand to unary operator %qT (%t)", tok, ex.ty); + err(P, ex.loc, "invalid operand to unary operator %qT (%t)", &tok, ex.ty); } return { tok.loc, ty_bool, .u: :UnOp { :not, exprdup(P.alloc, ex) }}; @@ -2043,13 +2049,13 @@ fn pexcmp(P *Parser) Expr { P.targty = #null; if typeof2(ex.ty, rhs.ty) == #null { fatal(P, tok.loc, "incompatible operands %t and %t to binary operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); } let ty = typeof2(ex.ty, rhs.ty); if tok.t != '==' and tok.t != '!=' { if !isnumtype(ty) and !ty->is(:Ptr) { fatal(P, tok.loc, "invalid non-numeric operands %t and %t to relational operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); } fn ispositiveintlit(ex Expr) bool { return ex.u.#tag == :IntLit and ex.u.IntLit.i >- 0; @@ -2167,14 +2173,14 @@ fn pexassign(P *Parser) Expr { and !((ex.ty->is(:Ptr) and rhs.ty->is(:Int) and (tok.t == '+=' or tok.t == '-='))); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case okind == :IntFlo and (!isnumtype(ex.ty) or !isnumtype(rhs.ty)); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case okind == :Int and (!ex.ty->is(:Int) or !rhs.ty->is(:Int)); err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT", - ex.ty, rhs.ty, tok); + ex.ty, rhs.ty, &tok); case ex.ty.konst; err(P, ex.loc, "left operand to assignment is const"); } @@ -2380,7 +2386,7 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt { err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty); } if seen->get(e.u.IntLit.i) { - err(P, e.loc, "duplicate case expression (previously seen at %l)", *seen->get(e.u.IntLit.i)); + err(P, e.loc, "duplicate case expression (previously seen at %l)", seen->get(e.u.IntLit.i)); } seen->put(e.u.IntLit.i, e.loc); es->push(e); @@ -2421,12 +2427,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { let vname = (tok = lexexpect(P, :ident)).u.ident; c.fld = findaggfield(test.ty, vname); if c.fld == #null { - fatal(P, tok.loc, "%t has no such variant %qT", test.ty, tok); + fatal(P, tok.loc, "%t has no such variant %qT", test.ty, &tok); } c.variant = c.fld - test.ty.u.Agg.flds.#ptr; if seen->get(c.variant) { - err(P, tok.loc, "duplicate case expression (previously seen at %l)", *seen->get(c.variant)); + err(P, tok.loc, "duplicate case expression (previously seen at %l)", seen->get(c.variant)); } seen->put(c.variant, tok.loc); @@ -2558,7 +2564,7 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void { if lexmatch(P, &tok2, :label) { let decl = finddecl(P, tok2.u.ident); if decl == #null { - fatal(P, tok2.loc, "no such label %qT", tok2); + fatal(P, tok2.loc, "no such label %qT", &tok2); } assert(decl.u.#tag == :Label, "label?"); loop = decl.u.Label; @@ -2700,7 +2706,7 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie } let decll *Decl #?; yield(decll = putdecl(P, tok.loc, decl), yarg); - if !letp and !fwd { + if !letp and !fwd and !P.error { llvm_genstatic(decl.externp, decl.name, &decl.u.Static); } @@ -2765,7 +2771,9 @@ fn parsefn(P *Parser, loc Loc, toplevel bool, externp bool, name *const u8) *Dec P.curblock = block; popenv(P); // ir_genfn(P.irctx, Fn); - llvm_genfn(externp, name, Fn); + if !P.error { + llvm_genfn(externp, name, Fn); + } (as(*Arena)P.alloc.a)->destroy(); } } @@ -2994,7 +3002,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) if streq(a, "lax") { attr |= ATTR_LAX; } else { - err(P, tok.loc, "unknown attribute %qT", tok); + err(P, tok.loc, "unknown attribute %qT", &tok); } } } @@ -3145,7 +3153,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) return parsedecls(P, tok.loc, yield, yarg, toplevel); } } - fatal(P, tok.loc, "expected declaration (near %qT)", tok); + fatal(P, tok.loc, "expected declaration (near %qT)", &tok); } if yield != #null and decl != #null { @@ -3176,7 +3184,6 @@ extern fn parse(P *Parser) [#]Decl { let alloc = Allocator { &aralloc, &Arena:allocf, #null }; let decls Vec<Decl> = {}; P.alloc = (P.tlalloc = &alloc); - P.irctx = mkirctx(P.alloc); P.curenv = mkenv(#null, P.alloc); if primenv == #null { primenv = mkenv(#null, P.alloc); @@ -3194,7 +3201,9 @@ extern fn parse(P *Parser) [#]Decl { } } - llvm_fini(); + if !P.error { + llvm_fini(); + } envfree(P.curenv); aralloc->destroy(); return decls.dat[0::decls.len]; diff --git a/src/targ.cff b/src/targ.cff index f0b500b..583a733 100644 --- a/src/targ.cff +++ b/src/targ.cff @@ -24,8 +24,6 @@ extern fn targ_ini(name *const u8) bool { foreach(targ, i, targs[0::]) { if streq(name, targ.name) { g_targ = targs[i]; - g_targ.B = &g_asmbackend; - g_targ.B.initf(g_targ.B, stdout); return #t; } } |