about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-01-19 10:21:42 -0800
committerNiko Matsakis <niko@alum.mit.edu>2012-01-21 19:31:51 -0800
commitcd1056df78d8936cfa732556bfaab8caf6d80c1c (patch)
tree29eeceb3c66030c89f589c7310bd85b61b4f796c /src/comp
parent98fd120ac15948857084821bb3dead9a7f6b65e9 (diff)
downloadrust-cd1056df78d8936cfa732556bfaab8caf6d80c1c.tar.gz
rust-cd1056df78d8936cfa732556bfaab8caf6d80c1c.zip
migrate size_of() and related funcs from trans into shape
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/shape.rs254
-rw-r--r--src/comp/middle/trans.rs251
-rw-r--r--src/comp/middle/trans_closure.rs2
-rw-r--r--src/comp/middle/trans_common.rs16
-rw-r--r--src/comp/middle/trans_uniq.rs2
-rw-r--r--src/comp/middle/trans_vec.rs6
6 files changed, 268 insertions, 263 deletions
diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs
index de1dddb923b..8ba8f6d36aa 100644
--- a/src/comp/middle/shape.rs
+++ b/src/comp/middle/shape.rs
@@ -1,18 +1,26 @@
 // A "shape" is a compact encoding of a type that is used by interpreted glue.
 // This substitutes for the runtime tags used by e.g. MLs.
 
-import lib::llvm::True;
+import lib::llvm::llvm;
+import lib::llvm::{True, False};
 import lib::llvm::llvm::{ModuleRef, TypeRef, ValueRef};
 import driver::session;
+import driver::session::session;
 import middle::{trans, trans_common};
-import middle::trans_common::{crate_ctxt, val_ty, C_bytes,
-                              C_named_struct, C_struct, T_tag_variant};
+import middle::trans_common::{crate_ctxt, val_ty, C_bytes, C_int,
+                              C_named_struct, C_struct, T_tag_variant,
+                              block_ctxt, result, rslt, bcx_ccx, bcx_tcx,
+                              type_has_static_size, umax, umin, align_to,
+                              tydesc_info};
+import back::abi;
 import middle::ty;
 import middle::ty::field;
 import syntax::ast;
 import syntax::ast_util::dummy_sp;
 import syntax::util::interner;
 import util::common;
+import trans_build::{Load, Store, Add, GEPi};
+import syntax::codemap::span;
 
 import core::{vec, str};
 import std::map::hashmap;
@@ -128,8 +136,8 @@ fn largest_variants(ccx: @crate_ctxt, tag_id: ast::def_id) -> [uint] {
                 // once we implement Issue #586.)
                 check (trans_common::type_has_static_size(ccx, elem_t));
                 let llty = trans::type_of(ccx, dummy_sp(), elem_t);
-                min_size += trans::llsize_of_real(ccx, llty);
-                min_align += trans::llalign_of_real(ccx, llty);
+                min_size += llsize_of_real(ccx, llty);
+                min_align += llalign_of_real(ccx, llty);
             }
         }
 
@@ -210,8 +218,8 @@ fn compute_static_tag_size(ccx: @crate_ctxt, largest_variants: [uint],
         }
 
         let llty = trans_common::T_struct(lltys);
-        let dp = trans::llsize_of_real(ccx, llty) as u16;
-        let variant_align = trans::llalign_of_real(ccx, llty) as u8;
+        let dp = llsize_of_real(ccx, llty) as u16;
+        let variant_align = llalign_of_real(ccx, llty) as u8;
 
         if max_size < dp { max_size = dp; }
         if max_align < variant_align { max_align = variant_align; }
@@ -222,8 +230,8 @@ fn compute_static_tag_size(ccx: @crate_ctxt, largest_variants: [uint],
     // aligned quantity, we don't align it.
     if vec::len(*variants) > 1u {
         let variant_t = T_tag_variant(ccx);
-        max_size += trans::llsize_of_real(ccx, variant_t) as u16;
-        let align = trans::llalign_of_real(ccx, variant_t) as u8;
+        max_size += llsize_of_real(ccx, variant_t) as u16;
+        let align = llalign_of_real(ccx, variant_t) as u8;
         if max_align < align { max_align = align; }
     }
 
@@ -596,3 +604,231 @@ fn gen_shape_tables(ccx: @crate_ctxt) {
                                         lib::llvm::llvm::Linkage);
 }
 
