use pwasm_utils::parity_wasm::elements::{ExportEntry, Instruction, Internal, Module, ValueType};
pub fn insert_stack_end_export(module: &mut Module) -> Result<(), &str> {
let name_section = module
.custom_sections()
.find(|x| x.name() == "name")
.ok_or("Cannot find name section")?;
let payload = unsafe { std::str::from_utf8_unchecked(name_section.payload()) };
if !payload.contains("__stack_pointer") {
return Err("has no stack pointer global");
}
let glob_section = module
.global_section()
.ok_or("Cannot find globals section")?;
let zero_global = glob_section
.entries()
.iter()
.next()
.ok_or("there is no globals")?;
if zero_global.global_type().content_type() != ValueType::I32 {
return Err("has no i32 global 0");
}
let init_code = zero_global.init_expr().code();
if init_code.len() != 2 {
return Err("num of init instructions != 2 for glob 0");
}
if init_code[1] != Instruction::End {
return Err("second init instruction is not end");
}
if let Instruction::I32Const(literal) = init_code[0] {
log::debug!("stack pointer init == {:#x}", literal);
let export_section = module
.export_section_mut()
.ok_or("Cannot find export section")?;
let x = export_section.entries_mut();
x.push(ExportEntry::new(
"__gear_stack_end".to_string(),
Internal::Global(0),
));
Ok(())
} else {
Err("has unexpected instr for init")
}
}