aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-29 23:01:37 +0200
committerlemon <lsof@mailbox.org>2022-08-29 23:01:37 +0200
commit34313d801d38aa726d01b7f09690fb7a86ac47dd (patch)
treeef891f88562c167e732dc7d7b9a8a656f92da6cd /src
parent2f243de6ce9402f880677a07b832c0e56a7f688d (diff)
remove ir*.cff; make vararg only with primitive types
Diffstat (limited to 'src')
-rw-r--r--src/asm.cff109
-rw-r--r--src/cffc.hff20
-rw-r--r--src/fmt.cff14
-rw-r--r--src/ir.cff10
-rw-r--r--src/ir.hff80
-rw-r--r--src/irdump.cff173
-rw-r--r--src/irgen.cff440
-rw-r--r--src/llvm.cff350
-rw-r--r--src/parse.cff95
-rw-r--r--src/targ.cff2
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;
}
}