Skip to content

Commit 54d4026

Browse files
committed
Implement relative-depth aliases
This continues to sync this implementation with WebAssembly/module-linking#26 by implementing the ability for outer aliases to have an arbitrary depth listed on them.
1 parent 980bb45 commit 54d4026

File tree

22 files changed

+477
-291
lines changed

22 files changed

+477
-291
lines changed

crates/dump/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ impl<'a> Dump<'a> {
144144
ExternalKind::Event => i.events += 1,
145145
ExternalKind::Type => i.types += 1,
146146
},
147-
Alias::ParentType(_) => i.types += 1,
148-
Alias::ParentModule(_) => i.modules += 1,
147+
Alias::ParentType { .. } => i.types += 1,
148+
Alias::ParentModule { .. } => i.modules += 1,
149149
}
150150
me.print(end)
151151
})?,

crates/wasmparser/src/readers/alias_section.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@ pub struct AliasSectionReader<'a> {
1111

1212
#[derive(Debug)]
1313
pub enum Alias<'a> {
14-
ParentType(u32),
15-
ParentModule(u32),
14+
ParentType {
15+
relative_depth: u32,
16+
index: u32,
17+
},
18+
ParentModule {
19+
relative_depth: u32,
20+
index: u32,
21+
},
1622
InstanceExport {
1723
instance: u32,
1824
kind: ExternalKind,
@@ -42,16 +48,25 @@ impl<'a> AliasSectionReader<'a> {
4248
kind: self.reader.read_external_kind()?,
4349
export: self.reader.read_string()?,
4450
},
45-
0x01 => match self.reader.read_external_kind()? {
46-
ExternalKind::Type => Alias::ParentType(self.reader.read_var_u32()?),
47-
ExternalKind::Module => Alias::ParentModule(self.reader.read_var_u32()?),
48-
_ => {
49-
return Err(BinaryReaderError::new(
50-
"invalid external kind in alias",
51-
self.original_position() - 1,
52-
))
51+
0x01 => {
52+
let relative_depth = self.reader.read_var_u32()?;
53+
match self.reader.read_external_kind()? {
54+
ExternalKind::Type => Alias::ParentType {
55+
relative_depth,
56+
index: self.reader.read_var_u32()?,
57+
},
58+
ExternalKind::Module => Alias::ParentModule {
59+
relative_depth,
60+
index: self.reader.read_var_u32()?,
61+
},
62+
_ => {
63+
return Err(BinaryReaderError::new(
64+
"invalid external kind in alias",
65+
self.original_position() - 1,
66+
))
67+
}
5368
}
54-
},
69+
}
5570
_ => {
5671
return Err(BinaryReaderError::new(
5772
"invalid byte in alias",

crates/wasmparser/src/validator.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -923,27 +923,37 @@ impl Validator {
923923
_ => return self.create_error("alias kind mismatch with export kind"),
924924
}
925925
}
926-
Alias::ParentType(i) => {
927-
let parent = match self.parents.last() {
928-
Some(parent) => parent,
929-
None => {
930-
return self.create_error("no parent module to alias from");
931-
}
932-
};
933-
let ty = match parent.state.types.get(i as usize) {
926+
Alias::ParentType {
927+
relative_depth,
928+
index,
929+
} => {
930+
let i = self
931+
.parents
932+
.len()
933+
.checked_sub(relative_depth as usize)
934+
.and_then(|i| i.checked_sub(1))
935+
.ok_or_else(|| {
936+
BinaryReaderError::new("relative depth too large", self.offset)
937+
})?;
938+
let ty = match self.parents[i].state.types.get(index as usize) {
934939
Some(m) => *m,
935940
None => return self.create_error("alias to type not defined in parent yet"),
936941
};
937942
self.cur.state.assert_mut().types.push(ty);
938943
}
939-
Alias::ParentModule(i) => {
940-
let parent = match self.parents.last() {
941-
Some(parent) => parent,
942-
None => {
943-
return self.create_error("no parent module to alias from");
944-
}
945-
};
946-
let module = match parent.state.submodules.get(i as usize) {
944+
Alias::ParentModule {
945+
relative_depth,
946+
index,
947+
} => {
948+
let i = self
949+
.parents
950+
.len()
951+
.checked_sub(relative_depth as usize)
952+
.and_then(|i| i.checked_sub(1))
953+
.ok_or_else(|| {
954+
BinaryReaderError::new("relative depth too large", self.offset)
955+
})?;
956+
let module = match self.parents[i].state.submodules.get(index as usize) {
947957
Some(m) => *m,
948958
None => return self.create_error("alias to module not defined in parent yet"),
949959
};

crates/wasmprinter/src/lib.rs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,26 @@ impl Printer {
331331
Ok(())
332332
}
333333

334-
fn print_functype_idx(&mut self, idx: u32, names_for: Option<u32>) -> Result<u32> {
334+
fn print_functype_idx(
335+
&mut self,
336+
idx: u32,
337+
always_print_type: bool,
338+
names_for: Option<u32>,
339+
) -> Result<Option<u32>> {
340+
if always_print_type {
341+
write!(self.result, " (type {})", idx)?;
342+
}
335343
let ty = match self.state.types.get(idx as usize) {
336344
Some(Some(ty)) => ty.clone(),
337-
Some(None) => bail!("function type index `{}` is not a function", idx),
345+
Some(None) => {
346+
if !always_print_type {
347+
write!(self.result, " (type {})", idx)?;
348+
}
349+
return Ok(None);
350+
}
338351
None => bail!("function type index `{}` out of bounds", idx),
339352
};
340-
self.print_functype(&ty, names_for)
353+
self.print_functype(&ty, names_for).map(Some)
341354
}
342355

343356
/// Returns the number of parameters, useful for local index calculations
@@ -502,8 +515,7 @@ impl Printer {
502515
if index {
503516
write!(self.result, "(;{};)", self.state.event)?;
504517
}
505-
write!(self.result, " (type {})", ty.type_index)?;
506-
self.print_functype_idx(ty.type_index, None)?;
518+
self.print_functype_idx(ty.type_index, true, None)?;
507519
Ok(())
508520
}
509521

@@ -589,8 +601,9 @@ impl Printer {
589601
Some(name) => name.write(&mut self.result),
590602
None => write!(self.result, "(;{};)", self.state.func)?,
591603
}
592-
write!(self.result, " (type {})", ty)?;
593-
let params = self.print_functype_idx(ty, Some(self.state.func))?;
604+
let params = self
605+
.print_functype_idx(ty, true, Some(self.state.func))?
606+
.unwrap_or(0);
594607

595608
let mut first = true;
596609
let mut local_idx = 0;
@@ -1407,7 +1420,7 @@ impl Printer {
14071420
Ok(())
14081421
}
14091422
TypeOrFuncType::FuncType(idx) => {
1410-
self.print_functype_idx(*idx, None)?;
1423+
self.print_functype_idx(*idx, false, None)?;
14111424
Ok(())
14121425
}
14131426
}
@@ -1595,9 +1608,6 @@ impl Printer {
15951608
kind,
15961609
export,
15971610
} => {
1598-
write!(self.result, "{} ", instance)?;
1599-
self.print_str(export)?;
1600-
self.result.push_str(" ");
16011611
match kind {
16021612
ExternalKind::Function => self.start_group("func"),
16031613
ExternalKind::Table => self.start_group("table"),
@@ -1642,22 +1652,29 @@ impl Printer {
16421652
}
16431653
ExternalKind::Type => self.state.types.push(None),
16441654
}
1655+
write!(self.result, " {} ", instance)?;
1656+
self.print_str(export)?;
16451657
self.end_group();
16461658
}
1647-
Alias::ParentType(i) => {
1659+
Alias::ParentType {
1660+
relative_depth,
1661+
index,
1662+
} => {
16481663
write!(
16491664
self.result,
1650-
"parent (;{};) {} (type)",
1651-
self.state.types.len(),
1652-
i,
1665+
"(type (;{};) outer {} {})",
1666+
self.state.module, relative_depth, index
16531667
)?;
16541668
self.state.types.push(None);
16551669
}
1656-
Alias::ParentModule(i) => {
1670+
Alias::ParentModule {
1671+
relative_depth,
1672+
index,
1673+
} => {
16571674
write!(
16581675
self.result,
1659-
"parent (;{};) {} (module)",
1660-
self.state.module, i
1676+
"(module (;{};) outer {} {})",
1677+
self.state.module, relative_depth, index
16611678
)?;
16621679
self.state.module += 1;
16631680
}

crates/wast/src/ast/alias.rs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ pub enum AliasKind<'a> {
2323
export: &'a str,
2424
kind: ast::ExportKind,
2525
},
26-
Parent {
27-
parent_index: ast::Index<'a>,
26+
Outer {
27+
/// The index of the module that this reference is referring to.
28+
module: ast::Index<'a>,
29+
/// The index of the item within `module` that this alias is referering
30+
/// to.
31+
index: ast::Index<'a>,
32+
/// The kind of item that's being aliased.
2833
kind: ast::ExportKind,
2934
},
3035
}
@@ -34,39 +39,44 @@ impl Alias<'_> {
3439
pub fn item_kind(&self) -> ast::ExportKind {
3540
match self.kind {
3641
AliasKind::InstanceExport { kind, .. } => kind,
37-
AliasKind::Parent { kind, .. } => kind,
42+
AliasKind::Outer { kind, .. } => kind,
3843
}
3944
}
4045
}
4146

4247
impl<'a> Parse<'a> for Alias<'a> {
4348
fn parse(parser: Parser<'a>) -> Result<Self> {
4449
let span = parser.parse::<kw::alias>()?.0;
45-
let (id, name, kind) = if parser.parse::<Option<kw::parent>>()?.is_some() {
46-
// (alias parent $parent_idx (type $my_name))
47-
let parent_index = parser.parse()?;
48-
let (kind, id) = parser.parens(|p| Ok((p.parse()?, p.parse()?)))?;
49-
(id, None, AliasKind::Parent { parent_index, kind })
50-
} else {
51-
// (alias $instance "export" (type $my_name))
52-
let instance = parser.parse::<ast::IndexOrRef<_>>()?.0;
53-
let export = parser.parse()?;
54-
let (kind, id, name) = parser.parens(|p| Ok((p.parse()?, p.parse()?, p.parse()?)))?;
55-
(
56-
id,
57-
name,
50+
let (id, kind) = parser.parens(|p| {
51+
let kind = p.parse()?;
52+
// Don't consume $i in an alias that looks like `(alias (func $i
53+
// "foo"))`
54+
let id =
55+
if parser.peek2::<ast::IndexOrRef<kw::instance>>() || parser.peek2::<kw::outer>() {
56+
p.parse()?
57+
} else {
58+
None
59+
};
60+
let kind = if parser.parse::<Option<kw::outer>>()?.is_some() {
61+
AliasKind::Outer {
62+
module: parser.parse()?,
63+
index: parser.parse()?,
64+
kind,
65+
}
66+
} else {
5867
AliasKind::InstanceExport {
59-
instance,
60-
export,
68+
instance: parser.parse::<ast::IndexOrRef<_>>()?.0,
69+
export: parser.parse()?,
6170
kind,
62-
},
63-
)
64-
};
71+
}
72+
};
73+
Ok((id, kind))
74+
})?;
6575

6676
Ok(Alias {
6777
span,
6878
id,
69-
name,
79+
name: None, // TODO: what syntax to implement for this?
7080
kind,
7181
})
7282
}

crates/wast/src/binary.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,10 +1229,15 @@ impl Encode for Alias<'_> {
12291229
kind.encode(e);
12301230
export.encode(e);
12311231
}
1232-
AliasKind::Parent { parent_index, kind } => {
1232+
AliasKind::Outer {
1233+
module,
1234+
index,
1235+
kind,
1236+
} => {
12331237
e.push(0x01);
1238+
module.encode(e);
12341239
kind.encode(e);
1235-
parent_index.encode(e);
1240+
index.encode(e);
12361241
}
12371242
}
12381243
}

crates/wast/src/resolve/aliases.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn run(fields: &mut Vec<ModuleField>) {
2020
struct Expander<'a> {
2121
to_prepend: Vec<ModuleField<'a>>,
2222
instances: HashMap<(Index<'a>, &'a str, ExportKind), Index<'a>>,
23-
parents: HashMap<(Index<'a>, ExportKind), Index<'a>>,
23+
parents: HashMap<(Index<'a>, Index<'a>, ExportKind), Index<'a>>,
2424
}
2525

2626
impl<'a> Expander<'a> {
@@ -39,8 +39,12 @@ impl<'a> Expander<'a> {
3939
self.instances
4040
.insert((*instance.unwrap_index(), export, *kind), id.into());
4141
}
42-
AliasKind::Parent { parent_index, kind } => {
43-
self.parents.insert((*parent_index, *kind), id.into());
42+
AliasKind::Outer {
43+
module,
44+
index,
45+
kind,
46+
} => {
47+
self.parents.insert((*module, *index, *kind), id.into());
4448
}
4549
}
4650
}
@@ -83,6 +87,7 @@ impl<'a> Expander<'a> {
8387
ModuleField::Export(e) => self.expand(&mut e.index),
8488

8589
ModuleField::Func(f) => {
90+
self.expand_type_use(&mut f.ty);
8691
if let FuncKind::Inline { expression, .. } = &mut f.kind {
8792
self.expand_expr(expression);
8893
}
@@ -178,7 +183,7 @@ impl<'a> Expander<'a> {
178183
{
179184
match item {
180185
ItemRef::Outer { kind, module, idx } => {
181-
let key = (*idx, (*kind).into());
186+
let key = (*module, *idx, (*kind).into());
182187
let idx = match self.parents.entry(key) {
183188
Entry::Occupied(e) => *e.get(),
184189
Entry::Vacant(v) => {
@@ -188,8 +193,9 @@ impl<'a> Expander<'a> {
188193
span,
189194
id: Some(id),
190195
name: None,
191-
kind: AliasKind::Parent {
192-
parent_index: *idx,
196+
kind: AliasKind::Outer {
197+
module: *module,
198+
index: *idx,
193199
kind: (*kind).into(),
194200
},
195201
}));

crates/wast/src/resolve/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub fn resolve<'a>(module: &mut Module<'a>) -> Result<Names<'a>, Error> {
7676

7777
// Perform name resolution over all `Index` items to resolve them all to
7878
// indices instead of symbolic names.
79-
let resolver = names::resolve(fields)?;
79+
let resolver = names::resolve(module.id, fields)?;
8080
Ok(Names { resolver })
8181
}
8282

0 commit comments

Comments
 (0)