aboutsummaryrefslogtreecommitdiff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-01-18 15:38:35 -0800
committerGraydon Hoare <[email protected]>2011-01-18 15:38:35 -0800
commite92298187bceb0cc1cf423dd37e0f5fe30359a17 (patch)
treea8ea621832055d8716821dcda1800b03c35f6eb0 /src/comp
parentAdd Benjamin to AUTHORS. (diff)
downloadrust-e92298187bceb0cc1cf423dd37e0f5fe30359a17.tar.xz
rust-e92298187bceb0cc1cf423dd37e0f5fe30359a17.zip
Add bzero glue and preliminary code for dynamic size/align calculations.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/abi.rs4
-rw-r--r--src/comp/middle/trans.rs185
2 files changed, 174 insertions, 15 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 0c940d2b..db17b942 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -63,6 +63,10 @@ fn memcpy_glue_name() -> str {
ret "rust_memcpy_glue";
}
+fn bzero_glue_name() -> str {
+ ret "rust_bzero_glue";
+}
+
fn upcall_glue_name(int n) -> str {
ret "rust_upcall_" + util.common.istr(n);
}
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index a56d1fd7..c3c8ee11 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -52,7 +52,8 @@ type glue_fns = rec(ValueRef activate_glue,
ValueRef exit_task_glue,
vec[ValueRef] upcall_glues,
ValueRef no_op_type_glue,
- ValueRef memcpy_glue);
+ ValueRef memcpy_glue,
+ ValueRef bzero_glue);
tag arity { nullary; n_ary; }
type tag_info = rec(type_handle th,
@@ -632,19 +633,110 @@ fn find_scope_cx(@block_ctxt cx) -> @block_ctxt {
}
}
-fn size_of(TypeRef t) -> ValueRef {
+fn umax(@block_ctxt cx, ValueRef a, ValueRef b) -> ValueRef {
+ auto cond = cx.build.ICmp(lib.llvm.LLVMIntULT, a, b);
+ ret cx.build.Select(cond, b, a);
+}
+
+fn align_to(@block_ctxt cx, ValueRef off, ValueRef align) -> ValueRef {
+ auto mask = cx.build.Sub(align, C_int(1));
+ auto bumped = cx.build.Add(off, mask);
+ ret cx.build.And(bumped, cx.build.Not(mask));
+}
+
+fn llsize_of(TypeRef t) -> ValueRef {
ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMSizeOf(t), T_int(), False);
}
-fn align_of(TypeRef t) -> ValueRef {
+fn llalign_of(TypeRef t) -> ValueRef {
ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMAlignOf(t), T_int(), False);
}
+fn size_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+ if (!ty.type_has_dynamic_size(t)) {
+ ret llsize_of(type_of(cx.fcx.ccx, t));
+ }
+ ret dynamic_size_of(cx, t);
+}
+
+fn align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+ if (!ty.type_has_dynamic_size(t)) {
+ ret llalign_of(type_of(cx.fcx.ccx, t));
+ }
+ ret dynamic_align_of(cx, t);
+}
+
+fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+ alt (t.struct) {
+ case (ty.ty_param(?p)) {
+ auto szptr = field_of_tydesc(cx, t, abi.tydesc_field_size);
+ ret cx.build.Load(szptr);
+ }
+ case (ty.ty_tup(?elts)) {
+ //
+ // C padding rules:
+ //
+ //
+ // - Pad after each element so that next element is aligned.
+ // - Pad after final structure member so that whole structure
+ // is aligned to max alignment of interior.
+ //
+ auto off = C_int(0);
+ auto max_align = C_int(1);
+ for (@ty.t e in elts) {
+ auto elt_align = align_of(cx, e);
+ auto elt_size = size_of(cx, e);
+ auto aligned_off = align_to(cx, off, elt_align);
+ off = cx.build.Add(aligned_off, elt_size);
+ max_align = umax(cx, max_align, elt_align);
+ }
+ off = align_to(cx, off, max_align);
+ ret off;
+ }
+ case (ty.ty_rec(?flds)) {
+ auto off = C_int(0);
+ auto max_align = C_int(1);
+ for (ty.field f in flds) {
+ auto elt_align = align_of(cx, f.ty);
+ auto elt_size = size_of(cx, f.ty);
+ auto aligned_off = align_to(cx, off, elt_align);
+ off = cx.build.Add(aligned_off, elt_size);
+ max_align = umax(cx, max_align, elt_align);
+ }
+ off = align_to(cx, off, max_align);
+ ret off;
+ }
+ }
+}
+
+fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
+ alt (t.struct) {
+ case (ty.ty_param(?p)) {
+ auto aptr = field_of_tydesc(cx, t, abi.tydesc_field_align);
+ ret cx.build.Load(aptr);
+ }
+ case (ty.ty_tup(?elts)) {
+ auto a = C_int(1);
+ for (@ty.t e in elts) {
+ a = umax(cx, a, align_of(cx, e));
+ }
+ ret a;
+ }
+ case (ty.ty_rec(?flds)) {
+ auto a = C_int(1);
+ for (ty.field f in flds) {
+ a = umax(cx, a, align_of(cx, f.ty));
+ }
+ ret a;
+ }
+ }
+}
+
fn trans_malloc_inner(@block_ctxt cx, TypeRef llptr_ty) -> result {
auto llbody_ty = lib.llvm.llvm.LLVMGetElementType(llptr_ty);
// FIXME: need a table to collect tydesc globals.
auto tydesc = C_int(0);
- auto sz = size_of(llbody_ty);
+ auto sz = llsize_of(llbody_ty);
auto sub = trans_upcall(cx, "upcall_malloc", vec(sz, tydesc));
sub.val = sub.bcx.build.IntToPtr(sub.val, llptr_ty);
ret sub;
@@ -699,8 +791,8 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t) {
auto pvoid = T_ptr(T_i8());
auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), pvoid), T_void()));
auto tydesc = C_struct(vec(C_null(pvoid),
- size_of(llty),
- align_of(llty),
+ llsize_of(llty),
+ llalign_of(llty),
take_glue, // take_glue_off
drop_glue, // drop_glue_off
C_null(glue_fn_ty), // free_glue_off
@@ -1146,7 +1238,7 @@ fn iter_sequence(@block_ctxt cx,
C_int(abi.vec_elt_fill)));
auto llunit_ty = type_of(cx.fcx.ccx, elt_ty);
- auto unit_sz = size_of(llunit_ty);
+ auto unit_sz = size_of(cx, elt_ty);
auto len = cx.build.Load(lenptr);
if (trailing_null) {
@@ -1249,6 +1341,15 @@ fn call_memcpy(@block_ctxt cx,
vec(dst_ptr, src_ptr, size)));
}
+fn call_bzero(@block_ctxt cx,
+ ValueRef dst,
+ ValueRef n_bytes) -> result {
+ auto dst_ptr = cx.build.PointerCast(dst, T_ptr(T_i8()));
+ auto size = cx.build.IntCast(n_bytes, T_int());
+ ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.bzero_glue,
+ vec(dst_ptr, size)));
+}
+
fn memcpy_ty(@block_ctxt cx,
ValueRef dst,
ValueRef src,
@@ -1901,7 +2002,7 @@ impure fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
auto v = lv.val;
auto llunit_ty = node_type(cx.fcx.ccx, ann);
- auto unit_sz = size_of(llunit_ty);
+ auto unit_sz = size_of(cx, node_ann_type(cx.fcx.ccx, ann));
auto scaled_ix = ix.bcx.build.Mul(ix.val, unit_sz);
auto lim = ix.bcx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_fill)));
@@ -2374,7 +2475,7 @@ impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
}
auto llunit_ty = type_of(cx.fcx.ccx, unit_ty);
- auto unit_sz = size_of(llunit_ty);
+ auto unit_sz = size_of(cx, unit_ty);
auto data_sz = llvm.LLVMConstMul(C_int(_vec.len[@ast.expr](args) as int),
unit_sz);
@@ -2681,9 +2782,15 @@ impure fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
sub = copy_ty(sub.bcx, true, llptr, sub.val, ty);
}
case (_) {
- auto llty = type_of(cx.fcx.ccx, ty);
- auto null = lib.llvm.llvm.LLVMConstNull(llty);
- sub = res(cx, cx.build.Store(null, llptr));
+ if (middle.ty.type_has_dynamic_size(ty)) {
+ auto llsz = size_of(cx, ty);
+ sub = call_bzero(cx, llptr, llsz);
+
+ } else {
+ auto llty = type_of(cx.fcx.ccx, ty);
+ auto null = lib.llvm.llvm.LLVMConstNull(llty);
+ sub = res(cx, cx.build.Store(null, llptr));
+ }
}
}
}
@@ -2779,8 +2886,14 @@ impure fn trans_block(@block_ctxt cx, &ast.block b) -> result {
auto bcx = cx;
for each (@ast.local local in block_locals(b)) {
- auto ty = node_type(cx.fcx.ccx, local.ann);
- auto val = bcx.build.Alloca(ty);
+ auto t = node_ann_type(cx.fcx.ccx, local.ann);
+ auto val = C_int(0);
+ if (ty.type_has_dynamic_size(t)) {
+ auto n = size_of(bcx, t);
+ val = bcx.build.ArrayAlloca(T_i8(), n);
+ } else {
+ val = bcx.build.Alloca(type_of(cx.fcx.ccx, t));
+ }
cx.fcx.lllocals.insert(local.id, val);
}
auto r = res(bcx, C_nil());
@@ -3684,6 +3797,47 @@ fn make_memcpy_glue(ModuleRef llmod) -> ValueRef {
ret fun;
}
+fn make_bzero_glue(ModuleRef llmod) -> ValueRef {
+
+ // We're not using the LLVM memset intrinsic. Same as with memcpy.
+
+ auto p8 = T_ptr(T_i8());
+
+ auto ty = T_fn(vec(p8, T_int()), T_void());
+ auto fun = decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty);
+
+ auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init"));
+ auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr"));
+ auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop"));
+ auto endbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("end"));
+
+ auto dst = llvm.LLVMGetParam(fun, 0u);
+ auto count = llvm.LLVMGetParam(fun, 1u);
+
+ // Init block.
+ auto ib = new_builder(initbb);
+ auto ip = ib.Alloca(T_int());
+ ib.Store(C_int(0), ip);
+ ib.Br(hdrbb);
+
+ // Loop-header block
+ auto hb = new_builder(hdrbb);
+ auto i = hb.Load(ip);
+ hb.CondBr(hb.ICmp(lib.llvm.LLVMIntEQ, count, i), endbb, loopbb);
+
+ // Loop-body block
+ auto lb = new_builder(loopbb);
+ i = lb.Load(ip);
+ lb.Store(C_integral(0, T_i8()), lb.GEP(dst, vec(i)));
+ lb.Store(lb.Add(i, C_int(1)), ip);
+ lb.Br(hdrbb);
+
+ // End block
+ auto eb = new_builder(endbb);
+ eb.RetVoid();
+ ret fun;
+}
+
fn make_glues(ModuleRef llmod) -> @glue_fns {
ret @rec(activate_glue = decl_glue(llmod, abi.activate_glue_name()),
yield_glue = decl_glue(llmod, abi.yield_glue_name()),
@@ -3704,7 +3858,8 @@ fn make_glues(ModuleRef llmod) -> @glue_fns {
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
abi.n_upcall_glues as uint),
no_op_type_glue = make_no_op_type_glue(llmod),
- memcpy_glue = make_memcpy_glue(llmod));
+ memcpy_glue = make_memcpy_glue(llmod),
+ bzero_glue = make_bzero_glue(llmod));
}
fn trans_crate(session.session sess, @ast.crate crate, str output,