wasm: Keep exported global variables from the preloaded object file

This commit is contained in:
Brian Carroll 2022-02-14 08:45:18 +00:00
parent b46690ecf2
commit 4c7be277c2
2 changed files with 45 additions and 9 deletions

View file

@ -11,8 +11,6 @@ pub use linking::SymInfo;
use roc_error_macros::internal_error;
pub use sections::{ConstExpr, Export, ExportType, Global, GlobalType, Signature};
use crate::wasm_module::serialize::SkipBytes;
use self::linking::{LinkingSection, RelocationSection};
use self::sections::{
CodeSection, DataSection, ElementSection, ExportSection, FunctionSection, GlobalSection,
@ -146,8 +144,7 @@ impl<'a> WasmModule<'a> {
let global = GlobalSection::preload(arena, bytes, &mut cursor);
ExportSection::skip_bytes(bytes, &mut cursor);
let export = ExportSection::empty(arena);
let export = ExportSection::preload_globals(arena, bytes, &mut cursor);
let start = OpaqueSection::preload(SectionId::Start, arena, bytes, &mut cursor);

View file

@ -646,6 +646,18 @@ pub enum ExportType {
Global = 3,
}
impl From<u8> for ExportType {
fn from(x: u8) -> Self {
match x {
0 => Self::Func,
1 => Self::Table,
2 => Self::Mem,
3 => Self::Global,
_ => internal_error!("invalid ExportType {:2x?}", x),
}
}
}
#[derive(Debug)]
pub struct Export<'a> {
pub name: &'a [u8],
@ -653,6 +665,19 @@ pub struct Export<'a> {
pub index: u32,
}
impl<'a> Export<'a> {
fn parse_type(bytes: &[u8], cursor: &mut usize) -> ExportType {
String::skip_bytes(bytes, cursor); // name
let ty = ExportType::from(bytes[*cursor]);
*cursor += 1;
u32::skip_bytes(bytes, cursor); // index
ty
}
}
impl Serialize for Export<'_> {
fn serialize<T: SerialBuffer>(&self, buffer: &mut T) {
self.name.serialize(buffer);
@ -683,18 +708,32 @@ impl<'a> ExportSection<'a> {
section_size(&self.bytes)
}
pub fn empty(arena: &'a Bump) -> Self {
fn empty(arena: &'a Bump) -> Self {
ExportSection {
count: 0,
bytes: Vec::with_capacity_in(256, arena),
function_indices: Vec::with_capacity_in(4, arena),
}
}
}
impl SkipBytes for ExportSection<'_> {
fn skip_bytes(bytes: &[u8], cursor: &mut usize) {
parse_section(Self::ID, bytes, cursor);
/// Preload from object file. Keep only the Global exports, ignore the rest.
pub fn preload_globals(arena: &'a Bump, module_bytes: &[u8], cursor: &mut usize) -> Self {
let (num_exports, body_bytes) = parse_section(Self::ID, module_bytes, cursor);
let mut export_section = ExportSection::empty(arena);
let mut body_cursor = 0;
for _ in 0..num_exports {
let export_start = body_cursor;
let export_type = Export::parse_type(body_bytes, &mut body_cursor);
if matches!(export_type, ExportType::Global) {
let global_bytes = &body_bytes[export_start..body_cursor];
export_section.bytes.extend_from_slice(global_bytes);
export_section.count += 1;
}
}
export_section
}
}