Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update blockty printing and space handling #799

Merged
merged 2 commits into from Oct 14, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions crates/wasm-compose/tests/compositions/complex-import/composed.wat
Expand Up @@ -2,15 +2,15 @@
(type (;0;)
(component
(type (;0;) (record (field "a" s8) (field "b" u8) (field "c" s16) (field "d" u16) (field "e" s32) (field "f" u32) (field "g" s64) (field "h" u64) (field "i" float32) (field "j" float64) (field "k" bool) (field "l" string)))
(export "record1" (type (eq 0)))
(export "record1" (type (eq 0)))
(type (;1;) (flags "a" "b" "c"))
(export "flags1" (type (eq 1)))
(export "flags1" (type (eq 1)))
(type (;2;) (enum "a" "b" "c"))
(export "enum1" (type (eq 2)))
(export "enum1" (type (eq 2)))
(type (;3;) (union s8 string 0))
(export "union1" (type (eq 3)))
(export "union1" (type (eq 3)))
(type (;4;) (variant (case "a" s8) (case "b" u8) (case "c" s16) (case "d" u16) (case "e" s32) (case "f" u32) (case "g" s64) (case "h" u64) (case "i" float32) (case "j" float64) (case "k" bool) (case "l" string) (case "m" 0)))
(export "variant1" (type (eq 4)))
(export "variant1" (type (eq 4)))
(type (;5;) (func))
(export "a" (func (type 5)))
(type (;6;) (func (param "x" s8)))
Expand Down Expand Up @@ -92,7 +92,7 @@
(type (;12;) (func (param "x" string)))
(export "m" (func (type 12)))
(type (;13;) (record (field "a" s8) (field "b" u8) (field "c" s16) (field "d" u16) (field "e" s32) (field "f" u32) (field "g" s64) (field "h" u64) (field "i" float32) (field "j" float64) (field "k" bool) (field "l" string)))
(export "record1" (type (eq 13)))
(export "record1" (type (eq 13)))
(type (;14;) (func (param "x" 13)))
(export "n" (func (type 14)))
(type (;15;) (list 13))
Expand All @@ -102,19 +102,19 @@
(type (;18;) (func (param "x" 17)))
(export "p" (func (type 18)))
(type (;19;) (flags "a" "b" "c"))
(export "flags1" (type (eq 19)))
(export "flags1" (type (eq 19)))
(type (;20;) (func (param "x" 19)))
(export "q" (func (type 20)))
(type (;21;) (enum "a" "b" "c"))
(export "enum1" (type (eq 21)))
(export "enum1" (type (eq 21)))
(type (;22;) (func (param "x" 21)))
(export "r" (func (type 22)))
(type (;23;) (union s8 string 13))
(export "union1" (type (eq 23)))
(export "union1" (type (eq 23)))
(type (;24;) (func (param "x" 23)))
(export "s" (func (type 24)))
(type (;25;) (variant (case "a" s8) (case "b" u8) (case "c" s16) (case "d" u16) (case "e" s32) (case "f" u32) (case "g" s64) (case "h" u64) (case "i" float32) (case "j" float64) (case "k" bool) (case "l" string) (case "m" 13)))
(export "variant1" (type (eq 25)))
(export "variant1" (type (eq 25)))
(type (;26;) (option 25))
(type (;27;) (func (param "x" 26)))
(export "t" (func (type 27)))
Expand Down
10 changes: 5 additions & 5 deletions crates/wasm-compose/tests/compositions/complex/composed.wat
Expand Up @@ -267,27 +267,27 @@
(alias outer 1 12 (type (;12;)))
(export "m" (func (type 12)))
(alias outer 1 13 (type (;13;)))
(export "record1" (type (eq 13)))
(export "record1" (type (eq 13)))
(alias outer 1 14 (type (;14;)))
(export "n" (func (type 14)))
(alias outer 1 16 (type (;15;)))
(export "o" (func (type 15)))
(alias outer 1 18 (type (;16;)))
(export "p" (func (type 16)))
(alias outer 1 19 (type (;17;)))
(export "flags1" (type (eq 17)))
(export "flags1" (type (eq 17)))
(alias outer 1 20 (type (;18;)))
(export "q" (func (type 18)))
(alias outer 1 21 (type (;19;)))
(export "enum1" (type (eq 19)))
(export "enum1" (type (eq 19)))
(alias outer 1 22 (type (;20;)))
(export "r" (func (type 20)))
(alias outer 1 23 (type (;21;)))
(export "union1" (type (eq 21)))
(export "union1" (type (eq 21)))
(alias outer 1 24 (type (;22;)))
(export "s" (func (type 22)))
(alias outer 1 25 (type (;23;)))
(export "variant1" (type (eq 23)))
(export "variant1" (type (eq 23)))
(alias outer 1 27 (type (;24;)))
(export "t" (func (type 24)))
(alias outer 1 29 (type (;25;)))
Expand Down
43 changes: 18 additions & 25 deletions crates/wasmprinter/src/lib.rs
Expand Up @@ -527,9 +527,9 @@ impl Printer {
&states.last().unwrap().core.type_names,
states.last().unwrap().core.types.len() as u32,
)?;
self.result.push(' ');
let ty = match ty {
wasmparser::CoreType::Func(ty) => {
self.result.push(' ');
self.start_group("func");
self.print_func_type(states.last().unwrap(), &ty, None)?;
self.end_group();
Expand Down Expand Up @@ -591,21 +591,13 @@ impl Printer {
&mut self,
state: &State,
idx: u32,
always_print_type: bool,
names_for: Option<u32>,
) -> Result<Option<u32>> {
if always_print_type {
self.print_type_ref(state, idx, true, None)?;
}
self.print_type_ref(state, idx, true, None)?;

match state.core.types.get(idx as usize) {
Some(Some(ty)) => self.print_func_type(state, ty, names_for).map(Some),
Some(None) | None => {
if !always_print_type {
self.print_type_ref(state, idx, true, None)?;
}
Ok(None)
}
Some(None) | None => Ok(None),
}
}

Expand Down Expand Up @@ -695,10 +687,10 @@ impl Printer {
fn print_import_ty(&mut self, state: &State, ty: &TypeRef, index: bool) -> Result<()> {
match ty {
TypeRef::Func(f) => {
self.start_group("func");
self.start_group("func ");
if index {
self.result.push(' ');
self.print_name(&state.core.func_names, state.core.funcs)?;
self.result.push(' ');
}
self.print_type_ref(state, *f, true, None)?;
}
Expand Down Expand Up @@ -742,9 +734,9 @@ impl Printer {
fn print_tag_type(&mut self, state: &State, ty: &TagType, index: bool) -> Result<()> {
self.start_group("tag ");
if index {
write!(self.result, "(;{};)", state.core.tags)?;
write!(self.result, "(;{};) ", state.core.tags)?;
}
self.print_core_functype_idx(state, ty.func_type_idx, true, None)?;
self.print_core_functype_idx(state, ty.func_type_idx, None)?;
Ok(())
}

Expand Down Expand Up @@ -838,8 +830,9 @@ impl Printer {
self.start_group("func ");
let func_idx = state.core.funcs;
self.print_name(&state.core.func_names, func_idx)?;
self.result.push(' ');
let params = self
.print_core_functype_idx(state, ty, true, Some(func_idx))?
.print_core_functype_idx(state, ty, Some(func_idx))?
.unwrap_or(0);

let mut first = true;
Expand Down Expand Up @@ -1015,7 +1008,7 @@ impl Printer {
core: bool,
bounds: Option<TypeBounds>,
) -> Result<()> {
self.result.push_str(" (type ");
self.result.push_str("(type ");
let closing = match bounds {
Some(TypeBounds::Eq) => {
self.result.push_str("(eq ");
Expand Down Expand Up @@ -1703,19 +1696,19 @@ impl Printer {
) -> Result<()> {
match ty {
ComponentTypeRef::Module(idx) => {
self.start_group("core module");
self.start_group("core module ");
if index {
self.result.push(' ');
self.print_name(&state.core.module_names, state.core.modules as u32)?;
self.result.push(' ');
}
self.print_type_ref(state, *idx, true, None)?;
self.end_group();
}
ComponentTypeRef::Func(idx) => {
self.start_group("func");
self.start_group("func ");
if index {
self.result.push(' ');
self.print_name(&state.component.func_names, state.component.funcs)?;
self.result.push(' ');
}
self.print_type_ref(state, *idx, false, None)?;
self.end_group();
Expand All @@ -1738,19 +1731,19 @@ impl Printer {
self.print_type_ref(state, *idx, false, Some(*bounds))?;
}
ComponentTypeRef::Instance(idx) => {
self.start_group("instance");
self.start_group("instance ");
if index {
self.result.push(' ');
self.print_name(&state.component.instance_names, state.component.instances)?;
self.result.push(' ');
}
self.print_type_ref(state, *idx, false, None)?;
self.end_group();
}
ComponentTypeRef::Component(idx) => {
self.start_group("component");
self.start_group("component ");
if index {
self.result.push(' ');
self.print_name(&state.component.component_names, state.component.components)?;
self.result.push(' ');
}
self.print_type_ref(state, *idx, false, None)?;
self.end_group();
Expand Down
16 changes: 12 additions & 4 deletions crates/wasmprinter/src/operator.rs
Expand Up @@ -33,26 +33,27 @@ impl<'a, 'b> PrintOperator<'a, 'b> {
.label_names
.get(&(self.state.core.funcs, self.state.core.labels))
{
self.printer.result.push(' ');
name.write(&mut self.printer.result);
self.printer.result.push(' ');
}
match ty {
BlockType::Empty => {}
BlockType::Type(t) => {
self.push_str("(result ");
self.printer.print_valtype(t)?;
self.push_str(")");
self.push_str(") ");
}
BlockType::FuncType(idx) => {
self.printer
.print_core_functype_idx(self.state, idx, false, None)?;
.print_core_functype_idx(self.state, idx, None)?;
self.printer.result.push(' ');
}
}
// Note that 1 is added to the current depth here since if a block type
// is being printed then a block is being created which will increase
// the label depth of the block itself.
let depth = self.cur_depth();
write!(self.result(), " ;; label = @{}", depth + 1)?;
write!(self.result(), ";; label = @{}", depth + 1)?;
self.state.core.labels += 1;
Ok(())
}
Expand Down Expand Up @@ -115,6 +116,7 @@ impl<'a, 'b> PrintOperator<'a, 'b> {
}

fn type_index(&mut self, idx: u32) -> Result<()> {
self.push_str(" ");
self.printer.print_type_ref(self.state, idx, true, None)
}

Expand Down Expand Up @@ -142,6 +144,12 @@ impl<'a, 'b> PrintOperator<'a, 'b> {
}

fn memarg(&mut self, memarg: MemArg) -> Result<()> {
// Remove the leading ' ' inserted by the macro below since memarg may
// not actually print anything if all of its parameters are defaulted.
// Ideally we wouldn't rely on the ability to pop here but this ends up
// being the easiest.
assert_eq!(self.printer.result.pop(), Some(' '));

if memarg.memory != 0 {
self.result().push(' ');
self.memory_index(memarg.memory)?;
Expand Down
55 changes: 11 additions & 44 deletions crates/wast/src/core/resolve/names.rs
Expand Up @@ -384,54 +384,21 @@ impl<'a, 'b> ExprResolver<'a, 'b> {
}

fn resolve_block_type(&mut self, bt: &mut BlockType<'a>) -> Result<(), Error> {
// Ok things get interesting here. First off when parsing `bt`
// *optionally* has an index and a function type listed. If
// they're both not present it's equivalent to 0 params and 0
// results.
// If the index is specified on this block type then that's the source
// of resolution and the resolver step here will verify the inline type
// matches. Note that indexes may come from the source text itself but
// may also come from being injected as part of the type expansion phase
// of resolution.
//
// In MVP wasm blocks can have 0 params and 0-1 results. Now
// there's also multi-value. We want to prefer MVP wasm wherever
// possible (for backcompat) so we want to list this block as
// being an "MVP" block if we can. The encoder only has
// `BlockType` to work with, so it'll be looking at `params` and
// `results` to figure out what to encode. If `params` and
// `results` fit within MVP, then it uses MVP encoding
//
// To put all that together, here we handle:
//
// * If the `index` was specified, resolve it and use it as the
// source of truth. If this turns out to be an MVP type,
// record it as such.
// * Otherwise use `params` and `results` as the source of
// truth. *If* this were a non-MVP compatible block `index`
// would be filled by by `tyexpand.rs`.
//
// tl;dr; we handle the `index` here if it's set and then fill
// out `params` and `results` if we can, otherwise no work
// happens.
// If no type is present then that means that the inline type is not
// present or has 0-1 results. In that case the nested value types are
// resolved, if they're there, to get encoded later on.
if bt.ty.index.is_some() {
let (ty, _) = self.resolver.resolve_type_use(&mut bt.ty)?;
let n = match ty {
Index::Num(n, _) => *n,
Index::Id(_) => panic!("expected `Num`"),
};
let ty = match self.resolver.type_info.get(n as usize) {
Some(TypeInfo::Func { params, results }) => (params, results),
_ => return Ok(()),
};
if ty.0.len() == 0 && ty.1.len() <= 1 {
let mut inline = FunctionType::default();
inline.results = ty.1.clone();
bt.ty.inline = Some(inline);
bt.ty.index = None;
}
}

// If the inline annotation persists to this point then resolve
// all of its inline value types.
if let Some(inline) = &mut bt.ty.inline {
self.resolver.resolve_type_use(&mut bt.ty)?;
} else if let Some(inline) = &mut bt.ty.inline {
inline.resolve(self.resolver)?;
}

Ok(())
}

Expand Down
14 changes: 14 additions & 0 deletions tests/dump/blockty.wat
@@ -0,0 +1,14 @@
(module
(type $empty (func))
(type $t (func (result i32)))
(func
(block)
(block (result i32))
(block (param i32))
(block (param i32) (result i32))
(block (param i32) (result i32 i32))
(block (type $t))
(block (type $t) (result i32))
(block (type $empty))
)
)
44 changes: 44 additions & 0 deletions tests/dump/blockty.wat.dump
@@ -0,0 +1,44 @@
0x0 | 00 61 73 6d | version 1 (Module)
| 01 00 00 00
0x8 | 01 17 | type section
0xa | 05 | 5 count
0xb | 60 00 00 | [type 0] Func(FuncType { params: [], returns: [] })
0xe | 60 00 01 7f | [type 1] Func(FuncType { params: [], returns: [I32] })
0x12 | 60 01 7f 00 | [type 2] Func(FuncType { params: [I32], returns: [] })
0x16 | 60 01 7f 01 | [type 3] Func(FuncType { params: [I32], returns: [I32] })
| 7f
0x1b | 60 01 7f 02 | [type 4] Func(FuncType { params: [I32], returns: [I32, I32] })
| 7f 7f
0x21 | 03 02 | func section
0x23 | 01 | 1 count
0x24 | 00 | [func 0] type 0
0x25 | 0a 1c | code section
0x27 | 01 | 1 count
============== func 0 ====================
0x28 | 1a | size of function
0x29 | 00 | 0 local blocks
0x2a | 02 40 | block blockty:Empty
0x2c | 0b | end
0x2d | 02 7f | block blockty:Type(I32)
0x2f | 0b | end
0x30 | 02 02 | block blockty:FuncType(2)
0x32 | 0b | end
0x33 | 02 03 | block blockty:FuncType(3)
0x35 | 0b | end
0x36 | 02 04 | block blockty:FuncType(4)
0x38 | 0b | end
0x39 | 02 01 | block blockty:FuncType(1)
0x3b | 0b | end
0x3c | 02 01 | block blockty:FuncType(1)
0x3e | 0b | end
0x3f | 02 00 | block blockty:FuncType(0)
0x41 | 0b | end
0x42 | 0b | end
0x43 | 00 12 | custom section
0x45 | 04 6e 61 6d | name: "name"
| 65
0x4a | 04 0b | type names
0x4c | 02 | 2 count
0x4d | 00 05 65 6d | Naming { index: 0, name: "empty" }
| 70 74 79
0x54 | 01 01 74 | Naming { index: 1, name: "t" }