auto merge of #7543 : sanxiyn/rust/newtype-immediates, r=catamorphism
Fix #6612. Rebase of #6725. Fixed an additional bug and added a test.
This commit is contained in:
commit
e07e9bbf36
9 changed files with 75 additions and 48 deletions
|
|
@ -1014,13 +1014,13 @@ pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
|
|||
|
||||
pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||
let _icx = push_ctxt("spill_if_immediate");
|
||||
if ty::type_is_immediate(t) { return do_spill(cx, v, t); }
|
||||
if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
|
||||
return v;
|
||||
}
|
||||
|
||||
pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||
let _icx = push_ctxt("load_if_immediate");
|
||||
if ty::type_is_immediate(t) { return Load(cx, v); }
|
||||
if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
@ -1545,7 +1545,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
|
|||
// slot where the return value of the function must go.
|
||||
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
|
||||
unsafe {
|
||||
if !ty::type_is_immediate(output_type) {
|
||||
if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
|
||||
llvm::LLVMGetParam(fcx.llfn, 0)
|
||||
} else {
|
||||
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
||||
|
|
@ -1584,7 +1584,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
|||
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
|
||||
}
|
||||
};
|
||||
let is_immediate = ty::type_is_immediate(substd_output_type);
|
||||
let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);
|
||||
let fcx = @mut fn_ctxt_ {
|
||||
llfn: llfndecl,
|
||||
llenv: unsafe {
|
||||
|
|
@ -1690,7 +1690,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
|||
match fcx.llself {
|
||||
Some(slf) => {
|
||||
let self_val = if slf.is_copy
|
||||
&& datum::appropriate_mode(slf.t).is_by_value() {
|
||||
&& datum::appropriate_mode(bcx.tcx(), slf.t).is_by_value() {
|
||||
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
|
||||
let alloc = alloc_ty(bcx, slf.t);
|
||||
Store(bcx, tmp, alloc);
|
||||
|
|
@ -1718,7 +1718,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
|
|||
// 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(arg_ty).is_by_value() {
|
||||
let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
|
||||
let alloc = alloc_ty(bcx, arg_ty);
|
||||
Store(bcx, raw_llarg, alloc);
|
||||
alloc
|
||||
|
|
|
|||
|
|
@ -633,7 +633,7 @@ pub fn trans_call_inner(in_cx: block,
|
|||
|
||||
let mut llargs = ~[];
|
||||
|
||||
if !ty::type_is_immediate(ret_ty) {
|
||||
if !ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||
llargs.push(llretslot);
|
||||
}
|
||||
|
||||
|
|
@ -680,7 +680,7 @@ pub fn trans_call_inner(in_cx: block,
|
|||
// case to ignore instead of invoking the Store
|
||||
// below into a scratch pointer of a mismatched
|
||||
// type.
|
||||
} else if ty::type_is_immediate(ret_ty) {
|
||||
} else if ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||
let llscratchptr = alloc_ty(bcx, ret_ty);
|
||||
Store(bcx, llresult, llscratchptr);
|
||||
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
|
||||
|
|
@ -694,7 +694,7 @@ pub fn trans_call_inner(in_cx: block,
|
|||
// If this is an immediate, store into the result location.
|
||||
// (If this was not an immediate, the result will already be
|
||||
// directly written into the output slot.)
|
||||
if ty::type_is_immediate(ret_ty) {
|
||||
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
|
||||
Store(bcx, llresult, lldest);
|
||||
}
|
||||
}
|
||||
|
|
@ -898,7 +898,7 @@ pub fn trans_arg_expr(bcx: block,
|
|||
}
|
||||
ty::ByCopy => {
|
||||
if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
|
||||
arg_datum.appropriate_mode().is_by_ref() {
|
||||
arg_datum.appropriate_mode(bcx.tcx()).is_by_ref() {
|
||||
debug!("by copy arg with type %s, storing to scratch",
|
||||
bcx.ty_to_str(arg_datum.ty));
|
||||
let scratch = scratch_datum(bcx, arg_datum.ty, false);
|
||||
|
|
@ -914,7 +914,7 @@ pub fn trans_arg_expr(bcx: block,
|
|||
scratch.add_clean(bcx);
|
||||
temp_cleanups.push(scratch.val);
|
||||
|
||||
match scratch.appropriate_mode() {
|
||||
match scratch.appropriate_mode(bcx.tcx()) {
|
||||
ByValue => val = Load(bcx, scratch.val),
|
||||
ByRef(_) => val = scratch.val,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
|
|||
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
|
||||
}
|
||||
|
||||
pub fn appropriate_mode(ty: ty::t) -> DatumMode {
|
||||
pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
|
||||
/*!
|
||||
*
|
||||
* Indicates the "appropriate" mode for this value,
|
||||
|
|
@ -197,7 +197,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {
|
|||
|
||||
if ty::type_is_nil(ty) || ty::type_is_bot(ty) {
|
||||
ByValue
|
||||
} else if ty::type_is_immediate(ty) {
|
||||
} else if ty::type_is_immediate(tcx, ty) {
|
||||
ByValue
|
||||
} else {
|
||||
ByRef(RevokeClean)
|
||||
|
|
@ -508,10 +508,10 @@ impl Datum {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn appropriate_mode(&self) -> DatumMode {
|
||||
pub fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
|
||||
/*! See the `appropriate_mode()` function */
|
||||
|
||||
appropriate_mode(self.ty)
|
||||
appropriate_mode(tcx, self.ty)
|
||||
}
|
||||
|
||||
pub fn to_appropriate_llval(&self, bcx: block) -> ValueRef {
|
||||
|
|
@ -519,7 +519,7 @@ impl Datum {
|
|||
*
|
||||
* Yields an llvalue with the `appropriate_mode()`. */
|
||||
|
||||
match self.appropriate_mode() {
|
||||
match self.appropriate_mode(bcx.tcx()) {
|
||||
ByValue => self.to_value_llval(bcx),
|
||||
ByRef(_) => self.to_ref_llval(bcx)
|
||||
}
|
||||
|
|
@ -530,7 +530,7 @@ impl Datum {
|
|||
*
|
||||
* Yields a datum with the `appropriate_mode()`. */
|
||||
|
||||
match self.appropriate_mode() {
|
||||
match self.appropriate_mode(bcx.tcx()) {
|
||||
ByValue => self.to_value_datum(bcx),
|
||||
ByRef(_) => self.to_ref_datum(bcx)
|
||||
}
|
||||
|
|
@ -657,13 +657,7 @@ impl Datum {
|
|||
ByValue => {
|
||||
// Actually, this case cannot happen right
|
||||
// now, because enums are never immediate.
|
||||
// But in principle newtype'd immediate
|
||||
// values should be immediate, and in that
|
||||
// case the * would be a no-op except for
|
||||
// changing the type, so I am putting this
|
||||
// code in place here to do the right
|
||||
// thing if this change ever goes through.
|
||||
assert!(ty::type_is_immediate(ty));
|
||||
assert!(ty::type_is_immediate(bcx.tcx(), ty));
|
||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
||||
}
|
||||
};
|
||||
|
|
@ -695,15 +689,15 @@ impl Datum {
|
|||
)
|
||||
}
|
||||
ByValue => {
|
||||
// Actually, this case cannot happen right now,
|
||||
// because structs are never immediate. But in
|
||||
// principle, newtype'd immediate values should be
|
||||
// immediate, and in that case the * would be a no-op
|
||||
// except for changing the type, so I am putting this
|
||||
// code in place here to do the right thing if this
|
||||
// change ever goes through.
|
||||
assert!(ty::type_is_immediate(ty));
|
||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
||||
assert!(ty::type_is_immediate(bcx.tcx(), ty));
|
||||
(
|
||||
Some(Datum {
|
||||
val: ExtractValue(bcx, self.val, 0),
|
||||
ty: ty,
|
||||
mode: ByValue
|
||||
}),
|
||||
bcx
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
|
||||
let scratch = scratch_datum(bcx, closure_ty, false);
|
||||
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
|
||||
assert_eq!(datum.appropriate_mode(), ByValue);
|
||||
assert_eq!(datum.appropriate_mode(tcx), 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), llenv);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
|
|||
LlvmSignature {
|
||||
llarg_tys: llarg_tys,
|
||||
llret_ty: llret_ty,
|
||||
sret: !ty::type_is_immediate(fn_sig.output),
|
||||
sret: !ty::type_is_immediate(ccx.tcx, fn_sig.output),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
|||
|
||||
// Patch up the return type if it's not immediate and we're returning via
|
||||
// the C ABI.
|
||||
if needs_c_return && !ty::type_is_immediate(tys.fn_sig.output) {
|
||||
if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
|
||||
let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
|
||||
fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
|
||||
lloutputtype));
|
||||
|
|
@ -648,7 +648,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(tp_ty);
|
||||
let mode = appropriate_mode(ccx.tcx, 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,
|
||||
|
|
@ -657,7 +657,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(tp_ty);
|
||||
let mode = appropriate_mode(ccx.tcx, 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));
|
||||
|
|
@ -731,7 +731,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
|
||||
|
||||
let llsrcval = get_param(decl, first_real_arg);
|
||||
let llsrcptr = if ty::type_is_immediate(in_type) {
|
||||
let llsrcptr = if ty::type_is_immediate(ccx.tcx, in_type) {
|
||||
let llsrcptr = alloca(bcx, llintype);
|
||||
Store(bcx, llsrcval, llsrcptr);
|
||||
llsrcptr
|
||||
|
|
@ -1221,7 +1221,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
|||
let mut i = 0u;
|
||||
let n = tys.fn_sig.inputs.len();
|
||||
|
||||
if !ty::type_is_immediate(tys.fn_sig.output) {
|
||||
if !ty::type_is_immediate(bcx.tcx(), tys.fn_sig.output) {
|
||||
let llretptr = load_inbounds(bcx, llargbundle, [0u, n]);
|
||||
llargvals.push(llretptr);
|
||||
}
|
||||
|
|
@ -1247,7 +1247,8 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
|||
shim_types: &ShimTypes,
|
||||
llargbundle: ValueRef,
|
||||
llretval: ValueRef) {
|
||||
if bcx.fcx.llretptr.is_some() && ty::type_is_immediate(shim_types.fn_sig.output) {
|
||||
if bcx.fcx.llretptr.is_some() &&
|
||||
ty::type_is_immediate(bcx.tcx(), shim_types.fn_sig.output) {
|
||||
// Write the value into the argument bundle.
|
||||
let arg_count = shim_types.fn_sig.inputs.len();
|
||||
let llretptr = load_inbounds(bcx,
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ pub fn make_mono_id(ccx: @mut CrateContext,
|
|||
let llty = type_of::type_of(ccx, subst);
|
||||
let size = machine::llbitsize_of_real(ccx, llty);
|
||||
let align = machine::llalign_of_min(ccx, llty);
|
||||
let mode = datum::appropriate_mode(subst);
|
||||
let mode = datum::appropriate_mode(ccx.tcx, subst);
|
||||
let data_class = mono_data_classify(subst);
|
||||
|
||||
debug!("make_mono_id: type %s -> size %u align %u mode %? class %?",
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ use middle::trans::type_::Type;
|
|||
|
||||
use syntax::ast;
|
||||
|
||||
pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
|
||||
!ty::type_is_immediate(*arg_ty)
|
||||
pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: &ty::t) -> bool {
|
||||
!ty::type_is_immediate(ccx.tcx, *arg_ty)
|
||||
}
|
||||
|
||||
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
|
|||
|
||||
// Arg 0: Output pointer.
|
||||
// (if the output type is non-immediate)
|
||||
let output_is_immediate = ty::type_is_immediate(output);
|
||||
let output_is_immediate = ty::type_is_immediate(cx.tcx, output);
|
||||
let lloutputtype = type_of(cx, output);
|
||||
if !output_is_immediate {
|
||||
atys.push(lloutputtype.ptr_to());
|
||||
|
|
|
|||
|
|
@ -1646,9 +1646,22 @@ pub fn type_is_scalar(ty: t) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn type_is_immediate(ty: t) -> bool {
|
||||
fn type_is_newtype_immediate(cx: ctxt, ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_struct(def_id, ref substs) => {
|
||||
let fields = struct_fields(cx, def_id, substs);
|
||||
fields.len() == 1 &&
|
||||
fields[0].ident == token::special_idents::unnamed_field &&
|
||||
type_is_immediate(cx, fields[0].mt.ty)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_immediate(cx: ctxt, ty: t) -> bool {
|
||||
return type_is_scalar(ty) || type_is_boxed(ty) ||
|
||||
type_is_unique(ty) || type_is_region_ptr(ty);
|
||||
type_is_unique(ty) || type_is_region_ptr(ty) ||
|
||||
type_is_newtype_immediate(cx, ty);
|
||||
}
|
||||
|
||||
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
||||
|
|
@ -3147,7 +3160,7 @@ pub fn expr_kind(tcx: ctxt,
|
|||
ast::expr_cast(*) => {
|
||||
match tcx.node_types.find(&(expr.id as uint)) {
|
||||
Some(&t) => {
|
||||
if ty::type_is_immediate(t) {
|
||||
if ty::type_is_immediate(tcx, t) {
|
||||
RvalueDatumExpr
|
||||
} else {
|
||||
RvalueDpsExpr
|
||||
|
|
|
|||
19
src/test/run-pass/newtype-temporary.rs
Normal file
19
src/test/run-pass/newtype-temporary.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Foo(uint);
|
||||
|
||||
fn foo() -> Foo {
|
||||
Foo(42)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(*foo(), 42);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue