diff options
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 198 |
1 files changed, 134 insertions, 64 deletions
diff --git a/src/llvm.cff b/src/llvm.cff index 1a3bfef..789db91 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -718,19 +718,28 @@ fn genexpr(f *Fn, ex *Expr) Value { let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + let voidp = ex.ty->is(:Void); + if !voidp { + 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); + if !voidp { + 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); + if !voidp { + 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); + if !voidp { + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); + } return res; case UnOp un; @@ -1313,7 +1322,7 @@ struct IntTraits<T> { } fn gendata(ty *const Type, ex *Expr) void { - fn dataaddr(ex *Expr) void { + fn addr(ex *Expr) void { switch ex.u { case Symbol decl; switch decl.u { @@ -1330,79 +1339,140 @@ fn gendata(ty *const Type, ex *Expr) void { assert(#f, "bad static addr"); } - fold(ex); - switch ex.u { - case IntLit i; return gen("%I", i.i); - case FloLit f; return gen("%f", f); - case BoolLit b; return gen("%d", b); - case NullLit; return gen("null"); - case ZeroIni; return gen("zeroinitializer"); - case StrLit *s; - if ty->is(:Arr) { - return gen("c%S", s); - } else { - strs->push(*s); - return gen("@.str.%z", strs.len - 1); - } - case UnOp un; - switch un.op { - case :addrof; - return dataaddr(un.ex); - } - case ArrIni ini; - assert(ty->is(:Arr), "not arr arr ini"); - - let map Map<i64, *Expr, IntTraits<i64>,> = {}; - defer map->clear(); - foreach (idx, i, ini.idxs) { - map->put(idx, &ini.exs[i]); - } - gen("[ "); - for let i = 0i64; i < ty.u.Arr.length; ++i { - gen("%t ", ty.u.Arr.child); - let ex **Expr = map->get(i); - if ex { - gendata(ty.u.Arr.child, *ex); + enum Action { type, value } + fn data(act Action, ty *const Type, ex *Expr) void { + fold(ex); + switch ex.u { + case IntLit i; + return act == :type ? gen("%t", ty) : gen("%I", i.i); + case FloLit f; + return act == :type ? gen("%t", ty) : gen("%f", f); + case BoolLit b; + return act == :type ? gen("%t", ty) : gen("%d", b); + case NullLit; + return act == :type ? gen("%t", ty) : gen("null"); + case ZeroIni; + return act == :type ? gen("%t", ty) : gen("zeroinitializer"); + case EnumIni i; + return act == :type ? gen("%t", ty) : gen("%I", i); + case StrLit *s; + if act == :type { return gen("%t", ty); } + if ty->is(:Arr) { + return gen("c%S", s); } else { - gen("zeroinitializer"); + strs->push(*s); + return gen("@.str.%z", strs.len - 1); } - if i < ty.u.Arr.length - 1 { - gen(", "); + case UnOp un; + switch un.op { + case :addrof; + if act == :type { return gen("%t", ty); } + return addr(un.ex); } - } - gen(" ]"); - return; - - case AggIni ini; - assert(ty->is(:Agg), "not agg agg ini"); + case ArrIni ini; + assert(ty->is(:Arr), "not arr arr ini"); - let map Map<u16, *Expr, IntTraits<u16>,> = {}; - defer map->clear(); - if ty.u.Agg.kind == :Struct { - foreach (fld, i, ini.flds) { - let idx = fld - ty.u.Agg.flds.#ptr; + let map Map<i64, *Expr, IntTraits<i64>,> = {}; + defer map->clear(); + foreach (idx, i, ini.idxs) { map->put(idx, &ini.exs[i]); } gen("{ "); - for let i = 0z; i < ty.u.Agg.flds.#len; ++i { - gen("%t ", ty.u.Agg.flds[i].ty); + for let i = 0i64; i < ty.u.Arr.length; ++i { let ex **Expr = map->get(i); - if ex { - gendata(ty.u.Agg.flds[i].ty, *ex); - } else { - gen("zeroinitializer"); + + ex ? data(:type, ty.u.Arr.child, *ex) : gen("%t", ty.u.Arr.child); + if act != :type { + gen(" "); + if ex { + data(:value, ty.u.Arr.child, *ex); + } else { + gen("zeroinitializer"); + } } - if i < ty.u.Agg.flds.#len - 1 { + if i < ty.u.Arr.length - 1 { gen(", "); } } gen(" }"); - } else { - assert(#f, "NYI static"); + return; + + case AggIni ini; + assert(ty->is(:Agg), "not agg agg ini"); + + let map Map<u16, *Expr, IntTraits<u16>,> = {}; + defer map->clear(); + if ty.u.Agg.kind == :Struct { + foreach (fld, i, ini.flds) { + let idx = fld - ty.u.Agg.flds.#ptr; + map->put(idx, &ini.exs[i]); + } + gen("{ "); + for let i = 0z; i < ty.u.Agg.flds.#len; ++i { + let ex **Expr = map->get(i); + ex ? data(:type, ty.u.Agg.flds[i].ty, *ex) : gen("%t", ty.u.Agg.flds[i].ty); + gen(" ", ty.u.Agg.flds[i].ty); + if act != :type { + if ex { + data(:value, ty.u.Agg.flds[i].ty, *ex); + } else { + gen("zeroinitializer"); + } + } + if i < ty.u.Agg.flds.#len - 1 { + gen(", "); + } + } + gen(" }"); + return; + } else if ty.u.Agg.kind == :Union { + assert(ini.exs.#len == 1, "bad static union init"); + let fty = ini.flds[0].ty; + let ex = &ini.exs[0]; + if act == :type { + gen("{ "); + data(:type, fty, ex); + gen(", [%z x i8] }", ty.size - fty.size); + } else { + gen("{ "); + gendata(fty, ex); + gen(", [%z x i8] zeroinitializer }", ty.size - fty.size); + } + return; + } + assert(#f, "bad static %d", ex.u.#tag); + + case EUnionIni ini; + let fld = ini.var; + let fty = fld.ty; + let ex = ini.ex; + if act == :type { + if ex { + gen("{ %t, [%z x i8], ", ty.u.Agg.enumty, fld.off - ty.u.Agg.enumty.size); + data(:type, fty, ex); + gen(", [%z x i8] }", ty.size - (fld.off + fty.size)); + } else { + gen("{ %t, [%z x i8] }", ty.u.Agg.enumty, ty.size - ty.u.Agg.enumty.size); + } + } else { + let idx isize = fld - ty.u.Agg.flds.#ptr; + if ex { + gen("{ %t %z, [%z x i8] zeroinitializer, ", ty.u.Agg.enumty, idx, fld.off - ty.u.Agg.enumty.size); + gendata(fty, ex); + gen(", [%z x i8] zeroinitializer }", ty.size - (fld.off + fty.size)); + } else { + gen("{ %t %z, [%z x i8] zeroinitializer }", ty.u.Agg.enumty, idx, ty.size - ty.u.Agg.enumty.size); + } + } + return; + + case else + assert(#f, "nyi static %d", ex.u.#tag); } - return; } - assert(#f, "bad static %d", ex.u.#tag); + data(:type, ty, ex); + gen(" "); + data(:value, ty, ex); } extern fn llvm_genstatic(externp bool, name *const u8, var *Var) void { @@ -1413,7 +1483,7 @@ extern fn llvm_genstatic(externp bool, name *const u8, var *Var) void { gen("@%s", name); } let ini = var.ini->some_or({.u: :ZeroIni}); - gen(" = %sglobal %t %C\n", externp ? "" : "internal ", var.ty, var.ty, &ini); + gen(" = %sglobal %C , align %z\n", externp ? "" : "internal ", var.ty, &ini, var.ty.align); } extern fn llvm_fini() void { |