1
Fork 0

Traitification of type_ methods

The methods are now attached to CodegenCx instead of Type
This commit is contained in:
Denis Merigoux 2018-09-05 14:14:03 -07:00 committed by Eduard-Mihai Burtescu
parent 5f28e0a0b6
commit 730b13ab51
20 changed files with 458 additions and 463 deletions

View file

@ -18,7 +18,7 @@ use type_::Type;
use type_of::{LayoutLlvmExt, PointerKind}; use type_of::{LayoutLlvmExt, PointerKind};
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
@ -111,16 +111,16 @@ pub trait LlvmType {
impl LlvmType for Reg { impl LlvmType for Reg {
fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
match self.kind { match self.kind {
RegKind::Integer => Type::ix(cx, self.size.bits()), RegKind::Integer => cx.ix(self.size.bits()),
RegKind::Float => { RegKind::Float => {
match self.size.bits() { match self.size.bits() {
32 => Type::f32(cx), 32 => cx.f32(),
64 => Type::f64(cx), 64 => cx.f64(),
_ => bug!("unsupported float: {:?}", self) _ => bug!("unsupported float: {:?}", self)
} }
} }
RegKind::Vector => { RegKind::Vector => {
Type::vector(Type::i8(cx), self.size.bytes()) cx.vector(cx.i8(), self.size.bytes())
} }
} }
} }
@ -144,7 +144,7 @@ impl LlvmType for CastTarget {
// Simplify to array when all chunks are the same size and type // Simplify to array when all chunks are the same size and type
if rem_bytes == 0 { if rem_bytes == 0 {
return Type::array(rest_ll_unit, rest_count); return cx.array(rest_ll_unit, rest_count);
} }
} }
@ -159,10 +159,10 @@ impl LlvmType for CastTarget {
if rem_bytes != 0 { if rem_bytes != 0 {
// Only integers can be really split further. // Only integers can be really split further.
assert_eq!(self.rest.unit.kind, RegKind::Integer); assert_eq!(self.rest.unit.kind, RegKind::Integer);
args.push(Type::ix(cx, rem_bytes * 8)); args.push(cx.ix(rem_bytes * 8));
} }
Type::struct_(cx, &args, false) cx.struct_(&args, false)
} }
} }
@ -212,7 +212,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
let can_store_through_cast_ptr = false; let can_store_through_cast_ptr = false;
if can_store_through_cast_ptr { if can_store_through_cast_ptr {
let cast_dst = bx.pointercast(dst.llval, cast.llvm_type(cx).ptr_to()); let cast_dst = bx.pointercast(dst.llval, cx.ptr_to(cast.llvm_type(cx)));
bx.store(val, cast_dst, self.layout.align); bx.store(val, cast_dst, self.layout.align);
} else { } else {
// The actual return type is a struct, but the ABI // The actual return type is a struct, but the ABI
@ -240,9 +240,9 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
// ...and then memcpy it to the intended destination. // ...and then memcpy it to the intended destination.
base::call_memcpy(bx, base::call_memcpy(bx,
bx.pointercast(dst.llval, Type::i8p(cx)), bx.pointercast(dst.llval, cx.i8p()),
self.layout.align, self.layout.align,
bx.pointercast(llscratch, Type::i8p(cx)), bx.pointercast(llscratch, cx.i8p()),
scratch_align, scratch_align,
cx.c_usize(self.layout.size.bytes()), cx.c_usize(self.layout.size.bytes()),
MemFlags::empty()); MemFlags::empty());
@ -635,14 +635,14 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
); );
let llreturn_ty = match self.ret.mode { let llreturn_ty = match self.ret.mode {
PassMode::Ignore => Type::void(cx), PassMode::Ignore => cx.void(),
PassMode::Direct(_) | PassMode::Pair(..) => { PassMode::Direct(_) | PassMode::Pair(..) => {
self.ret.layout.immediate_llvm_type(cx) self.ret.layout.immediate_llvm_type(cx)
} }
PassMode::Cast(cast) => cast.llvm_type(cx), PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(..) => { PassMode::Indirect(..) => {
llargument_tys.push(self.ret.memory_ty(cx).ptr_to()); llargument_tys.push(cx.ptr_to(self.ret.memory_ty(cx)));
Type::void(cx) cx.void()
} }
}; };
@ -668,15 +668,15 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
continue; continue;
} }
PassMode::Cast(cast) => cast.llvm_type(cx), PassMode::Cast(cast) => cast.llvm_type(cx),
PassMode::Indirect(_, None) => arg.memory_ty(cx).ptr_to(), PassMode::Indirect(_, None) => cx.ptr_to(arg.memory_ty(cx)),
}; };
llargument_tys.push(llarg_ty); llargument_tys.push(llarg_ty);
} }
if self.variadic { if self.variadic {
Type::variadic_func(&llargument_tys, llreturn_ty) cx.variadic_func(&llargument_tys, llreturn_ty)
} else { } else {
Type::func(&llargument_tys, llreturn_ty) cx.func(&llargument_tys, llreturn_ty)
} }
} }

View file

