diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-02 01:59:28 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-02 01:59:28 -0700 |
commit | 3092d6130c7f4b462d36377eefffb399c594a6b2 (patch) | |
tree | 221b43f83d6ed00fa44ea4a62f04126ae7f20bba | |
parent | daf1935534de9cd09a8d3f4384af20eaa4fe0f01 (diff) | |
parent | 330d16a746aa6673da94d200cdb5decbab005bfa (diff) |
Auto merge of #729 - emilio:mangling-hack, r=fitzgen
ir: Use the mangling hack in win32 too.
-rw-r--r-- | build.rs | 6 | ||||
-rw-r--r-- | src/codegen/mod.rs | 39 | ||||
-rw-r--r-- | src/ir/context.rs | 35 | ||||
-rw-r--r-- | src/ir/function.rs | 70 |
4 files changed, 114 insertions, 36 deletions
@@ -1,6 +1,8 @@ mod codegen { extern crate quasi_codegen; use std::env; + use std::fs::File; + use std::io::Write; use std::path::{Path, PathBuf}; pub fn main() { @@ -13,6 +15,10 @@ mod codegen { println!("cargo:rerun-if-changed=src/codegen/error.rs"); println!("cargo:rerun-if-changed=src/codegen/helpers.rs"); println!("cargo:rerun-if-changed=src/codegen/struct_layout.rs"); + + let mut dst = + File::create(Path::new(&out_dir).join("host-target.txt")).unwrap(); + dst.write_all(env::var("TARGET").unwrap().as_bytes()).unwrap(); } } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 449cfa03..86aafa39 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -15,7 +15,7 @@ use ir::context::{BindgenContext, ItemId}; use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; -use ir::function::{Function, FunctionSig}; +use ir::function::{Abi, Function, FunctionSig}; use ir::int::IntKind; use ir::item::{Item, ItemAncestors, ItemCanonicalName, ItemCanonicalPath, ItemSet}; @@ -34,7 +34,7 @@ use std::collections::hash_map::{Entry, HashMap}; use std::fmt::Write; use std::mem; use std::ops; -use syntax::abi::Abi; +use syntax::abi; use syntax::ast; use syntax::codemap::{Span, respan}; use syntax::ptr::P; @@ -221,7 +221,7 @@ struct ForeignModBuilder { } impl ForeignModBuilder { - fn new(abi: Abi) -> Self { + fn new(abi: abi::Abi) -> Self { ForeignModBuilder { inner: ast::ForeignMod { abi: abi, @@ -503,7 +503,7 @@ impl CodeGenerator for Var { vis: ast::Visibility::Public, }; - let item = ForeignModBuilder::new(Abi::C) + let item = ForeignModBuilder::new(abi::Abi::C) .with_foreign_item(item) .build(ctx); result.push(item); @@ -1927,7 +1927,7 @@ impl MethodCodegen for Method { let sig = ast::MethodSig { unsafety: ast::Unsafety::Unsafe, - abi: Abi::Rust, + abi: abi::Abi::Rust, decl: P(fndecl), generics: ast::Generics::default(), constness: respan(ctx.span(), ast::Constness::NotConst), @@ -2683,7 +2683,7 @@ impl TryToRustTy for Type { // sizeof(NonZero<_>) optimization with opaque blobs (because // they aren't NonZero), so don't *ever* use an or_opaque // variant here. - let ty = fs.try_to_rust_ty(ctx, &())?; + let ty = fs.try_to_rust_ty(ctx, item)?; let prefix = ctx.trait_prefix(); Ok(quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>)) @@ -2851,11 +2851,11 @@ impl TryToRustTy for TemplateInstantiation { } impl TryToRustTy for FunctionSig { - type Extra = (); + type Extra = Item; fn try_to_rust_ty(&self, ctx: &BindgenContext, - _: &()) + item: &Item) -> error::Result<P<ast::Ty>> { // TODO: we might want to consider ignoring the reference return value. let ret = utils::fnsig_return_ty(ctx, &self); @@ -2867,9 +2867,17 @@ impl TryToRustTy for FunctionSig { variadic: self.is_variadic(), }); + let abi = match self.abi() { + Abi::Known(abi) => abi, + Abi::Unknown(unknown_abi) => { + panic!("Invalid or unknown abi {:?} for function {:?} {:?}", + unknown_abi, item.canonical_name(ctx), self); + } + }; + let fnty = ast::TyKind::BareFn(P(ast::BareFnTy { unsafety: ast::Unsafety::Unsafe, - abi: self.abi().expect("Invalid or unknown ABI for function!"), + abi: abi, lifetimes: vec![], decl: decl, })); @@ -2949,8 +2957,15 @@ impl CodeGenerator for Function { vis: ast::Visibility::Public, }; - let item = ForeignModBuilder::new(signature.abi() - .expect("Invalid or unknown ABI for function!")) + let abi = match signature.abi() { + Abi::Known(abi) => abi, + Abi::Unknown(unknown_abi) => { + panic!("Invalid or unknown abi {:?} for function {:?} ({:?})", + unknown_abi, canonical_name, self); + } + }; + + let item = ForeignModBuilder::new(abi) .with_foreign_item(foreign_item) .build(ctx); @@ -3420,7 +3435,7 @@ mod utils { _ => panic!("How?"), }; - let decl_ty = signature.try_to_rust_ty(ctx, &()) + let decl_ty = signature.try_to_rust_ty(ctx, sig) .expect("function signature to Rust type conversion is infallible"); match decl_ty.unwrap().node { ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl, diff --git a/src/ir/context.rs b/src/ir/context.rs index c5807d2b..a70425c7 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -139,6 +139,9 @@ pub struct BindgenContext<'ctx> { /// The active replacements collected from replaces="xxx" annotations. replacements: HashMap<Vec<String>, ItemId>, + /// The target string bindgen was able to deduce from the input. + effective_target: String, + collected_typerefs: bool, /// Dummy structures for code generation. @@ -232,6 +235,32 @@ impl<'ctx> BindgenContext<'ctx> { parse_options) .expect("TranslationUnit::parse failed"); + // TODO(emilio): Use the CXTargetInfo here when available. + // + // see: https://reviews.llvm.org/D32389 + let mut effective_target = None; + for opt in &options.clang_args { + if opt.starts_with("--target=") { + let mut split = opt.split('='); + split.next(); + effective_target = Some(split.next().unwrap().to_owned()); + break; + } + } + + if effective_target.is_none() { + use std::env; + // If we're running from a build script, try to find the cargo + // target. + effective_target = env::var("TARGET").ok(); + } + + if effective_target.is_none() { + const HOST_TARGET: &'static str = + include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); + effective_target = Some(HOST_TARGET.to_owned()); + } + let root_module = Self::build_root_module(ItemId(0)); let mut me = BindgenContext { items: Default::default(), @@ -244,6 +273,7 @@ impl<'ctx> BindgenContext<'ctx> { currently_parsed_types: vec![], parsed_macros: Default::default(), replacements: Default::default(), + effective_target: effective_target.unwrap(), collected_typerefs: false, gen_ctx: None, span: DUMMY_SP, @@ -764,6 +794,11 @@ impl<'ctx> BindgenContext<'ctx> { Item::new(id, None, None, id, ItemKind::Module(module)) } + /// Returns the target triple bindgen is running over. + pub fn target(&self) -> &str { + &self.effective_target + } + /// Get the root module. pub fn root_module(&self) -> ItemId { self.root_module diff --git a/src/ir/function.rs b/src/ir/function.rs index 10a791d8..6281306b 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -79,6 +79,25 @@ impl DotAttributes for Function { } } +/// An ABI extracted from a clang cursor. +#[derive(Debug, Copy, Clone)] +pub enum Abi { + /// A known ABI, that rust also understand. + Known(abi::Abi), + /// An unknown or invalid ABI. + Unknown(CXCallingConv), +} + +impl Abi { + /// Returns whether this Abi is known or not. + fn is_unknown(&self) -> bool { + match *self { + Abi::Unknown(..) => true, + _ => false, + } + } +} + /// A function signature. #[derive(Debug)] pub struct FunctionSig { @@ -93,29 +112,32 @@ pub struct FunctionSig { is_variadic: bool, /// The ABI of this function. - abi: Option<abi::Abi>, + abi: Abi, } -fn get_abi(cc: CXCallingConv) -> Option<abi::Abi> { +fn get_abi(cc: CXCallingConv) -> Abi { use clang_sys::*; - match cc { - CXCallingConv_Default => Some(abi::Abi::C), - CXCallingConv_C => Some(abi::Abi::C), - CXCallingConv_X86StdCall => Some(abi::Abi::Stdcall), - CXCallingConv_X86FastCall => Some(abi::Abi::Fastcall), - CXCallingConv_AAPCS => Some(abi::Abi::Aapcs), - CXCallingConv_X86_64Win64 => Some(abi::Abi::Win64), - _ => None, - } + Abi::Known(match cc { + CXCallingConv_Default => abi::Abi::C, + CXCallingConv_C => abi::Abi::C, + CXCallingConv_X86StdCall => abi::Abi::Stdcall, + CXCallingConv_X86FastCall => abi::Abi::Fastcall, + CXCallingConv_AAPCS => abi::Abi::Aapcs, + CXCallingConv_X86_64Win64 => abi::Abi::Win64, + other => return Abi::Unknown(other), + }) } -// Mac os needs __ for mangled symbols but rust will automatically prepend the extra _. -// We need to make sure that we don't include __ because rust will turn into ___. +// Mac os and Win32 need __ for mangled symbols but rust will automatically +// prepend the extra _. // -// TODO(emilio): This is wrong when the target system is not the host -// system. See https://github.com/servo/rust-bindgen/issues/593 -fn macos_mangling(symbol: &mut String) { - if cfg!(target_os = "macos") && symbol.starts_with("_") { +// We need to make sure that we don't include __ because rust will turn into +// ___. +fn mangling_hack_if_needed(ctx: &BindgenContext, symbol: &mut String) { + // NB: win64 also contains the substring "win32" in the target triple, so + // we need to actually check for i686... + if ctx.target().contains("macos") || + (ctx.target().contains("i686") && ctx.target().contains("windows")) { symbol.remove(0); } } @@ -138,7 +160,7 @@ pub fn cursor_mangling(ctx: &BindgenContext, if let Ok(mut manglings) = cursor.cxx_manglings() { if let Some(mut m) = manglings.pop() { - macos_mangling(&mut m); + mangling_hack_if_needed(ctx, &mut m); return Some(m); } } @@ -148,7 +170,7 @@ pub fn cursor_mangling(ctx: &BindgenContext, return None; } - macos_mangling(&mut mangling); + mangling_hack_if_needed(ctx, &mut mangling); if cursor.kind() == clang_sys::CXCursor_Destructor { // With old (3.8-) libclang versions, and the Itanium ABI, clang returns @@ -185,7 +207,7 @@ impl FunctionSig { pub fn new(return_type: ItemId, arguments: Vec<(Option<String>, ItemId)>, is_variadic: bool, - abi: Option<abi::Abi>) + abi: Abi) -> Self { FunctionSig { return_type: return_type, @@ -299,7 +321,7 @@ impl FunctionSig { let call_conv = ty.call_conv(); let abi = get_abi(call_conv); - if abi.is_none() { + if abi.is_unknown() { warn!("Unknown calling convention: {:?}", call_conv); } @@ -317,7 +339,7 @@ impl FunctionSig { } /// Get this function signature's ABI. - pub fn abi(&self) -> Option<abi::Abi> { + pub fn abi(&self) -> Abi { self.abi } @@ -429,8 +451,8 @@ impl CanDeriveDebug for FunctionSig { } match self.abi { - Some(abi::Abi::C) | - None => true, + Abi::Known(abi::Abi::C) | + Abi::Unknown(..) => true, _ => false, } } |