Skip to documentation
SLOP

tiny.choir.backends.wasm.emission.function.instruction.memory

Reference tiny.choir backends wasm emission function instruction memory

Defined in backends.wasm.emission.function.instruction.

API (2)

Actions

Public operations.

No direct callersNo direct callsbackends.wasm.emission.function.instructionmemory
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsbackends.wasm.emission.function.instructionWriterprivate sourcelib.choir.src.backends.wasm.emission.function...alignmentPowerprivate sourcelib.choir.src.backends.wasm.emission.function...elementByteSizeprivate sourcelib.choir.src.backends.wasm.emission.function...loadOpcodeprivate sourcelib.choir.src.backends.wasm.emission.function...memrefParamsprivate sourcelib.choir.src.backends.wasm.emission.function...writeAddressbackends.wasm.emission.function.instruction.m...writeLoad
Static calls · unresolved targets: 0 · external targets: 8.
Called byCallsbackends.wasm.emission.function.instructionWriterprivate sourcelib.choir.src.backends.wasm.emission.function...alignmentPowerprivate sourcelib.choir.src.backends.wasm.emission.function...elementByteSizeprivate sourcelib.choir.src.backends.wasm.emission.function...memrefParamsprivate sourcelib.choir.src.backends.wasm.emission.function...storeOpcodeprivate sourcelib.choir.src.backends.wasm.emission.function...writeAddressbackends.wasm.emission.function.instruction.m...writeStore
Static calls · unresolved targets: 0 · external targets: 7.

Source: lib/choir/src/backends/wasm/emission/function/instruction/memory.zig

zig
const std = @import("std");const wasm = @import("../../../root.zig");const ir = @import("../../../../../core/root.zig");const dialects = @import("../../../../../dialects/root.zig");const emission = @import("../../root.zig");const instruction = @import("root.zig");const MemrefDialect = dialects.MemrefDialect;pub fn writeLoad(    comptime Out: type,    writer: *instruction.Writer(Out),    operation: *ir.Operation,) emission.Error!void {    const load = MemrefDialect.LoadOp{ .op = operation };    const layout = try memrefParams(load.getMemref().type);    try writeAddress(Out, writer, load.getMemref(), load.getIndex(), layout);    try writer.out.writeByte(try loadOpcode(layout.element_type_name));    try wasm.binary.writeUleb(        writer.out,        alignmentPower(try elementByteSize(layout.element_type_name)),    );    try wasm.binary.writeUleb(writer.out, @as(u32, 0));    try writer.writeLocalSet(try writer.localFor(load.getResult()));}pub fn writeStore(    comptime Out: type,    writer: *instruction.Writer(Out),    operation: *ir.Operation,) emission.Error!void {    const store = MemrefDialect.StoreOp{ .op = operation };    const layout = try memrefParams(store.getMemref().type);    try writeAddress(Out, writer, store.getMemref(), store.getIndex(), layout);    try writer.writeValue(store.getValue());    try writer.out.writeByte(try storeOpcode(layout.element_type_name));    try wasm.binary.writeUleb(        writer.out,        alignmentPower(try elementByteSize(layout.element_type_name)),    );    try wasm.binary.writeUleb(writer.out, @as(u32, 0));}fn writeAddress(    comptime Out: type,    writer: *instruction.Writer(Out),    memref: *ir.Value,    index: *ir.Value,    layout: MemrefDialect.MemrefParams,) emission.Error!void {    try requireMemoryAddressSpace(layout);    const element_size = try elementByteSize(layout.element_type_name);    try writer.writeValue(memref);    try writer.writeValue(index);    if (element_size != 1) {        try writer.out.writeByte(0x41);        try wasm.binary.writeSleb(writer.out, @intCast(element_size));        try writer.out.writeByte(0x6c);    }    try writer.out.writeByte(0x6a);}fn memrefParams(memref_type: ir.Type) error{CodeGenFailed}!MemrefDialect.MemrefParams {    const key = memref_type.getDialectParamKey() orelse return error.CodeGenFailed;    return MemrefDialect.parseMemrefParams(key) orelse return error.CodeGenFailed;}fn requireMemoryAddressSpace(layout: MemrefDialect.MemrefParams) error{CodeGenFailed}!void {    if (layout.addr_space != .host and layout.addr_space != .unified) {        return error.CodeGenFailed;    }}fn elementByteSize(element_type_name: []const u8) error{CodeGenFailed}!u32 {    const kind = dialects.arith.scalarKindFromTypeName(element_type_name) orelse        return error.CodeGenFailed;    return switch (kind) {        .i8, .u8 => 1,        .i16, .u16, .f16, .bf16 => 2,        .i32, .u32, .f32, .index, .bool => 4,        .i64, .u64, .f64 => 8,    };}fn alignmentPower(size: u32) u32 {    return switch (size) {        1 => 0,        2 => 1,        4 => 2,        8 => 3,        else => 0,    };}fn loadOpcode(element_type_name: []const u8) error{CodeGenFailed}!u8 {    const kind = dialects.arith.scalarKindFromTypeName(element_type_name) orelse        return error.CodeGenFailed;    return switch (kind) {        .i8 => 0x2c,        .u8 => 0x2d,        .i16 => 0x2e,        .u16 => 0x2f,        .i32, .u32, .index, .bool => 0x28,        .i64, .u64 => 0x29,        .f32 => 0x2a,        .f64 => 0x2b,        .f16, .bf16 => error.CodeGenFailed,    };}fn storeOpcode(element_type_name: []const u8) error{CodeGenFailed}!u8 {    const kind = dialects.arith.scalarKindFromTypeName(element_type_name) orelse        return error.CodeGenFailed;    return switch (kind) {        .i8, .u8 => 0x3a,        .i16, .u16 => 0x3b,        .i32, .u32, .index, .bool => 0x36,        .i64, .u64 => 0x37,        .f32 => 0x38,        .f64 => 0x39,        .f16, .bf16 => error.CodeGenFailed,    };}test "wasm memory opcodes preserve element width and signedness" {    try std.testing.expectEqual(@as(u32, 1), try elementByteSize("arith.i8"));    try std.testing.expectEqual(@as(u32, 2), try elementByteSize("arith.f16"));    try std.testing.expectEqual(@as(u32, 4), try elementByteSize("arith.index"));    try std.testing.expectEqual(@as(u32, 8), try elementByteSize("arith.f64"));    try std.testing.expectEqual(@as(u8, 0x2c), try loadOpcode("arith.i8"));    try std.testing.expectEqual(@as(u8, 0x2d), try loadOpcode("arith.u8"));    try std.testing.expectEqual(@as(u8, 0x3a), try storeOpcode("arith.i8"));    try std.testing.expectEqual(@as(u8, 0x3a), try storeOpcode("arith.u8"));    try std.testing.expectEqual(@as(u32, 0), alignmentPower(1));    try std.testing.expectEqual(@as(u32, 3), alignmentPower(8));}test "wasm memory accepts only host-visible address spaces" {    const base = MemrefDialect.MemrefParams{        .size = null,        .element_type_name = "arith.i32",        .addr_space = .host,    };    try requireMemoryAddressSpace(base);    var unified = base;    unified.addr_space = .unified;    try requireMemoryAddressSpace(unified);    var device = base;    device.addr_space = .device;    try std.testing.expectError(error.CodeGenFailed, requireMemoryAddressSpace(device));}

Source: lib/choir/src/backends/wasm/emission/function/instruction/root.zig:4

zig
pub const memory = @import("memory.zig");

Audit

Definitions3
Public names3
Members0
Version26.7.0
Revisiondaab053ee433