about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/back/upcall.rs8
-rw-r--r--src/librustc/lib/llvm.rs47
-rw-r--r--src/librustc/middle/trans/_match.rs2
-rw-r--r--src/librustc/middle/trans/adt.rs12
-rw-r--r--src/librustc/middle/trans/asm.rs2
-rw-r--r--src/librustc/middle/trans/base.rs92
-rw-r--r--src/librustc/middle/trans/build.rs55
-rw-r--r--src/librustc/middle/trans/cabi.rs57
-rw-r--r--src/librustc/middle/trans/cabi_arm.rs89
-rw-r--r--src/librustc/middle/trans/cabi_mips.rs101
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs2
-rw-r--r--src/librustc/middle/trans/cabi_x86_64.rs178
-rw-r--r--src/librustc/middle/trans/callee.rs8
-rw-r--r--src/librustc/middle/trans/closure.rs2
-rw-r--r--src/librustc/middle/trans/common.rs392
-rw-r--r--src/librustc/middle/trans/consts.rs54
-rw-r--r--src/librustc/middle/trans/context.rs16
-rw-r--r--src/librustc/middle/trans/controlflow.rs4
-rw-r--r--src/librustc/middle/trans/expr.rs14
-rw-r--r--src/librustc/middle/trans/foreign.rs19
-rw-r--r--src/librustc/middle/trans/glue.rs78
-rw-r--r--src/librustc/middle/trans/machine.rs4
-rw-r--r--src/librustc/middle/trans/meth.rs6
-rw-r--r--src/librustc/middle/trans/reflect.rs4
-rw-r--r--src/librustc/middle/trans/shape.rs6
-rw-r--r--src/librustc/middle/trans/tvec.rs2
-rw-r--r--src/librustc/middle/trans/type_.rs64
-rw-r--r--src/librustc/middle/trans/type_of.rs73
-rw-r--r--src/librustc/middle/trans/write_guard.rs2
-rw-r--r--src/libstd/unstable/intrinsics.rs10
30 files changed, 517 insertions, 886 deletions
diff --git a/src/librustc/back/upcall.rs b/src/librustc/back/upcall.rs
index 731fa1c0ad7..76bba481619 100644
--- a/src/librustc/back/upcall.rs
+++ b/src/librustc/back/upcall.rs
@@ -24,17 +24,17 @@ pub struct Upcalls {
 
 macro_rules! upcall (
     (fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
-        let fn_ty = Type::func([ $($arg),* ], $ret);
+        let fn_ty = Type::func([ $($arg),* ], &$ret);
         base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty)
     });
     (nothrow fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
-        let fn_ty = Type::func([ $($arg),* ], $ret);
+        let fn_ty = Type::func([ $($arg),* ], &$ret);
         let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
         base::set_no_unwind(decl);
         decl
     });
     (nothrow fn $name:ident -> $ret:expr) => ({
-        let fn_ty = Type::func([], $ret);
+        let fn_ty = Type::func([], &$ret);
         let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
         base::set_no_unwind(decl);
         decl
@@ -42,7 +42,7 @@ macro_rules! upcall (
 )
 
 pub fn declare_upcalls(targ_cfg: @session::config, llmod: ModuleRef) -> @Upcalls {
-    let opaque_ptr = Type::i8().to_ptr();
+    let opaque_ptr = Type::i8().ptr_to();
     let int_ty = Type::int(targ_cfg.arch);
 
     @Upcalls {
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 627474b2189..ec3bf61608c 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -2141,7 +2141,7 @@ impl TypeNames {
     }
 
     pub fn find_name<'r>(&'r self, ty: &Type) -> Option<&'r str> {
-        match self.type_names.find(ty.to_ref()) {
+        match self.type_names.find(&ty.to_ref()) {
             Some(a) => Some(a.slice(0, a.len())),
             None => None
         }
@@ -2151,14 +2151,14 @@ impl TypeNames {
         self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
     }
 
-    pub fn type_to_str(&self, ty: TypeRef) -> ~str {
+    pub fn type_to_str(&self, ty: Type) -> ~str {
         match self.find_name(&ty) {
             option::Some(name) => return name.to_owned(),
             None => ()
         }
 
         unsafe {
-            let kind = llvm::LLVMGetTypeKind(ty);
+            let kind = ty.kind();
 
             match kind {
                 Void => ~"Void",
@@ -2172,31 +2172,28 @@ impl TypeNames {
                 Metadata => ~"Metadata",
                 X86_MMX => ~"X86_MMAX",
                 Integer => {
-                    fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty) as int)
+                    fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty.to_ref()) as int)
                 }
                 Function => {
-                    let out_ty = llvm::LLVMGetReturnType(ty);
-                    let n_args = llvm::LLVMCountParamTypes(ty) as uint;
-                    let args = vec::from_elem(n_args, 0 as TypeRef);
-                    llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
-
+                    let out_ty = ty.return_type();
+                    let args = ty.func_params();
                     let args = args.map(|&ty| self.type_to_str(ty)).connect(", ");
                     let out_ty = self.type_to_str(out_ty);
                     fmt!("fn(%s) -> %s", args, out_ty)
                 }
                 Struct => {
-                    let tys = struct_tys(ty);
+                    let tys = ty.field_types();
                     let tys = tys.map(|&ty| self.type_to_str(ty)).connect(", ");
                     fmt!("{%s}", tys)
                 }
                 Array => {
-                    let el_ty = llvm::LLVMGetElementType(ty);
+                    let el_ty = ty.element_type();
                     let el_ty = self.type_to_str(el_ty);
-                    let len = llvm::LLVMGetArrayLength(ty) as uint;
+                    let len = ty.array_length();
                     fmt!("[%s x %u]", el_ty, len)
                 }
                 Pointer => {
-                    let el_ty = llvm::LLVMGetElementType(ty);
+                    let el_ty = ty.element_type();
                     let el_ty = self.type_to_str(el_ty);
                     fmt!("*%s", el_ty)
                 }
@@ -2207,32 +2204,12 @@ impl TypeNames {
 
     pub fn val_to_str(&self, val: ValueRef) -> ~str {
         unsafe {
-            self.type_to_str(llvm::LLVMTypeOf(val))
+            let ty = Type::from_ref(llvm::LLVMTypeOf(val));
+            self.type_to_str(ty)
         }
     }
 }
 
-pub fn float_width(llt: TypeRef) -> uint {
-    unsafe {
-        return match llvm::LLVMGetTypeKind(llt) as int {
-              1 => 32u,
-              2 => 64u,
-              3 => 80u,
-              4 | 5 => 128u,
-              _ => fail!("llvm_float_width called on a non-float type")
-            };
-    }
-}
-
-pub fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] {
-    unsafe {
-        let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint,
-                                 0 as TypeRef);
-        llvm::LLVMGetParamTypes(fn_ty, vec::raw::to_ptr(args));
-        return args;
-    }
-}
-
 
 /* Memory-managed interface to target data. */
 
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index db5a642019c..72da71afed6 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -911,7 +911,7 @@ pub fn extract_vec_elems(bcx: block,
                     Sub(bcx, count,
                         C_int(bcx.ccx(), (elem_count - i) as int))])
             }
-            _ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty) }
+            _ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty.to_ref()) }
         }
     };
     if slice.is_some() {
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 65163e384b1..906c9d028eb 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -59,6 +59,8 @@ use middle::ty;
 use syntax::ast;
 use util::ppaux::ty_to_str;
 
+use middle::trans::type_::Type;
+
 
 /// Representations.
 pub enum Repr {
@@ -260,10 +262,8 @@ fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool) -> ~[Type] {
             let most_aligned = most_aligned.get();
             let padding = largest_size - most_aligned.size;
 
-            assert!(padding >= 0);
-
             struct_llfields(cx, most_aligned, sizing)
-                + [Type::array(Type::i8(), padding /*bad*/as uint)]
+                + [Type::array(&Type::i8(), padding)]
         }
     }
 }
@@ -439,7 +439,7 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
                 // The unit-like case might have a nonzero number of unit-like fields.
                 // (e.g., Result or Either with () as one side.)
                 let ty = type_of::type_of(bcx.ccx(), nullfields[ix]);
-                assert_eq!(machine::llsize_of_alloc(bcx.ccx(), llty), 0);
+                assert_eq!(machine::llsize_of_alloc(bcx.ccx(), ty), 0);
                 // The contents of memory at this pointer can't matter, but use
                 // the value that's "reasonable" in case of pointer comparison.
                 PointerCast(bcx, val, ty.ptr_to())
@@ -457,7 +457,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
             type_of::type_of(ccx, ty)
         };
         let real_ty = Type::struct_(fields, st.packed);
-        PointerCast(bcx, val, real_llty.to_ptr().to_ref())
+        PointerCast(bcx, val, real_ty.ptr_to())
     } else {
         val
     };
@@ -572,7 +572,7 @@ fn build_const_struct(ccx: &mut CrateContext, st: &Struct, vals: &[ValueRef])
 }
 
 fn padding(size: u64) -> ValueRef {
-    C_undef(Type::array(Type::i8(), size).to_ref())
+    C_undef(Type::array(&Type::i8(), size))
 }
 
 // XXX this utility routine should be somewhere more general
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 17294107ce3..dd8b7ebc00b 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -20,6 +20,8 @@ use middle::trans::callee;
 use middle::trans::common::*;
 use middle::ty;
 
+use middle::trans::type_::Type;
+
 use core::str;
 use syntax::ast;
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index de91a9c593a..8ec05f447ee 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -63,6 +63,8 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::{Repr, ty_to_str};
 
+use middle::trans::type_::Type;
+
 use core::hash;
 use core::hashmap::{HashMap};
 use core::int;
@@ -150,7 +152,7 @@ pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type)
 }
 
 pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
-    return decl_fn(llmod, name, lib::llvm::CCallConv, llty);
+    return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
 }
 
 // Only use this if you are going to actually define the function. It's
@@ -229,7 +231,7 @@ pub fn opaque_box_body(bcx: block,
     let _icx = bcx.insn_ctxt("opaque_box_body");
     let ccx = bcx.ccx();
     let ty = type_of(ccx, body_t);
-    let ty = Type::box(ccx, ty);
+    let ty = Type::box(ccx, &ty);
     let boxptr = PointerCast(bcx, boxptr, ty.ptr_to());
     GEPi(bcx, boxptr, [0u, abi::box_field_body])
 }
@@ -281,15 +283,8 @@ pub fn malloc_raw_dyn(bcx: block,
 * address space 0. Otherwise the resulting (non-box) pointer will be in the
 * wrong address space and thus be the wrong type.
 */
-pub fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef {
-    unsafe {
-        debug!("non_gc_box_cast");
-        add_comment(bcx, "non_gc_box_cast");
-        assert!(llvm::LLVMGetPointerAddressSpace(val_ty(val)) ==
-                     gc_box_addrspace || bcx.unreachable);
-        let non_gc_t = llvm::LLVMGetElementType(val_ty(val)).ptr_to();
-        PointerCast(bcx, val, non_gc_t)
-    }
+pub fn non_gc_box_cast(_: block, val: ValueRef) -> ValueRef {
+    val
 }
 
 // malloc_raw: expects an unboxed type and returns a pointer to
@@ -721,8 +716,8 @@ pub fn cast_shift_expr_rhs(cx: block, op: ast::binop,
 pub fn cast_shift_const_rhs(op: ast::binop,
                             lhs: ValueRef, rhs: ValueRef) -> ValueRef {
     cast_shift_rhs(op, lhs, rhs,
-                   |a, b| unsafe { llvm::LLVMConstTrunc(a, b) },
-                   |a, b| unsafe { llvm::LLVMConstZExt(a, b) })
+                   |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) },
+                   |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
 }
 
 pub fn cast_shift_rhs(op: ast::binop,
@@ -735,8 +730,8 @@ pub fn cast_shift_rhs(op: ast::binop,
         if ast_util::is_shift_binop(op) {
             let rhs_llty = val_ty(rhs);
             let lhs_llty = val_ty(lhs);
-            let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty);
-            let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty);
+            let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty.to_ref());
+            let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty.to_ref());
             if lhs_sz < rhs_sz {
                 trunc(rhs, lhs_llty)
             } else if lhs_sz > rhs_sz {
@@ -761,11 +756,11 @@ pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
     };
     let is_zero = match ty::get(rhs_t).sty {
       ty::ty_int(t) => {
-        let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, False);
+        let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false);
         ICmp(cx, lib::llvm::IntEQ, rhs, zero)
       }
       ty::ty_uint(t) => {
-        let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, False);
+        let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false);
         ICmp(cx, lib::llvm::IntEQ, rhs, zero)
       }
       _ => {
@@ -779,7 +774,7 @@ pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
 }
 
 pub fn null_env_ptr(bcx: block) -> ValueRef {
-    C_null(Type::opaque_box(bcx.ccx()).to_ptr())
+    C_null(Type::opaque_box(bcx.ccx()).ptr_to())
 }
 
 pub fn trans_external_path(ccx: &mut CrateContext, did: ast::def_id, t: ty::t)
@@ -1479,7 +1474,7 @@ pub fn memzero(cx: block, llptr: ValueRef, llty: TypeRef) {
     let llintrinsicfn = ccx.intrinsics.get_copy(&intrinsic_key);
     let llptr = PointerCast(cx, llptr, Type::i8().ptr_to());
     let llzeroval = C_u8(0);
-    let size = IntCast(cx, machine::llsize_of(ccx, ty), ccx.int_type.to_ref());
+    let size = IntCast(cx, machine::llsize_of(ccx, ty), ccx.int_type);
     let align = C_i32(llalign_of_min(ccx, ty) as i32);
     let volatile = C_i1(false);
     Call(cx, llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
@@ -1506,7 +1501,7 @@ pub fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
         }
     }
     let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