+// ______________________________________________________________________
+// compute sizeof / alignof
+
+fn size_of(cx: @block_ctxt, t: ty::t) -> result {
+    let ccx = bcx_ccx(cx);
+    if check type_has_static_size(ccx, t) {
+        let sp = cx.sp;
+        rslt(cx, llsize_of(bcx_ccx(cx), trans::type_of(ccx, sp, t)))
+    } else { dynamic_size_of(cx, t) }
+}
+
+fn align_of(cx: @block_ctxt, t: ty::t) -> result {
+    let ccx = bcx_ccx(cx);
+    if check type_has_static_size(ccx, t) {
+        let sp = cx.sp;
+        rslt(cx, llalign_of(bcx_ccx(cx), trans::type_of(ccx, sp, t)))
+    } else { dynamic_align_of(cx, t) }
+}
+
+// Returns the real size of the given type for the current target.
+fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
+    ret llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
+}
+
+// Returns the real alignment of the given type for the current target.
+fn llalign_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
+    ret llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
+}
+
+fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
+    ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
+                               False);
+}
+
+fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
+    ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMAlignOf(t), cx.int_type,
+                               False);
+}
+
+// Computes the size of the data part of a non-dynamically-sized enum.
+fn static_size_of_tag(cx: @crate_ctxt, sp: span, t: ty::t)
+    : type_has_static_size(cx, t) -> uint {
+    if cx.tag_sizes.contains_key(t) { ret cx.tag_sizes.get(t); }
+    alt ty::struct(cx.tcx, t) {
+      ty::ty_tag(tid, subtys) {
+        // Compute max(variant sizes).
+
+        let max_size = 0u;
+        let variants = ty::tag_variants(cx.tcx, tid);
+        for variant: ty::variant_info in *variants {
+            let tup_ty = simplify_type(cx, ty::mk_tup(cx.tcx, variant.args));
+            // Perform any type parameter substitutions.
+
+            tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
+            // Here we possibly do a recursive call.
+
+            // FIXME: Avoid this check. Since the parent has static
+            // size, any field must as well. There should be a way to
+            // express that with constrained types.
+            check (type_has_static_size(cx, tup_ty));
+            let this_size = llsize_of_real(cx, type_of(cx, sp, tup_ty));
+            if max_size < this_size { max_size = this_size; }
+        }
+        cx.tag_sizes.insert(t, max_size);
+        ret max_size;
+      }
+      _ {
+        cx.tcx.sess.span_fatal(sp, "non-enum passed to static_size_of_tag()");
+      }
+    }
+}
+
+fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
+    fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
+        //
+        // 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.
+        //
+
+        let off = C_int(bcx_ccx(cx), 0);
+        let max_align = C_int(bcx_ccx(cx), 1);
+        let bcx = cx;
+        for e: ty::t in elts {
+            let elt_align = align_of(bcx, e);
+            bcx = elt_align.bcx;
+            let elt_size = size_of(bcx, e);
+            bcx = elt_size.bcx;
+            let aligned_off = align_to(bcx, off, elt_align.val);
+            off = Add(bcx, aligned_off, elt_size.val);
+            max_align = umax(bcx, max_align, elt_align.val);
+        }
+        off = align_to(bcx, off, max_align);
+        //off = alt mode {
+        //  align_total. {
+        //    align_to(bcx, off, max_align)
+        //  }
+        //  align_next(t) {
+        //    let {bcx, val: align} = align_of(bcx, t);
+        //    align_to(bcx, off, align)
+        //  }
+        //};
+        ret rslt(bcx, off);
+    }
+    alt ty::struct(bcx_tcx(cx), t) {
+      ty::ty_param(p, _) {
+        let szptr = field_of_tydesc(cx, t, false, abi::tydesc_field_size);
+        ret rslt(szptr.bcx, Load(szptr.bcx, szptr.val));
+      }
+      ty::ty_rec(flds) {
+        let tys: [ty::t] = [];
+        for f: ty::field in flds { tys += [f.mt.ty]; }
+        ret align_elements(cx, tys);
+      }
+      ty::ty_tup(elts) {
+        let tys = [];
+        for tp in elts { tys += [tp]; }
+        ret align_elements(cx, tys);
+      }
+      ty::ty_tag(tid, tps) {
+        let bcx = cx;
+        let ccx = bcx_ccx(bcx);
+        // Compute max(variant sizes).
+
+        let max_size: ValueRef = trans::alloca(bcx, ccx.int_type);
+        Store(bcx, C_int(ccx, 0), max_size);
+        let variants = ty::tag_variants(bcx_tcx(bcx), tid);
+        for variant: ty::variant_info in *variants {
+            // Perform type substitution on the raw argument types.
+
+            let raw_tys: [ty::t] = variant.args;
+            let tys: [ty::t] = [];
+            for raw_ty: ty::t in raw_tys {
+                let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty);
+                tys += [t];
+            }
+            let rslt = align_elements(bcx, tys);
+            bcx = rslt.bcx;
+            let this_size = rslt.val;
+            let old_max_size = Load(bcx, max_size);
+            Store(bcx, umax(bcx, this_size, old_max_size), max_size);
+        }
+        let max_size_val = Load(bcx, max_size);
+        let total_size =
+            if vec::len(*variants) != 1u {
+                Add(bcx, max_size_val, llsize_of(ccx, ccx.int_type))
+            } else { max_size_val };
+        ret rslt(bcx, total_size);
+      }
+    }
+}
+
+fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
+// FIXME: Typestate constraint that shows this alt is
+// exhaustive
+    alt ty::struct(bcx_tcx(cx), t) {
+      ty::ty_param(p, _) {
+        let aptr = field_of_tydesc(cx, t, false, abi::tydesc_field_align);
+        ret rslt(aptr.bcx, Load(aptr.bcx, aptr.val));
+      }
+      ty::ty_rec(flds) {
+        let a = C_int(bcx_ccx(cx), 1);
+        let bcx = cx;
+        for f: ty::field in flds {
+            let align = align_of(bcx, f.mt.ty);
+            bcx = align.bcx;
+            a = umax(bcx, a, align.val);
+        }
+        ret rslt(bcx, a);
+      }
+      ty::ty_tag(_, _) {
+        ret rslt(cx, C_int(bcx_ccx(cx), 1)); // FIXME: stub
+      }
+      ty::ty_tup(elts) {
+        let a = C_int(bcx_ccx(cx), 1);
+        let bcx = cx;
+        for e in elts {
+            let align = align_of(bcx, e);
+            bcx = align.bcx;
+            a = umax(bcx, a, align.val);
+        }
+        ret rslt(bcx, a);
+      }
+    }
+}
+
+// Given a type and a field index into its corresponding type descriptor,
+// returns an LLVM ValueRef of that field from the tydesc, generating the
+// tydesc if necessary.
+fn field_of_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool, field: int) ->
+   result {
+    let ti = none::<@tydesc_info>;
+    let tydesc = trans::get_tydesc(cx, t, escapes, ti).result;
+    ret rslt(tydesc.bcx,
+             GEPi(tydesc.bcx, tydesc.val, [0, field]));
+}
+
+// Creates a simpler, size-equivalent type. The resulting type is guaranteed
+// to have (a) the same size as the type that was passed in; (b) to be non-
+// recursive. This is done by replacing all boxes in a type with boxed unit
+// types.
+fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
+    fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
+        alt ty::struct(ccx.tcx, typ) {
+          ty::ty_box(_) | ty::ty_iface(_, _) {
+            ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx));
+          }
+          ty::ty_uniq(_) {
+            ret ty::mk_imm_uniq(ccx.tcx, ty::mk_nil(ccx.tcx));
+          }
+          ty::ty_fn(_) {
+            ret ty::mk_tup(ccx.tcx,
+                           [ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)),
+                            ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx))]);
+          }
+          ty::ty_res(_, sub, tps) {
+            let sub1 = ty::substitute_type_params(ccx.tcx, tps, sub);
+            ret ty::mk_tup(ccx.tcx,
+                           [ty::mk_int(ccx.tcx), simplify_type(ccx, sub1)]);
+          }
+          _ { ret typ; }
+        }
+    }
+    ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
+}
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index b628c82fe81..94d9b75fb13 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -41,6 +41,8 @@ import link::{mangle_internal_name_by_type_only,
               mangle_exported_name};
 import metadata::{csearch, cstore};
 import util::ppaux::{ty_to_str, ty_to_short_str};
