diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/clang.rs | 32 | ||||
-rw-r--r-- | src/ir/context.rs | 35 |
3 files changed, 63 insertions, 6 deletions
@@ -47,7 +47,7 @@ cexpr = "0.2" cfg-if = "0.1.0" # This kinda sucks: https://github.com/rust-lang/cargo/issues/1982 clap = "2" -clang-sys = { version = "0.22.0", features = ["runtime", "clang_3_9"] } +clang-sys = { version = "0.22.0", features = ["runtime", "clang_6_0"] } lazy_static = "1" peeking_take_while = "0.1.2" quote = "0.3.15" diff --git a/src/clang.rs b/src/clang.rs index cb873994..04d5c9d3 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1812,3 +1812,35 @@ impl Drop for EvalResult { unsafe { clang_EvalResult_dispose(self.x) }; } } + +/// Target information obtained from libclang. +#[derive(Debug)] +pub struct TargetInfo { + /// The target triple. + pub triple: String, + /// The width of the pointer _in bits_. + pub pointer_width: usize, +} + +impl TargetInfo { + /// Tries to obtain target information from libclang. + pub fn new(tu: &TranslationUnit) -> Option<Self> { + if !clang_getTranslationUnitTargetInfo::is_loaded() { + return None; + } + let triple; + let pointer_width; + unsafe { + let ti = clang_getTranslationUnitTargetInfo(tu.x); + triple = cxstring_into_string(clang_TargetInfo_getTriple(ti)); + pointer_width = clang_TargetInfo_getPointerWidth(ti); + clang_TargetInfo_dispose(ti); + } + assert!(pointer_width > 0); + assert_eq!(pointer_width % 8, 0); + Some(TargetInfo { + triple, + pointer_width: pointer_width as usize, + }) + } +} diff --git a/src/ir/context.rs b/src/ir/context.rs index b453378d..07863809 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -366,6 +366,9 @@ pub struct BindgenContext { /// The translation unit for parsing. translation_unit: clang::TranslationUnit, + /// Target information that can be useful for some stuff. + target_info: Option<clang::TargetInfo>, + /// The options given by the user via cli or other medium. options: BindgenOptions, @@ -503,6 +506,9 @@ impl<'ctx> WhitelistedItemsTraversal<'ctx> { } } +const HOST_TARGET: &'static str = + include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); + /// Returns the effective target, and whether it was explicitly specified on the /// clang flags. fn find_effective_target(clang_args: &[String]) -> (String, bool) { @@ -521,8 +527,6 @@ fn find_effective_target(clang_args: &[String]) -> (String, bool) { return (t, false) } - const HOST_TARGET: &'static str = - include_str!(concat!(env!("OUT_DIR"), "/host-target.txt")); (HOST_TARGET.to_owned(), false) } @@ -561,6 +565,17 @@ impl BindgenContext { ).expect("TranslationUnit::parse failed") }; + let target_info = clang::TargetInfo::new(&translation_unit); + + #[cfg(debug_assertions)] + { + if let Some(ref ti) = target_info { + if effective_target == HOST_TARGET { + assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>()); + } + } + } + let root_module = Self::build_root_module(ItemId(0)); let root_module_id = root_module.id().as_module_id_unchecked(); @@ -578,9 +593,10 @@ impl BindgenContext { replacements: Default::default(), collected_typerefs: false, in_codegen: false, - index: index, - translation_unit: translation_unit, - options: options, + index, + translation_unit, + target_info, + options, generated_bindegen_complex: Cell::new(false), whitelisted: None, codegen_items: None, @@ -611,6 +627,15 @@ impl BindgenContext { Timer::new(name).with_output(self.options.time_phases) } + /// Returns the pointer width to use for the target for the current + /// translation. + pub fn target_pointer_size(&self) -> usize { + if let Some(ref ti) = self.target_info { + return ti.pointer_width / 8; + } + mem::size_of::<*mut ()>() + } + /// Get the stack of partially parsed types that we are in the middle of /// parsing. pub fn currently_parsed_types(&self) -> &[PartialType] { |