///|
fn gen_valid_is_simplify_locals_family_profile_config(
config : GenValidConfig,
) -> Bool {
config == GenValidConfig::for_profile(SimplifyLocalsFamilyCoverageProfile)
}
///|
fn gen_valid_simplify_locals_profile_family_ids(
profile : GenValidProfile,
) -> Array[Int32] {
match profile {
SimplifyLocalsFamilyCoverageProfile => {
let ids : Array[Int32] = []
for id = 1; id <= 35; id = id + 1 {
ids.push(id)
}
ids
}
_ => []
}
}
///|
fn gen_valid_simplify_locals_family_profile_config() -> GenValidConfig {
let base = GenValidConfig::binaryen_oracle_coverage_forced_default()
GenValidConfig::{
..base,
max_type_defs: 8,
max_imports: 0,
max_defined_funcs: 16,
max_tables: 1,
max_mems: 1,
max_globals: 1,
max_tags: 1,
max_elems: 0,
max_datas: 0,
max_params: 2,
max_results: 1,
max_locals: 8,
max_body_statements: 128,
max_body_depth: 8,
features: GenValidFeatureToggles::{
..base.features,
allow_imports: false,
allow_tables: true,
allow_mems: true,
allow_globals: true,
allow_tags: true,
allow_calls: true,
allow_call_indirect: false,
allow_tail_calls: false,
allow_branch_heavy_control: true,
allow_ref_types: true,
allow_v128: false,
allow_relaxed_simd: false,
allow_atomics: false,
allow_shared_memories: false,
allow_memory64: false,
allow_subtyping_topology: false,
allow_name_custom_sections: false,
allow_typed_body_generator: false,
allow_ssa_nomerge_body_generator: false,
},
}
}
///|
fn gen_valid_simplify_locals_family_i32(
seed : UInt64,
salt : UInt64,
) -> @lib.I32 {
I32(((seed ^ (salt * 0x9e3779b97f4a7c15UL)) % 100000UL + 1UL).to_int())
}
///|
fn gen_valid_simplify_locals_func_type(
params : Array[ValType],
results : Array[ValType],
) -> RecType {
RecType::new(SubType::comp_type(CompType::func(params, results)))
}
///|
fn gen_valid_simplify_locals_family_profile_module(seed : UInt64) -> Module {
let void_type = TypeIdx::new(0U)
let i32_result_type = TypeIdx::new(1U)
let i32_param_type = TypeIdx::new(2U)
let ref_param_type = TypeIdx::new(3U)
let helper_idx = FuncIdx::new(0U)
let i32_local = ValType::i32()
let funcref = ValType::funcref()
let externref = ValType::externref()
let memarg = MemArg::new(2U, None, 0UL)
let c0 = gen_valid_simplify_locals_family_i32(seed, 1UL)
let c1 = gen_valid_simplify_locals_family_i32(seed, 2UL)
let c2 = gen_valid_simplify_locals_family_i32(seed, 3UL)
let c3 = gen_valid_simplify_locals_family_i32(seed, 4UL)
let c4 = gen_valid_simplify_locals_family_i32(seed, 5UL)
let c5 = gen_valid_simplify_locals_family_i32(seed, 6UL)
let helper = Func::new(
Locals::empty(),
Expr::new([Instruction::i32_const(c0)]),
)
// SL-01..03, SL-07..09, SL-24, and SL-32..33: read counting,
// first/later-cycle sinking, tee/drop cleanup, overwrite preservation,
// deferred cycles, and final dead-set cleanup.
let local_traffic = Func::new(
Locals::from_types([i32_local, i32_local, i32_local]),
Expr::new([
Instruction::i32_const(c1),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::i32_const(c2),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::i32_const(c3),
Instruction::local_tee(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::call(helper_idx),
Instruction::local_set(LocalIdx::new(2U)),
Instruction::call(helper_idx),
Instruction::local_set(LocalIdx::new(2U)),
Instruction::local_get(LocalIdx::new(2U)),
Instruction::drop(),
Instruction::i32_const(c4),
Instruction::local_set(LocalIdx::new(1U)),
]),
)
// SL-04..05: nonesting copy retargeting and parent-position legality.
let flat_parent = Func::new(
Locals::from_types([i32_local, i32_local]),
Expr::new([
Instruction::i32_const(c1),
Instruction::i32_const(c2),
Instruction::i32_add(),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::i32_const(c3),
Instruction::i32_const(c4),
Instruction::i32_add(),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
]),
)
// SL-13..17 and SL-23: named-block exit collection, unsupported-target
// boundary, block-result lifting, br_if ordering, and structure-created tee.
let block_result = Func::new(
Locals::from_types([i32_local]),
Expr::new([
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::i32_const(c1),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::br_if(LabelIdx::new(0U)),
Instruction::i32_const(c2),
Instruction::local_set(LocalIdx::new(1U)),
]),
),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::ref_null(HeapType::abs(AbsHeapType::extern_())),
Instruction::br_on_null(LabelIdx::new(0U)),
Instruction::drop(),
]),
),
]),
)
// SL-18..21 and SL-23: two-arm, one-reachable-arm, one-arm speculative,
// defaultability, and enlargement-equivalent result-slot behavior.
let if_results = Func::new(
Locals::from_types([i32_local]),
Expr::new([
Instruction::local_get(LocalIdx::new(0U)),
Instruction::if_(
BlockType::void_(),
[Instruction::i32_const(c1), Instruction::local_set(LocalIdx::new(1U))],
Some([
Instruction::i32_const(c2),
Instruction::local_set(LocalIdx::new(1U)),
]),
),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::if_(
BlockType::void_(),
[Instruction::return_()],
Some([
Instruction::i32_const(c3),
Instruction::local_set(LocalIdx::new(1U)),
]),
),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::if_(
BlockType::void_(),
[Instruction::i32_const(c4), Instruction::local_set(LocalIdx::new(1U))],
None,
),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
]),
)
// SL-22..23: narrow loop-result lifting.
let loop_result = Func::new(
Locals::from_types([i32_local]),
Expr::new([
Instruction::loop_(
BlockType::void_(),
Expr::new([
Instruction::i32_const(c5),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::nop(),
]),
),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
]),
)
// SL-25..31: equivalence classes, transparent block fallthrough,
// equivalent-set removal policy, representative selection, and adjacent
// block connectivity.
let equivalent_sets = Func::new(
Locals::from_types([i32_local, i32_local, i32_local]),
Expr::new([
Instruction::local_get(LocalIdx::new(0U)),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::local_get(LocalIdx::new(1U)),
Instruction::local_set(LocalIdx::new(2U)),
]),
),
Instruction::local_get(LocalIdx::new(2U)),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
]),
)
// SL-10 and the local/global/memory/table/call legality domains.
let effect_order = Func::new(
Locals::from_types([i32_local, funcref]),
Expr::new([
Instruction::global_get(GlobalIdx::new(0U)),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::i32_const(c1),
Instruction::global_set(GlobalIdx::new(0U)),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::i32_const(I32(0)),
Instruction::i32_load(memarg),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::i32_const(I32(4)),
Instruction::i32_load(memarg),
Instruction::drop(),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::i32_const(I32(0)),
Instruction::i32_load(memarg),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(c2),
Instruction::i32_store(memarg),
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
Instruction::i32_const(I32(0)),
Instruction::table_get(TableIdx::new(0U)),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::nop(),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
Instruction::i32_const(I32(0)),
Instruction::ref_null(HeapType::abs(AbsHeapType::func())),
Instruction::table_set(TableIdx::new(0U)),
Instruction::call(helper_idx),
Instruction::drop(),
]),
)
// SL-09, SL-11..12: may-throw try_table boundary and fresh nonlinear state.
let eh_boundaries = Func::new(
Locals::from_types([i32_local, i32_local]),
Expr::new([
Instruction::call(helper_idx),
Instruction::local_set(LocalIdx::new(0U)),
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::try_table(
BlockType::void_(),
[Catch::new(TagIdx::new(0U), LabelIdx::new(0U))],
Expr::new([
Instruction::local_get(LocalIdx::new(0U)),
Instruction::drop(),
]),
),
]),
),
Instruction::i32_const(c3),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::try_table(
BlockType::void_(),
[Catch::new(TagIdx::new(0U), LabelIdx::new(0U))],
Expr::new([
Instruction::local_get(LocalIdx::new(1U)),
Instruction::drop(),
]),
),
]),
),
]),
)
// SL-06, SL-21, SL-30, SL-34..35: refined replacement, defaultability,
// representative type preference, refinalization, and nondefaultable fixups.
let refined_types = Func::new(
Locals::from_types([externref]),
Expr::new([
Instruction::local_get(LocalIdx::new(0U)),
Instruction::ref_as_non_null(),
Instruction::local_set(LocalIdx::new(1U)),
Instruction::local_get(LocalIdx::new(1U)),
Instruction::ref_as_non_null(),
Instruction::drop(),
]),
)
let func_types = [
i32_result_type, void_type, void_type, i32_param_type, i32_param_type, void_type,
i32_param_type, void_type, void_type, ref_param_type,
]
Module::new()
.with_type_sec(
TypeSec::new([
gen_valid_simplify_locals_func_type([], []),
gen_valid_simplify_locals_func_type([], [i32_local]),
gen_valid_simplify_locals_func_type([i32_local], []),
gen_valid_simplify_locals_func_type([externref], []),
]),
)
.with_func_sec(FuncSec::new(func_types))
.with_table_sec(
TableSec::new([
Table::new(
TableType::new(
RefType::new(true, HeapType::abs(AbsHeapType::func())),
Limits::i32(1U, Some(1U)),
),
None,
),
]),
)
.with_mem_sec(MemSec::new([MemType::new(Limits::i32(1U, None))]))
.with_global_sec(
GlobalSec::new([
Global::new(
GlobalType::new(i32_local, true),
Expr::new([Instruction::i32_const(I32(0))]),
),
]),
)
.with_tag_sec(TagSec::new([TagType::new(void_type)]))
.with_code_sec(
CodeSec::new([
helper, local_traffic, flat_parent, block_result, if_results, loop_result,
equivalent_sets, effect_order, eh_boundaries, refined_types,
]),
)
}