Skip to content
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

Add option to try to fit macro constants into smaller integer types #1945

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 43 additions & 11 deletions src/ir/var.rs
Expand Up @@ -117,21 +117,53 @@ impl DotAttributes for Var {
}
}

// TODO(emilio): we could make this more (or less) granular, I guess.
fn default_macro_constant_type(ctx: &BindgenContext, value: i64) -> IntKind {
if value < 0 ||
ctx.options().default_macro_constant_type ==
MacroTypeVariation::Signed
{
if value < i32::min_value() as i64 || value > i32::max_value() as i64 {
IntKind::I64
if ctx.options().fit_macro_constants {
if value < 0 ||
ctx.options().default_macro_constant_type ==
MacroTypeVariation::Signed
{
if value < i32::min_value() as i64 ||
value > i32::max_value() as i64
{
IntKind::I64
} else if value < i16::min_value() as i64 ||
value > i16::max_value() as i64
{
IntKind::I32
} else if value < i8::min_value() as i64 ||
value > i8::max_value() as i64
{
IntKind::I16
} else {
IntKind::I8
}
} else if value > u32::max_value() as i64 {
IntKind::U64
} else if value > u16::max_value() as i64 {
IntKind::U32
} else if value > u8::max_value() as i64 {
IntKind::U16
} else {
IntKind::I32
IntKind::U8
}
} else if value > u32::max_value() as i64 {
IntKind::U64
} else {
IntKind::U32
if value < 0 ||
ctx.options().default_macro_constant_type ==
MacroTypeVariation::Signed
{
if value < i32::min_value() as i64 ||
value > i32::max_value() as i64
{
IntKind::I64
} else {
IntKind::I32
}
} else if value > u32::max_value() as i64 {
IntKind::U64
} else {
IntKind::U32
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/lib.rs
Expand Up @@ -478,6 +478,10 @@ impl Builder {
output_vector.push("--no-prepend-enum-name".into());
}

if self.options.fit_macro_constants {
output_vector.push("--fit-macro-constant-types".into());
}

if self.options.array_pointers_in_arguments {
output_vector.push("--use-array-pointers-in-arguments".into());
}
Expand Down Expand Up @@ -1287,6 +1291,12 @@ impl Builder {
self
}

/// Whether to try to fit macro constants to types smaller than u32/i32
pub fn fit_macro_constants(mut self, doit: bool) -> Self {
self.options.fit_macro_constants = doit;
self
}

/// Prepend the enum name to constant or newtype variants.
pub fn prepend_enum_name(mut self, doit: bool) -> Self {
self.options.prepend_enum_name = doit;
Expand Down Expand Up @@ -1735,6 +1745,9 @@ struct BindgenOptions {
/// Whether to detect include paths using clang_sys.
detect_include_paths: bool,

/// Whether to try to fit macro constants into types smaller than u32/i32
fit_macro_constants: bool,

/// Whether to prepend the enum name to constant or newtype variants.
prepend_enum_name: bool,

Expand Down Expand Up @@ -1905,6 +1918,7 @@ impl Default for BindgenOptions {
block_extern_crate: false,
enable_mangling: true,
detect_include_paths: true,
fit_macro_constants: false,
prepend_enum_name: true,
time_phases: false,
record_matches: true,
Expand Down
7 changes: 7 additions & 0 deletions src/options.rs
Expand Up @@ -316,6 +316,9 @@ where
Arg::with_name("no-include-path-detection")
.long("no-include-path-detection")
.help("Do not try to detect default include paths"),
Arg::with_name("fit-macro-constant-types")
.long("fit-macro-constant-types")
.help("Try to fit macro constants into types smaller than u32/i32"),
Arg::with_name("unstable-rust")
.long("unstable-rust")
.help("Generate unstable Rust code (deprecated; use --rust-target instead).")
Expand Down Expand Up @@ -654,6 +657,10 @@ where
builder = builder.detect_include_paths(false);
}

if matches.is_present("fit-macro-constant-types") {
builder = builder.fit_macro_constants(true);
}

if matches.is_present("time-phases") {
builder = builder.time_phases(true);
}
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/tests/default-macro-constant-type-signed.rs
Expand Up @@ -10,6 +10,18 @@ pub const N1: i32 = 1;
pub const N2: i32 = 2;
pub const N_1: i32 = -1;
pub const N_2: i32 = -2;
pub const MAX_U16: i32 = 65535;
pub const MAX_I16: i32 = 32767;
pub const MAX_I16_Plus1: i32 = 32768;
pub const MAX_U16_Plus1: i32 = 65536;
pub const MAX_I16_Minus1: i32 = 32766;
pub const MAX_U16_Minus1: i32 = 65534;
pub const MIN_U16: i32 = 0;
pub const MIN_I16: i32 = -32768;
pub const MIN_U16_Plus1: i32 = 1;
pub const MIN_I16_Plus1: i32 = -32767;
pub const MIN_U16_Minus1: i32 = -1;
pub const MIN_I16_Minus1: i32 = -32769;
pub const MAX_U32: i64 = 4294967295;
pub const MAX_I32: i32 = 2147483647;
pub const MAX_I32_Plus1: i64 = 2147483648;
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/tests/default-macro-constant-type-unsigned.rs
Expand Up @@ -10,6 +10,18 @@ pub const N1: u32 = 1;
pub const N2: u32 = 2;
pub const N_1: i32 = -1;
pub const N_2: i32 = -2;
pub const MAX_U16: u32 = 65535;
pub const MAX_I16: u32 = 32767;
pub const MAX_I16_Plus1: u32 = 32768;
pub const MAX_U16_Plus1: u32 = 65536;
pub const MAX_I16_Minus1: u32 = 32766;
pub const MAX_U16_Minus1: u32 = 65534;
pub const MIN_U16: u32 = 0;
pub const MIN_I16: i32 = -32768;
pub const MIN_U16_Plus1: u32 = 1;
pub const MIN_I16_Plus1: i32 = -32767;
pub const MIN_U16_Minus1: i32 = -1;
pub const MIN_I16_Minus1: i32 = -32769;
pub const MAX_U32: u32 = 4294967295;
pub const MAX_I32: u32 = 2147483647;
pub const MAX_I32_Plus1: u32 = 2147483648;
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/tests/default-macro-constant-type.rs
Expand Up @@ -10,6 +10,18 @@ pub const N1: u32 = 1;
pub const N2: u32 = 2;
pub const N_1: i32 = -1;
pub const N_2: i32 = -2;
pub const MAX_U16: u32 = 65535;
pub const MAX_I16: u32 = 32767;
pub const MAX_I16_Plus1: u32 = 32768;
pub const MAX_U16_Plus1: u32 = 65536;
pub const MAX_I16_Minus1: u32 = 32766;
pub const MAX_U16_Minus1: u32 = 65534;
pub const MIN_U16: u32 = 0;
pub const MIN_I16: i32 = -32768;
pub const MIN_U16_Plus1: u32 = 1;
pub const MIN_I16_Plus1: i32 = -32767;
pub const MIN_U16_Minus1: i32 = -1;
pub const MIN_I16_Minus1: i32 = -32769;
pub const MAX_U32: u32 = 4294967295;
pub const MAX_I32: u32 = 2147483647;
pub const MAX_I32_Plus1: u32 = 2147483648;
Expand Down
54 changes: 54 additions & 0 deletions tests/expectations/tests/fit-macro-constant-types.rs
@@ -0,0 +1,54 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

pub const N0: u8 = 0;
pub const N1: u8 = 1;
pub const N2: u8 = 2;
pub const N_1: i8 = -1;
pub const N_2: i8 = -2;
pub const MAX_U16: u16 = 65535;
pub const MAX_I16: u16 = 32767;
pub const MAX_I16_Plus1: u16 = 32768;
pub const MAX_U16_Plus1: u32 = 65536;
pub const MAX_I16_Minus1: u16 = 32766;
pub const MAX_U16_Minus1: u16 = 65534;
pub const MIN_U16: u8 = 0;
pub const MIN_I16: i16 = -32768;
pub const MIN_U16_Plus1: u8 = 1;
pub const MIN_I16_Plus1: i16 = -32767;
pub const MIN_U16_Minus1: i8 = -1;
pub const MIN_I16_Minus1: i32 = -32769;
pub const MAX_U32: u32 = 4294967295;
pub const MAX_I32: u32 = 2147483647;
pub const MAX_I32_Plus1: u32 = 2147483648;
pub const MAX_U32_Plus1: u64 = 4294967296;
pub const MAX_I32_Minus1: u32 = 2147483646;
pub const MAX_U32_Minus1: u32 = 4294967294;
pub const MIN_U32: u8 = 0;
pub const MIN_I32: i32 = -2147483648;
pub const MIN_U32_Plus1: u8 = 1;
pub const MIN_I32_Plus1: i32 = -2147483647;
pub const MIN_U32_Minus1: i8 = -1;
pub const MIN_I32_Minus1: i64 = -2147483649;
pub const LONG12: u64 = 123456789012;
pub const LONG_12: i64 = -123456789012;
extern "C" {
pub fn foo(
arg1: ::std::os::raw::c_int,
arg2: ::std::os::raw::c_int,
arg3: ::std::os::raw::c_uint,
arg4: ::std::os::raw::c_char,
arg5: ::std::os::raw::c_uchar,
arg6: ::std::os::raw::c_schar,
) -> ::std::os::raw::c_int;
}
extern "C" {
pub fn bar(
arg1: ::std::os::raw::c_long,
arg2: ::std::os::raw::c_longlong,
) -> ::std::os::raw::c_long;
}
18 changes: 18 additions & 0 deletions tests/headers/default-macro-constant-type.h
Expand Up @@ -8,6 +8,24 @@
#define N_1 (-1LL)
#define N_2 (-2LL)

#define MAX_U16 0xFFFFULL
#define MAX_I16 (0x8000ULL - 1)

#define MAX_I16_Plus1 (MAX_I16 + 1)
#define MAX_U16_Plus1 (MAX_U16 + 1)

#define MAX_I16_Minus1 (MAX_I16 - 1)
#define MAX_U16_Minus1 (MAX_U16 - 1)

#define MIN_U16 0
#define MIN_I16 (- (1ULL<<15))

#define MIN_U16_Plus1 (MIN_U16 + 1)
#define MIN_I16_Plus1 (MIN_I16 + 1)

#define MIN_U16_Minus1 (MIN_U16 - 1)
#define MIN_I16_Minus1 (MIN_I16 - 1)

#define MAX_U32 0xFFFFFFFFULL
#define MAX_I32 (0x80000000ULL - 1)

Expand Down
4 changes: 4 additions & 0 deletions tests/headers/fit-macro-constant-types.h
@@ -0,0 +1,4 @@
// bindgen-flags: --fit-macro-constant-types
// Test fitting macro constants into smaller integer types
// Negative values are i8, i16, i32 or i64; others are u8, u16, u32 or u64.
#include "default-macro-constant-type.h"