diff options
| author | 2022-08-24 08:23:36 +0200 | |
|---|---|---|
| committer | 2022-08-24 08:23:36 +0200 | |
| commit | ca3b09c836af6878ce3879ef91d7ba75f9898cb8 (patch) | |
| tree | 25697e64c4976df1ba80fd7695bec6eb646629d2 /src/llvm.cff | |
| parent | fa541d48d80d99d78e2ff41b0bea66d8a92c9bd6 (diff) | |
dot operator llvm
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 166 |
1 files changed, 82 insertions, 84 deletions
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"); } |