@ -10,13 +10,12 @@
use llvm; use llvm;
use context::CodegenCx; use context::CodegenCx;
use type_::Type;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use builder::Builder; use builder::Builder;
use value::Value; use value::Value;
use rustc::hir; use rustc::hir;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use mir::place::PlaceRef; use mir::place::PlaceRef;
use mir::operand::OperandValue; use mir::operand::OperandValue;
@ -76,9 +75,9 @@ pub fn codegen_inline_asm(
// Depending on how many outputs we have, the return type is different // Depending on how many outputs we have, the return type is different
let num_outputs = output_types.len(); let num_outputs = output_types.len();
let output_type = match num_outputs { let output_type = match num_outputs {
0 => Type::void(bx.cx()), 0 => bx.cx().void(),
1 => output_types[0], 1 => output_types[0],
_ => Type::struct_(bx.cx(), &output_types, false) _ => bx.cx().struct_(&output_types, false)
}; };
let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap(); let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();

View file

@ -456,6 +456,14 @@ impl CommonWriteMethods for CodegenContext<'ll> {
} }
} }
impl CodegenContext<'ll> {
pub fn ptr_to(&self, ty: &'ll Type) -> &'ll Type {
unsafe {
llvm::LLVMPointerType(ty, 0)
}
}
}
pub struct DiagnosticHandlers<'a> { pub struct DiagnosticHandlers<'a> {
data: *mut (&'a CodegenContext<'a>, &'a Handler), data: *mut (&'a CodegenContext<'a>, &'a Handler),
@ -2609,7 +2617,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::M
"\x01__imp_" "\x01__imp_"
}; };
unsafe { unsafe {
let i8p_ty = Type::i8p_llcx(llcx); let i8p_ty = Type::i8p_llcx(cgcx, llcx);
let globals = base::iter_globals(llmod) let globals = base::iter_globals(llmod)
.filter(|&val| { .filter(|&val| {
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage && llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&

View file

@ -74,7 +74,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods}; use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods, TypeMethods};
use std::any::Any; use std::any::Any;
use std::cmp; use std::cmp;
@ -234,13 +234,13 @@ pub fn unsize_thin_ptr(
(&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
&ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
assert!(bx.cx().type_is_sized(a)); assert!(bx.cx().type_is_sized(a));
let ptr_ty = bx.cx().layout_of(b).llvm_type(bx.cx()).ptr_to(); let ptr_ty = bx.cx().ptr_to(bx.cx().layout_of(b).llvm_type(bx.cx()));
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
} }
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty()); let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
assert!(bx.cx().type_is_sized(a)); assert!(bx.cx().type_is_sized(a));
let ptr_ty = bx.cx().layout_of(b).llvm_type(bx.cx()).ptr_to(); let ptr_ty = bx.cx().ptr_to(bx.cx().layout_of(b).llvm_type(bx.cx()));
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
} }
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
@ -353,14 +353,14 @@ fn cast_shift_rhs<'ll, F, G>(bx: &Builder<'_, 'll, '_>,
if op.is_shift() { if op.is_shift() {
let mut rhs_llty = bx.cx().val_ty(rhs); let mut rhs_llty = bx.cx().val_ty(rhs);
let mut lhs_llty = bx.cx().val_ty(lhs); let mut lhs_llty = bx.cx().val_ty(lhs);
if rhs_llty.kind() == TypeKind::Vector { if bx.cx().kind(rhs_llty) == TypeKind::Vector {
rhs_llty = rhs_llty.element_type() rhs_llty = bx.cx().element_type(rhs_llty)
} }
if lhs_llty.kind() == TypeKind::Vector { if bx.cx().kind(lhs_llty) == TypeKind::Vector {
lhs_llty = lhs_llty.element_type() lhs_llty = bx.cx().element_type(lhs_llty)
} }
let rhs_sz = rhs_llty.int_width(); let rhs_sz = bx.cx().int_width(rhs_llty);
let lhs_sz = lhs_llty.int_width(); let lhs_sz = bx.cx().int_width(lhs_llty);
if lhs_sz < rhs_sz { if lhs_sz < rhs_sz {
trunc(rhs, lhs_llty) trunc(rhs, lhs_llty)
} else if lhs_sz > rhs_sz { } else if lhs_sz > rhs_sz {
@ -393,8 +393,8 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
bx: &Builder<'_ ,'ll, '_, &'ll Value>, bx: &Builder<'_ ,'ll, '_, &'ll Value>,
val: &'ll Value val: &'ll Value
) -> &'ll Value { ) -> &'ll Value {
if bx.cx().val_ty(val) == Type::i1(bx.cx()) { if bx.cx().val_ty(val) == bx.cx().i1() {
bx.zext(val, Type::i8(bx.cx())) bx.zext(val, bx.cx().i8())
} else { } else {
val val
} }
@ -417,7 +417,7 @@ pub fn to_immediate_scalar(
scalar: &layout::Scalar, scalar: &layout::Scalar,
) -> &'ll Value { ) -> &'ll Value {
if scalar.is_bool() { if scalar.is_bool() {
return bx.trunc(val, Type::i1(bx.cx())); return bx.trunc(val, bx.cx().i1());
} }
val val
} }
@ -434,13 +434,13 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
if flags.contains(MemFlags::NONTEMPORAL) { if flags.contains(MemFlags::NONTEMPORAL) {
// HACK(nox): This is inefficient but there is no nontemporal memcpy. // HACK(nox): This is inefficient but there is no nontemporal memcpy.
let val = bx.load(src, src_align); let val = bx.load(src, src_align);
let ptr = bx.pointercast(dst, bx.cx().val_ty(val).ptr_to()); let ptr = bx.pointercast(dst, bx.cx().ptr_to(bx.cx().val_ty(val)));
bx.store_with_flags(val, ptr, dst_align, flags); bx.store_with_flags(val, ptr, dst_align, flags);
return; return;
} }
let cx = bx.cx(); let cx = bx.cx();
let src_ptr = bx.pointercast(src, Type::i8p(cx)); let src_ptr = bx.pointercast(src, cx.i8p());
let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let dst_ptr = bx.pointercast(dst, cx.i8p());
let size = bx.intcast(n_bytes, cx.isize_ty, false); let size = bx.intcast(n_bytes, cx.isize_ty, false);
let volatile = flags.contains(MemFlags::VOLATILE); let volatile = flags.contains(MemFlags::VOLATILE);
bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile); bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
@ -551,7 +551,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
use_start_lang_item: bool, use_start_lang_item: bool,
) { ) {
let llfty = let llfty =
Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx)); cx.func(&[cx.t_int(), cx.ptr_to(cx.i8p())], cx.t_int());
let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output(); let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
// Given that `main()` has no arguments, // Given that `main()` has no arguments,
@ -594,7 +594,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
start_def_id, start_def_id,
cx.tcx.intern_substs(&[main_ret_ty.into()]), cx.tcx.intern_substs(&[main_ret_ty.into()]),
); );
(start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()), (start_fn, vec![bx.pointercast(rust_main, cx.ptr_to(cx.i8p())),
arg_argc, arg_argv]) arg_argc, arg_argv])
} else { } else {
debug!("using user-defined start fn"); debug!("using user-defined start fn");
@ -602,7 +602,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
}; };
let result = bx.call(start_fn, &args, None); let result = bx.call(start_fn, &args, None);
bx.ret(bx.intcast(result, Type::c_int(cx), true)); bx.ret(bx.intcast(result, cx.t_int(), true));
} }
} }
@ -1151,7 +1151,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if !cx.used_statics.borrow().is_empty() { if !cx.used_statics.borrow().is_empty() {
let name = const_cstr!("llvm.used"); let name = const_cstr!("llvm.used");
let section = const_cstr!("llvm.metadata"); let section = const_cstr!("llvm.metadata");
let array = cx.c_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow()); let array = cx.c_array(&cx.ptr_to(cx.i8()), &*cx.used_statics.borrow());
unsafe { unsafe {
let g = llvm::LLVMAddGlobal(cx.llmod, let g = llvm::LLVMAddGlobal(cx.llmod,

View file

@ -19,7 +19,7 @@ use rustc::ty::TyCtxt;
use rustc::ty::layout::{Align, Size}; use rustc::ty::layout::{Align, Size};
use rustc::session::{config, Session}; use rustc::session::{config, Session};
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use interfaces::{BuilderMethods, Backend, CommonMethods, CommonWriteMethods}; use interfaces::{BuilderMethods, Backend, CommonMethods, CommonWriteMethods, TypeMethods};
use syntax; use syntax;
use std::borrow::Cow; use std::borrow::Cow;
@ -765,7 +765,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
debug!("Asm Output Type: {:?}", output); debug!("Asm Output Type: {:?}", output);
let fty = type_::Type::func(&argtys[..], output); let fty = &self.cx().func(&argtys[..], output);
unsafe { unsafe {
// Ask LLVM to verify that the constraints are well-formed. // Ask LLVM to verify that the constraints are well-formed.
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons); let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons);
@ -861,10 +861,10 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value { fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
unsafe { unsafe {
let elt_ty = self.cx.val_ty(elt); let elt_ty = self.cx.val_ty(elt);
let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64)); let undef = llvm::LLVMGetUndef(&self.cx().vector(elt_ty, num_elts as u64));
let vec = self.insert_element(undef, elt, self.cx.c_i32(0)); let vec = self.insert_element(undef, elt, self.cx.c_i32(0));
let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64); let vec_i32_ty = &self.cx().vector(&self.cx().i32(), num_elts as u64);
self.shuffle_vector(vec, undef, self.cx.c_null(vec_i32_ty)) self.shuffle_vector(vec, undef, self.cx().c_null(vec_i32_ty))
} }
} }
@ -1142,9 +1142,9 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
ptr: &'ll Value) -> &'ll Value { ptr: &'ll Value) -> &'ll Value {
let dest_ptr_ty = self.cx.val_ty(ptr); let dest_ptr_ty = self.cx.val_ty(ptr);
let stored_ty = self.cx.val_ty(val); let stored_ty = self.cx.val_ty(val);
let stored_ptr_ty = stored_ty.ptr_to(); let stored_ptr_ty = self.cx.ptr_to(stored_ty);
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer); assert_eq!(self.cx.kind(dest_ptr_ty), llvm::TypeKind::Pointer);
if dest_ptr_ty == stored_ptr_ty { if dest_ptr_ty == stored_ptr_ty {
ptr ptr
@ -1163,14 +1163,14 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> { args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
let mut fn_ty = self.cx.val_ty(llfn); let mut fn_ty = self.cx.val_ty(llfn);
// Strip off pointers // Strip off pointers
while fn_ty.kind() == llvm::TypeKind::Pointer { while self.cx.kind(fn_ty) == llvm::TypeKind::Pointer {
fn_ty = fn_ty.element_type(); fn_ty = self.cx.element_type(fn_ty);
} }
assert!(fn_ty.kind() == llvm::TypeKind::Function, assert!(self.cx.kind(fn_ty) == llvm::TypeKind::Function,
"builder::{} not passed a function, but {:?}", typ, fn_ty); "builder::{} not passed a function, but {:?}", typ, fn_ty);
let param_tys = fn_ty.func_params(); let param_tys = self.cx.func_params(fn_ty);
let all_args_match = param_tys.iter() let all_args_match = param_tys.iter()
.zip(args.iter().map(|&v| self.cx().val_ty(v))) .zip(args.iter().map(|&v| self.cx().val_ty(v)))
@ -1227,7 +1227,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic); let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
let ptr = self.pointercast(ptr, type_::Type::i8p(self.cx)); let ptr = self.pointercast(ptr, self.cx.i8p());
self.call(lifetime_intrinsic, &[self.cx.c_u64(size), ptr], None); self.call(lifetime_intrinsic, &[self.cx.c_u64(size), ptr], None);
} }

View file

@ -24,7 +24,7 @@ use declare;
use type_::Type; use type_::Type;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use value::Value; use value::Value;
use interfaces::{Backend, CommonMethods, CommonWriteMethods}; use interfaces::{Backend, CommonMethods, CommonWriteMethods, TypeMethods};
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::ty::layout::{HasDataLayout, LayoutOf};
@ -236,19 +236,19 @@ impl<'ll, 'tcx: 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
} }
fn c_bool(&self, val: bool) -> &'ll Value { fn c_bool(&self, val: bool) -> &'ll Value {
&self.c_uint(Type::i1(&self), val as u64) &self.c_uint(&self.i1(), val as u64)
} }
fn c_i32(&self, i: i32) -> &'ll Value { fn c_i32(&self, i: i32) -> &'ll Value {
&self.c_int(Type::i32(&self), i as i64) &self.c_int(&self.i32(), i as i64)
} }
fn c_u32(&self, i: u32) -> &'ll Value { fn c_u32(&self, i: u32) -> &'ll Value {
&self.c_uint(Type::i32(&self), i as u64) &self.c_uint(&self.i32(), i as u64)
} }
fn c_u64(&self, i: u64) -> &'ll Value { fn c_u64(&self, i: u64) -> &'ll Value {
&self.c_uint(Type::i64(&self), i) &self.c_uint(&self.i64(), i)
} }
fn c_usize(&self, i: u64) -> &'ll Value { fn c_usize(&self, i: u64) -> &'ll Value {
@ -262,7 +262,7 @@ impl<'ll, 'tcx: 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
} }
fn c_u8(&self, i: u8) -> &'ll Value { fn c_u8(&self, i: u8) -> &'ll Value {
&self.c_uint(Type::i8(&self), i as u64) &self.c_uint(&self.i8(), i as u64)
} }
@ -300,7 +300,7 @@ impl<'ll, 'tcx: 'll> CommonMethods for CodegenCx<'ll, 'tcx> {
fn c_str_slice(&self, s: LocalInternedString) -> &'ll Value { fn c_str_slice(&self, s: LocalInternedString) -> &'ll Value {
let len = s.len(); let len = s.len();
let cs = consts::ptrcast(&self.c_cstr(s, false), let cs = consts::ptrcast(&self.c_cstr(s, false),
&self.layout_of(&self.tcx.mk_str()).llvm_type(&self).ptr_to()); &self.ptr_to(&self.layout_of(&self.tcx.mk_str()).llvm_type(&self)));
&self.c_fat_ptr(cs, &self.c_usize(len as u64)) &self.c_fat_ptr(cs, &self.c_usize(len as u64))
} }
@ -505,11 +505,11 @@ pub fn shift_mask_val(
mask_llty: &'ll Type, mask_llty: &'ll Type,
invert: bool invert: bool
) -> &'ll Value { ) -> &'ll Value {
let kind = llty.kind(); let kind = bx.cx().kind(llty);
match kind { match kind {
TypeKind::Integer => { TypeKind::Integer => {
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc. // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
let val = llty.int_width() - 1; let val = bx.cx().int_width(llty) - 1;
if invert { if invert {
bx.cx.c_int(mask_llty, !val as i64) bx.cx.c_int(mask_llty, !val as i64)
} else { } else {
@ -517,8 +517,13 @@ pub fn shift_mask_val(
} }
}, },
TypeKind::Vector => { TypeKind::Vector => {
let mask = shift_mask_val(bx, llty.element_type(), mask_llty.element_type(), invert); let mask = shift_mask_val(
bx.vector_splat(mask_llty.vector_length(), mask) bx,
bx.cx().element_type(llty),
bx.cx().element_type(mask_llty),
invert
);
bx.vector_splat(bx.cx().vector_length(mask_llty), mask)
}, },
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
} }

View file

@ -24,7 +24,7 @@ use type_::Type;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use value::Value; use value::Value;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use interfaces::CommonWriteMethods; use interfaces::{CommonWriteMethods, TypeMethods};
use rustc::ty::layout::{Align, LayoutOf}; use rustc::ty::layout::{Align, LayoutOf};
@ -313,8 +313,8 @@ pub fn codegen_static<'a, 'tcx>(
// boolean SSA values are i1, but they have to be stored in i8 slots, // boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected // otherwise some LLVM optimization passes don't work as expected
let mut val_llty = cx.val_ty(v); let mut val_llty = cx.val_ty(v);
let v = if val_llty == Type::i1(cx) { let v = if val_llty == cx.i1() {
val_llty = Type::i8(cx); val_llty = cx.i8();
llvm::LLVMConstZExt(v, val_llty) llvm::LLVMConstZExt(v, val_llty)
} else { } else {
v v
@ -432,7 +432,7 @@ pub fn codegen_static<'a, 'tcx>(
if attrs.flags.contains(CodegenFnAttrFlags::USED) { if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// This static will be stored in the llvm.used variable which is an array of i8* // This static will be stored in the llvm.used variable which is an array of i8*
let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx)); let cast = llvm::LLVMConstPointerCast(g, cx.i8p());
cx.used_statics.borrow_mut().push(cast); cx.used_statics.borrow_mut().push(cast);
} }
} }

View file

@ -23,6 +23,7 @@ use value::Value;
use monomorphize::partitioning::CodegenUnit; use monomorphize::partitioning::CodegenUnit;
use type_::Type; use type_::Type;
use type_of::PointeeInfo; use type_of::PointeeInfo;
use interfaces::TypeMethods;
use rustc_data_structures::base_n; use rustc_data_structures::base_n;
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
@ -379,7 +380,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
} else { } else {
"rust_eh_personality" "rust_eh_personality"
}; };
let fty = Type::variadic_func(&[], Type::i32(self)); let fty = &self.variadic_func(&[], &self.i32());
declare::declare_cfn(self, name, fty) declare::declare_cfn(self, name, fty)
} }
}; };
@ -487,7 +488,7 @@ fn declare_intrinsic(
macro_rules! ifn { macro_rules! ifn {
($name:expr, fn() -> $ret:expr) => ( ($name:expr, fn() -> $ret:expr) => (
if key == $name { if key == $name {
let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret)); let f = declare::declare_cfn(cx, $name, cx.func(&[], $ret));
llvm::SetUnnamedAddr(f, false); llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone()); cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f); return Some(f);
@ -495,7 +496,7 @@ fn declare_intrinsic(
); );
($name:expr, fn(...) -> $ret:expr) => ( ($name:expr, fn(...) -> $ret:expr) => (
if key == $name { if key == $name {
let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret)); let f = declare::declare_cfn(cx, $name, cx.variadic_func(&[], $ret));
llvm::SetUnnamedAddr(f, false); llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone()); cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f); return Some(f);
@ -503,7 +504,7 @@ fn declare_intrinsic(
); );
($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
if key == $name { if key == $name {
let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret)); let f = declare::declare_cfn(cx, $name, cx.func(&[$($arg),*], $ret));
llvm::SetUnnamedAddr(f, false); llvm::SetUnnamedAddr(f, false);
cx.intrinsics.borrow_mut().insert($name, f.clone()); cx.intrinsics.borrow_mut().insert($name, f.clone());
return Some(f); return Some(f);
@ -511,28 +512,28 @@ fn declare_intrinsic(
); );
} }
macro_rules! mk_struct { macro_rules! mk_struct {
($($field_ty:expr),*) => (Type::struct_(cx, &[$($field_ty),*], false)) ($($field_ty:expr),*) => (cx.struct_( &[$($field_ty),*], false))
} }
let i8p = Type::i8p(cx); let i8p = cx.i8p();
let void = Type::void(cx); let void = cx.void();
let i1 = Type::i1(cx); let i1 = cx.i1();
let t_i8 = Type::i8(cx); let t_i8 = cx.i8();
let t_i16 = Type::i16(cx); let t_i16 = cx.i16();
let t_i32 = Type::i32(cx); let t_i32 = cx.i32();
let t_i64 = Type::i64(cx); let t_i64 = cx.i64();
let t_i128 = Type::i128(cx); let t_i128 = cx.i128();
let t_f32 = Type::f32(cx); let t_f32 = cx.f32();
let t_f64 = Type::f64(cx); let t_f64 = cx.f64();
let t_v2f32 = Type::vector(t_f32, 2); let t_v2f32 = cx.vector(t_f32, 2);
let t_v4f32 = Type::vector(t_f32, 4); let t_v4f32 = cx.vector(t_f32, 4);
let t_v8f32 = Type::vector(t_f32, 8); let t_v8f32 = cx.vector(t_f32, 8);
let t_v16f32 = Type::vector(t_f32, 16); let t_v16f32 = cx.vector(t_f32, 16);
let t_v2f64 = Type::vector(t_f64, 2); let t_v2f64 = cx.vector(t_f64, 2);
let t_v4f64 = Type::vector(t_f64, 4); let t_v4f64 = cx.vector(t_f64, 4);
let t_v8f64 = Type::vector(t_f64, 8); let t_v8f64 = cx.vector(t_f64, 8);
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void); 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); ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
@ -785,8 +786,8 @@ fn declare_intrinsic(
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void); ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
if cx.sess().opts.debuginfo != DebugInfo::None { if cx.sess().opts.debuginfo != DebugInfo::None {
ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void); ifn!("llvm.dbg.declare", fn(cx.metadata(), cx.metadata()) -> void);
ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void); ifn!("llvm.dbg.value", fn(cx.metadata(), t_i64, cx.metadata()) -> void);
} }
None None

