Skip to content

Constant variable improvements. #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 16, 2016
Merged
7 changes: 4 additions & 3 deletions libbindgen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ mod testgen {
.replace(|c| !char::is_alphanumeric(c), "_")
.replace("__", "_")
.to_lowercase();
let _ = writeln!(dst, "test_header!(header_{}, {:?});",
func, entry.path());
writeln!(dst, "test_header!(header_{}, {:?});",
func, entry.path()).unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you rustfmt this? I'd think it would put each parameter on its own line if they are too long to fit on one line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't because cargo fmt doesn't detect the build.rs file apparently. Probably worth making it recognise it as a followup.

}
_ => {}
}
}
let _ = dst.flush();

dst.flush().unwrap();
}
}

Expand Down
78 changes: 76 additions & 2 deletions libbindgen/src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ impl Cursor {

/// Given that this cursor's referent is reference type, get the cursor
/// pointing to the referenced type.
pub fn referenced(&self) -> Option<Cursor> {
pub fn referenced(&self) -> Option<Cursor> {
unsafe {
let ret = Cursor {
x: clang_getCursorReferenced(self.x),
Expand Down Expand Up @@ -475,6 +475,11 @@ impl Cursor {
pub fn is_virtual_base(&self) -> bool {
unsafe { clang_isVirtualBase(self.x) != 0 }
}

/// Try to evaluate this cursor.
pub fn evaluate(&self) -> EvalResult {
EvalResult::new(*self)
}
}

extern "C" fn visit_children<Visitor>(cur: CXCursor,
Expand Down Expand Up @@ -933,7 +938,9 @@ impl Into<String> for CXString {
}
unsafe {
let c_str = CStr::from_ptr(clang_getCString(self) as *const _);
c_str.to_string_lossy().into_owned()
let ret = c_str.to_string_lossy().into_owned();
clang_disposeString(self);
ret
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... lol ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a big deal because they're refcounted, but still...

}
}
}
Expand Down Expand Up @@ -1259,3 +1266,70 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult {
pub fn extract_clang_version() -> String {
unsafe { clang_getClangVersion().into() }
}

/// A wrapper for the result of evaluating an expression.
#[derive(Debug)]
pub struct EvalResult {
x: CXEvalResult,
}

#[cfg(feature = "llvm_stable")]
impl EvalResult {
/// Create a dummy EvalResult.
pub fn new(_: Cursor) -> Self {
EvalResult {
x: ::std::ptr::null_mut(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use std::ptr at the top?

}
}

/// Not useful in llvm 3.8.
pub fn as_double(&self) -> Option<f64> {
None
}

/// Not useful in llvm 3.8.
pub fn as_int(&self) -> Option<i32> {
None
}
}

#[cfg(not(feature = "llvm_stable"))]
impl EvalResult {
/// Evaluate `cursor` and return the result.
pub fn new(cursor: Cursor) -> Self {
EvalResult {
x: unsafe { clang_Cursor_Evaluate(cursor.x) },
}
}

fn kind(&self) -> Enum_CXEvalResultKind {
unsafe { clang_EvalResult_getKind(self.x) }
}

/// Try to get back the result as a double.
pub fn as_double(&self) -> Option<f64> {
match self.kind() {
CXEval_Float => {
Some(unsafe { clang_EvalResult_getAsDouble(self.x) } as f64)
}
_ => None,
}
}

/// Try to get back the result as an integer.
pub fn as_int(&self) -> Option<i32> {
match self.kind() {
CXEval_Int => {
Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32)
}
_ => None,
}
}
}

#[cfg(not(feature = "llvm_stable"))]
impl Drop for EvalResult {
fn drop(&mut self) {
unsafe { clang_EvalResult_dispose(self.x) };
}
}
29 changes: 28 additions & 1 deletion libbindgen/src/clangll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,22 @@
#![allow(non_upper_case_globals)]
#![cfg_attr(rustfmt, rustfmt_skip)]

use ::std::os::raw::{ c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void};
use ::std::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void};

#[cfg(not(feature = "llvm_stable"))]
use std::os::raw::c_double;


pub type CXEvalResult = *mut c_void;
pub type Enum_CXEvalResultKind = c_uint;

pub const CXEval_Int: c_uint = 1;
pub const CXEval_Float: c_uint = 2;
pub const CXEval_ObjCStrLiteral: c_uint = 3;
pub const CXEval_StrLiteral: c_uint = 4;
pub const CXEval_CFStr: c_uint = 5;
pub const CXEval_Other: c_uint = 6;
pub const CXEval_UnExposed: c_uint = 0;

pub type ptrdiff_t = c_long;
pub type size_t = c_ulong;
Expand Down Expand Up @@ -1436,4 +1451,16 @@ extern "C" {
offset: *mut c_uint);
pub fn clang_indexLoc_getCXSourceLocation(loc: CXIdxLoc) ->
CXSourceLocation;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_Cursor_Evaluate(C: CXCursor) -> CXEvalResult;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_EvalResult_getKind(E: CXEvalResult) -> Enum_CXEvalResultKind;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_EvalResult_getAsInt(E: CXEvalResult) -> c_int;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_EvalResult_getAsDouble(E: CXEvalResult) -> c_double;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_EvalResult_getAsStr(E: CXEvalResult) -> *const c_char;
#[cfg(not(feature="llvm_stable"))]
pub fn clang_EvalResult_dispose(E: CXEvalResult);
}
33 changes: 33 additions & 0 deletions libbindgen/src/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,37 @@ pub mod ast_ty {
expr.int(val)
}
}

pub fn byte_array_expr(bytes: &[u8]) -> P<ast::Expr> {
let mut vec = Vec::with_capacity(bytes.len() + 1);
for byte in bytes {
vec.push(int_expr(*byte as i64));
}
vec.push(int_expr(0));

let kind = ast::ExprKind::Vec(vec);

aster::AstBuilder::new().expr().build_expr_kind(kind)
}

pub fn cstr_expr(mut string: String) -> P<ast::Expr> {
string.push('\0');
aster::AstBuilder::new()
.expr()
.build_lit(aster::AstBuilder::new().lit().byte_str(string))
}

pub fn float_expr(f: f64) -> P<ast::Expr> {
use aster::str::ToInternedString;
let mut string = f.to_string();

// So it gets properly recognised as a floating point constant.
if !string.contains('.') {
string.push('.');
}

let interned_str = string.as_str().to_interned_string();
let kind = ast::LitKind::FloatUnsuffixed(interned_str);
aster::AstBuilder::new().expr().lit().build_lit(kind)
}
}
43 changes: 39 additions & 4 deletions libbindgen/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl CodeGenerator for Var {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
use ir::var::VarType;
debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);

let canonical_name = item.canonical_name(ctx);
Expand All @@ -320,10 +321,44 @@ impl CodeGenerator for Var {
.item()
.pub_()
.const_(canonical_name)
.expr()
.build(helpers::ast_ty::int_expr(val))
.build(ty);
result.push(const_item)
.expr();
let item = match *val {
VarType::Int(val) => {
const_item.build(helpers::ast_ty::int_expr(val))
.build(ty)
}
VarType::String(ref bytes) => {
// Account the trailing zero.
//
// TODO: Here we ignore the type we just made up, probably
// we should refactor how the variable type and ty id work.
let len = bytes.len() + 1;
let ty = quote_ty!(ctx.ext_cx(), [u8; $len]);

match String::from_utf8(bytes.clone()) {
Ok(string) => {
const_item.build(helpers::ast_ty::cstr_expr(string))
.build(quote_ty!(ctx.ext_cx(), &'static $ty))
}
Err(..) => {
const_item
.build(helpers::ast_ty::byte_array_expr(bytes))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should always make C strings a byte array...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just because the bytestring reads better, but should be effectively equivalent.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emilio

It's just because the bytestring reads better, but should be effectively equivalent

actually bindgen generates i8 byte arrays for literal strings in processor definitions. u8 arrays would IMHO be a more useful resp. *const c_char compatible representation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you file an issue with a test-case? Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you file an issue with a test-case? Thanks!

Copy link

@mash-graz mash-graz Sep 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wrote an issue ticket in the meanwhile: #1401

but i think it's more an issue, which rather needs contemplation than any example, where it leads to unpleasant results.

.build(ty)
}
}
}
VarType::Float(f) => {
const_item.build(helpers::ast_ty::float_expr(f))
.build(ty)
}
VarType::Char(c) => {
const_item
.build(aster::AstBuilder::new().expr().lit().byte(c))
.build(ty)
}
};

result.push(item);
} else {
let mut attrs = vec![];
if let Some(mangled) = self.mangled_name() {
Expand Down
5 changes: 2 additions & 3 deletions libbindgen/src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl<'ctx> BindgenContext<'ctx> {
error!("Valid declaration with no USR: {:?}, {:?}",
declaration,
location);
return;
TypeKey::Declaration(declaration)
};

let old = self.types.insert(key, id);
Expand Down Expand Up @@ -609,8 +609,7 @@ impl<'ctx> BindgenContext<'ctx> {
-> Option<ItemId> {
use clangll::{CXCursor_ClassTemplate,
CXCursor_ClassTemplatePartialSpecialization,
CXCursor_TypeAliasTemplateDecl,
CXCursor_TypeRef};
CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
debug!("builtin_or_resolved_ty: {:?}, {:?}, {:?}",
ty,
location,
Expand Down
6 changes: 1 addition & 5 deletions libbindgen/src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,11 +840,7 @@ impl ClangItemParser for Item {
ctx: &mut BindgenContext)
-> ItemId {
let id = ctx.next_item_id();
Self::from_ty_or_ref_with_id(id,
ty,
location,
parent_id,
ctx)
Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
}

/// Parse a C++ type. If we find a reference to a type that has not been
Expand Down
12 changes: 10 additions & 2 deletions libbindgen/src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ impl Type {
Self::new(Some(name), None, kind, false)
}

/// Is this an floating point type?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"an" -> "a"

pub fn is_float(&self) -> bool {
match self.kind {
TypeKind::Float(..) => true,
_ => false,
}
}

/// Is this an integer type?
pub fn is_integer(&self) -> bool {
match self.kind {
Expand Down Expand Up @@ -667,7 +675,7 @@ impl Type {
TypeKind::TemplateAlias(inner.unwrap(), args)
}
CXCursor_TemplateRef => {
let referenced = location.referenced().expect("expected value, got none");
let referenced = location.referenced().unwrap();
let referenced_ty = referenced.cur_type();
let referenced_declaration =
Some(referenced_ty.declaration());
Expand All @@ -679,7 +687,7 @@ impl Type {
ctx);
}
CXCursor_TypeRef => {
let referenced = location.referenced().expect("expected value, got none");
let referenced = location.referenced().unwrap();
let referenced_ty = referenced.cur_type();
let referenced_declaration =
Some(referenced_ty.declaration());
Expand Down
Loading