Skip to content

Commit 0adc42b

Browse files
committed
Support casts in macros.
1 parent 3842b11 commit 0adc42b

File tree

2 files changed

+126
-4
lines changed

2 files changed

+126
-4
lines changed

src/ir/context.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ pub struct BindgenContext {
354354
/// This needs to be an std::HashMap because the cexpr API requires it.
355355
parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
356356

357+
wrapper_ids: StdHashMap<String, TypeId>,
358+
357359
/// A set of all the included filenames.
358360
deps: BTreeSet<String>,
359361

@@ -555,6 +557,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
555557
semantic_parents: Default::default(),
556558
currently_parsed_types: vec![],
557559
parsed_macros: Default::default(),
560+
wrapper_ids: Default::default(),
558561
replacements: Default::default(),
559562
collected_typerefs: false,
560563
in_codegen: false,
@@ -1919,7 +1922,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19191922
let layout = ty.fallible_layout(self).ok();
19201923
let location = ty.declaration().location();
19211924
let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1922-
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1925+
1926+
eprintln!("Building wrapper type {:?} ({:?})", spelling, wrapped_id);
1927+
1928+
let ty = Type::new(Some(spelling.clone()), layout, type_kind, is_const);
19231929
let item = Item::new(
19241930
with_id,
19251931
None,
@@ -1929,7 +1935,15 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19291935
Some(location),
19301936
);
19311937
self.add_builtin_item(item);
1932-
with_id.as_type_id_unchecked()
1938+
let type_id = with_id.as_type_id_unchecked();
1939+
1940+
self.wrapper_ids.insert(spelling.clone(), type_id);
1941+
1942+
type_id
1943+
}
1944+
1945+
pub fn wrapper_id_by_name(&self, name: &str) -> Option<&TypeId> {
1946+
self.wrapper_ids.get(name)
19331947
}
19341948

19351949
/// Returns the next item id to be used for an item.
@@ -1988,6 +2002,9 @@ If you encounter an error missing from this list, please file an issue or a PR!"
19882002
let is_const = ty.is_const();
19892003
let layout = ty.fallible_layout(self).ok();
19902004
let location = ty.declaration().location();
2005+
2006+
eprintln!("Building type {:?}", spelling);
2007+
19912008
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
19922009
let id = self.next_item_id();
19932010
let item = Item::new(

src/ir/var.rs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,23 @@ impl Var {
7777
}
7878

7979
/// Get this variable's type.
80-
pub fn ty(&self) -> TypeId {
81-
self.ty
80+
#[track_caller]
81+
pub fn ty(&self, ctx: &BindgenContext) -> Option<TypeId> {
82+
match self.ty {
83+
VarTypeId::Concrete(type_id) => Some(type_id),
84+
VarTypeId::Lazy(ref type_name) => {
85+
let type_id = ctx.wrapper_id_by_name(type_name).or_else(|| {
86+
ctx.wrapper_id_by_name(&format!("const {}", type_name))
87+
});
88+
89+
eprintln!(
90+
"Looking for type_name '{}': {:?}",
91+
type_name, type_id
92+
);
93+
94+
type_id.cloned()
95+
}
96+
}
8297
}
8398

8499
/// Get this variable's name.
@@ -117,6 +132,25 @@ impl DotAttributes for Var {
117132
}
118133
}
119134

135+
fn default_limit_constant_type(name: &str, value: i64) -> Option<IntKind> {
136+
Some(match name {
137+
"SCHAR_MIN" | "SCHAR_MAX" => IntKind::SChar,
138+
"CHAR_MIN" | "CHAR_MAX" => IntKind::Char {
139+
is_signed: value < 0,
140+
},
141+
"UCHAR_MIN" | "UCHAR_MAX" => IntKind::UChar,
142+
"SHRT_MIN" | "SHRT_MAX" => IntKind::Short,
143+
"USHRT_MIN" | "USHRT_MAX" => IntKind::UShort,
144+
"INT_MIN" | "INT_MAX" => IntKind::Int,
145+
"UINT_MIN" | "UINT_MAX" => IntKind::UInt,
146+
"LONG_MIN" | "LONG_MAX" => IntKind::Long,
147+
"ULONG_MIN" | "ULONG_MAX" => IntKind::ULong,
148+
"LLONG_MIN" | "LLONG_MAX" => IntKind::LongLong,
149+
"ULLONG_MIN" | "ULLONG_MAX" => IntKind::ULongLong,
150+
_ => return None,
151+
})
152+
}
153+
120154
fn default_macro_constant_type(ctx: &BindgenContext, value: i64) -> IntKind {
121155
if value < 0 ||
122156
ctx.options().default_macro_constant_type ==
@@ -258,12 +292,83 @@ impl ClangSubItemParser for Var {
258292
let kind = ctx
259293
.parse_callbacks()
260294
.and_then(|c| c.int_macro(&name, value))
295+
.or_else(|| {
296+
default_limit_constant_type(&name, value)
297+
})
261298
.unwrap_or_else(|| {
262299
default_macro_constant_type(ctx, value)
263300
});
264301

265302
(TypeKind::Int(kind), VarType::Int(value))
266303
}
304+
EvalResult::Cast(c, v) => {
305+
let ty = c
306+
.iter()
307+
.map(|v| std::str::from_utf8(v).unwrap())
308+
.collect::<Vec<&str>>();
309+
310+
if let EvalResult::Int(Wrapping(value)) = *v {
311+
let val = VarType::Int(value);
312+
313+
let kind = match &ty[..] {
314+
["bool"] => IntKind::Bool,
315+
["char"] => IntKind::Char {
316+
is_signed: value < 0,
317+
},
318+
["signed", "char"] => IntKind::SChar,
319+
["unsigned", "char"] => IntKind::UChar,
320+
["short"] => IntKind::Short,
321+
["unsigned", "short"] => IntKind::UShort,
322+
["int"] => IntKind::Int,
323+
["unsigned", "int"] => IntKind::UInt,
324+
["long"] => IntKind::Long,
325+
["unsigned", "long"] => IntKind::ULong,
326+
["long", "long"] => IntKind::LongLong,
327+
["unsigned", "long", "long"] => {
328+
IntKind::ULongLong
329+
}
330+
["int8_t"] => IntKind::I8,
331+
["uint8_t"] => IntKind::U8,
332+
["int16_t"] => IntKind::I16,
333+
["uint16_t"] => IntKind::U16,
334+
["int32_t"] => IntKind::I32,
335+
["uint32_t"] => IntKind::U32,
336+
["int64_t"] => IntKind::I64,
337+
["uint64_t"] => IntKind::U64,
338+
[custom_type] => {
339+
eprintln!(
340+
"looking for type {:?}",
341+
custom_type
342+
);
343+
344+
// FIXME: Doesn't work since types are parsed after macros.
345+
let type_id = ctx
346+
.wrapper_id_by_name(custom_type)
347+
.or_else(|| {
348+
ctx.wrapper_id_by_name(&format!(
349+
"const {}",
350+
custom_type
351+
))
352+
});
353+
354+
if let Some(type_id) = type_id {
355+
todo!(
356+
"type id for {:?} = {:?}",
357+
custom_type,
358+
type_id
359+
);
360+
}
361+
362+
return Err(ParseError::Continue);
363+
}
364+
_ => return Err(ParseError::Continue),
365+
};
366+
367+
(TypeKind::Int(kind), val)
368+
} else {
369+
return Err(ParseError::Continue);
370+
}
371+
}
267372
};
268373

269374
let ty = Item::builtin_type(type_kind, true, ctx);

0 commit comments

Comments
 (0)