diff --git a/src/librustc_trans/trans/abi.rs b/src/librustc_trans/trans/abi.rs index d802a41ed69..a0351e32259 100644 --- a/src/librustc_trans/trans/abi.rs +++ b/src/librustc_trans/trans/abi.rs @@ -10,8 +10,7 @@ pub use self::ArgKind::*; -use llvm::{self, AttrHelper, ValueRef}; -use trans::attributes; +use llvm; use trans::common::{return_type_is_void, type_is_fat_ptr}; use trans::context::CrateContext; use trans::cabi_x86; @@ -23,7 +22,7 @@ use trans::cabi_powerpc; use trans::cabi_powerpc64; use trans::cabi_mips; use trans::cabi_asmjs; -use trans::machine::llsize_of_alloc; +use trans::machine::{llsize_of_alloc, llsize_of_real}; use trans::type_::Type; use trans::type_of; @@ -191,6 +190,13 @@ impl FnType { cconv: cconv }; + // Add ZExt attributes to i1 arguments and returns. + for arg in Some(&mut fty.ret).into_iter().chain(&mut fty.args) { + if arg.ty == Type::i1(ccx) { + arg.attr = Some(llvm::Attribute::ZExt); + } + } + if abi == Rust || abi == RustCall { let fixup = |arg: &mut ArgType| { if !arg.ty.is_aggregate() { @@ -246,7 +252,7 @@ impl FnType { fty } - pub fn to_llvm(&self, ccx: &CrateContext) -> Type { + pub fn llvm_type(&self, ccx: &CrateContext) -> Type { let mut llargument_tys = Vec::new(); let llreturn_ty = if self.ret.is_indirect() { @@ -281,19 +287,29 @@ impl FnType { } } - pub fn add_attributes(&self, llfn: ValueRef) { - let mut i = if self.ret.is_indirect() { - 1 - } else { - 0 + pub fn llvm_attrs(&self, ccx: &CrateContext) -> llvm::AttrBuilder { + let mut attrs = llvm::AttrBuilder::new(); + let mut i = if self.ret.is_indirect() { 1 } else { 0 }; + + // Add attributes that are always applicable, independent of the concrete foreign ABI + if self.ret.is_indirect() { + let llret_sz = llsize_of_real(ccx, self.ret.ty); + + // The outptr can be noalias and nocapture because it's entirely + // invisible to the program. We also know it's nonnull as well + // as how many bytes we can dereference + attrs.arg(i, llvm::Attribute::StructRet) + .arg(i, llvm::Attribute::NoAlias) + .arg(i, llvm::Attribute::NoCapture) + .arg(i, llvm::DereferenceableAttribute(llret_sz)); }; + // Add attributes that depend on the concrete foreign ABI if let Some(attr) = self.ret.attr { - attr.apply_llfn(i, llfn); + attrs.arg(i, attr); } i += 1; - for arg in &self.args { if arg.is_ignore() { continue; @@ -302,12 +318,12 @@ impl FnType { if arg.pad.is_some() { i += 1; } if let Some(attr) = arg.attr { - attr.apply_llfn(i, llfn); + attrs.arg(i, attr); } i += 1; } - attributes::unwind(llfn, false); + attrs } } diff --git a/src/librustc_trans/trans/cabi_aarch64.rs b/src/librustc_trans/trans/cabi_aarch64.rs index c98c53894ca..65d2ad9c4fa 100644 --- a/src/librustc_trans/trans/cabi_aarch64.rs +++ b/src/librustc_trans/trans/cabi_aarch64.rs @@ -10,7 +10,7 @@ #![allow(non_upper_case_globals)] -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute}; +use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; use trans::abi::{FnType, ArgType, Indirect}; use trans::context::CrateContext; use trans::type_::Type; @@ -163,9 +163,6 @@ fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> { fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { if is_reg_ty(ret.ty) { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt) - } return; } if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) { @@ -189,14 +186,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { return; } ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); } fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { if is_reg_ty(arg.ty) { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } return; } if let Some((base_ty, members)) = is_homogenous_aggregate_ty(arg.ty) { diff --git a/src/librustc_trans/trans/cabi_arm.rs b/src/librustc_trans/trans/cabi_arm.rs index abdc5bbd79f..77941a853e6 100644 --- a/src/librustc_trans/trans/cabi_arm.rs +++ b/src/librustc_trans/trans/cabi_arm.rs @@ -10,7 +10,7 @@ #![allow(non_upper_case_globals)] -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute}; +use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; use trans::abi::{FnType, ArgType, Indirect}; use trans::context::CrateContext; use trans::type_::Type; @@ -131,9 +131,6 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize { fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) { if is_reg_ty(ret.ty) { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt); - } return; } let size = ty_size(ret.ty, align_fn); @@ -149,14 +146,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType, align_fn: TyAlignFn) { return; } ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); } fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, align_fn: TyAlignFn) { if is_reg_ty(arg.ty) { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } return; } let align = align_fn(arg.ty); diff --git a/src/librustc_trans/trans/cabi_asmjs.rs b/src/librustc_trans/trans/cabi_asmjs.rs index fd831f0e253..5c9bf28e4e0 100644 --- a/src/librustc_trans/trans/cabi_asmjs.rs +++ b/src/librustc_trans/trans/cabi_asmjs.rs @@ -20,7 +20,7 @@ use trans::type_::Type; // See the https://github.com/kripken/emscripten-fastcomp-clang repository. // The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions. -fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { +fn classify_ret_ty(ret: &mut ArgType) { match ret.ty.kind() { Struct => { let field_types = ret.ty.field_types(); @@ -28,38 +28,28 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { ret.cast = Some(field_types[0]); } else { ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); - } - }, - Array => { - ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); - }, - _ => { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt); } } + Array => { + ret.kind = Indirect; + } + _ => {} } } -fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { +fn classify_arg_ty(arg: &mut ArgType) { if arg.ty.is_aggregate() { arg.kind = Indirect; arg.attr = Some(Attribute::ByVal); - } else { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } } } pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { if fty.ret.ty != Type::void(ccx) { - classify_ret_ty(ccx, &mut fty.ret); + classify_ret_ty(&mut fty.ret); } for arg in &mut fty.args { - classify_arg_ty(ccx, arg); + classify_arg_ty(arg); } } diff --git a/src/librustc_trans/trans/cabi_mips.rs b/src/librustc_trans/trans/cabi_mips.rs index a07f897c122..419c56072b4 100644 --- a/src/librustc_trans/trans/cabi_mips.rs +++ b/src/librustc_trans/trans/cabi_mips.rs @@ -13,7 +13,7 @@ use libc::c_uint; use std::cmp; use llvm; -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute}; +use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; use trans::abi::{ArgType, FnType, Indirect}; use trans::context::CrateContext; use trans::type_::Type; @@ -86,17 +86,6 @@ fn ty_size(ty: Type) -> usize { } } -fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { - if is_reg_ty(ret.ty) { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt); - } - } else { - ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); - } -} - fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) { let orig_offset = *offset; let size = ty_size(arg.ty) * 8; @@ -106,11 +95,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) { *offset = align_up_to(*offset, align); *offset += align_up_to(size, align * 8) / 8; - if is_reg_ty(arg.ty) { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } - } else { + if !is_reg_ty(arg.ty) { arg.cast = Some(struct_ty(ccx, arg.ty)); arg.pad = padding_ty(ccx, align, orig_offset); } @@ -162,7 +147,9 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type { pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { if fty.ret.ty != Type::void(ccx) { - classify_ret_ty(ccx, &mut fty.ret); + if !is_reg_ty(fty.ret.ty) { + fty.ret.kind = Indirect; + } } let mut offset = if fty.ret.is_indirect() { 4 } else { 0 }; diff --git a/src/librustc_trans/trans/cabi_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs index 19307cc230f..ecd5b71ada9 100644 --- a/src/librustc_trans/trans/cabi_powerpc.rs +++ b/src/librustc_trans/trans/cabi_powerpc.rs @@ -10,7 +10,7 @@ use libc::c_uint; use llvm; -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute}; +use llvm::{Integer, Pointer, Float, Double, Struct, Array}; use trans::abi::{FnType, ArgType, Indirect}; use trans::context::CrateContext; use trans::type_::Type; @@ -82,17 +82,6 @@ fn ty_size(ty: Type) -> usize { } } -fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { - if is_reg_ty(ret.ty) { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt); - } - } else { - ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); - } -} - fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) { let orig_offset = *offset; let size = ty_size(arg.ty) * 8; @@ -102,11 +91,7 @@ fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) { *offset = align_up_to(*offset, align); *offset += align_up_to(size, align * 8) / 8; - if is_reg_ty(arg.ty) { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } - } else { + if !is_reg_ty(arg.ty) { arg.cast = Some(struct_ty(ccx, arg.ty)); arg.pad = padding_ty(ccx, align, orig_offset); } @@ -157,7 +142,9 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type { pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { if fty.ret.ty != Type::void(ccx) { - classify_ret_ty(ccx, &mut fty.ret); + if !is_reg_ty(fty.ret.ty) { + fty.ret.kind = Indirect; + } } let mut offset = if fty.ret.is_indirect() { 4 } else { 0 }; diff --git a/src/librustc_trans/trans/cabi_powerpc64.rs b/src/librustc_trans/trans/cabi_powerpc64.rs index ee1e5a39b61..b28ec618650 100644 --- a/src/librustc_trans/trans/cabi_powerpc64.rs +++ b/src/librustc_trans/trans/cabi_powerpc64.rs @@ -15,7 +15,7 @@ // Alignment of 128 bit types is not currently handled, this will // need to be fixed when PowerPC vector support is added. -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute}; +use llvm::{Integer, Pointer, Float, Double, Struct, Array}; use trans::abi::{FnType, ArgType, Indirect}; use trans::context::CrateContext; use trans::type_::Type; @@ -153,16 +153,12 @@ fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> { fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { if is_reg_ty(ret.ty) { - if ret.ty == Type::i1(ccx) { - ret.attr = Some(Attribute::ZExt); - } return; } // The PowerPC64 big endian ABI doesn't return aggregates in registers if ccx.sess().target.target.target_endian == "big" { ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); } if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) { @@ -187,14 +183,10 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { } ret.kind = Indirect; - ret.attr = Some(Attribute::StructRet); } fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) { if is_reg_ty(arg.ty) { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } return; } diff --git a/src/librustc_trans/trans/cabi_x86.rs b/src/librustc_trans/trans/cabi_x86.rs index b5dd3393ba9..fd1b8b21401 100644 --- a/src/librustc_trans/trans/cabi_x86.rs +++ b/src/librustc_trans/trans/cabi_x86.rs @@ -30,17 +30,11 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { 2 => fty.ret.cast = Some(Type::i16(ccx)), 4 => fty.ret.cast = Some(Type::i32(ccx)), 8 => fty.ret.cast = Some(Type::i64(ccx)), - _ => { - fty.ret.kind = Indirect; - fty.ret.attr = Some(Attribute::StructRet); - } + _ => fty.ret.kind = Indirect } } else { fty.ret.kind = Indirect; - fty.ret.attr = Some(Attribute::StructRet); } - } else if fty.ret.ty == Type::i1(ccx) { - fty.ret.attr = Some(Attribute::ZExt); } for arg in &mut fty.args { @@ -51,8 +45,6 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { arg.kind = Indirect; arg.attr = Some(Attribute::ByVal); } - } else if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); } } } diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index 4c6ff6ff955..ab32ca206fc 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -387,21 +387,17 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { fn x86_64_ty(ccx: &CrateContext, arg: &mut ArgType, is_mem_cls: F, - ind_attr: Attribute) + ind_attr: Option) where F: FnOnce(&[RegClass]) -> bool { if !arg.ty.is_reg_ty() { let cls = classify_ty(arg.ty); if is_mem_cls(&cls) { arg.kind = Indirect; - arg.attr = Some(ind_attr); + arg.attr = ind_attr; } else { arg.cast = Some(llreg_ty(ccx, &cls)); } - } else { - if arg.ty == Type::i1(ccx) { - arg.attr = Some(Attribute::ZExt); - } } } @@ -417,7 +413,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { } else { false } - }, Attribute::StructRet); + }, None); } for arg in &mut fty.args { @@ -436,7 +432,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { sse_regs -= needed_sse; } in_mem - }, Attribute::ByVal); + }, Some(Attribute::ByVal)); // An integer, pointer, double or float parameter // thus the above closure passed to `x86_64_ty` won't diff --git a/src/librustc_trans/trans/cabi_x86_win64.rs b/src/librustc_trans/trans/cabi_x86_win64.rs index ab9323dda7b..e9a06fd8d6b 100644 --- a/src/librustc_trans/trans/cabi_x86_win64.rs +++ b/src/librustc_trans/trans/cabi_x86_win64.rs @@ -17,27 +17,22 @@ use trans::type_::Type; // Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) { - let fixup = |a: &mut ArgType, indirect_attr| { + let fixup = |a: &mut ArgType| { if a.ty.kind() == Struct { match llsize_of_alloc(ccx, a.ty) { 1 => a.cast = Some(Type::i8(ccx)), 2 => a.cast = Some(Type::i16(ccx)), 4 => a.cast = Some(Type::i32(ccx)), 8 => a.cast = Some(Type::i64(ccx)), - _ => { - a.kind = Indirect; - a.attr = indirect_attr; - } + _ => a.kind = Indirect } - } else if a.ty == Type::i1(ccx) { - a.attr = Some(Attribute::ZExt); } }; if fty.ret.ty != Type::void(ccx) { - fixup(&mut fty.ret, Some(Attribute::StructRet)); + fixup(&mut fty.ret); } for arg in &mut fty.args { - fixup(arg, None); + fixup(arg); } } diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs index 76195f19e9f..f7bc22a4482 100644 --- a/src/librustc_trans/trans/declare.rs +++ b/src/librustc_trans/trans/declare.rs @@ -103,17 +103,20 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, debug!("declare_rust_fn (after region erasure) sig={:?}", sig); let fty = FnType::new(ccx, f.abi, &sig, &[]); - let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.to_llvm(ccx)); + let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx)); if sig.output == ty::FnDiverging { llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn); } - if f.abi == Abi::Rust || f.abi == Abi::RustCall { - attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); + let attrs = if f.abi == Abi::Rust || f.abi == Abi::RustCall { + attributes::from_fn_type(ccx, fn_type) } else { - fty.add_attributes(llfn); - } + attributes::unwind(llfn, false); + fty.llvm_attrs(ccx) + }; + + attrs.apply_llfn(llfn); llfn } diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 46eb8006272..870853af1ee 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -247,47 +247,13 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // A function pointer is called without the declaration available, so we have to apply // any attributes with ABI implications directly to the call instruction. - let mut attrs = llvm::AttrBuilder::new(); - // Add attributes that are always applicable, independent of the concrete foreign ABI - if fn_type.ret.is_indirect() { - let llret_sz = machine::llsize_of_real(ccx, fn_type.ret.ty); - - // The outptr can be noalias and nocapture because it's entirely - // invisible to the program. We also know it's nonnull as well - // as how many bytes we can dereference - attrs.arg(1, llvm::Attribute::NoAlias) - .arg(1, llvm::Attribute::NoCapture) - .arg(1, llvm::DereferenceableAttribute(llret_sz)); - }; - - // Add attributes that depend on the concrete foreign ABI - let mut arg_idx = if fn_type.ret.is_indirect() { 1 } else { 0 }; - match fn_type.ret.attr { - Some(attr) => { attrs.arg(arg_idx, attr); }, - _ => () - } - - arg_idx += 1; - for arg_ty in &fn_type.args { - if arg_ty.is_ignore() { - continue; - } - // skip padding - if arg_ty.pad.is_some() { arg_idx += 1; } - - if let Some(attr) = arg_ty.attr { - attrs.arg(arg_idx, attr); - } - - arg_idx += 1; - } let llforeign_retval = CallWithConv(bcx, llfn, &llargs_foreign[..], fn_type.cconv, - Some(attrs), + Some(fn_type.llvm_attrs(ccx)), call_debug_loc); // If the function we just called does not use an outpointer, diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 662471241d5..634d33d445e 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -322,7 +322,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ty::TyFnPtr(f) => { let sig = cx.tcx().erase_late_bound_regions(&f.sig); let sig = infer::normalize_associated_type(cx.tcx(), &sig); - FnType::new(cx, f.abi, &sig, &[]).to_llvm(cx).ptr_to() + FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to() } ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx), ty::TyTuple(..) => {