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
170 changes: 92 additions & 78 deletions crates/wast/src/core/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,11 @@ fn find_names<'a>(
Data,
}

enum ExtraNames<'a, 'b> {
Func(&'a Func<'b>),
Type(&'a Type<'b>),
}

let mut ret = Names::default();
ret.module = get_name(module_id, module_name);
let mut names = Vec::new();
Expand All @@ -1058,7 +1063,7 @@ fn find_names<'a>(
ItemKind::Global(_) => Name::Global,
ItemKind::Tag(_) => Name::Tag,
};
names.push((name, &sig.id, &sig.name, field));
names.push((name, &sig.id, &sig.name, None));
}
continue;
}
Expand All @@ -1069,7 +1074,7 @@ fn find_names<'a>(
ModuleField::Type(t) => (Name::Type, &t.id, &t.name),
ModuleField::Rec(r) => {
for ty in &r.types {
names.push((Name::Type, &ty.id, &ty.name, field));
names.push((Name::Type, &ty.id, &ty.name, Some(ExtraNames::Type(ty))));
}
continue;
}
Expand All @@ -1078,10 +1083,15 @@ fn find_names<'a>(
ModuleField::Func(f) => (Name::Func, &f.id, &f.name),
ModuleField::Export(_) | ModuleField::Start(_) | ModuleField::Custom(_) => continue,
};
names.push((kind, id, name, field));
let extra = match field {
ModuleField::Func(f) => Some(ExtraNames::Func(f)),
ModuleField::Type(t) => Some(ExtraNames::Type(t)),
_ => None,
};
names.push((kind, id, name, extra));
}

