@@ -171,6 +171,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
171
171
let foreign_item = tcx. map . expect_foreign_item ( node) ;
172
172
let name = token:: get_ident ( foreign_item. ident ) ;
173
173
174
+ let call_debug_location = DebugLoc :: At ( call_info. id , call_info. span ) ;
175
+
174
176
// For `transmute` we can just trans the input expr directly into dest
175
177
if & name[ ..] == "transmute" {
176
178
let llret_ty = type_of:: type_of ( ccx, ret_ty. unwrap ( ) ) ;
@@ -199,14 +201,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
199
201
} ;
200
202
201
203
// An approximation to which types can be directly cast via
202
- // LLVM's bitcast. This doesn't cover pointer -> pointer casts,
203
- // but does, importantly, cover SIMD types.
204
+ // LLVM's bitcast.
204
205
let in_kind = llintype. kind ( ) ;
205
206
let ret_kind = llret_ty. kind ( ) ;
206
207
let bitcast_compatible =
207
- ( nonpointer_nonaggregate ( in_kind) && nonpointer_nonaggregate ( ret_kind) ) || {
208
- in_kind == TypeKind :: Pointer && ret_kind == TypeKind :: Pointer
209
- } ;
208
+ ( nonpointer_nonaggregate ( in_kind) && nonpointer_nonaggregate ( ret_kind) ) ||
209
+ ( in_kind == TypeKind :: Pointer && ret_kind == TypeKind :: Pointer ) ||
210
+ ( in_kind == TypeKind :: Pointer && ret_kind == TypeKind :: Integer ) ||
211
+ ( in_kind == TypeKind :: Integer && ret_kind == TypeKind :: Pointer ) ;
210
212
211
213
let val = if bitcast_compatible {
212
214
// if we're here, the type is scalar-like (a primitive, a
@@ -226,29 +228,62 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
226
228
from_arg_ty ( bcx, datum. val , datum. ty )
227
229
} ;
228
230
229
- let cast_val = BitCast ( bcx, val, llret_ty) ;
231
+ // Do the appropriate cast type
232
+ let cast_val = match ( in_kind, ret_kind) {
233
+ ( TypeKind :: Pointer , TypeKind :: Pointer ) => PointerCast ( bcx, val, llret_ty) ,
234
+ ( TypeKind :: Pointer , TypeKind :: Integer ) => PtrToInt ( bcx, val, llret_ty) ,
235
+ ( TypeKind :: Integer , TypeKind :: Pointer ) => IntToPtr ( bcx, val, llret_ty) ,
236
+ _ => BitCast ( bcx, val, llret_ty)
237
+ } ;
230
238
231
239
match dest {
232
240
expr:: SaveIn ( d) => {
233
241
// this often occurs in a sequence like `Store(val,
234
242
// d); val2 = Load(d)`, so disappears easily.
235
243
Store ( bcx, cast_val, d) ;
236
- d
237
244
}
238
- expr:: Ignore => { cast_val }
245
+ expr:: Ignore => { }
239
246
}
247
+ cast_val
240
248
} else {
241
249
// The types are too complicated to do with a by-value
242
250
// bitcast, so pointer cast instead. We need to cast the
243
251
// dest so the types work out.
244
- let dest = match dest {
252
+
253
+ // Create the destination, if we were passed a destination, bitcast it to the
254
+ // appropriate type. Otherwise, create a temporary destination for immediate
255
+ // types and just ignore non-immediate types. This is because we return the
256
+ // result for immediate values.
257
+ let tmp_dest = match dest {
245
258
expr:: SaveIn ( d) => expr:: SaveIn ( PointerCast ( bcx, d, llintype. ptr_to ( ) ) ) ,
246
- expr:: Ignore => expr:: Ignore
259
+ expr:: Ignore => if type_is_immediate ( bcx. ccx ( ) , out_type) {
260
+ expr:: SaveIn ( alloc_ty ( bcx, in_type, "intrinsic_result" ) )
261
+ } else {
262
+ expr:: Ignore
263
+ }
247
264
} ;
248
- bcx = expr:: trans_into ( bcx, & * arg_exprs[ 0 ] , dest ) ;
265
+ bcx = expr:: trans_into ( bcx, & * arg_exprs[ 0 ] , tmp_dest ) ;
249
266
match dest {
250
267
expr:: SaveIn ( d) => d,
251
- expr:: Ignore => C_undef ( llret_ty)
268
+ expr:: Ignore => {
269
+ // We weren't passed a destination to save to, if we made a temporary
270
+ // destination, load the immediate value stored and clean up the type.
271
+ // Otherwise return ().
272
+ if let expr:: SaveIn ( d) = tmp_dest {
273
+ let val = if type_is_immediate ( bcx. ccx ( ) , out_type) {
274
+ let d = PointerCast ( bcx, d, llouttype. ptr_to ( ) ) ;
275
+ load_ty ( bcx, d, out_type)
276
+ } else {
277
+ C_nil ( bcx. ccx ( ) )
278
+ } ;
279
+
280
+ bcx = glue:: drop_ty ( bcx, d, out_type, call_debug_location) ;
281
+
282
+ val
283
+ } else {
284
+ C_nil ( bcx. ccx ( ) )
285
+ }
286
+ }
252
287
}
253
288
} ;
254
289
@@ -320,8 +355,6 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
320
355
321
356
fcx. scopes . borrow_mut ( ) . last_mut ( ) . unwrap ( ) . drop_non_lifetime_clean ( ) ;
322
357
323
- let call_debug_location = DebugLoc :: At ( call_info. id , call_info. span ) ;
324
-
325
358
// These are the only intrinsic functions that diverge.
326
359
if & name[ ..] == "abort" {
327
360
let llfn = ccx. get_intrinsic ( & ( "llvm.trap" ) ) ;
0 commit comments