1
Fork 0

Traitified IntrinsicCallMethods

This commit is contained in:
Denis Merigoux 2018-09-11 11:46:03 +02:00 committed by Eduard-Mihai Burtescu
parent a5aeb8edd6
commit 0a1c50955b
11 changed files with 670 additions and 646 deletions

View file

@ -73,9 +73,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::indexed_vec::Idx;
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use interfaces::*;
use std::any::Any;
use std::cmp;

View file

@ -19,10 +19,7 @@ use rustc::ty::TyCtxt;
use rustc::ty::layout::{Align, Size};
use rustc::session::{config, Session};
use rustc_data_structures::small_c_str::SmallCStr;
use interfaces::{
Backend,
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use interfaces::*;
use syntax;
use std::borrow::Cow;
@ -59,16 +56,11 @@ bitflags! {
}
}
impl Backend for Builder<'a, 'll, 'tcx> {
type Value = &'ll Value;
type BasicBlock = &'ll BasicBlock;
type Type = &'ll Type;
type Context = &'ll llvm::Context;
impl HasCodegen for Builder<'a, 'll, 'tcx> {
type CodegenCx = CodegenCx<'ll, 'tcx>;
}
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
type CodegenCx = CodegenCx<'ll, 'tcx>;
fn new_block<'b>(
cx: &'a CodegenCx<'ll, 'tcx>,
llfn: &'ll Value,

View file

