summaryrefslogtreecommitdiff
path: root/libbindgen/src/ir/function.rs
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-01-22 12:58:12 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-01-23 10:22:08 +0100
commitb83da2729fc83663f979da05201920e039ae3c3f (patch)
tree27e1c8b1b7f0fef74b064740238da843d4cfc1f6 /libbindgen/src/ir/function.rs
parent7373a4258f652c23e5fe00ad14740393caa40082 (diff)
Unify under the `bindgen` name.
Diffstat (limited to 'libbindgen/src/ir/function.rs')
-rw-r--r--libbindgen/src/ir/function.rs318
1 files changed, 0 insertions, 318 deletions
diff --git a/libbindgen/src/ir/function.rs b/libbindgen/src/ir/function.rs
deleted file mode 100644
index 50c442db..00000000
--- a/libbindgen/src/ir/function.rs
+++ /dev/null
@@ -1,318 +0,0 @@
-//! Intermediate representation for C/C++ functions and methods.
-
-use clang;
-use clang_sys::CXCallingConv;
-use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
-use super::context::{BindgenContext, ItemId};
-use super::item::Item;
-use super::ty::TypeKind;
-use super::type_collector::{ItemSet, TypeCollector};
-use syntax::abi;
-
-/// A function declaration, with a signature, arguments, and argument names.
-///
-/// The argument names vector must be the same length as the ones in the
-/// signature.
-#[derive(Debug)]
-pub struct Function {
- /// The name of this function.
- name: String,
-
- /// The mangled name, that is, the symbol.
- mangled_name: Option<String>,
-
- /// The id pointing to the current function signature.
- signature: ItemId,
-
- /// The doc comment on the function, if any.
- comment: Option<String>,
-}
-
-impl Function {
- /// Construct a new function.
- pub fn new(name: String,
- mangled_name: Option<String>,
- sig: ItemId,
- comment: Option<String>)
- -> Self {
- Function {
- name: name,
- mangled_name: mangled_name,
- signature: sig,
- comment: comment,
- }
- }
-
- /// Get this function's name.
- pub fn name(&self) -> &str {
- &self.name
- }
-
- /// Get this function's name.
- pub fn mangled_name(&self) -> Option<&str> {
- self.mangled_name.as_ref().map(|n| &**n)
- }
-
- /// Get this function's signature.
- pub fn signature(&self) -> ItemId {
- self.signature
- }
-}
-
-/// A function signature.
-#[derive(Debug)]
-pub struct FunctionSig {
- /// The return type of the function.
- return_type: ItemId,
-
- /// The type of the arguments, optionally with the name of the argument when
- /// declared.
- argument_types: Vec<(Option<String>, ItemId)>,
-
- /// Whether this function is variadic.
- is_variadic: bool,
-
- /// The ABI of this function.
- abi: abi::Abi,
-}
-
-fn get_abi(cc: CXCallingConv) -> abi::Abi {
- use clang_sys::*;
- 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 => panic!("unsupported calling convention: {:?}", other),
- }
-}
-
-/// Get the mangled name for the cursor's referent.
-pub fn cursor_mangling(cursor: &clang::Cursor) -> Option<String> {
- // We early return here because libclang may crash in some case
- // if we pass in a variable inside a partial specialized template.
- // See servo/rust-bindgen#67.
- if cursor.is_in_non_fully_specialized_template() {
- return None;
- }
-
- let mut mangling = cursor.mangling();
- if mangling.is_empty() {
- return None;
- }
-
- // Try to undo backend linkage munging (prepended _, generally)
- if cfg!(target_os = "macos") {
- mangling.remove(0);
- }
-
- Some(mangling)
-}
-
-impl FunctionSig {
- /// Construct a new function signature.
- pub fn new(return_type: ItemId,
- arguments: Vec<(Option<String>, ItemId)>,
- is_variadic: bool,
- abi: abi::Abi)
- -> Self {
- FunctionSig {
- return_type: return_type,
- argument_types: arguments,
- is_variadic: is_variadic,
- abi: abi,
- }
- }
-
- /// Construct a new function signature from the given Clang type.
- pub fn from_ty(ty: &clang::Type,
- cursor: &clang::Cursor,
- ctx: &mut BindgenContext)
- -> Result<Self, ParseError> {
- use clang_sys::*;
- debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
-
- // Skip function templates
- if cursor.kind() == CXCursor_FunctionTemplate {
- return Err(ParseError::Continue);
- }
-
- // Don't parse operatorxx functions in C++
- let spelling = cursor.spelling();
- if spelling.starts_with("operator") {
- return Err(ParseError::Continue);
- }
-
- let cursor = if cursor.is_valid() {
- *cursor
- } else {
- ty.declaration()
- };
-
- let mut args: Vec<_> = match cursor.kind() {
- CXCursor_FunctionDecl |
- CXCursor_Constructor |
- CXCursor_CXXMethod => {
- // For CXCursor_FunctionDecl, cursor.args() is the reliable way
- // to get parameter names and types.
- cursor.args()
- .unwrap()
- .iter()
- .map(|arg| {
- let arg_ty = arg.cur_type();
- let name = arg.spelling();
- let name =
- if name.is_empty() { None } else { Some(name) };
- let ty = Item::from_ty(&arg_ty, Some(*arg), None, ctx)
- .expect("Argument?");
- (name, ty)
- })
- .collect()
- }
- _ => {
- // For non-CXCursor_FunctionDecl, visiting the cursor's children
- // is the only reliable way to get parameter names.
- let mut args = vec![];
- cursor.visit(|c| {
- if c.kind() == CXCursor_ParmDecl {
- let ty =
- Item::from_ty(&c.cur_type(), Some(c), None, ctx)
- .expect("ParmDecl?");
- let name = c.spelling();
- let name =
- if name.is_empty() { None } else { Some(name) };
- args.push((name, ty));
- }
- CXChildVisit_Continue
- });
- args
- }
- };
-
- let is_method = cursor.kind() == CXCursor_CXXMethod;
- let is_constructor = cursor.kind() == CXCursor_Constructor;
- if (is_constructor || is_method) &&
- cursor.lexical_parent() != cursor.semantic_parent() {
- // Only parse constructors once.
- return Err(ParseError::Continue);
- }
-
- if is_method || is_constructor {
- let is_const = is_method && cursor.method_is_const();
- let is_virtual = is_method && cursor.method_is_virtual();
- let is_static = is_method && cursor.method_is_static();
- if !is_static && !is_virtual {
- let class = Item::parse(cursor.semantic_parent(), None, ctx)
- .expect("Expected to parse the class");
- let ptr =
- Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
- args.insert(0, (Some("this".into()), ptr));
- } else if is_virtual {
- let void = Item::builtin_type(TypeKind::Void, false, ctx);
- let ptr =
- Item::builtin_type(TypeKind::Pointer(void), false, ctx);
- args.insert(0, (Some("this".into()), ptr));
- }
- }
-
- let ty_ret_type = try!(ty.ret_type().ok_or(ParseError::Continue));
- let ret = try!(Item::from_ty(&ty_ret_type, None, None, ctx));
- let abi = get_abi(ty.call_conv());
-
- Ok(Self::new(ret, args, ty.is_variadic(), abi))
- }
-
- /// Get this function signature's return type.
- pub fn return_type(&self) -> ItemId {
- self.return_type
- }
-
- /// Get this function signature's argument (name, type) pairs.
- pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
- &self.argument_types
- }
-
- /// Get this function signature's ABI.
- pub fn abi(&self) -> abi::Abi {
- self.abi
- }
-
- /// Is this function signature variadic?
- pub fn is_variadic(&self) -> bool {
- // Clang reports some functions as variadic when they *might* be
- // variadic. We do the argument check because rust doesn't codegen well
- // variadic functions without an initial argument.
- self.is_variadic && !self.argument_types.is_empty()
- }
-}
-
-impl ClangSubItemParser for Function {
- fn parse(cursor: clang::Cursor,
- context: &mut BindgenContext)
- -> Result<ParseResult<Self>, ParseError> {
- use clang_sys::*;
- match cursor.kind() {
- // FIXME(emilio): Generate destructors properly.
- CXCursor_FunctionDecl |
- CXCursor_Constructor |
- CXCursor_CXXMethod => {}
- _ => return Err(ParseError::Continue),
- };
-
- debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
-
- let visibility = cursor.visibility();
- if visibility != CXVisibility_Default {
- return Err(ParseError::Continue);
- }
-
- if cursor.access_specifier() == CX_CXXPrivate {
- return Err(ParseError::Continue);
- }
-
- if cursor.is_inlined_function() {
- return Err(ParseError::Continue);
- }
-
- let linkage = cursor.linkage();
- if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal {
- return Err(ParseError::Continue);
- }
-
- // Grab the signature using Item::from_ty.
- let sig = try!(Item::from_ty(&cursor.cur_type(),
- Some(cursor),
- None,
- context));
-
- let name = cursor.spelling();
- assert!(!name.is_empty(), "Empty function name?");
-
- let mut mangled_name = cursor_mangling(&cursor);
- if mangled_name.as_ref() == Some(&name) {
- mangled_name = None;
- }
-
- let comment = cursor.raw_comment();
-
- let function = Self::new(name, mangled_name, sig, comment);
- Ok(ParseResult::New(function, Some(cursor)))
- }
-}
-
-impl TypeCollector for FunctionSig {
- type Extra = Item;
-
- fn collect_types(&self,
- _context: &BindgenContext,
- types: &mut ItemSet,
- _item: &Item) {
- types.insert(self.return_type());
-
- for &(_, ty) in self.argument_types() {
- types.insert(ty);
- }
- }
-}