diff options
| -rw-r--r-- | src/llvm.cff | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/src/llvm.cff b/src/llvm.cff index b839f09..c07ab4a 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -128,6 +128,9 @@ fn gen(fmt *const u8, ...) void { } static tmpid int = 1; +fn mktmp(ty *const Type) Value { + return Value{ty, :Tmp(tmpid++)}; +} fn genexpr(f *Fn, ex *Expr) Value; static arena Arena = {}; @@ -142,22 +145,25 @@ fn genaddr(f *Fn, e *Expr) Value { let s = p[0::s.#len]; strs->push(s); return {mkptrtype(e.ty), :StrConstRef(strs.len - 1)}; - case else - assert(#f, "genaddr"); + case Symbol decl; + switch decl.u { + case Let *var; return {var.ty, :LocalRef(var)}; + case Static *var; return {var.ty, :GlobalRef(var)}; + } } + assert(#f, "genaddr"); } fn convert(f *Fn, to *const Type, ex *Expr) Value { let from = ex.ty; defmacro cvt(inst) [ - (do let t = Value{to, :Tmp(tmpid++)}, + (do let t = mktmp(to), val = genexpr(f, ex); gen("\t%v = %s %t %v to %t\n", t, inst, from, val, to); t; ) ] - switch { case from == to; return genexpr(f, ex); @@ -188,10 +194,16 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Flo) and from->is(:Flo) and to.size < from.size; return cvt("fptrunc"); + + case to->is(:Ptr) and from->is(:Ptr); + let t = mktmp(to), + val = genexpr(f, ex); + gen("\t%v = bitcast %t %v to %t\n", t, from, val, to); + return t; case to->is(:Ptr) and from->is(:Arr); let addr = genaddr(f, ex); - let t = Value{ex.ty, :Tmp(tmpid++)}; + 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, ty_usize, ty_usize); return t; @@ -215,7 +227,7 @@ fn genexpr(f *Fn, ex *Expr) Value { defmacro genbinop(inst) [ { let lhs = convert(f, ex.ty, b.lhs), rhs = convert(f, ex.ty, b.rhs), - t = Value{ex.ty, :Tmp(tmpid++)}; + t = mktmp(ex.ty); gen("\t%v = %s %t %v, %v\n", t, inst, ex.ty, lhs, rhs); return t; } ] @@ -223,8 +235,8 @@ fn genexpr(f *Fn, ex *Expr) Value { defmacro gencmp(op) [ { let lhs = convert(f, ty2, b.lhs), rhs = convert(f, ty2, b.rhs), - t0 = Value{ex.ty, :Tmp(tmpid++)}, - t1 = Value{ex.ty, :Tmp(tmpid++)}; + 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); @@ -252,16 +264,29 @@ fn genexpr(f *Fn, ex *Expr) Value { case else assert(#f, "binop? %d", b.op); } - case UnOp op; + case UnOp un; + switch un.op { + case :preinc, :predec; + let one = Value{ex.ty, :IImm(un.op == :preinc ? 1 : -1)}; + let addr = genaddr(f, un.ex); + let var = mktmp(ex.ty); + let val = mktmp(ex.ty); + gen("\t%v = load %t, %t* %v\n", var, ex.ty, ex.ty, addr); + gen("\t%v = add %t %v, %v\n", val, ex.ty, var, one); + gen("\tstore %t %v, %t* %v\n", ex.ty, val, ex.ty, addr); + return val; + case else + assert(#f, "unop?"); + } case Symbol decl; switch decl.u { case Let *var; - let t = Value{ex.ty, :Tmp(tmpid++)}; + let t = mktmp(ex.ty); gen("\t%v = load %t, %t* %%%s.%d\n", t, ex.ty, ex.ty, decl.name, var.id); return t; case Static *var; - let t = Value{ex.ty, :Tmp(tmpid++)}; + let t = mktmp(ex.ty); if decl.externp { gen("\t%v = load %t, %t* @%s\n", t, ex.ty, ex.ty, decl.name); } else { @@ -282,7 +307,7 @@ fn genexpr(f *Fn, ex *Expr) Value { let ty = i < fnty.params.#len ? fnty.params[i] : typeof2(arg.ty, arg.ty); args[i] = convert(f, ty, arg); } - let t = Value{ex.ty, :Tmp(tmpid++)}; + let t = mktmp(ex.ty); gen("\t%v = call %t %v(", t, call.lhs.ty, lhs); foreach_ptr(arg, i, call.args) { let ty = i < fnty.params.#len ? fnty.params[i] : typeof2(arg.ty, arg.ty); @@ -301,7 +326,7 @@ fn genexpr(f *Fn, ex *Expr) Value { fn llvmbool(f *Fn, ex *Expr) Value { let v = genexpr(f, ex); - let t = Value{ty_i1, :Tmp(tmpid++)}; + let t = mktmp(ty_i1); if v.ty->is(:Bool) or v.ty->is(:Int) { gen("\t%v = icmp ne %t %v, 0\n", t, v.ty, v); } else { @@ -412,7 +437,7 @@ static funcs Map<FuncKey, FuncEntry, struct { return h; } fn eq(a FuncKey, b FuncKey) bool { - return a.name == b.name and a.externp == b.externp; + return streq(a.name, b.name) and a.externp == b.externp; } }> = {}; @@ -427,9 +452,7 @@ extern fn llvm_addfn(decl *Decl) void { } extern fn llvm_genfn(externp bool, name *const u8, f *Fn) void { - if externp { - funcs->put({name, externp}, {:Def, f.ty, f.id}); - } + funcs->put({name, externp}, {:Def, f.ty, f.id}); tmpid = 0; gen("define%s %t ", externp ? "" : " internal", f.ty.u.Fn.ret); if !externp { @@ -486,7 +509,7 @@ extern fn llvm_fini() void { map_each(f, k, funcs) { if f.t == :Decl { let ty = f.ty; - gen("declare%s %t ", k.externp ? "" : " internal", ty.u.Fn.ret); + gen("declare %t ", ty.u.Fn.ret); if !k.externp { gen("@%s.%d(", k.name, f.id); } else { |