diff options
| author | 2022-08-24 08:23:36 +0200 | |
|---|---|---|
| committer | 2022-08-24 08:23:36 +0200 | |
| commit | ca3b09c836af6878ce3879ef91d7ba75f9898cb8 (patch) | |
| tree | 25697e64c4976df1ba80fd7695bec6eb646629d2 | |
| parent | fa541d48d80d99d78e2ff41b0bea66d8a92c9bd6 (diff) | |
dot operator llvm
| -rw-r--r-- | examples/vec2f.hff | 16 | ||||
| -rw-r--r-- | src/cffc.hff | 2 | ||||
| -rw-r--r-- | src/llvm.cff | 166 | ||||
| -rw-r--r-- | src/main.cff | 1 | ||||
| -rw-r--r-- | src/type.cff | 4 | ||||
| -rw-r--r-- | x | 19 |
6 files changed, 120 insertions, 88 deletions
diff --git a/examples/vec2f.hff b/examples/vec2f.hff new file mode 100644 index 0000000..38687eb --- /dev/null +++ b/examples/vec2f.hff @@ -0,0 +1,16 @@ +struct Vec2f { + x f32, y f32, + + fn x(v Vec2f) f32 { + return (&v).x; + } + + fn y(v *Vec2f) f32 { + return v.y; + } + + #{ fn add(l Vec2f, r Vec2f) Vec2f { + return { l.x + r.x, l.y + r.y }; + } + } +} 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); } } @@ -0,0 +1,19 @@ +target triple = "x86_64-pc-linux-gnu" +%Vec2f.0 = type opaque +%Vec2f.0 = type { float, float } + +define internal float @x.1(%Vec2f.0 %v) { +%v.0 = alloca %Vec2f.0 store %Vec2f.0 %v, %Vec2f.0* %v.0 + %t1 = getelementptr %Vec2f.0, %Vec2f.0* %v.0, i32 0, i32 0 + %t0 = load float, float* %t1 + ret float %t0 + ret float undef +} +define internal float @y.2(%Vec2f.0* %v) { +%v.0 = alloca %Vec2f.0* store %Vec2f.0* %v, %Vec2f.0** %v.0 + %t1 = load %Vec2f.0*, %Vec2f.0** %v.0 + %t2 = getelementptr %Vec2f.0, %Vec2f.0* %t1, i32 0, i32 1 + %t0 = load float, float* %t2 + ret float %t0 + ret float undef +} |