diff options
| author | Luqman Aden <me@luqman.ca> | 2014-07-09 20:09:57 -0700 |
|---|---|---|
| committer | Luqman Aden <me@luqman.ca> | 2014-07-09 20:11:40 -0700 |
| commit | 83122af6ca01a6379a53e92630ed2c4eb2d07e2d (patch) | |
| tree | f798fd0d3670eb8351256a78153ba527eb0e1ab6 | |
| parent | 8fa30065aa08503b4365abec62f56ce4f492ab57 (diff) | |
| download | rust-83122af6ca01a6379a53e92630ed2c4eb2d07e2d.tar.gz rust-83122af6ca01a6379a53e92630ed2c4eb2d07e2d.zip | |
librustc: Translate input for transmute directly into dest.
| -rw-r--r-- | src/librustc/middle/trans/intrinsic.rs | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index ac8af182f23..309c700bfe8 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -10,8 +10,7 @@ #![allow(non_uppercase_pattern_statics)] -use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg}; -use lib::llvm::{ValueRef, Pointer, Array, Struct}; +use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg, ValueRef}; use lib; use middle::subst; use middle::subst::FnSpace; @@ -137,6 +136,47 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, _ => fail!("expected bare_fn in trans_intrinsic_call") }; let llret_ty = type_of::type_of(ccx, ret_ty); + let foreign_item = tcx.map.expect_foreign_item(node); + let name = token::get_ident(foreign_item.ident); + + // For `transmute` we can just trans the input expr directly into dest + if name.get() == "transmute" { + match args { + callee::ArgExprs(arg_exprs) => { + assert_eq!(arg_exprs.len(), 1); + + let (in_type, out_type) = (*substs.types.get(FnSpace, 0), + *substs.types.get(FnSpace, 1)); + let llintype = type_of::type_of(ccx, in_type); + let llouttype = type_of::type_of(ccx, out_type); + + let in_type_size = machine::llbitsize_of_real(ccx, llintype); + let out_type_size = machine::llbitsize_of_real(ccx, llouttype); + + // This should be caught by the intrinsicck pass + assert_eq!(in_type_size, out_type_size); + + // We need to cast the dest so the types work out + let dest = match dest { + expr::SaveIn(d) => expr::SaveIn(PointerCast(bcx, d, llintype.ptr_to())), + expr::Ignore => expr::Ignore + }; + bcx = expr::trans_into(bcx, &*arg_exprs[0], dest); + + fcx.pop_custom_cleanup_scope(cleanup_scope); + + return match dest { + expr::SaveIn(d) => Result::new(bcx, d), + expr::Ignore => Result::new(bcx, C_undef(llret_ty.ptr_to())) + }; + + } + + _ => { + ccx.sess().bug("expected expr as argument for transmute"); + } + } + } // Get location to store the result. If the user does // not care about the result, just make a stack slot @@ -158,8 +198,6 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, fcx.pop_custom_cleanup_scope(cleanup_scope); - let foreign_item = tcx.map.expect_foreign_item(node); - let name = token::get_ident(foreign_item.ident); let simple = get_simple_intrinsic(ccx, &*foreign_item); let llval = match (simple, name.get()) { @@ -240,60 +278,6 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, (_, "uninit") | (_, "forget") => { C_nil(ccx) } - (_, "transmute") => { - let (in_type, out_type) = (*substs.types.get(FnSpace, 0), - *substs.types.get(FnSpace, 1)); - let llintype = type_of::type_of(ccx, in_type); - let llouttype = type_of::type_of(ccx, out_type); - - let in_type_size = machine::llbitsize_of_real(ccx, llintype); - let out_type_size = machine::llbitsize_of_real(ccx, llouttype); - - // This should be caught by the intrinsicck pass - assert_eq!(in_type_size, out_type_size); - - if !return_type_is_void(ccx, out_type) { - let llsrcval = *llargs.get(0); - if type_is_immediate(ccx, in_type) { - if type_is_immediate(ccx, out_type) { - Store(bcx, llsrcval, PointerCast(bcx, llresult, llintype.ptr_to())); - C_nil(ccx) - } else { - match (llintype.kind(), llouttype.kind()) { - (Pointer, other) | (other, Pointer) if other != Pointer => { - let tmp = Alloca(bcx, llouttype, ""); - Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to())); - Load(bcx, tmp) - } - (Array, _) | (_, Array) | (Struct, _) | (_, Struct) => { - let tmp = Alloca(bcx, llouttype, ""); - Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to())); - Load(bcx, tmp) - } - _ => { - BitCast(bcx, llsrcval, llouttype) - } - } - } - } else if type_is_immediate(ccx, out_type) { - Load(bcx, PointerCast(bcx, llsrcval, llouttype.ptr_to())) - } else { - // NB: Do not use a Load and Store here. This causes massive - // code bloat when `transmute` is used on large structural - // types. - let lldestptr = llresult; - let lldestptr = PointerCast(bcx, lldestptr, Type::i8p(ccx)); - let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p(ccx)); - - let llsize = llsize_of(ccx, llintype); - call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1); - - C_nil(ccx) - } - } else { - C_nil(ccx) - } - } (_, "needs_drop") => { let tp_ty = *substs.types.get(FnSpace, 0); C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)) |