+import shape::{size_of, align_of, llsize_of_real, llalign_of_real,
+               llsize_of, llalign_of, static_size_of_tag};
 
 import trans_common::*;
 import trans_build::*;
@@ -374,63 +376,6 @@ fn trans_shared_free(cx: @block_ctxt, v: ValueRef) -> @block_ctxt {
     ret cx;
 }
 
-fn umax(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = ICmp(cx, lib::llvm::LLVMIntULT, a, b);
-    ret Select(cx, cond, b, a);
-}
-
-fn umin(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
-    let cond = ICmp(cx, lib::llvm::LLVMIntULT, a, b);
-    ret Select(cx, cond, a, b);
-}
-
-fn align_to(cx: @block_ctxt, off: ValueRef, align: ValueRef) -> ValueRef {
-    let mask = Sub(cx, align, C_int(bcx_ccx(cx), 1));
-    let bumped = Add(cx, off, mask);
-    ret And(cx, bumped, Not(cx, mask));
-}
-
-
-// Returns the real size of the given type for the current target.
-fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
-    ret llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
-}
-
-// Returns the real alignment of the given type for the current target.
-fn llalign_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
-    ret llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
-}
-
-fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
-    ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
-                               False);
-}
-
-fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
-    ret llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMAlignOf(t), cx.int_type,
-                               False);
-}
-
-fn size_of(cx: @block_ctxt, t: ty::t) -> result {
-    size_of_(cx, t)
-}
-
-fn size_of_(cx: @block_ctxt, t: ty::t) -> result {
-    let ccx = bcx_ccx(cx);
-    if check type_has_static_size(ccx, t) {
-        let sp = cx.sp;
-        rslt(cx, llsize_of(bcx_ccx(cx), type_of(ccx, sp, t)))
-    } else { dynamic_size_of(cx, t) }
-}
-
-fn align_of(cx: @block_ctxt, t: ty::t) -> result {
-    let ccx = bcx_ccx(cx);
-    if check type_has_static_size(ccx, t) {
-        let sp = cx.sp;
-        rslt(cx, llalign_of(bcx_ccx(cx), type_of(ccx, sp, t)))
-    } else { dynamic_align_of(cx, t) }
-}
-
 fn alloca(cx: @block_ctxt, t: TypeRef) -> ValueRef {
     if cx.unreachable { ret llvm::LLVMGetUndef(t); }
     ret Alloca(new_raw_block_ctxt(cx.fcx, cx.fcx.llstaticallocas), t);
@@ -467,187 +412,6 @@ fn mk_obstack_token(ccx: @crate_ctxt, fcx: @fn_ctxt) ->
     ret Call(cx, ccx.upcalls.dynastack_mark, []);
 }
 
