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 } ;
1514use lib;
1615use middle:: subst;
1716use 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