aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-24 08:23:36 +0200
committerlemon <lsof@mailbox.org>2022-08-24 08:23:36 +0200
commitca3b09c836af6878ce3879ef91d7ba75f9898cb8 (patch)
tree25697e64c4976df1ba80fd7695bec6eb646629d2 /src
parentfa541d48d80d99d78e2ff41b0bea66d8a92c9bd6 (diff)
dot operator llvm
Diffstat (limited to 'src')
-rw-r--r--src/cffc.hff2
-rw-r--r--src/llvm.cff166
-rw-r--r--src/main.cff1
-rw-r--r--src/type.cff4
4 files changed, 85 insertions, 88 deletions
diff --git a/src/cffc.hff b/src/cffc.hff
index a4099e7..882793f 100644
--- a/src/cffc.hff
+++ b/src/cffc.hff
@@ -459,7 +459,7 @@ fn isnumtype(ty *const Type) bool {
return ty->is(:Int) or ty->is(:Flo) or (ty->is(:Enum) and ty.u.Enum.lax);
}
extern fn typeof2(a *const Type, b *const Type) *const Type;
-extern fn types_to_llvm() void;
+extern fn visittypes(*fn(*const Type, *void) void, *void) void;
// env.cff
extern fn mkenv(parent *Env, alloc *Allocator) *Env;
diff --git a/src/llvm.cff b/src/llvm.cff
index b12c995..7a84690 100644
--- a/src/llvm.cff
+++ b/src/llvm.cff
@@ -25,6 +25,52 @@ struct Value {
static ty_i1 *Type = as(*void)&outfp; // dummy
fn gen(fmt *const u8, ...) void;
+extern fn genagg(ty *const Type) void {
+ let agg = &ty.u.Agg;
+ if agg.fwd {
+ gen("%.type.opaque");
+ } 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(" }");
+ } 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("}");
+ } 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("}");
+ }
+}
+
fn gen(fmt *const u8, ...) void {
let ap va_list #?;
ap->start(fmt);
@@ -42,7 +88,8 @@ fn gen(fmt *const u8, ...) void {
case Ptr p; gen("%t*", p->is(:Void) ? ty_i8 : p);
case Slice p; gen("{ %t*, %t }", p, ty_usize);
case Arr arr; gen("[%z x %t]", arr.length, arr.child);
- case Agg agg; gen("%%%s.%d", agg.name ?? as(*const u8)"_", agg.id);
+ case Agg;
+ genagg(ty);
case Enum enu; pritype(enu.intty);
case Fn f;
gen("%t(", f.ret);
@@ -155,6 +202,9 @@ fn genaddr(f *Fn, ex *Expr) Value {
switch un.op {
case :deref;
return genexpr(f, un.ex);
+
+ case :addrof;
+ return genaddr(f, un.ex);
}
case Index idx;
let lhs Value #?;
@@ -166,10 +216,17 @@ fn genaddr(f *Fn, ex *Expr) Value {
lhs = genexpr(f, idx.lhs);
}
let rhs = genexpr(f, idx.rhs),
- addr = mktmp(ex.ty),
- val = mktmp(ex.ty);
+ addr = mktmp(ex.ty);
gen("\t%v = getelementptr %t, %t* %v, %t %v\n", addr, ex.ty, ex.ty, lhs, rhs.ty, rhs);
return addr;
+
+ case Dot dot;
+ let lhs = dot.lhs.ty->is(:Ptr) ? genexpr(f, dot.lhs) : genaddr(f, dot.lhs);
+ assert(dot.fld.off % dot.fld.ty.align == 0, "field align");
+ let idx int = dot.fld.off / dot.fld.ty.align;
+ let addr = mktmp(ex.ty);
+ gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", addr, lhs.ty.u.Ptr, lhs.ty, lhs, idx);
+ return addr;
}
assert(#f, "genaddr");
}
@@ -422,46 +479,37 @@ fn genexpr(f *Fn, ex *Expr) Value {
gen("\t%v = load %t, %t* %v\n", val, ex.ty, ex.ty, rhs);
return val;
+ case :addrof;
+ return genaddr(f, ex);
+
case else
assert(#f, "unop?");
}
- case Index idx;
- let lhs Value #?;
- if idx.lhs.ty->is(:Arr) {
- let arr = genaddr(f, idx.lhs);
- lhs = mktmp(ex.ty);
- gen("\t%v = getelementptr %t, %t %v, i32 0, i32 0\n", lhs, arr.ty.u.Arr.child, arr.ty, arr);
- } else {
- lhs = genexpr(f, idx.lhs);
- }
- let rhs = genexpr(f, idx.rhs),
- addr = mktmp(ex.ty),
- val = mktmp(ex.ty);
- gen("\t%v = getelementptr %t, %t* %v, %t %v\n", addr, ex.ty, ex.ty, lhs, rhs.ty, rhs);
- gen("\t%v = load %t, %t* %v\n", val, ex.ty, ex.ty, addr);
- return val;
+ case Index;
+ let tmp = mktmp(ex.ty);
+ let addr = genaddr(f, ex);
+ gen("\t%v = load %t, %t* %v\n", tmp, ex.ty, ex.ty, addr);
+ return tmp;
+
+ case Dot;
+ let tmp = mktmp(ex.ty);
+ let addr = genaddr(f, ex);
+ gen("\t%v = load %t, %t* %v\n", tmp, ex.ty, ex.ty, addr);
+ return tmp;
+
case Cast it;
return convert(f, ex.ty, it);
case Symbol decl;
switch decl.u {
- case Let *var;
- 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 = mktmp(ex.ty);
- if decl.externp {
- gen("\t%v = load %t, %t* @%s\n", t, ex.ty, ex.ty, decl.name);
- } else {
- gen("\t%v = load %t, %t* @%s.%d\n", t, ex.ty, ex.ty, decl.name, var.id);
- }
- return t;
case Fn *f;
- return {ex.ty, :Fn(f)};
+ return {ex.ty, :Fn(f)};
case else
- assert(#f, "decl");
+ let tmp = mktmp(ex.ty);
+ let addr = genaddr(f, ex);
+ gen("\t%v = load %t, %t* %v\n", tmp, ex.ty, ex.ty, addr);
+ return tmp;
}
case Call call;
let lhs = genexpr(f, call.lhs);
@@ -596,7 +644,6 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void {
if defers.age < ret.deferage {
genexpr(f, &defers.ex);
}
-
}
switch ret.ex {
case None;
@@ -695,57 +742,6 @@ extern fn llvm_genfn(externp bool, name *const u8, f *Fn) void {
gen("}\n");
}
-extern fn llvm_addtype(ty *const Type) void {
- if ty.konst { return; }
- switch ty.u {
- case Agg agg;
- gen("%%%s.%d = type ", agg.name ?? as(*const u8)"_", agg.id);
- if agg.fwd {
- 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");
- }
-
- }
-}
-
extern fn llvm_fini() void {
vec_each(s, i, strs) {
gen("@.str.%z = internal constant [%z x i8] c%S;\n", i, s.#len + 1, s);
@@ -779,4 +775,6 @@ extern fn llvm_init(out *FILE) void {
alloc = {&arena, &Arena:allocf, #null};
outfp = out;
gen("target triple = \"%s\"\n", g_targ.triple);
+ gen("%%.type.opaque = type opaque\n");
+ gen("\n");
}
diff --git a/src/main.cff b/src/main.cff
index 46cd8dc..70d8bdf 100644
--- a/src/main.cff
+++ b/src/main.cff
@@ -18,7 +18,6 @@ extern fn main(argc int, argv **u8) int {
llvm_init(stdout);
let decls = parse(&p);
defer free(decls.#ptr);
- types_to_llvm();
llvm_fini();
}
diff --git a/src/type.cff b/src/type.cff
index 3feb14c..d93548a 100644
--- a/src/type.cff
+++ b/src/type.cff
@@ -307,8 +307,8 @@ extern fn typeof2(a *const Type, b *const Type) *const Type {
return #null;
}
-extern fn types_to_llvm() void {
+extern fn visittypes(proc *fn(*const Type, *void) void, arg *void) void {
set_each(ty, types_set) {
- llvm_addtype(ty);
+ proc(ty, arg);
}
}