-    let p = Alloca(initcx, ty.to_ref());
+    let p = Alloca(initcx, ty);
     if zero { memzero(initcx, p, ty); }
     p
 }
@@ -1515,10 +1510,10 @@ pub fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
     let _icx = cx.insn_ctxt("arrayalloca");
     if cx.unreachable {
         unsafe {
-            return llvm::LLVMGetUndef(ty);
+            return llvm::LLVMGetUndef(ty.to_ref());
         }
     }
-    return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), ty.to_ref(), v);
+    return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), ty, v);
 }
 
 pub struct BasicBlocks {
@@ -1588,7 +1583,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
     let fcx = @mut fn_ctxt_ {
           llfn: llfndecl,
           llenv: unsafe {
-              llvm::LLVMGetUndef(Type::i8p())
+              llvm::LLVMGetUndef(Type::i8p().to_ref())
           },
           llretptr: None,
           llstaticallocas: llbbs.sa,
@@ -2309,7 +2304,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
     fn create_entry_fn(ccx: @mut CrateContext,
                        rust_main: ValueRef,
                        use_start_lang_item: bool) {
-        let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], ccx.int_type);
+        let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], &ccx.int_type);
 
         // FIXME #4404 android JNI hacks
         let llfn = if *ccx.sess.building_library {
@@ -2338,10 +2333,9 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
             }
 
             let crate_map = ccx.crate_map;
-            let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
-                                                              crate_map,
-                                                              Type::i8p(),
-                                                              noname());
+            let opaque_crate_map = do "crate_map".as_c_str |buf| {
+                llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf)
+            };
 
             let (start_fn, args) = if use_start_lang_item {
                 let start_def_id = ccx.tcx.lang_items.start_fn();
@@ -2354,8 +2348,9 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
                 };
 
                 let args = {
-                    let opaque_rust_main = llvm::LLVMBuildPointerCast(
-                            bld, rust_main, Type::i8p(), noname());
+                    let opaque_rust_main = do "rust_main".as_c_str |buf| {
+                        llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf)
+                    };
 
                     ~[
                         C_null(Type::opaque_box(ccx).ptr_to()),
@@ -2487,7 +2482,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
                     let g = do str::as_c_str(ident) |buf| {
                         unsafe {
                             let ty = type_of(ccx, typ);
-                            llvm::LLVMAddGlobal(ccx.llmod, ty, buf)
+                            llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
                         }
                     };
                     g
@@ -2583,7 +2578,7 @@ pub fn trans_constant(ccx: @mut CrateContext, it: @ast::item) {
             note_unique_llvm_symbol(ccx, s);
             let discrim_gvar = str::as_c_str(s, |buf| {
                 unsafe {
-                    llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+                    llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
                 }
             });
             unsafe {
@@ -2616,14 +2611,14 @@ pub fn vp2i(cx: block, v: ValueRef) -> ValueRef {
 
 pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
     unsafe {
-        return llvm::LLVMConstPtrToInt(v, ccx.int_type);
+        return llvm::LLVMConstPtrToInt(v, ccx.int_type.to_ref());
     }
 }
 
 macro_rules! ifn (
     ($name:expr, $args:expr, $ret:expr) => ({
         let name = $name;
-        let f = decl_cdecl_fn(llmod, name, Type::func($args, $ret));
+        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret));
         intrinsics.insert(name, f);
     })
 )
@@ -2642,7 +2637,7 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
          [i8p, i8p, Type::i64(), Type::i32(), Type::i1()], Type::void());
     ifn!("llvm.memset.p0i8.i32",
          [i8p, Type::i8(), Type::i32(), Type::i32(), Type::i1()], Type::void());
-    ifn!("llvm.memcpy.p0i8.i64",
+    ifn!("llvm.memset.p0i8.i64",
          [i8p, Type::i8(), Type::i64(), Type::i32(), Type::i1()], Type::void());
 
     ifn!("llvm.trap", [], Type::void());
@@ -2710,7 +2705,7 @@ pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<&'stati
 }
 
 pub fn trap(bcx: block) {
-    match bcx.ccx().intrinsics.find_equiv("llvm.trap") {
+    match bcx.ccx().intrinsics.find_equiv(& &"llvm.trap") {
       Some(&x) => { Call(bcx, x, []); },
       _ => bcx.sess().bug("unbound llvm.trap in trap")
     }
@@ -2724,7 +2719,7 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
     let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
     let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| {
         unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod, Type::i32(), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
         }
     };
     unsafe {
@@ -2736,12 +2731,12 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
 
 pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
     let elttype = Type::struct_([ccx.int_type, ccx.int_type], false);
-    let maptype = Type::array(elttype, ccx.module_data.len() + 1);
-    let map = str::as_c_str("_rust_mod_map", |buf| {
+    let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64);
+    let map = do "_rust_mod_map".as_c_str |buf| {
         unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
+            llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
         }
-    });
+    };
     lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
     let mut elts: ~[ValueRef] = ~[];
 
@@ -2783,11 +2778,11 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
         ~"toplevel"
     };
     let sym_name = ~"_rust_crate_map_" + mapname;
-    let arrtype = Type::array(int_type, n_subcrates as u64);
+    let arrtype = Type::array(&int_type, n_subcrates as u64);
     let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
     let map = str::as_c_str(sym_name, |buf| {
         unsafe {
-            llvm::LLVMAddGlobal(llmod, maptype, buf)
+            llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
         }
     });
     lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
@@ -2806,7 +2801,7 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
                       cstore::get_crate_hash(cstore, i));
         let cr = str::as_c_str(nm, |buf| {
             unsafe {
-                llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+                llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
             }
         });
         subcrates.push(p2i(ccx, cr));
@@ -2830,8 +2825,7 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
         let mod_map = create_module_map(ccx);
         llvm::LLVMSetInitializer(map, C_struct(
             [C_i32(1),
-             lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn,
-                                                   Type::i8p()),
+             lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn, Type::i8p().to_ref()),
              p2i(ccx, mod_map),
              C_array(ccx.int_type, subcrates)]));
     }
@@ -2869,7 +2863,7 @@ pub fn write_metadata(cx: &mut CrateContext, crate: &ast::crate) {
     let llconst = C_struct([llmeta]);
     let mut llglobal = str::as_c_str("rust_metadata", |buf| {
         unsafe {
-            llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf)
+            llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
         }
     });
     unsafe {
@@ -2880,9 +2874,9 @@ pub fn write_metadata(cx: &mut CrateContext, crate: &ast::crate) {
         lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
 
         let t_ptr_i8 = Type::i8p();
-        llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8);
+        llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8.to_ref());
         let llvm_used = do "llvm.used".as_c_str |buf| {
-            llvm::LLVMAddGlobal(cx.llmod, Type::array(t_ptr_i8, 1u), buf)
+            llvm::LLVMAddGlobal(cx.llmod, Type::array(&t_ptr_i8, 1).to_ref(), buf)
         };
         lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
         llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, [llglobal]));
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index be14da66a16..3e5a23cb18e 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -13,12 +13,14 @@ use core::prelude::*;
 use lib::llvm::llvm;
 use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect};
 use lib::llvm::{Opcode, IntPredicate, RealPredicate, False};
-use lib::llvm::{ValueRef, Type, BasicBlockRef, BuilderRef, ModuleRef};
+use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
 use lib;
 use middle::trans::common::*;
 use middle::trans::machine::llalign_of_min;
 use syntax::codemap::span;
 
+use middle::trans::type_::Type;
+
 use core::cast;
 use core::hashmap::HashMap;
 use core::libc::{c_uint, c_ulonglong, c_char};
@@ -232,7 +234,7 @@ pub fn Unreachable(cx: block) {
 
 pub fn _Undef(val: ValueRef) -> ValueRef {
     unsafe {
-        return llvm::LLVMGetUndef(val_ty(val));
+        return llvm::LLVMGetUndef(val_ty(val).to_ref());
     }
 }
 
@@ -504,7 +506,7 @@ pub fn ArrayMalloc(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
 
 pub fn Alloca(cx: block, Ty: Type) -> ValueRef {
     unsafe {
-        if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ptr().to_ref()); }
+        if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
         count_insn(cx, "alloca");
         return llvm::LLVMBuildAlloca(B(cx), Ty.to_ref(), noname());
     }
@@ -512,7 +514,7 @@ pub fn Alloca(cx: block, Ty: Type) -> ValueRef {
 
 pub fn ArrayAlloca(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ptr().to_ref()); }
+        if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
         count_insn(cx, "arrayalloca");
         return llvm::LLVMBuildArrayAlloca(B(cx), Ty.to_ref(), Val, noname());
     }
@@ -531,9 +533,12 @@ pub fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
         let ccx = cx.fcx.ccx;
         if cx.unreachable {
             let ty = val_ty(PointerVal);
-            let eltty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Array {
-                llvm::LLVMGetElementType(ty) } else { ccx.int_type };
-            return llvm::LLVMGetUndef(eltty);
+            let eltty = if ty.kind() == lib::llvm::Array {
+                ty.element_type()
+            } else {
+                ccx.int_type
+            };
+            return llvm::LLVMGetUndef(eltty.to_ref());
         }
         count_insn(cx, "load");
         return llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
@@ -544,7 +549,7 @@ pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> Val
     unsafe {
         let ccx = cx.fcx.ccx;
         if cx.unreachable {
-            return llvm::LLVMGetUndef(ccx.int_type);
+            return llvm::LLVMGetUndef(ccx.int_type.to_ref());
         }
         count_insn(cx, "load.atomic");
         let align = llalign_of_min(ccx, ccx.int_type);
@@ -639,7 +644,7 @@ pub fn StructGEP(cx: block, Pointer: ValueRef, Idx: uint) -> ValueRef {
 
 pub fn GlobalString(cx: block, _Str: *c_char) -> ValueRef {
     unsafe {
-        if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p()); }
+        if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
         count_insn(cx, "globalstring");
         return llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
     }
@@ -647,7 +652,7 @@ pub fn GlobalString(cx: block, _Str: *c_char) -> ValueRef {
 
 pub fn GlobalStringPtr(cx: block, _Str: *c_char) -> ValueRef {
     unsafe {
-        if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p()); }
+        if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
         count_insn(cx, "globalstringptr");
         return llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
     }
@@ -841,7 +846,7 @@ pub fn Phi(cx: block, Ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef])
     unsafe {
         if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); }
         assert_eq!(vals.len(), bbs.len());
-        let phi = EmptyPhi(cx, Ty.to_ref());
+        let phi = EmptyPhi(cx, Ty);
         count_insn(cx, "addincoming");
         llvm::LLVMAddIncoming(phi, vec::raw::to_ptr(vals),
                               vec::raw::to_ptr(bbs),
@@ -863,10 +868,13 @@ pub fn _UndefReturn(cx: block, Fn: ValueRef) -> ValueRef {
     unsafe {
         let ccx = cx.fcx.ccx;
         let ty = val_ty(Fn);
-        let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer {
-            llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
-            count_insn(cx, "");
-        return llvm::LLVMGetUndef(retty);
+        let retty = if ty.kind() == lib::llvm::Integer {
+            ty.return_type()
+        } else {
+            ccx.int_type
+        };
+        count_insn(cx, "ret_undef");
+        return llvm::LLVMGetUndef(retty.to_ref());
     }
 }
 
@@ -887,9 +895,10 @@ pub fn add_comment(bcx: block, text: &str) {
             let comment_text = ~"# " +
                 sanitized.replace("\n", "\n\t# ");
             count_insn(bcx, "inlineasm");
-            let asm = str::as_c_str(comment_text, |c| {
-                llvm::LLVMConstInlineAsm(Type::func([], Type::void()), c, noname(), False, False)
-            });
+            let asm = do comment_text.as_c_str |c| {
+                llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
+                                         c, noname(), False, False)
+            };
             Call(bcx, asm, []);
         }
     }
@@ -913,8 +922,8 @@ pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
         };
 
         debug!("Asm Output Type: %?", cx.ccx().tn.type_to_str(output));
-        let fty = Type::func(argtys, output);
-        let v = llvm::LLVMInlineAsm(llfty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
+        let fty = Type::func(argtys, &output);
+        let v = llvm::LLVMInlineAsm(fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
 
         Call(cx, v, inputs)
     }
@@ -1005,9 +1014,9 @@ pub fn ShuffleVector(cx: block, V1: ValueRef, V2: ValueRef,
 pub fn VectorSplat(cx: block, NumElts: uint, EltVal: ValueRef) -> ValueRef {
     unsafe {
         let elt_ty = val_ty(EltVal);
-        let Undef = llvm::LLVMGetUndef(Type::vector(elt_ty, NumElts).to_ref());
+        let Undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, NumElts as u64).to_ref());
         let VecVal = InsertElement(cx, Undef, EltVal, C_i32(0));
-        ShuffleVector(cx, VecVal, Undef, C_null(Type::vector(Type::i32().to_ref(), NumElts)))
+        ShuffleVector(cx, VecVal, Undef, C_null(Type::vector(&Type::i32(), NumElts as u64)))
     }
 }
 