for (kind, id, name, field) in names {
for (kind, id, name, extra) in names {
// .. and using the kind we can figure out where to place this name
let (list, idx) = match kind {
Name::Func => (&mut ret.funcs, &mut ret.func_idx),
Expand All @@ -1098,96 +1108,100 @@ fn find_names<'a>(
}

// Handle module locals separately from above
if let ModuleField::Func(f) = field {
let mut local_names = Vec::new();
let mut label_names = Vec::new();
let mut local_idx = 0;
let mut label_idx = 0;
let mut discard_locals = false;

if let Some(ty) = &f.ty.inline {
// Consult the inline type listed for local names of parameters.
// This is specifically preserved during the name resolution
// pass, but only for functions, so here we can look at the
// original source's names.
for (id, name, _) in ty.params.iter() {
if let Some(name) = get_name(id, name) {
local_names.push((local_idx, name));
match extra {
Some(ExtraNames::Func(f)) => {
let mut local_names = Vec::new();
let mut label_names = Vec::new();
let mut local_idx = 0;
let mut label_idx = 0;
let mut discard_locals = false;

if let Some(ty) = &f.ty.inline {
// Consult the inline type listed for local names of parameters.
// This is specifically preserved during the name resolution
// pass, but only for functions, so here we can look at the
// original source's names.
for (id, name, _) in ty.params.iter() {
if let Some(name) = get_name(id, name) {
local_names.push((local_idx, name));
}
local_idx += 1;
}
local_idx += 1;
}
} else {
// If the inline type isn't listed then it's either not present
// (e.g. no params or results) or it was referenced by index.
// Either way we've got the index here, so look it up in the
// list of types and see how many parameters this function's
// type has.
let index = match f.ty.index.as_ref().unwrap() {
Index::Num(n, _) => *n,
_ => unreachable!(),
};
} else {
// If the inline type isn't listed then it's either not present
// (e.g. no params or results) or it was referenced by index.
// Either way we've got the index here, so look it up in the
// list of types and see how many parameters this function's
// type has.
let index = match f.ty.index.as_ref().unwrap() {
Index::Num(n, _) => *n,
_ => unreachable!(),
};

match func_type(types, index) {
Some(ft) => local_idx = ft.params.len() as u32,
// If the function type index is invalid then skip
// preserving names since we don't know how many parameters
// this function will have so we don't know where to start
// indexing at.
None => discard_locals = true,
match func_type(types, index) {
Some(ft) => local_idx = ft.params.len() as u32,
// If the function type index is invalid then skip
// preserving names since we don't know how many parameters
// this function will have so we don't know where to start
// indexing at.
None => discard_locals = true,
}
}
}

if let FuncKind::Inline {
locals, expression, ..
} = &f.kind
{
for local in locals.iter() {
if let Some(name) = get_name(&local.id, &local.name) {
local_names.push((local_idx, name));
if let FuncKind::Inline {
locals, expression, ..
} = &f.kind
{
for local in locals.iter() {
if let Some(name) = get_name(&local.id, &local.name) {
local_names.push((local_idx, name));
}
local_idx += 1;
}
local_idx += 1;
}

for i in expression.instrs.iter() {
match i {
Instruction::If(block)
| Instruction::Block(block)
| Instruction::Loop(block)
| Instruction::Try(block)
| Instruction::TryTable(TryTable { block, .. }) => {
if let Some(name) = get_name(&block.label, &block.label_name) {
label_names.push((label_idx, name));
for i in expression.instrs.iter() {
match i {
Instruction::If(block)
| Instruction::Block(block)
| Instruction::Loop(block)
| Instruction::Try(block)
| Instruction::TryTable(TryTable { block, .. }) => {
if let Some(name) = get_name(&block.label, &block.label_name) {
label_names.push((label_idx, name));
}
label_idx += 1;
}
label_idx += 1;
_ => {}
}
_ => {}
}
}
if !discard_locals && local_names.len() > 0 {
ret.locals.push((*idx, local_names));
}
if label_names.len() > 0 {
ret.labels.push((*idx, label_names));
}
}
if !discard_locals && local_names.len() > 0 {
ret.locals.push((*idx, local_names));
}
if label_names.len() > 0 {
ret.labels.push((*idx, label_names));
}
}

// Handle struct fields separately from above
if let ModuleField::Type(ty) = field {
let mut field_names = vec![];
match &ty.def.kind {
InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {}
InnerTypeKind::Struct(ty_struct) => {
for (idx, field) in ty_struct.fields.iter().enumerate() {
if let Some(name) = get_name(&field.id, &None) {
field_names.push((idx as u32, name))
// Handle struct fields separately from above
Some(ExtraNames::Type(ty)) => {
let mut field_names = vec![];
match &ty.def.kind {
InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {}
InnerTypeKind::Struct(ty_struct) => {
for (idx, field) in ty_struct.fields.iter().enumerate() {
if let Some(name) = get_name(&field.id, &field.name) {
field_names.push((idx as u32, name))
}
}
}
}
if field_names.len() > 0 {
ret.fields.push((*idx, field_names))
}
}
if field_names.len() > 0 {
ret.fields.push((*idx, field_names))
}

None => {}
}

*idx += 1;
Expand Down
8 changes: 4 additions & 4 deletions crates/wast/src/core/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,31 +314,31 @@ impl<'a> Parse<'a> for ItemSig<'a> {
Ok(ItemSig {
span,
id: parser.parse()?,
name: None,
name: parser.parse()?,
kind: ItemKind::Table(parser.parse()?),
})
} else if l.peek::<kw::memory>()? {
let span = parser.parse::<kw::memory>()?.0;
Ok(ItemSig {
span,
id: parser.parse()?,
name: None,
name: parser.parse()?,
kind: ItemKind::Memory(parser.parse()?),
})
} else if l.peek::<kw::global>()? {
let span = parser.parse::<kw::global>()?.0;
Ok(ItemSig {
span,
id: parser.parse()?,
name: None,
name: parser.parse()?,
kind: ItemKind::Global(parser.parse()?),
})
} else if l.peek::<kw::tag>()? {
let span = parser.parse::<kw::tag>()?.0;
Ok(ItemSig {
span,
id: parser.parse()?,
name: None,
name: parser.parse()?,
kind: ItemKind::Tag(parser.parse()?),
})
} else {
Expand Down
24 changes: 18 additions & 6 deletions crates/wast/src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,12 +818,14 @@ impl<'a> Parse<'a> for StructType<'a> {
while !parser.is_empty() {
parser.parens(|parser| {
parser.parse::<kw::field>()?;
if parser.peek::<Id>()? {
let field = StructField::parse(parser, true);
let id = parser.parse::<Option<Id<'a>>>()?;
let name = parser.parse::<Option<NameAnnotation<'a>>>()?;
if id.is_some() || name.is_some() {
let field = StructField::parse(parser, id, name);
ret.fields.push(field?);
} else {
while !parser.is_empty() {
let field = StructField::parse(parser, false);
let field = StructField::parse(parser, None, None);
ret.fields.push(field?);
}
}
Expand All @@ -839,15 +841,20 @@ impl<'a> Parse<'a> for StructType<'a> {
pub struct StructField<'a> {
/// An optional identifier for name resolution.
pub id: Option<Id<'a>>,
/// An optional name for this function stored in the custom `name` section.
pub name: Option<NameAnnotation<'a>>,
/// Whether this field may be mutated or not.
pub mutable: bool,
/// The storage type stored in this field.
pub ty: StorageType<'a>,
}

impl<'a> StructField<'a> {
fn parse(parser: Parser<'a>, with_id: bool) -> Result<Self> {
let id = if with_id { parser.parse()? } else { None };
fn parse(
parser: Parser<'a>,
id: Option<Id<'a>>,
name: Option<NameAnnotation<'a>>,
) -> Result<Self> {
let (ty, mutable) = if parser.peek2::<kw::r#mut>()? {
let ty = parser.parens(|parser| {
parser.parse::<kw::r#mut>()?;
Expand All @@ -857,7 +864,12 @@ impl<'a> StructField<'a> {
} else {
(parser.parse::<StorageType<'a>>()?, false)
};
Ok(StructField { id, mutable, ty })
Ok(StructField {
id,
name,
mutable,
ty,
})
}
}

Expand Down
19 changes: 19 additions & 0 deletions tests/cli/names.wast
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,22 @@

(module
(func (local (@name "") i32)))

(module
(type (@name "T") (func))
(type (@name "T") (func (param i32)))
(type (@name "S") (sub final (struct)))
(rec
(type (@name "R1") (struct
(field (@name "f") i32)
(field (@name "g") (ref null $r2))
))
(type $r2 (@name "R2") (array (mut i8)))
)
(type (@name "R2") (struct (field (@name "f") i32)))
)

(module
(import "" "" (func (@name "foo")))
(import "" "" (table (@name "foo") 1 funcref))
)
12 changes: 12 additions & 0 deletions tests/snapshots/cli/names.wast.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
"line": 23,
"filename": "names.5.wasm",
"module_type": "binary"
},
{
"type": "module",
"line": 26,
"filename": "names.6.wasm",
"module_type": "binary"
},
{
"type": "module",
"line": 40,
"filename": "names.7.wasm",
"module_type": "binary"
}
]
}
10 changes: 10 additions & 0 deletions tests/snapshots/cli/names.wast/6.print
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(module
(type $T (;0;) (func))
(type $"#type1 T" (@name "T") (;1;) (func (param i32)))
(type $S (;2;) (struct))
(rec
(type $R1 (;3;) (struct (field $f i32) (field $g (ref null $R2))))
(type $R2 (;4;) (array (mut i8)))
)
(type $"#type5 R2" (@name "R2") (;5;) (struct (field $f i32)))
)
5 changes: 5 additions & 0 deletions tests/snapshots/cli/names.wast/7.print
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(module
(type (;0;) (func))
(import "" "" (func $foo (;0;) (type 0)))
(import "" "" (table $foo (;0;) 1 funcref))
)
Loading