-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add generic/typed take_struct imports + ops
#11713
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
faa4512
b83186f
fd2423d
e1d2bd0
0634e51
74b05e4
e77a216
320f01d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,9 @@ const TABLE_SIZE_RANGE: RangeInclusive<u32> = 0..=100; | |||||||||||||||||||||||||||||
| const MAX_REC_GROUPS_RANGE: RangeInclusive<u32> = 0..=10; | ||||||||||||||||||||||||||||||
| const MAX_OPS: usize = 100; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const STRUCT_BASE: u32 = 5; | ||||||||||||||||||||||||||||||
| const TYPED_FN_BASE: u32 = 4; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /// RecGroup ID struct definition. | ||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||
| Debug, Copy, Clone, Eq, PartialOrd, PartialEq, Ord, Hash, Default, Serialize, Deserialize, | ||||||||||||||||||||||||||||||
|
|
@@ -191,6 +194,14 @@ impl TableOps { | |||||||||||||||||||||||||||||
| vec![ValType::EXTERNREF, ValType::EXTERNREF, ValType::EXTERNREF], | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| types.ty().function( | ||||||||||||||||||||||||||||||
| vec![ValType::Ref(RefType { | ||||||||||||||||||||||||||||||
| nullable: false, | ||||||||||||||||||||||||||||||
| heap_type: wasm_encoder::HeapType::ANY, | ||||||||||||||||||||||||||||||
| })], | ||||||||||||||||||||||||||||||
| vec![], | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let mut rec_groups: BTreeMap<RecGroupId, Vec<TypeId>> = self | ||||||||||||||||||||||||||||||
| .types | ||||||||||||||||||||||||||||||
| .rec_groups | ||||||||||||||||||||||||||||||
|
|
@@ -219,16 +230,45 @@ impl TableOps { | |||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let mut struct_count: u32 = 0; | ||||||||||||||||||||||||||||||
| for type_ids in rec_groups.values() { | ||||||||||||||||||||||||||||||
| let members: Vec<wasm_encoder::SubType> = type_ids.iter().map(encode_ty_id).collect(); | ||||||||||||||||||||||||||||||
| types.ty().rec(members); | ||||||||||||||||||||||||||||||
| struct_count += type_ids.len() as u32; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let typed_ft_base: u32 = STRUCT_BASE + struct_count; | ||||||||||||||||||||||||||||||
| for i in 0..struct_count { | ||||||||||||||||||||||||||||||
| let concrete = STRUCT_BASE + i; | ||||||||||||||||||||||||||||||
| types.ty().function( | ||||||||||||||||||||||||||||||
| vec![ValType::Ref(RefType { | ||||||||||||||||||||||||||||||
| nullable: false, | ||||||||||||||||||||||||||||||
| heap_type: wasm_encoder::HeapType::Concrete(concrete), | ||||||||||||||||||||||||||||||
| })], | ||||||||||||||||||||||||||||||
| vec![], | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Import the GC function. | ||||||||||||||||||||||||||||||
| let mut imports = ImportSection::new(); | ||||||||||||||||||||||||||||||
| imports.import("", "gc", EntityType::Function(0)); | ||||||||||||||||||||||||||||||
| imports.import("", "take_refs", EntityType::Function(2)); | ||||||||||||||||||||||||||||||
| imports.import("", "make_refs", EntityType::Function(3)); | ||||||||||||||||||||||||||||||
| imports.import("", "take_struct", EntityType::Function(4)); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let mut typed_names: Vec<String> = Vec::new(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| for i in 0..struct_count { | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| let concrete = STRUCT_BASE + i; | ||||||||||||||||||||||||||||||
| let ty_idx = typed_ft_base + i; // | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| let name = format!("take_struct_{concrete}"); | ||||||||||||||||||||||||||||||
| typed_names.push(name); | ||||||||||||||||||||||||||||||
| imports.import( | ||||||||||||||||||||||||||||||
| "", | ||||||||||||||||||||||||||||||
| typed_names.last().unwrap().as_str(), | ||||||||||||||||||||||||||||||
| EntityType::Function(ty_idx), | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| let name = format!("take_struct_{concrete}"); | |
| typed_names.push(name); | |
| imports.import( | |
| "", | |
| typed_names.last().unwrap().as_str(), | |
| EntityType::Function(ty_idx), | |
| ); | |
| let name = format!("take_struct_{concrete}"); | |
| imports.import( | |
| "", | |
| &name, | |
| EntityType::Function(ty_idx), | |
| ); | |
| typed_names.push(name); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned earlier, things get a bit simpler and less brittle if we use the len functions on the sections that define index spaces:
| exports.export("run", ExportKind::Func, imported_fn_count); | |
| let mut functions = FunctionSection::new(); | |
| let mut exports = ExportSection::new(); | |
| // Define the "run" function export. | |
| let run_index = functions.len(); | |
| functions.function(1); | |
| exports.export("run", ExportKind::Func, run_index); |
I think it is worth doing this to avoid adding more opaque <constant> + <count> incantations.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing to change in this PR, but I want to point out that these emitted instruction sequences are not our ideal end state. We want to separate struct.new from various calls and drops and have the existing TableOp::Drop be used to drop struct refs and we want the take_* calls to take a struct ref from the stack, not create a new one to pass to the import. This will require updating the abstract stack representation to track types, however, so it should be left to a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary in this PR, but it would probably be easier/cleaner down the line to switch from constants to using the
wasm_encoder::{Type,Func}Section::lenmethods to keep track of these things, so that we don't need to update these constants every time we unconditionally add a new type/function.https://docs.rs/wasm-encoder/latest/wasm_encoder/struct.TypeSection.html#method.len