View file

@ -16,9 +16,8 @@ use common::CodegenCx;
use builder::Builder; use builder::Builder;
use declare; use declare;
use rustc::session::config::DebugInfo; use rustc::session::config::DebugInfo;
use type_::Type;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use syntax::attr; use syntax::attr;
@ -56,7 +55,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
unsafe { unsafe {
let llvm_type = Type::array(Type::i8(cx), let llvm_type = cx.array(cx.i8(),
section_contents.len() as u64); section_contents.len() as u64);
let section_var = declare::define_global(cx, section_var_name, let section_var = declare::define_global(cx, section_var_name,

View file

@ -22,22 +22,20 @@ pub trait TypeMethods : Backend {
fn ix(&self, num_bites: u64) -> Self::Type; fn ix(&self, num_bites: u64) -> Self::Type;
fn f32(&self) -> Self::Type; fn f32(&self) -> Self::Type;
fn f64(&self) -> Self::Type; fn f64(&self) -> Self::Type;
fn bool(&self) -> Self::Type; fn x86_mmx(&self) -> Self::Type;
fn char(&self) -> Self::Type;
fn i8p(&self) -> Self::Type;
fn func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; fn func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
fn variadic_func(&self, args: &[Self::Type]) -> Self::Type; fn variadic_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
fn struct_(&self, els: &[Self::Type], packed: bool) -> Self::Type; fn struct_(&self, els: &[Self::Type], packed: bool) -> Self::Type;
fn named_struct(&self, name: &str) -> Self::Type; fn named_struct(&self, name: &str) -> Self::Type;
fn array(&self, ty: Self::Type, len: u64) -> Self::Type; fn array(&self, ty: Self::Type, len: u64) -> Self::Type;
fn vector(&self, ty: Self::Type, len: u64) -> Self::Type; fn vector(&self, ty: Self::Type, len: u64) -> Self::Type;
fn kind(&self, ty: Self::Type) -> Self::TypeKind; fn kind(&self, ty: Self::Type) -> Self::TypeKind;
fn set_struct_body(&self, els: &[Self::Type], packed: bool); fn set_struct_body(&self, ty: Self::Type, els: &[Self::Type], packed: bool);
fn ptr_to(&self, ty: Self::Type) -> Self::Type; fn ptr_to(&self, ty: Self::Type) -> Self::Type;
fn element_type(&self, ty: Self::Type) -> Self::Type; fn element_type(&self, ty: Self::Type) -> Self::Type;
fn vector_length(&self, ty: Self::Type) -> usize; fn vector_length(&self, ty: Self::Type) -> usize;
fn func_params(&self, ty: Self::Type) -> Vec<Self::Type>; fn func_params(&self, ty: Self::Type) -> Vec<Self::Type>;
fn float_width(&self, ty: Self::Type) -> usize; fn float_width(&self, ty: Self::Type) -> usize;
fn int_width(&self, ty: Self::Type) -> usize; fn int_width(&self, ty: Self::Type) -> u64;
} }

View file

@ -32,7 +32,7 @@ use syntax::symbol::Symbol;
use builder::Builder; use builder::Builder;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use rustc::session::Session; use rustc::session::Session;
use syntax_pos::Span; use syntax_pos::Span;
@ -252,7 +252,7 @@ pub fn codegen_intrinsic_call(
let tp_ty = substs.type_at(0); let tp_ty = substs.type_at(0);
let mut ptr = args[0].immediate(); let mut ptr = args[0].immediate();
if let PassMode::Cast(ty) = fn_ty.ret.mode { if let PassMode::Cast(ty) = fn_ty.ret.mode {
ptr = bx.pointercast(ptr, ty.llvm_type(cx).ptr_to()); ptr = bx.pointercast(ptr, bx.cx().ptr_to(ty.llvm_type(cx)));
} }
let load = bx.volatile_load(ptr); let load = bx.volatile_load(ptr);
let align = if name == "unaligned_volatile_load" { let align = if name == "unaligned_volatile_load" {
@ -338,7 +338,7 @@ pub fn codegen_intrinsic_call(
args[1].immediate() args[1].immediate()
], None); ], None);
let val = bx.extract_value(pair, 0); let val = bx.extract_value(pair, 0);
let overflow = bx.zext(bx.extract_value(pair, 1), Type::bool(cx)); let overflow = bx.zext(bx.extract_value(pair, 1), cx.bool());
let dest = result.project_field(bx, 0); let dest = result.project_field(bx, 0);
bx.store(val, dest.llval, dest.align); bx.store(val, dest.llval, dest.align);
@ -388,7 +388,7 @@ pub fn codegen_intrinsic_call(
} else { } else {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
let width = cx.c_uint(Type::ix(cx, width), width); let width = cx.c_uint(cx.ix(width), width);
let shift = bx.urem(raw_shift, width); let shift = bx.urem(raw_shift, width);
let inv_shift = bx.urem(bx.sub(width, 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 shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
@ -495,7 +495,7 @@ pub fn codegen_intrinsic_call(
failorder, failorder,
weak); weak);
let val = bx.extract_value(pair, 0); let val = bx.extract_value(pair, 0);
let success = bx.zext(bx.extract_value(pair, 1), Type::bool(bx.cx())); let success = bx.zext(bx.extract_value(pair, 1), bx.cx().bool());
let dest = result.project_field(bx, 0); let dest = result.project_field(bx, 0);
bx.store(val, dest.llval, dest.align); bx.store(val, dest.llval, dest.align);
@ -582,32 +582,32 @@ pub fn codegen_intrinsic_call(
fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> { fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> {
use intrinsics::Type::*; use intrinsics::Type::*;
match *t { match *t {
Void => vec![Type::void(cx)], Void => vec![cx.void()],
Integer(_signed, _width, llvm_width) => { Integer(_signed, _width, llvm_width) => {
vec![Type::ix(cx, llvm_width as u64)] vec![cx.ix( llvm_width as u64)]
} }
Float(x) => { Float(x) => {
match x { match x {
32 => vec![Type::f32(cx)], 32 => vec![cx.f32()],
64 => vec![Type::f64(cx)], 64 => vec![cx.f64()],
_ => bug!() _ => bug!()
} }
} }
Pointer(ref t, ref llvm_elem, _const) => { Pointer(ref t, ref llvm_elem, _const) => {
let t = llvm_elem.as_ref().unwrap_or(t); let t = llvm_elem.as_ref().unwrap_or(t);
let elem = one(ty_to_type(cx, t)); let elem = one(ty_to_type(cx, t));
vec![elem.ptr_to()] vec![cx.ptr_to(elem)]
} }
Vector(ref t, ref llvm_elem, length) => { Vector(ref t, ref llvm_elem, length) => {
let t = llvm_elem.as_ref().unwrap_or(t); let t = llvm_elem.as_ref().unwrap_or(t);
let elem = one(ty_to_type(cx, t)); let elem = one(ty_to_type(cx, t));
vec![Type::vector(elem, length as u64)] vec![cx.vector(elem, length as u64)]
} }
Aggregate(false, ref contents) => { Aggregate(false, ref contents) => {
let elems = contents.iter() let elems = contents.iter()
.map(|t| one(ty_to_type(cx, t))) .map(|t| one(ty_to_type(cx, t)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
vec![Type::struct_(cx, &elems, false)] vec![cx.struct_( &elems, false)]
} }
Aggregate(true, ref contents) => { Aggregate(true, ref contents) => {
contents.iter() contents.iter()
@ -646,20 +646,20 @@ pub fn codegen_intrinsic_call(
} }
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => { intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
let llvm_elem = one(ty_to_type(bx.cx(), llvm_elem)); let llvm_elem = one(ty_to_type(bx.cx(), llvm_elem));
vec![bx.pointercast(arg.immediate(), llvm_elem.ptr_to())] vec![bx.pointercast(arg.immediate(), bx.cx().ptr_to(llvm_elem))]
} }
intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => { intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
let llvm_elem = one(ty_to_type(bx.cx(), llvm_elem)); let llvm_elem = one(ty_to_type(bx.cx(), llvm_elem));
vec![ vec![
bx.bitcast(arg.immediate(), bx.bitcast(arg.immediate(),
Type::vector(llvm_elem, length as u64)) bx.cx().vector(llvm_elem, length as u64))
] ]
} }
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => { intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
// the LLVM intrinsic uses a smaller integer // the LLVM intrinsic uses a smaller integer
// size than the C intrinsic's signature, so // size than the C intrinsic's signature, so
// we have to trim it down here. // we have to trim it down here.
vec![bx.trunc(arg.immediate(), Type::ix(bx.cx(), llvm_width as u64))] vec![bx.trunc(arg.immediate(), bx.cx().ix(llvm_width as u64))]
} }
_ => vec![arg.immediate()], _ => vec![arg.immediate()],
} }
@ -681,7 +681,7 @@ pub fn codegen_intrinsic_call(
intrinsics::IntrinsicDef::Named(name) => { intrinsics::IntrinsicDef::Named(name) => {
let f = declare::declare_cfn(cx, let f = declare::declare_cfn(cx,
name, name,
Type::func(&inputs, outputs)); cx.func(&inputs, outputs));
bx.call(f, &llargs, None) bx.call(f, &llargs, None)
} }
}; };
@ -705,7 +705,7 @@ pub fn codegen_intrinsic_call(
if !fn_ty.ret.is_ignore() { if !fn_ty.ret.is_ignore() {
if let PassMode::Cast(ty) = fn_ty.ret.mode { if let PassMode::Cast(ty) = fn_ty.ret.mode {
let ptr = bx.pointercast(result.llval, ty.llvm_type(cx).ptr_to()); let ptr = bx.pointercast(result.llval, cx.ptr_to(ty.llvm_type(cx)));
bx.store(llval, ptr, result.align); bx.store(llval, ptr, result.align);
} else { } else {
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout) OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
@ -727,8 +727,8 @@ fn copy_intrinsic(
let (size, align) = cx.size_and_align_of(ty); let (size, align) = cx.size_and_align_of(ty);
let size = cx.c_usize(size.bytes()); let size = cx.c_usize(size.bytes());
let align = align.abi(); let align = align.abi();
let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let dst_ptr = bx.pointercast(dst, cx.i8p());
let src_ptr = bx.pointercast(src, Type::i8p(cx)); let src_ptr = bx.pointercast(src, cx.i8p());
if allow_overlap { if allow_overlap {
bx.memmove(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile) bx.memmove(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile)
} else { } else {
@ -748,7 +748,7 @@ fn memset_intrinsic(
let (size, align) = cx.size_and_align_of(ty); let (size, align) = cx.size_and_align_of(ty);
let size = cx.c_usize(size.bytes()); let size = cx.c_usize(size.bytes());
let align = cx.c_i32(align.abi() as i32); let align = cx.c_i32(align.abi() as i32);
let dst = bx.pointercast(dst, Type::i8p(cx)); let dst = bx.pointercast(dst, cx.i8p());
call_memset(bx, dst, val, bx.mul(size, count), align, volatile) call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
} }
@ -763,7 +763,7 @@ fn try_intrinsic(
if bx.sess().no_landing_pads() { if bx.sess().no_landing_pads() {
bx.call(func, &[data], None); bx.call(func, &[data], None);
let ptr_align = bx.tcx().data_layout.pointer_align; let ptr_align = bx.tcx().data_layout.pointer_align;
bx.store(bx.cx().c_null(Type::i8p(&bx.cx())), dest, ptr_align); bx.store(cx.c_null(cx.i8p()), dest, ptr_align);
} else if wants_msvc_seh(bx.sess()) { } else if wants_msvc_seh(bx.sess()) {
codegen_msvc_try(bx, cx, func, data, local_ptr, dest); codegen_msvc_try(bx, cx, func, data, local_ptr, dest);
} else { } else {
@ -839,7 +839,7 @@ fn codegen_msvc_try(
// } // }
// //
// More information can be found in libstd's seh.rs implementation. // More information can be found in libstd's seh.rs implementation.
let i64p = Type::i64(cx).ptr_to(); let i64p = cx.ptr_to(cx.i64());
let ptr_align = bx.tcx().data_layout.pointer_align; let ptr_align = bx.tcx().data_layout.pointer_align;
let slot = bx.alloca(i64p, "slot", ptr_align); let slot = bx.alloca(i64p, "slot", ptr_align);
bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
@ -930,12 +930,12 @@ fn codegen_gnu_try(
// being thrown. The second value is a "selector" indicating which of // being thrown. The second value is a "selector" indicating which of
// the landing pad clauses the exception's type had been matched to. // the landing pad clauses the exception's type had been matched to.
// rust_try ignores the selector. // rust_try ignores the selector.
let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false); let lpad_ty = cx.struct_(&[cx.i8p(), cx.i32()], false);
let vals = catch.landing_pad(lpad_ty, bx.cx().eh_personality(), 1); let vals = catch.landing_pad(lpad_ty, bx.cx().eh_personality(), 1);
catch.add_clause(vals, bx.cx().c_null(Type::i8p(cx))); catch.add_clause(vals, bx.cx().c_null(cx.i8p()));
let ptr = catch.extract_value(vals, 0); let ptr = catch.extract_value(vals, 0);
let ptr_align = bx.tcx().data_layout.pointer_align; let ptr_align = bx.tcx().data_layout.pointer_align;
catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align); catch.store(ptr, catch.bitcast(local_ptr, cx.ptr_to(cx.i8p())), ptr_align);
catch.ret(cx.c_i32(1)); catch.ret(cx.c_i32(1));
}); });
@ -1078,7 +1078,7 @@ fn generic_simd_intrinsic(
found `{}` with length {}", found `{}` with length {}",
in_len, in_ty, in_len, in_ty,
ret_ty, out_len); ret_ty, out_len);
require!(llret_ty.element_type().kind() == TypeKind::Integer, require!(bx.cx().kind(bx.cx().element_type(llret_ty)) == TypeKind::Integer,
"expected return type with integer elements, found `{}` with non-integer `{}`", "expected return type with integer elements, found `{}` with non-integer `{}`",
ret_ty, ret_ty,
ret_ty.simd_type(tcx)); ret_ty.simd_type(tcx));
@ -1167,8 +1167,8 @@ fn generic_simd_intrinsic(
_ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty) _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty)
} }
// truncate the mask to a vector of i1s // truncate the mask to a vector of i1s
let i1 = Type::i1(bx.cx()); let i1 = bx.cx().i1();
let i1xn = Type::vector(i1, m_len as u64); let i1xn = bx.cx().vector(i1, m_len as u64);
let m_i1s = bx.trunc(args[0].immediate(), i1xn); let m_i1s = bx.trunc(args[0].immediate(), i1xn);
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
} }
@ -1300,16 +1300,16 @@ fn generic_simd_intrinsic(
mut no_pointers: usize) -> &'ll Type { mut no_pointers: usize) -> &'ll Type {
// FIXME: use cx.layout_of(ty).llvm_type() ? // FIXME: use cx.layout_of(ty).llvm_type() ?
let mut elem_ty = match elem_ty.sty { let mut elem_ty = match elem_ty.sty {
ty::Int(v) => Type::int_from_ty(cx, v), ty::Int(v) => cx.int_from_ty( v),
ty::Uint(v) => Type::uint_from_ty(cx, v), ty::Uint(v) => cx.uint_from_ty( v),
ty::Float(v) => Type::float_from_ty(cx, v), ty::Float(v) => cx.float_from_ty( v),
_ => unreachable!(), _ => unreachable!(),
}; };
while no_pointers > 0 { while no_pointers > 0 {
elem_ty = elem_ty.ptr_to(); elem_ty = cx.ptr_to(elem_ty);
no_pointers -= 1; no_pointers -= 1;
} }
Type::vector(elem_ty, vec_len as u64) cx.vector(elem_ty, vec_len as u64)
} }
@ -1386,13 +1386,13 @@ fn generic_simd_intrinsic(
} }
// Alignment of T, must be a constant integer value: // Alignment of T, must be a constant integer value:
let alignment_ty = Type::i32(bx.cx()); let alignment_ty = bx.cx().i32();
let alignment = bx.cx().c_i32(bx.cx().align_of(in_elem).abi() as i32); let alignment = bx.cx().c_i32(bx.cx().align_of(in_elem).abi() as i32);
// Truncate the mask vector to a vector of i1s: // Truncate the mask vector to a vector of i1s:
let (mask, mask_ty) = { let (mask, mask_ty) = {
let i1 = Type::i1(bx.cx()); let i1 = bx.cx().i1();
let i1xn = Type::vector(i1, in_len as u64); let i1xn = bx.cx().vector(i1, in_len as u64);
(bx.trunc(args[2].immediate(), i1xn), i1xn) (bx.trunc(args[2].immediate(), i1xn), i1xn)
}; };
@ -1407,7 +1407,7 @@ fn generic_simd_intrinsic(
let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", let llvm_intrinsic = format!("llvm.masked.gather.{}.{}",
llvm_elem_vec_str, llvm_pointer_vec_str); llvm_elem_vec_str, llvm_pointer_vec_str);
let f = declare::declare_cfn(bx.cx(), &llvm_intrinsic, let f = declare::declare_cfn(bx.cx(), &llvm_intrinsic,
Type::func(&[ bx.cx().func(&[
llvm_pointer_vec_ty, llvm_pointer_vec_ty,
alignment_ty, alignment_ty,
mask_ty, mask_ty,
@ -1486,17 +1486,17 @@ fn generic_simd_intrinsic(
} }
// Alignment of T, must be a constant integer value: // Alignment of T, must be a constant integer value:
let alignment_ty = Type::i32(bx.cx()); let alignment_ty = bx.cx().i32();
let alignment = bx.cx().c_i32(bx.cx().align_of(in_elem).abi() as i32); let alignment = bx.cx().c_i32(bx.cx().align_of(in_elem).abi() as i32);
// Truncate the mask vector to a vector of i1s: // Truncate the mask vector to a vector of i1s:
let (mask, mask_ty) = { let (mask, mask_ty) = {
let i1 = Type::i1(bx.cx()); let i1 = bx.cx().i1();
let i1xn = Type::vector(i1, in_len as u64); let i1xn = bx.cx().vector(i1, in_len as u64);
(bx.trunc(args[2].immediate(), i1xn), i1xn) (bx.trunc(args[2].immediate(), i1xn), i1xn)
}; };
let ret_t = Type::void(bx.cx()); let ret_t = bx.cx().void();
// Type of the vector of pointers: // Type of the vector of pointers:
let llvm_pointer_vec_ty = llvm_vector_ty(bx.cx(), underlying_ty, in_len, pointer_count); let llvm_pointer_vec_ty = llvm_vector_ty(bx.cx(), underlying_ty, in_len, pointer_count);
@ -1509,7 +1509,7 @@ fn generic_simd_intrinsic(
let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}",
llvm_elem_vec_str, llvm_pointer_vec_str); llvm_elem_vec_str, llvm_pointer_vec_str);
let f = declare::declare_cfn(bx.cx(), &llvm_intrinsic, let f = declare::declare_cfn(bx.cx(), &llvm_intrinsic,
Type::func(&[llvm_elem_vec_ty, bx.cx().func(&[llvm_elem_vec_ty,
llvm_pointer_vec_ty, llvm_pointer_vec_ty,
alignment_ty, alignment_ty,
mask_ty], ret_t)); mask_ty], ret_t));
@ -1565,8 +1565,8 @@ fn generic_simd_intrinsic(
} else { } else {
// unordered arithmetic reductions do not: // unordered arithmetic reductions do not:
match f.bit_width() { match f.bit_width() {
32 => bx.cx().c_undef(Type::f32(bx.cx())), 32 => bx.cx().c_undef(bx.cx().f32()),
64 => bx.cx().c_undef(Type::f64(bx.cx())), 64 => bx.cx().c_undef(bx.cx().f64()),
v => { v => {
return_error!(r#" return_error!(r#"
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
@ -1643,8 +1643,8 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
} }
// boolean reductions operate on vectors of i1s: // boolean reductions operate on vectors of i1s:
let i1 = Type::i1(bx.cx()); let i1 = bx.cx().i1();
let i1xn = Type::vector(i1, in_len as u64); let i1xn = bx.cx().vector(i1, in_len as u64);
bx.trunc(args[0].immediate(), i1xn) bx.trunc(args[0].immediate(), i1xn)
}; };
return match in_elem.sty { return match in_elem.sty {
@ -1654,7 +1654,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
if !$boolean { if !$boolean {
r r
} else { } else {
bx.zext(r, Type::bool(bx.cx())) bx.zext(r, bx.cx().bool())
} }
) )
}, },

View file

@ -14,10 +14,9 @@ use context::CodegenCx;
use builder::Builder; use builder::Builder;
use consts; use consts;
use monomorphize; use monomorphize;
use type_::Type;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::layout::HasDataLayout; use rustc::ty::layout::HasDataLayout;
@ -41,7 +40,10 @@ impl<'a, 'tcx> VirtualIndex {
// Load the data pointer from the object. // Load the data pointer from the object.
debug!("get_fn({:?}, {:?})", llvtable, self); debug!("get_fn({:?}, {:?})", llvtable, self);
let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx()).ptr_to()); let llvtable = bx.pointercast(
llvtable,
bx.cx().ptr_to(fn_ty.ptr_to_llvm_type(bx.cx()))
);
let ptr_align = bx.tcx().data_layout.pointer_align; let ptr_align = bx.tcx().data_layout.pointer_align;
let ptr = bx.load( let ptr = bx.load(
bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]), bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]),
@ -61,7 +63,7 @@ impl<'a, 'tcx> VirtualIndex {
// Load the data pointer from the object. // Load the data pointer from the object.
debug!("get_int({:?}, {:?})", llvtable, self); debug!("get_int({:?}, {:?})", llvtable, self);
let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx()).ptr_to()); let llvtable = bx.pointercast(llvtable, bx.cx().ptr_to(bx.cx().isize()));
let usize_align = bx.tcx().data_layout.pointer_align; let usize_align = bx.tcx().data_layout.pointer_align;
let ptr = bx.load( let ptr = bx.load(
bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]), bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]),
@ -96,7 +98,7 @@ pub fn get_vtable(
} }
// Not in the cache. Build it. // Not in the cache. Build it.
let nullptr = cx.c_null(Type::i8p(cx)); let nullptr = cx.c_null(cx.i8p());
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
let methods = methods.iter().cloned().map(|opt_mth| { let methods = methods.iter().cloned().map(|opt_mth| {

View file

@ -26,7 +26,7 @@ use type_of::LayoutLlvmExt;
use type_::Type; use type_::Type;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax_pos::Pos; use syntax_pos::Pos;
@ -268,7 +268,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
} }
}; };
bx.load( bx.load(
bx.pointercast(llslot, cast_ty.llvm_type(bx.cx()).ptr_to()), bx.pointercast(llslot, bx.cx().ptr_to(cast_ty.llvm_type(bx.cx()))),
self.fn_ty.ret.layout.align) self.fn_ty.ret.layout.align)
} }
}; };
@ -560,7 +560,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
let dest = match ret_dest { let dest = match ret_dest {
_ if fn_ty.ret.is_indirect() => llargs[0], _ if fn_ty.ret.is_indirect() => llargs[0],
ReturnDest::Nothing => { ReturnDest::Nothing => {
bx.cx().c_undef(fn_ty.ret.memory_ty(bx.cx()).ptr_to()) bx.cx().c_undef(bx.cx().ptr_to(fn_ty.ret.memory_ty(bx.cx())))
} }
ReturnDest::IndirectOperand(dst, _) | ReturnDest::IndirectOperand(dst, _) |
ReturnDest::Store(dst) => dst.llval, ReturnDest::Store(dst) => dst.llval,
@ -801,7 +801,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
if by_ref && !arg.is_indirect() { if by_ref && !arg.is_indirect() {
// Have to load the argument, maybe while casting it. // Have to load the argument, maybe while casting it.
if let PassMode::Cast(ty) = arg.mode { if let PassMode::Cast(ty) = arg.mode {
llval = bx.load(bx.pointercast(llval, ty.llvm_type(bx.cx()).ptr_to()), llval = bx.load(bx.pointercast(llval, bx.cx().ptr_to(ty.llvm_type(bx.cx()))),
align.min(arg.layout.align)); align.min(arg.layout.align));
} else { } else {
// We can't use `PlaceRef::load` here because the argument // We can't use `PlaceRef::load` here because the argument
@ -902,7 +902,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
fn landing_pad_type(&self) -> &'ll Type { fn landing_pad_type(&self) -> &'ll Type {
let cx = self.cx; let cx = self.cx;
Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false) cx.struct_( &[cx.i8p(), cx.i32()], false)
} }
fn unreachable_block(&mut self) -> &'ll BasicBlock { fn unreachable_block(&mut self) -> &'ll BasicBlock {
@ -1014,7 +1014,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
dst: PlaceRef<'tcx, &'ll Value>) { dst: PlaceRef<'tcx, &'ll Value>) {
let src = self.codegen_operand(bx, src); let src = self.codegen_operand(bx, src);
let llty = src.layout.llvm_type(bx.cx()); let llty = src.layout.llvm_type(bx.cx());
let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to()); let cast_ptr = bx.pointercast(dst.llval, bx.cx().ptr_to(llty));
let align = src.layout.align.min(dst.layout.align); let align = src.layout.align.min(dst.layout.align);
src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align)); src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align));
} }