-
-// Creates a simpler, size-equivalent type. The resulting type is guaranteed
-// to have (a) the same size as the type that was passed in; (b) to be non-
-// recursive. This is done by replacing all boxes in a type with boxed unit
-// types.
-fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
-    fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
-        alt ty::struct(ccx.tcx, typ) {
-          ty::ty_box(_) | ty::ty_iface(_, _) {
-            ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx));
-          }
-          ty::ty_uniq(_) {
-            ret ty::mk_imm_uniq(ccx.tcx, ty::mk_nil(ccx.tcx));
-          }
-          ty::ty_fn(_) {
-            ret ty::mk_tup(ccx.tcx,
-                           [ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)),
-                            ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx))]);
-          }
-          ty::ty_res(_, sub, tps) {
-            let sub1 = ty::substitute_type_params(ccx.tcx, tps, sub);
-            ret ty::mk_tup(ccx.tcx,
-                           [ty::mk_int(ccx.tcx), simplify_type(ccx, sub1)]);
-          }
-          _ { ret typ; }
-        }
-    }
-    ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
-}
-
-
-// Computes the size of the data part of a non-dynamically-sized enum.
-fn static_size_of_tag(cx: @crate_ctxt, sp: span, t: ty::t)
-    : type_has_static_size(cx, t) -> uint {
-    if cx.tag_sizes.contains_key(t) { ret cx.tag_sizes.get(t); }
-    alt ty::struct(cx.tcx, t) {
-      ty::ty_tag(tid, subtys) {
-        // Compute max(variant sizes).
-
-        let max_size = 0u;
-        let variants = ty::tag_variants(cx.tcx, tid);
-        for variant: ty::variant_info in *variants {
-            let tup_ty = simplify_type(cx, ty::mk_tup(cx.tcx, variant.args));
-            // Perform any type parameter substitutions.
-
-            tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
-            // Here we possibly do a recursive call.
-
-            // FIXME: Avoid this check. Since the parent has static
-            // size, any field must as well. There should be a way to
-            // express that with constrained types.
-            check (type_has_static_size(cx, tup_ty));
-            let this_size = llsize_of_real(cx, type_of(cx, sp, tup_ty));
-            if max_size < this_size { max_size = this_size; }
-        }
-        cx.tag_sizes.insert(t, max_size);
-        ret max_size;
-      }
-      _ {
-        cx.tcx.sess.span_fatal(sp, "non-enum passed to static_size_of_tag()");
-      }
-    }
-}
-
-fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
-    fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
-        //
-        // 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.
-        //
-
-        let off = C_int(bcx_ccx(cx), 0);
-        let max_align = C_int(bcx_ccx(cx), 1);
-        let bcx = cx;
-        for e: ty::t in elts {
-            let elt_align = align_of(bcx, e);
-            bcx = elt_align.bcx;
-            let elt_size = size_of(bcx, e);
-            bcx = elt_size.bcx;
-            let aligned_off = align_to(bcx, off, elt_align.val);
-            off = Add(bcx, aligned_off, elt_size.val);
-            max_align = umax(bcx, max_align, elt_align.val);
-        }
-        off = align_to(bcx, off, max_align);
-        //off = alt mode {
-        //  align_total. {
-        //    align_to(bcx, off, max_align)
-        //  }
-        //  align_next(t) {
-        //    let {bcx, val: align} = align_of(bcx, t);
-        //    align_to(bcx, off, align)
-        //  }
-        //};
-        ret rslt(bcx, off);
-    }
-    alt ty::struct(bcx_tcx(cx), t) {
-      ty::ty_param(p, _) {
-        let szptr = field_of_tydesc(cx, t, false, abi::tydesc_field_size);
-        ret rslt(szptr.bcx, Load(szptr.bcx, szptr.val));
-      }
-      ty::ty_rec(flds) {
-        let tys: [ty::t] = [];
-        for f: ty::field in flds { tys += [f.mt.ty]; }
-        ret align_elements(cx, tys);
-      }
-      ty::ty_tup(elts) {
-        let tys = [];
-        for tp in elts { tys += [tp]; }
-        ret align_elements(cx, tys);
-      }
-      ty::ty_tag(tid, tps) {
-        let bcx = cx;
-        let ccx = bcx_ccx(bcx);
-        // Compute max(variant sizes).
-
-        let max_size: ValueRef = alloca(bcx, ccx.int_type);
-        Store(bcx, C_int(ccx, 0), max_size);
-        let variants = ty::tag_variants(bcx_tcx(bcx), tid);
-        for variant: ty::variant_info in *variants {
-            // Perform type substitution on the raw argument types.
-
-            let raw_tys: [ty::t] = variant.args;
-            let tys: [ty::t] = [];
-            for raw_ty: ty::t in raw_tys {
-                let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty);
-                tys += [t];
-            }
-            let rslt = align_elements(bcx, tys);
-            bcx = rslt.bcx;
-            let this_size = rslt.val;
-            let old_max_size = Load(bcx, max_size);
-            Store(bcx, umax(bcx, this_size, old_max_size), max_size);
-        }
-        let max_size_val = Load(bcx, max_size);
-        let total_size =
-            if vec::len(*variants) != 1u {
-                Add(bcx, max_size_val, llsize_of(ccx, ccx.int_type))
-            } else { max_size_val };
-        ret rslt(bcx, total_size);
-      }
-    }
-}
-
-fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
-// FIXME: Typestate constraint that shows this alt is
-// exhaustive
-    alt ty::struct(bcx_tcx(cx), t) {
-      ty::ty_param(p, _) {
-        let aptr = field_of_tydesc(cx, t, false, abi::tydesc_field_align);
-        ret rslt(aptr.bcx, Load(aptr.bcx, aptr.val));
-      }
-      ty::ty_rec(flds) {
-        let a = C_int(bcx_ccx(cx), 1);
-        let bcx = cx;
-        for f: ty::field in flds {
-            let align = align_of(bcx, f.mt.ty);
-            bcx = align.bcx;
-            a = umax(bcx, a, align.val);
-        }
-        ret rslt(bcx, a);
-      }
-      ty::ty_tag(_, _) {
-        ret rslt(cx, C_int(bcx_ccx(cx), 1)); // FIXME: stub
-      }
-      ty::ty_tup(elts) {
-        let a = C_int(bcx_ccx(cx), 1);
-        let bcx = cx;
-        for e in elts {
-            let align = align_of(bcx, e);
-            bcx = align.bcx;
-            a = umax(bcx, a, align.val);
-        }
-        ret rslt(bcx, a);
-      }
-    }
-}
-
 // Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
 // The type of the returned pointer is always i8*.  If you care about the
 // return type, use bump_ptr().
