-
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 all commits
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 { | ||||||||||||||||||||||||||||||
Comment on lines
+259
to
+261
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to have a single-sentence comment for readers here describing what this code is doing, so that they don't have to scrutinize it to figure out what is going on. Something like
|
||||||||||||||||||||||||||||||
let concrete = STRUCT_BASE + i; | ||||||||||||||||||||||||||||||
let ty_idx = typed_ft_base + i; // | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty comment at the end of line? |
||||||||||||||||||||||||||||||
let name = format!("take_struct_{concrete}"); | ||||||||||||||||||||||||||||||
typed_names.push(name); | ||||||||||||||||||||||||||||||
imports.import( | ||||||||||||||||||||||||||||||
"", | ||||||||||||||||||||||||||||||
typed_names.last().unwrap().as_str(), | ||||||||||||||||||||||||||||||
EntityType::Function(ty_idx), | ||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||
Comment on lines
+264
to
+270
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can avoid the wonky
Suggested change
|
||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// Define our table. | ||||||||||||||||||||||||||||||
let mut tables = TableSection::new(); | ||||||||||||||||||||||||||||||
|
@@ -258,7 +298,8 @@ impl TableOps { | |||||||||||||||||||||||||||||
functions.function(1); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
let mut exports = ExportSection::new(); | ||||||||||||||||||||||||||||||
exports.export("run", ExportKind::Func, 3); | ||||||||||||||||||||||||||||||
let imported_fn_count: u32 = 4 + struct_count; | ||||||||||||||||||||||||||||||
exports.export("run", ExportKind::Func, imported_fn_count); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// Give ourselves one scratch local that we can use in various `TableOp` | ||||||||||||||||||||||||||||||
// implementations. | ||||||||||||||||||||||||||||||
|
@@ -600,6 +641,8 @@ define_table_ops! { | |||||||||||||||||||||||||||||
LocalSet(local_index: |ops| ops.num_params => u32) : 1 => 0, | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
StructNew(type_index: |ops| ops.max_types => u32) : 0 => 0, | ||||||||||||||||||||||||||||||
TakeStructCall(type_index: |ops| ops.max_types => u32) : 0 => 0, | ||||||||||||||||||||||||||||||
TakeTypedStructCall(type_index: |ops| ops.max_types => u32) : 0 => 0, | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Drop : 1 => 0, | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
@@ -611,6 +654,7 @@ impl TableOp { | |||||||||||||||||||||||||||||
let gc_func_idx = 0; | ||||||||||||||||||||||||||||||
let take_refs_func_idx = 1; | ||||||||||||||||||||||||||||||
let make_refs_func_idx = 2; | ||||||||||||||||||||||||||||||
let take_structref_idx = 3; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
match self { | ||||||||||||||||||||||||||||||
Self::Gc() => { | ||||||||||||||||||||||||||||||
|
@@ -651,8 +695,18 @@ impl TableOp { | |||||||||||||||||||||||||||||
func.instruction(&Instruction::RefNull(wasm_encoder::HeapType::EXTERN)); | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Self::StructNew(x) => { | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::StructNew(x + 4)); | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::Drop); | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::StructNew(x + 5)); | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::Call(take_structref_idx)); | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Self::TakeStructCall(x) => { | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::StructNew(x + 5)); | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::Call(take_structref_idx)); | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Self::TakeTypedStructCall(x) => { | ||||||||||||||||||||||||||||||
let s = STRUCT_BASE + x; | ||||||||||||||||||||||||||||||
let f = TYPED_FN_BASE + x; | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::StructNew(s)); | ||||||||||||||||||||||||||||||
func.instruction(&Instruction::Call(f)); | ||||||||||||||||||||||||||||||
Comment on lines
+698
to
+709
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I agree! |
||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
@@ -726,7 +780,7 @@ mod tests { | |||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
let mut session = mutatis::Session::new(); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
for _ in 0..5 { | ||||||||||||||||||||||||||||||
for _ in 0..2048 { | ||||||||||||||||||||||||||||||
session.mutate(&mut res)?; | ||||||||||||||||||||||||||||||
let wasm = res.to_wasm_binary(); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
@@ -738,7 +792,6 @@ mod tests { | |||||||||||||||||||||||||||||
let wat = wasmprinter::print_bytes(&wasm).expect("[-] Failed .print_bytes(&wasm)."); | ||||||||||||||||||||||||||||||
let result = validator.validate_all(&wasm); | ||||||||||||||||||||||||||||||
log::debug!("{wat}"); | ||||||||||||||||||||||||||||||
println!("{wat}"); | ||||||||||||||||||||||||||||||
assert!( | ||||||||||||||||||||||||||||||
result.is_ok(), | ||||||||||||||||||||||||||||||
"\n[-] Invalid wat: {}\n\t\t==== Failed Wat ====\n{}", | ||||||||||||||||||||||||||||||
|
@@ -788,37 +841,59 @@ mod tests { | |||||||||||||||||||||||||||||
(type (;1;) (func (param externref externref))) | ||||||||||||||||||||||||||||||
(type (;2;) (func (param externref externref externref))) | ||||||||||||||||||||||||||||||
(type (;3;) (func (result externref externref externref))) | ||||||||||||||||||||||||||||||
(type (;4;) (func (param (ref any)))) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;4;) (struct)) | ||||||||||||||||||||||||||||||
(type (;5;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(rec) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;5;) (struct)) | ||||||||||||||||||||||||||||||
(type (;6;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;6;) (struct)) | ||||||||||||||||||||||||||||||
(type (;7;) (struct)) | ||||||||||||||||||||||||||||||
(type (;8;) (struct)) | ||||||||||||||||||||||||||||||
(type (;9;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;9;) (struct)) | ||||||||||||||||||||||||||||||
(type (;10;) (struct)) | ||||||||||||||||||||||||||||||
(type (;11;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;11;) (struct)) | ||||||||||||||||||||||||||||||
(type (;12;) (struct)) | ||||||||||||||||||||||||||||||
(type (;13;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(rec | ||||||||||||||||||||||||||||||
(type (;13;) (struct)) | ||||||||||||||||||||||||||||||
(type (;14;) (struct)) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
(type (;15;) (func (param (ref 5)))) | ||||||||||||||||||||||||||||||
(type (;16;) (func (param (ref 6)))) | ||||||||||||||||||||||||||||||
(type (;17;) (func (param (ref 7)))) | ||||||||||||||||||||||||||||||
(type (;18;) (func (param (ref 8)))) | ||||||||||||||||||||||||||||||
(type (;19;) (func (param (ref 9)))) | ||||||||||||||||||||||||||||||
(type (;20;) (func (param (ref 10)))) | ||||||||||||||||||||||||||||||
(type (;21;) (func (param (ref 11)))) | ||||||||||||||||||||||||||||||
(type (;22;) (func (param (ref 12)))) | ||||||||||||||||||||||||||||||
(type (;23;) (func (param (ref 13)))) | ||||||||||||||||||||||||||||||
(type (;24;) (func (param (ref 14)))) | ||||||||||||||||||||||||||||||
(import "" "gc" (func (;0;) (type 0))) | ||||||||||||||||||||||||||||||
(import "" "take_refs" (func (;1;) (type 2))) | ||||||||||||||||||||||||||||||
(import "" "make_refs" (func (;2;) (type 3))) | ||||||||||||||||||||||||||||||
(import "" "take_struct" (func (;3;) (type 4))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_5" (func (;4;) (type 15))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_6" (func (;5;) (type 16))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_7" (func (;6;) (type 17))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_8" (func (;7;) (type 18))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_9" (func (;8;) (type 19))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_10" (func (;9;) (type 20))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_11" (func (;10;) (type 21))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_12" (func (;11;) (type 22))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_13" (func (;12;) (type 23))) | ||||||||||||||||||||||||||||||
(import "" "take_struct_14" (func (;13;) (type 24))) | ||||||||||||||||||||||||||||||
(table (;0;) 5 externref) | ||||||||||||||||||||||||||||||
(global (;0;) (mut externref) ref.null extern) | ||||||||||||||||||||||||||||||
(global (;1;) (mut externref) ref.null extern) | ||||||||||||||||||||||||||||||
(export "run" (func 3)) | ||||||||||||||||||||||||||||||
(func (;3;) (type 1) (param externref externref) | ||||||||||||||||||||||||||||||
(export "run" (func 14)) | ||||||||||||||||||||||||||||||
(func (;14;) (type 1) (param externref externref) | ||||||||||||||||||||||||||||||
(local externref) | ||||||||||||||||||||||||||||||
loop ;; label = @1 | ||||||||||||||||||||||||||||||
ref.null extern | ||||||||||||||||||||||||||||||
|
@@ -828,8 +903,8 @@ mod tests { | |||||||||||||||||||||||||||||
local.get 0 | ||||||||||||||||||||||||||||||
global.set 0 | ||||||||||||||||||||||||||||||
global.get 0 | ||||||||||||||||||||||||||||||
struct.new 4 | ||||||||||||||||||||||||||||||
drop | ||||||||||||||||||||||||||||||
struct.new 5 | ||||||||||||||||||||||||||||||
call 3 | ||||||||||||||||||||||||||||||
drop | ||||||||||||||||||||||||||||||
drop | ||||||||||||||||||||||||||||||
drop | ||||||||||||||||||||||||||||||
|
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::len
methods 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