diff options
| author | 2022-08-24 06:46:23 +0200 | |
|---|---|---|
| committer | 2022-08-24 06:46:23 +0200 | |
| commit | e5ed3b20351a2715fe88d9a5dbcc8e6757fe96aa (patch) | |
| tree | 7333f357bc38ed389e8845d59196594377dc46d6 /src/llvm.cff | |
| parent | 039ab20bbf6b68c423f420be2481b447d85c606b (diff) | |
llvm defer and more
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 119 |
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"); } } |