1use crate::ast::{BuiltinArg, Expr, ExprKind, Initializer};
24use crate::fields_dict::{FieldsDict, StructDef};
25use crate::global_const_dict::{GlobalConstDecl, GlobalConstDict};
26use crate::intern::{InternedStr, StringInterner};
27use crate::rust_decl::RustDeclDict;
28use crate::type_repr::TypeRepr;
29
30pub struct EmittedStaticArrays {
34 pub source: String,
35 pub emitted_names: std::collections::HashSet<String>,
36 pub emitted_types: std::collections::HashMap<String, String>,
39}
40
41pub fn emit_static_arrays(
44 global_const_dict: &GlobalConstDict,
45 fields_dict: &FieldsDict,
46 rust_decl_dict: Option<&RustDeclDict>,
47 interner: &StringInterner,
48) -> EmittedStaticArrays {
49 let mut out = String::new();
50 let mut emitted_names: std::collections::HashSet<String> = std::collections::HashSet::new();
51 let mut emitted_types: std::collections::HashMap<String, String> = std::collections::HashMap::new();
52 let bindings_consts: std::collections::HashSet<String> = rust_decl_dict
53 .map(|d| d.consts.keys().cloned().collect())
54 .unwrap_or_default();
55
56 let mut entries: Vec<(InternedStr, &GlobalConstDecl)> = global_const_dict
57 .iter()
58 .map(|(n, d)| (*n, d))
59 .collect();
60 entries.sort_by(|a, b| interner.get(a.0).cmp(interner.get(b.0)));
61
62 let mut header_emitted = false;
63 for (name, decl) in entries {
64 let name_str = interner.get(name);
65 if bindings_consts.contains(name_str) {
67 continue;
68 }
69 let struct_name = match decl.element_type.type_name() {
71 Some(n) => n,
72 None => continue,
73 };
74 let struct_def = match fields_dict.get_struct_def(struct_name) {
75 Some(d) => d,
76 None => continue, };
78 let result = emit_one_array(name_str, decl, struct_def, interner);
79 match result {
80 Ok(s) => {
81 if !header_emitted {
82 out.push_str("// === Auto-generated static const arrays ===\n");
83 out.push_str("// `static const X NAME[] = {...}` declarations from C headers,\n");
84 out.push_str("// translated to Rust `static` so that referencing inline functions/macros\n");
85 out.push_str("// can resolve them. Each entry's expression is translated using\n");
86 out.push_str("// core::mem::{size_of,offset_of,size_of_val_raw}.\n\n");
87 header_emitted = true;
88 }
89 out.push_str(&s);
90 out.push('\n');
91 emitted_names.insert(name_str.to_string());
92 let elem_str = decl.element_type.to_rust_string(interner);
93 let count = match &decl.initializer {
94 Initializer::List(items) => items.len(),
95 _ => 0,
96 };
97 emitted_types.insert(
98 name_str.to_string(),
99 format!("[{}; {}]", elem_str, count),
100 );
101 }
102 Err(reason) => {
103 if !header_emitted {
104 out.push_str("// === Auto-generated static const arrays ===\n\n");
105 header_emitted = true;
106 }
107 out.push_str(&format!(
108 "// [SKIPPED] static {} — {}\n\n", name_str, reason
109 ));
110 }
111 }
112 }
113 EmittedStaticArrays { source: out, emitted_names, emitted_types }
114}
115
116fn emit_one_array(
117 name: &str,
118 decl: &GlobalConstDecl,
119 struct_def: &StructDef,
120 interner: &StringInterner,
121) -> Result<String, String> {
122 let items = match &decl.initializer {
123 Initializer::List(items) => items,
124 _ => return Err("initializer is not a list".into()),
125 };
126 let elem_type_str = decl.element_type.to_rust_string(interner);
127 let count = items.len();
128
129 let mut entries_rust: Vec<String> = Vec::new();
131 for (idx, item) in items.iter().enumerate() {
132 match &item.init {
133 Initializer::List(inner) => {
134 let entry_str = build_struct_literal(
135 &elem_type_str, struct_def, inner, interner,
136 ).map_err(|e| format!("entry [{}]: {}", idx, e))?;
137 entries_rust.push(entry_str);
138 }
139 Initializer::Expr(_) => return Err(format!("entry [{}] is not a compound", idx)),
140 }
141 }
142
143 let mut out = String::new();
144 out.push_str(&format!(
145 "#[allow(non_upper_case_globals)]\n\
146 pub static {}: [{}; {}] = [\n",
147 name, elem_type_str, count
148 ));
149 for (i, e) in entries_rust.iter().enumerate() {
150 out.push_str(&format!(" /* [{}] */ {},\n", i, e));
151 }
152 out.push_str("];\n");
153 Ok(out)
154}
155
156fn build_struct_literal(
160 type_str: &str,
161 struct_def: &StructDef,
162 inner: &[crate::ast::InitializerItem],
163 interner: &StringInterner,
164) -> Result<String, String> {
165 let values: Vec<&Expr> = inner.iter().filter_map(|ii| match &ii.init {
167 Initializer::Expr(e) => Some(e.as_ref()),
168 _ => None,
169 }).collect();
170
171 let mut field_strs: Vec<String> = Vec::new();
172 let mut value_idx = 0usize;
173 let mut i = 0usize;
174 let mut bitfield_group_idx = 0usize;
175 while i < struct_def.members.len() {
176 let m = &struct_def.members[i];
177 if m.bitfield_width.is_some() {
178 let group_start = i;
180 let mut total_width = 0u32;
181 let mut group_widths: Vec<u32> = Vec::new();
182 while i < struct_def.members.len() && struct_def.members[i].bitfield_width.is_some() {
183 let w = struct_def.members[i].bitfield_width.unwrap();
184 group_widths.push(w);
185 total_width += w;
186 i += 1;
187 }
188 let pack_ty = if total_width <= 8 { "u8" }
189 else if total_width <= 16 { "u16" }
190 else if total_width <= 32 { "u32" }
191 else { "u64" };
192 if value_idx + group_widths.len() > values.len() {
194 return Err(format!("not enough initializer values for bitfield group at member {}",
195 interner.get(struct_def.members[group_start].name)));
196 }
197 let mut shift = 0u32;
198 let mut parts: Vec<String> = Vec::new();
199 for (gi, w) in group_widths.iter().enumerate() {
200 let val_expr = values[value_idx + gi];
201 let val_rust = translate_const_expr(val_expr, interner);
202 let mask = (1u64 << w) - 1;
203 let part = format!("(({}) as {} & {:#x}) << {}",
204 val_rust, pack_ty, mask, shift);
205 parts.push(crate::syn_codegen::normalize_parens(&part));
206 shift += w;
207 }
208 field_strs.push(format!("_bitfield_{}: {}",
209 bitfield_group_idx,
210 parts.join(" | ")));
211 bitfield_group_idx += 1;
212 value_idx += group_widths.len();
213 } else {
214 if value_idx >= values.len() {
216 return Err(format!("not enough initializer values for member {}",
217 interner.get(m.name)));
218 }
219 let val_expr = values[value_idx];
220 let mut val_rust = translate_const_expr(val_expr, interner);
221 let target_ty = m.type_repr.to_rust_string(interner);
222 if is_integer_target(&target_ty) {
223 val_rust = format!("({}) as {}", val_rust, target_ty);
224 }
225 let val_rust = crate::syn_codegen::normalize_parens(&val_rust);
226 field_strs.push(format!("{}: {}", interner.get(m.name), val_rust));
227 value_idx += 1;
228 i += 1;
229 }
230 }
231
232 if value_idx < values.len() {
233 return Err(format!("excess initializer values: {} > {}", values.len(), value_idx));
234 }
235
236 Ok(format!("{} {{ {} }}", type_str, field_strs.join(", ")))
237}
238
239fn is_integer_target(ty: &str) -> bool {
240 matches!(ty,
241 "u8" | "u16" | "u32" | "u64" | "u128" | "usize" |
242 "i8" | "i16" | "i32" | "i64" | "i128" | "isize" |
243 "U8" | "U16" | "U32" | "U64" | "I8" | "I16" | "I32" | "I64" |
244 "IV" | "UV" | "STRLEN" | "Size_t" | "SSize_t" | "ssize_t" | "size_t")
245}
246
247fn translate_const_expr(expr: &Expr, interner: &StringInterner) -> String {
251 match &expr.kind {
252 ExprKind::IntLit(n) => format!("{}", n),
253 ExprKind::UIntLit(n) => format!("{}", n),
254 ExprKind::Ident(name) => {
255 interner.get(*name).to_string()
257 }
258 ExprKind::SizeofType(tn) => {
259 let t = type_name_to_rust(tn, interner);
260 format!("core::mem::size_of::<{}>()", t)
261 }
262 ExprKind::Sizeof(inner) => {
263 if let Some((type_name, field_path)) = match_sizeof_field_pattern(inner, interner) {
269 format!(
273 "{{ let _z = unsafe {{ core::mem::zeroed::<{}>() }}; \
274 core::mem::size_of_val(unsafe {{ &_z.{} }}) }}",
275 type_name, field_path
276 )
277 } else {
278 let inner_rust = translate_const_expr(inner, interner);
279 format!(
281 "core::mem::size_of_val(&{{ {} }})",
282 inner_rust
283 )
284 }
285 }
286 ExprKind::BuiltinCall { name, args } => {
287 let func_name = interner.get(*name);
288 if matches!(func_name, "offsetof" | "__builtin_offsetof" | "STRUCT_OFFSET")
289 && args.len() == 2
290 {
291 let type_str = match &args[0] {
292 BuiltinArg::TypeName(tn) => type_name_to_rust(tn, interner),
293 BuiltinArg::Expr(e) => translate_const_expr(e, interner),
294 };
295 let field_path = match &args[1] {
296 BuiltinArg::Expr(e) => expr_to_field_path(e, interner)
297 .unwrap_or_else(|| translate_const_expr(e, interner)),
298 _ => String::from("__UNRESOLVED_FIELD_PATH__"),
299 };
300 format!("core::mem::offset_of!({}, {})", type_str, field_path)
301 } else {
302 format!("__UNSUPPORTED_BUILTIN_{}__()", func_name)
303 }
304 }
305 ExprKind::Cast { type_name, expr: inner } => {
306 let t = type_name_to_rust(type_name, interner);
307 let inner_rust = translate_const_expr(inner, interner);
308 if t.contains('*') {
310 format!("(({}) as {})", inner_rust, t)
311 } else {
312 format!("(({}) as {})", inner_rust, t)
313 }
314 }
315 ExprKind::Binary { op, lhs, rhs } => {
316 let l = translate_const_expr(lhs, interner);
317 let r = translate_const_expr(rhs, interner);
318 let op_str = bin_op_to_rust(op);
319 format!("({} {} {})", l, op_str, r)
320 }
321 ExprKind::UnaryPlus(inner) => translate_const_expr(inner, interner),
322 ExprKind::UnaryMinus(inner) => format!("-({})", translate_const_expr(inner, interner)),
323 ExprKind::Conditional { cond, then_expr, else_expr } => {
324 let c = translate_const_expr(cond, interner);
328 let t = translate_const_expr(then_expr, interner);
329 let e = translate_const_expr(else_expr, interner);
330 if is_bool_expr(cond) {
331 format!("(if ({}) {{ {} }} else {{ {} }})", c, t, e)
332 } else {
333 format!("(if ({}) != 0 {{ {} }} else {{ {} }})", c, t, e)
334 }
335 }
336 ExprKind::Member { expr: base, member } => {
337 let b = translate_const_expr(base, interner);
338 format!("({}.{})", b, interner.get(*member))
339 }
340 ExprKind::PtrMember { expr: base, member } => {
341 let b = translate_const_expr(base, interner);
343 format!("((*{}).{})", b, interner.get(*member))
344 }
345 ExprKind::Deref(inner) => {
346 let i = translate_const_expr(inner, interner);
347 format!("(*({}))", i)
348 }
349 _ => format!("/* UNSUPPORTED EXPR: {:?} */ 0",
351 std::mem::discriminant(&expr.kind)),
352 }
353}
354
355fn is_bool_expr(expr: &Expr) -> bool {
358 use crate::ast::BinOp::*;
359 match &expr.kind {
360 ExprKind::Binary { op, .. } => matches!(op,
361 Lt | Gt | Le | Ge | Eq | Ne | LogAnd | LogOr),
362 ExprKind::LogNot(_) => true,
363 _ => false,
364 }
365}
366
367fn bin_op_to_rust(op: &crate::ast::BinOp) -> &'static str {
368 use crate::ast::BinOp::*;
369 match op {
370 Add => "+", Sub => "-", Mul => "*", Div => "/", Mod => "%",
371 Lt => "<", Gt => ">", Le => "<=", Ge => ">=",
372 Eq => "==", Ne => "!=",
373 BitAnd => "&", BitOr => "|", BitXor => "^",
374 Shl => "<<", Shr => ">>",
375 LogAnd => "&&", LogOr => "||",
376 }
377}
378
379fn type_name_to_rust(tn: &crate::ast::TypeName, interner: &StringInterner) -> String {
380 let repr = TypeRepr::from_type_name(tn, interner);
381 repr.to_rust_string(interner)
382}
383
384fn match_sizeof_field_pattern(
388 expr: &Expr,
389 interner: &StringInterner,
390) -> Option<(String, String)> {
391 let mut path: Vec<String> = Vec::new();
394 let mut cur = expr;
395 loop {
396 match &cur.kind {
397 ExprKind::Member { expr: base, member }
398 | ExprKind::PtrMember { expr: base, member } => {
399 path.push(interner.get(*member).to_string());
400 cur = base;
401 }
402 ExprKind::Cast { type_name, expr: _ } => {
403 let has_ptr = type_name
405 .declarator
406 .as_ref()
407 .map(|d| d.derived.iter().any(|x| matches!(x, crate::ast::DerivedDecl::Pointer(_))))
408 .unwrap_or(false);
409 if has_ptr {
410 let mut tn_no_ptr = (**type_name).clone();
411 if let Some(d) = tn_no_ptr.declarator.as_mut() {
412 d.derived.retain(|x| !matches!(x, crate::ast::DerivedDecl::Pointer(_)));
413 }
414 let type_str = type_name_to_rust(&tn_no_ptr, interner);
415 if path.is_empty() { return None; }
416 path.reverse();
417 return Some((type_str, path.join(".")));
418 }
419 return None;
420 }
421 _ => return None,
422 }
423 }
424}
425
426fn expr_to_field_path(expr: &Expr, interner: &StringInterner) -> Option<String> {
428 match &expr.kind {
429 ExprKind::Ident(name) => Some(interner.get(*name).to_string()),
430 ExprKind::Member { expr: base, member } => {
431 let b = expr_to_field_path(base, interner)?;
432 Some(format!("{}.{}", b, interner.get(*member)))
433 }
434 ExprKind::PtrMember { expr: base, member } => {
435 let b = expr_to_field_path(base, interner)?;
438 Some(format!("{}.{}", b, interner.get(*member)))
439 }
440 _ => None,
441 }
442}