View file

@ -25,7 +25,7 @@ use type_::Type;
use syntax::ast::Mutability; use syntax::ast::Mutability;
use syntax::source_map::Span; use syntax::source_map::Span;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use super::super::callee; use super::super::callee;
use super::FunctionCx; use super::FunctionCx;
@ -40,11 +40,11 @@ pub fn scalar_to_llvm(
match cv { match cv {
Scalar::Bits { size: 0, .. } => { Scalar::Bits { size: 0, .. } => {
assert_eq!(0, layout.value.size(cx).bytes()); assert_eq!(0, layout.value.size(cx).bytes());
cx.c_undef(Type::ix(cx, 0)) cx.c_undef(cx.ix(0))
}, },
Scalar::Bits { bits, size } => { Scalar::Bits { bits, size } => {
assert_eq!(size as u64, layout.value.size(cx).bytes()); assert_eq!(size as u64, layout.value.size(cx).bytes());
let llval = cx.c_uint_big(Type::ix(cx, bitsize), bits); let llval = cx.c_uint_big(cx.ix(bitsize), bits);
if layout.value == layout::Pointer { if layout.value == layout::Pointer {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) } unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
} else { } else {
@ -72,7 +72,7 @@ pub fn scalar_to_llvm(
None => bug!("missing allocation {:?}", ptr.alloc_id), None => bug!("missing allocation {:?}", ptr.alloc_id),
}; };
let llval = unsafe { llvm::LLVMConstInBoundsGEP( let llval = unsafe { llvm::LLVMConstInBoundsGEP(
consts::bitcast(base_addr, Type::i8p(cx)), consts::bitcast(base_addr, cx.i8p()),
&cx.c_usize(ptr.offset.bytes()), &cx.c_usize(ptr.offset.bytes()),
1, 1,
) }; ) };
@ -109,7 +109,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
value: layout::Primitive::Pointer, value: layout::Primitive::Pointer,
valid_range: 0..=!0 valid_range: 0..=!0
}, },
Type::i8p(cx) cx.i8p()
)); ));
next_offset = offset + pointer_size; next_offset = offset + pointer_size;
} }

