Rustup after layout optimizations

This commit is contained in:
Oliver Schneider 2017-11-21 13:32:40 +01:00
parent 6dbfe23c4d
commit a107f14ed8
No known key found for this signature in database
GPG Key ID: A69F8D225B3AD7D9
3 changed files with 63 additions and 59 deletions

View File

@ -45,6 +45,8 @@ pub trait EvalContextExt<'tcx> {
span: Span, span: Span,
sig: ty::FnSig<'tcx>, sig: ty::FnSig<'tcx>,
) -> EvalResult<'tcx, bool>; ) -> EvalResult<'tcx, bool>;
fn write_null(&mut self, dest: Lvalue, dest_ty: Ty<'tcx>) -> EvalResult<'tcx>;
} }
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> { impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> {
@ -416,10 +418,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
// Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t. // Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference) let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference)
.ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty; .ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
let key_size = { let key_size = self.type_layout(key_type)?.size;
let layout = self.type_layout(key_type)?;
layout.size(&self.tcx.data_layout)
};
// Create key and write it into the memory where key_ptr wants it // Create key and write it into the memory where key_ptr wants it
let key = self.memory.create_tls_key(dtor) as u128; let key = self.memory.create_tls_key(dtor) as u128;
@ -655,4 +654,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.goto_block(dest_block); self.goto_block(dest_block);
return Ok(()); return Ok(());
} }
fn write_null(&mut self, dest: Lvalue, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)
}
} }

View File

