///|
fn gen_valid_tuple_alias_captures_config() -> GenValidConfig {
  let base = gen_valid_tuple_optimization_profile_config(
    TupleOptimizationSpillProfile,
  )
  GenValidConfig::{
    ..base,
    max_defined_funcs: 2,
    max_params: 1,
    max_results: 2,
    max_locals: 9,
    max_body_statements: 16,
    max_body_depth: 3,
  }
}

///|
fn gen_valid_tuple_alias_captures_body(
  seed : UInt64,
  delayed : Bool,
) -> Array[Instruction] {
  let first = 11 + (seed & 31UL).to_int()
  let second = 100 + ((seed >> 5) & 31UL).to_int()
  let variant = seed % 3UL
  let capture = [
    Instruction::local_get(LocalIdx::new(1U)),
    Instruction::local_set(LocalIdx::new(3U)),
    Instruction::local_get(LocalIdx::new(2U)),
    Instruction::local_set(LocalIdx::new(4U)),
  ]
  if variant == 2UL {
    capture.append([
      Instruction::local_get(LocalIdx::new(3U)),
      Instruction::local_set(LocalIdx::new(5U)),
      Instruction::local_get(LocalIdx::new(4U)),
      Instruction::local_set(LocalIdx::new(6U)),
    ])
  }
  let saved_first = LocalIdx::new(if variant == 2UL { 5U } else { 3U })
  let saved_second = LocalIdx::new(if variant == 2UL { 6U } else { 4U })
  let copy_body = if variant == 1UL {
    [
      Instruction::local_get(saved_first),
      Instruction::local_get(saved_second),
      Instruction::local_set(LocalIdx::new(8U)),
    ]
  } else {
    [
      Instruction::local_get(saved_second),
      Instruction::local_set(LocalIdx::new(8U)),
      Instruction::local_get(saved_first),
    ]
  }
  let copy = [
    Instruction::block(
      BlockType::val_type(ValType::i32()),
      Expr::new(copy_body),
    ),
    Instruction::local_set(LocalIdx::new(7U)),
  ]
  let loop_body = [
    Instruction::block(
      BlockType::type_idx(TypeIdx::new(1U)),
      Expr::new([
        Instruction::local_get(LocalIdx::new(9U)),
        Instruction::i32_const(I32(first)),
        Instruction::i32_add(),
        Instruction::local_get(LocalIdx::new(9U)),
        Instruction::i32_const(I32(second)),
        Instruction::i32_add(),
      ]),
    ),
    Instruction::local_set(LocalIdx::new(2U)),
    Instruction::local_set(LocalIdx::new(1U)),
  ]
  // Every captured/output lane has one lexical write. Extra initializers
  // would hide the alias resolver's stale-capture trigger from this profile.
  if delayed {
    loop_body.append(copy)
    loop_body.append(capture)
  } else {
    loop_body.append([
      Instruction::local_get(LocalIdx::new(9U)),
      Instruction::i32_eqz(),
      Instruction::if_(BlockType::void_(), capture, None),
    ])
    loop_body.append(copy)
  }
  loop_body.append([
    Instruction::local_get(LocalIdx::new(9U)),
    Instruction::i32_const(I32(1)),
    Instruction::i32_add(),
    Instruction::local_tee(LocalIdx::new(9U)),
    Instruction::local_get(LocalIdx::new(0U)),
    Instruction::i32_lt_s(),
    Instruction::br_if(LabelIdx::new(0U)),
  ])
  [
    // Bound every host argument to 1..4 iterations, including negative values.
    Instruction::local_get(LocalIdx::new(0U)),
    Instruction::i32_const(I32(3)),
    Instruction::i32_and(),
    Instruction::i32_const(I32(1)),
    Instruction::i32_add(),
    Instruction::local_set(LocalIdx::new(0U)),
    Instruction::loop_(BlockType::void_(), Expr::new(loop_body)),
    Instruction::local_get(LocalIdx::new(7U)),
    Instruction::local_get(LocalIdx::new(8U)),
  ]
}

///|
fn gen_valid_tuple_alias_captures_module(seed : UInt64) -> Module {
  Module::new()
  .with_type_sec(
    TypeSec::new([
      RecType::new(
        SubType::comp_type(
          CompType::func([ValType::i32()], [ValType::i32(), ValType::i32()]),
        ),
      ),
      RecType::new(
        SubType::comp_type(CompType::func([], [ValType::i32(), ValType::i32()])),
      ),
    ]),
  )
  .with_func_sec(FuncSec::new([TypeIdx::new(0U), TypeIdx::new(0U)]))
  .with_export_sec(
    ExportSec::new([
      Export::new(
        Name::from_string("snapshot"),
        ExternIdx::func(FuncIdx::new(0U)),
      ),
      Export::new(
        Name::from_string("delayed"),
        ExternIdx::func(FuncIdx::new(1U)),
      ),
    ]),
  )
  .with_code_sec(
    CodeSec::new([
      Func::new(
        Locals::single(9U, ValType::i32()),
        Expr::new(gen_valid_tuple_alias_captures_body(seed, false)),
      ),
      Func::new(
        Locals::single(9U, ValType::i32()),
        Expr::new(gen_valid_tuple_alias_captures_body(seed, true)),
      ),
    ]),
  )
}