View file

@ -23,7 +23,6 @@ use common::{CodegenCx, Funclet};
use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext}; use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
use monomorphize::Instance; use monomorphize::Instance;
use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode}; use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
use type_::Type;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods};
@ -420,7 +419,7 @@ fn create_funclets(
// C++ personality function, but `catch (...)` has no type so // C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which // it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block. // represents that this is a catch-all block.
let null = bx.cx().c_null(Type::i8p(bx.cx())); let null = bx.cx().c_null(bx.cx().i8p());
let sixty_four = bx.cx().c_i32(64); let sixty_four = bx.cx().c_i32(64);
cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]); cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
cp_bx.br(llbb); cp_bx.br(llbb);

View file

@ -18,10 +18,9 @@ use common::CodegenCx;
use builder::{Builder, MemFlags}; use builder::{Builder, MemFlags};
use value::Value; use value::Value;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use type_::Type;
use glue; use glue;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use std::fmt; use std::fmt;
@ -349,7 +348,7 @@ impl OperandValue<&'ll Value> {
// Allocate an appropriate region on the stack, and copy the value into it // Allocate an appropriate region on the stack, and copy the value into it
let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
let lldst = bx.array_alloca(Type::i8(bx.cx()), llsize, "unsized_tmp", max_align); let lldst = bx.array_alloca(bx.cx().i8(), llsize, "unsized_tmp", max_align);
base::call_memcpy(bx, lldst, max_align, llptr, min_align, llsize, flags); base::call_memcpy(bx, lldst, max_align, llptr, min_align, llsize, flags);
// Store the allocated region and the extra to the indirect place. // Store the allocated region and the extra to the indirect place.
@ -463,7 +462,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
// We've errored, so we don't have to produce working code. // We've errored, so we don't have to produce working code.
let layout = bx.cx().layout_of(ty); let layout = bx.cx().layout_of(ty);
PlaceRef::new_sized( PlaceRef::new_sized(
bx.cx().c_undef(layout.llvm_type(bx.cx()).ptr_to()), bx.cx().c_undef(bx.cx().ptr_to(layout.llvm_type(bx.cx()))),
layout, layout,
layout.align, layout.align,
).load(bx) ).load(bx)