@ -23,8 +23,7 @@ use value::Value;
use monomorphize::partitioning::CodegenUnit;
use type_::Type;
use type_of::PointeeInfo;
use interfaces::{BaseTypeMethods, DerivedTypeMethods,
IntrinsicMethods, BaseIntrinsicMethods, DerivedIntrinsicMethods};
use interfaces::{BaseTypeMethods, DerivedTypeMethods, IntrinsicDeclarationMethods};
use rustc_data_structures::base_n;
use rustc_data_structures::small_c_str::SmallCStr;
@ -323,9 +322,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
}
}
impl BaseIntrinsicMethods for CodegenCx<'_, '_> {}
impl DerivedIntrinsicMethods for CodegenCx<'b, 'tcx> {
impl IntrinsicDeclarationMethods for CodegenCx<'b, 'tcx> {
fn get_intrinsic(&self, key: &str) -> &'b Value {
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
return v;
@ -647,8 +644,6 @@ impl DerivedIntrinsicMethods for CodegenCx<'b, 'tcx> {
}
}
impl IntrinsicMethods for CodegenCx<'a, 'tcx> {}
impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
/// Generate a new symbol name with the given prefix. This symbol name must
/// only be used for definitions with `internal` or `private` linkage.

View file

@ -17,21 +17,29 @@ use builder::MemFlags;
use super::backend::Backend;
use super::type_::TypeMethods;
use super::consts::ConstMethods;
use super::intrinsic::IntrinsicMethods;
use super::intrinsic::IntrinsicDeclarationMethods;
use std::borrow::Cow;
use std::ops::Range;
use syntax::ast::AsmDialect;
pub trait BuilderMethods<'a, 'tcx: 'a>: Backend {
type CodegenCx: 'a + TypeMethods + ConstMethods + IntrinsicMethods + Backend<
pub trait HasCodegen: Backend {
type CodegenCx: TypeMethods + ConstMethods + IntrinsicDeclarationMethods + Backend<
Value = Self::Value,
BasicBlock = Self::BasicBlock,
Type = Self::Type,
Context = Self::Context,
>;
}
impl<T: HasCodegen> Backend for T {
type Value = <T::CodegenCx as Backend>::Value;
type BasicBlock = <T::CodegenCx as Backend>::BasicBlock;
type Type = <T::CodegenCx as Backend>::Type;
type Context = <T::CodegenCx as Backend>::Context;
}
pub trait BuilderMethods<'a, 'tcx: 'a>: HasCodegen {
fn new_block<'b>(
cx: &'a Self::CodegenCx,
llfn: Self::Value,

View file

@ -9,17 +9,27 @@
// except according to those terms.
use super::backend::Backend;
use super::builder::HasCodegen;
use mir::operand::OperandRef;
use rustc::ty::Ty;
use abi::FnType;
use syntax_pos::Span;
pub trait BaseIntrinsicMethods: Backend {
pub trait IntrinsicCallMethods<'a, 'tcx: 'a>: HasCodegen {
fn codegen_intrinsic_call(
&self,
callee_ty: Ty<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
span: Span,
);
}
pub trait DerivedIntrinsicMethods: Backend {
pub trait IntrinsicDeclarationMethods: Backend {
fn get_intrinsic(&self, key: &str) -> Self::Value;
fn declare_intrinsic(
&self,
key: &str
) -> Option<Self::Value>;
}
pub trait IntrinsicMethods: BaseIntrinsicMethods + DerivedIntrinsicMethods {}

View file

@ -15,9 +15,9 @@ mod type_;
mod intrinsic;
mod statics;
pub use self::builder::BuilderMethods;
pub use self::builder::{BuilderMethods, HasCodegen};
pub use self::backend::Backend;
pub use self::consts::ConstMethods;
pub use self::type_::{TypeMethods, BaseTypeMethods, DerivedTypeMethods};
pub use self::intrinsic::{IntrinsicMethods, BaseIntrinsicMethods, DerivedIntrinsicMethods};
pub use self::intrinsic::{IntrinsicCallMethods, IntrinsicDeclarationMethods};
pub use self::statics::StaticMethods;

View file

@ -32,10 +32,7 @@ use syntax::symbol::Symbol;
use builder::{Builder, MemFlags};
use value::Value;
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use interfaces::*;
use rustc::session::Session;
use syntax_pos::Span;
@ -90,18 +87,19 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
Some(cx.get_intrinsic(&llvm_name))
}
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
/// add them to librustc_codegen_llvm/context.rs
pub fn codegen_intrinsic_call(
bx: &Builder<'a, 'll, 'tcx>,
impl IntrinsicCallMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
/// add them to librustc_codegen_llvm/context.rs
fn codegen_intrinsic_call(
&self,
callee_ty: Ty<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, &'ll Value>],
llresult: &'ll Value,
span: Span,
) {
let cx = bx.cx();
) {
let cx = self.cx();
let tcx = cx.tcx;
let (def_id, substs) = match callee_ty.sty {
@ -121,7 +119,7 @@ pub fn codegen_intrinsic_call(
let simple = get_simple_intrinsic(cx, name);
let llval = match name {
_ if simple.is_some() => {
bx.call(simple.unwrap(),
self.call(simple.unwrap(),
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None)
}
@ -130,14 +128,14 @@ pub fn codegen_intrinsic_call(
},
"likely" => {
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
bx.call(expect, &[args[0].immediate(), bx.cx().const_bool(true)], None)
self.call(expect, &[args[0].immediate(), cx.const_bool(true)], None)
}
"unlikely" => {
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
bx.call(expect, &[args[0].immediate(), bx.cx().const_bool(false)], None)
self.call(expect, &[args[0].immediate(), cx.const_bool(false)], None)
}
"try" => {
try_intrinsic(bx, cx,
try_intrinsic(self, cx,
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
@ -146,7 +144,7 @@ pub fn codegen_intrinsic_call(
}
"breakpoint" => {
let llfn = cx.get_intrinsic(&("llvm.debugtrap"));
bx.call(llfn, &[], None)
self.call(llfn, &[], None)
}
"size_of" => {
let tp_ty = substs.type_at(0);
@ -156,7 +154,7 @@ pub fn codegen_intrinsic_call(
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
let (llsize, _) =
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
llsize
} else {
cx.const_usize(cx.size_of(tp_ty).bytes())
@ -170,7 +168,7 @@ pub fn codegen_intrinsic_call(
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
let (_, llalign) =
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
glue::size_and_align_of_dst(&self, tp_ty, Some(meta));
llalign
} else {
cx.const_usize(cx.align_of(tp_ty).abi())
@ -192,11 +190,11 @@ pub fn codegen_intrinsic_call(
let ty = substs.type_at(0);
if !cx.layout_of(ty).is_zst() {
// Just zero out the stack slot.
// If we store a zero constant, LLVM will drown in vreg allocation for large data
// structures, and the generated code will be awful. (A telltale sign of this is
// large quantities of `mov [byte ptr foo],0` in the generated code.)
// If we store a zero constant, LLVM will drown in vreg allocation for large
// data structures, and the generated code will be awful. (A telltale sign of
// this is large quantities of `mov [byte ptr foo],0` in the generated code.)
memset_intrinsic(
bx,
&self,
false,
ty,
llresult,
@ -213,47 +211,47 @@ pub fn codegen_intrinsic_call(
"needs_drop" => {
let tp_ty = substs.type_at(0);
cx.const_bool(bx.cx().type_needs_drop(tp_ty))
cx.const_bool(cx.type_needs_drop(tp_ty))
}
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
bx.inbounds_gep(ptr, &[offset])
self.inbounds_gep(ptr, &[offset])
}
"arith_offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
bx.gep(ptr, &[offset])
self.gep(ptr, &[offset])
}
"copy_nonoverlapping" => {
copy_intrinsic(bx, false, false, substs.type_at(0),
copy_intrinsic(&self, false, false, substs.type_at(0),
args[1].immediate(), args[0].immediate(), args[2].immediate());
return;
}
"copy" => {
copy_intrinsic(bx, true, false, substs.type_at(0),
copy_intrinsic(&self, true, false, substs.type_at(0),
args[1].immediate(), args[0].immediate(), args[2].immediate());
return;
}
"write_bytes" => {
memset_intrinsic(bx, false, substs.type_at(0),
memset_intrinsic(&self, false, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate());
return;
}
"volatile_copy_nonoverlapping_memory" => {
copy_intrinsic(bx, false, true, substs.type_at(0),
copy_intrinsic(&self, false, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate());
return;
}
"volatile_copy_memory" => {
copy_intrinsic(bx, true, true, substs.type_at(0),
copy_intrinsic(&self, true, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate());
return;
}
"volatile_set_memory" => {
memset_intrinsic(bx, true, substs.type_at(0),
memset_intrinsic(&self, true, substs.type_at(0),
args[0].immediate(), args[1].immediate(), args[2].immediate());
return;
}
@ -261,9 +259,9 @@ pub fn codegen_intrinsic_call(
let tp_ty = substs.type_at(0);
let mut ptr = args[0].immediate();
if let PassMode::Cast(ty) = fn_ty.ret.mode {
ptr = bx.pointercast(ptr, bx.cx().type_ptr_to(ty.llvm_type(cx)));
ptr = self.pointercast(ptr, cx.type_ptr_to(ty.llvm_type(cx)));
}
let load = bx.volatile_load(ptr);
let load = self.volatile_load(ptr);
let align = if name == "unaligned_volatile_load" {
1
} else {
@ -272,16 +270,16 @@ pub fn codegen_intrinsic_call(
unsafe {
llvm::LLVMSetAlignment(load, align);
}
to_immediate(bx, load, cx.layout_of(tp_ty))
to_immediate(self, load, cx.layout_of(tp_ty))
},
"volatile_store" => {
let dst = args[0].deref(bx.cx());
args[1].val.volatile_store(bx, dst);
let dst = args[0].deref(cx);
args[1].val.volatile_store(&self, dst);
return;
},
"unaligned_volatile_store" => {
let dst = args[0].deref(bx.cx());
args[1].val.unaligned_volatile_store(bx, dst);
let dst = args[0].deref(cx);
args[1].val.unaligned_volatile_store(&self, dst);
return;
},
"prefetch_read_data" | "prefetch_write_data" |
@ -294,7 +292,7 @@ pub fn codegen_intrinsic_call(
"prefetch_write_instruction" => (1, 0),
_ => bug!()
};
bx.call(expect, &[
self.call(expect, &[
args[0].immediate(),
cx.const_i32(rw),
args[1].immediate(),
@ -313,76 +311,82 @@ pub fn codegen_intrinsic_call(
"ctlz" | "cttz" => {
let y = cx.const_bool(false);
let llfn = cx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
bx.call(llfn, &[args[0].immediate(), y], None)
self.call(llfn, &[args[0].immediate(), y], None)
}
"ctlz_nonzero" | "cttz_nonzero" => {
let y = cx.const_bool(true);
let llvm_name = &format!("llvm.{}.i{}", &name[..4], width);
let llfn = cx.get_intrinsic(llvm_name);
bx.call(llfn, &[args[0].immediate(), y], None)
self.call(llfn, &[args[0].immediate(), y], None)
}
"ctpop" => bx.call(cx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
&[args[0].immediate()], None),
"ctpop" => self.call(
cx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
&[args[0].immediate()],
None
),
"bswap" => {
if width == 8 {
args[0].immediate() // byte swap a u8/i8 is just a no-op
} else {
bx.call(cx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
self.call(cx.get_intrinsic(&format!("llvm.bswap.i{}", width)),
&[args[0].immediate()], None)
}
}
"bitreverse" => {
bx.call(cx.get_intrinsic(&format!("llvm.bitreverse.i{}", width)),
self.call(cx.get_intrinsic(&format!("llvm.bitreverse.i{}", width)),
&[args[0].immediate()], None)
}
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => {
let intrinsic = format!("llvm.{}{}.with.overflow.i{}",
if signed { 's' } else { 'u' },
&name[..3], width);
let llfn = bx.cx().get_intrinsic(&intrinsic);
let llfn = cx.get_intrinsic(&intrinsic);
// Convert `i1` to a `bool`, and write it to the out parameter
let pair = bx.call(llfn, &[
let pair = self.call(llfn, &[
args[0].immediate(),
args[1].immediate()
], None);
let val = bx.extract_value(pair, 0);
let overflow = bx.zext(bx.extract_value(pair, 1), cx.type_bool());
let val = self.extract_value(pair, 0);
let overflow = self.zext(
self.extract_value(pair, 1),
cx.type_bool()
);
let dest = result.project_field(bx, 0);
bx.store(val, dest.llval, dest.align);
let dest = result.project_field(bx, 1);
bx.store(overflow, dest.llval, dest.align);
let dest = result.project_field(&self, 0);
self.store(val, dest.llval, dest.align);
let dest = result.project_field(&self, 1);
self.store(overflow, dest.llval, dest.align);
return;
},
"overflowing_add" => bx.add(args[0].immediate(), args[1].immediate()),
"overflowing_sub" => bx.sub(args[0].immediate(), args[1].immediate()),
"overflowing_mul" => bx.mul(args[0].immediate(), args[1].immediate()),
"overflowing_add" => self.add(args[0].immediate(), args[1].immediate()),
"overflowing_sub" => self.sub(args[0].immediate(), args[1].immediate()),
"overflowing_mul" => self.mul(args[0].immediate(), args[1].immediate()),
"exact_div" =>
if signed {
bx.exactsdiv(args[0].immediate(), args[1].immediate())
self.exactsdiv(args[0].immediate(), args[1].immediate())
} else {
bx.exactudiv(args[0].immediate(), args[1].immediate())
self.exactudiv(args[0].immediate(), args[1].immediate())
},
"unchecked_div" =>
if signed {
bx.sdiv(args[0].immediate(), args[1].immediate())
self.sdiv(args[0].immediate(), args[1].immediate())
} else {
bx.udiv(args[0].immediate(), args[1].immediate())
self.udiv(args[0].immediate(), args[1].immediate())
},
"unchecked_rem" =>
if signed {
bx.srem(args[0].immediate(), args[1].immediate())
self.srem(args[0].immediate(), args[1].immediate())
} else {
bx.urem(args[0].immediate(), args[1].immediate())
self.urem(args[0].immediate(), args[1].immediate())
},
"unchecked_shl" => bx.shl(args[0].immediate(), args[1].immediate()),
"unchecked_shl" => self.shl(args[0].immediate(), args[1].immediate()),
"unchecked_shr" =>
if signed {
bx.ashr(args[0].immediate(), args[1].immediate())
self.ashr(args[0].immediate(), args[1].immediate())
} else {
bx.lshr(args[0].immediate(), args[1].immediate())
self.lshr(args[0].immediate(), args[1].immediate())
},
"rotate_left" | "rotate_right" => {
let is_left = name == "rotate_left";
@ -393,16 +397,22 @@ pub fn codegen_intrinsic_call(
let llvm_name = &format!("llvm.fsh{}.i{}",
if is_left { 'l' } else { 'r' }, width);
let llfn = cx.get_intrinsic(llvm_name);
bx.call(llfn, &[val, val, raw_shift], None)
self.call(llfn, &[val, val, raw_shift], None)
} else {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
let width = cx.const_uint(cx.type_ix(width), width);
let shift = bx.urem(raw_shift, width);
let inv_shift = bx.urem(bx.sub(width, raw_shift), width);
let shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
let shift2 = bx.lshr(val, if !is_left { shift } else { inv_shift });
bx.or(shift1, shift2)
let shift = self.urem(raw_shift, width);
let inv_shift = self.urem(self.sub(width, raw_shift), width);
let shift1 = self.shl(
val,
if is_left { shift } else { inv_shift },
);
let shift2 = self.lshr(
val,
if !is_left { shift } else { inv_shift },
);
self.or(shift1, shift2)
}
},
_ => bug!(),
@ -415,17 +425,18 @@ pub fn codegen_intrinsic_call(
return;
}
}
},
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
let sty = &arg_tys[0].sty;
match float_type_width(sty) {
Some(_width) =>
match name {
"fadd_fast" => bx.fadd_fast(args[0].immediate(), args[1].immediate()),
"fsub_fast" => bx.fsub_fast(args[0].immediate(), args[1].immediate()),
"fmul_fast" => bx.fmul_fast(args[0].immediate(), args[1].immediate()),
"fdiv_fast" => bx.fdiv_fast(args[0].immediate(), args[1].immediate()),
"frem_fast" => bx.frem_fast(args[0].immediate(), args[1].immediate()),
"fadd_fast" => self.fadd_fast(args[0].immediate(), args[1].immediate()),
"fsub_fast" => self.fsub_fast(args[0].immediate(), args[1].immediate()),
"fmul_fast" => self.fmul_fast(args[0].immediate(), args[1].immediate()),
"fdiv_fast" => self.fdiv_fast(args[0].immediate(), args[1].immediate()),
"frem_fast" => self.frem_fast(args[0].immediate(), args[1].immediate()),
_ => bug!(),
},
None => {
@ -440,11 +451,11 @@ pub fn codegen_intrinsic_call(
},
"discriminant_value" => {
args[0].deref(bx.cx()).codegen_get_discr(bx, ret_ty)
args[0].deref(cx).codegen_get_discr(&self, ret_ty)
}
name if name.starts_with("simd_") => {
match generic_simd_intrinsic(bx, name,
match generic_simd_intrinsic(&self, name,
callee_ty,
args,
ret_ty, llret_ty,
@ -496,20 +507,23 @@ pub fn codegen_intrinsic_call(
let ty = substs.type_at(0);
if int_type_width_signed(ty, cx).is_some() {
let weak = split[1] == "cxchgweak";
let pair = bx.atomic_cmpxchg(
let pair = self.atomic_cmpxchg(
args[0].immediate(),
args[1].immediate(),
args[2].immediate(),
order,
failorder,
weak);
let val = bx.extract_value(pair, 0);
let success = bx.zext(bx.extract_value(pair, 1), bx.cx().type_bool());
let val = self.extract_value(pair, 0);
let success = self.zext(
self.extract_value(pair, 1),
cx.type_bool()
);
let dest = result.project_field(bx, 0);
bx.store(val, dest.llval, dest.align);
let dest = result.project_field(bx, 1);
bx.store(success, dest.llval, dest.align);
let dest = result.project_field(&self, 0);
self.store(val, dest.llval, dest.align);
let dest = result.project_field(&self, 1);
self.store(success, dest.llval, dest.align);
return;
} else {
return invalid_monomorphization(ty);
@ -520,7 +534,7 @@ pub fn codegen_intrinsic_call(
let ty = substs.type_at(0);
if int_type_width_signed(ty, cx).is_some() {
let size = cx.size_of(ty);
bx.atomic_load(args[0].immediate(), order, size)
self.atomic_load(args[0].immediate(), order, size)
} else {
return invalid_monomorphization(ty);
}
@ -530,7 +544,12 @@ pub fn codegen_intrinsic_call(
let ty = substs.type_at(0);
if int_type_width_signed(ty, cx).is_some() {
let size = cx.size_of(ty);
bx.atomic_store(args[1].immediate(), args[0].immediate(), order, size);
self.atomic_store(
args[1].immediate(),
args[0].immediate(),
order,
size
);
return;
} else {
return invalid_monomorphization(ty);
@ -538,12 +557,12 @@ pub fn codegen_intrinsic_call(
}
"fence" => {
bx.atomic_fence(order, SynchronizationScope::CrossThread);
self.atomic_fence(order, SynchronizationScope::CrossThread);
return;
}
"singlethreadfence" => {
bx.atomic_fence(order, SynchronizationScope::SingleThread);
self.atomic_fence(order, SynchronizationScope::SingleThread);
return;
}
@ -566,7 +585,12 @@ pub fn codegen_intrinsic_call(
let ty = substs.type_at(0);
if int_type_width_signed(ty, cx).is_some() {
bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
self.atomic_rmw(
atom_op,
args[0].immediate(),
args[1].immediate(),
order
)
} else {
return invalid_monomorphization(ty);
}
@ -575,20 +599,24 @@ pub fn codegen_intrinsic_call(
}
"nontemporal_store" => {
let dst = args[0].deref(bx.cx());
args[1].val.nontemporal_store(bx, dst);
let dst = args[0].deref(cx);
args[1].val.nontemporal_store(&self, dst);
return;
}
_ => {
let intr = Intrinsic::find(&name).unwrap_or_else(||
bug!("unknown intrinsic '{}'", name));
let intr = match Intrinsic::find(&name) {
Some(intr) => intr,
None => bug!("unknown intrinsic '{}'", name),
};
fn one<T>(x: Vec<T>) -> T {
assert_eq!(x.len(), 1);
x.into_iter().next().unwrap()
}
fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> {
fn ty_to_type<'ll>(
cx: &CodegenCx<'ll, '_>,
t: &intrinsics::Type
) -> Vec<&'ll Type> {
use intrinsics::Type::*;
match *t {
Void => vec![cx.type_void()],
@ -630,8 +658,8 @@ pub fn codegen_intrinsic_call(
// qux` to be converted into `foo, bar, baz, qux`, integer
// arguments to be truncated as needed and pointers to be
// cast.
fn modify_as_needed(
bx: &Builder<'a, 'll, 'tcx>,
fn modify_as_needed<'ll, 'tcx>(
bx: &Builder<'_, 'll, 'tcx>,
t: &intrinsics::Type,
arg: &OperandRef<'tcx, &'ll Value>,
) -> Vec<&'ll Value> {
@ -682,7 +710,7 @@ pub fn codegen_intrinsic_call(
let outputs = one(ty_to_type(cx, &intr.output));
let llargs: Vec<_> = intr.inputs.iter().zip(args).flat_map(|(t, arg)| {
modify_as_needed(bx, t, arg)
modify_as_needed(&self, t, arg)
}).collect();
assert_eq!(inputs.len(), llargs.len());
@ -691,7 +719,7 @@ pub fn codegen_intrinsic_call(
let f = declare::declare_cfn(cx,
name,
cx.type_func(&inputs, outputs));
bx.call(f, &llargs, None)
self.call(f, &llargs, None)
}
};
@ -701,9 +729,9 @@ pub fn codegen_intrinsic_call(
assert!(!flatten);
for i in 0..elems.len() {
let dest = result.project_field(bx, i);
let val = bx.extract_value(val, i as u64);
bx.store(val, dest.llval, dest.align);
let dest = result.project_field(&self, i);
let val = self.extract_value(val, i as u64);
self.store(val, dest.llval, dest.align);
}
return;
}
@ -714,11 +742,12 @@ pub fn codegen_intrinsic_call(
if !fn_ty.ret.is_ignore() {
if let PassMode::Cast(ty) = fn_ty.ret.mode {
let ptr = bx.pointercast(result.llval, cx.type_ptr_to(ty.llvm_type(cx)));
bx.store(llval, ptr, result.align);
let ptr = self.pointercast(result.llval, cx.type_ptr_to(ty.llvm_type(cx)));
self.store(llval, ptr, result.align);
} else {
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
.val.store(bx, result);
OperandRef::from_immediate_or_packed_pair(&self, llval, result.layout)
.val.store(&self, result);
}
}
}
}

View file

@ -25,10 +25,7 @@ use type_of::LayoutLlvmExt;
use type_::Type;
use value::Value;
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use interfaces::*;
use syntax::symbol::Symbol;
use syntax_pos::Pos;
@ -560,8 +557,6 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
};
if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
use intrinsic::codegen_intrinsic_call;
let dest = match ret_dest {
_ if fn_ty.ret.is_indirect() => llargs[0],
ReturnDest::Nothing => {
@ -628,7 +623,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
let callee_ty = instance.as_ref().unwrap().ty(bx.cx().tcx);
codegen_intrinsic_call(&bx, callee_ty, &fn_ty, &args, dest,
&bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
terminator.source_info.span);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {

View file

@ -20,7 +20,7 @@ use value::Value;
use type_of::LayoutLlvmExt;
use glue;
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedIntrinsicMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, IntrinsicDeclarationMethods};
use std::fmt;

View file

@ -21,10 +21,7 @@ use value::Value;
use glue;
use mir::constant::const_alloc_to_llvm;
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use interfaces::*;
use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};

View file

@ -25,7 +25,7 @@ use type_::Type;
use type_of::LayoutLlvmExt;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedIntrinsicMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, IntrinsicDeclarationMethods};
use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};