mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-13 13:01:22 +00:00
Create the wasm-bindgen-wasm-conventions
crate
This tiny crate provides utilities for working with Wasm codegen conventions (typically established by LLVM or lld) such as getting the shadow stack pointer. It also de-duplicates all the places in the codebase where we were implementing these conventions in one-off ways.
This commit is contained in:
@ -8,6 +8,7 @@ use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
use walrus::Module;
|
||||
use wasm_bindgen_wasm_conventions as wasm_conventions;
|
||||
|
||||
mod anyref;
|
||||
mod decode;
|
||||
@ -278,18 +279,13 @@ impl Bindgen {
|
||||
}
|
||||
};
|
||||
|
||||
// Our multi-value xform relies on the presence of the stack pointer, so
|
||||
// temporarily export it so that our many GC's don't remove it before
|
||||
// the xform runs.
|
||||
if self.multi_value {
|
||||
// Assume that the first global is the shadow stack pointer, since that is
|
||||
// what LLVM codegens.
|
||||
match module.globals.iter().next() {
|
||||
Some(g) if g.ty == walrus::ValType::I32 => {
|
||||
module.exports.add("__shadow_stack_pointer", g.id());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Our threads and multi-value xforms rely on the presence of the stack
|
||||
// pointer, so temporarily export it so that our many GC's don't remove
|
||||
// it before the xform runs.
|
||||
let mut exported_shadow_stack_pointer = false;
|
||||
if self.multi_value || self.threads.is_enabled() {
|
||||
wasm_conventions::export_shadow_stack_pointer(&mut module)?;
|
||||
exported_shadow_stack_pointer = true;
|
||||
}
|
||||
|
||||
// This isn't the hardest thing in the world too support but we
|
||||
@ -387,6 +383,17 @@ impl Bindgen {
|
||||
}
|
||||
}
|
||||
|
||||
// If we exported the shadow stack pointer earlier, remove it from the
|
||||
// export set now.
|
||||
if exported_shadow_stack_pointer {
|
||||
wasm_conventions::unexport_shadow_stack_pointer(&mut module)?;
|
||||
// The shadow stack pointer is potentially unused now, but since it
|
||||
// most likely _is_ in use, we don't pay the cost of a full GC here
|
||||
// just to remove one potentially unnecessary global.
|
||||
//
|
||||
// walrus::passes::gc::run(&mut module);
|
||||
}
|
||||
|
||||
Ok(Output {
|
||||
module,
|
||||
stem: stem.to_string(),
|
||||
|
@ -53,9 +53,10 @@ use crate::descriptor::VectorKind;
|
||||
use crate::webidl::{AuxExportKind, AuxImport, AuxValue, JsImport, JsImportName};
|
||||
use crate::webidl::{NonstandardIncoming, NonstandardOutgoing};
|
||||
use crate::webidl::{NonstandardWebidlSection, WasmBindgenAux};
|
||||
use failure::{bail, format_err, Error, ResultExt};
|
||||
use walrus::{GlobalId, MemoryId, Module};
|
||||
use failure::{bail, Error, ResultExt};
|
||||
use walrus::Module;
|
||||
use wasm_bindgen_multi_value_xform as multi_value_xform;
|
||||
use wasm_bindgen_wasm_conventions as wasm_conventions;
|
||||
use wasm_webidl_bindings::ast;
|
||||
|
||||
pub fn add_multi_value(
|
||||
@ -79,8 +80,8 @@ pub fn add_multi_value(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let memory = get_memory(module)?;
|
||||
let shadow_stack_pointer = get_shadow_stack_pointer(module)?;
|
||||
let shadow_stack_pointer = wasm_conventions::get_shadow_stack_pointer(module)?;
|
||||
let memory = wasm_conventions::get_memory(module)?;
|
||||
multi_value_xform::run(module, memory, shadow_stack_pointer, &to_xform)?;
|
||||
|
||||
// Finally, unset `return_via_outptr`, fix up its incoming bindings'
|
||||
@ -163,43 +164,6 @@ fn fixup_binding_argument_gets(incoming: &mut [NonstandardIncoming]) -> Result<(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_memory(module: &Module) -> Result<MemoryId, Error> {
|
||||
let mut memories = module.memories.iter().map(|m| m.id());
|
||||
let memory = memories.next();
|
||||
if memories.next().is_some() {
|
||||
bail!(
|
||||
"expected a single memory, found multiple; multiple memories \
|
||||
currently not supported"
|
||||
);
|
||||
}
|
||||
memory.ok_or_else(|| {
|
||||
format_err!(
|
||||
"module does not have a memory; must have a memory \
|
||||
to transform return pointers into Wasm multi-value"
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// Get the `__shadow_stack_pointer` global that we stashed in an export early on
|
||||
// in the pipeline.
|
||||
fn get_shadow_stack_pointer(module: &mut Module) -> Result<GlobalId, Error> {
|
||||
let (g, e) = module
|
||||
.exports
|
||||
.iter()
|
||||
.find(|e| e.name == "__shadow_stack_pointer")
|
||||
.map(|e| {
|
||||
let g = match e.item {
|
||||
walrus::ExportItem::Global(g) => g,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
(g, e.id())
|
||||
})
|
||||
.ok_or_else(|| format_err!("module does not have a shadow stack pointer"))?;
|
||||
|
||||
module.exports.delete(e);
|
||||
Ok(g)
|
||||
}
|
||||
|
||||
pub fn add_section(
|
||||
module: &mut Module,
|
||||
aux: &WasmBindgenAux,
|
||||
|
Reference in New Issue
Block a user