aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-30 13:43:10 +0200
committerlemon <lsof@mailbox.org>2022-08-30 13:43:10 +0200
commitbbb6779bed7abcc9fec24ddc513e09bc8f876481 (patch)
tree5a882ec06ebd1b112678c892cfcb4016b7c40bdc /src
parentdeb6b8e1b6fc2543ff27f8d0c75789733374a2c1 (diff)
union statics
Diffstat (limited to 'src')
-rw-r--r--src/llvm.cff198
-rw-r--r--src/parse.cff2
2 files changed, 135 insertions, 65 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 {
diff --git a/src/parse.cff b/src/parse.cff
index ffe9a9d..b758061 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -2106,7 +2106,7 @@ fn pexcmp(P *Parser) Expr {
ex.ty, rhs.ty, &tok);
}
fn ispositiveintlit(ex Expr) bool {
- return ex.u.#tag == :IntLit and ex.u.IntLit.i >- 0;
+ return ex.u.#tag == :IntLit and ex.u.IntLit.i >= 0;
}
if ty->is(:Int) and ty != ty_int and ex.ty.u.Int.sgn != rhs.ty.u.Int.sgn
and !(ispositiveintlit(ex) or ispositiveintlit(rhs)) {