summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs39
-rw-r--r--src/ir/function.rs51
2 files changed, 62 insertions, 28 deletions
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/function.rs b/src/ir/function.rs
index 30f76944..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,20 +112,20 @@ 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 and Win32 need __ for mangled symbols but rust will automatically
@@ -188,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,
@@ -302,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);
}
@@ -320,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
}
@@ -432,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,
}
}