View file

@ -18,12 +18,11 @@ use builder::Builder;
use common::{CodegenCx, IntPredicate}; use common::{CodegenCx, IntPredicate};
use consts; use consts;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use type_::Type;
use value::Value; use value::Value;
use glue; use glue;
use mir::constant::const_alloc_to_llvm; use mir::constant::const_alloc_to_llvm;
use interfaces::{BuilderMethods, CommonMethods}; use interfaces::{BuilderMethods, CommonMethods, TypeMethods};
use super::{FunctionCx, LocalRef}; use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue}; use super::operand::{OperandRef, OperandValue};
@ -68,11 +67,11 @@ impl PlaceRef<'tcx, &'ll Value> {
let base_addr = consts::addr_of(bx.cx(), init, layout.align, None); let base_addr = consts::addr_of(bx.cx(), init, layout.align, None);
let llval = unsafe { LLVMConstInBoundsGEP( let llval = unsafe { LLVMConstInBoundsGEP(
consts::bitcast(base_addr, Type::i8p(bx.cx())), consts::bitcast(base_addr, bx.cx().i8p()),
&bx.cx().c_usize(offset.bytes()), &bx.cx().c_usize(offset.bytes()),
1, 1,
)}; )};
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx()).ptr_to()); let llval = consts::bitcast(llval, bx.cx().ptr_to(layout.llvm_type(bx.cx())));
PlaceRef::new_sized(llval, layout, alloc.align) PlaceRef::new_sized(llval, layout, alloc.align)
} }
@ -160,7 +159,7 @@ impl PlaceRef<'tcx, &'ll Value> {
let load = bx.load(llptr, self.align); let load = bx.load(llptr, self.align);
scalar_load_metadata(load, scalar); scalar_load_metadata(load, scalar);
if scalar.is_bool() { if scalar.is_bool() {
bx.trunc(load, Type::i1(bx.cx())) bx.trunc(load, bx.cx().i1())
} else { } else {
load load
} }
@ -197,7 +196,7 @@ impl PlaceRef<'tcx, &'ll Value> {
}; };
PlaceRef { PlaceRef {
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
llval: bx.pointercast(llval, field.llvm_type(cx).ptr_to()), llval: bx.pointercast(llval, cx.ptr_to(field.llvm_type(cx))),
llextra: if cx.type_has_metadata(field.ty) { llextra: if cx.type_has_metadata(field.ty) {
self.llextra self.llextra
} else { } else {
@ -266,7 +265,7 @@ impl PlaceRef<'tcx, &'ll Value> {
debug!("struct_field_ptr: DST field offset: {:?}", offset); debug!("struct_field_ptr: DST field offset: {:?}", offset);
// Cast and adjust pointer // Cast and adjust pointer
let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx)); let byte_ptr = bx.pointercast(self.llval, cx.i8p());
let byte_ptr = bx.gep(byte_ptr, &[offset]); let byte_ptr = bx.gep(byte_ptr, &[offset]);
// Finally, cast back to the type expected // Finally, cast back to the type expected
@ -274,7 +273,7 @@ impl PlaceRef<'tcx, &'ll Value> {
debug!("struct_field_ptr: Field type is {:?}", ll_fty); debug!("struct_field_ptr: Field type is {:?}", ll_fty);
PlaceRef { PlaceRef {
llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()), llval: bx.pointercast(byte_ptr, bx.cx().ptr_to(ll_fty)),
llextra: self.llextra, llextra: self.llextra,
layout: field, layout: field,
align: effective_field_align, align: effective_field_align,
@ -380,7 +379,7 @@ impl PlaceRef<'tcx, &'ll Value> {
bx.sess().target.target.arch == "aarch64" { bx.sess().target.target.arch == "aarch64" {
// Issue #34427: As workaround for LLVM bug on ARM, // Issue #34427: As workaround for LLVM bug on ARM,
// use memset of 0 before assigning niche value. // use memset of 0 before assigning niche value.
let llptr = bx.pointercast(self.llval, Type::i8(bx.cx()).ptr_to()); let llptr = bx.pointercast(self.llval, bx.cx().ptr_to(bx.cx().i8()));
let fill_byte = bx.cx().c_u8(0); let fill_byte = bx.cx().c_u8(0);
let (size, align) = self.layout.size_and_align(); let (size, align) = self.layout.size_and_align();
let size = bx.cx().c_usize(size.bytes()); let size = bx.cx().c_usize(size.bytes());
@ -423,7 +422,7 @@ impl PlaceRef<'tcx, &'ll Value> {
// Cast to the appropriate variant struct type. // Cast to the appropriate variant struct type.
let variant_ty = downcast.layout.llvm_type(bx.cx()); let variant_ty = downcast.layout.llvm_type(bx.cx());
downcast.llval = bx.pointercast(downcast.llval, variant_ty.ptr_to()); downcast.llval = bx.pointercast(downcast.llval, bx.cx().ptr_to(variant_ty));
downcast downcast
} }
@ -484,7 +483,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
// so we generate an abort // so we generate an abort
let fnname = bx.cx().get_intrinsic(&("llvm.trap")); let fnname = bx.cx().get_intrinsic(&("llvm.trap"));
bx.call(fnname, &[], None); bx.call(fnname, &[], None);
let llval = bx.cx().c_undef(layout.llvm_type(bx.cx()).ptr_to()); let llval = bx.cx().c_undef(bx.cx().ptr_to(layout.llvm_type(bx.cx())));
PlaceRef::new_sized(llval, layout, layout.align) PlaceRef::new_sized(llval, layout, layout.align)
} }
} }
@ -544,7 +543,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
// Cast the place pointer type to the new // Cast the place pointer type to the new
// array or slice type (*[%_; new_len]). // array or slice type (*[%_; new_len]).
subslice.llval = bx.pointercast(subslice.llval, subslice.llval = bx.pointercast(subslice.llval,
subslice.layout.llvm_type(bx.cx()).ptr_to()); bx.cx().ptr_to(subslice.layout.llvm_type(bx.cx())));
subslice subslice
} }

View file

@ -26,7 +26,7 @@ use type_::Type;
use type_of::LayoutLlvmExt; use type_of::LayoutLlvmExt;
use value::Value; use value::Value;
use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods}; use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods, TypeMethods};
use super::{FunctionCx, LocalRef}; use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue}; use super::operand::{OperandRef, OperandValue};
@ -117,7 +117,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
// Use llvm.memset.p0i8.* to initialize byte arrays // Use llvm.memset.p0i8.* to initialize byte arrays
let v = base::from_immediate(&bx, v); let v = base::from_immediate(&bx, v);
if bx.cx().val_ty(v) == Type::i8(bx.cx()) { if bx.cx().val_ty(v) == bx.cx().i8() {
base::call_memset(&bx, start, v, size, align, false); base::call_memset(&bx, start, v, size, align, false);
return bx; return bx;
} }
@ -349,8 +349,8 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
bx.intcast(llval, ll_t_out, signed) bx.intcast(llval, ll_t_out, signed)
} }
(CastTy::Float, CastTy::Float) => { (CastTy::Float, CastTy::Float) => {
let srcsz = ll_t_in.float_width(); let srcsz = bx.cx().float_width(ll_t_in);
let dstsz = ll_t_out.float_width(); let dstsz = bx.cx().float_width(ll_t_out);
if dstsz > srcsz { if dstsz > srcsz {
bx.fpext(llval, ll_t_out) bx.fpext(llval, ll_t_out)
} else if srcsz > dstsz { } else if srcsz > dstsz {
@ -828,7 +828,9 @@ fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
// Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding. // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
// It's only u128 -> f32 that can cause overflows (i.e., should yield infinity). // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
// LLVM's uitofp produces undef in those cases, so we manually check for that case. // LLVM's uitofp produces undef in those cases, so we manually check for that case.
let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32; let is_u128_to_f32 = !signed &&
bx.cx().int_width(int_ty) == 128 &&
bx.cx().float_width(float_ty) == 32;
if is_u128_to_f32 { if is_u128_to_f32 {
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity, // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
// and for everything else LLVM's uitofp works just fine. // and for everything else LLVM's uitofp works just fine.
@ -883,39 +885,48 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
// On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer). // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: &Type) -> (u128, u128) { let int_max = |signed: bool, int_ty: &'ll Type| -> u128 {
let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero); let shift_amount = 128 - bx.cx().int_width(int_ty);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
}
fn int_max(signed: bool, int_ty: &Type) -> u128 {
let shift_amount = 128 - int_ty.int_width();
if signed { if signed {
i128::MAX as u128 >> shift_amount i128::MAX as u128 >> shift_amount
} else { } else {
u128::MAX >> shift_amount u128::MAX >> shift_amount
} }
} };
fn int_min(signed: bool, int_ty: &Type) -> i128 { let int_min = |signed: bool, int_ty: &'ll Type| -> i128 {
if signed { if signed {
i128::MIN >> (128 - int_ty.int_width()) i128::MIN >> (128 - bx.cx().int_width(int_ty))
} else { } else {
0 0
} }
} };
let compute_clamp_bounds_single = |signed: bool, int_ty: &'ll Type| -> (u128, u128) {
let rounded_min = ieee::Single::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max = ieee::Single::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
let compute_clamp_bounds_double = |signed: bool, int_ty: &'ll Type| -> (u128, u128) {
let rounded_min = ieee::Double::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
assert_eq!(rounded_min.status, Status::OK);
let rounded_max = ieee::Double::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
assert!(rounded_max.value.is_finite());
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
};
let float_bits_to_llval = |bits| { let float_bits_to_llval = |bits| {
let bits_llval = match float_ty.float_width() { let bits_llval = match bx.cx().float_width(float_ty) {
32 => bx.cx().c_u32(bits as u32), 32 => bx.cx().c_u32(bits as u32),
64 => bx.cx().c_u64(bits as u64), 64 => bx.cx().c_u64(bits as u64),
n => bug!("unsupported float width {}", n), n => bug!("unsupported float width {}", n),
}; };
consts::bitcast(bits_llval, float_ty) consts::bitcast(bits_llval, float_ty)
}; };
let (f_min, f_max) = match float_ty.float_width() { let (f_min, f_max) = match bx.cx().float_width(float_ty) {
32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty), 32 => compute_clamp_bounds_single(signed, int_ty),
64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty), 64 => compute_clamp_bounds_double(signed, int_ty),
n => bug!("unsupported float width {}", n), n => bug!("unsupported float width {}", n),
}; };
let f_min = float_bits_to_llval(f_min); let f_min = float_bits_to_llval(f_min);

