diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 3a35f144ab5..8182dd9339e 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -236,7 +236,7 @@ pub fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
         _ => ()
     }
 
-    let uses_outptr = type_of::return_uses_outptr(ccx.tcx, output);
+    let uses_outptr = type_of::return_uses_outptr(ccx, output);
     let offset = if uses_outptr { 2 } else { 1 };
 
     for (i, &arg_ty) in inputs.iter().enumerate() {
@@ -1117,13 +1117,13 @@ pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef {
 
 pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
     let _icx = push_ctxt("spill_if_immediate");
-    if type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
+    if type_is_immediate(cx.ccx(), t) { return do_spill(cx, v, t); }
     return v;
 }
 
 pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
     let _icx = push_ctxt("load_if_immediate");
-    if type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
+    if type_is_immediate(cx.ccx(), t) { return Load(cx, v); }
     return v;
 }
 
@@ -1656,7 +1656,7 @@ pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
 // slot where the return value of the function must go.
 pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> ValueRef {
     unsafe {
-        if type_of::return_uses_outptr(fcx.ccx.tcx, output_type) {
+        if type_of::return_uses_outptr(fcx.ccx, output_type) {
             llvm::LLVMGetParam(fcx.llfn, 0)
         } else {
             let lloutputtype = type_of::type_of(fcx.ccx, output_type);
@@ -1696,7 +1696,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
             ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
         }
     };
-    let uses_outptr = type_of::return_uses_outptr(ccx.tcx, substd_output_type);
+    let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
     let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
 
     let fcx = @mut FunctionContext {
@@ -1808,7 +1808,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
     match fcx.llself {
         Some(slf) => {
             let self_val = if slf.is_copy
-                    && datum::appropriate_mode(bcx.tcx(), slf.t).is_by_value() {
+                    && datum::appropriate_mode(bcx.ccx(), slf.t).is_by_value() {
                 let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
                 let alloc = alloc_ty(bcx, slf.t, "__self");
                 Store(bcx, tmp, alloc);
@@ -1838,7 +1838,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
         // only by value if immediate:
-        let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
+        let llarg = if datum::appropriate_mode(bcx.ccx(), arg_ty).is_by_value() {
             let alloc = alloc_ty(bcx, arg_ty, "__arg");
             Store(bcx, raw_llarg, alloc);
             alloc
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index c1a9f764962..700d9c7597b 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -655,7 +655,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
         // not care about the result, just make a stack slot.
         let opt_llretslot = match dest {
             None => {
-                assert!(!type_of::return_uses_outptr(in_cx.tcx(), ret_ty));
+                assert!(!type_of::return_uses_outptr(in_cx.ccx(), ret_ty));
                 None
             }
             Some(expr::SaveIn(dst)) => Some(dst),
@@ -685,7 +685,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
 
             // Push the out-pointer if we use an out-pointer for this
             // return type, otherwise push "undef".
-            if type_of::return_uses_outptr(in_cx.tcx(), ret_ty) {
+            if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
                 llargs.push(opt_llretslot.unwrap());
             }
 
@@ -711,7 +711,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
             // any attributes with ABI implications directly to the call instruction. Right now, the
             // only attribute we need to worry about is `sret`.
             let mut attrs = ~[];
-            if type_of::return_uses_outptr(in_cx.tcx(), ret_ty) {
+            if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
                 attrs.push((1, StructRetAttribute));
             }
 
@@ -734,7 +734,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
             // the return value, copy it into llretslot.
             match opt_llretslot {
                 Some(llretslot) => {
-                    if !type_of::return_uses_outptr(bcx.tcx(), ret_ty) &&
+                    if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
                         !ty::type_is_voidish(ret_ty)
                     {
                         Store(bcx, llret, llretslot);
@@ -758,7 +758,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
         // drop the temporary slot we made.
         match dest {
             None => {
-                assert!(!type_of::return_uses_outptr(bcx.tcx(), ret_ty));
+                assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
             }
             Some(expr::Ignore) => {
                 // drop the value if it is not being saved.
@@ -871,7 +871,7 @@ pub fn trans_arg_expr(bcx: @mut Block,
             DontAutorefArg => {
                 let need_scratch = ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
                     (bcx.expr_is_lval(arg_expr) &&
-                     arg_datum.appropriate_mode(bcx.tcx()).is_by_ref());
+                     arg_datum.appropriate_mode(bcx.ccx()).is_by_ref());
 
                 let arg_datum = if need_scratch {
                     let scratch = scratch_datum(bcx, arg_datum.ty, "__self", false);
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 4d46ae385eb..8fbf8b1813c 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -46,23 +46,37 @@ use syntax::{ast, ast_map};
 
 pub use middle::trans::context::CrateContext;
 
-fn type_is_newtype_immediate(cx: ty::ctxt, ty: ty::t) -> bool {
+fn type_is_newtype_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool {
     match ty::get(ty).sty {
         ty::ty_struct(def_id, ref substs) => {
-            let fields = ty::struct_fields(cx, def_id, substs);
+            let fields = ty::struct_fields(ccx.tcx, def_id, substs);
             fields.len() == 1 &&
                 fields[0].ident.name == token::special_idents::unnamed_field.name &&
-                type_is_immediate(cx, fields[0].mt.ty)
+                type_is_immediate(ccx, fields[0].mt.ty)
         }
         _ => false
     }
 }
 
-pub fn type_is_immediate(cx: ty::ctxt, ty: ty::t) -> bool {
-    ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
+pub fn type_is_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool {
+    use middle::trans::machine::llsize_of_alloc;
+    use middle::trans::type_of::sizing_type_of;
+    let tcx = ccx.tcx;
+    let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
-        type_is_newtype_immediate(cx, ty) ||
-        ty::type_is_simd(cx, ty)
+        type_is_newtype_immediate(ccx, ty) ||
+        ty::type_is_simd(tcx, ty);
+    if simple {
+        return true;
+    }
+    match ty::get(ty).sty {
+        // FIXME: #9651: small `ty_struct` and `ty_enum` should also be immediate
+        ty::ty_tup(*) => {
+            let llty = sizing_type_of(ccx, ty);
+            llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type)
+        }
+        _ => false
+    }
 }
 
 pub fn gensym_name(name: &str) -> (Ident, path_elt) {
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 78422159126..c17262b9282 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -188,7 +188,7 @@ pub fn scratch_datum(bcx: @mut Block, ty: ty::t, name: &str, zero: bool) -> Datu
     Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
 }
 
-pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
+pub fn appropriate_mode(ccx: &mut CrateContext, ty: ty::t) -> DatumMode {
     /*!
      * Indicates the "appropriate" mode for this value,
      * which is either by ref or by value, depending
@@ -197,7 +197,7 @@ pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
 
     if ty::type_is_voidish(ty) {
         ByValue
-    } else if type_is_immediate(tcx, ty) {
+    } else if type_is_immediate(ccx, ty) {
         ByValue
     } else {
         ByRef(RevokeClean)
@@ -505,10 +505,10 @@ impl Datum {
         }
     }
 
-    pub fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
+    pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode {
         /*! See the `appropriate_mode()` function */
 
-        appropriate_mode(tcx, self.ty)
+        appropriate_mode(ccx, self.ty)
     }
 
     pub fn to_appropriate_llval(&self, bcx: @mut Block) -> ValueRef {
@@ -516,7 +516,7 @@ impl Datum {
          *
          * Yields an llvalue with the `appropriate_mode()`. */
 
-        match self.appropriate_mode(bcx.tcx()) {
+        match self.appropriate_mode(bcx.ccx()) {
             ByValue => self.to_value_llval(bcx),
             ByRef(_) => self.to_ref_llval(bcx)
         }
@@ -527,7 +527,7 @@ impl Datum {
          *
          * Yields a datum with the `appropriate_mode()`. */
 
-        match self.appropriate_mode(bcx.tcx()) {
+        match self.appropriate_mode(bcx.ccx()) {
             ByValue => self.to_value_datum(bcx),
             ByRef(_) => self.to_ref_datum(bcx)
         }
@@ -667,7 +667,7 @@ impl Datum {
                     ByValue => {
                         // Actually, this case cannot happen right
                         // now, because enums are never immediate.
-                        assert!(type_is_immediate(bcx.tcx(), ty));
+                        assert!(type_is_immediate(bcx.ccx(), ty));
                         (Some(Datum {ty: ty, ..*self}), bcx)
                     }
                 };
@@ -699,7 +699,7 @@ impl Datum {
                         )
                     }
                     ByValue => {
-                        assert!(type_is_immediate(bcx.tcx(), ty));
+                        assert!(type_is_immediate(bcx.ccx(), ty));
                         (
                             Some(Datum {
                                 val: ExtractValue(bcx, self.val, 0),
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 995b2467888..65e0f17f651 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -290,7 +290,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock {
         debug2!("add_env(closure_ty={})", closure_ty.repr(tcx));
         let scratch = scratch_datum(bcx, closure_ty, "__adjust", false);
         let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
-        assert_eq!(datum.appropriate_mode(tcx), ByValue);
+        assert_eq!(datum.appropriate_mode(bcx.ccx()), ByValue);
         Store(bcx, datum.to_appropriate_llval(bcx), llfn);
         let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
         Store(bcx, base::null_env_ptr(bcx.ccx()), llenv);
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 6ca0967f8ee..84ee1cc8ef3 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -492,7 +492,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext,
 
         // Push Rust return pointer, using null if it will be unused.
         let rust_uses_outptr =
-            type_of::return_uses_outptr(tcx, tys.fn_sig.output);
+            type_of::return_uses_outptr(ccx, tys.fn_sig.output);
         let return_alloca: Option<ValueRef>;
         let llrust_ret_ty = tys.llsig.llret_ty;
         let llrust_retptr_ty = llrust_ret_ty.ptr_to();
@@ -702,7 +702,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
     LlvmSignature {
         llarg_tys: llarg_tys,
         llret_ty: llret_ty,
-        sret: type_of::return_uses_outptr(ccx.tcx, fn_sig.output),
+        sret: type_of::return_uses_outptr(ccx, fn_sig.output),
     }
 }
 
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index da71e99badb..a68c10c74ee 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -53,7 +53,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         Ret(bcx, llcall);
     }
 
-    fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
+    fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str, t: ty::t) {
         let first_real_arg = bcx.fcx.arg_pos(0u);
         let a = get_param(bcx.fcx.llfn, first_real_arg);
         let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
@@ -63,12 +63,17 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         let val = Call(bcx, llfn, [a, b], []);
         let result = ExtractValue(bcx, val, 0);
         let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
-        let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
-        let ret = Load(bcx, retptr);
+        let ret = Load(bcx, Alloca(bcx, type_of::type_of(bcx.ccx(), t), ""));
         let ret = InsertValue(bcx, ret, result, 0);
         let ret = InsertValue(bcx, ret, overflow, 1);
-        Store(bcx, ret, retptr);
-        RetVoid(bcx)
+
+        if type_is_immediate(bcx.ccx(), t) {
+            Ret(bcx, ret);
+        } else {
+            let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
+            Store(bcx, ret, retptr);
+            RetVoid(bcx);
+        }
     }
 
     fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
@@ -227,7 +232,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             // intrinsics, there are no argument cleanups to
             // concern ourselves with.
             let tp_ty = substs.tys[0];
-            let mode = appropriate_mode(ccx.tcx, tp_ty);
+            let mode = appropriate_mode(ccx, tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
                              ty: tp_ty, mode: mode};
             bcx = src.move_to(bcx, DROP_EXISTING,
@@ -237,7 +242,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         "move_val_init" => {
             // See comments for `"move_val"`.
             let tp_ty = substs.tys[0];
-            let mode = appropriate_mode(ccx.tcx, tp_ty);
+            let mode = appropriate_mode(ccx, tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
                              ty: tp_ty, mode: mode};
             bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
@@ -278,7 +283,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         "uninit" => {
             // Do nothing, this is effectively a no-op
             let retty = substs.tys[0];
-            if type_is_immediate(ccx.tcx, retty) && !ty::type_is_nil(retty) {
+            if type_is_immediate(ccx, retty) && !ty::type_is_nil(retty) {
                 unsafe {
                     Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
                 }
@@ -316,7 +321,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
 
             if !ty::type_is_voidish(out_type) {
                 let llsrcval = get_param(decl, first_real_arg);
-                if type_is_immediate(ccx.tcx, in_type) {
+                if type_is_immediate(ccx, in_type) {
                     match fcx.llretptr {
                         Some(llretptr) => {
                             Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to()));
@@ -335,7 +340,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
                             }
                         }
                     }
-                } else if type_is_immediate(ccx.tcx, out_type) {
+                } else if type_is_immediate(ccx, out_type) {
                     let llsrcptr = PointerCast(bcx, llsrcval, llouttype.ptr_to());
                     let ll_load = Load(bcx, llsrcptr);
                     Ret(bcx, ll_load);
@@ -466,35 +471,59 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
         "bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
         "bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),
 
-        "i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"),
-        "i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"),
-        "i32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32"),
-        "i64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64"),
+        "i8_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8", output_type),
+        "i16_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16", output_type),
+        "i32_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32", output_type),
+        "i64_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64", output_type),
 
-        "u8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8"),
-        "u16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16"),
-        "u32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32"),
-        "u64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64"),
+        "u8_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8", output_type),
+        "u16_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16", output_type),
+        "u32_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32", output_type),
+        "u64_add_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64", output_type),
 
-        "i8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8"),
-        "i16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16"),
-        "i32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32"),
-        "i64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64"),
+        "i8_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8", output_type),
+        "i16_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16", output_type),
+        "i32_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32", output_type),
+        "i64_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64", output_type),
 
-        "u8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8"),
-        "u16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16"),
-        "u32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32"),
-        "u64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64"),
+        "u8_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8", output_type),
+        "u16_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16", output_type),
+        "u32_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32", output_type),
+        "u64_sub_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64", output_type),
 
