Repository: bytecodealliance/wasm-tools
Pull request #1512 (2024-04-23 16:13:28)

wasmprinter: prints field names declared in the names section
Noticed these were missing from the output of `wasm-tools print`. I'm surprised that none of the snapshots had to be updated. Is there something I'm missing?

kritzcreek: > Would you be up for implementing a bit more support so a test can be added for this? Ideally this PR would additionally have tests and/or examples showing the field names getting printed too, but I believe that the lack of parsing support is why they're not showing up. The implementation would go [around here](https://github.com/bytecodealliance/wasm-tools/blob/30200e188316b6ca00b296de2c53eea3ec6fef64/crates/wast/src/core/binary.rs#L893-L1127) if you're interested.

Hah! Lack of parsing support was my first guess, but when I checked out the parser it _did_ parse the optional name. I didn't think to check if it ended up actually encoding it into the names section.

I added an additional test case to explicitly check that referencing named struct fields via index get replaced with their names when printing the file back.

PTAL

Patch:
diff --git a/crates/wasm-metadata/src/lib.rs b/crates/wasm-metadata/src/lib.rs
index e12abd15..8a3626e0 100644
--- a/crates/wasm-metadata/src/lib.rs
+++ b/crates/wasm-metadata/src/lib.rs
@@ -646,6 +646,7 @@ impl<'a> ModuleNames<'a> {
                 wasmparser::Name::Global(m) => section.globals(&name_map(&m)?),
                 wasmparser::Name::Element(m) => section.elements(&name_map(&m)?),
                 wasmparser::Name::Data(m) => section.data(&name_map(&m)?),
+                wasmparser::Name::Field(m) => section.fields(&indirect_name_map(&m)?),
                 wasmparser::Name::Tag(m) => section.tags(&name_map(&m)?),
                 wasmparser::Name::Unknown { .. } => {} // wasm-encoder doesn't support it
             }