@ -1,7 +1,7 @@
use rustc::mir; use rustc::mir;
use rustc::traits::Reveal; use rustc::traits::Reveal;
use rustc::ty::layout::Layout; use rustc::ty::layout::TyLayout;
use rustc::ty::{self, Ty}; use rustc::ty;
use rustc::mir::interpret::{EvalResult, Lvalue, LvalueExtra, PrimVal, PrimValKind, Value, Pointer, use rustc::mir::interpret::{EvalResult, Lvalue, LvalueExtra, PrimVal, PrimValKind, Value, Pointer,
HasMemory, AccessKind, EvalContext, PtrAndAlign, ValTy}; HasMemory, AccessKind, EvalContext, PtrAndAlign, ValTy};
@ -14,8 +14,7 @@ pub trait EvalContextExt<'tcx> {
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
args: &[ValTy<'tcx>], args: &[ValTy<'tcx>],
dest: Lvalue, dest: Lvalue,
dest_ty: Ty<'tcx>, dest_layout: TyLayout<'tcx>,
dest_layout: &'tcx Layout,
target: mir::BasicBlock, target: mir::BasicBlock,
) -> EvalResult<'tcx>; ) -> EvalResult<'tcx>;
} }
@ -26,8 +25,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
args: &[ValTy<'tcx>], args: &[ValTy<'tcx>],
dest: Lvalue, dest: Lvalue,
dest_ty: Ty<'tcx>, dest_layout: TyLayout<'tcx>,
dest_layout: &'tcx Layout,
target: mir::BasicBlock, target: mir::BasicBlock,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
let substs = instance.substs; let substs = instance.substs;
@ -37,7 +35,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"align_offset" => { "align_offset" => {
// FIXME: return a real value in case the target allocation has an // FIXME: return a real value in case the target allocation has an
// alignment bigger than the one requested // alignment bigger than the one requested
self.write_primval(dest, PrimVal::Bytes(u128::max_value()), dest_ty)?; self.write_primval(dest, PrimVal::Bytes(u128::max_value()), dest_layout.ty)?;
}, },
"add_with_overflow" => { "add_with_overflow" => {
@ -46,7 +44,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)? )?
} }
@ -56,7 +54,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)? )?
} }
@ -66,7 +64,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)? )?
} }
@ -74,7 +72,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let offset = self.value_to_primval(args[1])?.to_i128()? as i64; let offset = self.value_to_primval(args[1])?.to_i128()? as i64;
let ptr = args[0].into_ptr(&self.memory)?; let ptr = args[0].into_ptr(&self.memory)?;
let result_ptr = self.wrapping_pointer_offset(ptr, substs.type_at(0), offset)?; let result_ptr = self.wrapping_pointer_offset(ptr, substs.type_at(0), offset)?;
self.write_ptr(dest, result_ptr, dest_ty)?; self.write_ptr(dest, result_ptr, dest_layout.ty)?;
} }
"assume" => { "assume" => {
@ -139,8 +137,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
Value::ByValPair(..) => bug!("atomic_cxchg doesn't work with nonprimitives"), Value::ByValPair(..) => bug!("atomic_cxchg doesn't work with nonprimitives"),
}; };
let (val, _) = self.binary_op(mir::BinOp::Eq, old, ty, expect_old, ty)?; let (val, _) = self.binary_op(mir::BinOp::Eq, old, ty, expect_old, ty)?;
let dest = self.force_allocation(dest)?.to_ptr()?; let valty = ValTy {
self.write_pair_to_ptr(old, val, dest, dest_ty)?; value: Value::ByValPair(old, val),
ty: dest_layout.ty,
};
self.write_value(valty, dest)?;
self.write_primval( self.write_primval(
Lvalue::from_primval_ptr(ptr), Lvalue::from_primval_ptr(ptr),
change, change,
@ -238,9 +239,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"discriminant_value" => { "discriminant_value" => {
let ty = substs.type_at(0); let ty = substs.type_at(0);
let adt_ptr = args[0].into_ptr(&self.memory)?.to_ptr()?; let adt_ptr = args[0].into_ptr(&self.memory)?;
let discr_val = self.read_discriminant_value(adt_ptr, ty)?; let lval = Lvalue::from_primval_ptr(adt_ptr);
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; let discr_val = self.read_discriminant_value(lval, ty)?;
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_layout.ty)?;
} }
"sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" | "sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" |
@ -262,7 +264,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"truncf32" => f.trunc(), "truncf32" => f.trunc(),
_ => bug!(), _ => bug!(),
}; };
self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_ty)?; self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_layout.ty)?;
} }
"sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" | "sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" |
@ -284,7 +286,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"truncf64" => f.trunc(), "truncf64" => f.trunc(),
_ => bug!(), _ => bug!(),
}; };
self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_ty)?; self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_layout.ty)?;
} }
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
@ -300,13 +302,13 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
_ => bug!(), _ => bug!(),
}; };
let result = self.binary_op(op, a, ty, b, ty)?; let result = self.binary_op(op, a, ty, b, ty)?;
self.write_primval(dest, result.0, dest_ty)?; self.write_primval(dest, result.0, dest_layout.ty)?;
} }
"likely" | "unlikely" | "forget" => {} "likely" | "unlikely" | "forget" => {}
"init" => { "init" => {
let size = self.type_size(dest_ty)?.expect("cannot zero unsized value"); let size = self.type_size(dest_layout.ty)?.expect("cannot zero unsized value");
let init = |this: &mut Self, val: Value| { let init = |this: &mut Self, val: Value| {
let zero_val = match val { let zero_val = match val {
Value::ByRef(PtrAndAlign { ptr, .. }) => { Value::ByRef(PtrAndAlign { ptr, .. }) => {
@ -316,10 +318,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
} }
// TODO(solson): Revisit this, it's fishy to check for Undef here. // TODO(solson): Revisit this, it's fishy to check for Undef here.
Value::ByVal(PrimVal::Undef) => { Value::ByVal(PrimVal::Undef) => {
match this.ty_to_primval_kind(dest_ty) { match this.ty_to_primval_kind(dest_layout.ty) {
Ok(_) => Value::ByVal(PrimVal::Bytes(0)), Ok(_) => Value::ByVal(PrimVal::Bytes(0)),
Err(_) => { Err(_) => {
let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?; let ptr = this.alloc_ptr_with_substs(dest_layout.ty, substs)?;
let ptr = Pointer::from(PrimVal::Ptr(ptr)); let ptr = Pointer::from(PrimVal::Ptr(ptr));
this.memory.write_repeat(ptr, 0, size)?; this.memory.write_repeat(ptr, 0, size)?;
Value::by_ref(ptr) Value::by_ref(ptr)
@ -349,15 +351,15 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let elem_ty = substs.type_at(0); let elem_ty = substs.type_at(0);
let elem_align = self.type_align(elem_ty)?; let elem_align = self.type_align(elem_ty)?;
let align_val = PrimVal::from_u128(elem_align as u128); let align_val = PrimVal::from_u128(elem_align as u128);
self.write_primval(dest, align_val, dest_ty)?; self.write_primval(dest, align_val, dest_layout.ty)?;
} }
"pref_align_of" => { "pref_align_of" => {
let ty = substs.type_at(0); let ty = substs.type_at(0);
let layout = self.type_layout(ty)?; let layout = self.type_layout(ty)?;
let align = layout.align(&self.tcx.data_layout).pref(); let align = layout.align.pref();
let align_val = PrimVal::from_u128(align as u128); let align_val = PrimVal::from_u128(align as u128);
self.write_primval(dest, align_val, dest_ty)?; self.write_primval(dest, align_val, dest_layout.ty)?;
} }
"move_val_init" => { "move_val_init" => {
@ -373,7 +375,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::from_bool(needs_drop), PrimVal::from_bool(needs_drop),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -381,7 +383,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let offset = self.value_to_primval(args[1])?.to_i128()? as i64; let offset = self.value_to_primval(args[1])?.to_i128()? as i64;
let ptr = args[0].into_ptr(&self.memory)?; let ptr = args[0].into_ptr(&self.memory)?;
let result_ptr = self.pointer_offset(ptr, substs.type_at(0), offset)?; let result_ptr = self.pointer_offset(ptr, substs.type_at(0), offset)?;
self.write_ptr(dest, result_ptr, dest_ty)?; self.write_ptr(dest, result_ptr, dest_layout.ty)?;
} }
"overflowing_sub" => { "overflowing_sub" => {
@ -390,7 +392,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -400,7 +402,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -410,7 +412,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -422,7 +424,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes(f.powf(f2).to_bits() as u128), PrimVal::Bytes(f.powf(f2).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -434,7 +436,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes(f.powf(f2).to_bits() as u128), PrimVal::Bytes(f.powf(f2).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -448,7 +450,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes((a * b + c).to_bits() as u128), PrimVal::Bytes((a * b + c).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -462,7 +464,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes((a * b + c).to_bits() as u128), PrimVal::Bytes((a * b + c).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -473,7 +475,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes(f.powi(i as i32).to_bits() as u128), PrimVal::Bytes(f.powi(i as i32).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -484,7 +486,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
self.write_primval( self.write_primval(
dest, dest,
PrimVal::Bytes(f.powi(i as i32).to_bits() as u128), PrimVal::Bytes(f.powi(i as i32).to_bits() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -493,7 +495,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let size = self.type_size(ty)?.expect( let size = self.type_size(ty)?.expect(
"size_of intrinsic called on unsized value", "size_of intrinsic called on unsized value",
) as u128; ) as u128;
self.write_primval(dest, PrimVal::from_u128(size), dest_ty)?; self.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?;
} }
"size_of_val" => { "size_of_val" => {
@ -501,8 +503,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let (size, _) = self.size_and_align_of_dst(ty, args[0].value)?; let (size, _) = self.size_and_align_of_dst(ty, args[0].value)?;
self.write_primval( self.write_primval(
dest, dest,
PrimVal::from_u128(size as u128), PrimVal::from_u128(size.bytes() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -512,8 +514,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let (_, align) = self.size_and_align_of_dst(ty, args[0].value)?; let (_, align) = self.size_and_align_of_dst(ty, args[0].value)?;
self.write_primval( self.write_primval(
dest, dest,
PrimVal::from_u128(align as u128), PrimVal::from_u128(align.pref() as u128),
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -521,12 +523,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let ty = substs.type_at(0); let ty = substs.type_at(0);
let ty_name = ty.to_string(); let ty_name = ty.to_string();
let value = self.str_to_value(&ty_name)?; let value = self.str_to_value(&ty_name)?;
self.write_value(ValTy { value, ty: dest_ty }, dest)?; self.write_value(ValTy { value, ty: dest_layout.ty }, dest)?;
} }
"type_id" => { "type_id" => {
let ty = substs.type_at(0); let ty = substs.type_at(0);
let n = self.tcx.type_id_hash(ty); let n = self.tcx.type_id_hash(ty);
self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?; self.write_primval(dest, PrimVal::Bytes(n as u128), dest_layout.ty)?;
} }
"transmute" => { "transmute" => {
@ -542,7 +544,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
} }
"unchecked_shl" => { "unchecked_shl" => {
let bits = self.type_size(dest_ty)?.expect( let bits = self.type_size(dest_layout.ty)?.expect(
"intrinsic can't be called on unsized type", "intrinsic can't be called on unsized type",
) as u128 * 8; ) as u128 * 8;
let rhs = self.value_to_primval(args[1])? let rhs = self.value_to_primval(args[1])?
@ -557,12 +559,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
"unchecked_shr" => { "unchecked_shr" => {
let bits = self.type_size(dest_ty)?.expect( let bits = self.type_size(dest_layout.ty)?.expect(
"intrinsic can't be called on unsized type", "intrinsic can't be called on unsized type",
) as u128 * 8; ) as u128 * 8;
let rhs = self.value_to_primval(args[1])? let rhs = self.value_to_primval(args[1])?
@ -577,7 +579,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -592,7 +594,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
@ -607,12 +609,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
args[0], args[0],
args[1], args[1],
dest, dest,
dest_ty, dest_layout.ty,
)?; )?;
} }
"uninit" => { "uninit" => {
let size = dest_layout.size(&self.tcx.data_layout).bytes(); let size = dest_layout.size.bytes();
let uninit = |this: &mut Self, val: Value| match val { let uninit = |this: &mut Self, val: Value| match val {
Value::ByRef(PtrAndAlign { ptr, .. }) => { Value::ByRef(PtrAndAlign { ptr, .. }) => {
this.memory.mark_definedness(ptr, size, false)?; this.memory.mark_definedness(ptr, size, false)?;

View File

@ -11,7 +11,7 @@ extern crate rustc;
extern crate syntax; extern crate syntax;
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::Layout; use rustc::ty::layout::TyLayout;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::mir; use rustc::mir;
use rustc::traits; use rustc::traits;
@ -50,7 +50,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
let main_mir = ecx.load_mir(main_instance.def)?; let main_mir = ecx.load_mir(main_instance.def)?;
let mut cleanup_ptr = None; // Pointer to be deallocated when we are done let mut cleanup_ptr = None; // Pointer to be deallocated when we are done
if !main_mir.return_ty.is_nil() || main_mir.arg_count != 0 { if !main_mir.return_ty().is_nil() || main_mir.arg_count != 0 {
return err!(Unimplemented( return err!(Unimplemented(
"miri does not support main functions without `fn()` type signatures" "miri does not support main functions without `fn()` type signatures"
.to_owned(), .to_owned(),
@ -208,11 +208,10 @@ impl<'tcx> Machine<'tcx> for Evaluator {
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
args: &[ValTy<'tcx>], args: &[ValTy<'tcx>],
dest: Lvalue, dest: Lvalue,
dest_ty: ty::Ty<'tcx>, dest_layout: TyLayout<'tcx>,
dest_layout: &'tcx Layout,
target: mir::BasicBlock, target: mir::BasicBlock,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
ecx.call_intrinsic(instance, args, dest, dest_ty, dest_layout, target) ecx.call_intrinsic(instance, args, dest, dest_layout, target)
} }
fn try_ptr_op<'a>( fn try_ptr_op<'a>(