// Licensing scope: see ../../LICENSE and this directory's LICENSE and NOTICE.
// Potentially incorporated Binaryen expression retains Apache-2.0 terms.
// Original Starshine contributions use the scoped MIT grant in ../../LICENSE.
// Modified for Starshine through 2026: implementation and validation use
// Starshine's representations and APIs; this is not an unchanged upstream file.
// Conservative notice retention does not establish copying or independence.
///|
pub fn propagate_globals_globally_summary() -> String {
"Propagate known literal globals through later global initializers and active segment offsets."
}
///|
fn pgg_imported_global_count(mod_ : @lib.Module) -> Int32 {
let mut count = 0
match mod_.import_sec {
Some(@lib.ImportSec(imports)) =>
for import_ in imports {
match import_ {
@lib.Import(_, _, @lib.GlobalExternType(_)) => count += 1
_ => ()
}
}
None => ()
}
count
}
///|
fn pgg_rewrite_globals(
global_sec : @lib.GlobalSec?,
imported_globals : Int32,
) -> (@lib.GlobalSec?, Array[@lib.Instruction?], Bool) {
let defined_globals = match global_sec {
Some(@lib.GlobalSec(globals)) => globals.length()
None => 0
}
let total_globals = imported_globals + defined_globals
let known = sgo_empty_const_array(total_globals)
let aliases = sgo_empty_global_idx_array(total_globals)
let inlines = sgo_empty_expr_array(total_globals)
match global_sec {
Some(@lib.GlobalSec(globals)) => {
let rewritten_globals : Array[@lib.Global] = []
let mut changed = false
for defined_idx = 0
defined_idx < globals.length()
defined_idx = defined_idx + 1 {
let @lib.Global(global_type, init) = globals[defined_idx]
let (rewritten_init, init_changed) = sgo_rewrite_global_init_expr(
init, known, aliases, inlines,
)
changed = changed || init_changed
known[imported_globals + defined_idx] = sgo_expr_single_const(
rewritten_init,
)
rewritten_globals.push(@lib.Global::new(global_type, rewritten_init))
}
(Some(@lib.GlobalSec::new(rewritten_globals)), known, changed)
}
None => (None, known, false)
}
}
///|
pub fn propagate_globals_globally_run_module_pass(
mod_ : @lib.Module,
) -> @lib.Module {
if pass_module_has_offset_sensitive_metadata(mod_) {
return mod_
}
let imported_globals = pgg_imported_global_count(mod_)
let (global_sec, known, global_changed) = pgg_rewrite_globals(
mod_.global_sec,
imported_globals,
)
let remove_sets = Array::make(known.length(), false)
let aliases = sgo_empty_global_idx_array(known.length())
let (elem_sec, elem_changed) = sgo_rewrite_elem_sec(
mod_.elem_sec,
known,
aliases,
remove_sets,
)
let (data_sec, data_changed) = sgo_rewrite_data_sec(
mod_.data_sec,
known,
aliases,
remove_sets,
)
if !global_changed && !elem_changed && !data_changed {
return mod_
}
sgo_build_module(
mod_,
global_sec,
mod_.table_sec,
elem_sec,
data_sec,
mod_.code_sec,
)
}