///|
// This scan marks exactly the same indices as the Unit marker. Its result is
// only an upper bound for indices the current remapper could change.
fn dae_prune_mark_type_idx_max(idx : @lib.TypeIdx, used : Array[Bool]) -> Int32 {
match dae_type_idx_slot(idx) {
Some(slot) =>
if slot >= 0 && slot < used.length() {
used[slot] = true
slot
} else {
-1
}
None => -1
}
}
///|
fn dae_prune_mark_heap_type_max(
ht : @lib.HeapType,
used : Array[Bool],
) -> Int32 {
match ht {
@lib.HeapType(type_idx) => dae_prune_mark_type_idx_max(type_idx, used)
@lib.DefTypeHeapType(_) => {
let mut idx = 0
while idx < used.length() {
used[idx] = true
idx += 1
}
// Embedded definitions retain all types. Keep a conservative high bound.
used.length()
}
_ => -1
}
}
///|
fn dae_prune_mark_ref_type_max(rt : @lib.RefType, used : Array[Bool]) -> Int32 {
match rt {
@lib.HeapTypeRefType(_, _, ht) => dae_prune_mark_heap_type_max(ht, used)
_ => -1
}
}
///|
fn dae_prune_mark_val_type_max(vt : @lib.ValType, used : Array[Bool]) -> Int32 {
match vt {
@lib.RefTypeValType(rt) => dae_prune_mark_ref_type_max(rt, used)
_ => -1
}
}
///|
fn dae_prune_mark_block_type_max(
bt : @lib.BlockType,
used : Array[Bool],
) -> Int32 {
match bt {
@lib.TypeIdxBlockType(type_idx) =>
dae_prune_mark_type_idx_max(type_idx, used)
@lib.ValTypeBlockType(val_type) =>
dae_prune_mark_val_type_max(val_type, used)
_ => -1
}
}
///|
fn dae_prune_collect_used_type_idx_max(
instrs : Array[@lib.Instruction],
used : Array[Bool],
) -> Int32 {
let mut maximum = -1
for instr in instrs {
match instr {
@lib.Block(block_type, @lib.Expr(body))
| @lib.Loop(block_type, @lib.Expr(body))
| @lib.TryTable(block_type, _, @lib.Expr(body)) => {
maximum = maximum.max(dae_prune_mark_block_type_max(block_type, used))
maximum = maximum.max(dae_prune_collect_used_type_idx_max(body, used))
}
@lib.Try(block_type, @lib.Expr(body), catches, _) => {
maximum = maximum.max(dae_prune_mark_block_type_max(block_type, used))
maximum = maximum.max(dae_prune_collect_used_type_idx_max(body, used))
for catch_ in catches {
let @lib.Expr(catch_body) = match catch_ {
@lib.LegacyCatch(_, catch_body) | @lib.LegacyCatchAll(catch_body) =>
catch_body
}
maximum = maximum.max(
dae_prune_collect_used_type_idx_max(catch_body, used),
)
}
}
@lib.If(block_type, then_body, else_body) => {
maximum = maximum.max(dae_prune_mark_block_type_max(block_type, used))
maximum = maximum.max(
dae_prune_collect_used_type_idx_max(then_body, used),
)
match else_body {
Some(body) =>
maximum = maximum.max(
dae_prune_collect_used_type_idx_max(body, used),
)
None => ()
}
}
@lib.CallIndirect(type_idx, _)
| @lib.ReturnCallIndirect(type_idx, _)
| @lib.CallRef(type_idx)
| @lib.ReturnCallRef(type_idx)
| @lib.ContNew(type_idx)
| @lib.Resume(type_idx, _)
| @lib.ResumeThrow(type_idx, _, _)
| @lib.ResumeThrowRef(type_idx, _)
| @lib.StackSwitch(type_idx, _)
| @lib.StructNew(type_idx)
| @lib.StructNewDefault(type_idx)
| @lib.StructNewDesc(type_idx)
| @lib.StructNewDefaultDesc(type_idx)
| @lib.ArrayNew(type_idx)
| @lib.ArrayNewDefault(type_idx)
| @lib.ArrayNewFixed(type_idx, _)
| @lib.ArrayNewData(type_idx, _)
| @lib.ArrayNewElem(type_idx, _)
| @lib.ArrayGet(type_idx)
| @lib.ArrayGetS(type_idx)
| @lib.ArrayGetU(type_idx)
| @lib.ArraySet(type_idx)
| @lib.ArrayFill(type_idx)
| @lib.ArrayInitData(type_idx, _)
| @lib.ArrayInitElem(type_idx, _)
| @lib.RefGetDesc(type_idx)
| @lib.StructGet(type_idx, _)
| @lib.StructGetS(type_idx, _)
| @lib.StructGetU(type_idx, _)
| @lib.StructWait(type_idx, _)
| @lib.StructAtomicSet(_, type_idx, _)
| @lib.ArrayAtomicSet(_, type_idx)
| @lib.StructAtomicGet(_, type_idx, _)
| @lib.StructAtomicGetS(_, type_idx, _)
| @lib.StructAtomicGetU(_, type_idx, _)
| @lib.StructAtomicRmw(_, _, type_idx, _)
| @lib.StructAtomicCmpxchg(_, type_idx, _)
| @lib.StructSet(type_idx, _)
| @lib.ArrayAtomicGet(_, type_idx)
| @lib.ArrayAtomicGetS(_, type_idx)
| @lib.ArrayAtomicGetU(_, type_idx)
| @lib.ArrayAtomicRmw(_, _, type_idx)
| @lib.ArrayAtomicCmpxchg(_, type_idx)
| @lib.ArrayLoad(_, type_idx, _)
| @lib.ArrayStore(_, type_idx, _) =>
maximum = maximum.max(dae_prune_mark_type_idx_max(type_idx, used))
@lib.ContBind(source_type, target_type)
| @lib.ArrayCopy(source_type, target_type) => {
maximum = maximum.max(dae_prune_mark_type_idx_max(source_type, used))
maximum = maximum.max(dae_prune_mark_type_idx_max(target_type, used))
}
@lib.Select(Some(types)) =>
for val_type in types {
maximum = maximum.max(dae_prune_mark_val_type_max(val_type, used))
}
@lib.RefNull(rt) =>
maximum = maximum.max(dae_prune_mark_ref_type_max(rt, used))
@lib.RefTest(_, _, ht)
| @lib.RefCast(_, _, ht)
| @lib.RefTestDesc(_, ht)
| @lib.RefCastDescEq(_, _, ht) =>
maximum = maximum.max(dae_prune_mark_heap_type_max(ht, used))
@lib.BrOnCast(_, _, source_ht, target_ht)
| @lib.BrOnCastFail(_, _, source_ht, target_ht) => {
maximum = maximum.max(dae_prune_mark_heap_type_max(source_ht, used))
maximum = maximum.max(dae_prune_mark_heap_type_max(target_ht, used))
}
@lib.BrOnCastDescEq(_, source_type, target_type)
| @lib.BrOnCastDescEqFail(_, source_type, target_type) => {
maximum = maximum.max(dae_prune_mark_ref_type_max(source_type, used))
maximum = maximum.max(dae_prune_mark_ref_type_max(target_type, used))
}
_ => ()
}
}
maximum
}