@@ 248,6 248,7 @@ enum union Ref {
BitDot struct { lhs Value, fld *const BitFField }
}
+fn gencopy(f *Fn, ty *const Type, ref Ref, src *Expr) void;
fn genref(f *Fn, ex *Expr) Ref {
switch ex.u {
case StrLit s;
@@ 339,8 340,7 @@ fn genref(f *Fn, ex *Expr) Ref {
gen("\t%v = bitcast %t %v to %t\n", &ptr, tmp.ty, &tmp, ptr.ty);
case else assert(#f, "?");
}
- let it = convert(f, fld.ty, fex);
- gen("\tstore %t %v, ptr %v\n", fld.ty, &it, &ptr);
+ gencopy(f, fld.ty, :Addr(ptr), fex);
}
return :Addr(tmp);
@@ 352,8 352,7 @@ fn genref(f *Fn, ex *Expr) Ref {
let fex = &ini.exs[i];
let ptr = mktmp(mkptrtype(fex.ty));
gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ty, tmp.ty, &tmp, idx);
- let it = convert(f, ty.u.Arr.child, fex);
- gen("\tstore %t %v, %t %v\n", fex.ty, &it, ptr.ty, &ptr);
+ gencopy(f, ty.u.Arr.child, :Addr(ptr), fex);
}
return :Addr(tmp);
@@ 413,6 412,20 @@ fn genstore(f *Fn, ref Ref, v Value) void {
}
}
+fn gencopy(f *Fn, ty *const Type, ref Ref, src *Expr) void {
+ if (ty.u.#tag == :Agg or ty.u.#tag == :Arr) and src.u.#tag == :ZeroIni {
+ gen("\tcall void @llvm.memset.p0.%t(ptr %v, i8 0, %t %z, i1 false)\n",
+ ty_usize, &ref.Addr, ty_usize, ty.size);
+ // XXX: LLVM optimizations mess this up ?
+ // } else if (ty.u.#tag == :Agg or ty.u.#tag == :Arr) and ref.#tag == :Addr {
+ // let rhs = genref(f, src);
+ // gen("\tcall void @llvm.memmove.p0.p0.%t(ptr %v, ptr %v, %t %z, i1 false)\n",
+ // ty_usize, &ref.Addr, &rhs.Addr, ty_usize, ty.size);
+ } else {
+ genstore(f, ref, convert(f, ty, src));
+ }
+}
+
fn convert(f *Fn, to *const Type, ex *Expr) Value {
to = unconstify(to);
let from = unconstify(ex.ty);
@@ 635,8 648,7 @@ fn genexpr(f *Fn, ex *Expr) Value {
case '>='; gencmp(ty2->is(:Flo) ? "oge" : ty2.u.Int.sgn ? "sge" : "uge");
case '=';
let ref = genref(f, b.lhs);
- let rhs = convert(f, b.lhs.ty, b.rhs);
- genstore(f, ref, rhs);
+ gencopy(f, b.lhs.ty, ref, b.rhs);
return genload(f, ref); // load again because value could have overflowed when storing it
case '+=';
@@ 979,13 991,10 @@ fn genexpr(f *Fn, ex *Expr) Value {
gen("\tcall void @llvm.memset.p0.%t(ptr %v, i8 0, %t %z, i1 false)\n", ty_usize, &t0, ty_usize, ex.ty.size);
gen("\tstore %t %d, ptr %v\n", ex.ty.u.Agg.enumty, vidx, &t0);
if ini.var.ty != #null {
- let tini = convert(f, ini.var.ty, ini.ex);
let t2 = gentmp(t0.ty, "getelementptr i8, ptr %v, i32 %z", &t0, ini.var.off);
- gen("\tstore %t %v, ptr %v\n", tini.ty, &tini, &t2);
+ gencopy(f, ini.var.ty, :Addr(t2), ini.ex);
}
- let res = mktmp(ex.ty);
- gen("\t%v = load %t, %t %v\n", &res, res.ty, t0.ty, &t0);
- return res;
+ return gentmp(ex.ty, "load %t, %t %v", ex.ty, t0.ty, &t0);
case VaStart ap;
let ap = genref(f, ap).Addr;
@@ 1165,8 1174,7 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void {
} else {
exaddr = mktmp(mkptrtype(sw.ex.ty));
gen("\t%v = alloca %t\n", &exaddr, sw.ex.ty);
- let test = genexpr(f, &sw.ex);
- gen("\tstore %t %v, %t %v\n", test.ty, &test, exaddr.ty, &exaddr);
+ gencopy(f, sw.ex.ty, :Addr(exaddr), &sw.ex);
}
let tag = (do
let addr = mktmp(mkptrtype(sw.ex.ty.u.Agg.enumty));
@@ 1524,8 1532,8 @@ extern fn llvm_fini() void {
gen("declare void @llvm.va_start(ptr)\n");
gen("declare void @llvm.va_copy(ptr, ptr)\n");
gen("declare void @llvm.va_end(ptr)\n");
- gen("declare void @llvm.memset.p0.i32(ptr, i8, i32, i1)\n");
- gen("declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)\n");
+ gen("declare void @llvm.memset.p0.%t(ptr, i8, %t, i1)\n", ty_usize, ty_usize);
+ gen("declare void @llvm.memmove.p0.p0.%t(ptr, ptr, %t, i1)\n", ty_usize, ty_usize);
vec_each(s, i, strs) {
gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, &s);
}