Skip to content

Commit 14b0abf

Browse files
committed
Consider all zero-sized data structures to be voidish, bypassing some "quirky" parts of LLVM (see e.g. LLVM bug 9900) but also generating better code
1 parent 7ff6b09 commit 14b0abf

File tree

9 files changed

+37
-32
lines changed

9 files changed

+37
-32
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ pub fn init_function<'a>(
13201320
}
13211321
};
13221322

1323-
if !ty::type_is_voidish(fcx.ccx.tcx, substd_output_type) {
1323+
if !type_is_voidish(fcx.ccx, substd_output_type) {
13241324
// If the function returns nil/bot, there is no real return
13251325
// value, so do not set `llretptr`.
13261326
if !skip_retptr || fcx.caller_expects_out_pointer {
@@ -1539,7 +1539,7 @@ pub fn trans_closure(ccx: @CrateContext,
15391539
// translation calls that don't have a return value (trans_crate,
15401540
// trans_mod, trans_item, et cetera) and those that do
15411541
// (trans_block, trans_expr, et cetera).
1542-
if body.expr.is_none() || ty::type_is_voidish(bcx.tcx(), block_ty) {
1542+
if body.expr.is_none() || type_is_voidish(bcx.ccx(), block_ty) {
15431543
bcx = controlflow::trans_block(bcx, body, expr::Ignore);
15441544
} else {
15451545
let dest = expr::SaveIn(fcx.llretptr.get().unwrap());
@@ -1679,15 +1679,17 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
16791679

16801680
let bcx = fcx.entry_bcx.get().unwrap();
16811681

1682-
let repr = adt::represent_type(ccx, result_ty);
1683-
adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
1684-
for (i, arg_datum) in arg_datums.move_iter().enumerate() {
1685-
let lldestptr = adt::trans_field_ptr(bcx,
1686-
repr,
1687-
fcx.llretptr.get().unwrap(),
1688-
disr,
1689-
i);
1690-
arg_datum.store_to(bcx, lldestptr);
1682+
if !type_is_voidish(fcx.ccx, result_ty) {
1683+
let repr = adt::represent_type(ccx, result_ty);
1684+
adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
1685+
for (i, arg_datum) in arg_datums.move_iter().enumerate() {
1686+
let lldestptr = adt::trans_field_ptr(bcx,
1687+
repr,
1688+
fcx.llretptr.get().unwrap(),
1689+
disr,
1690+
i);
1691+
arg_datum.store_to(bcx, lldestptr);
1692+
}
16911693
}
16921694

16931695
finish_fn(&fcx, bcx);

src/librustc/middle/trans/callee.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,6 @@ pub fn trans_call_inner<'a>(
623623
// scope will ever execute.
624624
let fcx = bcx.fcx;
625625
let ccx = fcx.ccx;
626-
let tcx = ccx.tcx;
627626
let arg_cleanup_scope = fcx.push_custom_cleanup_scope();
628627

629628
let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope));
@@ -668,12 +667,11 @@ pub fn trans_call_inner<'a>(
668667
}
669668
Some(expr::SaveIn(dst)) => Some(dst),
670669
Some(expr::Ignore) => {
671-
if !ty::type_is_voidish(tcx, ret_ty) {
670+
if !type_is_voidish(ccx, ret_ty) {
672671
Some(alloc_ty(bcx, ret_ty, "__llret"))
673672
} else {
674-
unsafe {
675-
Some(llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()))
676-
}
673+
let llty = type_of::type_of(ccx, ret_ty);
674+
Some(C_undef(llty.ptr_to()))
677675
}
678676
}
679677
};
@@ -738,7 +736,7 @@ pub fn trans_call_inner<'a>(
738736
match opt_llretslot {
739737
Some(llretslot) => {
740738
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
741-
!ty::type_is_voidish(bcx.tcx(), ret_ty)
739+
!type_is_voidish(bcx.ccx(), ret_ty)
742740
{
743741
Store(bcx, llret, llretslot);
744742
}

src/librustc/middle/trans/common.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
7979
}
8080
}
8181

82+
pub fn type_is_voidish(ccx: &CrateContext, ty: ty::t) -> bool {
83+
//! Identify types like `()`, bottom, or empty structs, which
84+
//! contain no information at all.
85+
use middle::trans::machine::llsize_of_alloc;
86+
use middle::trans::type_of::sizing_type_of;
87+
let llty = sizing_type_of(ccx, ty);
88+
llsize_of_alloc(ccx, llty) == 0
89+
}
90+
8291
pub fn gensym_name(name: &str) -> (Ident, PathElem) {
8392
let name = token::gensym(name);
8493
let ident = Ident::new(name);

src/librustc/middle/trans/datum.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode {
171171
* on whether type is immediate or not.
172172
*/
173173

174-
if ty::type_is_voidish(ccx.tcx, ty) {
174+
if type_is_voidish(ccx, ty) {
175175
ByValue
176176
} else if type_is_immediate(ccx, ty) {
177177
ByValue
@@ -583,8 +583,8 @@ fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
583583
* what we are loading.
584584
*/
585585

586-
if ty::type_is_voidish(bcx.tcx(), ty) {
587-
C_nil()
586+
if type_is_voidish(bcx.ccx(), ty) {
587+
C_undef(type_of::type_of(bcx.ccx(), ty))
588588
} else if ty::type_is_bool(ty) {
589589
LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::True)
590590
} else {
@@ -638,7 +638,7 @@ impl<K:KindOps> Datum<K> {
638638

639639
let _icx = push_ctxt("copy_to_no_check");
640640

641-
if ty::type_is_voidish(bcx.tcx(), self.ty) {
641+
if type_is_voidish(bcx.ccx(), self.ty) {
642642
return bcx;
643643
}
644644

src/librustc/middle/trans/expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ fn trans_unadjusted<'a>(bcx: &'a Block<'a>,
474474

475475
ty::RvalueDpsExpr => {
476476
let ty = expr_ty(bcx, expr);
477-
if ty::type_is_voidish(bcx.tcx(), ty) {
477+
if type_is_voidish(bcx.ccx(), ty) {
478478
bcx = trans_rvalue_dps_unadjusted(bcx, expr, Ignore);
479479
nil(bcx, ty)
480480
} else {
@@ -500,7 +500,8 @@ fn trans_unadjusted<'a>(bcx: &'a Block<'a>,
500500
};
501501

502502
fn nil<'a>(bcx: &'a Block<'a>, ty: ty::t) -> DatumBlock<'a, Expr> {
503-
let datum = immediate_rvalue(C_nil(), ty);
503+
let llval = C_undef(type_of::type_of(bcx.ccx(), ty));
504+
let datum = immediate_rvalue(llval, ty);
504505
DatumBlock(bcx, datum.to_expr_datum())
505506
}
506507
}

src/librustc/middle/trans/foreign.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub fn trans_native_call<'a>(
198198
_ => ccx.sess.bug("trans_native_call called on non-function type")
199199
};
200200
let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys);
201-
let ret_def = !ty::type_is_voidish(bcx.tcx(), fn_sig.output);
201+
let ret_def = !type_is_voidish(bcx.ccx(), fn_sig.output);
202202
let fn_type = cabi::compute_abi_info(ccx,
203203
llsig.llarg_tys,
204204
llsig.llret_ty,
@@ -778,7 +778,7 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext,
778778
_ => ccx.sess.bug("foreign_types_for_fn_ty called on non-function type")
779779
};
780780
let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs);
781-
let ret_def = !ty::type_is_voidish(ccx.tcx, fn_sig.output);
781+
let ret_def = !type_is_voidish(ccx, fn_sig.output);
782782
let fn_ty = cabi::compute_abi_info(ccx,
783783
llsig.llarg_tys,
784784
llsig.llret_ty,

src/librustc/middle/trans/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
356356
pluralize(out_type_size)));
357357
}
358358

359-
if !ty::type_is_voidish(ccx.tcx, out_type) {
359+
if !type_is_voidish(ccx, out_type) {
360360
let llsrcval = get_param(decl, first_real_arg);
361361
if type_is_immediate(ccx, in_type) {
362362
match fcx.llretptr.get() {

src/librustc/middle/trans/type_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn type_of_rust_fn(cx: &CrateContext,
6868
atys.push_all(type_of_explicit_args(cx, inputs));
6969

7070
// Use the output as the actual return value if it's immediate.
71-
if !use_out_pointer && !ty::type_is_voidish(cx.tcx, output) {
71+
if !use_out_pointer && !type_is_voidish(cx, output) {
7272
Type::func(atys, &lloutputtype)
7373
} else {
7474
Type::func(atys, &Type::void())

src/librustc/middle/ty.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,11 +1455,6 @@ pub fn subst(cx: ctxt,
14551455

14561456
// Type utilities
14571457

1458-
pub fn type_is_voidish(tcx: ctxt, ty: t) -> bool {
1459-
//! "nil" and "bot" are void types in that they represent 0 bits of information
1460-
type_is_nil(ty) || type_is_bot(ty) || type_is_empty(tcx, ty)
1461-
}
1462-
14631458
pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
14641459

14651460
pub fn type_is_bot(ty: t) -> bool {

0 commit comments

Comments
 (0)