From 9e036c0ff0e8ba6018f9e0240064f7f7cf26885f Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 6 Mar 2016 12:38:46 +0200 Subject: [PATCH] trans: Provide the FnType for a direct call via Callee::direct_fn_type. --- src/librustc_trans/trans/abi.rs | 70 ++++++++++++++++-------------- src/librustc_trans/trans/callee.rs | 17 ++++++++ 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/librustc_trans/trans/abi.rs b/src/librustc_trans/trans/abi.rs index bd5de8efc19..6345395d441 100644 --- a/src/librustc_trans/trans/abi.rs +++ b/src/librustc_trans/trans/abi.rs @@ -150,17 +150,18 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, abi: Abi, sig: &ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType { + let mut fn_ty = FnType::unadjusted(ccx, abi, sig, extra_args); + fn_ty.adjust_for_abi(ccx, abi, sig); + fn_ty + } + + pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + abi: Abi, + sig: &ty::FnSig<'tcx>, + extra_args: &[Ty<'tcx>]) -> FnType { use self::Abi::*; let cconv = match ccx.sess().target.target.adjust_abi(abi) { - RustIntrinsic => { - // Intrinsics are emitted at the call site - ccx.sess().bug("asked to compute FnType of intrinsic"); - } - PlatformIntrinsic => { - // Intrinsics are emitted at the call site - ccx.sess().bug("asked to compute FnType of platform intrinsic"); - } - + RustIntrinsic | PlatformIntrinsic | Rust | RustCall => llvm::CCallConv, // It's the ABI's job to select this, not us. @@ -309,14 +310,20 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } - let mut fty = FnType { + FnType { args: args, ret: ret, variadic: sig.variadic, cconv: cconv - }; + } + } - if abi == Rust || abi == RustCall { + pub fn adjust_for_abi<'a, 'tcx>(&mut self, + ccx: &CrateContext<'a, 'tcx>, + abi: Abi, + sig: &ty::FnSig<'tcx>) { + if abi == Abi::Rust || abi == Abi::RustCall || + abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { let fixup = |arg: &mut ArgType| { if !arg.ty.is_aggregate() { // Scalars and vectors, always immediate. @@ -332,49 +339,48 @@ pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg.cast = Some(Type::ix(ccx, size * 8)); } }; - if fty.ret.ty != Type::void(ccx) { - // Fat pointers are returned by-value. + // Fat pointers are returned by-value. + if !self.ret.is_ignore() { if !type_is_fat_ptr(ccx.tcx(), sig.output.unwrap()) { - fixup(&mut fty.ret); + fixup(&mut self.ret); } } - for arg in &mut fty.args { + for arg in &mut self.args { + if arg.is_ignore() { continue; } fixup(arg); } - if fty.ret.is_indirect() { - fty.ret.attrs.set(llvm::Attribute::StructRet); + if self.ret.is_indirect() { + self.ret.attrs.set(llvm::Attribute::StructRet); } - return fty; + return; } match &ccx.sess().target.target.arch[..] { - "x86" => cabi_x86::compute_abi_info(ccx, &mut fty), + "x86" => cabi_x86::compute_abi_info(ccx, self), "x86_64" => if ccx.sess().target.target.options.is_like_windows { - cabi_x86_win64::compute_abi_info(ccx, &mut fty); + cabi_x86_win64::compute_abi_info(ccx, self); } else { - cabi_x86_64::compute_abi_info(ccx, &mut fty); + cabi_x86_64::compute_abi_info(ccx, self); }, - "aarch64" => cabi_aarch64::compute_abi_info(ccx, &mut fty), + "aarch64" => cabi_aarch64::compute_abi_info(ccx, self), "arm" => { let flavor = if ccx.sess().target.target.target_os == "ios" { cabi_arm::Flavor::Ios } else { cabi_arm::Flavor::General }; - cabi_arm::compute_abi_info(ccx, &mut fty, flavor); + cabi_arm::compute_abi_info(ccx, self, flavor); }, - "mips" => cabi_mips::compute_abi_info(ccx, &mut fty), - "powerpc" => cabi_powerpc::compute_abi_info(ccx, &mut fty), - "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, &mut fty), - "asmjs" => cabi_asmjs::compute_abi_info(ccx, &mut fty), + "mips" => cabi_mips::compute_abi_info(ccx, self), + "powerpc" => cabi_powerpc::compute_abi_info(ccx, self), + "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self), + "asmjs" => cabi_asmjs::compute_abi_info(ccx, self), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)) } - if fty.ret.is_indirect() { - fty.ret.attrs.set(llvm::Attribute::StructRet); + if self.ret.is_indirect() { + self.ret.attrs.set(llvm::Attribute::StructRet); } - - fty } pub fn llvm_type(&self, ccx: &CrateContext) -> Type { diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 9236d29ca72..1d302b65f9c 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -210,6 +210,23 @@ pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>, } } + /// Get the abi::FnType for a direct call. Mainly deals with the fact + /// that a Virtual call doesn't take the vtable, like its shim does. + /// The extra argument types are for variadic (extern "C") functions. + pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>, + extra_args: &[Ty<'tcx>]) -> FnType { + let abi = self.ty.fn_abi(); + let sig = ccx.tcx().erase_late_bound_regions(self.ty.fn_sig()); + let sig = infer::normalize_associated_type(ccx.tcx(), &sig); + let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args); + if let Virtual(_) = self.data { + // Don't pass the vtable, it's not an argument of the virtual fn. + fn_ty.args[1].ignore(); + } + fn_ty.adjust_for_abi(ccx, abi, &sig); + fn_ty + } + /// This behemoth of a function translates function calls. Unfortunately, in /// order to generate more efficient LLVM output at -O0, it has quite a complex /// signature (refactoring this into two functions seems like a good idea).