10
10
11
11
#![ allow( non_uppercase_pattern_statics) ]
12
12
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 } ;
15
14
use lib;
16
15
use middle:: subst;
17
16
use middle:: subst:: FnSpace ;
@@ -137,6 +136,47 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
137
136
_ => fail ! ( "expected bare_fn in trans_intrinsic_call" )
138
137
} ;
139
138
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
+ }
140
180
141
181
// Get location to store the result. If the user does
142
182
// 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,
158
198
159
199
fcx. pop_custom_cleanup_scope ( cleanup_scope) ;
160
200
161
- let foreign_item = tcx. map . expect_foreign_item ( node) ;
162
- let name = token:: get_ident ( foreign_item. ident ) ;
163
201
let simple = get_simple_intrinsic ( ccx, & * foreign_item) ;
164
202
165
203
let llval = match ( simple, name. get ( ) ) {
@@ -240,60 +278,6 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
240
278
( _, "uninit" ) | ( _, "forget" ) => {
241
279
C_nil ( ccx)
242
280
}
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
- }
297
281
( _, "needs_drop" ) => {
298
282
let tp_ty = * substs. types . get ( FnSpace , 0 ) ;
299
283
C_bool ( ccx, ty:: type_needs_drop ( ccx. tcx ( ) , tp_ty) )
0 commit comments