Skip to content

Newtype structs as immediates #7543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,13 +996,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;
}

Expand Down Expand Up @@ -1527,7 +1527,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);
Expand Down Expand Up @@ -1566,7 +1566,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 {
Expand Down Expand Up @@ -1672,7 +1672,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);
Expand Down Expand Up @@ -1700,7 +1700,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
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand All @@ -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,
}
Expand Down
38 changes: 16 additions & 22 deletions src/librustc/middle/trans/datum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -508,18 +508,18 @@ 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 {
/*!
*
* 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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
};
Expand Down Expand Up @@ -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
)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 8 additions & 7 deletions src/librustc/middle/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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,
Expand All @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,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 %?",
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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());
Expand Down
19 changes: 16 additions & 3 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1647,9 +1647,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 {
Expand Down Expand Up @@ -3148,7 +3161,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
Expand Down
19 changes: 19 additions & 0 deletions src/test/run-pass/newtype-temporary.rs
Original file line number Diff line number Diff line change
@@ -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);
}