// The accesses that carry a memarg.
//
// Generated by the same rule as the nullary table -- type prefix, dot, the rest
// in snake case -- with one number beside each: the alignment the access
// naturally has, which is the one the format leaves unwritten. `align=` appears
// only when the source asked for something else, so an access and its natural
// alignment must be spelled together or the printer would write an `align=` on
// every load in the corpus.
//
// The lowering stores the LOG of the alignment, because that is what the binary
// encodes; the text writes the byte count, so the two differ by an exponent
// here and nowhere else.
///|
/// An index the format leaves out when it is the unnamed default: the memory
/// or table an access reaches, which is memory 0 or table 0 unless said
/// otherwise. A NAMED one is always written -- the name is what the source
/// wrote, and dropping it would change the text even though the index is 0.
fn opt_index(names : Map[Int, Bytes], k : Int) -> String {
match names.get(k) {
Some(b) => " " + ident(b)
None => if k == 0 { "" } else { " " + k.to_string() }
}
}
///|
fn memidx(names : @wasm_bin.Names, k : Int) -> String {
opt_index(names.memories, k)
}
///|
/// A load or store: its mnemonic, its memory, and the immediates that differ
/// from the defaults.
fn memarg(
name : String,
mem : Int,
align : Int,
offset : Int64,
natural : Int,
names : @wasm_bin.Names,
) -> String {
let out = StringBuilder::new()
out.write_string(name + memidx(names, mem))
if offset != 0L {
// UNSIGNED: a memory64 offset fills the 64 bits, and the format writes the
// number rather than the two's complement reading of it.
out.write_string(" offset=" + offset.reinterpret_as_uint64().to_string())
}
if align != natural {
out.write_string(" align=" + (1L << align).to_string())
}
out.to_string()
}
///|
/// The text name and immediates of an access that carries a memarg, or `None`
/// when the instruction is not one.
fn memarg_instr(i : @wasm_bin.Instruction, names : @wasm_bin.Names) -> String? {
match i {
I32Load(mem, align, offset) =>
Some(memarg("i32.load", mem, align, offset, 2, names))
I64Load(mem, align, offset) =>
Some(memarg("i64.load", mem, align, offset, 3, names))
F32Load(mem, align, offset) =>
Some(memarg("f32.load", mem, align, offset, 2, names))
F64Load(mem, align, offset) =>
Some(memarg("f64.load", mem, align, offset, 3, names))
I32Load8S(mem, align, offset) =>
Some(memarg("i32.load8_s", mem, align, offset, 0, names))
I32Load8U(mem, align, offset) =>
Some(memarg("i32.load8_u", mem, align, offset, 0, names))
I32Load16S(mem, align, offset) =>
Some(memarg("i32.load16_s", mem, align, offset, 1, names))
I32Load16U(mem, align, offset) =>
Some(memarg("i32.load16_u", mem, align, offset, 1, names))
I64Load8S(mem, align, offset) =>
Some(memarg("i64.load8_s", mem, align, offset, 0, names))
I64Load8U(mem, align, offset) =>
Some(memarg("i64.load8_u", mem, align, offset, 0, names))
I64Load16S(mem, align, offset) =>
Some(memarg("i64.load16_s", mem, align, offset, 1, names))
I64Load16U(mem, align, offset) =>
Some(memarg("i64.load16_u", mem, align, offset, 1, names))
I64Load32S(mem, align, offset) =>
Some(memarg("i64.load32_s", mem, align, offset, 2, names))
I64Load32U(mem, align, offset) =>
Some(memarg("i64.load32_u", mem, align, offset, 2, names))
I32Store(mem, align, offset) =>
Some(memarg("i32.store", mem, align, offset, 2, names))
I64Store(mem, align, offset) =>
Some(memarg("i64.store", mem, align, offset, 3, names))
F32Store(mem, align, offset) =>
Some(memarg("f32.store", mem, align, offset, 2, names))
F64Store(mem, align, offset) =>
Some(memarg("f64.store", mem, align, offset, 3, names))
I32Store8(mem, align, offset) =>
Some(memarg("i32.store8", mem, align, offset, 0, names))
I32Store16(mem, align, offset) =>
Some(memarg("i32.store16", mem, align, offset, 1, names))
I64Store8(mem, align, offset) =>
Some(memarg("i64.store8", mem, align, offset, 0, names))
I64Store16(mem, align, offset) =>
Some(memarg("i64.store16", mem, align, offset, 1, names))
I64Store32(mem, align, offset) =>
Some(memarg("i64.store32", mem, align, offset, 2, names))
V128Load(mem, align, offset) =>
Some(memarg("v128.load", mem, align, offset, 4, names))
V128Load8x8S(mem, align, offset) =>
Some(memarg("v128.load8x8_s", mem, align, offset, 3, names))
V128Load8x8U(mem, align, offset) =>
Some(memarg("v128.load8x8_u", mem, align, offset, 3, names))
V128Load16x4S(mem, align, offset) =>
Some(memarg("v128.load16x4_s", mem, align, offset, 3, names))
V128Load16x4U(mem, align, offset) =>
Some(memarg("v128.load16x4_u", mem, align, offset, 3, names))
V128Load32x2S(mem, align, offset) =>
Some(memarg("v128.load32x2_s", mem, align, offset, 3, names))
V128Load32x2U(mem, align, offset) =>
Some(memarg("v128.load32x2_u", mem, align, offset, 3, names))
V128Load8Splat(mem, align, offset) =>
Some(memarg("v128.load8_splat", mem, align, offset, 0, names))
V128Load16Splat(mem, align, offset) =>
Some(memarg("v128.load16_splat", mem, align, offset, 1, names))
V128Load32Splat(mem, align, offset) =>
Some(memarg("v128.load32_splat", mem, align, offset, 2, names))
V128Load64Splat(mem, align, offset) =>
Some(memarg("v128.load64_splat", mem, align, offset, 3, names))
V128Load32Zero(mem, align, offset) =>
Some(memarg("v128.load32_zero", mem, align, offset, 2, names))
V128Load64Zero(mem, align, offset) =>
Some(memarg("v128.load64_zero", mem, align, offset, 3, names))
V128Store(mem, align, offset) =>
Some(memarg("v128.store", mem, align, offset, 4, names))
V128Load8Lane(mem, align, offset, lane) =>
Some(
memarg("v128.load8_lane", mem, align, offset, 0, names) +
" " +
lane.to_string(),
)
V128Load16Lane(mem, align, offset, lane) =>
Some(
memarg("v128.load16_lane", mem, align, offset, 1, names) +
" " +
lane.to_string(),
)
V128Load32Lane(mem, align, offset, lane) =>
Some(
memarg("v128.load32_lane", mem, align, offset, 2, names) +
" " +
lane.to_string(),
)
V128Load64Lane(mem, align, offset, lane) =>
Some(
memarg("v128.load64_lane", mem, align, offset, 3, names) +
" " +
lane.to_string(),
)
V128Store8Lane(mem, align, offset, lane) =>
Some(
memarg("v128.store8_lane", mem, align, offset, 0, names) +
" " +
lane.to_string(),
)
V128Store16Lane(mem, align, offset, lane) =>
Some(
memarg("v128.store16_lane", mem, align, offset, 1, names) +
" " +
lane.to_string(),
)
V128Store32Lane(mem, align, offset, lane) =>
Some(
memarg("v128.store32_lane", mem, align, offset, 2, names) +
" " +
lane.to_string(),
)
V128Store64Lane(mem, align, offset, lane) =>
Some(
memarg("v128.store64_lane", mem, align, offset, 3, names) +
" " +
lane.to_string(),
)
_ => None
}
}