Skip to content

Commit

Permalink
[compiler-v2] Enum types in the VM
Browse files Browse the repository at this point in the history
In #13725 support for enums was added to the stackless bytecode IR. This PR extends the Move VM's representation of bytecode ('file format') by struct variants. It also implements

- representation in file format
- serialization/deserialization of file format
- bytecode verifier
- code generation in compiler v2

The runtime semantics (intepreter, runtime types, compatibility checking), as well as certain other features (as marked by #13806 in the code), are not yet implemented by this PR.

On Move bytecode level, there are `5 * 2` new instructions (each instruction has a dual generic version):

```
TestVariant(StructVariantHandleIndex)
	and TestVariantGeneric(StructVariantInstantiationIndex)
PackVariant(StructVariantHandleIndex)
	and PackVariantGeneric(StructVariantInstantiationIndex)
UnpackVariant(StructVariantHandleIndex)
	and UnpackVariantGeneric(StructVariantInstantiationIndex)
ImmBorrowVariantField(VariantFieldHandleIndex)
	and ImmBorrowVariantFieldGeneric(VariantFieldInstantiationIndex)
MutBorrowVariantField(VariantFieldHandleIndex)
	and MutBorrowVariantFieldGeneric(VariantFieldInstantiationIndex)
```

For the indices used in those instructions, 4 new tables have been added to the file format holding the associated data.

There is a lot of boilerplate code to support the new instructions and tables. Some refactoring of existing code has been done to avoid too much copy and paste, specifically in the serializers and in the bytecode verifier.

Apart of passing existing tests, there is a new test in `move-compiler-v2/tests/file-format-generator/struct_variants.move` which shows the disassembeled output of various match expressions. To add negative tests for the bytecode verifier and serializers, we first need a better way to build code from scratch (like a `CompiledModuleBuilder` or similar) which is planned to be done in a followup PR. Unfortunately, `.mvir` files cannot be used for this purpose, as there is no plan to support struct variants in this language right now.
  • Loading branch information
wrwg committed Jun 26, 2024
1 parent 0ecae5c commit da7e31d
Show file tree
Hide file tree
Showing 70 changed files with 4,753 additions and 1,225 deletions.
4 changes: 4 additions & 0 deletions api/types/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ pub trait Bytecode {
.map(|f| self.new_move_struct_field(f))
.collect(),
),
StructFieldInformation::DeclaredVariants(..) => {
// TODO(#13806): implement for struct variants
panic!("enums/struct variants not yet supported by the API")
},
};
let name = self.identifier_at(handle.name).to_owned();
let abilities = handle
Expand Down
4 changes: 4 additions & 0 deletions aptos-move/e2e-move-tests/src/tests/access_path_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ fn access_path_panic() {
],
}),
}],
struct_variant_handles: vec![],
struct_variant_instantiations: vec![],
variant_field_handles: vec![],
variant_field_instantiations: vec![],
};

let mut module_bytes = vec![];
Expand Down
42 changes: 42 additions & 0 deletions third_party/move/move-binary-format/src/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ pub trait ModuleAccess: Sync {
handle
}

fn variant_field_handle_at(&self, idx: VariantFieldHandleIndex) -> &VariantFieldHandle {
let handle = &self.as_module().variant_field_handles[idx.into_index()];
debug_assert!(handle.owner.into_index() < self.as_module().struct_variant_handles.len()); // invariant
handle
}

fn struct_variant_handle_at(&self, idx: StructVariantHandleIndex) -> &StructVariantHandle {
let handle = &self.as_module().struct_variant_handles[idx.into_index()];
debug_assert!(handle.struct_index.into_index() < self.as_module().struct_defs.len()); // invariant
handle
}

fn struct_instantiation_at(&self, idx: StructDefInstantiationIndex) -> &StructDefInstantiation {
&self.as_module().struct_def_instantiations[idx.into_index()]
}
Expand All @@ -78,6 +90,20 @@ pub trait ModuleAccess: Sync {
&self.as_module().field_instantiations[idx.into_index()]
}

