diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/bin/bindgen.rs | 5 | ||||
-rw-r--r-- | src/clang.rs | 8 | ||||
-rw-r--r-- | src/clangll.rs | 4 | ||||
-rw-r--r-- | src/gen.rs | 80 | ||||
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/macro.rs | 7 | ||||
-rw-r--r-- | src/parser.rs | 22 | ||||
-rw-r--r-- | src/types.rs | 4 |
9 files changed, 82 insertions, 61 deletions
@@ -45,7 +45,6 @@ Options: matching any rule are bound to -builtins Output bindings for builtin definitions (for example __builtin_va_list) - -abi <abi> Indicate abi of extern functions (default C) -allow-bitfields Don't fail if we encounter a bitfield (note that bindgen does not support bitfields) -allow-unknown-types Don't fail if we encounter types we do not support, @@ -80,7 +79,6 @@ Options: link_framework multiple strings match multiple strings emit_builtins bool true - abi string "C" allow_bitfields bool false allow_unknown_types bool false clang_args string @@ -122,4 +120,4 @@ TODO * bit field [clay's bindgen]: https://github.com/jckarter/clay/blob/master/tools/bindgen.clay -[issue 89]: https://github.com/crabtw/rust-bindgen/issues/89
\ No newline at end of file +[issue 89]: https://github.com/crabtw/rust-bindgen/issues/89 diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 2189c553..4e3ffd11 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -100,10 +100,6 @@ fn parse_args(args: &[String]) -> ParseResult { options.builtins = true; ix += 1u; } - "-abi" => { - options.abi = args[ix + 1u].clone(); - ix += 2u; - } "-allow-bitfields" => { options.fail_on_bitfield = false; ix += 1u; @@ -147,7 +143,6 @@ Options: matching any rule are bound to. -builtins Output bindings for builtin definitions (for example __builtin_va_list) - -abi <abi> Indicate abi of extern functions (default C) -allow-bitfields Don't fail if we encounter a bitfield (note that bindgen does not support bitfields) -allow-unknown-types Don't fail if we encounter types we do not support, diff --git a/src/clang.rs b/src/clang.rs index 9eff324f..c3da6ec7 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1,4 +1,4 @@ -#![allow(non_uppercase_statics)] +#![allow(non_upper_case_globals)] use libc::{c_uint, c_char, c_int, c_ulong}; use std::{mem, io, ptr, string}; @@ -239,6 +239,12 @@ impl Type { Type { x: clang_getResultType(self.x) } } } + + pub fn call_conv(&self) -> Enum_CXCallingConv { + unsafe { + clang_getFunctionTypeCallingConv(self.x) + } + } } // SourceLocation diff --git a/src/clangll.rs b/src/clangll.rs index 02834274..68be6675 100644 --- a/src/clangll.rs +++ b/src/clangll.rs @@ -2,9 +2,9 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -#![allow(unused_attribute)] +#![allow(unused_attributes)] #![allow(non_snake_case)] -#![allow(non_uppercase_statics)] +#![allow(non_upper_case_globals)] pub type ptrdiff_t = ::libc::c_long; pub type size_t = ::libc::c_ulong; @@ -5,6 +5,8 @@ use std::option; use std::iter; use std::vec::Vec; use std::rc::Rc; +use std::collections::HashMap; +use std::collections::hashmap::{Occupied, Vacant}; use syntax::abi; use syntax::ast; @@ -22,7 +24,6 @@ use types::*; struct GenCtx<'r> { ext_cx: base::ExtCtxt<'r>, unnamed_ty: uint, - abi: abi::Abi, span: Span } @@ -105,17 +106,7 @@ fn enum_name(name: String) -> String { format!("Enum_{}", name) } -pub fn gen_mod(abi: &str, links: &[(String, Option<String>)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> { - let abi = match abi { - "cdecl" => abi::Cdecl, - "stdcall" => abi::Stdcall, - "fastcall" => abi::Fastcall, - "aapcs" => abi::Aapcs, - "Rust" => abi::Rust, - "rust-intrinsic" => abi::RustIntrinsic, - _ => abi::C - }; - +pub fn gen_mod(links: &[(String, Option<String>)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> { // Create a dummy ExtCtxt. We only need this for string interning and that uses TLS. let cfg = ExpansionConfig { deriving_hash_type_parameter: false, @@ -131,7 +122,6 @@ pub fn gen_mod(abi: &str, links: &[(String, Option<String>)], globs: Vec<Global> cfg, ), unnamed_ty: 0, - abi: abi, span: span }; ctx.ext_cx.bt_push(ExpnInfo { @@ -220,22 +210,43 @@ pub fn gen_mod(abi: &str, links: &[(String, Option<String>)], globs: Vec<Global> } }).collect(); - let funcs = fs.into_iter().map(|f| { - match f { - GFunc(vi) => { - let v = vi.borrow(); - match v.ty { - TFunc(ref rty, ref aty, var) => - cfunc_to_rs(&mut ctx, v.name.clone(), - &**rty, aty.as_slice(), var), - _ => unreachable!() + let funcs = { + let mut func_list = fs.into_iter().map(|f| { + match f { + GFunc(vi) => { + let v = vi.borrow(); + match v.ty { + TFunc(ref rty, ref aty, var, abi) => { + let decl = cfunc_to_rs(&mut ctx, v.name.clone(), + &**rty, aty.as_slice(), var); + (abi, decl) + } + _ => unreachable!() + } + }, + _ => unreachable!() + } + }); + + let mut map: HashMap<abi::Abi, Vec<_>> = HashMap::new(); + for (abi, func) in func_list { + match map.entry(abi) { + Occupied(mut occ) => { + occ.get_mut().push(func); } - }, - _ => unreachable!() + Vacant(vac) => { + vac.set(vec!(func)); + } + } } - }).collect(); + map + }; - defs.push(mk_extern(&mut ctx, links, vars, funcs)); + defs.push(mk_extern(&mut ctx, links, vars, abi::C)); + + for (abi, funcs) in funcs.into_iter() { + defs.push(mk_extern(&mut ctx, links, funcs, abi)); + } //let attrs = vec!(mk_attr_list(&mut ctx, "allow", ["dead_code", "non_camel_case_types", "uppercase_variables"])); @@ -243,8 +254,8 @@ pub fn gen_mod(abi: &str, links: &[(String, Option<String>)], globs: Vec<Global> } fn mk_extern(ctx: &mut GenCtx, links: &[(String, Option<String>)], - vars: Vec<P<ast::ForeignItem>>, - funcs: Vec<P<ast::ForeignItem>>) -> P<ast::Item> { + foreign_items: Vec<P<ast::ForeignItem>>, + abi: abi::Abi) -> P<ast::Item> { let attrs = if links.is_empty() { Vec::new() } else { @@ -279,10 +290,9 @@ fn mk_extern(ctx: &mut GenCtx, links: &[(String, Option<String>)], }; let mut items = Vec::new(); - items.extend(vars.into_iter()); - items.extend(funcs.into_iter()); + items.extend(foreign_items.into_iter()); let ext = ast::ItemForeignMod(ast::ForeignMod { - abi: ctx.abi, + abi: abi, view_items: Vec::new(), items: items }); @@ -823,9 +833,9 @@ fn cty_to_rs(ctx: &mut GenCtx, ty: &Type) -> ast::Ty { let ty = cty_to_rs(ctx, &**t); mk_arrty(ctx, &ty, s) }, - TFunc(ref rty, ref atys, var) => { + TFunc(ref rty, ref atys, var, abi) => { let decl = cfuncty_to_rs(ctx, &**rty, atys.as_slice(), var); - mk_fnty(ctx, &decl) + mk_fnty(ctx, &decl, abi) }, TNamed(ref ti) => { let id = rust_type_id(ctx, ti.borrow().name.clone()); @@ -904,10 +914,10 @@ fn mk_arrty(ctx: &mut GenCtx, base: &ast::Ty, n: uint) -> ast::Ty { }; } -fn mk_fnty(ctx: &mut GenCtx, decl: &ast::FnDecl) -> ast::Ty { +fn mk_fnty(ctx: &mut GenCtx, decl: &ast::FnDecl, abi: abi::Abi) -> ast::Ty { let fnty = ast::TyBareFn(P(ast::BareFnTy { fn_style: ast::NormalFn, - abi: ctx.abi, + abi: abi, lifetimes: Vec::new(), decl: P(decl.clone()) })); @@ -31,7 +31,6 @@ pub fn plugin_registrar(reg: &mut Registry) { pub struct BindgenOptions { pub match_pat: Vec<String>, - pub abi: String, pub builtins: bool, pub links: Vec<(String, Option<String>)>, pub emit_ast: bool, @@ -45,7 +44,6 @@ impl Default for BindgenOptions { fn default() -> BindgenOptions { BindgenOptions { match_pat: Vec::new(), - abi: "C".to_string(), builtins: false, links: Vec::new(), emit_ast: false, @@ -71,15 +69,14 @@ pub fn generate_bindings(options: BindgenOptions, logger: Option<&Logger>, span: } }; let globals = try!(parse_headers(&options, logger)); - Ok(gen::gen_mod(options.abi.as_slice(), options.links.as_slice(), globals, span)) + Ok(gen::gen_mod(options.links.as_slice(), globals, span)) } struct DummyLogger; -#[allow(unused_variable)] impl Logger for DummyLogger { - fn error(&self, msg: &str) { } - fn warn(&self, msg: &str) { } + fn error(&self, _msg: &str) { } + fn warn(&self, _msg: &str) { } } fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result<Vec<Global>, ()> { diff --git a/src/macro.rs b/src/macro.rs index f3817072..e3b05a28 100644 --- a/src/macro.rs +++ b/src/macro.rs @@ -71,7 +71,6 @@ impl MacroArgsVisitor for BindgenArgsVisitor { Some("link") => self.options.links.push((val.to_string(), None)), Some("link_static") => self.options.links.push((val.to_string(), Some("static".to_string()))), Some("link_framework") => self.options.links.push((val.to_string(), Some("framework".to_string()))), - Some("abi") => self.options.abi = val.to_string(), Some("match") => self.options.match_pat.push(val.to_string()), Some("clang_args") => self.options.clang_args.push(val.to_string()), _ => return false @@ -79,8 +78,7 @@ impl MacroArgsVisitor for BindgenArgsVisitor { true } - #[allow(unused_variable)] - fn visit_int(&mut self, name: Option<&str>, val: i64) -> bool { + fn visit_int(&mut self, name: Option<&str>, _val: i64) -> bool { if name.is_some() { self.seen_named = true; } false } @@ -96,8 +94,7 @@ impl MacroArgsVisitor for BindgenArgsVisitor { true } - #[allow(unused_variable)] - fn visit_ident(&mut self, name: Option<&str>, val: &str) -> bool { + fn visit_ident(&mut self, name: Option<&str>, _val: &str) -> bool { if name.is_some() { self.seen_named = true; } false } diff --git a/src/parser.rs b/src/parser.rs index 0eb9cc3d..7796604f 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,11 +1,13 @@ #![allow(unused_must_use)] -#![allow(non_uppercase_statics)] +#![allow(non_upper_case_globals)] use std::collections::{HashMap, HashSet}; use std::collections::hashmap; use std::cell::RefCell; use std::rc::Rc; +use syntax::abi; + use types as il; use types::*; use clang as cx; @@ -141,6 +143,18 @@ fn fwd_decl(ctx: &mut ClangParserCtx, cursor: &Cursor, f: |ctx: &mut ClangParser } } +fn get_abi(cc: Enum_CXCallingConv) -> abi::Abi { + match cc { + CXCallingConv_Default => abi::C, + CXCallingConv_C => abi::C, + CXCallingConv_X86StdCall => abi::Stdcall, + CXCallingConv_X86FastCall => abi::Fastcall, + CXCallingConv_AAPCS => abi::Aapcs, + CXCallingConv_X86_64Win64 => abi::Win64, + _other => panic!("unsupported calling convention: {}", _other), + } +} + fn conv_ptr_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor, layout: Layout) -> il::Type { let is_const = ty.is_const(); match ty.kind() { @@ -157,8 +171,9 @@ fn conv_ptr_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor, layout: ("".to_string(), conv_ty(ctx, arg, cursor)) }).collect(); let ret_ty = box conv_ty(ctx, &ret_ty, cursor); + let abi = get_abi(ty.call_conv()); - TFunc(ret_ty, args_lst, ty.is_variadic()) + TFunc(ret_ty, args_lst, ty.is_variadic(), abi) } else if decl.kind() != CXCursor_NoDeclFound { TPtr(box conv_decl_ty(ctx, &decl), is_const, layout) } else { @@ -374,11 +389,12 @@ fn visit_top<'r>(cur: &'r Cursor, let ty = cursor.cur_type(); let ret_ty = box conv_ty(ctx, &cursor.ret_type(), cursor); + let abi = get_abi(ty.call_conv()); let func = decl_name(ctx, cursor); let vi = func.varinfo(); let mut vi = vi.borrow_mut(); - vi.ty = TFunc(ret_ty.clone(), args_lst.clone(), ty.is_variadic()); + vi.ty = TFunc(ret_ty.clone(), args_lst.clone(), ty.is_variadic(), abi); ctx.globals.push(func); return CXChildVisit_Continue; diff --git a/src/types.rs b/src/types.rs index c1a98891..76200c49 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,6 +2,8 @@ use std::cell::RefCell; use std::fmt; use std::rc::Rc; +use syntax::abi; + #[deriving(Clone)] pub enum Global { GType(Rc<RefCell<TypeInfo>>), @@ -69,7 +71,7 @@ pub enum Type { TFloat(FKind, Layout), TPtr(Box<Type>, bool, Layout), TArray(Box<Type>, uint, Layout), - TFunc(Box<Type>, Vec<(String, Type)>, bool), + TFunc(Box<Type>, Vec<(String, Type)>, bool, abi::Abi), TNamed(Rc<RefCell<TypeInfo>>), TComp(Rc<RefCell<CompInfo>>), TEnum(Rc<RefCell<EnumInfo>>) |