diff --git a/crates/wasmparser/src/readers/core/names.rs b/crates/wasmparser/src/readers/core/names.rs
index b4782427..93633854 100644
--- a/crates/wasmparser/src/readers/core/names.rs
+++ b/crates/wasmparser/src/readers/core/names.rs
@@ -101,6 +101,8 @@ pub enum Name<'a> {
     Element(NameMap<'a>),
     /// The name is for the data segments.
     Data(NameMap<'a>),
+    /// The name is for fields.
+    Field(IndirectNameMap<'a>),
     /// The name is for tags.
     Tag(NameMap<'a>),
     /// An unknown [name subsection](https://webassembly.github.io/spec/core/appendix/custom.html#subsections).
@@ -145,6 +147,7 @@ impl<'a> Subsection<'a> for Name<'a> {
             7 => Name::Global(NameMap::new(data, offset)?),
             8 => Name::Element(NameMap::new(data, offset)?),
             9 => Name::Data(NameMap::new(data, offset)?),
+            10 => Name::Field(IndirectNameMap::new(data, offset)?),
             11 => Name::Tag(NameMap::new(data, offset)?),
             ty => Name::Unknown {
                 ty,
diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs
index 433d7d15..4a8e5cac 100644
--- a/crates/wasmprinter/src/lib.rs
+++ b/crates/wasmprinter/src/lib.rs
@@ -72,6 +72,7 @@ struct CoreState {
     local_names: NamingMap<(u32, u32), NameLocal>,
     label_names: NamingMap<(u32, u32), NameLabel>,
     type_names: NamingMap<u32, NameType>,
+    field_names: NamingMap<(u32, u32), NameField>,
     tag_names: NamingMap<u32, NameTag>,
     table_names: NamingMap<u32, NameTable>,
     memory_names: NamingMap<u32, NameMemory>,
@@ -639,7 +640,7 @@ impl Printer {
                 let mut used = match name {
                     // labels can be shadowed, so maintaining the used names is not useful.
                     "label" => None,
-                    "local" => Some(HashSet::new()),
+                    "local" | "field" => Some(HashSet::new()),
                     _ => unimplemented!("{name} is an unknown type of indirect names"),
                 };
                 for naming in indirect.names {
@@ -668,6 +669,7 @@ impl Printer {
                 Name::Global(n) => name_map(&mut state.core.global_names, n, "global")?,
                 Name::Element(n) => name_map(&mut state.core.element_names, n, "elem")?,
                 Name::Data(n) => name_map(&mut state.core.data_names, n, "data")?,
+                Name::Field(n) => indirect_name_map(&mut state.core.field_names, n, "field")?,
                 Name::Tag(n) => name_map(&mut state.core.tag_names, n, "tag")?,
                 Name::Unknown { .. } => (),
             }
@@ -774,37 +776,33 @@ impl Printer {
 
     fn print_type(&mut self, state: &mut State, ty: SubType) -> Result<()> {
         self.start_group("type ");
-        self.print_name(&state.core.type_names, state.core.types.len() as u32)?;
+        let ty_idx = state.core.types.len() as u32;
+        self.print_name(&state.core.type_names, ty_idx)?;
         self.result.push(' ');
-        self.print_sub(state, &ty, None)?;
+        self.print_sub(state, &ty, ty_idx)?;
         self.end_group(); // `type`
         state.core.types.push(Some(ty));
         Ok(())
     }
 
-    fn print_sub(&mut self, state: &State, ty: &SubType, names_for: Option<u32>) -> Result<u32> {
+    fn print_sub(&mut self, state: &State, ty: &SubType, ty_idx: u32) -> Result<u32> {
         let r = if !ty.is_final || !ty.supertype_idx.is_none() {
             self.start_group("sub");
             self.print_sub_type(state, ty)?;
-            let r = self.print_composite(state, &ty.composite_type, names_for)?;
+            let r = self.print_composite(state, &ty.composite_type, ty_idx)?;
             self.end_group(); // `sub`
             r
         } else {
-            self.print_composite(state, &ty.composite_type, names_for)?
+            self.print_composite(state, &ty.composite_type, ty_idx)?
         };
         Ok(r)
     }
 
-    fn print_composite(
-        &mut self,
-        state: &State,
-        ty: &CompositeType,
-        names_for: Option<u32>,
-    ) -> Result<u32> {
+    fn print_composite(&mut self, state: &State, ty: &CompositeType, ty_idx: u32) -> Result<u32> {
         let r = match &ty {
             CompositeType::Func(ty) => {
                 self.start_group("func");
-                let r = self.print_func_type(state, ty, names_for)?;
+                let r = self.print_func_type(state, ty, None)?;
                 self.end_group(); // `func`
                 r
             }
@@ -816,7 +814,7 @@ impl Printer {
             }
             CompositeType::Struct(ty) => {
                 self.start_group("struct");
-                let r = self.print_struct_type(state, ty)?;
+                let r = self.print_struct_type(state, ty, ty_idx)?;
                 self.end_group(); // `struct`
                 r
             }
@@ -904,8 +902,20 @@ impl Printer {
         Ok(ty.params().len() as u32)
     }
 
-    fn print_field_type(&mut self, state: &State, ty: &FieldType) -> Result<u32> {
+    fn print_field_type(
+        &mut self,
+        state: &State,
+        ty: &FieldType,
+        ty_field_idx: Option<(u32, u32)>,
+    ) -> Result<u32> {
         self.result.push(' ');
+        if let Some(idxs @ (_, field_idx)) = ty_field_idx {
+            match state.core.field_names.index_to_name.get(&idxs) {
+                Some(name) => write!(self.result, "${} ", name.identifier())?,
+                None if self.name_unnamed => write!(self.result, "$#field{field_idx} ")?,
+                None => {}
+            }
+        }
         if ty.mutable {
             self.result.push_str("(mut ");
         }
@@ -917,13 +927,13 @@ impl Printer {
     }
 
     fn print_array_type(&mut self, state: &State, ty: &ArrayType) -> Result<u32> {
-        self.print_field_type(state, &ty.0)
+        self.print_field_type(state, &ty.0, None)
     }
 
-    fn print_struct_type(&mut self, state: &State, ty: &StructType) -> Result<u32> {
-        for field in ty.fields.iter() {
+    fn print_struct_type(&mut self, state: &State, ty: &StructType, ty_idx: u32) -> Result<u32> {
+        for (field_index, field) in ty.fields.iter().enumerate() {
             self.result.push_str(" (field");
-            self.print_field_type(state, field)?;
+            self.print_field_type(state, field, Some((ty_idx, field_index as u32)))?;
             self.result.push(')');
         }
         Ok(0)
@@ -1459,6 +1469,15 @@ impl Printer {
         Ok(())
     }
 
+    fn print_field_idx(&mut self, state: &State, ty: u32, idx: u32) -> Result<()> {
+        match state.core.field_names.index_to_name.get(&(ty, idx)) {
+            Some(name) => write!(self.result, "${}", name.identifier())?,
+            None if self.name_unnamed => write!(self.result, "$#field{idx}")?,
+            None => write!(self.result, "{}", idx)?,
+        }
+        Ok(())
+    }
+
     fn print_name<K>(&mut self, names: &NamingMap<u32, K>, cur_idx: u32) -> Result<()>
     where
         K: NamingNamespace,
@@ -3184,6 +3203,7 @@ naming_namespaces! {
     struct NameTable => "table"
     struct NameValue => "value"
     struct NameType => "type"
+    struct NameField => "field"
     struct NameData => "data"
     struct NameElem => "elem"
     struct NameComponent => "component"
diff --git a/crates/wasmprinter/src/operator.rs b/crates/wasmprinter/src/operator.rs
index efcfa98d..fcb3acc5 100644
--- a/crates/wasmprinter/src/operator.rs
+++ b/crates/wasmprinter/src/operator.rs
@@ -254,11 +254,6 @@ impl<'a, 'b> PrintOperator<'a, 'b> {
         self.printer.print_idx(&self.state.core.type_names, idx)
     }
 
-    fn field_index(&mut self, idx: u32) -> Result<()> {
-        write!(&mut self.printer.result, "{idx}")?;
-        Ok(())
-    }
-
     fn from_ref_type(&mut self, ref_ty: RefType) -> Result<()> {
         self.printer.print_reftype(self.state, ref_ty)
     }
@@ -555,6 +550,30 @@ macro_rules! define_visit {
             .ok_or_else(|| anyhow!("implementation limit: type index too large"))?;
         $self.printer.print_reftype($self.state, rty)?;
     );
+    (payload $self:ident StructGet $ty:ident $field:ident) => (
+        $self.push_str(" ");
+        $self.struct_type_index($ty)?;
+        $self.push_str(" ");
+        $self.printer.print_field_idx($self.state, $ty, $field)?;
+    );
+    (payload $self:ident StructGetS $ty:ident $field:ident) => (
+        $self.push_str(" ");
+        $self.struct_type_index($ty)?;
+        $self.push_str(" ");
+        $self.printer.print_field_idx($self.state, $ty, $field)?;
+    );
+    (payload $self:ident StructGetU $ty:ident $field:ident) => (
+        $self.push_str(" ");
+        $self.struct_type_index($ty)?;
+        $self.push_str(" ");
+        $self.printer.print_field_idx($self.state, $ty, $field)?;
+    );
+    (payload $self:ident StructSet $ty:ident $field:ident) => (
+        $self.push_str(" ");
+        $self.struct_type_index($ty)?;
+        $self.push_str(" ");
+        $self.printer.print_field_idx($self.state, $ty, $field)?;
+    );
     (payload $self:ident $op:ident $($arg:ident)*) => (
         $(
             $self.push_str(" ");
diff --git a/crates/wast/src/core/binary.rs b/crates/wast/src/core/binary.rs
index 769e1201..a0ded4e1 100644
--- a/crates/wast/src/core/binary.rs
+++ b/crates/wast/src/core/binary.rs
@@ -911,6 +911,7 @@ struct Names<'a> {
     data_idx: u32,
     elems: Vec<(u32, &'a str)>,
     elem_idx: u32,
+    fields: Vec<(u32, Vec<(u32, &'a str)>)>,
 }
 
 fn find_names<'a>(
@@ -1045,6 +1046,24 @@ fn find_names<'a>(
             }
         }
 
+        // Handle struct fields separately from above
+        if let ModuleField::Type(ty) = field {
+            let mut field_names = vec![];
+            match &ty.def {
+                TypeDef::Func(_) | TypeDef::Array(_) => {}
+                TypeDef::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))
+                        }
+                    }
+                }
+            }
+            if field_names.len() > 0 {
+                ret.fields.push((*idx, field_names))
+            }
+        }
+
         *idx += 1;
     }
 
@@ -1061,8 +1080,9 @@ impl Names<'_> {
             && self.memories.is_empty()
             && self.tables.is_empty()
             && self.types.is_empty()
-            && self.data.is_empty()
             && self.elems.is_empty()
+            && self.data.is_empty()
+            && self.fields.is_empty()
             && self.tags.is_empty()
         // NB: specifically don't check modules/instances since they're
         // not encoded for now.
@@ -1119,6 +1139,10 @@ impl Encode for Names<'_> {
             self.data.encode(&mut tmp);
             subsec(9, &mut tmp);
         }
+        if self.fields.len() > 0 {
+            self.fields.encode(&mut tmp);
+            subsec(10, &mut tmp);
+        }
         if self.tags.len() > 0 {
             self.tags.encode(&mut tmp);
             subsec(11, &mut tmp);
diff --git a/fuzz/src/roundtrip.rs b/fuzz/src/roundtrip.rs
index 221193bb..17021f60 100644
--- a/fuzz/src/roundtrip.rs
+++ b/fuzz/src/roundtrip.rs
@@ -82,7 +82,7 @@ fn validate_name_section(wasm: &[u8]) -> wasmparser::Result<()> {
                         name?;
                     }
                 }
-                Name::Local(n) | Name::Label(n) => {
+                Name::Local(n) | Name::Label(n) | Name::Field(n) => {
                     for name in n {
                         for name in name?.names {
                             name?;
diff --git a/src/bin/wasm-tools/demangle.rs b/src/bin/wasm-tools/demangle.rs
index 297e299c..613177e3 100644
--- a/src/bin/wasm-tools/demangle.rs
+++ b/src/bin/wasm-tools/demangle.rs
@@ -73,6 +73,7 @@ impl Opts {
                 Name::Data(names) => new_section.data(&self.name_map(names)?),
                 Name::Local(names) => new_section.locals(&self.indirect_name_map(names)?),
                 Name::Label(names) => new_section.labels(&self.indirect_name_map(names)?),
+                Name::Field(names) => new_section.fields(&self.indirect_name_map(names)?),
                 Name::Tag(names) => new_section.tags(&self.name_map(names)?),
                 Name::Unknown { .. } => bail!("unknown name section"),
             }
diff --git a/src/bin/wasm-tools/dump.rs b/src/bin/wasm-tools/dump.rs
index c620e464..14a7c3c4 100644
--- a/src/bin/wasm-tools/dump.rs
+++ b/src/bin/wasm-tools/dump.rs
@@ -566,6 +566,7 @@ impl<'a> Dump<'a> {
             Name::Global(n) => self.print_name_map("global", n)?,
             Name::Element(n) => self.print_name_map("element", n)?,
             Name::Data(n) => self.print_name_map("data", n)?,
+            Name::Field(n) => self.print_indirect_name_map("type", "field", n)?,
             Name::Tag(n) => self.print_name_map("tag", n)?,
             Name::Unknown { ty, range, .. } => {
                 write!(self.state, "unknown names: {}", ty)?;


Test patch:
diff --git a/tests/local/gc/gc-struct-names.wat b/tests/local/gc/gc-struct-names.wat
new file mode 100644
index 00000000..8b03f9f5
--- /dev/null
+++ b/tests/local/gc/gc-struct-names.wat
@@ -0,0 +1,39 @@
+;; --enable-gc
+
+(module
+  (type $named (struct (field $x i32) (field $y i32)))
+  (type $partially_named (struct (field $x i32) (field i32)))
+  (type $unnamed (struct (field i32) (field i32)))
+
+  (func (param (ref $named) (ref $partially_named) (ref $unnamed))
+    i32.const 1
+    i32.const 2
+    struct.new $named
+    local.tee 0
+    struct.get $named 0
+    local.get 0
+    struct.get $named 1
+    drop
+    drop
+
+    i32.const 1
+    i32.const 2
+    struct.new $partially_named
+    local.tee 1
+    struct.get $partially_named 0
+    local.get 1
+    struct.get $partially_named 1
+    drop
+    drop
+
+    i32.const 1
+    i32.const 2
+    struct.new $unnamed
+    local.tee 2
+    struct.get $unnamed 0
+    local.get 2
+    struct.get $unnamed 1
+    drop
+    drop
+  )
+)
diff --git a/tests/snapshots/local/gc/gc-struct-names.wat.print b/tests/snapshots/local/gc/gc-struct-names.wat.print
new file mode 100644
index 00000000..4ce1b0ec
--- /dev/null
+++ b/tests/snapshots/local/gc/gc-struct-names.wat.print
@@ -0,0 +1,35 @@
+(module
+  (type $named (;0;) (struct (field $x i32) (field $y i32)))
+  (type $partially_named (;1;) (struct (field $x i32) (field i32)))
+  (type $unnamed (;2;) (struct (field i32) (field i32)))
+  (type (;3;) (func (param (ref $named) (ref $partially_named) (ref $unnamed))))
+  (func (;0;) (type 3) (param (ref $named) (ref $partially_named) (ref $unnamed))
+    i32.const 1
+    i32.const 2
+    struct.new $named
+    local.tee 0
+    struct.get $named $x
+    local.get 0
+    struct.get $named $y
+    drop
+    drop
+    i32.const 1
+    i32.const 2
+    struct.new $partially_named
+    local.tee 1
+    struct.get $partially_named $x
+    local.get 1
+    struct.get $partially_named 1
+    drop
+    drop
+    i32.const 1
+    i32.const 2
+    struct.new $unnamed
+    local.tee 2
+    struct.get $unnamed 0
+    local.get 2
+    struct.get $unnamed 1
+    drop
+    drop
+  )
+)
diff --git a/tests/snapshots/local/gc/gc-struct-types.wat.print b/tests/snapshots/local/gc/gc-struct-types.wat.print
index b422ed87..2ef43bf1 100644
--- a/tests/snapshots/local/gc/gc-struct-types.wat.print
+++ b/tests/snapshots/local/gc/gc-struct-types.wat.print
@@ -7,14 +7,14 @@
   (type (;5;) (struct (field (mut i32)) (field (mut i32))))
   (type $a (;6;) (struct (field f32)))
   (type $b (;7;) (struct (field f32)))
-  (type (;8;) (struct (field externref)))
-  (type (;9;) (struct (field externref) (field funcref)))
+  (type (;8;) (struct (field $field_a externref)))
+  (type (;9;) (struct (field $field_b externref) (field $field_c funcref)))
   (type (;10;) (struct))
   (type (;11;) (struct (field i32) (field i32)))
   (type (;12;) (struct (field i32) (field (mut i32))))
   (type (;13;) (struct (field (mut i32)) (field i32)))
   (type (;14;) (struct (field (mut i32)) (field (mut i32))))
-  (type (;15;) (struct (field i32) (field f32) (field f32) (field f32)))
+  (type (;15;) (struct (field $a i32) (field f32) (field f32) (field f32)))
   (type (;16;) (struct (field i32) (field (ref null $a)) (field (mut (ref null $b)))))
   (type (;17;) (struct (field i32) (field (ref null $a)) (field (mut (ref null $b)))))
   (type (;18;) (struct (field i32) (field i64) (field i8) (field i31ref) (field anyref)))
diff --git a/tests/snapshots/local/gc/gc-struct.wat.print b/tests/snapshots/local/gc/gc-struct.wat.print
index afcde042..a4798150 100644
--- a/tests/snapshots/local/gc/gc-struct.wat.print
+++ b/tests/snapshots/local/gc/gc-struct.wat.print
@@ -5,10 +5,10 @@
   (type (;3;) (struct (field i32) (field i32)))
   (type (;4;) (struct (field i32) (field (mut i32))))
   (type (;5;) (struct (field (mut i32)) (field (mut i32))))
-  (type $a (;6;) (struct (field f32)))
-  (type $b (;7;) (struct (field (mut f32))))
-  (type (;8;) (struct (field externref)))
-  (type (;9;) (struct (field externref) (field funcref)))
+  (type $a (;6;) (struct (field $field_a f32)))
+  (type $b (;7;) (struct (field $field_b (mut f32))))
+  (type (;8;) (struct (field $field_a externref)))
+  (type (;9;) (struct (field $field_b externref) (field $field_c funcref)))
   (type (;10;) (func (param (ref $a) (ref $b))))
   (func (;0;) (type 10) (param (ref $a) (ref $b))
     f32.const 0x1p+0 (;=1;)
@@ -17,10 +17,10 @@
     struct.new_default $a
     drop
     local.get 0
-    struct.get $a 0
+    struct.get $a $field_a
     drop
     local.get 1
     f32.const 0x1p+0 (;=1;)
-    struct.set $b 0
+    struct.set $b $field_b
   )
 )
diff --git a/tests/snapshots/local/gc/gc-subtypes.wat.print b/tests/snapshots/local/gc/gc-subtypes.wat.print
index 46f3569a..0abcb9e1 100644
--- a/tests/snapshots/local/gc/gc-subtypes.wat.print
+++ b/tests/snapshots/local/gc/gc-subtypes.wat.print
@@ -68,8 +68,8 @@
   (type $y0 (;66;) (sub $v0 (array (ref noextern))))
   (type $y01 (;67;) (sub $u0 (array (ref noextern))))
   (type $z0 (;68;) (sub $u0 (array nullexternref)))
-  (type $A (;69;) (sub (struct (field (mut i32)))))
-  (type $B (;70;) (sub $A (struct (field (mut i32)))))
-  (type (;71;) (sub $A (struct (field (mut i32)))))
-  (type (;72;) (sub $A (struct (field (mut i32)) (field (mut i64)))))
+  (type $A (;69;) (sub (struct (field $vt (mut i32)))))
+  (type $B (;70;) (sub $A (struct (field $vt (mut i32)))))
+  (type (;71;) (sub $A (struct (field $tv (mut i32)))))
+  (type (;72;) (sub $A (struct (field (mut i32)) (field $vt (mut i64)))))
 )
diff --git a/tests/snapshots/testsuite/proposals/gc/struct.wast/0.print b/tests/snapshots/testsuite/proposals/gc/struct.wast/0.print
index 1806dd02..5726941b 100644
--- a/tests/snapshots/testsuite/proposals/gc/struct.wast/0.print
+++ b/tests/snapshots/testsuite/proposals/gc/struct.wast/0.print
@@ -3,8 +3,8 @@
   (type (;1;) (struct))
   (type (;2;) (struct (field i8)))
   (type (;3;) (struct (field i8) (field i8) (field i8) (field i8)))
-  (type (;4;) (struct (field i32) (field i32)))
+  (type (;4;) (struct (field $x1 i32) (field $y1 i32)))
   (type (;5;) (struct (field i8) (field i16) (field i32) (field i64) (field f32) (field f64) (field anyref) (field funcref) (field (ref 0)) (field (ref null 1))))
   (type (;6;) (struct (field i32) (field i64) (field i8) (field i31ref) (field anyref)))
-  (type (;7;) (struct (field i32) (field f32) (field f64) (field i32)))
+  (type (;7;) (struct (field $x2 i32) (field f32) (field f64) (field $y2 i32)))
 )
diff --git a/tests/snapshots/testsuite/proposals/gc/struct.wast/5.print b/tests/snapshots/testsuite/proposals/gc/struct.wast/5.print
index 4ba020cd..79c4911e 100644
--- a/tests/snapshots/testsuite/proposals/gc/struct.wast/5.print
+++ b/tests/snapshots/testsuite/proposals/gc/struct.wast/5.print
@@ -1,20 +1,20 @@
 (module
-  (type (;0;) (struct (field i32)))
-  (type $t1 (;1;) (struct (field i32) (field f32)))
-  (type $t2 (;2;) (struct (field i32) (field i32) (field i64)))
+  (type (;0;) (struct (field $x i32)))
+  (type $t1 (;1;) (struct (field i32) (field $x f32)))
+  (type $t2 (;2;) (struct (field i32) (field i32) (field $x i64)))
   (type (;3;) (func (param (ref 0)) (result i32)))
   (type (;4;) (func (param (ref $t1)) (result f32)))
   (type (;5;) (func (param (ref $t2)) (result i64)))
   (func (;0;) (type 3) (param (ref 0)) (result i32)
     local.get 0
-    struct.get 0 0
+    struct.get 0 $x
   )
   (func (;1;) (type 4) (param (ref $t1)) (result f32)
     local.get 0
-    struct.get $t1 1
+    struct.get $t1 $x
   )
   (func (;2;) (type 5) (param (ref $t2)) (result i64)
     local.get 0
-    struct.get $t2 2
+    struct.get $t2 $x
   )
 )
diff --git a/tests/snapshots/testsuite/proposals/gc/struct.wast/7.print b/tests/snapshots/testsuite/proposals/gc/struct.wast/7.print
index 51e4cbbb..64caae26 100644
--- a/tests/snapshots/testsuite/proposals/gc/struct.wast/7.print
+++ b/tests/snapshots/testsuite/proposals/gc/struct.wast/7.print
@@ -1,5 +1,5 @@
 (module
-  (type $vec (;0;) (struct (field f32) (field (mut f32)) (field f32)))
+  (type $vec (;0;) (struct (field f32) (field $y (mut f32)) (field $z f32)))
   (type (;1;) (func (result anyref)))
   (type (;2;) (func (param (ref $vec)) (result f32)))
   (type (;3;) (func (result f32)))
@@ -26,7 +26,7 @@
   )
   (func $get_0_y (;5;) (type 2) (param $v (ref $vec)) (result f32)
     local.get $v
-    struct.get $vec 1
+    struct.get $vec $y
   )
   (func (;6;) (type 3) (result f32)
     struct.new_default $vec
@@ -34,7 +34,7 @@
   )
   (func $get_vec_y (;7;) (type 2) (param $v (ref $vec)) (result f32)
     local.get $v
-    struct.get $vec 1
+    struct.get $vec $y
   )
   (func (;8;) (type 3) (result f32)
     struct.new_default $vec
@@ -43,9 +43,9 @@
   (func $set_get_y (;9;) (type 4) (param $v (ref $vec)) (param $y f32) (result f32)
     local.get $v
     local.get $y
-    struct.set $vec 1
+    struct.set $vec $y
     local.get $v
-    struct.get $vec 1
+    struct.get $vec $y
   )
   (func (;10;) (type 5) (param $y f32) (result f32)
     struct.new_default $vec
@@ -55,9 +55,9 @@
   (func $set_get_1 (;11;) (type 4) (param $v (ref $vec)) (param $y f32) (result f32)
     local.get $v
     local.get $y
-    struct.set $vec 1
+    struct.set $vec $y
     local.get $v
-    struct.get $vec 1
+    struct.get $vec $y
   )
   (func (;12;) (type 5) (param $y f32) (result f32)
     struct.new_default $vec