@@ -1049,7 +1058,7 @@ pub fn IsNotNull(cx: block, Val: ValueRef) -> ValueRef {
 pub fn PtrDiff(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
     unsafe {
         let ccx = cx.fcx.ccx;
-        if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type); }
+        if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type.to_ref()); }
         count_insn(cx, "ptrdiff");
         return llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
     }
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index 036f34b1974..dffa5a7f1ad 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -8,20 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use lib::llvm::{llvm, TypeRef, ValueRef, Attribute, Void};
+use lib::llvm::{llvm, ValueRef, Attribute, Void};
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::common::*;
 
+use middle::trans::type_::Type;
+
 use core::libc::c_uint;
 use core::option;
 use core::vec;
 
 pub trait ABIInfo {
-    fn compute_info(&self,
-                    atys: &[TypeRef],
-                    rty: TypeRef,
-                    ret_def: bool) -> FnType;
+    fn compute_info(&self, atys: &[Type], rty: Type, ret_def: bool) -> FnType;
 }
 
 pub struct LLVMType {
@@ -40,7 +39,7 @@ impl FnType {
     pub fn decl_fn(&self, decl: &fn(fnty: Type) -> ValueRef) -> ValueRef {
         let atys = vec::map(self.arg_tys, |t| t.ty);
         let rty = self.ret_ty.ty;
-        let fnty = Type::func(atys, rty);
+        let fnty = Type::func(atys, &rty);
         let llfn = decl(fnty);
 
         for self.attrs.iter().enumerate().advance |(i, a)| {
@@ -57,10 +56,7 @@ impl FnType {
         return llfn;
     }
 
-    pub fn build_shim_args(&self,
-                           bcx: block,
-                           arg_tys: &[Type],
-                           llargbundle: ValueRef)
+    pub fn build_shim_args(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef)
                            -> ~[ValueRef] {
         let mut atys: &[LLVMType] = self.arg_tys;
         let mut attrs: &[option::Option<Attribute>] = self.attrs;
@@ -80,7 +76,7 @@ impl FnType {
         while i < n {
             let llargval = if atys[i].cast {
                 let arg_ptr = GEPi(bcx, llargbundle, [0u, i]);
-                let arg_ptr = BitCast(bcx, arg_ptr, T_ptr(atys[i].ty));
+                let arg_ptr = BitCast(bcx, arg_ptr, atys[i].ty.ptr_to());
                 Load(bcx, arg_ptr)
             } else if attrs[i].is_some() {
                 GEPi(bcx, llargbundle, [0u, i])
@@ -94,19 +90,14 @@ impl FnType {
         return llargvals;
     }
 
-    pub fn build_shim_ret(&self,
-                          bcx: block,
-                          arg_tys: &[Type],
-                          ret_def: bool,
-                          llargbundle: ValueRef,
-                          llretval: ValueRef) {
+    pub fn build_shim_ret(&self, bcx: block, arg_tys: &[Type], ret_def: bool,
+                          llargbundle: ValueRef, llretval: ValueRef) {
+        for vec::eachi(self.attrs) |i, a| {
         for self.attrs.iter().enumerate().advance |(i, a)| {
             match *a {
                 option::Some(attr) => {
                     unsafe {
-                        llvm::LLVMAddInstrAttribute(llretval,
-                                                    (i + 1u) as c_uint,
-                                                    attr as c_uint);
+                        llvm::LLVMAddInstrAttribute(llretval, (i + 1u) as c_uint, attr as c_uint);
                     }
                 }
                 _ => ()
@@ -121,7 +112,7 @@ impl FnType {
         // R* llretloc = *llretptr; /* (args->r) */
         let llretloc = Load(bcx, llretptr);
         if self.ret_ty.cast {
-            let tmp_ptr = BitCast(bcx, llretloc, T_ptr(self.ret_ty.ty));
+            let tmp_ptr = BitCast(bcx, llretloc, self.ret_ty.ty.ptr_to());
             // *args->r = r;
             Store(bcx, llretval, tmp_ptr);
         } else {
@@ -130,11 +121,8 @@ impl FnType {
         };
     }
 
-    pub fn build_wrap_args(&self,
-                           bcx: block,
-                           ret_ty: Type,
-                           llwrapfn: ValueRef,
-                           llargbundle: ValueRef) {
+    pub fn build_wrap_args(&self, bcx: block, ret_ty: Type,
+                           llwrapfn: ValueRef, llargbundle: ValueRef) {
         let mut atys: &[LLVMType] = self.arg_tys;
         let mut attrs: &[option::Option<Attribute>] = self.attrs;
         let mut j = 0u;
@@ -159,7 +147,7 @@ impl FnType {
                 store_inbounds(bcx, argval, llargbundle, [0u, i]);
             } else if atys[i].cast {
                 let argptr = GEPi(bcx, llargbundle, [0u, i]);
-                let argptr = BitCast(bcx, argptr, T_ptr(atys[i].ty));
+                let argptr = BitCast(bcx, argptr, atys[i].ty.ptr_to());
                 Store(bcx, argval, argptr);
             } else {
                 store_inbounds(bcx, argval, llargbundle, [0u, i]);
@@ -169,14 +157,9 @@ impl FnType {
         store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
     }
 
-    pub fn build_wrap_ret(&self,
-                          bcx: block,
-                          arg_tys: &[TypeRef],
-                          llargbundle: ValueRef) {
-        unsafe {
-            if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void {
-                return;
-            }
+    pub fn build_wrap_ret(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef) {
+        if self.ret_ty.ty.kind() == Void {
+            return;
         }
 
         if bcx.fcx.llretptr.is_some() {
@@ -187,9 +170,7 @@ impl FnType {
             } else {
                 Load(bcx, llretval)
             };
-            let llretptr = BitCast(bcx,
-                                   bcx.fcx.llretptr.get(),
-                                   self.ret_ty.ty.ptr_to());
+            let llretptr = BitCast(bcx, bcx.fcx.llretptr.get(), self.ret_ty.ty.ptr_to());
             Store(bcx, llretval, llretptr);
         }
     }
diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs
index f29ccad76b1..69896972ef0 100644
--- a/src/librustc/middle/trans/cabi_arm.rs
+++ b/src/librustc/middle/trans/cabi_arm.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
-use lib::llvm::struct_tys;
 use lib::llvm::{Attribute, StructRetAttribute};
 use lib::llvm::True;
 use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
 
+use middle::trans::type_::Type;
+
 use core::option::{Option, None, Some};
 use core::uint;
 
@@ -27,58 +28,58 @@ fn align(off: uint, ty: Type) -> uint {
 }
 
 fn ty_align(ty: Type) -> uint {
-    unsafe {
-        match ty.kind() {
-            Integer => {
+    match ty.kind() {
+        Integer => {
+            unsafe {
                 ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
             }
-            Pointer => 4,
-            Float => 4,
-            Double => 8,
-            Struct => {
-                if ty.is_packed() {
-                    1
-                } else {
-                    let str_tys = ty.field_types();
-                    str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
-                }
-            }
-            Array => {
-                let elt = ty.element_type();
-                ty_align(elt)
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                1
+            } else {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
             }
-            _ => fail!("ty_align: unhandled type")
         }
+        Array => {
+            let elt = ty.element_type();
+            ty_align(elt)
+        }
+        _ => fail!("ty_align: unhandled type")
     }
 }
 
 fn ty_size(ty: Type) -> uint {
-    unsafe {
-        match ty.kind() {
-            Integer => {
+    match ty.kind() {
+        Integer => {
+            unsafe {
                 ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
             }
-            Pointer => 4,
-            Float => 4,
-            Double => 8,
-            Struct => {
-                if ty.is_packed() {
-                    let str_tys = ty.field_types();
-                    str_tys.iter().fold(0, |s, t| s + ty_size(*t))
-                } else {
-                    let str_tys = ty.field_types();
-                    let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
-                    align(size, ty)
-                }
-            }
-            Array => {
-                let len = ty.array_length();
-                let elt = ty.element_type();
-                let eltsz = ty_size(elt);
-                len * eltsz
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+            } else {
+                let str_tys = ty.field_types();
+                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                align(size, ty)
             }
-            _ => fail!("ty_size: unhandled type")
         }
+        Array => {
+            let len = ty.array_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => fail!("ty_size: unhandled type")
     }
 }
 
@@ -107,9 +108,9 @@ fn classify_arg_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
     let align = ty_align(ty);
     let size = ty_size(ty);
     let llty = if align <= 4 {
-        Type::array(Type::i32(), (size + 3) / 4)
+        Type::array(&Type::i32(), (size + 3) / 4 as u64)
     } else {
-        Type::array(Type::i64(), (size + 7) / 8)
+        Type::array(&Type::i64(), (size + 7) / 8 as u64)
     };
     (LLVMType { cast: true, ty: llty }, None)
 }
@@ -122,7 +123,7 @@ fn is_reg_ty(ty: Type) -> bool {
             | Float
             | Double => true,
             _ => false
-        };
+        }
     }
 }
 
diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs
index 73d26b91672..27ac267895b 100644
--- a/src/librustc/middle/trans/cabi_mips.rs
+++ b/src/librustc/middle/trans/cabi_mips.rs
@@ -15,13 +15,14 @@ use core::ptr;
 use core::uint;
 use core::vec;
 use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
-use lib::llvm::struct_tys;
 use lib::llvm::{Attribute, StructRetAttribute};
 use lib::llvm::True;
 use middle::trans::context::task_llcx;
 use middle::trans::common::*;
 use middle::trans::cabi::*;
 
+use middle::trans::type_::Type;
+
 fn align_up_to(off: uint, a: uint) -> uint {
     return (off + a - 1u) / a * a;
 }
@@ -32,58 +33,58 @@ fn align(off: uint, ty: Type) -> uint {
 }
 
 fn ty_align(ty: Type) -> uint {
-    unsafe {
-        return match llvm::LLVMGetTypeKind(ty) {
-            Integer => {
-                ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
-            }
-            Pointer => 4,
-            Float => 4,
-            Double => 8,
-            Struct => {
-              if ty.is_packed() {
-                1
-              } else {
-                let str_tys = struct_tys(ty);
-                str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
-              }
-            }
-            Array => {
-                let elt = llvm::LLVMGetElementType(ty);
-                ty_align(elt)
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
             }
-            _ => fail!("ty_size: unhandled type")
-        };
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+          if ty.is_packed() {
+            1
+          } else {
+            let str_tys = ty.field_types();
+            str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
+          }
+        }
+        Array => {
+            let elt = ty.element_type();
+            ty_align(elt)
+        }
+        _ => fail!("ty_size: unhandled type")
     }
 }
 
-fn ty_size(ty: TypeRef) -> uint {
-    unsafe {
-        return match llvm::LLVMGetTypeKind(ty) {
-            Integer => {
-                ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
+fn ty_size(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
             }
-            Pointer => 4,
-            Float => 4,
-            Double => 8,
-            Struct => {
-                if llvm::LLVMIsPackedStruct(ty) == True {
-                    let str_tys = struct_tys(ty);
-                    str_tys.iter().fold(0, |s, t| s + ty_size(*t))
-                } else {
-                    let str_tys = ty.field_types();
-                    let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
-                    align(size, ty)
-                }
-            }
-            Array => {
-                let len = ty.array_length();
-                let elt = ty.element_type();
-                let eltsz = ty_size(elt);
-                len * eltsz
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+            } else {
+                let str_tys = ty.field_types();
+                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                align(size, ty)
             }
-            _ => fail!("ty_size: unhandled type")
-        };
+        }
+        Array => {
+            let len = ty.array_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => fail!("ty_size: unhandled type")
     }
 }
 
@@ -120,7 +121,7 @@ fn classify_arg_ty(ty: Type, offset: &mut uint) -> (LLVMType, Option<Attribute>)
     };
 }
 
-fn is_reg_ty(ty: TypeRef) -> bool {
+fn is_reg_ty(ty: Type) -> bool {
     unsafe {
         return match ty.kind() {
             Integer
@@ -153,11 +154,11 @@ fn coerce_to_int(size: uint) -> ~[Type] {
     let r = size % 32;
     if r > 0 {
         unsafe {
-            Type::from_ref(args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)))
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)));
         }
     }
 
-    return args;
+    args
 }
 
 fn struct_ty(ty: Type,
diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs
index 0f02f7d2f86..bdfe0e3d77d 100644
--- a/src/librustc/middle/trans/cabi_x86.rs
+++ b/src/librustc/middle/trans/cabi_x86.rs
@@ -17,6 +17,8 @@ use super::cabi::*;
 use super::common::*;
 use super::machine::*;
 
+use middle::trans::type_::Type;
+
 struct X86_ABIInfo {
     ccx: @mut CrateContext
 }
diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs
index e0f9ad85e10..01ec4a90cb0 100644
--- a/src/librustc/middle/trans/cabi_x86_64.rs
+++ b/src/librustc/middle/trans/cabi_x86_64.rs
@@ -11,14 +11,15 @@
 // The classification code for the x86_64 ABI is taken from the clay language
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
-use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
+use lib::llvm::{llvm, Integer, Pointer, Float, Double};
 use lib::llvm::{Struct, Array, Attribute};
 use lib::llvm::{StructRetAttribute, ByValAttribute};
-use lib::llvm::struct_tys;
 use lib::llvm::True;
 use middle::trans::common::*;
 use middle::trans::cabi::*;
 
+use middle::trans::type_::Type;
+
 use core::libc::c_uint;
 use core::option;
 use core::option::Option;
@@ -28,7 +29,7 @@ use core::vec;
 #[deriving(Eq)]
 enum RegClass {
     NoClass,
-    Integer,
+    Int,
     SSEFs,
     SSEFv,
     SSEDs,
@@ -43,7 +44,7 @@ enum RegClass {
 
 impl Type {
     fn is_reg_ty(&self) -> bool {
-        match ty.kind() {
+        match self.kind() {
             Integer | Pointer | Float | Double => true,
             _ => false
         }
@@ -59,6 +60,11 @@ impl RegClass {
     }
 }
 
+trait ClassList {
+    fn is_pass_byval(&self) -> bool;
+    fn is_ret_bysret(&self) -> bool;
+}
+
 impl<'self> ClassList for &'self [RegClass] {
     fn is_pass_byval(&self) -> bool {
         if self.len() == 0 { return false; }
@@ -83,64 +89,64 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
     }
 
     fn ty_align(ty: Type) -> uint {
-        unsafe {
-            match ty.kind() {
-                Integer => {
+        match ty.kind() {
+            Integer => {
+                unsafe {
                     ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                 }
-                Pointer => 8,
-                Float => 4,
-                Double => 8,
-                Struct => {
-                  if ty.is_packed() {
-                    1
-                  } else {
-                    let str_tys = ty.field_types();
-                    str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
-                  }
-                }
-                Array => {
-                    let elt = ty.element_type();
-                    ty_align(elt)
-                }
-                _ => fail!("ty_size: unhandled type")
-            };
+            }
+            Pointer => 8,
+            Float => 4,
+            Double => 8,
+            Struct => {
+              if ty.is_packed() {
+                1
+              } else {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
+              }
+            }
+            Array => {
+                let elt = ty.element_type();
+                ty_align(elt)
+            }
+            _ => fail!("ty_size: unhandled type")
         }
     }
 
-    fn ty_size(ty: TypeRef) -> uint {
-        unsafe {
-            match ty.kind() {
-                Integer => {
-                    ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
-                }
-                Pointer => 8,
-                Float => 4,
-                Double => 8,
-                Struct => {
-                    if ty.is_packed() {
-                        let str_tys = ty.field_types();
-                        str_tys.iter().fold(0, |s, t| s + ty_size(*t))
-                    } else {
-                        let str_tys = ty.field_types();
-                        let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
-                        align(size, ty)
-                    }
+    fn ty_size(ty: Type) -> uint {
+        match ty.kind() {
+            Integer => {
+                unsafe {
+                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
                 }
-                Array => {
-                    let len = ty.array_length();
-                    let elt = ty.element_type();
-                    let eltsz = ty_size(elt);
-                    len * eltsz
+            }
+            Pointer => 8,
+            Float => 4,
+            Double => 8,
+            Struct => {
+                if ty.is_packed() {
+                    let str_tys = ty.field_types();
+                    str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+                } else {
+                    let str_tys = ty.field_types();
+                    let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                    align(size, ty)
                 }
-                _ => fail!("ty_size: unhandled type")
             }
+            Array => {
+                let len = ty.array_length();
+                let elt = ty.element_type();
+                let eltsz = ty_size(elt);
+                len * eltsz
+            }
+            _ => fail!("ty_size: unhandled type")
         }
     }
 
     fn all_mem(cls: &mut [RegClass]) {
         for uint::range(0, cls.len()) |i| {
-            cls[i] = memory_class;
+            cls[i] = Memory;
         }
     }
 
@@ -149,21 +155,21 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
              newv: RegClass) {
         if cls[i] == newv {
             return;
-        } else if cls[i] == no_class {
+        } else if cls[i] == NoClass {
             cls[i] = newv;
-        } else if newv == no_class {
+        } else if newv == NoClass {
             return;
-        } else if cls[i] == memory_class || newv == memory_class {
-            cls[i] = memory_class;
-        } else if cls[i] == integer_class || newv == integer_class {
-            cls[i] = integer_class;
-        } else if cls[i] == x87_class ||
-                  cls[i] == x87up_class ||
-                  cls[i] == complex_x87_class ||
-                  newv == x87_class ||
-                  newv == x87up_class ||
-                  newv == complex_x87_class {
-            cls[i] = memory_class;
+        } else if cls[i] == Memory || newv == Memory {
+            cls[i] = Memory;
+        } else if cls[i] == Int || newv == Int {
+            cls[i] = Int;
+        } else if cls[i] == X87 ||
+                  cls[i] == X87Up ||
+                  cls[i] == ComplexX87 ||
+                  newv == X87 ||
+                  newv == X87Up ||
+                  newv == ComplexX87 {
+            cls[i] = Memory;
         } else {
             cls[i] = newv;
         }
@@ -192,7 +198,7 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
                 let mut i = off / 8u;
                 let e = (off + t_size + 7u) / 8u;
                 while i < e {
-                    unify(cls, ix + i, memory_class);
+                    unify(cls, ix + i, Memory);
                     i += 1u;
                 }
                 return;
@@ -201,17 +207,17 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
             match ty.kind() {
                 Integer |
                 Pointer => {
-                    unify(cls, ix + off / 8u, integer_class);
+                    unify(cls, ix + off / 8u, Int);
                 }
                 Float => {
                     if off % 8u == 4u {
-                        unify(cls, ix + off / 8u, sse_fv_class);
+                        unify(cls, ix + off / 8u, SSEFv);
                     } else {
-                        unify(cls, ix + off / 8u, sse_fs_class);
+                        unify(cls, ix + off / 8u, SSEFs);
                     }
                 }
                 Double => {
-                    unify(cls, ix + off / 8u, sse_ds_class);
+                    unify(cls, ix + off / 8u, SSEDs);
                 }
                 Struct => {
                     classify_struct(ty.field_types(), cls, ix, off);
@@ -242,7 +248,7 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
                 if cls[i].is_sse() {
                     i += 1u;
                     while i < e {
-                        if cls[i] != sseup_class {
+                        if cls[i] != SSEUp {
                             all_mem(cls);
                             return;
                         }
@@ -254,24 +260,24 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
                 }
             } else {
                 while i < e {
-                    if cls[i] == memory_class {
+                    if cls[i] == Memory {
                         all_mem(cls);
                         return;
                     }
-                    if cls[i] == x87up_class {
+                    if cls[i] == X87Up {
                         // for darwin
-                        // cls[i] = sse_ds_class;
+                        // cls[i] = SSEDs;
                         all_mem(cls);
                         return;
                     }
-                    if cls[i] == sseup_class {
-                        cls[i] = sse_int_class;
+                    if cls[i] == SSEUp {
+                        cls[i] = SSEInt;
                     } else if cls[i].is_sse() {
                         i += 1;
-                        while i != e && cls[i] == sseup_class { i += 1u; }
-                    } else if cls[i] == x87_class {
+                        while i != e && cls[i] == SSEUp { i += 1u; }
+                    } else if cls[i] == X87 {
                         i += 1;
-                        while i != e && cls[i] == x87up_class { i += 1u; }
+                        while i != e && cls[i] == X87Up { i += 1u; }
                     } else {
                         i += 1;
                     }
@@ -281,7 +287,7 @@ fn classify_ty(ty: Type) -> ~[RegClass] {
     }
 
     let words = (ty_size(ty) + 7) / 8;
-    let mut cls = vec::from_elem(words, no_class);
+    let mut cls = vec::from_elem(words, NoClass);
     if words > 4 {
         all_mem(cls);
         let cls = cls;
@@ -296,7 +302,7 @@ fn llreg_ty(cls: &[RegClass]) -> Type {
     fn llvec_len(cls: &[RegClass]) -> uint {
         let mut len = 1u;
         for cls.each |c| {
-            if *c != sseup_class {
+            if *c != SSEUp {
                 break;
             }
             len += 1u;
@@ -310,20 +316,20 @@ fn llreg_ty(cls: &[RegClass]) -> Type {
         let e = cls.len();
         while i < e {
             match cls[i] {
-                integer_class => {
+                Int => {
                     tys.push(Type::i64());
                 }
-                sse_fv_class => {
+                SSEFv => {
                     let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
-                    let vec_ty = Type::vector(Type::f32(), vec_len);
+                    let vec_ty = Type::vector(&Type::f32(), vec_len as u64);
                     tys.push(vec_ty);
                     i += vec_len;
                     loop;
                 }
-                sse_fs_class => {
+                SSEFs => {
                     tys.push(Type::f32());
                 }
-                sse_ds_class => {
+                SSEDs => {
                     tys.push(Type::f64());
                 }
                 _ => fail!("llregtype: unhandled class")
@@ -341,6 +347,7 @@ fn x86_64_tys(atys: &[Type],
     fn x86_64_ty(ty: Type,
                  is_mem_cls: &fn(cls: &[RegClass]) -> bool,
                  attr: Attribute) -> (LLVMType, Option<Attribute>) {
+
         let (cast, attr, ty) = if !ty.is_reg_ty() {
             let cls = classify_ty(ty);
             if is_mem_cls(cls) {
@@ -348,8 +355,11 @@ fn x86_64_tys(atys: &[Type],
             } else {
                 (true, option::None, llreg_ty(cls))
             }
+        } else {
+            (false, option::None, ty)
         };
-        return (LLVMType { cast: cast, ty: ty }, attr);
+
+        (LLVMType { cast: cast, ty: ty }, attr)
     }
 
     let mut arg_tys = ~[];
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 6d2446f0137..c74a2320b5b 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -45,6 +45,8 @@ use middle::typeck;
 use middle::typeck::coherence::make_substs_for_receiver_types;
 use util::ppaux::Repr;
 
+use middle::trans::type_::Type;
+
 use core::vec;
 use syntax::ast;
 use syntax::ast_map;
@@ -526,7 +528,7 @@ pub fn trans_call_inner(in_cx: block,
         let (llfn, llenv) = unsafe {
             match callee.data {
                 Fn(d) => {
-                    (d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to()))
+                    (d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
                 }
                 Method(d) => {
                     // Weird but true: we pass self in the *environment* slot!
@@ -653,7 +655,7 @@ pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
         expr::Ignore => {
             if ty::type_is_nil(retty) {
                 unsafe {
-                    llvm::LLVMGetUndef(Type::nil().ptr_to())
+                    llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
                 }
             } else {
                 alloc_ty(bcx, retty)
@@ -777,7 +779,7 @@ pub fn trans_arg_expr(bcx: block,
         // to have type lldestty (the callee's expected type).
         let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty);
         unsafe {
-            val = llvm::LLVMGetUndef(llformal_arg_ty);
+            val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref());
         }
     } else {
         // FIXME(#3548) use the adjustments table
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 35e8e866039..7d7c024640a 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -26,6 +26,8 @@ use middle::trans::type_of::*;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
+use middle::trans::type_::Type;
+
 use core::str;
 use core::vec;
 use syntax::ast;
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 01b0411a07b..3f9f39ac852 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -31,6 +31,8 @@ use middle::typeck;
 use middle::borrowck::root_map_key;
 use util::ppaux::{Repr};
 
+use middle::trans::type_::Type;
+
 use core::cast::transmute;
 use core::cast;
 use core::hashmap::{HashMap};
@@ -58,29 +60,11 @@ pub fn new_namegen() -> namegen {
     f
 }
 
-pub type addrspace = c_uint;
-
-// Address spaces communicate to LLVM which destructors need to run for
-// specific types.
-//    0 is ignored by the GC, and is used for all non-GC'd pointers.
-//    1 is for opaque GC'd boxes.
-//    >= 2 are for specific types (e.g. resources).
-pub static default_addrspace: addrspace = 0;
-pub static gc_box_addrspace: addrspace = 1;
-
-pub type addrspace_gen = @fn() -> addrspace;
-pub fn new_addrspace_gen() -> addrspace_gen {
-    let i = @mut 1;
-    let result: addrspace_gen = || { *i += 1; *i };
-    result
-}
-
 pub struct tydesc_info {
     ty: ty::t,
     tydesc: ValueRef,
     size: ValueRef,
     align: ValueRef,
-    addrspace: addrspace,
     take_glue: Option<ValueRef>,
     drop_glue: Option<ValueRef>,
     free_glue: Option<ValueRef>,
@@ -345,39 +329,14 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
     }
 }
 
-// This is not the same as datum::Datum::root(), which is used to keep copies
-// of @ values live for as long as a borrowed pointer to the interior exists.
-// In the new GC, we can identify immediates on the stack without difficulty,
-// but have trouble knowing where non-immediates are on the stack. For
-// non-immediates, we must add an additional level of indirection, which
-// allows us to alloca a pointer with the right addrspace.
-pub fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t)
-    -> (ValueRef, bool) {
-    let ccx = bcx.ccx();
-
-    let addrspace = base::get_tydesc(ccx, t).addrspace;
-    if addrspace > gc_box_addrspace {
-        let llty = type_of::type_of_rooted(ccx, t);
-        let root = base::alloca(bcx, llty);
-        build::Store(bcx, build::PointerCast(bcx, v, llty), root);
-        (root, true)
-    } else {
-        (v, false)
-    }
-}
-
 pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
     if !ty::type_needs_drop(bcx.tcx(), t) { return; }
-    debug!("add_clean(%s, %s, %s)",
-           bcx.to_str(),
-           bcx.val_to_str(val),
-           t.repr(bcx.tcx()));
-    let (root, rooted) = root_for_cleanup(bcx, val, t);
+
+    debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
+
     let cleanup_type = cleanup_type(bcx.tcx(), t);
     do in_scope_cx(bcx) |scope_info| {
-        scope_info.cleanups.push(
-            clean(|a| glue::drop_ty_root(a, root, rooted, t),
-                  cleanup_type));
+        scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
@@ -400,12 +359,9 @@ pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
     debug!("add_clean_temp_mem(%s, %s, %s)",
            bcx.to_str(), bcx.val_to_str(val),
            t.repr(bcx.tcx()));
-    let (root, rooted) = root_for_cleanup(bcx, val, t);
     let cleanup_type = cleanup_type(bcx.tcx(), t);
     do in_scope_cx(bcx) |scope_info| {
-        scope_info.cleanups.push(
-            clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t),
-                       cleanup_type));
+        scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
@@ -431,12 +387,8 @@ pub fn add_clean_return_to_mut(bcx: block,
         scope_info.cleanups.push(
             clean_temp(
                 frozen_val_ref,
-                |bcx| write_guard::return_to_mut(bcx,
-                                                 root_key,
-                                                 frozen_val_ref,
-                                                 bits_val_ref,
-                                                 filename_val,
-                                                 line_val),
+                |bcx| write_guard::return_to_mut(bcx, root_key, frozen_val_ref, bits_val_ref,
+                                                 filename_val, line_val),
                 normal_exit_only));
         grow_scope_clean(scope_info);
     }
@@ -621,9 +573,9 @@ impl Result {
     }
 }
 
-pub fn val_ty(v: ValueRef) -> TypeRef {
+pub fn val_ty(v: ValueRef) -> Type {
     unsafe {
-        return llvm::LLVMTypeOf(v);
+        Type::from_ref(llvm::LLVMTypeOf(v))
     }
 }
 
@@ -706,313 +658,6 @@ impl block_ {
     }
 }
 
-/*
-// LLVM type constructors.
-pub fn T_void() -> TypeRef {
-    unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); }
-}
-
-pub fn T_nil() -> TypeRef {
-    return T_struct([], false)
-}
-
-pub fn T_metadata() -> TypeRef {
-    unsafe { return llvm::LLVMMetadataTypeInContext(base::task_llcx()); }
-}
-
-pub fn T_i1() -> TypeRef {
-    unsafe { return llvm::LLVMInt1TypeInContext(base::task_llcx()); }
-}
-
-pub fn T_i8() -> TypeRef {
-    unsafe { return llvm::LLVMInt8TypeInContext(base::task_llcx()); }
-}
-
-pub fn T_i16() -> TypeRef {
-    unsafe { return llvm::LLVMInt16TypeInContext(base::task_llcx()); }
-}
-
-pub fn T_i32() -> TypeRef {
-    unsafe { return llvm::LLVMInt32TypeInContext(base::task_llcx()); }
-}
-
-pub fn T_i64() -> TypeRef {
-    unsafe { return llvm::LLVMInt64TypeInContext(base::task_llcx()); }
-}
-
-pub fn T_f32() -> TypeRef {
-    unsafe { return llvm::LLVMFloatTypeInContext(base::task_llcx()); }
-}
-
-pub fn T_f64() -> TypeRef {
-    unsafe { return llvm::LLVMDoubleTypeInContext(base::task_llcx()); }
-}
-
-pub fn T_bool() -> TypeRef { return T_i8(); }
-
-pub fn T_int(targ_cfg: &session::config) -> TypeRef {
-    return match targ_cfg.arch {
-        X86 => T_i32(),
-        X86_64 => T_i64(),
-        Arm => T_i32(),
-        Mips => T_i32()
-    };
-}
-
-pub fn T_int_ty(cx: &CrateContext, t: ast::int_ty) -> TypeRef {
-    match t {
-      ast::ty_i => cx.int_type,
-      ast::ty_char => T_char(),
-      ast::ty_i8 => T_i8(),
-      ast::ty_i16 => T_i16(),
-      ast::ty_i32 => T_i32(),
-      ast::ty_i64 => T_i64()
-    }
-}
-
-pub fn T_uint_ty(cx: &CrateContext, t: ast::uint_ty) -> TypeRef {
-    match t {
-      ast::ty_u => cx.int_type,
-      ast::ty_u8 => T_i8(),
-      ast::ty_u16 => T_i16(),
-      ast::ty_u32 => T_i32(),
-      ast::ty_u64 => T_i64()
-    }
-}
-
-pub fn T_float_ty(cx: &CrateContext, t: ast::float_ty) -> TypeRef {
-    match t {
-      ast::ty_f => cx.float_type,
-      ast::ty_f32 => T_f32(),
-      ast::ty_f64 => T_f64()
-    }
-}
-
-pub fn T_float(targ_cfg: &session::config) -> TypeRef {
-    return match targ_cfg.arch {
-        X86 => T_f64(),
-        X86_64 => T_f64(),
-        Arm => T_f64(),
-        Mips => T_f64()
-    };
-}
-
-pub fn T_char() -> TypeRef { return T_i32(); }
-
-pub fn T_size_t(targ_cfg: &session::config) -> TypeRef {
-    return T_int(targ_cfg);
-}
-
-pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
-    unsafe {
-        return llvm::LLVMFunctionType(output, to_ptr(inputs),
-                                      inputs.len() as c_uint,
-                                      False);
-    }
-}
-
-pub fn T_fn_pair(cx: &CrateContext, tfn: TypeRef) -> TypeRef {
-    return T_struct([T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
-}
-
-pub fn T_ptr(t: TypeRef) -> TypeRef {
-    unsafe {
-        return llvm::LLVMPointerType(t, default_addrspace);
-    }
-}
-
-pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
-    unsafe {
-        return llvm::LLVMPointerType(t, addrspace);
-    }
-}
-
-pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
-    unsafe {
-        return llvm::LLVMStructTypeInContext(base::task_llcx(),
-                                             to_ptr(elts),
-                                             elts.len() as c_uint,
-                                             packed as Bool);
-    }
-}
-
-pub fn T_named_struct(name: &str) -> TypeRef {
-    unsafe {
-        return str::as_c_str(name, |buf| {
-            llvm::LLVMStructCreateNamed(base::task_llcx(), buf)
-        });
-    }
-}
-
-pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
-    unsafe {
-        llvm::LLVMStructSetBody(t,
-                                to_ptr(elts),
-                                elts.len() as c_uint,
-                                packed as Bool);
-    }
-}
-
-pub fn T_empty_struct() -> TypeRef { return T_struct([], false); }
-
-// A vtable is, in reality, a vtable pointer followed by zero or more pointers
-// to tydescs and other vtables that it closes over. But the types and number
-// of those are rarely known to the code that needs to manipulate them, so
-// they are described by this opaque type.
-pub fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
-
-pub fn T_tydesc_field(cx: &CrateContext, field: uint) -> TypeRef {
-    // Bit of a kludge: pick the fn typeref out of the tydesc..
-
-    unsafe {
-        let mut tydesc_elts: ~[TypeRef] =
-            vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
-                                     T_nil());
-        llvm::LLVMGetStructElementTypes(cx.tydesc_type, &mut tydesc_elts[0]);
-        let t = llvm::LLVMGetElementType(tydesc_elts[field]);
-        return t;
-    }
-}
-
-pub fn T_generic_glue_fn(cx: &mut CrateContext) -> TypeRef {
-    let s = @"glue_fn";
-    match cx.tn.find_type(s) {
-      Some(t) => return t,
-      _ => ()
-    }
-    let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
-    cx.tn.associate_type(s, t);
-    return t;
-}
-
-pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
-    let tydesc = T_named_struct("tydesc");
-    let tydescpp = T_ptr(T_ptr(tydesc));
-    let pvoid = T_ptr(T_i8());
-    let glue_fn_ty =
-        T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void()));
-
-    let int_type = T_int(targ_cfg);
-    let elems =
-        ~[int_type, int_type,
-          glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
-          T_ptr(T_i8()), T_ptr(T_i8())];
-    set_struct_body(tydesc, elems, false);
-    return tydesc;
-}
-
-pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
-    unsafe {
-        return llvm::LLVMArrayType(t, n as c_uint);
-    }
-}
-
-pub fn T_vector(t: TypeRef, n: uint) -> TypeRef {
-    unsafe {
-        return llvm::LLVMVectorType(t, n as c_uint);
-    }
-}
-
-// Interior vector.
-pub fn T_vec2(targ_cfg: &session::config, t: TypeRef) -> TypeRef {
-    return T_struct([T_int(targ_cfg), // fill
-                     T_int(targ_cfg), // alloc
-                     T_array(t, 0u)], // elements
-                    false);
-}
-
-pub fn T_vec(ccx: &CrateContext, t: TypeRef) -> TypeRef {
-    return T_vec2(ccx.sess.targ_cfg, t);
-}
-
-// Note that the size of this one is in bytes.
-pub fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
-    return T_vec2(targ_cfg, T_i8());
-}
-
-pub fn T_box_header_fields(cx: &CrateContext) -> ~[TypeRef] {
-    let ptr = T_ptr(T_i8());
-    return ~[cx.int_type, T_ptr(cx.tydesc_type), ptr, ptr];
-}
-
-pub fn T_box_header(cx: &CrateContext) -> TypeRef {
-    return T_struct(T_box_header_fields(cx), false);
-}
-
-pub fn T_box(cx: &CrateContext, t: TypeRef) -> TypeRef {
-    return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
-}
-
-pub fn T_box_ptr(t: TypeRef) -> TypeRef {
-    unsafe {
-        return llvm::LLVMPointerType(t, gc_box_addrspace);
-    }
-}
-
-pub fn T_opaque_box(cx: &CrateContext) -> TypeRef {
-    return T_box(cx, T_i8());
-}
-
-pub fn T_opaque_box_ptr(cx: &CrateContext) -> TypeRef {
-    return T_box_ptr(T_opaque_box(cx));
-}
-
-pub fn T_unique(cx: &CrateContext, t: TypeRef) -> TypeRef {
-    return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
-}
-
-pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
-    unsafe {
-        return llvm::LLVMPointerType(t, gc_box_addrspace);
-    }
-}
-
-pub fn T_port(cx: &CrateContext, _t: TypeRef) -> TypeRef {
-    return T_struct([cx.int_type], false); // Refcount
-
-}
-
-pub fn T_chan(cx: &CrateContext, _t: TypeRef) -> TypeRef {
-    return T_struct([cx.int_type], false); // Refcount
-
-}
-
-
-pub fn T_opaque_cbox_ptr(cx: &CrateContext) -> TypeRef {
-    // closures look like boxes (even when they are ~fn or &fn)
-    // see trans_closure.rs
-    return T_opaque_box_ptr(cx);
-}
-
-pub fn T_enum_discrim(cx: &CrateContext) -> TypeRef {
-    return cx.int_type;
-}
-
-pub fn T_captured_tydescs(cx: &CrateContext, n: uint) -> TypeRef {
-    return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
-}
-
-pub fn T_opaque_trait(cx: &CrateContext, store: ty::TraitStore) -> TypeRef {
-    match store {
-        ty::BoxTraitStore => {
-            T_struct([T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
-        }
-        ty::UniqTraitStore => {
-            T_struct([T_ptr(cx.tydesc_type),
-                      T_unique_ptr(T_unique(cx, T_i8()))],
-                     false)
-        }
-        ty::RegionTraitStore(_) => {
-            T_struct([T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
-        }
-    }
-}
-
-pub fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
-
-pub fn T_opaque_chan_ptr() -> TypeRef { return T_ptr(T_i8()); }
-*/
-
 // Let T be the content of a box @T.  tuplify_box_ty(t) returns the
 // representation of @T as a tuple (i.e., the ty::t version of what T_box()
 // returns).
@@ -1101,7 +746,7 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
         };
 
         let gsym = token::gensym("str");
-        let g = fmt!("str%u", gsym).as_c_str |buf| {
+        let g = do fmt!("str%u", gsym).as_c_str |buf| {
             llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(g, sc);
@@ -1138,7 +783,8 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef {
         let mut i = 0u;
         let mut elts: ~[ValueRef] = ~[];
         while i < size { elts.push(C_u8(0u)); i += 1u; }
-        return llvm::LLVMConstArray(Type::i8(), vec::raw::to_ptr(elts), elts.len() as c_uint);
+        return llvm::LLVMConstArray(Type::i8().to_ref(),
+                                    vec::raw::to_ptr(elts), elts.len() as c_uint);
     }
 }
 
@@ -1158,17 +804,17 @@ pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
     }
 }
 
-pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
+pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
     unsafe {
         do vec::as_imm_buf(elts) |ptr, len| {
-            llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
+            llvm::LLVMConstNamedStruct(T.to_ref(), ptr, len as c_uint)
         }
     }
 }
 
-pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
+pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
     unsafe {
-        return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), elts.len() as c_uint);
+        return llvm::LLVMConstArray(ty.to_ref(), vec::raw::to_ptr(elts), elts.len() as c_uint);
     }
 }
 
@@ -1193,7 +839,7 @@ pub fn C_shape(ccx: &CrateContext, bytes: ~[u8]) -> ValueRef {
         let llglobal = do name.as_c_str |buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape).to_ref(), buf)
         };
-        llvm::LLVMSetInitializer(llglobal, llshape.to_ref());
+        llvm::LLVMSetInitializer(llglobal, llshape);
         llvm::LLVMSetGlobalConstant(llglobal, True);
         lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
         return llvm::LLVMConstPointerCast(llglobal, Type::i8p().to_ref());
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index dcdb53ec532..456dc6edfb6 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -11,7 +11,7 @@
 use core::prelude::*;
 
 use back::abi;
-use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool,
+use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool,
     True, False};
 use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
     RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
@@ -30,6 +30,8 @@ use middle::trans::type_of;
 use middle::ty;
 use util::ppaux::{Repr, ty_to_str};
 
+use middle::trans::type_::Type;
+
 use core::libc::c_uint;
 use core::str;
 use syntax::{ast, ast_util, ast_map};
@@ -38,28 +40,28 @@ pub fn const_lit(cx: @mut CrateContext, e: @ast::expr, lit: ast::lit)
     -> ValueRef {
     let _icx = cx.insn_ctxt("trans_lit");
     match lit.node {
-      ast::lit_int(i, t) => C_integral(T_int_ty(cx, t), i as u64, True),
-      ast::lit_uint(u, t) => C_integral(T_uint_ty(cx, t), u, False),
+      ast::lit_int(i, t) => C_integral(Type::int_from_ty(cx, t), i as u64, true),
+      ast::lit_uint(u, t) => C_integral(Type::uint_from_ty(cx, t), u, false),
       ast::lit_int_unsuffixed(i) => {
         let lit_int_ty = ty::node_id_to_type(cx.tcx, e.id);
         match ty::get(lit_int_ty).sty {
           ty::ty_int(t) => {
-            C_integral(T_int_ty(cx, t), i as u64, True)
+            C_integral(Type::int_from_ty(cx, t), i as u64, true)
           }
           ty::ty_uint(t) => {
-            C_integral(T_uint_ty(cx, t), i as u64, False)
+            C_integral(Type::uint_from_ty(cx, t), i as u64, false)
           }
           _ => cx.sess.span_bug(lit.span,
                    fmt!("integer literal has type %s (expected int or uint)",
                         ty_to_str(cx.tcx, lit_int_ty)))
         }
       }
-      ast::lit_float(fs, t) => C_floating(fs, T_float_ty(cx, t)),
+      ast::lit_float(fs, t) => C_floating(fs, Type::float_from_ty(cx, t)),
       ast::lit_float_unsuffixed(fs) => {
         let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id);
         match ty::get(lit_float_ty).sty {
           ty::ty_float(t) => {
-            C_floating(fs, T_float_ty(cx, t))
+            C_floating(fs, Type::float_from_ty(cx, t))
           }
           _ => {
             cx.sess.span_bug(lit.span,
@@ -73,16 +75,16 @@ pub fn const_lit(cx: @mut CrateContext, e: @ast::expr, lit: ast::lit)
     }
 }
 
-pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: TypeRef) -> ValueRef {
+pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef {
     unsafe {
-        let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
+        let b = llvm::LLVMConstPointerCast(a, t.ptr_to().to_ref());
         assert!(cx.const_globals.insert(b as int, a));
         b
     }
 }
 
 pub fn const_vec(cx: @mut CrateContext, e: @ast::expr, es: &[@ast::expr])
-    -> (ValueRef, ValueRef, TypeRef) {
+    -> (ValueRef, ValueRef, Type) {
     unsafe {
         let vec_ty = ty::expr_ty(cx.tcx, e);
         let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
@@ -102,8 +104,8 @@ pub fn const_vec(cx: @mut CrateContext, e: @ast::expr, es: &[@ast::expr])
 
 fn const_addr_of(cx: @mut CrateContext, cv: ValueRef) -> ValueRef {
     unsafe {
-        let gv = do str::as_c_str("const") |name| {
-            llvm::LLVMAddGlobal(cx.llmod, val_ty(cv), name)
+        let gv = do "const".as_c_str |name| {
+            llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name)
         };
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetGlobalConstant(gv, True);
@@ -180,7 +182,7 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
     match adjustment {
         None => { }
         Some(@ty::AutoAddEnv(ty::re_static, ast::BorrowedSigil)) => {
-            llconst = C_struct([llconst, C_null(T_opaque_box_ptr(cx))])
+            llconst = C_struct([llconst, C_null(Type::opaque_box(cx).ptr_to())])
         }
         Some(@ty::AutoAddEnv(ref r, ref s)) => {
             cx.sess.span_bug(e.span, fmt!("unexpected static function: \
@@ -349,9 +351,9 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
                     ty::ty_bool => {
                         // Somewhat questionable, but I believe this is
                         // correct.
-                        let te = llvm::LLVMConstTrunc(te, T_i1());
+                        let te = llvm::LLVMConstTrunc(te, Type::i1().to_ref());
                         let te = llvm::LLVMConstNot(te);
-                        llvm::LLVMConstZExt(te, T_bool())
+                        llvm::LLVMConstZExt(te, Type::bool().to_ref())
                     }
                     _ => llvm::LLVMConstNot(te),
                 }
@@ -426,21 +428,21 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
 
               (expr::cast_integral, expr::cast_integral) => {
                 let s = ty::type_is_signed(basety) as Bool;
-                llvm::LLVMConstIntCast(v, llty, s)
+                llvm::LLVMConstIntCast(v, llty.to_ref(), s)
               }
               (expr::cast_integral, expr::cast_float) => {
                 if ty::type_is_signed(basety) {
-                    llvm::LLVMConstSIToFP(v, llty)
+                    llvm::LLVMConstSIToFP(v, llty.to_ref())
                 } else {
-                    llvm::LLVMConstUIToFP(v, llty)
+                    llvm::LLVMConstUIToFP(v, llty.to_ref())
                 }
               }
               (expr::cast_float, expr::cast_float) => {
-                llvm::LLVMConstFPCast(v, llty)
+                llvm::LLVMConstFPCast(v, llty.to_ref())
               }
               (expr::cast_float, expr::cast_integral) => {
-                if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty) }
-                else { llvm::LLVMConstFPToUI(v, llty) }
+                if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
+                else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
               }
               (expr::cast_enum, expr::cast_integral) |
               (expr::cast_enum, expr::cast_float)  => {
@@ -451,18 +453,18 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
                 match ety_cast {
                     expr::cast_integral => {
                         let s = ty::type_is_signed(ety) as Bool;
-                        llvm::LLVMConstIntCast(iv, llty, s)
+                        llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
                     }
-                    expr::cast_float => llvm::LLVMConstUIToFP(iv, llty),
+                    expr::cast_float => llvm::LLVMConstUIToFP(iv, llty.to_ref()),
                     _ => cx.sess.bug("enum cast destination is not \
                                       integral or float")
                 }
               }
               (expr::cast_pointer, expr::cast_pointer) => {
-                llvm::LLVMConstPointerCast(v, llty)
+                llvm::LLVMConstPointerCast(v, llty.to_ref())
               }
               (expr::cast_integral, expr::cast_pointer) => {
-                llvm::LLVMConstIntToPtr(v, llty)
+                llvm::LLVMConstIntToPtr(v, llty.to_ref())
               }
               _ => {
                 cx.sess.impossible_case(e.span,
@@ -513,7 +515,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
                 let (cv, sz, llunitty) = const_vec(cx, e, *es);
                 let llty = val_ty(cv);
                 let gv = do str::as_c_str("const") |name| {
-                    llvm::LLVMAddGlobal(cx.llmod, llty, name)
+                    llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
                 };
                 llvm::LLVMSetInitializer(gv, cv);
                 llvm::LLVMSetGlobalConstant(gv, True);
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index bf9d3932298..a709600cb9d 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -12,7 +12,7 @@ use core::prelude::*;
 
 use back::{upcall};
 use driver::session;
-use lib::llvm::{ContextRef, ModuleRef, ValueRef, TypeRef};
+use lib::llvm::{ContextRef, ModuleRef, ValueRef};
 use lib::llvm::{llvm, TargetData, TypeNames};
 use lib::llvm::{mk_target_data};
 use lib;
@@ -36,8 +36,8 @@ use core::local_data;
 use extra::time;
 use syntax::ast;
 
-use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res,Stats,namegen,addrspace_gen};
-use middle::trans::common::{mono_id,new_namegen,new_addrspace_gen};
+use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res,Stats,namegen};
+use middle::trans::common::{mono_id,new_namegen};
 
 use middle::trans::base::{decl_crate_map};
 
@@ -94,11 +94,10 @@ pub struct CrateContext {
      impl_method_cache: HashMap<(ast::def_id, ast::ident), ast::def_id>,
 
      module_data: HashMap<~str, ValueRef>,
-     lltypes: HashMap<ty::t, TypeRef>,
-     llsizingtypes: HashMap<ty::t, TypeRef>,
+     lltypes: HashMap<ty::t, Type>,
+     llsizingtypes: HashMap<ty::t, Type>,
      adt_reprs: HashMap<ty::t, @adt::Repr>,
      names: namegen,
-     next_addrspace: addrspace_gen,
      symbol_hasher: hash::State,
      type_hashcodes: HashMap<ty::t, @str>,
      type_short_names: HashMap<ty::t, ~str>,
@@ -151,8 +150,8 @@ impl CrateContext {
             let tydesc_type = Type::tydesc(targ_cfg.arch);
             let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
 
-            let str_slice_ty = Type::named_struct("str_slice");
-            str_slice_ty.set_struct_body([Type::i8p(), int_type]);
+            let mut str_slice_ty = Type::named_struct("str_slice");
+            str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
 
             tn.associate_type("tydesc", &tydesc_type);
             tn.associate_type("str_slice", &str_slice_ty);
@@ -197,7 +196,6 @@ impl CrateContext {
                   llsizingtypes: HashMap::new(),
                   adt_reprs: HashMap::new(),
                   names: new_namegen(),
-                  next_addrspace: new_addrspace_gen(),
                   symbol_hasher: symbol_hasher,
                   type_hashcodes: HashMap::new(),
                   type_short_names: HashMap::new(),
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 17009afda49..a9892b34ccd 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -24,6 +24,8 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux;
 
+use middle::trans::type_::Type;
+
 use core::str;
 use core::vec;
 use syntax::ast;
@@ -204,7 +206,7 @@ pub fn trans_log(log_ex: @ast::expr,
         let global;
         unsafe {
             global = str::as_c_str(s, |buf| {
-                llvm::LLVMAddGlobal(ccx.llmod, Type::i32(), buf)
+                llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
             });
             llvm::LLVMSetGlobalConstant(global, False);
             llvm::LLVMSetInitializer(global, C_null(Type::i32()));
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 92cbf2c0957..c0a3b76aca4 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -152,6 +152,8 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::Repr;
 
+use middle::trans::type_::Type;
+
 use core::cast::transmute;
 use core::hashmap::HashMap;
 use core::vec;
@@ -981,9 +983,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
                             let symbol = csearch::get_symbol(
                                 bcx.ccx().sess.cstore,
                                 did);
-                            let llval = llvm::LLVMAddGlobal(
-                                bcx.ccx().llmod,
-                                llty,
+                            let llval = llvm::LLVMAddGlobal( bcx.ccx().llmod, llty.to_ref(),
                                 transmute::<&u8,*i8>(&symbol[0]));
                             let extern_const_values = &mut bcx.ccx().extern_const_values;
                             extern_const_values.insert(did, llval);
@@ -1552,8 +1552,8 @@ fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
             llsrc: ValueRef, signed: bool) -> ValueRef {
     let _icx = bcx.insn_ctxt("int_cast");
     unsafe {
-        let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype);
-        let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype);
+        let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype.to_ref());
+        let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype.to_ref());
         return if dstsz == srcsz {
             BitCast(bcx, llsrc, lldsttype)
         } else if srcsz > dstsz {
@@ -1569,8 +1569,8 @@ fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
 fn float_cast(bcx: block, lldsttype: Type, llsrctype: Type,
               llsrc: ValueRef) -> ValueRef {
     let _icx = bcx.insn_ctxt("float_cast");
-    let srcsz = lib::llvm::float_width(llsrctype);
-    let dstsz = lib::llvm::float_width(lldsttype);
+    let srcsz = llsrctype.float_width();
+    let dstsz = lldsttype.float_width();
     return if dstsz > srcsz {
         FPExt(bcx, llsrc, lldsttype)
     } else if srcsz > dstsz {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 50d4709735c..5cad76e471e 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -44,6 +44,7 @@ use syntax::parse::token;
 use syntax::abi::{X86, X86_64, Arm, Mips};
 use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall,
                   Cdecl, Aapcs, C};
+use middle::trans::type_::Type;
 
 fn abi_info(ccx: @mut CrateContext) -> @cabi::ABIInfo {
     return match ccx.sess.targ_cfg.arch {
@@ -122,7 +123,7 @@ fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
         llsig: llsig,
         ret_def: ret_def,
         bundle_ty: bundle_ty,
-        shim_fn_ty: Type::func([bundle_ty.ptr_to()], Type::void()),
+        shim_fn_ty: Type::func([bundle_ty.ptr_to()], &Type::void()),
         fn_ty: fn_ty
     }
 }
@@ -220,12 +221,9 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
         let return_context = raw_block(fcx, false, fcx.llreturn);
 
         let llfunctiontype = val_ty(llwrapfn);
-        let llfunctiontype =
-            ::lib::llvm::llvm::LLVMGetElementType(llfunctiontype);
-        let llfunctionreturntype =
-            ::lib::llvm::llvm::LLVMGetReturnType(llfunctiontype);
-        if ::lib::llvm::llvm::LLVMGetTypeKind(llfunctionreturntype) ==
-                ::lib::llvm::Void {
+        let llfunctiontype = llfunctiontype.element_type();
+        let return_type = llfunctiontype.return_type();
+        if return_type.kind() == ::lib::llvm::Void {
             // XXX: This might be wrong if there are any functions for which
             // the C ABI specifies a void output pointer and the Rust ABI
             // does not.
@@ -233,9 +231,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
         } else {
             // Cast if we have to...
             // XXX: This is ugly.
-            let llretptr = BitCast(return_context,
-                                   fcx.llretptr.get(),
-                                   llfunctionreturntype.ptr_to());
+            let llretptr = BitCast(return_context, fcx.llretptr.get(), return_type.ptr_to());
             Ret(return_context, Load(return_context, llretptr));
         }
     }
@@ -636,6 +632,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             }
         }
 
+        build_return(bcx);
+        finish_fn(fcx, lltop);
+
         return;
     }
 
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 7396508fb8d..294d56dcd76 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -18,7 +18,7 @@ use back::abi;
 use back::link::*;
 use driver::session;
 use lib;
-use lib::llvm::{llvm, ValueRef, Type, True};
+use lib::llvm::{llvm, ValueRef, True};
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::callee;
@@ -29,12 +29,14 @@ use middle::trans::expr;
 use middle::trans::machine::*;
 use middle::trans::reflect;
 use middle::trans::tvec;
-use middle::trans::type_of::{type_of, type_of_glue_fn};
+use middle::trans::type_of::type_of;
 use middle::trans::uniq;
 use middle::ty;
 use util::ppaux;
 use util::ppaux::ty_to_short_str;
 
+use middle::trans::type_::Type;
+
 use core::io;
 use core::libc::c_uint;
 use core::str;
@@ -76,16 +78,6 @@ pub fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
     return cx;
 }
 
-pub fn drop_ty_root(bcx: block, v: ValueRef, rooted: bool, t: ty::t) -> block {
-    if rooted {
-        // NB: v is a raw ptr to an addrspace'd ptr to the value.
-        let v = PointerCast(bcx, Load(bcx, v), type_of(bcx.ccx(), t).ptr_to());
-        drop_ty(bcx, v, t)
-    } else {
-        drop_ty(bcx, v, t)
-    }
-}
-
 pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
     let _icx = bcx.insn_ctxt("drop_ty_immediate");
     match ty::get(t).sty {
@@ -436,8 +428,8 @@ pub fn trans_struct_drop(bcx: block,
 
         // The second argument is the "self" argument for drop
         let params = unsafe {
-            lib::llvm::fn_ty_param_tys(
-                llvm::LLVMGetElementType(llvm::LLVMTypeOf(dtor_addr)))
+            let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
+            ty.element_type().func_params()
         };
 
         // Class dtors have no explicit args, so the params should
@@ -617,20 +609,6 @@ pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
 }
 
 
-// Chooses the addrspace for newly declared types.
-pub fn declare_tydesc_addrspace(ccx: &CrateContext, t: ty::t) -> addrspace {
-    if !ty::type_needs_drop(ccx.tcx, t) {
-        return default_addrspace;
-    } else if ty::type_is_immediate(t) {
-        // For immediate types, we don't actually need an addrspace, because
-        // e.g. boxed types include pointers to their contents which are
-        // already correctly tagged with addrspaces.
-        return default_addrspace;
-    } else {
-        return (ccx.next_addrspace)();
-    }
-}
-
 // Generates the declaration for (but doesn't emit) a type descriptor.
 pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
     // If emit_tydescs already ran, then we shouldn't be creating any new
@@ -640,20 +618,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
     let llty = type_of(ccx, t);
 
     if ccx.sess.count_type_sizes() {
-        io::println(fmt!("%u\t%s",
-                         llsize_of_real(ccx, llty),
+        io::println(fmt!("%u\t%s", llsize_of_real(ccx, llty),
                          ppaux::ty_to_str(ccx.tcx, t)));
     }
 
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
-    let addrspace = declare_tydesc_addrspace(ccx, t);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
     note_unique_llvm_symbol(ccx, name);
     debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
     let gvar = str::as_c_str(name, |buf| {
         unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
+            llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
         }
     });
     let inf = @mut tydesc_info {
@@ -661,7 +637,6 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
         tydesc: gvar,
         size: llsize,
         align: llalign,
-        addrspace: addrspace,
         take_glue: None,
         drop_glue: None,
         free_glue: None,
@@ -706,7 +681,11 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
     let llty = type_of(ccx, t);
     let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
     helper(bcx, llrawptr0, t);
-    finish_fn(fcx, lltop);
+
+    // This is from the general finish fn, but that emits a ret {} that we don't want
+    Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
+    RetVoid(raw_block(fcx, false, fcx.llreturn));
+
     return llfn;
 }
 
@@ -732,7 +711,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
     //let _icx = ccx.insn_ctxt("emit_tydescs");
     // As of this point, allow no more tydescs to be created.
     ccx.finished_tydescs = true;
-    let glue_fn_ty = T_generic_glue_fn(ccx).ptr_to();
+    let glue_fn_ty = Type::generic_glue_fn(ccx);
     let tyds = &mut ccx.tydescs;
     for tyds.each_value |&val| {
         let ti = val;
@@ -747,7 +726,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               Some(v) => {
                 unsafe {
                     ccx.stats.n_real_glues += 1u;
-                    llvm::LLVMConstPointerCast(v, glue_fn_ty)
+                    llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
                 }
               }
             };
@@ -757,7 +736,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               Some(v) => {
                 unsafe {
                     ccx.stats.n_real_glues += 1u;
-                    llvm::LLVMConstPointerCast(v, glue_fn_ty)
+                    llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
                 }
               }
             };
@@ -767,7 +746,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               Some(v) => {
                 unsafe {
                     ccx.stats.n_real_glues += 1u;
-                    llvm::LLVMConstPointerCast(v, glue_fn_ty)
+                    llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
                 }
               }
             };
@@ -777,16 +756,16 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               Some(v) => {
                 unsafe {
                     ccx.stats.n_real_glues += 1u;
-                    llvm::LLVMConstPointerCast(v, glue_fn_ty)
+                    llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
                 }
               }
             };
 
+
         let shape = C_null(Type::i8p());
         let shape_tables = C_null(Type::i8p());
 
-        let tydesc =
-            C_named_struct(ccx.tydesc_type,
+        let tydesc = C_named_struct(ccx.tydesc_type,
                            [ti.size, // size
                             ti.align, // align
                             take_glue, // take_glue
@@ -802,18 +781,11 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
             llvm::LLVMSetGlobalConstant(gvar, True);
             lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
 
-            // Index tydesc by addrspace.
-            if ti.addrspace > gc_box_addrspace {
-                let llty = ccx.tydesc_type.ptr_to();
-                let addrspace_name = fmt!("_gc_addrspace_metadata_%u",
-                                          ti.addrspace as uint);
-                let addrspace_gvar = str::as_c_str(addrspace_name, |buf| {
-                    llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
-                });
-                lib::llvm::SetLinkage(addrspace_gvar,
-                                      lib::llvm::InternalLinkage);
-                llvm::LLVMSetInitializer(addrspace_gvar, gvar);
-            }
         }
     };
 }
+
+fn type_of_glue_fn(ccx: &CrateContext) -> Type {
+    let tydescpp = ccx.tydesc_type.ptr_to().ptr_to();
+    Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], &Type::void())
+}
diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs
index eb7240419ed..495d3bcae16 100644
--- a/src/librustc/middle/trans/machine.rs
+++ b/src/librustc/middle/trans/machine.rs
@@ -18,6 +18,8 @@ use middle::trans::type_of;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
+use middle::trans::type_::Type;
+
 // ______________________________________________________________________
 // compute sizeof / alignof
 
@@ -140,7 +142,7 @@ pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
 
                 debug!("static_size_of_enum: variant %s type %s",
                        cx.tcx.sess.str_of(variant.name),
-                       cx.tn.type_to_str(T_struct(lltypes, false)));
+                       cx.tn.type_to_str(Type::struct_(lltypes, false)));
 
                 let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
                 if max_size < this_size {
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ce240dc2484..055e1ebbd37 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -30,6 +30,8 @@ use middle::typeck;
 use util::common::indenter;
 use util::ppaux::Repr;
 
+use middle::trans::type_::Type;
+
 use core::str;
 use core::vec;
 use syntax::ast_map::{path, path_mod, path_name};
@@ -463,7 +465,7 @@ pub fn trans_monomorphized_callee(bcx: block,
 
           // create a llvalue that represents the fn ptr
           let fn_ty = node_id_type(bcx, callee_id);
-          let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).to_ptr();
+          let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).ptr_to();
           let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
 
           // combine the self environment with the rest
@@ -778,7 +780,7 @@ pub fn make_vtable(ccx: @mut CrateContext,
         let tbl = C_struct(components);
         let vtable = ccx.sess.str_of((ccx.names)("vtable"));
         let vt_gvar = do str::as_c_str(vtable) |buf| {
-            llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(vt_gvar, tbl);
         llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index ebf2d888148..cb68a2af92b 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use back::link::mangle_internal_name_by_path_and_seq;
-use lib::llvm::{Type, ValueRef, llvm};
+use lib::llvm::{ValueRef, llvm};
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::build::*;
@@ -33,6 +33,8 @@ use syntax::ast;
 use syntax::ast_map::path_name;
 use syntax::parse::token::special_idents;
 
+use middle::trans::type_::Type;
+
 pub struct Reflector {
     visitor_val: ValueRef,
     visitor_methods: @~[@ty::Method],
diff --git a/src/librustc/middle/trans/shape.rs b/src/librustc/middle/trans/shape.rs
index f3554b34806..82db5d405da 100644
--- a/src/librustc/middle/trans/shape.rs
+++ b/src/librustc/middle/trans/shape.rs
@@ -17,6 +17,8 @@ use lib::llvm::{True, ModuleRef, ValueRef};
 use middle::trans::common::*;
 use middle::trans;
 
+use middle::trans::type_::Type;
+
 use core::str;
 
 pub struct Ctxt {
@@ -32,7 +34,7 @@ pub fn mk_global(ccx: &CrateContext,
               -> ValueRef {
     unsafe {
         let llglobal = do str::as_c_str(name) |buf| {
-            llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(llglobal, llval);
         llvm::LLVMSetGlobalConstant(llglobal, True);
@@ -50,7 +52,7 @@ pub fn mk_ctxt(llmod: ModuleRef) -> Ctxt {
     unsafe {
         let llshapetablesty = Type::named_struct("shapes");
         do "shapes".as_c_str |buf| {
-            llvm::LLVMAddGlobal(llmod, llshapetablesty, buf)
+            llvm::LLVMAddGlobal(llmod, llshapetablesty.to_ref(), buf)
         };
 
         Ctxt {
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 00933865012..014c46b06e4 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -27,6 +27,8 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::ty_to_str;
 
+use middle::trans::type_::Type;
+
 use core::option::None;
 use syntax::ast;
 use syntax::codemap;
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 851ff4511a0..14c4ac71d97 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -11,6 +11,7 @@
 use core::prelude::*;
 
 use lib::llvm::{llvm, TypeRef, Bool, False, True, TypeKind};
+use lib::llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 
 use middle::ty;
 
@@ -26,6 +27,7 @@ use core::cast;
 
 use core::libc::{c_uint};
 
+#[deriving(Eq)]
 pub struct Type {
     priv rf: TypeRef
 }
@@ -38,12 +40,14 @@ macro_rules! ty (
  * Wrapper for LLVM TypeRef
  */
 impl Type {
+    #[inline(always)]
     pub fn from_ref(r: TypeRef) -> Type {
         Type {
             rf: r
         }
     }
 
+    #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
     pub fn to_ref(&self) -> TypeRef {
         self.rf
     }
@@ -136,7 +140,7 @@ impl Type {
 
     pub fn float_from_ty(ctx: &CrateContext, t: ast::float_ty) -> Type {
         match t {
-            ast::ty_f => ctx.float_ty,
+            ast::ty_f => ctx.float_type,
             ast::ty_f32 => Type::f32(),
             ast::ty_f64 => Type::f64()
         }
@@ -147,7 +151,7 @@ impl Type {
     }
 
     pub fn func(args: &[Type], ret: &Type) -> Type {
-        let vec : &[TypeRef] = unsafe { cast::transmute() };
+        let vec : &[TypeRef] = unsafe { cast::transmute(args) };
         ty!(llvm::LLVMFunctionType(ret.to_ref(), vec::raw::to_ptr(vec),
                                    args.len() as c_uint, False))
     }
@@ -157,12 +161,13 @@ impl Type {
     }
 
     pub fn ptr(ty: Type) -> Type {
-        ty!(llvm::LLVMPointerType(ty, 0 as c_uint))
+        ty!(llvm::LLVMPointerType(ty.to_ref(), 0 as c_uint))
     }
 
     pub fn struct_(els: &[Type], packed: bool) -> Type {
         let els : &[TypeRef] = unsafe { cast::transmute(els) };
-        ty!(llvm::LLVMStructType(vec::raw::to_ptr(els), els.len() as c_uint, packed as Bool))
+        ty!(llvm::LLVMStructTypeInContext(base::task_llcx(), vec::raw::to_ptr(els),
+                                          els.len() as c_uint, packed as Bool))
     }
 
     pub fn named_struct(name: &str) -> Type {
@@ -175,7 +180,7 @@ impl Type {
     }
 
     pub fn vtable() -> Type {
-        Type::array(Type::i8().ptr_to(), 1)
+        Type::array(&Type::i8().ptr_to(), 1)
     }
 
     pub fn generic_glue_fn(cx: &mut CrateContext) -> Type {
@@ -185,7 +190,7 @@ impl Type {
         }
 
         let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue);
-        cx.tn.associate_type("glue_fn", ty);
+        cx.tn.associate_type("glue_fn", &ty);
 
         return ty;
     }
@@ -193,10 +198,9 @@ impl Type {
     pub fn tydesc(arch: Architecture) -> Type {
         let mut tydesc = Type::named_struct("tydesc");
         let tydescpp = tydesc.ptr_to().ptr_to();
-        let pvoid = Type::i8().ptr_to();
-        let glue_fn_ty = Type::func(
-            [ Type::nil.ptr_to(), tydescpp, pvoid ],
-            Type::void()).ptr_to();
+        let pvoid = Type::i8p();
+        let glue_fn_ty = Type::func([ Type::nil().ptr_to(), tydescpp, pvoid ],
+            &Type::void()).ptr_to();
 
         let int_ty = Type::int(arch);
 
@@ -226,7 +230,7 @@ impl Type {
     }
 
     pub fn opaque_vec(arch: Architecture) -> Type {
-        Type::vec(arch, Type::i8())
+        Type::vec(arch, &Type::i8())
     }
 
     #[inline]
@@ -242,11 +246,11 @@ impl Type {
     }
 
     pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
-        Type::struct_(Type::box_header_fields(ctx) + [ty], false)
+        Type::struct_(Type::box_header_fields(ctx) + [*ty], false)
     }
 
     pub fn opaque_box(ctx: &CrateContext) -> Type {
-        Type::box(ctx, Type::i8())
+        Type::box(ctx, &Type::i8())
     }
 
     pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
@@ -254,7 +258,7 @@ impl Type {
     }
 
     pub fn opaque_cbox_ptr(cx: &CrateContext) -> Type {
-        Type::opaque_box().ptr_to()
+        Type::opaque_box(cx).ptr_to()
     }
 
     pub fn enum_discrim(cx: &CrateContext) -> Type {
@@ -275,7 +279,7 @@ impl Type {
             }
             ty::UniqTraitStore => {
                 Type::struct_(
-                    [ tydesc_ptr, Type::unique(ctx, Type::i8()).ptr_to()],
+                    [ tydesc_ptr, Type::unique(ctx, &Type::i8()).ptr_to()],
                 false)
             }
             ty::RegionTraitStore(*) => {
@@ -301,7 +305,7 @@ impl Type {
     }
 
     pub fn ptr_to(&self) -> Type {
-        ty!(llvm::LLVMPointerType(self.to_ref()))
+        ty!(llvm::LLVMPointerType(self.to_ref(), 0))
     }
 
     pub fn get_field(&self, idx: uint) -> Type {
@@ -335,14 +339,38 @@ impl Type {
 
     pub fn field_types(&self) -> ~[Type] {
         unsafe {
-            let n_elts = llvm::LLVMCountStructElementTypes(struct_ty) as uint;
+            let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as uint;
             if n_elts == 0 {
                 return ~[];
             }
             let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
-            llvm::LLVMGetStructElementTypes(struct_ty, &mut elts[0]);
+            llvm::LLVMGetStructElementTypes(self.to_ref(), &mut elts[0]);
             cast::transmute(elts)
         }
     }
 
+    pub fn return_type(&self) -> Type {
+        unsafe {
+            ty!(llvm::LLVMGetReturnType(self.to_ref()))
+        }
+    }
+
+    pub fn func_params(&self) -> ~[Type] {
+        unsafe {
+            let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
+            let args = vec::from_elem(n_args, 0 as TypeRef);
+            llvm::LLVMGetParamTypes(self.to_ref(), vec::raw::to_ptr(args));
+            cast::transmute(args)
+        }
+    }
+
+    pub fn float_width(&self) -> uint {
+        match self.kind() {
+            Float => 32,
+            Double => 64,
+            X86_FP80 => 80,
+            FP128 | PPC_FP128 => 128,
+            _ => fail!("llvm_float_width called on a non-float type")
+        }
+    }
 }
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 9ace4991f1b..0f4ffb04b28 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -18,6 +18,8 @@ use middle::trans::common;
 use middle::ty;
 use util::ppaux;
 
+use middle::trans::type_::Type;
+
 use syntax::ast;
 
 pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
@@ -58,10 +60,15 @@ pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t)
         atys.push_all(type_of_explicit_args(cx, inputs));
 
         // Use the output as the actual return value if it's immediate.
+<<<<<<< HEAD
         if output_is_immediate && !ty::type_is_nil(output) {
             Type::func(atys, lloutputtype)
+=======
+        if output_is_immediate {
+            Type::func(atys, &lloutputtype)
+>>>>>>> Finish up Type refactoring
         } else {
-            Type::func(atys, Type::void())
+            Type::func(atys, &Type::void())
         }
     }
 }
@@ -87,11 +94,11 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
         match ty::get(t).sty {
           ty::ty_box(mt) => {
               let ty = type_of(cx, mt.ty);
-              Type::box(cx, ty).ptr_to()
+              Type::box(cx, &ty).ptr_to()
           }
           ty::ty_uniq(mt) => {
               let ty = type_of(cx, mt.ty);
-              Type::unique(cx, ty).ptr_to()
+              Type::unique(cx, &ty).ptr_to()
           }
           _ => {
             cx.sess.bug("non-box in type_of_non_gc_box");
@@ -146,14 +153,14 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
         ty::ty_closure(*) => Type::struct_([Type::i8p(), Type::i8p()], false),
         ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
 
-        ty::ty_estr(ty::vstore_fixed(size)) => Type::array(Type::i8(), size),
+        ty::ty_estr(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
         ty::ty_evec(mt, ty::vstore_fixed(size)) => {
-            Type::array(sizing_type_of(cx, mt.ty), size)
+            Type::array(&sizing_type_of(cx, mt.ty), size as u64)
         }
 
         ty::ty_unboxed_vec(mt) => {
             let sz_ty = sizing_type_of(cx, mt.ty);
-            Type::vec(cx.sess.targ_cfg.arch, sz_ty)
+            Type::vec(cx.sess.targ_cfg.arch, &sz_ty)
         }
 
         ty::ty_tup(*) | ty::ty_enum(*) => {
@@ -165,7 +172,7 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
             if ty::type_is_simd(cx.tcx, t) {
                 let et = ty::simd_type(cx.tcx, t);
                 let n = ty::simd_size(cx.tcx, t);
-                Type::vector(type_of(cx, et), n)
+                Type::vector(&type_of(cx, et), n as u64)
             } else {
                 let repr = adt::represent_type(cx, t);
                 let packed = ty::lookup_packed(cx.tcx, did);
@@ -205,14 +212,14 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
         return llty;
     }
 
-    let llty = match ty::get(t).sty {
+    let mut llty = match ty::get(t).sty {
       ty::ty_nil | ty::ty_bot => Type::nil(),
       ty::ty_bool => Type::bool(),
       ty::ty_int(t) => Type::int_from_ty(cx, t),
       ty::ty_uint(t) => Type::uint_from_ty(cx, t),
       ty::ty_float(t) => Type::float_from_ty(cx, t),
       ty::ty_estr(ty::vstore_uniq) => {
-        Type::unique(cx, Type::vec(cx.sess.targ_cfg.arch, Type::i8())).ptr_to()
+        Type::unique(cx, &Type::vec(cx.sess.targ_cfg.arch, &Type::i8())).ptr_to()
       }
       ty::ty_enum(did, ref substs) => {
         // Only create the named struct, but don't fill it in. We
@@ -223,30 +230,30 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
         Type::named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
       }
       ty::ty_estr(ty::vstore_box) => {
-        Type::box(cx, Type::vec(cx, Type::i8())).ptr_to()
+        Type::box(cx, &Type::vec(cx.sess.targ_cfg.arch, &Type::i8())).ptr_to()
       }
       ty::ty_evec(ref mt, ty::vstore_box) => {
           let e_ty = type_of(cx, mt.ty);
-          let v_ty = Type::vec(cx.sess.targ_cfg.arch, e_ty);
-          Type::box(cx, v_ty).ptr_to()
+          let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
+          Type::box(cx, &v_ty).ptr_to()
       }
       ty::ty_box(ref mt) => {
           let ty = type_of(cx, mt.ty);
-          Type::box(cx, ty).ptr_to()
+          Type::box(cx, &ty).ptr_to()
       }
       ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
       ty::ty_uniq(ref mt) => {
           let ty = type_of(cx, mt.ty);
-          Type::unique(cx, ty).ptr_to()
+          Type::unique(cx, &ty).ptr_to()
       }
       ty::ty_evec(ref mt, ty::vstore_uniq) => {
           let ty = type_of(cx, mt.ty);
-          let ty = Type::vec(cx, ty);
-          Type::unique(cx, ty).ptr_to()
+          let ty = Type::vec(cx.sess.targ_cfg.arch, &ty);
+          Type::unique(cx, &ty).ptr_to()
       }
       ty::ty_unboxed_vec(ref mt) => {
           let ty = type_of(cx, mt.ty);
-          Type::vec(cx.sess.targ_cfg.arch, ty)
+          Type::vec(cx.sess.targ_cfg.arch, &ty)
       }
       ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
       ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
@@ -263,20 +270,20 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
       }
 
       ty::ty_estr(ty::vstore_fixed(n)) => {
-          Type::array(Type::i8(), n + 1u /* +1 for trailing null */)
+          Type::array(&Type::i8(), (n + 1u) as u64)
       }
 
       ty::ty_evec(ref mt, ty::vstore_fixed(n)) => {
-          Type::array(type_of(cx, mt.ty), n)
+          Type::array(&type_of(cx, mt.ty), n as u64)
       }
 
       ty::ty_bare_fn(_) => type_of_fn_from_ty(cx, t).ptr_to(),
       ty::ty_closure(_) => {
           let ty = type_of_fn_from_ty(cx, t);
-          Type::func_pair(cx, ty)
+          Type::func_pair(cx, &ty)
       }
       ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
-      ty::ty_type => cx.tydesc_type.to_ptr(),
+      ty::ty_type => cx.tydesc_type.ptr_to(),
       ty::ty_tup(*) => {
           let repr = adt::represent_type(cx, t);
           Type::struct_(adt::fields_of(cx, repr), false)
@@ -286,7 +293,7 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
           if ty::type_is_simd(cx.tcx, t) {
               let et = ty::simd_type(cx.tcx, t);
               let n = ty::simd_size(cx.tcx, t);
-              Type::vector(type_of(cx, et), n)
+              Type::vector(&type_of(cx, et), n as u64)
           } else {
               // Only create the named struct, but don't fill it in. We fill it
               // in *after* placing it into the type cache. This prevents
@@ -306,16 +313,14 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
     match ty::get(t).sty {
       ty::ty_enum(*) => {
           let repr = adt::represent_type(cx, t);
-          common::set_struct_body(llty, adt::fields_of(cx, repr),
-                                  false);
+          llty.set_struct_body(adt::fields_of(cx, repr), false);
       }
 
       ty::ty_struct(did, _) => {
         if !ty::type_is_simd(cx.tcx, t) {
           let repr = adt::represent_type(cx, t);
           let packed = ty::lookup_packed(cx.tcx, did);
-          common::set_struct_body(llty, adt::fields_of(cx, repr),
-                                  packed);
+          llty.set_struct_body(adt::fields_of(cx, repr), packed);
         }
       }
       _ => ()
@@ -345,19 +350,5 @@ pub fn llvm_type_name(cx: &CrateContext,
 
 pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> Type {
     let self_ty = type_of(ccx, self_ty).ptr_to();
-    Type::func([self_ty], Type::viod())
-}
-
-/*
-pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> Type {
-    let addrspace = base::get_tydesc(ccx, t).addrspace;
-    debug!("type_of_rooted %s in addrspace %u",
-           ppaux::ty_to_str(ccx.tcx, t), addrspace as uint);
-    return T_root(type_of(ccx, t), addrspace);
-}
-
-pub fn type_of_glue_fn(ccx: &CrateContext) -> Type {
-    let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
-    return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_void());
+    Type::func([self_ty], Type::void())
 }
-*/
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 6b2c6801e58..eb5376da696 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -28,6 +28,8 @@ use middle::ty;
 use syntax::codemap::span;
 use syntax::ast;
 
+use middle::trans::type_::Type;
+
 pub fn root_and_write_guard(datum: &Datum,
                             mut bcx: block,
                             span: span,
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index e1daf6c81b2..c38b013a75a 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -175,15 +175,15 @@ pub extern "rust-intrinsic" {
     pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int;
 
     #[cfg(not(stage0))]
-    pub fn atomic_umin(dst: &mut int, src: int) -> int;
+    pub fn atomic_umax(dst: &mut int, src: int) -> int;
     #[cfg(not(stage0))]
-    pub fn atomic_umin_acq(dst: &mut int, src: int) -> int;
+    pub fn atomic_umax_acq(dst: &mut int, src: int) -> int;
     #[cfg(not(stage0))]
-    pub fn atomic_umin_rel(dst: &mut int, src: int) -> int;
+    pub fn atomic_umax_rel(dst: &mut int, src: int) -> int;
     #[cfg(not(stage0))]
-    pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int;
+    pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
     #[cfg(not(stage0))]
-    pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int;
+    pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
 
     /// The size of a type in bytes.
     ///