Skip to content

Commit 83122af

Browse files
committed
librustc: Translate input for transmute directly into dest.
1 parent 8fa3006 commit 83122af

File tree

1 file changed

+42
-58
lines changed

1 file changed

+42
-58
lines changed

src/librustc/middle/trans/intrinsic.rs

Lines changed: 42 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010

1111
#![allow(non_uppercase_pattern_statics)]
1212

13-
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
14-
use lib::llvm::{ValueRef, Pointer, Array, Struct};
13+
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg, ValueRef};
1514
use lib;
1615
use middle::subst;
1716
use middle::subst::FnSpace;
@@ -137,6 +136,47 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
137136
_ => fail!("expected bare_fn in trans_intrinsic_call")
138137
};
139138
let llret_ty = type_of::type_of(ccx, ret_ty);
139+
let foreign_item = tcx.map.expect_foreign_item(node);
140+
let name = token::get_ident(foreign_item.ident);
141+
142+
// For `transmute` we can just trans the input expr directly into dest
143+
if name.get() == "transmute" {
144+
match args {
145+
callee::ArgExprs(arg_exprs) => {
146+
assert_eq!(arg_exprs.len(), 1);
147+
148+
let (in_type, out_type) = (*substs.types.get(FnSpace, 0),
149+
*substs.types.get(FnSpace, 1));
150+
let llintype = type_of::type_of(ccx, in_type);
151+
let llouttype = type_of::type_of(ccx, out_type);
152+
153+
let in_type_size = machine::llbitsize_of_real(ccx, llintype);
154+
let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
155+
156+
// This should be caught by the intrinsicck pass
157+
assert_eq!(in_type_size, out_type_size);
158+
159+
// We need to cast the dest so the types work out
160+
let dest = match dest {
161+
expr::SaveIn(d) => expr::SaveIn(PointerCast(bcx, d, llintype.ptr_to())),
162+
expr::Ignore => expr::Ignore
163+
};
164+
bcx = expr::trans_into(bcx, &*arg_exprs[0], dest);
165+
166+
fcx.pop_custom_cleanup_scope(cleanup_scope);
167+
168+
return match dest {
169+
expr::SaveIn(d) => Result::new(bcx, d),
170+
expr::Ignore => Result::new(bcx, C_undef(llret_ty.ptr_to()))
171+
};
172+
173+
}
174+
175+
_ => {
176+
ccx.sess().bug("expected expr as argument for transmute");
177+
}
178+
}
179+
}
140180

141181
// Get location to store the result. If the user does
142182
// 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,
158198

159199
fcx.pop_custom_cleanup_scope(cleanup_scope);
160200

161-
let foreign_item = tcx.map.expect_foreign_item(node);
162-
let name = token::get_ident(foreign_item.ident);
163201
let simple = get_simple_intrinsic(ccx, &*foreign_item);
164202

165203
let llval = match (simple, name.get()) {
@@ -240,60 +278,6 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
240278
(_, "uninit") | (_, "forget") => {
241279
C_nil(ccx)
242280
}
243-
(_, "transmute") => {
244-
let (in_type, out_type) = (*substs.types.get(FnSpace, 0),
245-
*substs.types.get(FnSpace, 1));
246-
let llintype = type_of::type_of(ccx, in_type);
247-
let llouttype = type_of::type_of(ccx, out_type);
248-
249-
let in_type_size = machine::llbitsize_of_real(ccx, llintype);
250-
let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
251-
252-
// This should be caught by the intrinsicck pass
253-
assert_eq!(in_type_size, out_type_size);
254-
255-
if !return_type_is_void(ccx, out_type) {
256-
let llsrcval = *llargs.get(0);
257-
if type_is_immediate(ccx, in_type) {
258-
if type_is_immediate(ccx, out_type) {
259-
Store(bcx, llsrcval, PointerCast(bcx, llresult, llintype.ptr_to()));
260-
C_nil(ccx)
261-
} else {
262-
match (llintype.kind(), llouttype.kind()) {
263-
(Pointer, other) | (other, Pointer) if other != Pointer => {
264-
let tmp = Alloca(bcx, llouttype, "");
265-
Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
266-
Load(bcx, tmp)
267-
}
268-
(Array, _) | (_, Array) | (Struct, _) | (_, Struct) => {
269-
let tmp = Alloca(bcx, llouttype, "");
270-
Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
271-
Load(bcx, tmp)
272-
}
273-
_ => {
274-
BitCast(bcx, llsrcval, llouttype)
275-
}
276-
}
277-
}
278-
} else if type_is_immediate(ccx, out_type) {
279-
Load(bcx, PointerCast(bcx, llsrcval, llouttype.ptr_to()))
280-
} else {
281-
// NB: Do not use a Load and Store here. This causes massive
282-
// code bloat when `transmute` is used on large structural
283-
// types.
284-
let lldestptr = llresult;
285-
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p(ccx));
286-
let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p(ccx));
287-
288-
let llsize = llsize_of(ccx, llintype);
289-
call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
290-
291-
C_nil(ccx)
292-
}
293-
} else {
294-
C_nil(ccx)
295-
}
296-
}
297281
(_, "needs_drop") => {
298282
let tp_ty = *substs.types.get(FnSpace, 0);
299283
C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty))

0 commit comments

Comments
 (0)