fn variant_field_instantiation_at(
&self,
idx: VariantFieldInstantiationIndex,
) -> &VariantFieldInstantiation {
&self.as_module().variant_field_instantiations[idx.into_index()]
}

fn struct_variant_instantiation_at(
&self,
idx: StructVariantInstantiationIndex,
) -> &StructVariantInstantiation {
&self.as_module().struct_variant_instantiations[idx.into_index()]
}

fn signature_at(&self, idx: SignatureIndex) -> &Signature {
&self.as_module().signatures[idx.into_index()]
}
Expand Down Expand Up @@ -124,6 +150,14 @@ pub trait ModuleAccess: Sync {
&self.as_module().field_handles
}

fn variant_field_handles(&self) -> &[VariantFieldHandle] {
&self.as_module().variant_field_handles
}

Check warning on line 155 in third_party/move/move-binary-format/src/access.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/access.rs#L153-L155

Added lines #L153 - L155 were not covered by tests

fn struct_variant_handles(&self) -> &[StructVariantHandle] {
&self.as_module().struct_variant_handles
}

Check warning on line 159 in third_party/move/move-binary-format/src/access.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/access.rs#L157-L159

Added lines #L157 - L159 were not covered by tests

fn struct_instantiations(&self) -> &[StructDefInstantiation] {
&self.as_module().struct_def_instantiations
}
Expand All @@ -136,6 +170,14 @@ pub trait ModuleAccess: Sync {
&self.as_module().field_instantiations
}

fn variant_field_instantiations(&self) -> &[VariantFieldInstantiation] {
&self.as_module().variant_field_instantiations
}

Check warning on line 175 in third_party/move/move-binary-format/src/access.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/access.rs#L173-L175

Added lines #L173 - L175 were not covered by tests

fn struct_variant_instantiations(&self) -> &[StructVariantInstantiation] {
&self.as_module().struct_variant_instantiations
}

Check warning on line 179 in third_party/move/move-binary-format/src/access.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/access.rs#L177-L179

Added lines #L177 - L179 were not covered by tests

fn signatures(&self) -> &[Signature] {
&self.as_module().signatures
}
Expand Down
80 changes: 79 additions & 1 deletion third_party/move/move-binary-format/src/binary_views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use crate::{
FunctionInstantiation, FunctionInstantiationIndex, IdentifierIndex, ModuleHandle,
ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, StructDefInstantiation,
StructDefInstantiationIndex, StructDefinition, StructDefinitionIndex, StructHandle,
StructHandleIndex,
StructHandleIndex, StructVariantHandle, StructVariantHandleIndex,
StructVariantInstantiation, StructVariantInstantiationIndex, VariantFieldHandle,
VariantFieldHandleIndex, VariantFieldInstantiation, VariantFieldInstantiationIndex,
},
CompiledModule,
};
Expand Down Expand Up @@ -157,6 +159,13 @@ impl<'a> BinaryIndexedView<'a> {
}
}

pub fn variant_field_handles(&self) -> Option<&[VariantFieldHandle]> {
match self {
BinaryIndexedView::Module(module) => Some(&module.variant_field_handles),
BinaryIndexedView::Script(_) => None,
}
}

