aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-23 05:58:49 +0200
committerlemon <lsof@mailbox.org>2022-08-23 05:58:49 +0200
commit09ea9f98e696235bf637c1df723d5796b4c9d185 (patch)
treeeff84352358f4fbd3937bf36c92fd047c20866de /src
parentd74ed7fb65bf7ac245d2548ac13f3f3fdabadd16 (diff)
ack works
Diffstat (limited to 'src')
-rw-r--r--src/llvm.cff59
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 {