llr: Don't generate unused globals

Global for which none of the properties are used can be omitted in the
generated code.
This commit is contained in:
Olivier Goffart 2024-07-03 21:10:05 +02:00
parent 6687995c36
commit 14593a55e1
4 changed files with 81 additions and 9 deletions

View file

@ -831,7 +831,7 @@ pub fn generate(
for glob in &llr.globals {
let ty = if glob.is_builtin {
format!("slint::cbindgen_private::{}", glob.name)
} else {
} else if glob.must_generate() {
generate_global(&mut file, &conditional_includes, glob, &llr);
file.definitions.extend(glob.aliases.iter().map(|name| {
Declaration::TypeAlias(TypeAlias {
@ -840,6 +840,8 @@ pub fn generate(
})
}));
ident(&glob.name)
} else {
continue;
};
globals_struct.members.push((
@ -954,12 +956,12 @@ fn generate_public_component(
}),
));
for glob in unit.globals.iter().filter(|glob| !glob.is_builtin) {
for glob in unit.globals.iter().filter(|glob| glob.must_generate()) {
component_struct.friends.push(ident(&glob.name));
}
let mut global_accessor_function_body = Vec::new();
for glob in unit.globals.iter().filter(|glob| glob.exported && !glob.is_builtin) {
for glob in unit.globals.iter().filter(|glob| glob.exported && glob.must_generate()) {
let accessor_statement = format!(
"{0}if constexpr(std::is_same_v<T, {1}>) {{ return *m_globals.global_{1}.get(); }}",
if global_accessor_function_body.is_empty() { "" } else { "else " },

View file

@ -181,8 +181,11 @@ pub fn generate(doc: &Document, compiler_config: &CompilerConfiguration) -> Toke
env!("CARGO_PKG_VERSION_PATCH"),
);
let globals =
llr.globals.iter().filter(|glob| !glob.is_builtin).map(|glob| generate_global(glob, &llr));
let globals = llr
.globals
.iter()
.filter(|glob| glob.must_generate())
.map(|glob| generate_global(glob, &llr));
let shared_globals = generate_shared_globals(&llr);
let globals_ids = llr.globals.iter().filter(|glob| glob.exported).flat_map(|glob| {
std::iter::once(ident(&glob.name)).chain(glob.aliases.iter().map(|x| ident(x)))
@ -310,12 +313,20 @@ fn generate_public_component(
}
fn generate_shared_globals(llr: &llr::CompilationUnit) -> TokenStream {
let global_names =
llr.globals.iter().map(|g| format_ident!("global_{}", ident(&g.name))).collect::<Vec<_>>();
let global_types = llr.globals.iter().map(global_inner_name).collect::<Vec<_>>();
let global_names = llr
.globals
.iter()
.filter(|g| g.is_builtin || g.must_generate())
.map(|g| format_ident!("global_{}", ident(&g.name)))
.collect::<Vec<_>>();
let global_types = llr
.globals
.iter()
.filter(|g| g.is_builtin || g.must_generate())
.map(global_inner_name)
.collect::<Vec<_>>();
quote! {
#[allow(dead_code)] // FIXME: some global are unused because of optimization, we should then remove them completely
struct SharedGlobals {
#(#global_names : ::core::pin::Pin<sp::Rc<#global_types>>,)*
window_adapter : sp::OnceCell<sp::WindowAdapterRc>,

View file

@ -73,6 +73,15 @@ pub struct GlobalComponent {
pub prop_analysis: Vec<crate::object_tree::PropertyAnalysis>,
}
impl GlobalComponent {
pub fn must_generate(&self) -> bool {
!self.is_builtin
&& (self.exported
|| !self.functions.is_empty()
|| self.properties.iter().any(|p| p.use_count.get() > 0))
}
}
/// a Reference to a property, in the context of a SubComponent
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum PropertyReference {

View file

@ -30,6 +30,11 @@ struct PrettyPrinter<'a> {
impl<'a> PrettyPrinter<'a> {
fn print_root(&mut self, root: &CompilationUnit) -> Result {
for g in &root.globals {
if !g.is_builtin {
self.print_global(root, g)?;
}
}
for c in &root.sub_components {
self.print_component(root, c, None)?
}
@ -111,6 +116,51 @@ impl<'a> PrettyPrinter<'a> {
writeln!(self.writer, "}}")
}
fn print_global(&mut self, root: &CompilationUnit, global: &super::GlobalComponent) -> Result {
let ctx = EvaluationContext::new_global(root, global, ());
if global.exported {
write!(self.writer, "export ")?;
}
let aliases = global.aliases.join(",");
let aliases = if aliases.is_empty() { String::new() } else { format!(" /*{aliases}*/") };
writeln!(self.writer, "global {} {{{aliases}", global.name)?;
self.indentation += 1;
for ((p, init), is_const) in
std::iter::zip(&global.properties, &global.init_values).zip(&global.const_properties)
{
self.indent()?;
let init = init.as_ref().map_or(String::new(), |init| {
format!(
": {}{}",
DisplayExpression(&init.expression.borrow(), &ctx,),
if init.is_constant { "/*const*/" } else { "" }
)
});
writeln!(
self.writer,
"property <{}> {}{init}; //use={}{}",
p.ty,
p.name,
p.use_count.get(),
if *is_const { " const" } else { "" }
)?;
}
for f in &global.functions {
self.indent()?;
writeln!(
self.writer,
"function {} ({}) -> {} {{ {} }}; ",
f.name,
f.args.iter().map(ToString::to_string).join(", "),
f.ret_ty,
DisplayExpression(&f.code, &ctx)
)?;
}
self.indentation -= 1;
self.indent()?;
writeln!(self.writer, "}}")
}
fn indent(&mut self) -> Result {
for _ in 0..self.indentation {
self.writer.write_str(" ")?;