aboutsummaryrefslogtreecommitdiff
path: root/src/llvm.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-24 06:46:23 +0200
committerlemon <lsof@mailbox.org>2022-08-24 06:46:23 +0200
commite5ed3b20351a2715fe88d9a5dbcc8e6757fe96aa (patch)
tree7333f357bc38ed389e8845d59196594377dc46d6 /src/llvm.cff
parent039ab20bbf6b68c423f420be2481b447d85c606b (diff)
llvm defer and more
Diffstat (limited to 'src/llvm.cff')
-rw-r--r--src/llvm.cff119
1 files changed, 95 insertions, 24 deletions
diff --git a/src/llvm.cff b/src/llvm.cff
index 4ea469d..053d44d 100644
--- a/src/llvm.cff
+++ b/src/llvm.cff
@@ -55,6 +55,7 @@ fn gen(fmt *const u8, ...) void {
}
}
gen(") ");
+ case VaList; gen("%s", g_targ.valistllvmty);
}
}
@@ -94,7 +95,7 @@ fn gen(fmt *const u8, ...) void {
switch ap->arg(Value).u {
case IImm i; gen("%I", i);
case FImm f; gen("%f", f);
- case BImm b; gen("%s", b ? "true" : "false");
+ case BImm b; gen("%d", as(int)b);
case Null; gen("null");
case ZeroIni; gen("zeroinitializer");
case Tmp t; fprintf(outfp, "%%t%d", t);
@@ -235,7 +236,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value {
}
}
-fn genblock(f *Fn, block [#]Stmt) void;
+fn genblock(f *Fn, block Block) Option<Value>;
fn genexpr(f *Fn, ex *Expr) Value {
fold(ex);
@@ -333,8 +334,8 @@ fn genexpr(f *Fn, ex *Expr) Value {
rhs = b.rhs.ty->is(:Ptr) ? genexpr(f, b.rhs) : convert(f, ty2 ?? b.rhs.ty, b.rhs);
return gensub(ex.ty, lhs, rhs);
case '*'; return genbinop(b.lhs, b.rhs, !ex.ty->is(:Flo) ? "mul" : "fmul");
- case '/'; return genbinop(b.lhs, b.rhs, ex.ty->is(:Flo) ? "fdiv"
- : ex.ty.u.Int.sgn ? "sdiv" : "udiv");
+ case '/'; return genbinop(b.lhs, b.rhs,
+ ex.ty->is(:Flo) ? "fdiv" : ex.ty.u.Int.sgn ? "sdiv" : "udiv");
case '%'; return genbinop(b.lhs, b.rhs, ex.ty.u.Int.sgn ? "srem" : "urem");
case '&'; return genbinop(b.lhs, b.rhs, "and");
case '|'; return genbinop(b.lhs, b.rhs, "or");
@@ -376,12 +377,12 @@ fn genexpr(f *Fn, ex *Expr) Value {
ex.ty, b.lhs, b.rhs);
case '%=';
return genassignop(ex.ty.u.Int.sgn ? "srem" : "urem", ex.ty, b.lhs, b.rhs);
- case '&='; return genassignop("and", ex.ty, b.lhs, b.rhs);
- case '|='; return genassignop("or", ex.ty, b.lhs, b.rhs);
- case '^='; return genassignop("xor", ex.ty, b.lhs, b.rhs);
- case '<<='; return genassignop("shl", ex.ty, b.lhs, b.rhs);
- case '>>='; return genassignop(ex.ty.u.Int.sgn ? "ashr" : "lshr", ex.ty, b.lhs, b.rhs);
-
+ case '&='; return genassignop("and", ex.ty, b.lhs, b.rhs);
+ case '|='; return genassignop("or", ex.ty, b.lhs, b.rhs);
+ case '^='; return genassignop("xor", ex.ty, b.lhs, b.rhs);
+ case'<<='; return genassignop("shl", ex.ty, b.lhs, b.rhs);
+ case'>>='; return genassignop(ex.ty.u.Int.sgn ? "ashr" : "lshr", ex.ty, b.lhs, b.rhs);
+
case else
assert(#f, "binop? %c", b.op);
}
@@ -393,7 +394,11 @@ fn genexpr(f *Fn, ex *Expr) Value {
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);
+ if ex.ty->is(:Ptr) {
+ 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("\tstore %t %v, %t* %v\n", ex.ty, val, ex.ty, addr);
return val;
@@ -403,7 +408,11 @@ fn genexpr(f *Fn, ex *Expr) Value {
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);
+ if ex.ty->is(:Ptr) {
+ 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("\tstore %t %v, %t* %v\n", ex.ty, val, ex.ty, addr);
return var;
@@ -466,7 +475,7 @@ fn genexpr(f *Fn, ex *Expr) Value {
let t Value #?;
if fnty.ret->is(:Void) {
t = {ty_void};
- gen("call %t %v(", call.lhs.ty, lhs);
+ gen("\tcall %t %v(", call.lhs.ty, lhs);
} else {
t = mktmp(ex.ty);
gen("\t%v = call %t %v(", t, call.lhs.ty, lhs);
@@ -480,6 +489,12 @@ fn genexpr(f *Fn, ex *Expr) Value {
}
gen(")\n");
return t;
+
+ case Stmt block;
+ switch genblock(f, block) {
+ case Some val; return val;
+ case None; return {ty_void};
+ }
case else
assert(#f, "expr? %d", ex.u.#tag);
@@ -501,8 +516,11 @@ fn nop() void {
gen("\t%%t%d = bitcast i8 0 to i8 ; NOP\n", tmpid++);
}
-fn genstmt(f *Fn, st *Stmt) void {
+fn genstmt(f *Fn, block *Block, st *Stmt) void {
switch st.u {
+ case Block block;
+ genblock(f, block);
+
case Expr *e;
genexpr(f, e);
@@ -525,14 +543,14 @@ fn genstmt(f *Fn, st *Stmt) void {
gen("IfT%d:", id);
nop();
genblock(f, cnd.t);
- if cnd.f.#ptr {
+ if cnd.f.sts.#ptr {
gen("\tbr label %%IfSk%d\n", id);
}
gen("\tbr label %%IfF%d\n", id);
gen("IfF%d:", id);
nop();
genblock(f, cnd.f);
- if cnd.f.#ptr {
+ if cnd.f.sts.#ptr {
gen("\tbr label %%IfSk%d\n", id);
gen("IfSk%d:", id);
nop();
@@ -573,8 +591,14 @@ fn genstmt(f *Fn, st *Stmt) void {
case Continue loopid;
gen("\tbr label %%Cont%d\n", loopid);
- case Return *e;
- switch *e {
+ case Return *ret;
+ for let defers = block.defers; defers; defers = defers.next {
+ if defers.age < ret.deferage {
+ genexpr(f, &defers.ex);
+ }
+
+ }
+ switch ret.ex {
case None;
gen("\tret void\n");
case Some *e;
@@ -586,10 +610,19 @@ fn genstmt(f *Fn, st *Stmt) void {
}
}
-fn genblock(f *Fn, block [#]Stmt) void {
- foreach_ptr (st, _, block) {
- genstmt(f, st);
+fn genblock(f *Fn, block Block) Option<Value> {
+ foreach_ptr (st, _, block.sts) {
+ genstmt(f, &block, st);
}
+ for let defers = block.defers; defers; defers = defers.next {
+ if defers.blockid == block.id {
+ let ex = genexpr(f, &defers.ex);
+ if defers.next == #null {
+ return :Some(ex);
+ }
+ }
+ }
+ return :None;
}
struct FuncKey {
@@ -666,10 +699,48 @@ extern fn llvm_addtype(ty *const Type) void {
if ty.konst { return; }
switch ty.u {
case Agg agg;
- assert(agg.kind == :Struct, "addtype");
+ gen("%%%s.%d = type ", agg.name ?? as(*const u8)"_", agg.id);
if agg.fwd {
- gen("%%%s.%d = type opaque\n", agg.name, agg.id);
- } else {
+ gen("opaque\n");
+ } else if agg.flds.#len == 0 {
+ gen("{ i8 }");
+ } else if agg.kind == :Struct {
+ gen("{ ");
+ foreach (fld, i, agg.flds) {
+ gen("%t", fld.ty);
+ if i < agg.flds.#len - 1 {
+ gen(", ");
+ }
+ }
+ gen(" }\n");
+ } else if agg.kind == :Union {
+ let size = ty.size;
+ let ty *const Type = #null;
+ foreach (fld, i, agg.flds) {
+ if ty == #null or fld.ty.align > ty.align {
+ ty = fld.ty;
+ }
+ }
+ gen("{ %t ", ty);
+ if ty.size < size {
+ gen(", [%z x i8] ", size - ty.size);
+ }
+ gen("}\n");
+ } else if agg.kind == :EUnion {
+ gen("{ %t, ", agg.enumty);
+ let size = ty.size;
+ let ty *const Type = #null;
+ foreach (fld, i, agg.flds) {
+ if ty == #null or (fld.ty != #null and fld.ty.align > ty.align) {
+ ty = fld.ty;
+ }
+ }
+ ty = ty ?? ty_void;
+ gen(" %t ", ty);
+ if ty.size < size {
+ gen(", [%z x i8] ", size - ty.size);
+ }
+ gen("}\n");
}
}