提交 d77e34f3 编写于 作者: D Denis Merigoux 提交者: Eduard-Mihai Burtescu

Generalized memset and memcpy

上级 0514c7b1
......@@ -18,7 +18,7 @@
use type_of::{LayoutLlvmExt, PointerKind};
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
use rustc::ty::{self, Ty};
......
......@@ -15,7 +15,7 @@
use value::Value;
use rustc::hir;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods};
use mir::place::PlaceRef;
use mir::operand::OperandValue;
......
......@@ -73,7 +73,9 @@
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::indexed_vec::Idx;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use std::any::Any;
use std::cmp;
......@@ -431,13 +433,13 @@ pub fn to_immediate_scalar<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
val
}
pub fn call_memcpy(
bx: &Builder<'_, 'll, '_>,
dst: &'ll Value,
pub fn call_memcpy<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
bx: &Builder,
dst: Builder::Value,
dst_align: Align,
src: &'ll Value,
src: Builder::Value,
src_align: Align,
n_bytes: &'ll Value,
n_bytes: Builder::Value,
flags: MemFlags,
) {
if flags.contains(MemFlags::NONTEMPORAL) {
......@@ -450,16 +452,16 @@ pub fn call_memcpy(
let cx = bx.cx();
let src_ptr = bx.pointercast(src, cx.type_i8p());
let dst_ptr = bx.pointercast(dst, cx.type_i8p());
let size = bx.intcast(n_bytes, cx.isize_ty, false);
let size = bx.intcast(n_bytes, cx.type_isize(), false);
let volatile = flags.contains(MemFlags::VOLATILE);
bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
}
pub fn memcpy_ty(
bx: &Builder<'_, 'll, '_>,
dst: &'ll Value,
pub fn memcpy_ty<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
bx: &Builder,
dst: Builder::Value,
dst_align: Align,
src: &'ll Value,
src: Builder::Value,
src_align: Align,
layout: TyLayout<'tcx>,
flags: MemFlags,
......@@ -472,15 +474,15 @@ pub fn memcpy_ty(
call_memcpy(bx, dst, dst_align, src, src_align, bx.cx().const_usize(size), flags);
}
pub fn call_memset(
bx: &Builder<'_, 'll, '_>,
ptr: &'ll Value,
fill_byte: &'ll Value,
size: &'ll Value,
align: &'ll Value,
pub fn call_memset<'a, 'tcx: 'a, Builder: BuilderMethods<'a, 'tcx>>(
bx: &Builder,
ptr: Builder::Value,
fill_byte: Builder::Value,
size: Builder::Value,
align: Builder::Value,
volatile: bool,
) -> &'ll Value {
let ptr_width = &bx.cx().sess().target.target.target_pointer_width;
) -> Builder::Value {
let ptr_width = &bx.sess().target.target.target_pointer_width;
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
let llintrinsicfn = bx.cx().get_intrinsic(&intrinsic_key);
let volatile = bx.cx().const_bool(volatile);
......
......@@ -19,7 +19,10 @@
use rustc::ty::layout::{Align, Size};
use rustc::session::{config, Session};
use rustc_data_structures::small_c_str::SmallCStr;
use interfaces::{BuilderMethods, Backend, ConstMethods, TypeMethods};
use interfaces::{
Backend,
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use syntax;
use std::borrow::Cow;
......
......@@ -22,7 +22,7 @@
use monomorphize::Instance;
use type_of::LayoutLlvmExt;
use value::Value;
use interfaces::TypeMethods;
use interfaces::BaseTypeMethods;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TypeFoldable};
......
......@@ -23,7 +23,7 @@
use type_::Type;
use type_of::LayoutLlvmExt;
use value::Value;
use interfaces::{Backend, ConstMethods, TypeMethods};
use interfaces::{Backend, ConstMethods, BaseTypeMethods};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{HasDataLayout, LayoutOf};
......
......@@ -24,7 +24,7 @@
use type_of::LayoutLlvmExt;
use value::Value;
use rustc::ty::{self, Ty};
use interfaces::TypeMethods;
use interfaces::{BaseTypeMethods, DerivedTypeMethods};
use rustc::ty::layout::{Align, LayoutOf};
......
......@@ -23,7 +23,8 @@
use monomorphize::partitioning::CodegenUnit;
use type_::Type;
use type_of::PointeeInfo;
use interfaces::TypeMethods;
use interfaces::{BaseTypeMethods, DerivedTypeMethods,
IntrinsicMethods, BaseIntrinsicMethods, DerivedIntrinsicMethods};
use rustc_data_structures::base_n;
use rustc_data_structures::small_c_str::SmallCStr;
......@@ -320,220 +321,73 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
pub fn sess<'a>(&'a self) -> &'a Session {
&self.tcx.sess
}
pub fn get_intrinsic(&self, key: &str) -> &'b Value {
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
return v;
}
declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
}
}
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.
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
let idx = self.local_gen_sym_counter.get();
self.local_gen_sym_counter.set(idx + 1);
// Include a '.' character, so there can be no accidental conflicts with
// user defined names
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push_str(".");
base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
name
}
impl BaseIntrinsicMethods for CodegenCx<'_, '_> {}
pub fn eh_personality(&self) -> &'b Value {
// The exception handling personality function.
//
// If our compilation unit has the `eh_personality` lang item somewhere
// within it, then we just need to codegen that. Otherwise, we're
// building an rlib which will depend on some upstream implementation of
// this function, so we just codegen a generic reference to it. We don't
// specify any of the types for the function, we just make it a symbol
// that LLVM can later use.
//
// Note that MSVC is a little special here in that we don't use the
// `eh_personality` lang item at all. Currently LLVM has support for
// both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
// *name of the personality function* to decide what kind of unwind side
// tables/landing pads to emit. It looks like Dwarf is used by default,
// injecting a dependency on the `_Unwind_Resume` symbol for resuming
// an "exception", but for MSVC we want to force SEH. This means that we
// can't actually have the personality function be our standard
// `rust_eh_personality` function, but rather we wired it up to the
// CRT's custom personality function, which forces LLVM to consider
// landing pads as "landing pads for SEH".
if let Some(llpersonality) = self.eh_personality.get() {
return llpersonality
}
let tcx = self.tcx;
let llfn = match tcx.lang_items().eh_personality() {
Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
}
_ => {
let name = if base::wants_msvc_seh(self.sess()) {
"__CxxFrameHandler3"
} else {
"rust_eh_personality"
};
let fty = &self.type_variadic_func(&[], &self.type_i32());
declare::declare_cfn(self, name, fty)
}
};
attributes::apply_target_cpu_attr(self, llfn);
self.eh_personality.set(Some(llfn));
llfn
}
// Returns a Value of the "eh_unwind_resume" lang item if one is defined,
// otherwise declares it as an external function.
pub fn eh_unwind_resume(&self) -> &'b Value {
use attributes;
let unwresume = &self.eh_unwind_resume;
if let Some(llfn) = unwresume.get() {
return llfn;
}
let tcx = self.tcx;
assert!(self.sess().target.target.options.custom_unwind_resume);
if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
unwresume.set(Some(llfn));
return llfn;
}
let sig = ty::Binder::bind(tcx.mk_fn_sig(
iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
tcx.types.never,
false,
hir::Unsafety::Unsafe,
Abi::C
));
let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", sig);
attributes::unwind(llfn, true);
attributes::apply_target_cpu_attr(self, llfn);
unwresume.set(Some(llfn));
llfn
}
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
common::type_needs_drop(self.tcx, ty)
}
pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
common::type_is_sized(self.tcx, ty)
}
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
common::type_is_freeze(self.tcx, ty)
}
pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
use syntax_pos::DUMMY_SP;
if ty.is_sized(self.tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
return false;
}
let tail = self.tcx.struct_tail(ty);
match tail.sty {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
_ => bug!("unexpected unsized tail: {:?}", tail.sty),
}
}
}
impl ty::layout::HasDataLayout for CodegenCx<'ll, 'tcx> {
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
&self.tcx.data_layout
}
}
impl HasTargetSpec for CodegenCx<'ll, 'tcx> {
fn target_spec(&self) -> &Target {
&self.tcx.sess.target.target
}
}
impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
impl DerivedIntrinsicMethods for CodegenCx<'b, 'tcx> {
fn get_intrinsic(&self, key: &str) -> &'b Value {
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
return v;
}
}
impl LayoutOf for CodegenCx<'ll, 'tcx> {
type Ty = Ty<'tcx>;
type TyLayout = TyLayout<'tcx>;
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
.unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e {
self.sess().fatal(&e.to_string())
} else {
bug!("failed to get layout for `{}`: {}", ty, e)
})
self.declare_intrinsic(key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
}
}
/// Declare any llvm intrinsics that you might need
fn declare_intrinsic(
cx: &CodegenCx<'ll, '_>,
/// Declare any llvm intrinsics that you might need
fn declare_intrinsic(
&self,
key: &str
) -> Option<&'ll Value> {
) -> Option<&'b Value> {
macro_rules! ifn {
($name:expr, fn() -> $ret:expr) => (
if key == $name {
let f = declare::declare_cfn(cx, $name, cx.type_func(&[], $ret));
let f = declare::declare_cfn(&self, $name, &self.type_func(&[], $ret));
llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone());
&self.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn(...) -> $ret:expr) => (
if key == $name {
let f = declare::declare_cfn(cx, $name, cx.type_variadic_func(&[], $ret));
let f = declare::declare_cfn(&self, $name, &self.type_variadic_func(&[], $ret));
llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone());
&self.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
if key == $name {
let f = declare::declare_cfn(cx, $name, cx.type_func(&[$($arg),*], $ret));
let f = declare::declare_cfn(&self, $name, &self.type_func(&[$($arg),*], $ret));
llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone());
&self.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f);
}
);
}
macro_rules! mk_struct {
($($field_ty:expr),*) => (cx.type_struct( &[$($field_ty),*], false))
($($field_ty:expr),*) => (&self.type_struct( &[$($field_ty),*], false))
}
let i8p = cx.type_i8p();
let void = cx.type_void();
let i1 = cx.type_i1();
let t_i8 = cx.type_i8();
let t_i16 = cx.type_i16();
let t_i32 = cx.type_i32();
let t_i64 = cx.type_i64();
let t_i128 = cx.type_i128();
let t_f32 = cx.type_f32();
let t_f64 = cx.type_f64();
let i8p = &self.type_i8p();
let void = &self.type_void();
let i1 = &self.type_i1();
let t_i8 = &self.type_i8();
let t_i16 = &self.type_i16();
let t_i32 = &self.type_i32();
let t_i64 = &self.type_i64();
let t_i128 = &self.type_i128();
let t_f32 = &self.type_f32();
let t_f64 = &self.type_f64();
let t_v2f32 = cx.type_vector(t_f32, 2);
let t_v4f32 = cx.type_vector(t_f32, 4);
let t_v8f32 = cx.type_vector(t_f32, 8);
let t_v16f32 = cx.type_vector(t_f32, 16);
let t_v2f32 = &self.type_vector(t_f32, 2);
let t_v4f32 = &self.type_vector(t_f32, 4);
let t_v8f32 = &self.type_vector(t_f32, 8);
let t_v16f32 = &self.type_vector(t_f32, 16);
let t_v2f64 = cx.type_vector(t_f64, 2);
let t_v4f64 = cx.type_vector(t_f64, 4);
let t_v8f64 = cx.type_vector(t_f64, 8);
let t_v2f64 = &self.type_vector(t_f64, 2);
let t_v4f64 = &self.type_vector(t_f64, 4);
let t_v8f64 = &self.type_vector(t_f64, 8);
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
......@@ -785,10 +639,162 @@ fn declare_intrinsic(
ifn!("llvm.assume", fn(i1) -> void);
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
if cx.sess().opts.debuginfo != DebugInfo::None {
ifn!("llvm.dbg.declare", fn(cx.type_metadata(), cx.type_metadata()) -> void);
ifn!("llvm.dbg.value", fn(cx.type_metadata(), t_i64, cx.type_metadata()) -> void);
if self.sess().opts.debuginfo != DebugInfo::None {
ifn!("llvm.dbg.declare", fn(&self.type_metadata(), &self.type_metadata()) -> void);
ifn!("llvm.dbg.value", fn(&self.type_metadata(), t_i64, &self.type_metadata()) -> void);
}
return None;
}
}
None
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.
pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
let idx = self.local_gen_sym_counter.get();
self.local_gen_sym_counter.set(idx + 1);
// Include a '.' character, so there can be no accidental conflicts with
// user defined names
let mut name = String::with_capacity(prefix.len() + 6);
name.push_str(prefix);
name.push_str(".");
base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
name
}
pub fn eh_personality(&self) -> &'b Value {
// The exception handling personality function.
//
// If our compilation unit has the `eh_personality` lang item somewhere
// within it, then we just need to codegen that. Otherwise, we're
// building an rlib which will depend on some upstream implementation of
// this function, so we just codegen a generic reference to it. We don't
// specify any of the types for the function, we just make it a symbol
// that LLVM can later use.
//
// Note that MSVC is a little special here in that we don't use the
// `eh_personality` lang item at all. Currently LLVM has support for
// both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
// *name of the personality function* to decide what kind of unwind side
// tables/landing pads to emit. It looks like Dwarf is used by default,
// injecting a dependency on the `_Unwind_Resume` symbol for resuming
// an "exception", but for MSVC we want to force SEH. This means that we
// can't actually have the personality function be our standard
// `rust_eh_personality` function, but rather we wired it up to the
// CRT's custom personality function, which forces LLVM to consider
// landing pads as "landing pads for SEH".
if let Some(llpersonality) = self.eh_personality.get() {
return llpersonality
}
let tcx = self.tcx;
let llfn = match tcx.lang_items().eh_personality() {
Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
}
_ => {
let name = if base::wants_msvc_seh(self.sess()) {
"__CxxFrameHandler3"
} else {
"rust_eh_personality"
};
let fty = &self.type_variadic_func(&[], &self.type_i32());
declare::declare_cfn(self, name, fty)
}
};
attributes::apply_target_cpu_attr(self, llfn);
self.eh_personality.set(Some(llfn));
llfn
}
// Returns a Value of the "eh_unwind_resume" lang item if one is defined,
// otherwise declares it as an external function.
pub fn eh_unwind_resume(&self) -> &'b Value {
use attributes;
let unwresume = &self.eh_unwind_resume;
if let Some(llfn) = unwresume.get() {
return llfn;
}
let tcx = self.tcx;
assert!(self.sess().target.target.options.custom_unwind_resume);
if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
unwresume.set(Some(llfn));
return llfn;
}
let sig = ty::Binder::bind(tcx.mk_fn_sig(
iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
tcx.types.never,
false,
hir::Unsafety::Unsafe,
Abi::C
));
let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", sig);
attributes::unwind(llfn, true);
attributes::apply_target_cpu_attr(self, llfn);
unwresume.set(Some(llfn));
llfn
}
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
common::type_needs_drop(self.tcx, ty)
}
pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
common::type_is_sized(self.tcx, ty)
}
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
common::type_is_freeze(self.tcx, ty)
}
pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
use syntax_pos::DUMMY_SP;
if ty.is_sized(self.tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
return false;
}
let tail = self.tcx.struct_tail(ty);
match tail.sty {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
_ => bug!("unexpected unsized tail: {:?}", tail.sty),
}
}
}
impl ty::layout::HasDataLayout for CodegenCx<'ll, 'tcx> {
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
&self.tcx.data_layout
}
}
impl HasTargetSpec for CodegenCx<'ll, 'tcx> {
fn target_spec(&self) -> &Target {
&self.tcx.sess.target.target
}
}
impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
}
impl LayoutOf for CodegenCx<'ll, 'tcx> {
type Ty = Ty<'tcx>;
type TyLayout = TyLayout<'tcx>;
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty))
.unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e {
self.sess().fatal(&e.to_string())
} else {
bug!("failed to get layout for `{}`: {}", ty, e)
})
}
}
......@@ -17,7 +17,7 @@
use declare;
use rustc::session::config::DebugInfo;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods};
use syntax::attr;
......
......@@ -17,6 +17,7 @@
use super::backend::Backend;
use super::type_::TypeMethods;
use super::consts::ConstMethods;
use super::intrinsic::IntrinsicMethods;
use std::borrow::Cow;
use std::ops::Range;
......@@ -24,7 +25,7 @@
pub trait BuilderMethods<'a, 'tcx: 'a>: Backend {
type CodegenCx: 'a + TypeMethods + ConstMethods + Backend<
type CodegenCx: 'a + TypeMethods + ConstMethods + IntrinsicMethods + Backend<
Value = Self::Value,
BasicBlock = Self::BasicBlock,
Type = Self::Type,
......
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::backend::Backend;
pub trait BaseIntrinsicMethods: Backend {
}
pub trait DerivedIntrinsicMethods: Backend {
fn get_intrinsic(&self, key: &str) -> Self::Value;
fn declare_intrinsic(
&self,
key: &str
) -> Option<Self::Value>;
}
pub trait IntrinsicMethods: BaseIntrinsicMethods + DerivedIntrinsicMethods {}
......@@ -12,8 +12,10 @@
mod backend;
mod consts;
mod type_;
mod intrinsic;
pub use self::builder::BuilderMethods;
pub use self::backend::Backend;
pub use self::consts::ConstMethods;
pub use self::type_::TypeMethods;
pub use self::type_::{TypeMethods, BaseTypeMethods, DerivedTypeMethods};
pub use self::intrinsic::{IntrinsicMethods, BaseIntrinsicMethods, DerivedIntrinsicMethods};
......@@ -10,8 +10,10 @@
use super::backend::Backend;
use common::TypeKind;
use syntax::ast;
use rustc::ty::layout::{self, Align, Size};
pub trait TypeMethods: Backend {
pub trait BaseTypeMethods: Backend {
fn type_void(&self) -> Self::Type;
fn type_metadata(&self) -> Self::Type;
fn type_i1(&self) -> Self::Type;
......@@ -42,3 +44,31 @@ pub trait TypeMethods: Backend {
fn val_ty(&self, v: Self::Value) -> Self::Type;
}
pub trait DerivedTypeMethods: Backend {
fn type_bool(&self) -> Self::Type;
fn type_i8p(&self) -> Self::Type;
fn type_isize(&self) -> Self::Type;
fn type_int(&self) -> Self::Type;
fn type_int_from_ty(
&self,
t: ast::IntTy
) -> Self::Type;
fn type_uint_from_ty(
&self,
t: ast::UintTy
) -> Self::Type;
fn type_float_from_ty(
&self,
t: ast::FloatTy
) -> Self::Type;
fn type_from_integer(&self, i: layout::Integer) -> Self::Type;
fn type_pointee_for_abi_align(&self, align: Align) -> Self::Type;
fn type_padding_filler(
&self,
size: Size,
align: Align
) -> Self::Type;
}
pub trait TypeMethods: BaseTypeMethods + DerivedTypeMethods {}
......@@ -32,7 +32,9 @@
use builder::Builder;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use rustc::session::Session;
use syntax_pos::Span;
......
......@@ -16,7 +16,7 @@
use monomorphize;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
use rustc::ty::{self, Ty};
use rustc::ty::layout::HasDataLayout;
......
......@@ -26,7 +26,9 @@
use type_::Type;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use syntax::symbol::Symbol;
use syntax_pos::Pos;
......
......@@ -25,7 +25,7 @@
use syntax::ast::Mutability;
use syntax::source_map::Span;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
use super::super::callee;
use super::FunctionCx;
......
......@@ -24,7 +24,7 @@
use monomorphize::Instance;
use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
use value::Value;
use interfaces::{BuilderMethods, ConstMethods};
use interfaces::{BuilderMethods, ConstMethods, DerivedTypeMethods};
use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
use syntax::symbol::keywords;
......
......@@ -20,7 +20,7 @@
use type_of::LayoutLlvmExt;
use glue;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedIntrinsicMethods};
use std::fmt;
......
......@@ -22,7 +22,9 @@
use glue;
use mir::constant::const_alloc_to_llvm;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
};
use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};
......
......@@ -26,7 +26,7 @@
use type_of::LayoutLlvmExt;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, TypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedIntrinsicMethods};
use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};
......
......@@ -15,7 +15,7 @@
use llvm;
use llvm::{Bool, False, True};
use context::CodegenCx;
use interfaces::TypeMethods;
use interfaces::{BaseTypeMethods, DerivedTypeMethods, TypeMethods};
use value::Value;
......@@ -42,8 +42,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl TypeMethods for CodegenCx<'ll, 'tcx> {
impl BaseTypeMethods for CodegenCx<'ll, 'tcx> {
fn type_void(&self) -> &'ll Type {
unsafe {
llvm::LLVMVoidTypeInContext(self.llcx)
......@@ -265,20 +264,20 @@ fn ptr_to(&self) -> &Type {
}
}
impl CodegenCx<'ll, 'tcx> {
pub fn type_bool(&self) -> &'ll Type {
impl DerivedTypeMethods for CodegenCx<'ll, 'tcx> {
fn type_bool(&self) -> &'ll Type {
self.type_i8()
}
pub fn type_i8p(&self) -> &'ll Type {
fn type_i8p(&self) -> &'ll Type {
self.type_ptr_to(self.type_i8())
}
pub fn type_isize(&self) -> &'ll Type {
fn type_isize(&self) -> &'ll Type {
self.isize_ty
}
pub fn type_int(&self) -> &'ll Type {
fn type_int(&self) -> &'ll Type {
match &self.sess().target.target.target_c_int_width[..] {
"16" => self.type_i16(),
"32" => self.type_i32(),
......@@ -287,7 +286,7 @@ pub fn type_int(&self) -> &'ll Type {
}
}
pub fn type_int_from_ty(
fn type_int_from_ty(
&self,
t: ast::IntTy
) -> &'ll Type {
......@@ -301,7 +300,7 @@ pub fn type_int_from_ty(
}
}
pub fn type_uint_from_ty(
fn type_uint_from_ty(
&self,
t: ast::UintTy
) -> &'ll Type {
......@@ -315,7 +314,7 @@ pub fn type_uint_from_ty(
}
}
pub fn type_float_from_ty(
fn type_float_from_ty(
&self,
t: ast::FloatTy
) -> &'ll Type {
......@@ -325,7 +324,7 @@ pub fn type_float_from_ty(
}
}
pub fn type_from_integer(&self, i: layout::Integer) -> &'ll Type {
fn type_from_integer(&self, i: layout::Integer) -> &'ll Type {
use rustc::ty::layout::Integer::*;
match i {
I8 => self.type_i8(),
......@@ -338,7 +337,7 @@ pub fn type_from_integer(&self, i: layout::Integer) -> &'ll Type {
/// Return a LLVM type that has at most the required alignment,
/// as a conservative approximation for unknown pointee types.
pub fn type_pointee_for_abi_align(&self, align: Align) -> &'ll Type {
fn type_pointee_for_abi_align(&self, align: Align) -> &'ll Type {
// FIXME(eddyb) We could find a better approximation if ity.align < align.
let ity = layout::Integer::approximate_abi_align(self, align);
self.type_from_integer(ity)
......@@ -346,7 +345,7 @@ pub fn type_pointee_for_abi_align(&self, align: Align) -> &'ll Type {
/// Return a LLVM type that has at most the required alignment,
/// and exactly the required size, as a best-effort padding array.
pub fn type_padding_filler(
fn type_padding_filler(
&self,
size: Size,
align: Align
......@@ -358,3 +357,5 @@ pub fn type_padding_filler(
self.type_array(self.type_from_integer(unit), size / unit_size)
}
}
impl TypeMethods for CodegenCx<'ll, 'tcx> {}
......@@ -16,7 +16,7 @@
use rustc_target::abi::FloatTy;
use rustc_mir::monomorphize::item::DefPathBasedNames;
use type_::Type;
use interfaces::TypeMethods;
use interfaces::{BaseTypeMethods, DerivedTypeMethods};
use std::fmt::Write;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册