提交 3e98220a 编写于 作者: E Eduard Burtescu

mir: Translate intrinsics, via old trans where possible.

上级 ee7687a5
......@@ -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());
......
......@@ -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 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
};
($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 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
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 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
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 @@ enum Style { Float, Int(/* is signed? */ bool), Unsupported }
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
......
......@@ -15,11 +15,11 @@
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)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册