From 730b13ab51b0885cb8a750036e9429e6c2a193f1 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 5 Sep 2018 14:14:03 -0700 Subject: [PATCH] Traitification of type_ methods The methods are now attached to CodegenCx instead of Type --- src/librustc_codegen_llvm/abi.rs | 34 +- src/librustc_codegen_llvm/asm.rs | 7 +- src/librustc_codegen_llvm/back/write.rs | 10 +- src/librustc_codegen_llvm/base.rs | 38 +- src/librustc_codegen_llvm/builder.rs | 24 +- src/librustc_codegen_llvm/common.rs | 27 +- src/librustc_codegen_llvm/consts.rs | 8 +- src/librustc_codegen_llvm/context.rs | 49 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 5 +- src/librustc_codegen_llvm/interfaces/type_.rs | 10 +- src/librustc_codegen_llvm/intrinsic.rs | 94 ++-- src/librustc_codegen_llvm/meth.rs | 12 +- src/librustc_codegen_llvm/mir/block.rs | 12 +- src/librustc_codegen_llvm/mir/constant.rs | 10 +- src/librustc_codegen_llvm/mir/mod.rs | 3 +- src/librustc_codegen_llvm/mir/operand.rs | 7 +- src/librustc_codegen_llvm/mir/place.rs | 23 +- src/librustc_codegen_llvm/mir/rvalue.rs | 55 ++- src/librustc_codegen_llvm/type_.rs | 446 +++++++++--------- src/librustc_codegen_llvm/type_of.rs | 47 +- 20 files changed, 458 insertions(+), 463 deletions(-) diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 9256eaccf91..f07ec35049b 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -18,7 +18,7 @@ use type_of::{LayoutLlvmExt, PointerKind}; 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::ty::{self, Ty}; @@ -111,16 +111,16 @@ pub trait LlvmType { impl LlvmType for Reg { fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { match self.kind { - RegKind::Integer => Type::ix(cx, self.size.bits()), + RegKind::Integer => cx.ix(self.size.bits()), RegKind::Float => { match self.size.bits() { - 32 => Type::f32(cx), - 64 => Type::f64(cx), + 32 => cx.f32(), + 64 => cx.f64(), _ => bug!("unsupported float: {:?}", self) } } RegKind::Vector => { - Type::vector(Type::i8(cx), self.size.bytes()) + cx.vector(cx.i8(), self.size.bytes()) } } } @@ -144,7 +144,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { // Simplify to array when all chunks are the same size and type if rem_bytes == 0 { - return Type::array(rest_ll_unit, rest_count); + return cx.array(rest_ll_unit, rest_count); } } @@ -159,10 +159,10 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { if rem_bytes != 0 { // Only integers can be really split further. 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 @@ fn store( // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. let can_store_through_cast_ptr = false; 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); } else { // The actual return type is a struct, but the ABI @@ -240,9 +240,9 @@ fn store( // ...and then memcpy it to the intended destination. base::call_memcpy(bx, - bx.pointercast(dst.llval, Type::i8p(cx)), + bx.pointercast(dst.llval, cx.i8p()), self.layout.align, - bx.pointercast(llscratch, Type::i8p(cx)), + bx.pointercast(llscratch, cx.i8p()), scratch_align, cx.c_usize(self.layout.size.bytes()), MemFlags::empty()); @@ -635,14 +635,14 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { ); let llreturn_ty = match self.ret.mode { - PassMode::Ignore => Type::void(cx), + PassMode::Ignore => cx.void(), PassMode::Direct(_) | PassMode::Pair(..) => { self.ret.layout.immediate_llvm_type(cx) } PassMode::Cast(cast) => cast.llvm_type(cx), PassMode::Indirect(..) => { - llargument_tys.push(self.ret.memory_ty(cx).ptr_to()); - Type::void(cx) + llargument_tys.push(cx.ptr_to(self.ret.memory_ty(cx))); + cx.void() } }; @@ -668,15 +668,15 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { continue; } 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); } if self.variadic { - Type::variadic_func(&llargument_tys, llreturn_ty) + cx.variadic_func(&llargument_tys, llreturn_ty) } else { - Type::func(&llargument_tys, llreturn_ty) + cx.func(&llargument_tys, llreturn_ty) } } diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 076fa400a27..15eceaf405f 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -10,13 +10,12 @@ use llvm; use context::CodegenCx; -use type_::Type; use type_of::LayoutLlvmExt; use builder::Builder; use value::Value; use rustc::hir; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use mir::place::PlaceRef; 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 let num_outputs = output_types.len(); let output_type = match num_outputs { - 0 => Type::void(bx.cx()), + 0 => bx.cx().void(), 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(); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 99921ac7eb8..7f1dafbe161 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -456,6 +456,14 @@ fn c_struct_in_context( } } +impl CodegenContext<'ll> { + pub fn ptr_to(&self, ty: &'ll Type) -> &'ll Type { + unsafe { + llvm::LLVMPointerType(ty, 0) + } + } +} + pub struct DiagnosticHandlers<'a> { 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_" }; unsafe { - let i8p_ty = Type::i8p_llcx(llcx); + let i8p_ty = Type::i8p_llcx(cgcx, llcx); let globals = base::iter_globals(llmod) .filter(|&val| { llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage && diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 9c4570f8a31..df0e47621a0 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -74,7 +74,7 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::indexed_vec::Idx; -use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods}; +use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods, TypeMethods}; use std::any::Any; use std::cmp; @@ -234,13 +234,13 @@ pub fn unsize_thin_ptr( (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { 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)) } (&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()); 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)) } (&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() { let mut rhs_llty = bx.cx().val_ty(rhs); let mut lhs_llty = bx.cx().val_ty(lhs); - if rhs_llty.kind() == TypeKind::Vector { - rhs_llty = rhs_llty.element_type() + if bx.cx().kind(rhs_llty) == TypeKind::Vector { + rhs_llty = bx.cx().element_type(rhs_llty) } - if lhs_llty.kind() == TypeKind::Vector { - lhs_llty = lhs_llty.element_type() + if bx.cx().kind(lhs_llty) == TypeKind::Vector { + lhs_llty = bx.cx().element_type(lhs_llty) } - let rhs_sz = rhs_llty.int_width(); - let lhs_sz = lhs_llty.int_width(); + let rhs_sz = bx.cx().int_width(rhs_llty); + let lhs_sz = bx.cx().int_width(lhs_llty); if lhs_sz < rhs_sz { trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { @@ -393,8 +393,8 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>( bx: &Builder<'_ ,'ll, '_, &'ll Value>, val: &'ll Value ) -> &'ll Value { - if bx.cx().val_ty(val) == Type::i1(bx.cx()) { - bx.zext(val, Type::i8(bx.cx())) + if bx.cx().val_ty(val) == bx.cx().i1() { + bx.zext(val, bx.cx().i8()) } else { val } @@ -417,7 +417,7 @@ pub fn to_immediate_scalar( scalar: &layout::Scalar, ) -> &'ll Value { if scalar.is_bool() { - return bx.trunc(val, Type::i1(bx.cx())); + return bx.trunc(val, bx.cx().i1()); } val } @@ -434,13 +434,13 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>( if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. 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); return; } let cx = bx.cx(); - let src_ptr = bx.pointercast(src, Type::i8p(cx)); - let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); + let src_ptr = bx.pointercast(src, cx.i8p()); + let dst_ptr = bx.pointercast(dst, cx.i8p()); let size = bx.intcast(n_bytes, cx.isize_ty, false); let volatile = flags.contains(MemFlags::VOLATILE); bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile); @@ -551,7 +551,7 @@ fn create_entry_fn( use_start_lang_item: bool, ) { 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(); // Given that `main()` has no arguments, @@ -594,7 +594,7 @@ fn create_entry_fn( start_def_id, 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]) } else { debug!("using user-defined start fn"); @@ -602,7 +602,7 @@ fn create_entry_fn( }; 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 module_codegen<'a, 'tcx>( if !cx.used_statics.borrow().is_empty() { let name = const_cstr!("llvm.used"); 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 { let g = llvm::LLVMAddGlobal(cx.llmod, diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 0c8ff0c9d92..1d3ef94f155 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -19,7 +19,7 @@ use rustc::ty::layout::{Align, Size}; use rustc::session::{config, Session}; use rustc_data_structures::small_c_str::SmallCStr; -use interfaces::{BuilderMethods, Backend, CommonMethods, CommonWriteMethods}; +use interfaces::{BuilderMethods, Backend, CommonMethods, CommonWriteMethods, TypeMethods}; use syntax; use std::borrow::Cow; @@ -765,7 +765,7 @@ fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, }).collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = type_::Type::func(&argtys[..], output); + let fty = &self.cx().func(&argtys[..], output); unsafe { // Ask LLVM to verify that the constraints are well-formed. let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons); @@ -861,10 +861,10 @@ fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &' fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value { unsafe { 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_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64); - self.shuffle_vector(vec, undef, self.cx.c_null(vec_i32_ty)) + 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)) } } @@ -1142,9 +1142,9 @@ fn check_store<'b>(&self, ptr: &'ll Value) -> &'ll Value { let dest_ptr_ty = self.cx.val_ty(ptr); 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 { ptr @@ -1163,14 +1163,14 @@ fn check_call<'b>(&self, args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> { let mut fn_ty = self.cx.val_ty(llfn); // Strip off pointers - while fn_ty.kind() == llvm::TypeKind::Pointer { - fn_ty = fn_ty.element_type(); + while self.cx.kind(fn_ty) == llvm::TypeKind::Pointer { + 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); - let param_tys = fn_ty.func_params(); + let param_tys = self.cx.func_params(fn_ty); let all_args_match = param_tys.iter() .zip(args.iter().map(|&v| self.cx().val_ty(v))) @@ -1227,7 +1227,7 @@ fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) 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); } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index dc46d23dd97..e31c5f1cae4 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -24,7 +24,7 @@ use type_::Type; use type_of::LayoutLlvmExt; use value::Value; -use interfaces::{Backend, CommonMethods, CommonWriteMethods}; +use interfaces::{Backend, CommonMethods, CommonWriteMethods, TypeMethods}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; @@ -236,19 +236,19 @@ fn c_uint_big(&self, t: &'ll Type, u: u128) -> &'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 { - &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 { - &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 { - &self.c_uint(Type::i64(&self), i) + &self.c_uint(&self.i64(), i) } fn c_usize(&self, i: u64) -> &'ll Value { @@ -262,7 +262,7 @@ fn c_usize(&self, i: u64) -> &'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 @@ fn c_cstr( fn c_str_slice(&self, s: LocalInternedString) -> &'ll Value { let len = s.len(); 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)) } @@ -505,11 +505,11 @@ pub fn shift_mask_val( mask_llty: &'ll Type, invert: bool ) -> &'ll Value { - let kind = llty.kind(); + let kind = bx.cx().kind(llty); match kind { TypeKind::Integer => { // 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 { bx.cx.c_int(mask_llty, !val as i64) } else { @@ -517,8 +517,13 @@ pub fn shift_mask_val( } }, TypeKind::Vector => { - let mask = shift_mask_val(bx, llty.element_type(), mask_llty.element_type(), invert); - bx.vector_splat(mask_llty.vector_length(), mask) + let mask = shift_mask_val( + 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), } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index f8f759365c0..49f30d67574 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -24,7 +24,7 @@ use type_of::LayoutLlvmExt; use value::Value; use rustc::ty::{self, Ty}; -use interfaces::CommonWriteMethods; +use interfaces::{CommonWriteMethods, TypeMethods}; 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, // otherwise some LLVM optimization passes don't work as expected let mut val_llty = cx.val_ty(v); - let v = if val_llty == Type::i1(cx) { - val_llty = Type::i8(cx); + let v = if val_llty == cx.i1() { + val_llty = cx.i8(); llvm::LLVMConstZExt(v, val_llty) } else { v @@ -432,7 +432,7 @@ pub fn codegen_static<'a, 'tcx>( if attrs.flags.contains(CodegenFnAttrFlags::USED) { // 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); } } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index a3c88d35a81..e19143efa98 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -23,6 +23,7 @@ use monomorphize::partitioning::CodegenUnit; use type_::Type; use type_of::PointeeInfo; +use interfaces::TypeMethods; use rustc_data_structures::base_n; use rustc_data_structures::small_c_str::SmallCStr; @@ -379,7 +380,7 @@ pub fn eh_personality(&self) -> &'b Value { } else { "rust_eh_personality" }; - let fty = Type::variadic_func(&[], Type::i32(self)); + let fty = &self.variadic_func(&[], &self.i32()); declare::declare_cfn(self, name, fty) } }; @@ -487,7 +488,7 @@ fn declare_intrinsic( macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( 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); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -495,7 +496,7 @@ macro_rules! ifn { ); ($name:expr, fn(...) -> $ret:expr) => ( 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); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -503,7 +504,7 @@ macro_rules! ifn { ); ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( 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); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -511,28 +512,28 @@ macro_rules! ifn { ); } 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 void = Type::void(cx); - let i1 = Type::i1(cx); - let t_i8 = Type::i8(cx); - let t_i16 = Type::i16(cx); - let t_i32 = Type::i32(cx); - let t_i64 = Type::i64(cx); - let t_i128 = Type::i128(cx); - let t_f32 = Type::f32(cx); - let t_f64 = Type::f64(cx); + let i8p = cx.i8p(); + let void = cx.void(); + let i1 = cx.i1(); + let t_i8 = cx.i8(); + let t_i16 = cx.i16(); + let t_i32 = cx.i32(); + let t_i64 = cx.i64(); + let t_i128 = cx.i128(); + let t_f32 = cx.f32(); + let t_f64 = cx.f64(); - let t_v2f32 = Type::vector(t_f32, 2); - let t_v4f32 = Type::vector(t_f32, 4); - let t_v8f32 = Type::vector(t_f32, 8); - let t_v16f32 = Type::vector(t_f32, 16); + let t_v2f32 = cx.vector(t_f32, 2); + let t_v4f32 = cx.vector(t_f32, 4); + let t_v8f32 = cx.vector(t_f32, 8); + let t_v16f32 = cx.vector(t_f32, 16); - let t_v2f64 = Type::vector(t_f64, 2); - let t_v4f64 = Type::vector(t_f64, 4); - let t_v8f64 = Type::vector(t_f64, 8); + let t_v2f64 = cx.vector(t_f64, 2); + let t_v4f64 = cx.vector(t_f64, 4); + 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.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void); @@ -785,8 +786,8 @@ macro_rules! mk_struct { ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void); if cx.sess().opts.debuginfo != DebugInfo::None { - ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void); - ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void); + ifn!("llvm.dbg.declare", fn(cx.metadata(), cx.metadata()) -> void); + ifn!("llvm.dbg.value", fn(cx.metadata(), t_i64, cx.metadata()) -> void); } None diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 78958080a3b..35b17a265a4 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -16,9 +16,8 @@ use builder::Builder; use declare; use rustc::session::config::DebugInfo; -use type_::Type; use value::Value; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; 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"; unsafe { - let llvm_type = Type::array(Type::i8(cx), + let llvm_type = cx.array(cx.i8(), section_contents.len() as u64); let section_var = declare::define_global(cx, section_var_name, diff --git a/src/librustc_codegen_llvm/interfaces/type_.rs b/src/librustc_codegen_llvm/interfaces/type_.rs index 2afa85accf9..7a2080e1a26 100644 --- a/src/librustc_codegen_llvm/interfaces/type_.rs +++ b/src/librustc_codegen_llvm/interfaces/type_.rs @@ -22,22 +22,20 @@ pub trait TypeMethods : Backend { fn ix(&self, num_bites: u64) -> Self::Type; fn f32(&self) -> Self::Type; fn f64(&self) -> Self::Type; - fn bool(&self) -> Self::Type; - fn char(&self) -> Self::Type; - fn i8p(&self) -> Self::Type; + fn x86_mmx(&self) -> 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 named_struct(&self, name: &str) -> Self::Type; fn array(&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 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 element_type(&self, ty: Self::Type) -> Self::Type; fn vector_length(&self, ty: Self::Type) -> usize; fn func_params(&self, ty: Self::Type) -> Vec; fn float_width(&self, ty: Self::Type) -> usize; - fn int_width(&self, ty: Self::Type) -> usize; + fn int_width(&self, ty: Self::Type) -> u64; } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 90837a95c60..6cc6692c3d1 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -32,7 +32,7 @@ use builder::Builder; use value::Value; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use rustc::session::Session; use syntax_pos::Span; @@ -252,7 +252,7 @@ pub fn codegen_intrinsic_call( let tp_ty = substs.type_at(0); let mut ptr = args[0].immediate(); if let PassMode::Cast(ty) = fn_ty.ret.mode { - ptr = bx.pointercast(ptr, 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 align = if name == "unaligned_volatile_load" { @@ -338,7 +338,7 @@ pub fn codegen_intrinsic_call( args[1].immediate() ], None); 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); bx.store(val, dest.llval, dest.align); @@ -388,7 +388,7 @@ pub fn codegen_intrinsic_call( } else { // rotate_left: (X << (S % BW)) | (X >> ((BW - 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 inv_shift = bx.urem(bx.sub(width, raw_shift), width); let shift1 = bx.shl(val, if is_left { shift } else { inv_shift }); @@ -495,7 +495,7 @@ pub fn codegen_intrinsic_call( failorder, weak); 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); bx.store(val, dest.llval, dest.align); @@ -582,32 +582,32 @@ fn one(x: Vec) -> T { fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> { use intrinsics::Type::*; match *t { - Void => vec![Type::void(cx)], + Void => vec![cx.void()], Integer(_signed, _width, llvm_width) => { - vec![Type::ix(cx, llvm_width as u64)] + vec![cx.ix( llvm_width as u64)] } Float(x) => { match x { - 32 => vec![Type::f32(cx)], - 64 => vec![Type::f64(cx)], + 32 => vec![cx.f32()], + 64 => vec![cx.f64()], _ => bug!() } } Pointer(ref t, ref llvm_elem, _const) => { let t = llvm_elem.as_ref().unwrap_or(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) => { let t = llvm_elem.as_ref().unwrap_or(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) => { let elems = contents.iter() .map(|t| one(ty_to_type(cx, t))) .collect::>(); - vec![Type::struct_(cx, &elems, false)] + vec![cx.struct_( &elems, false)] } Aggregate(true, ref contents) => { contents.iter() @@ -646,20 +646,20 @@ fn modify_as_needed( } intrinsics::Type::Pointer(_, Some(ref 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) => { let llvm_elem = one(ty_to_type(bx.cx(), llvm_elem)); vec![ 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 => { // the LLVM intrinsic uses a smaller integer // size than the C intrinsic's signature, so // 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()], } @@ -681,7 +681,7 @@ fn modify_as_needed( intrinsics::IntrinsicDef::Named(name) => { let f = declare::declare_cfn(cx, name, - Type::func(&inputs, outputs)); + cx.func(&inputs, outputs)); bx.call(f, &llargs, None) } }; @@ -705,7 +705,7 @@ fn modify_as_needed( if !fn_ty.ret.is_ignore() { 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); } else { 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 = cx.c_usize(size.bytes()); let align = align.abi(); - let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); - let src_ptr = bx.pointercast(src, Type::i8p(cx)); + let dst_ptr = bx.pointercast(dst, cx.i8p()); + let src_ptr = bx.pointercast(src, cx.i8p()); if allow_overlap { bx.memmove(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile) } else { @@ -748,7 +748,7 @@ fn memset_intrinsic( let (size, align) = cx.size_and_align_of(ty); let size = cx.c_usize(size.bytes()); 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) } @@ -763,7 +763,7 @@ fn try_intrinsic( if bx.sess().no_landing_pads() { bx.call(func, &[data], None); 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()) { codegen_msvc_try(bx, cx, func, data, local_ptr, dest); } else { @@ -839,7 +839,7 @@ fn codegen_msvc_try( // } // // 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 slot = bx.alloca(i64p, "slot", ptr_align); 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 // the landing pad clauses the exception's type had been matched to. // 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); - 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_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)); }); @@ -1078,7 +1078,7 @@ macro_rules! require_simd { found `{}` with length {}", in_len, in_ty, 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 `{}`", ret_ty, ret_ty.simd_type(tcx)); @@ -1167,8 +1167,8 @@ macro_rules! require_simd { _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty) } // truncate the mask to a vector of i1s - let i1 = Type::i1(bx.cx()); - let i1xn = Type::vector(i1, m_len as u64); + let i1 = bx.cx().i1(); + let i1xn = bx.cx().vector(i1, m_len as u64); let m_i1s = bx.trunc(args[0].immediate(), i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } @@ -1300,16 +1300,16 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize, mut no_pointers: usize) -> &'ll Type { // FIXME: use cx.layout_of(ty).llvm_type() ? let mut elem_ty = match elem_ty.sty { - ty::Int(v) => Type::int_from_ty(cx, v), - ty::Uint(v) => Type::uint_from_ty(cx, v), - ty::Float(v) => Type::float_from_ty(cx, v), + ty::Int(v) => cx.int_from_ty( v), + ty::Uint(v) => cx.uint_from_ty( v), + ty::Float(v) => cx.float_from_ty( v), _ => unreachable!(), }; while no_pointers > 0 { - elem_ty = elem_ty.ptr_to(); + elem_ty = cx.ptr_to(elem_ty); no_pointers -= 1; } - Type::vector(elem_ty, vec_len as u64) + cx.vector(elem_ty, vec_len as u64) } @@ -1386,13 +1386,13 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { } // 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); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { - let i1 = Type::i1(bx.cx()); - let i1xn = Type::vector(i1, in_len as u64); + let i1 = bx.cx().i1(); + let i1xn = bx.cx().vector(i1, in_len as u64); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1407,7 +1407,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); let f = declare::declare_cfn(bx.cx(), &llvm_intrinsic, - Type::func(&[ + bx.cx().func(&[ llvm_pointer_vec_ty, alignment_ty, mask_ty, @@ -1486,17 +1486,17 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { } // 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); // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { - let i1 = Type::i1(bx.cx()); - let i1xn = Type::vector(i1, in_len as u64); + let i1 = bx.cx().i1(); + let i1xn = bx.cx().vector(i1, in_len as u64); (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: let llvm_pointer_vec_ty = llvm_vector_ty(bx.cx(), underlying_ty, in_len, pointer_count); @@ -1509,7 +1509,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); 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, alignment_ty, mask_ty], ret_t)); @@ -1565,8 +1565,8 @@ macro_rules! arith_red { } else { // unordered arithmetic reductions do not: match f.bit_width() { - 32 => bx.cx().c_undef(Type::f32(bx.cx())), - 64 => bx.cx().c_undef(Type::f64(bx.cx())), + 32 => bx.cx().c_undef(bx.cx().f32()), + 64 => bx.cx().c_undef(bx.cx().f64()), v => { return_error!(r#" unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, @@ -1643,8 +1643,8 @@ macro_rules! bitwise_red { } // boolean reductions operate on vectors of i1s: - let i1 = Type::i1(bx.cx()); - let i1xn = Type::vector(i1, in_len as u64); + let i1 = bx.cx().i1(); + let i1xn = bx.cx().vector(i1, in_len as u64); bx.trunc(args[0].immediate(), i1xn) }; return match in_elem.sty { @@ -1654,7 +1654,7 @@ macro_rules! bitwise_red { if !$boolean { r } else { - bx.zext(r, Type::bool(bx.cx())) + bx.zext(r, bx.cx().bool()) } ) }, diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index e4c4417654a..a8312b2a469 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -14,10 +14,9 @@ use builder::Builder; use consts; use monomorphize; -use type_::Type; use value::Value; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use rustc::ty::{self, Ty}; use rustc::ty::layout::HasDataLayout; @@ -41,7 +40,10 @@ pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>, // Load the data pointer from the object. 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 = bx.load( bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]), @@ -61,7 +63,7 @@ pub fn get_usize( // Load the data pointer from the object. 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 ptr = bx.load( bx.inbounds_gep(llvtable, &[bx.cx().c_usize(self.0)]), @@ -96,7 +98,7 @@ pub fn get_vtable( } // 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 = methods.iter().cloned().map(|opt_mth| { diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 4b9727d1e7a..810baab48d6 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -26,7 +26,7 @@ use type_::Type; use value::Value; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use syntax::symbol::Symbol; use syntax_pos::Pos; @@ -268,7 +268,7 @@ fn codegen_terminator(&mut self, } }; 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) } }; @@ -560,7 +560,7 @@ fn codegen_terminator(&mut self, let dest = match ret_dest { _ if fn_ty.ret.is_indirect() => llargs[0], 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::Store(dst) => dst.llval, @@ -801,7 +801,7 @@ fn codegen_argument(&mut self, if by_ref && !arg.is_indirect() { // Have to load the argument, maybe while casting it. 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)); } else { // We can't use `PlaceRef::load` here because the argument @@ -902,7 +902,7 @@ fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBloc fn landing_pad_type(&self) -> &'ll Type { 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 { @@ -1014,7 +1014,7 @@ fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>, dst: PlaceRef<'tcx, &'ll Value>) { let src = self.codegen_operand(bx, src); 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); src.val.store(bx, PlaceRef::new_sized(cast_ptr, src.layout, align)); } diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs index 70e86b690fa..4c401a3fdb8 100644 --- a/src/librustc_codegen_llvm/mir/constant.rs +++ b/src/librustc_codegen_llvm/mir/constant.rs @@ -25,7 +25,7 @@ use syntax::ast::Mutability; use syntax::source_map::Span; use value::Value; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use super::super::callee; use super::FunctionCx; @@ -40,11 +40,11 @@ pub fn scalar_to_llvm( match cv { Scalar::Bits { size: 0, .. } => { 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 } => { 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 { unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { @@ -72,7 +72,7 @@ pub fn scalar_to_llvm( None => bug!("missing allocation {:?}", ptr.alloc_id), }; let llval = unsafe { llvm::LLVMConstInBoundsGEP( - consts::bitcast(base_addr, Type::i8p(cx)), + consts::bitcast(base_addr, cx.i8p()), &cx.c_usize(ptr.offset.bytes()), 1, ) }; @@ -109,7 +109,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll value: layout::Primitive::Pointer, valid_range: 0..=!0 }, - Type::i8p(cx) + cx.i8p() )); next_offset = offset + pointer_size; } diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index 84bc4280239..10282c1053f 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -23,7 +23,6 @@ use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext}; use monomorphize::Instance; use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode}; -use type_::Type; use value::Value; use interfaces::{BuilderMethods, CommonMethods}; @@ -420,7 +419,7 @@ fn create_funclets( // C++ personality function, but `catch (...)` has no type so // it's null. The 64 here is actually a bitfield which // 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); cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]); cp_bx.br(llbb); diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index 1581302c285..887b8fb0d0f 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -18,10 +18,9 @@ use builder::{Builder, MemFlags}; use value::Value; use type_of::LayoutLlvmExt; -use type_::Type; use glue; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use std::fmt; @@ -349,7 +348,7 @@ pub fn store_unsized( // 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 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); // Store the allocated region and the extra to the indirect place. @@ -463,7 +462,7 @@ pub fn codegen_operand(&mut self, // We've errored, so we don't have to produce working code. let layout = bx.cx().layout_of(ty); 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.align, ).load(bx) diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 3ad9f87cd90..b34eea0ce1c 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -18,12 +18,11 @@ use common::{CodegenCx, IntPredicate}; use consts; use type_of::LayoutLlvmExt; -use type_::Type; use value::Value; use glue; use mir::constant::const_alloc_to_llvm; -use interfaces::{BuilderMethods, CommonMethods}; +use interfaces::{BuilderMethods, CommonMethods, TypeMethods}; use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; @@ -68,11 +67,11 @@ pub fn from_const_alloc( let base_addr = consts::addr_of(bx.cx(), init, layout.align, None); 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()), 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) } @@ -160,7 +159,7 @@ pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'tcx, &'ll Value> let load = bx.load(llptr, self.align); scalar_load_metadata(load, scalar); if scalar.is_bool() { - bx.trunc(load, Type::i1(bx.cx())) + bx.trunc(load, bx.cx().i1()) } else { load } @@ -197,7 +196,7 @@ pub fn project_field( }; PlaceRef { // 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) { self.llextra } else { @@ -266,7 +265,7 @@ pub fn project_field( debug!("struct_field_ptr: DST field offset: {:?}", offset); // 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]); // Finally, cast back to the type expected @@ -274,7 +273,7 @@ pub fn project_field( debug!("struct_field_ptr: Field type is {:?}", ll_fty); PlaceRef { - llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()), + llval: bx.pointercast(byte_ptr, bx.cx().ptr_to(ll_fty)), llextra: self.llextra, layout: field, align: effective_field_align, @@ -380,7 +379,7 @@ pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: Vari bx.sess().target.target.arch == "aarch64" { // Issue #34427: As workaround for LLVM bug on ARM, // 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 (size, align) = self.layout.size_and_align(); let size = bx.cx().c_usize(size.bytes()); @@ -423,7 +422,7 @@ pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: Varia // Cast to the appropriate variant struct type. 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 } @@ -484,7 +483,7 @@ pub fn codegen_place(&mut self, // so we generate an abort let fnname = bx.cx().get_intrinsic(&("llvm.trap")); 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) } } @@ -544,7 +543,7 @@ pub fn codegen_place(&mut self, // Cast the place pointer type to the new // array or slice type (*[%_; new_len]). 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 } diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index 2496e10b74b..3066e38753a 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -26,7 +26,7 @@ use type_of::LayoutLlvmExt; use value::Value; -use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods}; +use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods, TypeMethods}; use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; @@ -117,7 +117,7 @@ pub fn codegen_rvalue(&mut self, // Use llvm.memset.p0i8.* to initialize byte arrays 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); return bx; } @@ -349,8 +349,8 @@ pub fn codegen_rvalue_operand( bx.intcast(llval, ll_t_out, signed) } (CastTy::Float, CastTy::Float) => { - let srcsz = ll_t_in.float_width(); - let dstsz = ll_t_out.float_width(); + let srcsz = bx.cx().float_width(ll_t_in); + let dstsz = bx.cx().float_width(ll_t_out); if dstsz > srcsz { bx.fpext(llval, ll_t_out) } 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. // 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. - 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 { // 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. @@ -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 // 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. - fn compute_clamp_bounds(signed: bool, int_ty: &Type) -> (u128, u128) { - let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero); - 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(); + let int_max = |signed: bool, int_ty: &'ll Type| -> u128 { + let shift_amount = 128 - bx.cx().int_width(int_ty); if signed { i128::MAX as u128 >> shift_amount } else { 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 { - i128::MIN >> (128 - int_ty.int_width()) + i128::MIN >> (128 - bx.cx().int_width(int_ty)) } else { 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 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), 64 => bx.cx().c_u64(bits as u64), n => bug!("unsupported float width {}", n), }; consts::bitcast(bits_llval, float_ty) }; - let (f_min, f_max) = match float_ty.float_width() { - 32 => compute_clamp_bounds::(signed, int_ty), - 64 => compute_clamp_bounds::(signed, int_ty), + let (f_min, f_max) = match bx.cx().float_width(float_ty) { + 32 => compute_clamp_bounds_single(signed, int_ty), + 64 => compute_clamp_bounds_double(signed, int_ty), n => bug!("unsupported float width {}", n), }; let f_min = float_bits_to_llval(f_min); diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index e78cf5dfa8d..d4b137926d5 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -16,10 +16,12 @@ use llvm::{Bool, False, True, TypeKind}; use context::CodegenCx; +use interfaces::TypeMethods; use syntax::ast; use rustc::ty::layout::{self, Align, Size}; use rustc_data_structures::small_c_str::SmallCStr; +use back::write; use std::fmt; @@ -39,84 +41,203 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } -impl Type { - pub fn void( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { +impl TypeMethods for CodegenCx<'ll, 'tcx> { + + fn void(&self) -> &'ll Type { unsafe { - llvm::LLVMVoidTypeInContext(cx.llcx) + llvm::LLVMVoidTypeInContext(self.llcx) } } - pub fn metadata( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { + fn metadata(&self) -> &'ll Type { unsafe { - llvm::LLVMRustMetadataTypeInContext(cx.llcx) + llvm::LLVMRustMetadataTypeInContext(self.llcx) } } - pub fn i1( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { + fn i1(&self) -> &'ll Type { unsafe { - llvm::LLVMInt1TypeInContext(cx.llcx) + llvm::LLVMInt1TypeInContext(self.llcx) } } - pub fn i8( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { + fn i8(&self) -> &'ll Type { unsafe { - llvm::LLVMInt8TypeInContext(cx.llcx) + llvm::LLVMInt8TypeInContext(self.llcx) } } - pub fn i8_llcx(llcx: &llvm::Context) -> &Type { + + fn i16(&self) -> &'ll Type { unsafe { - llvm::LLVMInt8TypeInContext(llcx) + + llvm::LLVMInt16TypeInContext(self.llcx) } } - pub fn i16( - cx: &CodegenCx<'ll, '_>) -> &'ll Type { + fn i32(&self) -> &'ll Type { unsafe { - - llvm::LLVMInt16TypeInContext(cx.llcx) + llvm::LLVMInt32TypeInContext(self.llcx) } } - pub fn i32( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { + fn i64(&self) -> &'ll Type { unsafe { - llvm::LLVMInt32TypeInContext(cx.llcx) + llvm::LLVMInt64TypeInContext(self.llcx) } } - pub fn i64( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { + fn i128(&self) -> &'ll Type { unsafe { - llvm::LLVMInt64TypeInContext(cx.llcx) - } - } - - pub fn i128( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { - unsafe { - llvm::LLVMIntTypeInContext(cx.llcx, 128) + llvm::LLVMIntTypeInContext(self.llcx, 128) } } // Creates an integer type with the given number of bits, e.g. i24 - pub fn ix( - cx: &CodegenCx<'ll, '_>, - num_bits: u64 + fn ix(&self, num_bits: u64) -> &'ll Type { + unsafe { + 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 { 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 @@ pub fn ix_llcx( } } - pub fn f32( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { - unsafe { - llvm::LLVMFloatTypeInContext(cx.llcx) - } + pub fn i8p_llcx(cx : &write::CodegenContext<'ll>, llcx: &'ll llvm::Context) -> &'ll Type { + cx.ptr_to(Type::i8_llcx(llcx)) + } +} + +impl CodegenCx<'ll, 'tcx> { + pub fn bool(&self) -> &'ll Type { + self.i8() } - pub fn f64( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { - unsafe { - llvm::LLVMDoubleTypeInContext(cx.llcx) - } + pub fn i8p(&self) -> &'ll Type { + self.ptr_to(self.i8()) } - pub fn bool( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { - Type::i8(cx) + pub fn isize(&self) -> &'ll Type { + self.isize_ty } - pub fn char( - cx: &CodegenCx<'ll, '_> - ) -> &'ll Type { - Type::i32(cx) - } - - 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), + pub fn t_int(&self) -> &'ll Type { + match &self.sess().target.target.target_c_int_width[..] { + "16" => self.i16(), + "32" => self.i32(), + "64" => self.i64(), width => bug!("Unsupported target_c_int_width: {}", width), } } pub fn int_from_ty( - cx: &CodegenCx<'ll, '_>, + &self, t: ast::IntTy ) -> &'ll Type { match t { - ast::IntTy::Isize => cx.isize_ty, - ast::IntTy::I8 => Type::i8(cx), - ast::IntTy::I16 => Type::i16(cx), - ast::IntTy::I32 => Type::i32(cx), - ast::IntTy::I64 => Type::i64(cx), - ast::IntTy::I128 => Type::i128(cx), + ast::IntTy::Isize => self.isize_ty, + ast::IntTy::I8 => self.i8(), + ast::IntTy::I16 => self.i16(), + ast::IntTy::I32 => self.i32(), + ast::IntTy::I64 => self.i64(), + ast::IntTy::I128 => self.i128(), } } pub fn uint_from_ty( - cx: &CodegenCx<'ll, '_>, + &self, t: ast::UintTy ) -> &'ll Type { match t { - ast::UintTy::Usize => cx.isize_ty, - ast::UintTy::U8 => Type::i8(cx), - ast::UintTy::U16 => Type::i16(cx), - ast::UintTy::U32 => Type::i32(cx), - ast::UintTy::U64 => Type::i64(cx), - ast::UintTy::U128 => Type::i128(cx), + ast::UintTy::Usize => self.isize_ty, + ast::UintTy::U8 => self.i8(), + ast::UintTy::U16 => self.i16(), + ast::UintTy::U32 => self.i32(), + ast::UintTy::U64 => self.i64(), + ast::UintTy::U128 => self.i128(), } } pub fn float_from_ty( - cx: &CodegenCx<'ll, '_>, + &self, t: ast::FloatTy ) -> &'ll Type { match t { - ast::FloatTy::F32 => Type::f32(cx), - ast::FloatTy::F64 => Type::f64(cx), + ast::FloatTy::F32 => self.f32(), + ast::FloatTy::F64 => self.f64(), } } - pub fn func( - 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 { + pub fn from_integer(&self, i: layout::Integer) -> &'ll Type { use rustc::ty::layout::Integer::*; match i { - I8 => Type::i8(cx), - I16 => Type::i16(cx), - I32 => Type::i32(cx), - I64 => Type::i64(cx), - I128 => Type::i128(cx), + I8 => self.i8(), + I16 => self.i16(), + I32 => self.i32(), + I64 => self.i64(), + I128 => self.i128(), } } /// Return a LLVM type that has at most the required alignment, /// 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. - let ity = layout::Integer::approximate_abi_align(cx, align); - Type::from_integer(cx, ity) + let ity = layout::Integer::approximate_abi_align(self, align); + self.from_integer(ity) } /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type { - let unit = layout::Integer::approximate_abi_align(cx, align); + pub fn padding_filler(&self, size: Size, align: Align) -> &'ll Type { + let unit = layout::Integer::approximate_abi_align(self, align); let size = size.bytes(); let unit_size = unit.size().bytes(); assert_eq!(size % unit_size, 0); - Type::array(Type::from_integer(cx, unit), size / unit_size) - } - - pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type { - unsafe { - llvm::LLVMX86MMXTypeInContext(cx.llcx) - } + self.array(self.from_integer(unit), size / unit_size) } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index fea02edf7be..4cc3d216aba 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -16,6 +16,7 @@ use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; use type_::Type; +use interfaces::TypeMethods; 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_64"); if use_x86_mmx { - return Type::x86_mmx(cx) + return cx.x86_mmx() } else { let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO); - return Type::vector(element, count); + return cx.vector(element, count); } } 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, 1, false), ], false); @@ -79,30 +80,30 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, match layout.fields { 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; match name { None => { - Type::struct_(cx, &[fill], packed) + cx.struct_( &[fill], packed) } Some(ref name) => { - let llty = Type::named_struct(cx, name); - llty.set_struct_body(&[fill], packed); + let llty = cx.named_struct( name); + cx.set_struct_body(llty, &[fill], packed); llty } } } 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 { .. } => { match name { None => { let (llfields, packed) = struct_llfields(cx, layout); - Type::struct_(cx, &llfields, packed) + cx.struct_( &llfields, packed) } Some(ref name) => { - let llty = Type::named_struct(cx, name); + let llty = cx.named_struct( name); *defer = Some((llty, layout)); llty } @@ -136,7 +137,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let padding = target_offset - offset; let padding_align = prev_effective_align.min(effective_field_align); 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); 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); debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", 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); } else { debug!("struct_llfields: offset: {:?} stride: {:?}", @@ -255,10 +256,10 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { let llty = match self.ty.sty { ty::Ref(_, 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() => { - 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) => { let sig = cx.tcx.normalize_erasing_late_bound_regions( @@ -307,7 +308,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { if let Some((llty, layout)) = defer { let (llfields, packed) = struct_llfields(cx, layout); - llty.set_struct_body(&llfields, packed) + cx.set_struct_body(llty, &llfields, packed) } llty @@ -316,7 +317,7 @@ fn 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 scalar.is_bool() { - return Type::i1(cx); + return cx.i1(); } } self.llvm_type(cx) @@ -325,17 +326,17 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: &layout::Scalar, offset: Size) -> &'a Type { match scalar.value { - layout::Int(i, _) => Type::from_integer(cx, i), - layout::Float(FloatTy::F32) => Type::f32(cx), - layout::Float(FloatTy::F64) => Type::f64(cx), + layout::Int(i, _) => cx.from_integer( i), + layout::Float(FloatTy::F32) => cx.f32(), + layout::Float(FloatTy::F64) => cx.f64(), layout::Pointer => { // If we know the alignment, pick something better than i8. 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 { - Type::i8(cx) + cx.i8() }; - pointee.ptr_to() + cx.ptr_to(pointee) } } } @@ -369,7 +370,7 @@ fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, // when immediate. We need to load/store `bool` as `i8` to avoid // crippling LLVM optimizations or triggering other LLVM bugs with `i1`. if immediate && scalar.is_bool() { - return Type::i1(cx); + return cx.i1(); } let offset = if index == 0 {