From d2a22f520c73d26730f9159e1ce1b6058c2287dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 5 Jul 2014 21:43:47 +0200 Subject: [PATCH 1/2] Remove remainders from when booleans were i8 --- src/librustc/middle/trans/adt.rs | 2 +- src/librustc/middle/trans/base.rs | 8 ++++---- src/librustc/middle/trans/common.rs | 4 ---- src/librustc/middle/trans/expr.rs | 10 ++-------- src/librustc/middle/trans/glue.rs | 2 +- src/librustc/middle/trans/intrinsic.rs | 7 ++++--- 6 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index d21ee37f291..33ad05977ed 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -618,7 +618,7 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr) RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => { assert!(discr == 0 || discr == 1); - _match::single_result(Result::new(bcx, C_i1(bcx.ccx(), discr != 0))) + _match::single_result(Result::new(bcx, C_bool(bcx.ccx(), discr != 0))) } } } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 75271804b79..b2558cdd364 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -539,8 +539,8 @@ pub fn compare_scalar_values<'a>( // We don't need to do actual comparisons for nil. // () == () holds but () < () does not. match op { - ast::BiEq | ast::BiLe | ast::BiGe => return C_i1(cx.ccx(), true), - ast::BiNe | ast::BiLt | ast::BiGt => return C_i1(cx.ccx(), false), + ast::BiEq | ast::BiLe | ast::BiGe => return C_bool(cx.ccx(), true), + ast::BiNe | ast::BiLt | ast::BiGt => return C_bool(cx.ccx(), false), // refinements would be nice _ => die(cx) } @@ -1014,7 +1014,7 @@ pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx)); let size = IntCast(cx, n_bytes, ccx.int_type); let align = C_i32(ccx, align as i32); - let volatile = C_i1(ccx, false); + let volatile = C_bool(ccx, false); Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []); } @@ -1059,7 +1059,7 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) { let llzeroval = C_u8(ccx, 0); let size = machine::llsize_of(ccx, ty); let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32); - let volatile = C_i1(ccx, false); + let volatile = C_bool(ccx, false); b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []); } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index b1577a6abfe..b1d98656740 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -526,10 +526,6 @@ pub fn C_nil(ccx: &CrateContext) -> ValueRef { } pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef { - C_integral(Type::bool(ccx), val as u64, false) -} - -pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef { C_integral(Type::i1(ccx), val as u64, false) } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index b10190b23c7..aad82f37028 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -505,7 +505,7 @@ fn trans_index<'a>(bcx: &'a Block<'a>, let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len); let expect = ccx.get_intrinsic(&("llvm.expect.i1")); - let expected = Call(bcx, expect, [bounds_check, C_i1(ccx, false)], []); + let expected = Call(bcx, expect, [bounds_check, C_bool(ccx, false)], []); let bcx = with_cond(bcx, expected, |bcx| { controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len) }); @@ -1149,13 +1149,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>, match op { ast::UnNot => { let datum = unpack_datum!(bcx, trans(bcx, sub_expr)); - let llresult = if ty::type_is_bool(un_ty) { - let val = datum.to_llscalarish(bcx); - Xor(bcx, val, C_bool(ccx, true)) - } else { - // Note: `Not` is bitwise, not suitable for logical not. - Not(bcx, datum.to_llscalarish(bcx)) - }; + let llresult = Not(bcx, datum.to_llscalarish(bcx)); immediate_rvalue_bcx(bcx, llresult, un_ty).to_expr_datumblock() } ast::UnNeg => { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 7024ea4b375..e5e61f38175 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -234,7 +234,7 @@ fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>, -> &'a Block<'a> { let repr = adt::represent_type(bcx.ccx(), t); let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0); - with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| { + with_cond(bcx, Load(bcx, drop_flag), |cx| { trans_struct_drop(cx, t, v0, dtor_did, class_did, substs) }) } diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index bc0c88ceee9..8e64df8c7d4 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -150,7 +150,8 @@ pub fn trans_intrinsic(ccx: &CrateContext, let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p(ccx)); let count = get_param(decl, first_real_arg + 2); let llfn = ccx.get_intrinsic(&name); - Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, C_i1(ccx, volatile)], []); + Call(bcx, llfn, + [dst_ptr, src_ptr, Mul(bcx, size, count), align, C_bool(ccx, volatile)], []); RetVoid(bcx); } @@ -171,13 +172,13 @@ pub fn trans_intrinsic(ccx: &CrateContext, let val = get_param(decl, first_real_arg + 1); let count = get_param(decl, first_real_arg + 2); let llfn = ccx.get_intrinsic(&name); - Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, C_i1(ccx, volatile)], []); + Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, C_bool(ccx, volatile)], []); RetVoid(bcx); } fn count_zeros_intrinsic(bcx: &Block, name: &'static str) { let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u)); - let y = C_i1(bcx.ccx(), false); + let y = C_bool(bcx.ccx(), false); let llfn = bcx.ccx().get_intrinsic(&name); let llcall = Call(bcx, llfn, [x, y], []); Ret(bcx, llcall); From dd4112bf7924767a6074b54ffe297c877f8b042d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sat, 5 Jul 2014 21:47:14 +0200 Subject: [PATCH 2/2] Store booleans as i8 in memory to improve optimizations by LLVM LLVM doesn't really like types with a bit-width that isn't a multiple of 8 and disable various optimizations if it encounters such types used with loads/stores. OTOH, booleans must be represented as i1 when used as SSA values. To get the best results, we must use i1 for SSA values, and i8 when storing the value to memory. By using range asserts on loads, LLVM can eliminate the required zero-extend and truncate operations. Fixes #15203 --- src/librustc/middle/trans/adt.rs | 2 +- src/librustc/middle/trans/base.rs | 58 ++++++++++++++++++++---- src/librustc/middle/trans/cabi_arm.rs | 4 +- src/librustc/middle/trans/cabi_mips.rs | 4 +- src/librustc/middle/trans/cabi_x86.rs | 4 +- src/librustc/middle/trans/cabi_x86_64.rs | 2 +- src/librustc/middle/trans/callee.rs | 4 +- src/librustc/middle/trans/datum.rs | 28 ++---------- src/librustc/middle/trans/expr.rs | 8 ++-- src/librustc/middle/trans/foreign.rs | 34 ++++++++++---- src/librustc/middle/trans/glue.rs | 4 +- src/librustc/middle/trans/intrinsic.rs | 12 +++-- src/librustc/middle/trans/reflect.rs | 2 +- src/librustc/middle/trans/type_.rs | 2 +- src/librustc/middle/trans/type_of.rs | 12 ++++- 15 files changed, 115 insertions(+), 65 deletions(-) diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 33ad05977ed..f7fb6646938 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -641,7 +641,7 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) { } Univariant(ref st, true) => { assert_eq!(discr, 0); - Store(bcx, C_bool(bcx.ccx(), true), + Store(bcx, C_u8(bcx.ccx(), 1), GEPi(bcx, val, [0, st.fields.len() - 1])) } Univariant(..) => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b2558cdd364..3eaa17a0571 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -959,10 +959,42 @@ pub fn need_invoke(bcx: &Block) -> bool { pub fn load_if_immediate(cx: &Block, v: ValueRef, t: ty::t) -> ValueRef { let _icx = push_ctxt("load_if_immediate"); - if type_is_immediate(cx.ccx(), t) { return Load(cx, v); } + if type_is_immediate(cx.ccx(), t) { return load_ty(cx, v, t); } return v; } +pub fn load_ty(cx: &Block, ptr: ValueRef, t: ty::t) -> ValueRef { + /*! + * Helper for loading values from memory. Does the necessary conversion if + * the in-memory type differs from the type used for SSA values. Also + * handles various special cases where the type gives us better information + * about what we are loading. + */ + if type_is_zero_size(cx.ccx(), t) { + C_undef(type_of::type_of(cx.ccx(), t)) + } else if ty::type_is_bool(t) { + Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, lib::llvm::False), Type::i1(cx.ccx())) + } else if ty::type_is_char(t) { + // a char is a unicode codepoint, and so takes values from 0 + // to 0x10FFFF inclusive only. + LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, lib::llvm::False) + } else { + Load(cx, ptr) + } +} + +pub fn store_ty(cx: &Block, v: ValueRef, dst: ValueRef, t: ty::t) { + /*! + * Helper for storing values in memory. Does the necessary conversion if + * the in-memory type differs from the type used for SSA values. + */ + if ty::type_is_bool(t) { + Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst); + } else { + Store(cx, v, dst); + }; +} + pub fn ignore_lhs(_bcx: &Block, local: &ast::Local) -> bool { match local.pat.node { ast::PatWild => true, _ => false @@ -1285,9 +1317,14 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>, // Ties up the llstaticallocas -> llloadenv -> lltop edges, // and builds the return block. pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>, - last_bcx: &'a Block<'a>) { + last_bcx: &'a Block<'a>, + retty: ty::t) { let _icx = push_ctxt("finish_fn"); + // This shouldn't need to recompute the return type, + // as new_fn_ctxt did it already. + let substd_retty = retty.substp(fcx.ccx.tcx(), fcx.param_substs); + let ret_cx = match fcx.llreturn.get() { Some(llreturn) => { if !last_bcx.terminated.get() { @@ -1297,13 +1334,13 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>, } None => last_bcx }; - build_return_block(fcx, ret_cx); + build_return_block(fcx, ret_cx, substd_retty); debuginfo::clear_source_location(fcx); fcx.cleanup(); } // Builds the return block for a function. -pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) { +pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) { // Return the value if this function immediate; otherwise, return void. if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer { return RetVoid(ret_cx); @@ -1321,13 +1358,16 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) { retptr.erase_from_parent(); } - retval + if ty::type_is_bool(retty) { + Trunc(ret_cx, retval, Type::i1(fcx.ccx)) + } else { + retval + } } // Otherwise, load the return value from the ret slot - None => Load(ret_cx, fcx.llretptr.get().unwrap()) + None => load_ty(ret_cx, fcx.llretptr.get().unwrap(), retty) }; - Ret(ret_cx, retval); } @@ -1429,7 +1469,7 @@ pub fn trans_closure(ccx: &CrateContext, } // Insert the mandatory first few basic blocks before lltop. - finish_fn(&fcx, bcx); + finish_fn(&fcx, bcx, output_type); } // trans_fn: creates an LLVM function corresponding to a source language @@ -1521,7 +1561,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext, } } - finish_fn(&fcx, bcx); + finish_fn(&fcx, bcx, result_ty); } fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef, diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs index 01bef64ebba..c44a4e02ad4 100644 --- a/src/librustc/middle/trans/cabi_arm.rs +++ b/src/librustc/middle/trans/cabi_arm.rs @@ -85,7 +85,7 @@ fn ty_size(ty: Type) -> uint { fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { if is_reg_ty(ty) { - let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; return ArgType::direct(ty, None, None, attr); } let size = ty_size(ty); @@ -104,7 +104,7 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType { if is_reg_ty(ty) { - let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; return ArgType::direct(ty, None, None, attr); } let align = ty_align(ty); diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index 60db609e59e..9e5b38d2f7d 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -85,7 +85,7 @@ fn ty_size(ty: Type) -> uint { fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { if is_reg_ty(ty) { - let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; ArgType::direct(ty, None, None, attr) } else { ArgType::indirect(ty, Some(StructRetAttribute)) @@ -102,7 +102,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType { *offset += align_up_to(size, align * 8) / 8; if is_reg_ty(ty) { - let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; ArgType::direct(ty, None, None, attr) } else { ArgType::direct( diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index 5fffdf08646..0d88c611cba 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -59,7 +59,7 @@ pub fn compute_abi_info(ccx: &CrateContext, } } } else { - let attr = if rty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; ret_ty = ArgType::direct(rty, None, None, attr); } @@ -74,7 +74,7 @@ pub fn compute_abi_info(ccx: &CrateContext, } } _ => { - let attr = if t == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; ArgType::direct(t, None, None, attr) } }; diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index b2cd9d256dd..5b8ddfe1be7 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -350,7 +350,7 @@ pub fn compute_abi_info(ccx: &CrateContext, None) } } else { - let attr = if ty == Type::bool(ccx) { Some(ZExtAttribute) } else { None }; + let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None }; ArgType::direct(ty, None, None, attr) } } diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index dc9828606cc..37b9da738e1 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -346,7 +346,7 @@ pub fn trans_unboxing_shim(bcx: &Block, }).bcx; bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_scope); - finish_fn(&fcx, bcx); + finish_fn(&fcx, bcx, return_type); llfn } @@ -758,7 +758,7 @@ pub fn trans_call_inner<'a>( if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) && !type_is_zero_size(bcx.ccx(), ret_ty) { - Store(bcx, llret, llretslot); + store_ty(bcx, llret, llretslot, ret_ty) } } None => {} diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 440aa36b28c..b93469ad2fb 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -13,10 +13,8 @@ * Datums are and how they are intended to be used. */ -use lib; use lib::llvm::ValueRef; use middle::trans::base::*; -use middle::trans::build::*; use middle::trans::common::*; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; @@ -344,7 +342,7 @@ impl Datum { match self.kind.mode { ByValue => DatumBlock::new(bcx, self), ByRef => { - let llval = load(bcx, self.val, self.ty); + let llval = load_ty(bcx, self.val, self.ty); DatumBlock::new(bcx, Datum::new(llval, self.ty, Rvalue::new(ByValue))) } } @@ -471,7 +469,7 @@ impl Datum { DatumBlock::new(bcx, scratch) } ByValue => { - let v = load(bcx, l.val, l.ty); + let v = load_ty(bcx, l.val, l.ty); bcx = l.kind.post_store(bcx, l.val, l.ty); DatumBlock::new(bcx, Datum::new(v, l.ty, Rvalue::new(ByValue))) } @@ -516,24 +514,6 @@ impl Datum { } } -fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef { - /*! - * Private helper for loading from a by-ref datum. Handles various - * special cases where the type gives us better information about - * what we are loading. - */ - - if type_is_zero_size(bcx.ccx(), ty) { - C_undef(type_of::type_of(bcx.ccx(), ty)) - } else if ty::type_is_char(ty) { - // a char is a unicode codepoint, and so takes values from 0 - // to 0x10FFFF inclusive only. - LoadRangeAssert(bcx, llptr, 0, 0x10FFFF + 1, lib::llvm::False) - } else { - Load(bcx, llptr) - } -} - /** * Generic methods applicable to any sort of datum. */ @@ -591,7 +571,7 @@ impl Datum { if self.kind.is_by_ref() { memcpy_ty(bcx, dst, self.val, self.ty); } else { - Store(bcx, self.val, dst); + store_ty(bcx, self.val, dst, self.ty); } return bcx; @@ -642,7 +622,7 @@ impl Datum { assert!(!ty::type_needs_drop(bcx.tcx(), self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { - load(bcx, self.val, self.ty) + load_ty(bcx, self.val, self.ty) } else { self.val } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index aad82f37028..ac33f9bd1a8 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1374,7 +1374,7 @@ fn trans_lazy_binop<'a>( } Br(past_rhs, join.llbb); - let phi = Phi(join, Type::bool(bcx.ccx()), [lhs, rhs], + let phi = Phi(join, Type::i1(bcx.ccx()), [lhs, rhs], [past_lhs.llbb, past_rhs.llbb]); return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock(); @@ -1591,8 +1591,8 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>, let k_in = cast_type_kind(t_in); let k_out = cast_type_kind(t_out); let s_in = k_in == cast_integral && ty::type_is_signed(t_in); - let ll_t_in = type_of::type_of(ccx, t_in); - let ll_t_out = type_of::type_of(ccx, t_out); + let ll_t_in = type_of::arg_type_of(ccx, t_in); + let ll_t_out = type_of::arg_type_of(ccx, t_out); // Convert the value to be cast into a ValueRef, either by-ref or // by-value as appropriate given its type: @@ -1683,7 +1683,7 @@ fn trans_assign_op<'a>( let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty)); let dst_ty = dst_datum.ty; - let dst = Load(bcx, dst_datum.val); + let dst = load_ty(bcx, dst_datum.val, dst_datum.ty); // Evaluate RHS let rhs_datum = unpack_datum!(bcx, trans(bcx, &*src)); diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 6d719873c76..4e009622b0e 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -325,7 +325,7 @@ pub fn trans_native_call<'a>( base::alloca(bcx, type_of::type_of(ccx, *passed_arg_tys.get(i)), "__arg"); - Store(bcx, llarg_rust, scratch); + base::store_ty(bcx, llarg_rust, scratch, *passed_arg_tys.get(i)); llarg_rust = scratch; } @@ -346,7 +346,12 @@ pub fn trans_native_call<'a>( let llarg_foreign = if foreign_indirect { llarg_rust } else { - Load(bcx, llarg_rust) + if ty::type_is_bool(*passed_arg_tys.get(i)) { + let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, lib::llvm::False); + Trunc(bcx, val, Type::i1(bcx.ccx())) + } else { + Load(bcx, llarg_rust) + } }; debug!("argument {}, llarg_foreign={}", @@ -431,7 +436,7 @@ pub fn trans_native_call<'a>( debug!("llforeign_ret_ty={}", ccx.tn.type_to_str(llforeign_ret_ty)); if llrust_ret_ty == llforeign_ret_ty { - Store(bcx, llforeign_retval, llretptr); + base::store_ty(bcx, llforeign_retval, llretptr, fn_sig.output) } else { // The actual return type is a struct, but the ABI // adaptation code has cast it into some scalar type. The @@ -715,9 +720,15 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, // pointer). It makes adapting types easier, since we can // always just bitcast pointers. if !foreign_indirect { - let lltemp = builder.alloca(val_ty(llforeign_arg), ""); - builder.store(llforeign_arg, lltemp); - llforeign_arg = lltemp; + llforeign_arg = if ty::type_is_bool(rust_ty) { + let lltemp = builder.alloca(Type::bool(ccx), ""); + builder.store(builder.zext(llforeign_arg, Type::bool(ccx)), lltemp); + lltemp + } else { + let lltemp = builder.alloca(val_ty(llforeign_arg), ""); + builder.store(llforeign_arg, lltemp); + lltemp + } } // If the types in the ABI and the Rust types don't match, @@ -731,7 +742,12 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, let llrust_arg = if rust_indirect { llforeign_arg } else { - builder.load(llforeign_arg) + if ty::type_is_bool(rust_ty) { + let tmp = builder.load_range_assert(llforeign_arg, 0, 2, lib::llvm::False); + builder.trunc(tmp, Type::i1(ccx)) + } else { + builder.load(llforeign_arg) + } }; debug!("llrust_arg {}{}: {}", "#", @@ -828,8 +844,8 @@ fn foreign_signature(ccx: &CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t]) * values by pointer like we do. */ - let llarg_tys = arg_tys.iter().map(|&arg| type_of(ccx, arg)).collect(); - let llret_ty = type_of::type_of(ccx, fn_sig.output); + let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect(); + let llret_ty = type_of::arg_type_of(ccx, fn_sig.output); LlvmSignature { llarg_tys: llarg_tys, llret_ty: llret_ty diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index e5e61f38175..d3552baa792 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -234,7 +234,7 @@ fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>, -> &'a Block<'a> { let repr = adt::represent_type(bcx.ccx(), t); let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0); - with_cond(bcx, Load(bcx, drop_flag), |cx| { + with_cond(bcx, load_ty(bcx, drop_flag, ty::mk_bool()), |cx| { trans_struct_drop(cx, t, v0, dtor_did, class_did, substs) }) } @@ -505,7 +505,7 @@ fn make_generic_glue(ccx: &CrateContext, let bcx = fcx.entry_bcx.borrow().clone().unwrap(); let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, fcx.arg_pos(0) as c_uint) }; let bcx = helper(bcx, llrawptr0, t); - finish_fn(&fcx, bcx); + finish_fn(&fcx, bcx, ty::mk_nil()); llfn } diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 8e64df8c7d4..c5ce61ed122 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -96,13 +96,19 @@ pub fn trans_intrinsic(ccx: &CrateContext, let b = get_param(bcx.fcx.llfn, first_real_arg + 1); let llfn = bcx.ccx().get_intrinsic(&name); + // convert `i1` to a `bool`, and write to the out parameter let val = Call(bcx, llfn, [a, b], []); + let result = ExtractValue(bcx, val, 0); + let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx())); + let ret = C_undef(type_of::type_of(bcx.ccx(), t)); + let ret = InsertValue(bcx, ret, result, 0); + let ret = InsertValue(bcx, ret, overflow, 1); if type_is_immediate(bcx.ccx(), t) { - Ret(bcx, val); + Ret(bcx, ret); } else { let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos()); - Store(bcx, val, retptr); + Store(bcx, ret, retptr); RetVoid(bcx); } } @@ -367,7 +373,7 @@ pub fn trans_intrinsic(ccx: &CrateContext, let retty = *substs.substs.types.get(FnSpace, 0); if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) { unsafe { - Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref())); + Ret(bcx, lib::llvm::llvm::LLVMGetUndef(arg_type_of(ccx, retty).to_ref())); } } else { RetVoid(bcx) diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 91148d31423..87a730dbc79 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -331,7 +331,7 @@ impl<'a, 'b> Reflector<'a, 'b> { Some(llreturn) => Br(bcx, llreturn), None => {} }; - finish_fn(&fcx, bcx); + finish_fn(&fcx, bcx, ty::mk_u64()); llfdecl }; diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 1ec792182bd..b10f6eda880 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -89,7 +89,7 @@ impl Type { } pub fn bool(ccx: &CrateContext) -> Type { - Type::i1(ccx) + Type::i8(ccx) } pub fn char(ccx: &CrateContext) -> Type { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index c26e11134b6..028722071a6 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -31,7 +31,7 @@ pub fn return_uses_outptr(ccx: &CrateContext, ty: ty::t) -> bool { } pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type { - let llty = type_of(ccx, arg_ty); + let llty = arg_type_of(ccx, arg_ty); if arg_is_indirect(ccx, arg_ty) { llty.ptr_to() } else { @@ -46,7 +46,7 @@ pub fn type_of_rust_fn(cx: &CrateContext, has_env: bool, // Arg 0: Output pointer. // (if the output type is non-immediate) let use_out_pointer = return_uses_outptr(cx, output); - let lloutputtype = type_of(cx, output); + let lloutputtype = arg_type_of(cx, output); if use_out_pointer { atys.push(lloutputtype.ptr_to()); } @@ -167,6 +167,14 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { llsizingty } +pub fn arg_type_of(cx: &CrateContext, t: ty::t) -> Type { + if ty::type_is_bool(t) { + Type::i1(cx) + } else { + type_of(cx, t) + } +} + // NB: If you update this, be sure to update `sizing_type_of()` as well. pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { // Check the cache.