///|
fn gen_valid_atomic_orders_config() -> GenValidConfig {
let base = gen_valid_array_memory_config()
GenValidConfig::{
..base,
max_mems: 1,
max_locals: 1,
max_body_statements: 463,
}
}
///|
fn gen_valid_atomic_orders_module(ctx : GenValidContext) -> Module {
let seed = if ctx.use_named_streams {
ctx.root_seed
} else {
ctx.rnd.next_uint64()
}
let kind = (seed % 3UL).to_int()
let order = match seed / 3UL % 3UL {
0UL => AtomicOrder::seq_cst()
1UL => AtomicOrder::acq_rel()
_ => AtomicOrder::relaxed()
}
let shared = ((seed / 9UL) & 1UL) == 0UL
let memory64 = ((seed / 18UL) & 1UL) != 0UL
let i32 = ValType::i32()
let ti = TypeIdx::new(0U)
let field = U32(((seed >> 6) & 1UL).to_uint())
let value = Instruction::i32_const(I32((seed >> 8).to_int()))
let body : Array[Instruction] = []
let types : Array[RecType] = []
let locals : Array[ValType] = []
let mut module_ = Module::new()
if kind == 0 {
let address = if memory64 {
Instruction::i64_const(I64(0L))
} else {
Instruction::i32_const(I32(0))
}
let ma = MemArg::new(2U, None, seed & 4UL)
module_ = module_.with_mem_sec(
MemSec::new([
MemType::new(
if memory64 {
Limits::i64(1UL, Some(1UL))
} else {
Limits::i32(1U, Some(1U))
},
shared~,
),
]),
)
body.push(address)
body.push(value)
body.push(Instruction::i32_atomic_store(ma, order~))
if (seed & 0x40UL) != 0UL {
body.push(Instruction::atomic_fence(order~))
}
body.push(address)
body.push(Instruction::i32_const(I32(1)))
body.push(Instruction::atomic_rmw(AtomicRmwOp::i32_add(), ma, order~))
body.push(Instruction::drop())
body.push(address)
body.push(Instruction::i32_atomic_load(ma, order~))
} else {
let field_type = FieldType::new(StorageType::val_type(i32), Mut::var_())
types.push(
RecType::new(
SubType::comp_type(
if kind == 1 {
CompType::struct_([field_type, field_type])
} else {
CompType::array(field_type)
},
metadata=TypeMetadata::new(shared~),
),
),
)
locals.push(ValType::ref_null(HeapType::new(ti)))
if kind == 1 {
body.push(Instruction::struct_new_default(ti))
} else {
body.push(Instruction::i32_const(I32(2)))
body.push(Instruction::array_new_default(ti))
}
body.push(Instruction::local_set(LocalIdx::new(0U)))
body.push(Instruction::local_get(LocalIdx::new(0U)))
if kind == 2 {
body.push(Instruction::i32_const(I32(field.0.reinterpret_as_int())))
}
body.push(value)
body.push(
if kind == 1 {
Instruction::struct_atomic_set(order, ti, field)
} else {
Instruction::array_atomic_set(order, ti)
},
)
let rmw_variant = (seed / 36UL % 5UL).to_int()
if rmw_variant != 0 {
body.push(Instruction::local_get(LocalIdx::new(0U)))
if kind == 2 {
body.push(Instruction::i32_const(I32(field.0.reinterpret_as_int())))
}
if rmw_variant <= 2 {
body.push(
Instruction::i32_const(I32(if rmw_variant == 1 { 0 } else { 7 })),
)
body.push(
if kind == 1 {
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::add(),
ti,
field,
order~,
)
} else {
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::add(),
ti,
order~,
)
},
)
} else {
body.push(Instruction::i32_const(I32(7)))
body.push(
Instruction::i32_const(I32(if rmw_variant == 3 { 7 } else { 8 })),
)
body.push(
if kind == 1 {
Instruction::struct_atomic_cmpxchg(ti, field, order~)
} else {
Instruction::array_atomic_cmpxchg(ti, order~)
},
)
}
body.push(Instruction::drop())
}
body.push(Instruction::local_get(LocalIdx::new(0U)))
if kind == 2 {
body.push(Instruction::i32_const(I32(field.0.reinterpret_as_int())))
}
body.push(
if kind == 1 {
Instruction::struct_atomic_get(order, ti, field)
} else {
Instruction::array_atomic_get(order, ti)
},
)
}
let function_type = TypeIdx::new(types.length().to_uint())
types.push(RecType::new(SubType::comp_type(CompType::func([], [i32]))))
module_
.with_type_sec(TypeSec::new(types))
.with_func_sec(FuncSec::new([function_type]))
.with_code_sec(
CodeSec::new([Func::new(Locals::from_types(locals), Expr::new(body))]),
)
.with_export_sec(
ExportSec::new([
Export::new(Name::new("run"), ExternIdx::func(FuncIdx::new(0U))),
]),
)
}