///|
fn gen_valid_directize_profile_config(
profile : GenValidProfile,
) -> GenValidConfig {
let base = GenValidConfig::binaryen_oracle_coverage_forced_default()
let profile_tag = match profile {
DirectizeConstantProfile => 110
DirectizeSelectProfile => 111
DirectizeTableFactsProfile => 112
DirectizeTailCallProfile => 113
DirectizeGcProfile => 114
DirectizeTable64Profile => 115
DirectizeLegacyEhProfile => 116
DirectizeBoundaryProfile => 117
_ => 110
}
GenValidConfig::{
..base,
max_type_defs: 4,
max_imports: 2,
max_defined_funcs: 3,
max_tables: 3,
max_mems: 0,
max_globals: 1,
max_tags: 1,
max_elems: 4,
max_datas: 0,
max_params: 2,
max_results: 1,
max_locals: 2,
max_body_statements: profile_tag,
max_body_depth: 6,
features: GenValidFeatureToggles::{
..base.features,
allow_imports: profile == DirectizeBoundaryProfile ||
profile == DirectizeConstantProfile,
allow_tables: true,
allow_mems: false,
allow_globals: profile == DirectizeConstantProfile,
allow_tags: profile == DirectizeLegacyEhProfile,
allow_elems: true,
allow_datas: false,
allow_ref_types: true,
allow_calls: true,
allow_call_indirect: true,
allow_tail_calls: profile == DirectizeTailCallProfile,
allow_branch_heavy_control: profile == DirectizeLegacyEhProfile,
allow_v128: false,
allow_relaxed_simd: false,
allow_atomics: false,
allow_shared_memories: false,
allow_memory64: profile == DirectizeTable64Profile,
allow_subtyping_topology: profile == DirectizeGcProfile,
allow_name_custom_sections: false,
allow_typed_body_generator: false,
allow_ssa_nomerge_body_generator: false,
allow_heap_store_optimization_body_generator: false,
allow_heap2local_body_generator: false,
},
}
}
///|
fn gen_valid_is_directize_profile_config(config : GenValidConfig) -> Bool {
config == GenValidConfig::for_profile(DirectizeConstantProfile) ||
config == GenValidConfig::for_profile(DirectizeSelectProfile) ||
config == GenValidConfig::for_profile(DirectizeTableFactsProfile) ||
config == GenValidConfig::for_profile(DirectizeTailCallProfile) ||
config == GenValidConfig::for_profile(DirectizeGcProfile) ||
config == GenValidConfig::for_profile(DirectizeTable64Profile) ||
config == GenValidConfig::for_profile(DirectizeLegacyEhProfile) ||
config == GenValidConfig::for_profile(DirectizeBoundaryProfile)
}
///|
pub fn gen_valid_directize_profile_case_label(
profile : GenValidProfile,
seed : UInt64,
) -> String? {
match profile {
DirectizeConstantProfile =>
match (seed % 5UL).to_int() {
0 => Some("directize:segment-known")
1 => Some("directize:defined-hole-trap")
2 => Some("directize:ref-func-default")
3 => Some("directize:unknown-default-active-override")
_ => Some("directize:wrong-type-trap")
}
DirectizeSelectProfile =>
match (seed % 5UL).to_int() {
0 => Some("directize:select-known-known")
1 => Some("directize:select-trap-known")
2 => Some("directize:select-trap-trap")
3 => Some("directize:select-known-known-condition")
_ => Some("directize:select-multivalue-results")
}
DirectizeTableFactsProfile =>
match (seed % 5UL).to_int() {
0 => Some("directize:table-set-barrier")
1 => Some("directize:table-fill-barrier")
2 => Some("directize:table-copy-destination-barrier")
3 => Some("directize:table-init-barrier")
_ => Some("directize:table-grow-known-and-unknown")
}
DirectizeTailCallProfile => Some("directize:return-call-indirect")
DirectizeGcProfile =>
if (seed & 1UL) == 0UL {
Some("directize:gc-subtype-known")
} else {
Some("directize:gc-reversed-subtype-trap")
}
DirectizeTable64Profile =>
if (seed & 1UL) == 0UL {
Some("directize:table64-known")
} else {
Some("directize:table64-no-truncation-trap")
}
DirectizeLegacyEhProfile =>
match (seed % 5UL).to_int() {
0 => Some("directize:legacy-eh-protected")
1 => Some("directize:legacy-eh-typed-catch")
2 => Some("directize:legacy-eh-catch-all")
3 => Some("directize:legacy-eh-delegate")
_ => Some("directize:try-table-protected")
}
DirectizeBoundaryProfile =>
match (seed % 4UL).to_int() {
0 => Some("directize:imported-table-negative")
1 => Some("directize:exported-table-negative")
2 => Some("directize:passive-declarative-ignored")
_ => Some("directize:multi-table-positive")
}
_ => None
}
}
///|
fn gen_valid_directize_void_type() -> RecType {
RecType::new(SubType::comp_type(CompType::func([], [])))
}
///|
fn gen_valid_directize_i32_param_type() -> RecType {
RecType::new(SubType::comp_type(CompType::func([ValType::i32()], [])))
}
///|
fn gen_valid_directize_funcref() -> RefType {
RefType::new(true, HeapType::abs(AbsHeapType::func()))
}
///|
fn gen_valid_directize_table(size : UInt32, init~ : Expr? = None) -> Table {
Table::new(
TableType::new(gen_valid_directize_funcref(), Limits::i32(size, Some(size))),
init,
)
}
///|
fn gen_valid_directize_active_elem(
table : UInt32,
offset : Int32,
funcs : Array[FuncIdx],
) -> Elem {
Elem::new(
ElemMode::active(
TableIdx::new(table),
Expr::new([Instruction::i32_const(I32(offset))]),
),
ElemKind::funcs(funcs),
)
}
///|
fn gen_valid_directize_call(
table : UInt32,
offset : Int32,
) -> Array[Instruction] {
[
Instruction::i32_const(I32(offset)),
Instruction::call_indirect(TypeIdx::new(0U), TableIdx::new(table)),
]
}
///|
fn gen_valid_directize_constant_module(seed : UInt64) -> Module {
let variant = (seed % 5UL).to_int()
let target_type = if variant == 4 {
TypeIdx::new(1U)
} else {
TypeIdx::new(0U)
}
let table_init = if variant == 2 {
Some(Expr::new([Instruction::ref_func(FuncIdx::new(0U))]))
} else if variant == 3 {
Some(Expr::new([Instruction::ref_null(HeapType::abs(AbsHeapType::func()))]))
} else {
None
}
let offset = if variant == 1 { 0 } else { 1 }
let elems = if variant == 0 || variant == 3 || variant == 4 {
Some(
ElemSec::new([gen_valid_directize_active_elem(0U, 1, [FuncIdx::new(0U)])]),
)
} else {
None
}
let target_body = if variant == 4 {
[Instruction::local_get(LocalIdx::new(0U)), Instruction::drop()]
} else {
[Instruction::nop()]
}
let mut mod_ = Module::new()
.with_type_sec(
TypeSec::new([
gen_valid_directize_void_type(),
gen_valid_directize_i32_param_type(),
]),
)
.with_func_sec(FuncSec::new([target_type, TypeIdx::new(0U)]))
.with_table_sec(
TableSec::new([gen_valid_directize_table(2U, init=table_init)]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new(target_body)),
Func::new(
Locals::empty(),
Expr::new(gen_valid_directize_call(0U, offset)),
),
]),
)
match elems {
Some(sec) => mod_ = mod_.with_elem_sec(sec)
None => ()
}
mod_
}
///|
fn gen_valid_directize_multivalue_select_module(seed : UInt64) -> Module {
Module::new()
.with_type_sec(
TypeSec::new([
RecType::new(
SubType::comp_type(CompType::func([], [ValType::i32(), ValType::i64()])),
),
]),
)
.with_func_sec(
FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U), TypeIdx::new(0U)]),
)
.with_table_sec(TableSec::new([gen_valid_directize_table(2U)]))
.with_elem_sec(
ElemSec::new([
gen_valid_directize_active_elem(0U, 0, [
FuncIdx::new(0U),
FuncIdx::new(1U),
]),
]),
)
.with_code_sec(
CodeSec::new([
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(1)),
Instruction::i64_const(I64(2L)),
]),
),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(3)),
Instruction::i64_const(I64(4L)),
]),
),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::i32_const(I32(((seed >> 8) & 1UL).to_int())),
Instruction::select(),
Instruction::call_indirect(TypeIdx::new(0U), TableIdx::new(0U)),
]),
),
]),
)
}
///|
fn gen_valid_directize_select_module(seed : UInt64) -> Module {
let variant = (seed % 5UL).to_int()
if variant == 4 {
return gen_valid_directize_multivalue_select_module(seed)
}
let (left, right) = match variant {
0 | 3 => (0, 1)
1 => (7, 1)
_ => (7, 8)
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(
FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U), TypeIdx::new(0U)]),
)
.with_table_sec(TableSec::new([gen_valid_directize_table(2U)]))
.with_elem_sec(
ElemSec::new([
gen_valid_directize_active_elem(0U, 0, [
FuncIdx::new(0U),
FuncIdx::new(1U),
]),
]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(left)),
Instruction::i32_const(I32(right)),
Instruction::i32_const(I32(((seed >> 8) & 1UL).to_int())),
Instruction::select(),
Instruction::call_indirect(TypeIdx::new(0U), TableIdx::new(0U)),
]),
),
]),
)
}
///|
fn gen_valid_directize_table_facts_module(seed : UInt64) -> Module {
let variant = (seed % 5UL).to_int()
let mutation : Array[Instruction] = match variant {
0 =>
[
Instruction::i32_const(I32(0)),
Instruction::ref_func(FuncIdx::new(0U)),
Instruction::table_set(TableIdx::new(0U)),
]
1 =>
[
Instruction::i32_const(I32(0)),
Instruction::ref_func(FuncIdx::new(0U)),
Instruction::i32_const(I32(1)),
Instruction::table_fill(TableIdx::new(0U)),
]
2 =>
[
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::table_copy(TableIdx::new(0U), TableIdx::new(1U)),
]
3 =>
[
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(0)),
Instruction::i32_const(I32(1)),
Instruction::table_init(ElemIdx::new(2U), TableIdx::new(0U)),
]
_ =>
[
Instruction::ref_null(HeapType::abs(AbsHeapType::func())),
Instruction::i32_const(I32(1)),
Instruction::table_grow(TableIdx::new(0U)),
Instruction::drop(),
]
}
let body = mutation.copy()
body.append(gen_valid_directize_call(0U, 0))
if variant == 4 {
body.append(gen_valid_directize_call(0U, 2))
}
body.append(gen_valid_directize_call(1U, 0))
Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(
TableSec::new([gen_valid_directize_table(2U), gen_valid_directize_table(2U)]),
)
.with_elem_sec(
ElemSec::new([
gen_valid_directize_active_elem(0U, 0, [FuncIdx::new(0U)]),
gen_valid_directize_active_elem(1U, 0, [FuncIdx::new(0U)]),
Elem::new(ElemMode::passive(), ElemKind::funcs([FuncIdx::new(0U)])),
]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(Locals::empty(), Expr::new(body)),
]),
)
}
///|
fn gen_valid_directize_tail_module(seed : UInt64) -> Module {
let offset = if (seed & 1UL) == 0UL { 0 } else { 7 }
Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(TableSec::new([gen_valid_directize_table(1U)]))
.with_elem_sec(
ElemSec::new([gen_valid_directize_active_elem(0U, 0, [FuncIdx::new(0U)])]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(offset)),
Instruction::return_call_indirect(TypeIdx::new(0U), TableIdx::new(0U)),
]),
),
]),
)
}
///|
fn gen_valid_directize_gc_module(seed : UInt64) -> Module {
let positive = (seed & 1UL) == 0UL
let super_idx = TypeIdx::new(0U)
let sub_idx = TypeIdx::new(1U)
let target_type = if positive { sub_idx } else { super_idx }
let call_type = if positive { super_idx } else { sub_idx }
Module::new()
.with_type_sec(
TypeSec::new([
RecType::new(SubType::new(false, [], CompType::func([], []))),
RecType::new(SubType::new(true, [super_idx], CompType::func([], []))),
gen_valid_directize_void_type(),
]),
)
.with_func_sec(FuncSec::new([target_type, TypeIdx::new(2U)]))
.with_table_sec(TableSec::new([gen_valid_directize_table(1U)]))
.with_elem_sec(
ElemSec::new([gen_valid_directize_active_elem(0U, 0, [FuncIdx::new(0U)])]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i32_const(I32(0)),
Instruction::call_indirect(call_type, TableIdx::new(0U)),
]),
),
]),
)
}
///|
fn gen_valid_directize_table64_module(seed : UInt64) -> Module {
let offset = if (seed & 1UL) == 0UL { 1L } else { 4294967297L }
let funcref = gen_valid_directize_funcref()
Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(
TableSec::new([
Table::new(TableType::new(funcref, Limits::i64(2UL, Some(2UL))), None),
]),
)
.with_elem_sec(
ElemSec::new([
Elem::new(
ElemMode::active(
TableIdx::new(0U),
Expr::new([Instruction::i64_const(I64(1L))]),
),
ElemKind::typed_exprs(funcref, [
Expr::new([Instruction::ref_func(FuncIdx::new(0U))]),
]),
),
]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(
Locals::empty(),
Expr::new([
Instruction::i64_const(I64(offset)),
Instruction::call_indirect(TypeIdx::new(0U), TableIdx::new(0U)),
]),
),
]),
)
}
///|
fn gen_valid_directize_legacy_eh_module(seed : UInt64) -> Module {
let tag = TagIdx::new(0U)
let call = Expr::new(gen_valid_directize_call(0U, 0))
let body = match (seed % 5UL).to_int() {
0 =>
[
Instruction::try_(BlockType::void_(), call, [
@lib.LegacyCatch::tagged(tag, Expr::new([Instruction::nop()])),
]),
]
1 =>
[
Instruction::try_(
BlockType::void_(),
Expr::new([Instruction::throw_(tag)]),
[@lib.LegacyCatch::tagged(tag, call)],
),
]
2 =>
[
Instruction::try_(
BlockType::void_(),
Expr::new([Instruction::throw_(tag)]),
[@lib.LegacyCatch::all(call)],
),
]
3 =>
[
Instruction::try_(
BlockType::void_(),
Expr::new([
Instruction::try_(
BlockType::void_(),
call,
[],
delegate=Some(LabelIdx::new(0U)),
),
]),
[@lib.LegacyCatch::tagged(tag, Expr::new([Instruction::nop()]))],
),
]
_ =>
[
Instruction::block(
BlockType::void_(),
Expr::new([
Instruction::try_table(
BlockType::void_(),
[Catch::new(tag, LabelIdx::new(0U))],
call,
),
]),
),
]
}
Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(TableSec::new([gen_valid_directize_table(1U)]))
.with_elem_sec(
ElemSec::new([gen_valid_directize_active_elem(0U, 0, [FuncIdx::new(0U)])]),
)
.with_tag_sec(TagSec::new([TagType::new(TypeIdx::new(0U))]))
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(Locals::empty(), Expr::new(body)),
]),
)
}
///|
fn gen_valid_directize_boundary_module(seed : UInt64) -> Module {
let variant = (seed % 4UL).to_int()
let funcref = gen_valid_directize_funcref()
let imports = if variant == 0 {
Some(
ImportSec::new([
Import::new(
Name::from_string("directize"),
Name::from_string("table"),
ExternType::table(TableType::new(funcref, Limits::i32(1U, Some(1U)))),
),
]),
)
} else {
None
}
let defined_table_idx = if variant == 0 { 1U } else { 0U }
let mut mod_ = Module::new()
.with_type_sec(TypeSec::new([gen_valid_directize_void_type()]))
.with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
.with_table_sec(
TableSec::new([
gen_valid_directize_table(1U),
gen_valid_directize_table(1U),
]),
)
.with_elem_sec(
ElemSec::new([
gen_valid_directize_active_elem(defined_table_idx, 0, [FuncIdx::new(0U)]),
Elem::new(ElemMode::passive(), ElemKind::funcs([FuncIdx::new(0U)])),
Elem::new(ElemMode::declarative(), ElemKind::funcs([FuncIdx::new(0U)])),
]),
)
.with_code_sec(
CodeSec::new([
Func::new(Locals::empty(), Expr::new([Instruction::nop()])),
Func::new(
Locals::empty(),
Expr::new(gen_valid_directize_call(defined_table_idx, 0)),
),
]),
)
match imports {
Some(sec) => mod_ = mod_.with_import_sec(sec)
None => ()
}
if variant == 1 {
mod_ = mod_.with_export_sec(
ExportSec::new([
Export::new(
Name::from_string("table"),
ExternIdx::table(TableIdx::new(1U)),
),
]),
)
}
mod_
}
///|
fn gen_valid_directize_profile_module(ctx : GenValidContext) -> Module {
if ctx.config == GenValidConfig::for_profile(DirectizeSelectProfile) {
gen_valid_directize_select_module(ctx.root_seed)
} else if ctx.config ==
GenValidConfig::for_profile(DirectizeTableFactsProfile) {
gen_valid_directize_table_facts_module(ctx.root_seed)
} else if ctx.config == GenValidConfig::for_profile(DirectizeTailCallProfile) {
gen_valid_directize_tail_module(ctx.root_seed)
} else if ctx.config == GenValidConfig::for_profile(DirectizeGcProfile) {
gen_valid_directize_gc_module(ctx.root_seed)
} else if ctx.config == GenValidConfig::for_profile(DirectizeTable64Profile) {
gen_valid_directize_table64_module(ctx.root_seed)
} else if ctx.config == GenValidConfig::for_profile(DirectizeLegacyEhProfile) {
gen_valid_directize_legacy_eh_module(ctx.root_seed)
} else if ctx.config == GenValidConfig::for_profile(DirectizeBoundaryProfile) {
gen_valid_directize_boundary_module(ctx.root_seed)
} else {
gen_valid_directize_constant_module(ctx.root_seed)
}
}