summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-06-02 01:59:28 -0700
committerGitHub <noreply@github.com>2017-06-02 01:59:28 -0700
commit3092d6130c7f4b462d36377eefffb399c594a6b2 (patch)
tree221b43f83d6ed00fa44ea4a62f04126ae7f20bba
parentdaf1935534de9cd09a8d3f4384af20eaa4fe0f01 (diff)
parent330d16a746aa6673da94d200cdb5decbab005bfa (diff)
Auto merge of #729 - emilio:mangling-hack, r=fitzgen
ir: Use the mangling hack in win32 too.
-rw-r--r--build.rs6
-rw-r--r--src/codegen/mod.rs39
-rw-r--r--src/ir/context.rs35
-rw-r--r--src/ir/function.rs70
4 files changed, 114 insertions, 36 deletions
diff --git a/build.rs b/build.rs
index bda91e28..06cb9e96 100644
--- a/build.rs
+++ b/build.rs
@@ -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,
}
}