From 5e7657fafb62b81eb68cb63b2a42e7b77ab9fce6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 16 Jan 2014 19:10:17 -0500 Subject: [PATCH] Distinguish zero-size types from those that we return as void --- src/librustc/middle/trans/base.rs | 6 +++--- src/librustc/middle/trans/callee.rs | 4 ++-- src/librustc/middle/trans/common.rs | 22 ++++++++++++++++++---- src/librustc/middle/trans/datum.rs | 6 +++--- src/librustc/middle/trans/expr.rs | 2 +- src/librustc/middle/trans/foreign.rs | 4 ++-- src/librustc/middle/trans/intrinsic.rs | 4 ++-- src/librustc/middle/trans/type_of.rs | 6 +++--- 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f908732ea0ad6..ef40629946df0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1320,7 +1320,7 @@ pub fn init_function<'a>( } }; - if !type_is_voidish(fcx.ccx, substd_output_type) { + if !return_type_is_void(fcx.ccx, substd_output_type) { // If the function returns nil/bot, there is no real return // value, so do not set `llretptr`. if !skip_retptr || fcx.caller_expects_out_pointer { @@ -1539,7 +1539,7 @@ pub fn trans_closure(ccx: @CrateContext, // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - if body.expr.is_none() || type_is_voidish(bcx.ccx(), block_ty) { + if body.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { let dest = expr::SaveIn(fcx.llretptr.get().unwrap()); @@ -1679,7 +1679,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext, let bcx = fcx.entry_bcx.get().unwrap(); - if !type_is_voidish(fcx.ccx, result_ty) { + if !type_is_zero_size(fcx.ccx, result_ty) { let repr = adt::represent_type(ccx, result_ty); adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr); for (i, arg_datum) in arg_datums.move_iter().enumerate() { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 7cc80318f872f..27903e74e07a5 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -667,7 +667,7 @@ pub fn trans_call_inner<'a>( } Some(expr::SaveIn(dst)) => Some(dst), Some(expr::Ignore) => { - if !type_is_voidish(ccx, ret_ty) { + if !type_is_zero_size(ccx, ret_ty) { Some(alloc_ty(bcx, ret_ty, "__llret")) } else { let llty = type_of::type_of(ccx, ret_ty); @@ -736,7 +736,7 @@ pub fn trans_call_inner<'a>( match opt_llretslot { Some(llretslot) => { if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) && - !type_is_voidish(bcx.ccx(), ret_ty) + !type_is_zero_size(bcx.ccx(), ret_ty) { Store(bcx, llret, llretslot); } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 90083541e4267..e466e4da38d72 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -75,19 +75,33 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool { let llty = sizing_type_of(ccx, ty); llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type) } - _ => type_is_voidish(ccx, ty) + _ => type_is_zero_size(ccx, ty) } } -pub fn type_is_voidish(ccx: &CrateContext, ty: ty::t) -> bool { - //! Identify types like `()`, bottom, or empty structs, which - //! contain no information at all. +pub fn type_is_zero_size(ccx: &CrateContext, ty: ty::t) -> bool { + /*! + * Identify types which have size zero at runtime. + */ + use middle::trans::machine::llsize_of_alloc; use middle::trans::type_of::sizing_type_of; let llty = sizing_type_of(ccx, ty); llsize_of_alloc(ccx, llty) == 0 } +pub fn return_type_is_void(ccx: &CrateContext, ty: ty::t) -> bool { + /*! + * Identifies types which we declare to be equivalent to `void` + * in C for the purpose of function return types. These are + * `()`, bot, and uninhabited enums. Note that all such types + * are also zero-size, but not all zero-size types use a `void` + * return type (in order to aid with C ABI compatibility). + */ + + ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx, ty) +} + pub fn gensym_name(name: &str) -> (Ident, PathElem) { let name = token::gensym(name); let ident = Ident::new(name); diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 624ff5f6ba18f..467501449b8d5 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -171,7 +171,7 @@ pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode { * on whether type is immediate or not. */ - if type_is_voidish(ccx, ty) { + if type_is_zero_size(ccx, ty) { ByValue } else if type_is_immediate(ccx, ty) { ByValue @@ -583,7 +583,7 @@ fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef { * what we are loading. */ - if type_is_voidish(bcx.ccx(), ty) { + if type_is_zero_size(bcx.ccx(), ty) { C_undef(type_of::type_of(bcx.ccx(), ty)) } else if ty::type_is_bool(ty) { LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::True) @@ -638,7 +638,7 @@ impl Datum { let _icx = push_ctxt("copy_to_no_check"); - if type_is_voidish(bcx.ccx(), self.ty) { + if type_is_zero_size(bcx.ccx(), self.ty) { return bcx; } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 9ae8280428d63..36fc927b64c45 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -474,7 +474,7 @@ fn trans_unadjusted<'a>(bcx: &'a Block<'a>, ty::RvalueDpsExpr => { let ty = expr_ty(bcx, expr); - if type_is_voidish(bcx.ccx(), ty) { + if type_is_zero_size(bcx.ccx(), ty) { bcx = trans_rvalue_dps_unadjusted(bcx, expr, Ignore); nil(bcx, ty) } else { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 9ba05352b3416..083a1c6988d83 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -198,7 +198,7 @@ pub fn trans_native_call<'a>( _ => ccx.sess.bug("trans_native_call called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys); - let ret_def = !type_is_voidish(bcx.ccx(), fn_sig.output); + let ret_def = !return_type_is_void(bcx.ccx(), fn_sig.output); let fn_type = cabi::compute_abi_info(ccx, llsig.llarg_tys, llsig.llret_ty, @@ -778,7 +778,7 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext, _ => ccx.sess.bug("foreign_types_for_fn_ty called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs); - let ret_def = !type_is_voidish(ccx, fn_sig.output); + let ret_def = !return_type_is_void(ccx, fn_sig.output); let fn_ty = cabi::compute_abi_info(ccx, llsig.llarg_tys, llsig.llret_ty, diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index b15377386465d..1fc749bb6876f 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -317,7 +317,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, "uninit" => { // Do nothing, this is effectively a no-op let retty = substs.tys[0]; - if type_is_immediate(ccx, retty) && !type_is_voidish(ccx, retty) { + 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())); } @@ -356,7 +356,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, pluralize(out_type_size))); } - if !type_is_voidish(ccx, out_type) { + if !return_type_is_void(ccx, out_type) { let llsrcval = get_param(decl, first_real_arg); if type_is_immediate(ccx, in_type) { match fcx.llretptr.get() { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 3aab6d5161911..4db89fbeccec7 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -68,10 +68,10 @@ pub fn type_of_rust_fn(cx: &CrateContext, atys.push_all(type_of_explicit_args(cx, inputs)); // Use the output as the actual return value if it's immediate. - if !use_out_pointer && !type_is_voidish(cx, output) { - Type::func(atys, &lloutputtype) - } else { + if use_out_pointer || return_type_is_void(cx, output) { Type::func(atys, &Type::void()) + } else { + Type::func(atys, &lloutputtype) } }