pub fn field_handle_at(&self, idx: FieldHandleIndex) -> PartialVMResult<&FieldHandle> {
match self {
BinaryIndexedView::Module(module) => Ok(module.field_handle_at(idx)),
Expand All @@ -166,6 +175,42 @@ impl<'a> BinaryIndexedView<'a> {
}
}

pub fn variant_field_handle_at(
&self,
idx: VariantFieldHandleIndex,
) -> PartialVMResult<&VariantFieldHandle> {
match self {
BinaryIndexedView::Module(module) => Ok(module.variant_field_handle_at(idx)),
BinaryIndexedView::Script(_) => {
Err(PartialVMError::new(StatusCode::INVALID_OPERATION_IN_SCRIPT))

Check warning on line 185 in third_party/move/move-binary-format/src/binary_views.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/binary_views.rs#L185

Added line #L185 was not covered by tests
},
}
}

pub fn struct_variant_handle_at(
&self,
idx: StructVariantHandleIndex,
) -> PartialVMResult<&StructVariantHandle> {
match self {
BinaryIndexedView::Module(module) => Ok(module.struct_variant_handle_at(idx)),
BinaryIndexedView::Script(_) => {
Err(PartialVMError::new(StatusCode::INVALID_OPERATION_IN_SCRIPT))

Check warning on line 197 in third_party/move/move-binary-format/src/binary_views.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/binary_views.rs#L197

Added line #L197 was not covered by tests
},
}
}

pub fn struct_variant_instantiation_at(
&self,
idx: StructVariantInstantiationIndex,
) -> PartialVMResult<&StructVariantInstantiation> {
match self {
BinaryIndexedView::Module(module) => Ok(module.struct_variant_instantiation_at(idx)),
BinaryIndexedView::Script(_) => {
Err(PartialVMError::new(StatusCode::INVALID_OPERATION_IN_SCRIPT))

Check warning on line 209 in third_party/move/move-binary-format/src/binary_views.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/binary_views.rs#L209

Added line #L209 was not covered by tests
},
}
}

pub fn friend_decls(&self) -> Option<&[ModuleHandle]> {
match self {
BinaryIndexedView::Module(module) => Some(module.friend_decls()),
Expand Down Expand Up @@ -199,6 +244,13 @@ impl<'a> BinaryIndexedView<'a> {
}
}

pub fn variant_field_instantiations(&self) -> Option<&[VariantFieldInstantiation]> {
match self {
BinaryIndexedView::Module(module) => Some(&module.variant_field_instantiations),
BinaryIndexedView::Script(_) => None,
}
}

pub fn field_instantiation_at(
&self,
idx: FieldInstantiationIndex,
Expand All @@ -211,6 +263,18 @@ impl<'a> BinaryIndexedView<'a> {
}
}

pub fn variant_field_instantiation_at(
&self,
idx: VariantFieldInstantiationIndex,
) -> PartialVMResult<&VariantFieldInstantiation> {
match self {
BinaryIndexedView::Module(module) => Ok(module.variant_field_instantiation_at(idx)),
BinaryIndexedView::Script(_) => {
Err(PartialVMError::new(StatusCode::INVALID_OPERATION_IN_SCRIPT))

Check warning on line 273 in third_party/move/move-binary-format/src/binary_views.rs

View check run for this annotation

Codecov / codecov/patch

third_party/move/move-binary-format/src/binary_views.rs#L273

Added line #L273 was not covered by tests
},
}
}

pub fn struct_defs(&self) -> Option<&[StructDefinition]> {
match self {
BinaryIndexedView::Module(module) => Some(module.struct_defs()),
Expand All @@ -227,6 +291,20 @@ impl<'a> BinaryIndexedView<'a> {
}
}

pub fn struct_variant_handles(&self) -> Option<&[StructVariantHandle]> {
match self {
BinaryIndexedView::Module(module) => Some(&module.struct_variant_handles),
BinaryIndexedView::Script(_) => None,
}
}

pub fn struct_variant_instantiations(&self) -> Option<&[StructVariantInstantiation]> {
match self {
BinaryIndexedView::Module(module) => Some(&module.struct_variant_instantiations),
BinaryIndexedView::Script(_) => None,
}
}

pub fn function_defs(&self) -> Option<&[FunctionDefinition]> {
match self {
BinaryIndexedView::Module(module) => Some(module.function_defs()),
Expand Down
Loading

0 comments on commit da7e31d

Please sign in to comment.