View file

@ -16,10 +16,12 @@ use llvm;
use llvm::{Bool, False, True, TypeKind}; use llvm::{Bool, False, True, TypeKind};
use context::CodegenCx; use context::CodegenCx;
use interfaces::TypeMethods;
use syntax::ast; use syntax::ast;
use rustc::ty::layout::{self, Align, Size}; use rustc::ty::layout::{self, Align, Size};
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use back::write;
use std::fmt; use std::fmt;
@ -39,84 +41,203 @@ impl fmt::Debug for Type {
} }
} }
impl Type { impl TypeMethods for CodegenCx<'ll, 'tcx> {
pub fn void(
cx: &CodegenCx<'ll, '_> fn void(&self) -> &'ll Type {
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMVoidTypeInContext(cx.llcx) llvm::LLVMVoidTypeInContext(self.llcx)
} }
} }
pub fn metadata( fn metadata(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMRustMetadataTypeInContext(cx.llcx) llvm::LLVMRustMetadataTypeInContext(self.llcx)
} }
} }
pub fn i1( fn i1(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt1TypeInContext(cx.llcx) llvm::LLVMInt1TypeInContext(self.llcx)
} }
} }
pub fn i8( fn i8(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt8TypeInContext(cx.llcx) llvm::LLVMInt8TypeInContext(self.llcx)
} }
} }
pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
fn i16(&self) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt8TypeInContext(llcx)
llvm::LLVMInt16TypeInContext(self.llcx)
} }
} }
pub fn i16( fn i32(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt32TypeInContext(self.llcx)
llvm::LLVMInt16TypeInContext(cx.llcx)
} }
} }
pub fn i32( fn i64(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt32TypeInContext(cx.llcx) llvm::LLVMInt64TypeInContext(self.llcx)
} }
} }
pub fn i64( fn i128(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMInt64TypeInContext(cx.llcx) llvm::LLVMIntTypeInContext(self.llcx, 128)
}
}
pub fn i128(
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
unsafe {
llvm::LLVMIntTypeInContext(cx.llcx, 128)
} }
} }
// Creates an integer type with the given number of bits, e.g. i24 // Creates an integer type with the given number of bits, e.g. i24
pub fn ix( fn ix(&self, num_bits: u64) -> &'ll Type {
cx: &CodegenCx<'ll, '_>, unsafe {
num_bits: u64 llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
}
}
fn f32(&self) -> &'ll Type {
unsafe {
llvm::LLVMFloatTypeInContext(self.llcx)
}
}
fn f64(&self) -> &'ll Type {
unsafe {
llvm::LLVMDoubleTypeInContext(self.llcx)
}
}
fn x86_mmx(&self) -> &'ll Type {
unsafe {
llvm::LLVMX86MMXTypeInContext(self.llcx)
}
}
fn func(
&self,
args: &[&'ll Type],
ret: &'ll Type
) -> &'ll Type { ) -> &'ll Type {
unsafe { unsafe {
llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint) llvm::LLVMFunctionType(ret, args.as_ptr(),
args.len() as c_uint, False)
}
}
fn variadic_func(
&self,
args: &[&'ll Type],
ret: &'ll Type
) -> &'ll Type {
unsafe {
llvm::LLVMFunctionType(ret, args.as_ptr(),
args.len() as c_uint, True)
}
}
fn struct_(
&self,
els: &[&'ll Type],
packed: bool
) -> &'ll Type {
unsafe {
llvm::LLVMStructTypeInContext(self.llcx, els.as_ptr(),
els.len() as c_uint,
packed as Bool)
}
}
fn named_struct(&self, name: &str) -> &'ll Type {
let name = SmallCStr::new(name);
unsafe {
llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr())
}
}
fn array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
unsafe {
llvm::LLVMRustArrayType(ty, len)
}
}
fn vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
unsafe {
llvm::LLVMVectorType(ty, len as c_uint)
}
}
fn kind(&self, ty: &'ll Type) -> TypeKind {
unsafe {
llvm::LLVMRustGetTypeKind(ty)
}
}
fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
unsafe {
llvm::LLVMStructSetBody(ty, els.as_ptr(),
els.len() as c_uint, packed as Bool)
}
}
fn ptr_to(&self, ty: &'ll Type) -> &'ll Type {
assert_ne!(self.kind(ty), TypeKind::Function,
"don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
unsafe {
llvm::LLVMPointerType(ty, 0)
}
}
fn element_type(&self, ty: &'ll Type) -> &'ll Type {
unsafe {
llvm::LLVMGetElementType(ty)
}
}
/// Return the number of elements in `self` if it is a LLVM vector type.
fn vector_length(&self, ty: &'ll Type) -> usize {
unsafe {
llvm::LLVMGetVectorSize(ty) as usize
}
}
fn func_params(&self, ty: &'ll Type) -> Vec<&'ll Type> {
unsafe {
let n_args = llvm::LLVMCountParamTypes(ty) as usize;
let mut args = Vec::with_capacity(n_args);
llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
args.set_len(n_args);
args
}
}
fn float_width(&self, ty : &'ll Type) -> usize {
match self.kind(ty) {
TypeKind::Float => 32,
TypeKind::Double => 64,
TypeKind::X86_FP80 => 80,
TypeKind::FP128 | TypeKind::PPc_FP128 => 128,
_ => bug!("llvm_float_width called on a non-float type")
}
}
/// Retrieve the bit width of the integer type `self`.
fn int_width(&self, ty: &'ll Type) -> u64 {
unsafe {
llvm::LLVMGetIntTypeWidth(ty) as u64
}
}
}
impl Type {
pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
unsafe {
llvm::LLVMInt8TypeInContext(llcx)
} }
} }
@ -130,244 +251,97 @@ impl Type {
} }
} }
pub fn f32( pub fn i8p_llcx(cx : &write::CodegenContext<'ll>, llcx: &'ll llvm::Context) -> &'ll Type {
cx: &CodegenCx<'ll, '_> cx.ptr_to(Type::i8_llcx(llcx))
) -> &'ll Type { }
unsafe { }
llvm::LLVMFloatTypeInContext(cx.llcx)
} impl CodegenCx<'ll, 'tcx> {
pub fn bool(&self) -> &'ll Type {
self.i8()
} }
pub fn f64( pub fn i8p(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_> self.ptr_to(self.i8())
) -> &'ll Type {
unsafe {
llvm::LLVMDoubleTypeInContext(cx.llcx)
}
} }
pub fn bool( pub fn isize(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_> self.isize_ty
) -> &'ll Type {
Type::i8(cx)
} }
pub fn char( pub fn t_int(&self) -> &'ll Type {
cx: &CodegenCx<'ll, '_> match &self.sess().target.target.target_c_int_width[..] {
) -> &'ll Type { "16" => self.i16(),
Type::i32(cx) "32" => self.i32(),
} "64" => self.i64(),
pub fn i8p(
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
Type::i8(cx).ptr_to()
}
pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
Type::i8_llcx(llcx).ptr_to()
}
pub fn isize(
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
cx.isize_ty
}
pub fn c_int(
cx: &CodegenCx<'ll, '_>
) -> &'ll Type {
match &cx.tcx.sess.target.target.target_c_int_width[..] {
"16" => Type::i16(cx),
"32" => Type::i32(cx),
"64" => Type::i64(cx),
width => bug!("Unsupported target_c_int_width: {}", width), width => bug!("Unsupported target_c_int_width: {}", width),
} }
} }
pub fn int_from_ty( pub fn int_from_ty(
cx: &CodegenCx<'ll, '_>, &self,
t: ast::IntTy t: ast::IntTy
) -> &'ll Type { ) -> &'ll Type {
match t { match t {
ast::IntTy::Isize => cx.isize_ty, ast::IntTy::Isize => self.isize_ty,
ast::IntTy::I8 => Type::i8(cx), ast::IntTy::I8 => self.i8(),
ast::IntTy::I16 => Type::i16(cx), ast::IntTy::I16 => self.i16(),
ast::IntTy::I32 => Type::i32(cx), ast::IntTy::I32 => self.i32(),
ast::IntTy::I64 => Type::i64(cx), ast::IntTy::I64 => self.i64(),
ast::IntTy::I128 => Type::i128(cx), ast::IntTy::I128 => self.i128(),
} }
} }
pub fn uint_from_ty( pub fn uint_from_ty(
cx: &CodegenCx<'ll, '_>, &self,
t: ast::UintTy t: ast::UintTy
) -> &'ll Type { ) -> &'ll Type {
match t { match t {
ast::UintTy::Usize => cx.isize_ty, ast::UintTy::Usize => self.isize_ty,
ast::UintTy::U8 => Type::i8(cx), ast::UintTy::U8 => self.i8(),
ast::UintTy::U16 => Type::i16(cx), ast::UintTy::U16 => self.i16(),
ast::UintTy::U32 => Type::i32(cx), ast::UintTy::U32 => self.i32(),
ast::UintTy::U64 => Type::i64(cx), ast::UintTy::U64 => self.i64(),
ast::UintTy::U128 => Type::i128(cx), ast::UintTy::U128 => self.i128(),
} }
} }
pub fn float_from_ty( pub fn float_from_ty(
cx: &CodegenCx<'ll, '_>, &self,
t: ast::FloatTy t: ast::FloatTy
) -> &'ll Type { ) -> &'ll Type {
match t { match t {
ast::FloatTy::F32 => Type::f32(cx), ast::FloatTy::F32 => self.f32(),
ast::FloatTy::F64 => Type::f64(cx), ast::FloatTy::F64 => self.f64(),
} }
} }
pub fn func( pub fn from_integer(&self, i: layout::Integer) -> &'ll Type {
args: &[&'ll Type],
ret: &'ll Type
) -> &'ll Type {
unsafe {
llvm::LLVMFunctionType(ret, args.as_ptr(),
args.len() as c_uint, False)
}
}
pub fn variadic_func(
args: &[&'ll Type],
ret: &'ll Type
) -> &'ll Type {
unsafe {
llvm::LLVMFunctionType(ret, args.as_ptr(),
args.len() as c_uint, True)
}
}
pub fn struct_(
cx: &CodegenCx<'ll, '_>,
els: &[&'ll Type],
packed: bool
) -> &'ll Type {
unsafe {
llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
els.len() as c_uint,
packed as Bool)
}
}
pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type {
let name = SmallCStr::new(name);
unsafe {
llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())
}
}
pub fn array(ty: &Type, len: u64) -> &Type {
unsafe {
llvm::LLVMRustArrayType(ty, len)
}
}
pub fn vector(ty: &Type, len: u64) -> &Type {
unsafe {
llvm::LLVMVectorType(ty, len as c_uint)
}
}
pub fn kind(&self) -> TypeKind {
unsafe {
llvm::LLVMRustGetTypeKind(self)
}
}
pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
unsafe {
llvm::LLVMStructSetBody(self, els.as_ptr(),
els.len() as c_uint, packed as Bool)
}
}
pub fn ptr_to(&self) -> &Type {
assert_ne!(self.kind(), TypeKind::Function,
"don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
unsafe {
llvm::LLVMPointerType(self, 0)
}
}
pub fn element_type(&self) -> &Type {
unsafe {
llvm::LLVMGetElementType(self)
}
}
/// Return the number of elements in `self` if it is a LLVM vector type.
pub fn vector_length(&self) -> usize {
unsafe {
llvm::LLVMGetVectorSize(self) as usize
}
}
pub fn func_params(&self) -> Vec<&Type> {
unsafe {
let n_args = llvm::LLVMCountParamTypes(self) as usize;
let mut args = Vec::with_capacity(n_args);
llvm::LLVMGetParamTypes(self, args.as_mut_ptr());
args.set_len(n_args);
args
}
}
pub fn float_width(&self) -> usize {
match self.kind() {
TypeKind::Float => 32,
TypeKind::Double => 64,
TypeKind::X86_FP80 => 80,
TypeKind::FP128 | TypeKind::PPc_FP128 => 128,
_ => bug!("llvm_float_width called on a non-float type")
}
}
/// Retrieve the bit width of the integer type `self`.
pub fn int_width(&self) -> u64 {
unsafe {
llvm::LLVMGetIntTypeWidth(self) as u64
}
}
pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type {
use rustc::ty::layout::Integer::*; use rustc::ty::layout::Integer::*;
match i { match i {
I8 => Type::i8(cx), I8 => self.i8(),
I16 => Type::i16(cx), I16 => self.i16(),
I32 => Type::i32(cx), I32 => self.i32(),
I64 => Type::i64(cx), I64 => self.i64(),
I128 => Type::i128(cx), I128 => self.i128(),
} }
} }
/// Return a LLVM type that has at most the required alignment, /// Return a LLVM type that has at most the required alignment,
/// as a conservative approximation for unknown pointee types. /// as a conservative approximation for unknown pointee types.
pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type { pub fn pointee_for_abi_align(&self, align: Align) -> &'ll Type {
// FIXME(eddyb) We could find a better approximation if ity.align < align. // FIXME(eddyb) We could find a better approximation if ity.align < align.
let ity = layout::Integer::approximate_abi_align(cx, align); let ity = layout::Integer::approximate_abi_align(self, align);
Type::from_integer(cx, ity) self.from_integer(ity)
} }
/// Return a LLVM type that has at most the required alignment, /// Return a LLVM type that has at most the required alignment,
/// and exactly the required size, as a best-effort padding array. /// and exactly the required size, as a best-effort padding array.
pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type { pub fn padding_filler(&self, size: Size, align: Align) -> &'ll Type {
let unit = layout::Integer::approximate_abi_align(cx, align); let unit = layout::Integer::approximate_abi_align(self, align);
let size = size.bytes(); let size = size.bytes();
let unit_size = unit.size().bytes(); let unit_size = unit.size().bytes();
assert_eq!(size % unit_size, 0); assert_eq!(size % unit_size, 0);
Type::array(Type::from_integer(cx, unit), size / unit_size) self.array(self.from_integer(unit), size / unit_size)
}
pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
unsafe {
llvm::LLVMX86MMXTypeInContext(cx.llcx)
}
} }
} }

