///|
fn gen_valid_msf_profile_config(profile : GenValidProfile) -> GenValidConfig {
if profile == MergeSimilarFunctionsRecordCopyProfile {
return gen_valid_msf_record_copy_config()
}
let base = GenValidConfig::binaryen_oracle_coverage_forced_default()
let family_id = match profile {
MergeSimilarFunctionsLiteralsProfile => 1
MergeSimilarFunctionsRepeatedDiffProfile => 2
MergeSimilarFunctionsLocalsProfile => 3
MergeSimilarFunctionsNestedProfile => 4
MergeSimilarFunctionsCallTargetsProfile => 5
MergeSimilarFunctionsTailCallsProfile => 6
MergeSimilarFunctionsExactDuplicatesProfile => 7
MergeSimilarFunctionsDuplicateTypesProfile => 8
_ => 1
}
GenValidConfig::{
..base,
max_type_defs: 4,
max_imports: 0,
max_defined_funcs: 10,
max_tables: 0,
max_mems: 0,
max_globals: 0,
max_tags: 0,
max_elems: 2,
max_datas: 0,
max_params: 2,
max_results: 1,
max_locals: 4,
max_body_statements: 160 + family_id,
max_body_depth: 8,
}
}
///|
fn gen_valid_is_msf_profile_config(config : GenValidConfig) -> Bool {
config == gen_valid_msf_record_copy_config() ||
config == gen_valid_msf_profile_config(MergeSimilarFunctionsLiteralsProfile) ||
config ==
gen_valid_msf_profile_config(MergeSimilarFunctionsRepeatedDiffProfile) ||
config ==
gen_valid_msf_profile_config(MergeSimilarFunctionsExactDuplicatesProfile) ||
config ==
gen_valid_msf_profile_config(MergeSimilarFunctionsDuplicateTypesProfile) ||
config == gen_valid_msf_profile_config(MergeSimilarFunctionsLocalsProfile) ||
config == gen_valid_msf_profile_config(MergeSimilarFunctionsNestedProfile) ||
config ==
gen_valid_msf_profile_config(MergeSimilarFunctionsCallTargetsProfile) ||
config == gen_valid_msf_profile_config(MergeSimilarFunctionsTailCallsProfile)
}
///|
fn gen_valid_msf_profile_kind(config : GenValidConfig) -> GenValidProfile {
for
profile in [
MergeSimilarFunctionsLiteralsProfile,
MergeSimilarFunctionsRepeatedDiffProfile,
MergeSimilarFunctionsExactDuplicatesProfile,
MergeSimilarFunctionsDuplicateTypesProfile,
MergeSimilarFunctionsLocalsProfile,
MergeSimilarFunctionsNestedProfile,
MergeSimilarFunctionsCallTargetsProfile,
MergeSimilarFunctionsTailCallsProfile,
MergeSimilarFunctionsRecordCopyProfile,
] {
if config == gen_valid_msf_profile_config(profile) {
return profile
}
}
MergeSimilarFunctionsLiteralsProfile
}
///|
pub fn gen_valid_msf_profile_case_label(
profile : GenValidProfile,
seed : UInt64,
) -> String? {
let class_size = 2 + (seed % 4UL).to_int()
let suffix = "class-\{class_size}"
match profile {
MergeSimilarFunctionsLiteralsProfile => Some("msf:literals:\{suffix}")
MergeSimilarFunctionsRepeatedDiffProfile =>
Some("msf:repeated-diff-vector:\{suffix}")
MergeSimilarFunctionsExactDuplicatesProfile =>
Some("msf:exact-duplicates:\{suffix}")
MergeSimilarFunctionsDuplicateTypesProfile =>
Some("msf:duplicate-types:\{suffix}")
MergeSimilarFunctionsLocalsProfile => Some("msf:local-shift:\{suffix}")
MergeSimilarFunctionsNestedProfile => Some("msf:nested-control:\{suffix}")
MergeSimilarFunctionsCallTargetsProfile =>
Some("msf:call-targets:\{suffix}")
MergeSimilarFunctionsTailCallsProfile =>
Some("msf:tail-call-targets:\{suffix}")
MergeSimilarFunctionsRecordCopyProfile =>
Some(
"msf:record-copy:fields-\{12 + (seed % 21UL).to_int()}:arms-\{8 + (seed % 5UL).to_int()}",
)
_ => None
}
}
///|
fn gen_valid_msf_nops(count : Int32) -> Array[Instruction] {
let out : Array[Instruction] = []
for idx = 0; idx < count; idx = idx + 1 {
out.push(Instruction::i32_const(I32(1000 + idx)))
out.push(Instruction::drop())
}
out
}
///|
fn gen_valid_msf_i32_func_type(params : Array[ValType]) -> RecType {
RecType::new(SubType::comp_type(CompType::func(params, [ValType::i32()])))
}
///|
fn gen_valid_msf_literal_value(
seed : UInt64,
ordinal : Int32,
lane : Int32,
) -> Int32 {
let mixed = seed ^
((ordinal + 1).to_uint64() * 0x9e3779b97f4a7c15UL) ^
((lane + 1).to_uint64() * 0xbf58476d1ce4e5b9UL)
1 + (mixed % 1000003UL).to_int()
}
///|
fn gen_valid_msf_literal_module(seed : UInt64) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let nop_count = 16 + ((seed >> 3) % 9UL).to_int()
let diff_count = 1 + ((seed >> 7) % 4UL).to_int()
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let body = gen_valid_msf_nops(nop_count)
for lane = 0; lane < diff_count - 1; lane = lane + 1 {
body.push(
Instruction::i32_const(
I32(gen_valid_msf_literal_value(seed, ordinal, lane)),
),
)
body.push(Instruction::drop())
}
body.push(
Instruction::i32_const(
I32(gen_valid_msf_literal_value(seed, ordinal, diff_count - 1)),
),
)
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_repeated_diff_module(seed : UInt64) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let nop_count = 16 + ((seed >> 5) % 7UL).to_int()
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let value = gen_valid_msf_literal_value(seed, ordinal, 0)
let body = gen_valid_msf_nops(nop_count)
body.push(Instruction::i32_const(I32(value)))
body.push(Instruction::i32_const(I32(value)))
body.push(Instruction::i32_add())
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_exact_duplicates_module(seed : UInt64) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let filler_count = 16 + ((seed >> 5) % 7UL).to_int()
let shared_value = gen_valid_msf_literal_value(seed, 0, 0)
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
ignore(ordinal)
let body = gen_valid_msf_nops(filler_count)
body.push(Instruction::i32_const(I32(shared_value)))
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_duplicate_types_module(seed : UInt64) -> Module {
let class_size = 2 + (seed % 4UL).to_int()
let filler_count = 16 + ((seed >> 5) % 7UL).to_int()
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let body = gen_valid_msf_nops(filler_count)
body.push(
Instruction::i32_const(I32(gen_valid_msf_literal_value(seed, ordinal, 0))),
)
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(TypeIdx::new((ordinal % 2).reinterpret_as_uint()))
}
Module::new()
.with_type_sec(
TypeSec::new([
gen_valid_msf_i32_func_type([]),
gen_valid_msf_i32_func_type([]),
]),
)
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_locals_module(seed : UInt64) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let nop_count = 18 + ((seed >> 5) % 7UL).to_int()
let local_count = 1 + ((seed >> 9) % 4UL).to_int()
let locals = Locals::single(local_count.reinterpret_as_uint(), ValType::i32())
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let body = gen_valid_msf_nops(nop_count)
body.push(
Instruction::i32_const(I32(gen_valid_msf_literal_value(seed, ordinal, 0))),
)
body.push(Instruction::local_get(LocalIdx::new(0U)))
body.push(Instruction::i32_add())
for local_idx = 0; local_idx < local_count; local_idx = local_idx + 1 {
body.push(
Instruction::local_get(
LocalIdx::new((1 + local_idx).reinterpret_as_uint()),
),
)
body.push(Instruction::i32_add())
}
funcs.push(Func::new(locals.copy(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([ValType::i32()])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_nested_module(seed : UInt64) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let nop_count = 16 + ((seed >> 4) % 7UL).to_int()
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let value = gen_valid_msf_literal_value(seed, ordinal, 0)
let body = gen_valid_msf_nops(nop_count)
let nested = if ((seed >> 10) & 1UL) == 0UL {
Instruction::block(
BlockType::val_type(ValType::i32()),
Expr::new([Instruction::i32_const(I32(value))]),
)
} else {
body.push(Instruction::i32_const(I32(1)))
Instruction::if_(
BlockType::val_type(ValType::i32()),
[Instruction::i32_const(I32(value))],
Some([Instruction::i32_const(I32(value + 1))]),
)
}
body.push(nested)
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(Name::from_string("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}
///|
fn gen_valid_msf_call_target_module(seed : UInt64, tail_calls : Bool) -> Module {
let type_idx = TypeIdx::new(0U)
let class_size = 2 + (seed % 4UL).to_int()
let nop_count = 18 + ((seed >> 5) % 7UL).to_int()
let funcs : Array[Func] = []
let type_idxs : Array[TypeIdx] = []
let declared : Array[FuncIdx] = []
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
funcs.push(
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(
I32(gen_valid_msf_literal_value(seed, ordinal, 0)),
),
]),
),
)
type_idxs.push(type_idx)
declared.push(FuncIdx::new(ordinal.reinterpret_as_uint()))
}
for ordinal = 0; ordinal < class_size; ordinal = ordinal + 1 {
let body = gen_valid_msf_nops(nop_count)
if !tail_calls {
body.push(
Instruction::i32_const(
I32(gen_valid_msf_literal_value(seed, ordinal, 1)),
),
)
body.push(Instruction::drop())
}
body.push(
if tail_calls {
Instruction::return_call(FuncIdx::new(ordinal.reinterpret_as_uint()))
} else {
Instruction::call(FuncIdx::new(ordinal.reinterpret_as_uint()))
},
)
funcs.push(Func::new(Locals::empty(), Expr::new(body)))
type_idxs.push(type_idx)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_msf_i32_func_type([])]))
.with_func_sec(FuncSec::new(type_idxs))
.with_elem_sec(
ElemSec::new([Elem::new(ElemMode::declarative(), ElemKind::funcs(declared))]),
)
.with_code_sec(CodeSec::new(funcs))
.with_export_sec(
ExportSec::new([
Export::new(
Name::from_string("run"),
ExternIdx::func(FuncIdx::new(class_size.reinterpret_as_uint())),
),
]),
)
}
///|
fn gen_valid_msf_profile_module(ctx : GenValidContext) -> Module {
match gen_valid_msf_profile_kind(ctx.config) {
MergeSimilarFunctionsLiteralsProfile =>
gen_valid_msf_literal_module(ctx.root_seed)
MergeSimilarFunctionsRepeatedDiffProfile =>
gen_valid_msf_repeated_diff_module(ctx.root_seed)
MergeSimilarFunctionsExactDuplicatesProfile =>
gen_valid_msf_exact_duplicates_module(ctx.root_seed)
MergeSimilarFunctionsDuplicateTypesProfile =>
gen_valid_msf_duplicate_types_module(ctx.root_seed)
MergeSimilarFunctionsLocalsProfile =>
gen_valid_msf_locals_module(ctx.root_seed)
MergeSimilarFunctionsNestedProfile =>
gen_valid_msf_nested_module(ctx.root_seed)
MergeSimilarFunctionsCallTargetsProfile =>
gen_valid_msf_call_target_module(ctx.root_seed, false)
MergeSimilarFunctionsTailCallsProfile =>
gen_valid_msf_call_target_module(ctx.root_seed, true)
MergeSimilarFunctionsRecordCopyProfile =>
gen_valid_msf_record_copy_module(ctx.root_seed)
_ => gen_valid_msf_literal_module(ctx.root_seed)
}
}