@@ -858,17 +622,6 @@ fn trans_malloc_boxed(cx: @block_ctxt, t: ty::t) ->
 
 // Type descriptor and type glue stuff
 
-// Given a type and a field index into its corresponding type descriptor,
-// returns an LLVM ValueRef of that field from the tydesc, generating the
-// tydesc if necessary.
-fn field_of_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool, field: int) ->
-   result {
-    let ti = none::<@tydesc_info>;
-    let tydesc = get_tydesc(cx, t, escapes, ti).result;
-    ret rslt(tydesc.bcx,
-             GEPi(tydesc.bcx, tydesc.val, [0, field]));
-}
-
 // Given a type containing ty params, build a vector containing a ValueRef for
 // each of the ty params it uses (from the current frame) and a vector of the
 // indices of the ty params present in the type. This is used solely for
diff --git a/src/comp/middle/trans_closure.rs b/src/comp/middle/trans_closure.rs
index fcfb4f5244e..7fece0cefdf 100644
--- a/src/comp/middle/trans_closure.rs
+++ b/src/comp/middle/trans_closure.rs
@@ -18,7 +18,6 @@ import util::ppaux::ty_to_str;
 import trans::{
     trans_shared_malloc,
     type_of_inner,
-    size_of,
     node_id_type,
     INIT,
     trans_shared_free,
@@ -27,6 +26,7 @@ import trans::{
     load_if_immediate,
     dest
 };
+import shape::{size_of};
 
 // ___Good to know (tm)__________________________________________________
 //
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index baf368ab631..7141117d231 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -902,6 +902,22 @@ fn hash_dict_id(&&dp: dict_id) -> uint {
     h
 }
 
+fn umax(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
+    let cond = trans_build::ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    ret trans_build::Select(cx, cond, b, a);
+}
+
+fn umin(cx: @block_ctxt, a: ValueRef, b: ValueRef) -> ValueRef {
+    let cond = trans_build::ICmp(cx, lib::llvm::LLVMIntULT, a, b);
+    ret trans_build::Select(cx, cond, a, b);
+}
+
+fn align_to(cx: @block_ctxt, off: ValueRef, align: ValueRef) -> ValueRef {
+    let mask = trans_build::Sub(cx, align, C_int(bcx_ccx(cx), 1));
+    let bumped = trans_build::Add(cx, off, mask);
+    ret trans_build::And(cx, bumped, trans_build::Not(cx, mask));
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/middle/trans_uniq.rs b/src/comp/middle/trans_uniq.rs
index 6b420a43091..b7ea546613e 100644
--- a/src/comp/middle/trans_uniq.rs
+++ b/src/comp/middle/trans_uniq.rs
@@ -5,7 +5,6 @@ import trans_build::*;
 import trans::{
     trans_shared_malloc,
     type_of_inner,
-    size_of,
     node_id_type,
     INIT,
     trans_shared_free,
@@ -14,6 +13,7 @@ import trans::{
     load_if_immediate,
     dest
 };
+import shape::{size_of};
 
 export trans_uniq, make_free_glue, type_is_unique_box, autoderef, duplicate,
        alloc_uniq;
diff --git a/src/comp/middle/trans_vec.rs b/src/comp/middle/trans_vec.rs
index feccfc413bf..68207867071 100644
--- a/src/comp/middle/trans_vec.rs
+++ b/src/comp/middle/trans_vec.rs
@@ -3,11 +3,11 @@ import option::none;
 import syntax::ast;
 import lib::llvm::llvm::{ValueRef, TypeRef};
 import back::abi;
-import trans::{call_memmove, trans_shared_malloc, llsize_of, type_of_or_i8,
-               INIT, copy_val, load_if_immediate, size_of,
-               get_tydesc,
+import trans::{call_memmove, trans_shared_malloc, type_of_or_i8,
+               INIT, copy_val, load_if_immediate, get_tydesc,
                node_id_type, new_sub_block_ctxt, do_spill_noroot,
                dest};
+import shape::{llsize_of, size_of};
 import trans_build::*;
 import trans_common::*;