View file

@ -16,6 +16,7 @@ use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
use rustc_target::abi::FloatTy; use rustc_target::abi::FloatTy;
use rustc_mir::monomorphize::item::DefPathBasedNames; use rustc_mir::monomorphize::item::DefPathBasedNames;
use type_::Type; use type_::Type;
use interfaces::TypeMethods;
use std::fmt::Write; use std::fmt::Write;
@ -37,14 +38,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
(cx.sess().target.target.arch == "x86" || (cx.sess().target.target.arch == "x86" ||
cx.sess().target.target.arch == "x86_64"); cx.sess().target.target.arch == "x86_64");
if use_x86_mmx { if use_x86_mmx {
return Type::x86_mmx(cx) return cx.x86_mmx()
} else { } else {
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO); let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
return Type::vector(element, count); return cx.vector(element, count);
} }
} }
layout::Abi::ScalarPair(..) => { layout::Abi::ScalarPair(..) => {
return Type::struct_(cx, &[ return cx.struct_( &[
layout.scalar_pair_element_llvm_type(cx, 0, false), layout.scalar_pair_element_llvm_type(cx, 0, false),
layout.scalar_pair_element_llvm_type(cx, 1, false), layout.scalar_pair_element_llvm_type(cx, 1, false),
], false); ], false);
@ -79,30 +80,30 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
match layout.fields { match layout.fields {
layout::FieldPlacement::Union(_) => { layout::FieldPlacement::Union(_) => {
let fill = Type::padding_filler(cx, layout.size, layout.align); let fill = cx.padding_filler( layout.size, layout.align);
let packed = false; let packed = false;
match name { match name {
None => { None => {
Type::struct_(cx, &[fill], packed) cx.struct_( &[fill], packed)
} }
Some(ref name) => { Some(ref name) => {
let llty = Type::named_struct(cx, name); let llty = cx.named_struct( name);
llty.set_struct_body(&[fill], packed); cx.set_struct_body(llty, &[fill], packed);
llty llty
} }
} }
} }
layout::FieldPlacement::Array { count, .. } => { layout::FieldPlacement::Array { count, .. } => {
Type::array(layout.field(cx, 0).llvm_type(cx), count) cx.array(layout.field(cx, 0).llvm_type(cx), count)
} }
layout::FieldPlacement::Arbitrary { .. } => { layout::FieldPlacement::Arbitrary { .. } => {
match name { match name {
None => { None => {
let (llfields, packed) = struct_llfields(cx, layout); let (llfields, packed) = struct_llfields(cx, layout);
Type::struct_(cx, &llfields, packed) cx.struct_( &llfields, packed)
} }
Some(ref name) => { Some(ref name) => {
let llty = Type::named_struct(cx, name); let llty = cx.named_struct( name);
*defer = Some((llty, layout)); *defer = Some((llty, layout));
llty llty
} }
@ -136,7 +137,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
let padding = target_offset - offset; let padding = target_offset - offset;
let padding_align = prev_effective_align.min(effective_field_align); let padding_align = prev_effective_align.min(effective_field_align);
assert_eq!(offset.abi_align(padding_align) + padding, target_offset); assert_eq!(offset.abi_align(padding_align) + padding, target_offset);
result.push(Type::padding_filler(cx, padding, padding_align)); result.push(cx.padding_filler( padding, padding_align));
debug!(" padding before: {:?}", padding); debug!(" padding before: {:?}", padding);
result.push(field.llvm_type(cx)); result.push(field.llvm_type(cx));
@ -153,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
assert_eq!(offset.abi_align(padding_align) + padding, layout.size); assert_eq!(offset.abi_align(padding_align) + padding, layout.size);
debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
padding, offset, layout.size); padding, offset, layout.size);
result.push(Type::padding_filler(cx, padding, padding_align)); result.push(cx.padding_filler(padding, padding_align));
assert_eq!(result.len(), 1 + field_count * 2); assert_eq!(result.len(), 1 + field_count * 2);
} else { } else {
debug!("struct_llfields: offset: {:?} stride: {:?}", debug!("struct_llfields: offset: {:?} stride: {:?}",
@ -255,10 +256,10 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
let llty = match self.ty.sty { let llty = match self.ty.sty {
ty::Ref(_, ty, _) | ty::Ref(_, ty, _) |
ty::RawPtr(ty::TypeAndMut { ty, .. }) => { ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
cx.layout_of(ty).llvm_type(cx).ptr_to() cx.ptr_to(cx.layout_of(ty).llvm_type(cx))
} }
ty::Adt(def, _) if def.is_box() => { ty::Adt(def, _) if def.is_box() => {
cx.layout_of(self.ty.boxed_ty()).llvm_type(cx).ptr_to() cx.ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
} }
ty::FnPtr(sig) => { ty::FnPtr(sig) => {
let sig = cx.tcx.normalize_erasing_late_bound_regions( let sig = cx.tcx.normalize_erasing_late_bound_regions(
@ -307,7 +308,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
if let Some((llty, layout)) = defer { if let Some((llty, layout)) = defer {
let (llfields, packed) = struct_llfields(cx, layout); let (llfields, packed) = struct_llfields(cx, layout);
llty.set_struct_body(&llfields, packed) cx.set_struct_body(llty, &llfields, packed)
} }
llty llty
@ -316,7 +317,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
if let layout::Abi::Scalar(ref scalar) = self.abi { if let layout::Abi::Scalar(ref scalar) = self.abi {
if scalar.is_bool() { if scalar.is_bool() {
return Type::i1(cx); return cx.i1();
} }
} }
self.llvm_type(cx) self.llvm_type(cx)
@ -325,17 +326,17 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
scalar: &layout::Scalar, offset: Size) -> &'a Type { scalar: &layout::Scalar, offset: Size) -> &'a Type {
match scalar.value { match scalar.value {
layout::Int(i, _) => Type::from_integer(cx, i), layout::Int(i, _) => cx.from_integer( i),
layout::Float(FloatTy::F32) => Type::f32(cx), layout::Float(FloatTy::F32) => cx.f32(),
layout::Float(FloatTy::F64) => Type::f64(cx), layout::Float(FloatTy::F64) => cx.f64(),
layout::Pointer => { layout::Pointer => {
// If we know the alignment, pick something better than i8. // If we know the alignment, pick something better than i8.
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) { let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
Type::pointee_for_abi_align(cx, pointee.align) cx.pointee_for_abi_align( pointee.align)
} else { } else {
Type::i8(cx) cx.i8()
}; };
pointee.ptr_to() cx.ptr_to(pointee)
} }
} }
} }
@ -369,7 +370,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
// when immediate. We need to load/store `bool` as `i8` to avoid // when immediate. We need to load/store `bool` as `i8` to avoid
// crippling LLVM optimizations or triggering other LLVM bugs with `i1`. // crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
if immediate && scalar.is_bool() { if immediate && scalar.is_bool() {
return Type::i1(cx); return cx.i1();
} }
let offset = if index == 0 { let offset = if index == 0 {