]> git.lizzy.rs Git - rust.git/commitdiff
mir: Translate intrinsics, via old trans where possible.
authorEduard Burtescu <edy.burt@gmail.com>
Tue, 8 Mar 2016 12:40:37 +0000 (14:40 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Thu, 17 Mar 2016 19:51:54 +0000 (21:51 +0200)
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_trans/trans/mir/block.rs

index bef96cb2b45f6d8a7b230b5a07f4e5cfe2068ae2..17d08cd6c2f292a756cebdd5799d9846fab995dc 100644 (file)
@@ -36,7 +36,7 @@
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
 use trans::closure;
-use trans::common::{self, Block, Result, NodeIdAndSpan, CrateContext, FunctionContext};
+use trans::common::{self, Block, Result, CrateContext, FunctionContext};
 use trans::common::{C_uint, C_undef};
 use trans::consts;
 use trans::datum::*;
@@ -56,7 +56,6 @@
 use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_front::hir;
 
-use syntax::ast;
 use syntax::codemap::DUMMY_SP;
 use syntax::errors;
 use syntax::ptr::P;
@@ -624,18 +623,9 @@ fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             assert!(abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic);
             assert!(dest.is_some());
 
-            let call_info = match debug_loc {
-                DebugLoc::At(id, span) => NodeIdAndSpan { id: id, span: span },
-                DebugLoc::None => {
-                    bcx.sess().bug("No call info for intrinsic call?")
-                }
-            };
-
-            let arg_cleanup_scope = fcx.push_custom_cleanup_scope();
             return intrinsic::trans_intrinsic_call(bcx, callee.ty, &fn_ty,
-                                                   arg_cleanup_scope, args,
-                                                   dest.unwrap(),
-                                                   call_info);
+                                                   args, dest.unwrap(),
+                                                   debug_loc);
         }
         NamedTupleConstructor(disr) => {
             assert!(dest.is_some());
index 7673c98af2a3330570e642fda67616256cf19af7..b99cb2b63311c3f2613fd7c7b608a09870b49ae2 100644 (file)
@@ -47,7 +47,7 @@
 
 use rustc::lint;
 use rustc::session::Session;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 
 use std::cmp::Ordering;
 
@@ -173,10 +173,9 @@ pub fn check_intrinsics(ccx: &CrateContext) {
 pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                             callee_ty: Ty<'tcx>,
                                             fn_ty: &FnType,
-                                            cleanup_scope: cleanup::CustomScopeIndex,
                                             args: callee::CallArgs<'a, 'tcx>,
                                             dest: expr::Dest,
-                                            call_info: NodeIdAndSpan)
+                                            call_debug_location: DebugLoc)
                                             -> Result<'blk, 'tcx> {
     let fcx = bcx.fcx;
     let ccx = fcx.ccx;
@@ -195,7 +194,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     let ret_ty = sig.output;
     let name = tcx.item_name(def_id).as_str();
 
-    let call_debug_location = DebugLoc::At(call_info.id, call_info.span);
+    let span = match call_debug_location {
+        DebugLoc::At(_, span) => span,
+        DebugLoc::None => fcx.span.unwrap_or(DUMMY_SP)
+    };
+
+    let cleanup_scope = fcx.push_custom_cleanup_scope();
 
     // For `transmute` we can just trans the input expr directly into dest
     if name == "transmute" {
@@ -644,7 +648,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     },
                 None => {
                     span_invalid_monomorphization_error(
-                        tcx.sess, call_info.span,
+                        tcx.sess, span,
                         &format!("invalid monomorphization of `{}` intrinsic: \
                                   expected basic integer type, found `{}`", name, sty));
                         C_null(llret_ty)
@@ -656,7 +660,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
         (_, "return_address") => {
             if !fcx.fn_ty.ret.is_indirect() {
-                span_err!(tcx.sess, call_info.span, E0510,
+                span_err!(tcx.sess, span, E0510,
                           "invalid use of `return_address` intrinsic: function \
                            does not use out pointer");
                 C_null(Type::i8p(ccx))
@@ -684,7 +688,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                    &llargs,
                                    ret_ty, llret_ty,
                                    call_debug_location,
-                                   call_info)
+                                   span)
         }
         // This requires that atomic intrinsics follow a specific naming pattern:
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
@@ -1404,7 +1408,7 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
      ret_ty: Ty<'tcx>,
      llret_ty: Type,
      call_debug_location: DebugLoc,
-     call_info: NodeIdAndSpan) -> ValueRef
+     span: Span) -> ValueRef
 {
     // macros for error handling:
     macro_rules! emit_error {
@@ -1413,7 +1417,7 @@ macro_rules! emit_error {
         };
         ($msg: tt, $($fmt: tt)*) => {
             span_invalid_monomorphization_error(
-                bcx.sess(), call_info.span,
+                bcx.sess(), span,
                 &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
                                  $msg),
                          name, $($fmt)*));
@@ -1482,7 +1486,7 @@ macro_rules! require_simd {
     if name.starts_with("simd_shuffle") {
         let n: usize = match name["simd_shuffle".len()..].parse() {
             Ok(n) => n,
-            Err(_) => tcx.sess.span_bug(call_info.span,
+            Err(_) => tcx.sess.span_bug(span,
                                         "bad `simd_shuffle` instruction only caught in trans?")
         };
 
@@ -1502,14 +1506,14 @@ macro_rules! require_simd {
 
         let vector = match args {
             Some(args) => &args[2],
-            None => bcx.sess().span_bug(call_info.span,
+            None => bcx.sess().span_bug(span,
                                         "intrinsic call with unexpected argument shape"),
         };
         let vector = match consts::const_expr(bcx.ccx(), vector, substs, None,
             consts::TrueConst::Yes, // this should probably help simd error reporting
         ) {
             Ok((vector, _)) => vector,
-            Err(err) => bcx.sess().span_fatal(call_info.span, &err.description()),
+            Err(err) => bcx.sess().span_fatal(span, &err.description()),
         };
 
         let indices: Option<Vec<_>> = (0..n)
@@ -1652,7 +1656,7 @@ macro_rules! arith {
         simd_or: TyUint, TyInt => Or;
         simd_xor: TyUint, TyInt => Xor;
     }
-    bcx.sess().span_bug(call_info.span, "unknown SIMD intrinsic");
+    bcx.sess().span_bug(span, "unknown SIMD intrinsic");
 }
 
 // Returns the width of an int TypeVariant, and if it's signed or not
index ac57cd843aab3d4f0c028e244643b66d6ed3825f..547382daab37c6eb08d490d8aaa918da40e44bc0 100644 (file)
 use trans::adt;
 use trans::base;
 use trans::build;
-use trans::callee::{Callee, CalleeData, Fn, Virtual};
+use trans::callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
 use trans::common::{self, Block, BlockAndBuilder, C_undef};
 use trans::debuginfo::DebugLoc;
 use trans::Disr;
-use trans::machine::llalign_of_min;
+use trans::machine::{llalign_of_min, llbitsize_of_real};
 use trans::meth;
 use trans::type_of;
 use trans::glue;
@@ -27,6 +27,7 @@
 
 use super::{MirContext, drop};
 use super::lvalue::LvalueRef;
+use super::operand::OperandRef;
 use super::operand::OperandValue::{self, FatPtr, Immediate, Ref};
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
@@ -168,8 +169,51 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                     _ => unreachable!("{} is not callable", callee.ty)
                 };
 
-                // We do not translate intrinsics here (they shouldn’t be functions)
-                assert!(abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic);
+                // Handle intrinsics old trans wants Expr's for, ourselves.
+                let intrinsic = match (&callee.ty.sty, &callee.data) {
+                    (&ty::TyFnDef(def_id, _, _), &Intrinsic) => {
+                        Some(bcx.tcx().item_name(def_id).as_str())
+                    }
+                    _ => None
+                };
+                let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
+
+                if intrinsic == Some("move_val_init") {
+                    let &(_, target) = destination.as_ref().unwrap();
+                    // The first argument is a thin destination pointer.
+                    let llptr = self.trans_operand(&bcx, &args[0]).immediate();
+                    let val = self.trans_operand(&bcx, &args[1]);
+                    self.store_operand(&bcx, llptr, val);
+                    self.set_operand_dropped(&bcx, &args[1]);
+                    funclet_br(bcx, self.llblock(target));
+                    return;
+                }
+
+                if intrinsic == Some("transmute") {
+                    let &(ref dest, target) = destination.as_ref().unwrap();
+                    let dst = self.trans_lvalue(&bcx, dest);
+                    let mut val = self.trans_operand(&bcx, &args[0]);
+                    if let ty::TyFnDef(def_id, substs, _) = val.ty.sty {
+                        let llouttype = type_of::type_of(bcx.ccx(), dst.ty.to_ty(bcx.tcx()));
+                        let out_type_size = llbitsize_of_real(bcx.ccx(), llouttype);
+                        if out_type_size != 0 {
+                            // FIXME #19925 Remove this hack after a release cycle.
+                            let f = Callee::def(bcx.ccx(), def_id, substs);
+                            let datum = f.reify(bcx.ccx());
+                            val = OperandRef {
+                                val: OperandValue::Immediate(datum.val),
+                                ty: datum.ty
+                            };
+                        }
+                    }
+
+                    let llty = type_of::type_of(bcx.ccx(), val.ty);
+                    let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
+                    self.store_operand(&bcx, cast_ptr, val);
+                    self.set_operand_dropped(&bcx, &args[0]);
+                    funclet_br(bcx, self.llblock(target));
+                    return;
+                }
 
                 let extra_args = &args[sig.0.inputs.len()..];
                 let extra_args = extra_args.iter().map(|op_arg| {
@@ -215,7 +259,44 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                                                   &mut idx, &mut callee.data)
                 }
 
-                let fn_ptr = callee.reify(bcx.ccx()).val;
+                let fn_ptr = match callee.data {
+                    NamedTupleConstructor(_) => {
+                        // FIXME translate this like mir::Rvalue::Aggregate.
+                        callee.reify(bcx.ccx()).val
+                    }
+                    Intrinsic => {
+                        use trans::callee::ArgVals;
+                        use trans::expr::{Ignore, SaveIn};
+                        use trans::intrinsic::trans_intrinsic_call;
+
+                        let (dest, llargs) = if fn_ty.ret.is_indirect() {
+                            (SaveIn(llargs[0]), &llargs[1..])
+                        } else if let Some(dest) = ret_dest {
+                            (SaveIn(dest.llval), &llargs[..])
+                        } else {
+                            (Ignore, &llargs[..])
+                        };
+
+                        bcx.with_block(|bcx| {
+                            let res = trans_intrinsic_call(bcx, callee.ty, &fn_ty,
+                                                           ArgVals(llargs), dest,
+                                                           DebugLoc::None);
+                            let bcx = res.bcx.build();
+                            if let Some((_, target)) = *destination {
+                                for op in args {
+                                    self.set_operand_dropped(&bcx, op);
+                                }
+                                funclet_br(bcx, self.llblock(target));
+                            } else {
+                                // trans_intrinsic_call already used Unreachable.
+                                // bcx.unreachable();
+                            }
+                        });
+                        return;
+                    }
+                    Fn(f) => f,
+                    Virtual(_) => unreachable!("Virtual fn ptr not extracted")
+                };
 
                 // Many different ways to call a function handled here
                 if let Some(cleanup) = cleanup.map(|bb| self.bcx(bb)) {