-        "i8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8"),
-        "i16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16"),
-        "i32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32"),
-        "i64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64"),
+        "i8_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8", output_type),
+        "i16_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16", output_type),
+        "i32_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32", output_type),
+        "i64_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64", output_type),
 
-        "u8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8"),
-        "u16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16"),
-        "u32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32"),
-        "u64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64"),
+        "u8_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8", output_type),
+        "u16_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16", output_type),
+        "u32_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32", output_type),
+        "u64_mul_with_overflow" =>
+            with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64", output_type),
 
         _ => {
             // Could we make this an enum rather than a string? does it get
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 3d5ebefcccb..3f37f12bc30 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -20,12 +20,12 @@ use middle::trans::type_::Type;
 use syntax::ast;
 use syntax::opt_vec;
 
-pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: ty::t) -> bool {
-    !type_is_immediate(ccx.tcx, arg_ty)
+pub fn arg_is_indirect(ccx: &mut CrateContext, arg_ty: ty::t) -> bool {
+    !type_is_immediate(ccx, arg_ty)
 }
 
-pub fn return_uses_outptr(tcx: ty::ctxt, ty: ty::t) -> bool {
-    !type_is_immediate(tcx, ty)
+pub fn return_uses_outptr(ccx: &mut CrateContext, ty: ty::t) -> bool {
+    !type_is_immediate(ccx, ty)
 }
 
 pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: ty::t) -> Type {
@@ -49,7 +49,7 @@ pub fn type_of_rust_fn(cx: &mut CrateContext,
 
     // Arg 0: Output pointer.
     // (if the output type is non-immediate)
-    let use_out_pointer = return_uses_outptr(cx.tcx, output);
+    let use_out_pointer = return_uses_outptr(cx, output);
     let lloutputtype = type_of(cx, output);
     if use_out_pointer {
         atys.push(lloutputtype.ptr_to());