Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ adler = { version = "1" }
toml = { version = "1", default-features = false, features = ["parse", "display", "serde"] }
libc = { version = "0.2" }


[profile.dev.package.wado-compiler]
opt-level = 1

Expand Down
38 changes: 31 additions & 7 deletions wado-compiler/src/cm_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,19 @@ pub fn layout_option_with_registry(
inner: &Type,
registry: &crate::component_model::WasiRegistry,
) -> CmLayout {
let payload_align = crate::component_model::cm_align_with_registry(inner, registry);
let payload_size = crate::component_model::cm_size_with_registry(inner, registry);
layout_option_with_registry_scoped(inner, registry, None)
}

/// Package-scoped registry-aware layout for option<T>.
pub fn layout_option_with_registry_scoped(
inner: &Type,
registry: &crate::component_model::WasiRegistry,
wasi_package: Option<&str>,
) -> CmLayout {
let payload_align =
crate::component_model::cm_align_with_registry_scoped(inner, registry, wasi_package);
let payload_size =
crate::component_model::cm_size_with_registry_scoped(inner, registry, wasi_package);
let overall_align = 1u32.max(payload_align);
let payload_offset = align_to(1, payload_align);
let size = align_to(payload_offset + payload_size, overall_align);
Expand All @@ -248,11 +259,24 @@ pub fn layout_result_with_registry(
err: &Type,
registry: &crate::component_model::WasiRegistry,
) -> CmLayout {
let payload_align = crate::component_model::cm_align_with_registry(ok, registry).max(
crate::component_model::cm_align_with_registry(err, registry),
);
let payload_size = crate::component_model::cm_size_with_registry(ok, registry)
.max(crate::component_model::cm_size_with_registry(err, registry));
layout_result_with_registry_scoped(ok, err, registry, None)
}

/// Package-scoped registry-aware layout for result<T, E>.
pub fn layout_result_with_registry_scoped(
ok: &Type,
err: &Type,
registry: &crate::component_model::WasiRegistry,
wasi_package: Option<&str>,
) -> CmLayout {
let payload_align =
crate::component_model::cm_align_with_registry_scoped(ok, registry, wasi_package).max(
crate::component_model::cm_align_with_registry_scoped(err, registry, wasi_package),
);
let payload_size =
crate::component_model::cm_size_with_registry_scoped(ok, registry, wasi_package).max(
crate::component_model::cm_size_with_registry_scoped(err, registry, wasi_package),
);
let overall_align = 1u32.max(payload_align);
let disc_size = 1u32;
let payload_offset = align_to(disc_size, payload_align);
Expand Down
4 changes: 2 additions & 2 deletions wado-compiler/src/codegen/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ fn generate_wasi_imports(
.iter()
.filter(|name| {
project.wasi_registry.is_variant(name)
&& !(name.as_str() == "ErrorCode" && !has_local_error_code)
&& (name.as_str() != "ErrorCode" || has_local_error_code)
})
.cloned()
.collect();
Expand All @@ -1448,7 +1448,7 @@ fn generate_wasi_imports(
.filter(|name| {
project.wasi_registry.is_enum(name)
&& !needed_variants.contains(name)
&& !(name.as_str() == "ErrorCode" && !has_local_error_code)
&& (name.as_str() != "ErrorCode" || has_local_error_code)
})
.cloned()
.collect();
Expand Down
154 changes: 151 additions & 3 deletions wado-compiler/src/component_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2286,16 +2286,37 @@ pub fn cm_align_with_registry(ty: &Type, registry: &WasiRegistry) -> u32 {
/// - payload: at `align_to(1, max_payload_align)`
/// - total: `align_to(payload_offset + max_payload_size, max_payload_align)`
pub fn wasi_variant_cm_size_align(name: &str, registry: &WasiRegistry) -> Option<(u32, u32)> {
let cases = registry.get_variant_cases(name)?;
wasi_variant_cm_size_align_scoped(name, registry, None)
}

/// Package-scoped variant of `wasi_variant_cm_size_align`.
///
/// When `wasi_package` is provided (e.g., `"http"`), uses package-scoped lookup
/// to disambiguate variant types that share the same Wado name across different
/// WASI packages (e.g., `ErrorCode` exists in http, filesystem, and sockets).
pub fn wasi_variant_cm_size_align_scoped(
name: &str,
registry: &WasiRegistry,
wasi_package: Option<&str>,
) -> Option<(u32, u32)> {
let cases = if let Some(pkg) = wasi_package {
registry
.get_variant_cases_by_package(pkg, name)
.or_else(|| registry.get_variant_cases(name))
} else {
registry.get_variant_cases(name)
}?;
if !cases.iter().any(|case| case.payload.is_some()) {
return None; // no payload cases — not outptr
}
let mut max_payload_size = 0u32;
let mut max_payload_align = 1u32;
for case in cases {
if let Some(ty) = &case.payload {
max_payload_size = max_payload_size.max(cm_size_with_registry(ty, registry));
max_payload_align = max_payload_align.max(cm_align_with_registry(ty, registry));
max_payload_size =
max_payload_size.max(cm_size_with_registry_scoped(ty, registry, wasi_package));
max_payload_align =
max_payload_align.max(cm_align_with_registry_scoped(ty, registry, wasi_package));
}
}
let disc_size = 1u32; // u8 for n ≤ 256 cases
Expand All @@ -2305,6 +2326,133 @@ pub fn wasi_variant_cm_size_align(name: &str, registry: &WasiRegistry) -> Option
Some((size, overall_align))
}

/// Package-scoped CM canonical ABI size for a type.
///
/// Like `cm_size_with_registry`, but uses `wasi_package` to disambiguate types
/// with the same name across different WASI packages.
pub fn cm_size_with_registry_scoped(
ty: &Type,
registry: &WasiRegistry,
wasi_package: Option<&str>,
) -> u32 {
match ty {
Type::Named(named) => {
if let Some(resolved) = registry.get_newtype(&named.name) {
return cm_size_with_registry_scoped(resolved, registry, wasi_package);
}
if let Some(fields) = registry.get_struct_fields(&named.name) {
let resolved_fields: Vec<Type> = fields
.iter()
.map(|(_, ty)| registry.resolve_type(ty))
.collect();
let mut offset = 0u32;
let mut max_align = 1u32;
for field_ty in &resolved_fields {
let fa = cm_align_with_registry_scoped(field_ty, registry, wasi_package);
let fs = cm_size_with_registry_scoped(field_ty, registry, wasi_package);
offset = crate::cm_abi::align_to(offset, fa);
offset += fs;
max_align = max_align.max(fa);
}
return crate::cm_abi::align_to(offset, max_align);
}
if let Some(sa) = wasi_variant_cm_size_align_scoped(&named.name, registry, wasi_package)
{
return sa.0;
}
if let Some(variants) = registry.get_enum_variants(&named.name) {
return crate::synthesis::cm_binding::cm_enum_byte_size(variants.len());
}
if let Some(members) = registry.get_flags_members(&named.name) {
return crate::synthesis::cm_binding::cm_flags_byte_size(members.len());
}
crate::cm_abi::cm_size(ty)
}
Type::Generic(g) => match g.name.as_str() {
"Option" if g.args.len() == 1 => {
let inner = &g.args[0];
let payload_align = cm_align_with_registry_scoped(inner, registry, wasi_package);
let payload_size = cm_size_with_registry_scoped(inner, registry, wasi_package);
let payload_offset = crate::cm_abi::align_to(1, payload_align);
let overall_align = 1u32.max(payload_align);
crate::cm_abi::align_to(payload_offset + payload_size, overall_align)
}
"Result" if g.args.len() == 2 => {
let ok_size = cm_size_with_registry_scoped(&g.args[0], registry, wasi_package);
let err_size = cm_size_with_registry_scoped(&g.args[1], registry, wasi_package);
let payload_size = ok_size.max(err_size);
let payload_align =
cm_align_with_registry_scoped(&g.args[0], registry, wasi_package).max(
cm_align_with_registry_scoped(&g.args[1], registry, wasi_package),
);
let payload_offset = crate::cm_abi::align_to(1, payload_align);
let overall_align = 1u32.max(payload_align);
crate::cm_abi::align_to(payload_offset + payload_size, overall_align)
}
_ => crate::cm_abi::cm_size(ty),
},
_ => crate::cm_abi::cm_size(ty),
}
}

/// Package-scoped CM canonical ABI alignment for a type.
pub fn cm_align_with_registry_scoped(
ty: &Type,
registry: &WasiRegistry,
wasi_package: Option<&str>,
) -> u32 {
match ty {
Type::Named(named) => {
if let Some(resolved) = registry.get_newtype(&named.name) {
return cm_align_with_registry_scoped(resolved, registry, wasi_package);
}
if let Some(fields) = registry.get_struct_fields(&named.name) {
let mut max_align = 1u32;
for (_, field_ty) in fields {
let resolved = registry.resolve_type(field_ty);
max_align = max_align.max(cm_align_with_registry_scoped(
&resolved,
registry,
wasi_package,
));
}
return max_align;
}
if let Some(sa) = wasi_variant_cm_size_align_scoped(&named.name, registry, wasi_package)
{
return sa.1;
}
if let Some(variants) = registry.get_enum_variants(&named.name) {
return crate::synthesis::cm_binding::cm_enum_byte_size(variants.len());
}
if let Some(members) = registry.get_flags_members(&named.name) {
return crate::synthesis::cm_binding::cm_flags_byte_align(members.len());
}
crate::cm_abi::cm_align(ty)
}
Type::Generic(g) => match g.name.as_str() {
"Option" if g.args.len() == 1 => 1u32.max(cm_align_with_registry_scoped(
&g.args[0],
registry,
wasi_package,
)),
"Result" if g.args.len() == 2 => 1u32
.max(cm_align_with_registry_scoped(
&g.args[0],
registry,
wasi_package,
))
.max(cm_align_with_registry_scoped(
&g.args[1],
registry,
wasi_package,
)),
_ => crate::cm_abi::cm_align(ty),
},
_ => crate::cm_abi::cm_align(ty),
}
}

/// Primitive type for CM tuple return handling
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CmPrimitiveType {
Expand Down
4 changes: 2 additions & 2 deletions wado-compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub async fn compile_with_options<H: CompilerHost>(
let is_todo_module = load_result.entry_ast.has_todo();

// Wrap all subsequent Bail errors with is_todo_module
let result = compile_after_load(load_result, options, &logger, filename).await;
let result = compile_after_load(load_result, options, &logger, filename);
match result {
Ok((wasm, module, wir_module)) => Ok(CompileResult {
wasm,
Expand All @@ -243,7 +243,7 @@ pub async fn compile_with_options<H: CompilerHost>(
}

/// Internal: run compilation phases after module loading.
async fn compile_after_load<H: CompilerHost>(
fn compile_after_load<H: CompilerHost>(
load_result: loader::LoadResult,
options: CompilerOptions,
logger: &Logger<'_, H>,
Expand Down
2 changes: 1 addition & 1 deletion wado-compiler/src/monomorphize/func_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1974,7 +1974,7 @@ impl Monomorphizer {
// selects the correct generic function template
// ("&^IntoIterator::into_iter" instead of "Array^IntoIterator::into_iter").
if info.is_ref_impl {
new_info.base_struct_name = info.base_struct_name.clone();
new_info.base_struct_name.clone_from(&info.base_struct_name);
}
new_info
} else {
Expand Down
Loading
Loading