Skip to content

Commit e07e9bb

Browse files
committed
auto merge of #7543 : sanxiyn/rust/newtype-immediates, r=catamorphism
Fix #6612. Rebase of #6725. Fixed an additional bug and added a test.
2 parents dd4f6bb + 8aa26ad commit e07e9bb

File tree

9 files changed

+75
-48
lines changed

9 files changed

+75
-48
lines changed

src/librustc/middle/trans/base.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1014,13 +1014,13 @@ pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
10141014

10151015
pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
10161016
let _icx = push_ctxt("spill_if_immediate");
1017-
if ty::type_is_immediate(t) { return do_spill(cx, v, t); }
1017+
if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
10181018
return v;
10191019
}
10201020

10211021
pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
10221022
let _icx = push_ctxt("load_if_immediate");
1023-
if ty::type_is_immediate(t) { return Load(cx, v); }
1023+
if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
10241024
return v;
10251025
}
10261026

@@ -1545,7 +1545,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
15451545
// slot where the return value of the function must go.
15461546
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
15471547
unsafe {
1548-
if !ty::type_is_immediate(output_type) {
1548+
if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
15491549
llvm::LLVMGetParam(fcx.llfn, 0)
15501550
} else {
15511551
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
@@ -1584,7 +1584,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
15841584
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
15851585
}
15861586
};
1587-
let is_immediate = ty::type_is_immediate(substd_output_type);
1587+
let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);
15881588
let fcx = @mut fn_ctxt_ {
15891589
llfn: llfndecl,
15901590
llenv: unsafe {
@@ -1690,7 +1690,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
16901690
match fcx.llself {
16911691
Some(slf) => {
16921692
let self_val = if slf.is_copy
1693-
&& datum::appropriate_mode(slf.t).is_by_value() {
1693+
&& datum::appropriate_mode(bcx.tcx(), slf.t).is_by_value() {
16941694
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
16951695
let alloc = alloc_ty(bcx, slf.t);
16961696
Store(bcx, tmp, alloc);
@@ -1718,7 +1718,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
17181718
// This alloca should be optimized away by LLVM's mem-to-reg pass in
17191719
// the event it's not truly needed.
17201720
// only by value if immediate:
1721-
let llarg = if datum::appropriate_mode(arg_ty).is_by_value() {
1721+
let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
17221722
let alloc = alloc_ty(bcx, arg_ty);
17231723
Store(bcx, raw_llarg, alloc);
17241724
alloc

src/librustc/middle/trans/callee.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ pub fn trans_call_inner(in_cx: block,
633633

634634
let mut llargs = ~[];
635635

636-
if !ty::type_is_immediate(ret_ty) {
636+
if !ty::type_is_immediate(bcx.tcx(), ret_ty) {
637637
llargs.push(llretslot);
638638
}
639639

@@ -680,7 +680,7 @@ pub fn trans_call_inner(in_cx: block,
680680
// case to ignore instead of invoking the Store
681681
// below into a scratch pointer of a mismatched
682682
// type.
683-
} else if ty::type_is_immediate(ret_ty) {
683+
} else if ty::type_is_immediate(bcx.tcx(), ret_ty) {
684684
let llscratchptr = alloc_ty(bcx, ret_ty);
685685
Store(bcx, llresult, llscratchptr);
686686
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
@@ -694,7 +694,7 @@ pub fn trans_call_inner(in_cx: block,
694694
// If this is an immediate, store into the result location.
695695
// (If this was not an immediate, the result will already be
696696
// directly written into the output slot.)
697-
if ty::type_is_immediate(ret_ty) {
697+
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
698698
Store(bcx, llresult, lldest);
699699
}
700700
}
@@ -898,7 +898,7 @@ pub fn trans_arg_expr(bcx: block,
898898
}
899899
ty::ByCopy => {
900900
if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
901-
arg_datum.appropriate_mode().is_by_ref() {
901+
arg_datum.appropriate_mode(bcx.tcx()).is_by_ref() {
902902
debug!("by copy arg with type %s, storing to scratch",
903903
bcx.ty_to_str(arg_datum.ty));
904904
let scratch = scratch_datum(bcx, arg_datum.ty, false);
@@ -914,7 +914,7 @@ pub fn trans_arg_expr(bcx: block,
914914
scratch.add_clean(bcx);
915915
temp_cleanups.push(scratch.val);
916916

917-
match scratch.appropriate_mode() {
917+
match scratch.appropriate_mode(bcx.tcx()) {
918918
ByValue => val = Load(bcx, scratch.val),
919919
ByRef(_) => val = scratch.val,
920920
}

src/librustc/middle/trans/datum.rs

+16-22
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
188188
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
189189
}
190190

191-
pub fn appropriate_mode(ty: ty::t) -> DatumMode {
191+
pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
192192
/*!
193193
*
194194
* Indicates the "appropriate" mode for this value,
@@ -197,7 +197,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {
197197

198198
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
199199
ByValue
200-
} else if ty::type_is_immediate(ty) {
200+
} else if ty::type_is_immediate(tcx, ty) {
201201
ByValue
202202
} else {
203203
ByRef(RevokeClean)
@@ -508,18 +508,18 @@ impl Datum {
508508
}
509509
}
510510

511-
pub fn appropriate_mode(&self) -> DatumMode {
511+
pub fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
512512
/*! See the `appropriate_mode()` function */
513513

514-
appropriate_mode(self.ty)
514+
appropriate_mode(tcx, self.ty)
515515
}
516516

517517
pub fn to_appropriate_llval(&self, bcx: block) -> ValueRef {
518518
/*!
519519
*
520520
* Yields an llvalue with the `appropriate_mode()`. */
521521

522-
match self.appropriate_mode() {
522+
match self.appropriate_mode(bcx.tcx()) {
523523
ByValue => self.to_value_llval(bcx),
524524
ByRef(_) => self.to_ref_llval(bcx)
525525
}
@@ -530,7 +530,7 @@ impl Datum {
530530
*
531531
* Yields a datum with the `appropriate_mode()`. */
532532

533-
match self.appropriate_mode() {
533+
match self.appropriate_mode(bcx.tcx()) {
534534
ByValue => self.to_value_datum(bcx),
535535
ByRef(_) => self.to_ref_datum(bcx)
536536
}
@@ -657,13 +657,7 @@ impl Datum {
657657
ByValue => {
658658
// Actually, this case cannot happen right
659659
// now, because enums are never immediate.
660-
// But in principle newtype'd immediate
661-
// values should be immediate, and in that
662-
// case the * would be a no-op except for
663-
// changing the type, so I am putting this
664-
// code in place here to do the right
665-
// thing if this change ever goes through.
666-
assert!(ty::type_is_immediate(ty));
660+
assert!(ty::type_is_immediate(bcx.tcx(), ty));
667661
(Some(Datum {ty: ty, ..*self}), bcx)
668662
}
669663
};
@@ -695,15 +689,15 @@ impl Datum {
695689
)
696690
}
697691
ByValue => {
698-
// Actually, this case cannot happen right now,
699-
// because structs are never immediate. But in
700-
// principle, newtype'd immediate values should be
701-
// immediate, and in that case the * would be a no-op
702-
// except for changing the type, so I am putting this
703-
// code in place here to do the right thing if this
704-
// change ever goes through.
705-
assert!(ty::type_is_immediate(ty));
706-
(Some(Datum {ty: ty, ..*self}), bcx)
692+
assert!(ty::type_is_immediate(bcx.tcx(), ty));
693+
(
694+
Some(Datum {
695+
val: ExtractValue(bcx, self.val, 0),
696+
ty: ty,
697+
mode: ByValue
698+
}),
699+
bcx
700+
)
707701
}
708702
}
709703
}

src/librustc/middle/trans/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
291291
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
292292
let scratch = scratch_datum(bcx, closure_ty, false);
293293
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
294-
assert_eq!(datum.appropriate_mode(), ByValue);
294+
assert_eq!(datum.appropriate_mode(tcx), ByValue);
295295
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
296296
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
297297
Store(bcx, base::null_env_ptr(bcx), llenv);

src/librustc/middle/trans/foreign.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
103103
LlvmSignature {
104104
llarg_tys: llarg_tys,
105105
llret_ty: llret_ty,
106-
sret: !ty::type_is_immediate(fn_sig.output),
106+
sret: !ty::type_is_immediate(ccx.tcx, fn_sig.output),
107107
}
108108
}
109109

@@ -192,7 +192,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
192192

193193
// Patch up the return type if it's not immediate and we're returning via
194194
// the C ABI.
195-
if needs_c_return && !ty::type_is_immediate(tys.fn_sig.output) {
195+
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
196196
let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
197197
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
198198
lloutputtype));
@@ -648,7 +648,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
648648
// intrinsics, there are no argument cleanups to
649649
// concern ourselves with.
650650
let tp_ty = substs.tys[0];
651-
let mode = appropriate_mode(tp_ty);
651+
let mode = appropriate_mode(ccx.tcx, tp_ty);
652652
let src = Datum {val: get_param(decl, first_real_arg + 1u),
653653
ty: tp_ty, mode: mode};
654654
bcx = src.move_to(bcx, DROP_EXISTING,
@@ -657,7 +657,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
657657
"move_val_init" => {
658658
// See comments for `"move_val"`.
659659
let tp_ty = substs.tys[0];
660-
let mode = appropriate_mode(tp_ty);
660+
let mode = appropriate_mode(ccx.tcx, tp_ty);
661661
let src = Datum {val: get_param(decl, first_real_arg + 1u),
662662
ty: tp_ty, mode: mode};
663663
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
@@ -731,7 +731,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
731731
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
732732

733733
let llsrcval = get_param(decl, first_real_arg);
734-
let llsrcptr = if ty::type_is_immediate(in_type) {
734+
let llsrcptr = if ty::type_is_immediate(ccx.tcx, in_type) {
735735
let llsrcptr = alloca(bcx, llintype);
736736
Store(bcx, llsrcval, llsrcptr);
737737
llsrcptr
@@ -1221,7 +1221,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
12211221
let mut i = 0u;
12221222
let n = tys.fn_sig.inputs.len();
12231223

1224-
if !ty::type_is_immediate(tys.fn_sig.output) {
1224+
if !ty::type_is_immediate(bcx.tcx(), tys.fn_sig.output) {
12251225
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
12261226
llargvals.push(llretptr);
12271227
}
@@ -1247,7 +1247,8 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
12471247
shim_types: &ShimTypes,
12481248
llargbundle: ValueRef,
12491249
llretval: ValueRef) {
1250-
if bcx.fcx.llretptr.is_some() && ty::type_is_immediate(shim_types.fn_sig.output) {
1250+
if bcx.fcx.llretptr.is_some() &&
1251+
ty::type_is_immediate(bcx.tcx(), shim_types.fn_sig.output) {
12511252
// Write the value into the argument bundle.
12521253
let arg_count = shim_types.fn_sig.inputs.len();
12531254
let llretptr = load_inbounds(bcx,

src/librustc/middle/trans/monomorphize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ pub fn make_mono_id(ccx: @mut CrateContext,
356356
let llty = type_of::type_of(ccx, subst);
357357
let size = machine::llbitsize_of_real(ccx, llty);
358358
let align = machine::llalign_of_min(ccx, llty);
359-
let mode = datum::appropriate_mode(subst);
359+
let mode = datum::appropriate_mode(ccx.tcx, subst);
360360
let data_class = mono_data_classify(subst);
361361

362362
debug!("make_mono_id: type %s -> size %u align %u mode %? class %?",

src/librustc/middle/trans/type_of.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use middle::trans::type_::Type;
1818

1919
use syntax::ast;
2020

21-
pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
22-
!ty::type_is_immediate(*arg_ty)
21+
pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: &ty::t) -> bool {
22+
!ty::type_is_immediate(ccx.tcx, *arg_ty)
2323
}
2424

2525
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> Type {
@@ -41,7 +41,7 @@ pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t) -> Typ
4141

4242
// Arg 0: Output pointer.
4343
// (if the output type is non-immediate)
44-
let output_is_immediate = ty::type_is_immediate(output);
44+
let output_is_immediate = ty::type_is_immediate(cx.tcx, output);
4545
let lloutputtype = type_of(cx, output);
4646
if !output_is_immediate {
4747
atys.push(lloutputtype.ptr_to());

src/librustc/middle/ty.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -1646,9 +1646,22 @@ pub fn type_is_scalar(ty: t) -> bool {
16461646
}
16471647
}
16481648

1649-
pub fn type_is_immediate(ty: t) -> bool {
1649+
fn type_is_newtype_immediate(cx: ctxt, ty: t) -> bool {
1650+
match get(ty).sty {
1651+
ty_struct(def_id, ref substs) => {
1652+
let fields = struct_fields(cx, def_id, substs);
1653+
fields.len() == 1 &&
1654+
fields[0].ident == token::special_idents::unnamed_field &&
1655+
type_is_immediate(cx, fields[0].mt.ty)
1656+
}
1657+
_ => false
1658+
}
1659+
}
1660+
1661+
pub fn type_is_immediate(cx: ctxt, ty: t) -> bool {
16501662
return type_is_scalar(ty) || type_is_boxed(ty) ||
1651-
type_is_unique(ty) || type_is_region_ptr(ty);
1663+
type_is_unique(ty) || type_is_region_ptr(ty) ||
1664+
type_is_newtype_immediate(cx, ty);
16521665
}
16531666

16541667
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
@@ -3147,7 +3160,7 @@ pub fn expr_kind(tcx: ctxt,
31473160
ast::expr_cast(*) => {
31483161
match tcx.node_types.find(&(expr.id as uint)) {
31493162
Some(&t) => {
3150-
if ty::type_is_immediate(t) {
3163+
if ty::type_is_immediate(tcx, t) {
31513164
RvalueDatumExpr
31523165
} else {
31533166
RvalueDpsExpr
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo(uint);
12+
13+
fn foo() -> Foo {
14+
Foo(42)
15+
}
16+
17+
fn main() {
18+
assert_eq!(*foo(), 42);
19+
}

0 commit comments

Comments
 (0)