DoxigAlpha

Function parameters

Parameters

#
stream:*std.io.FixedBufferStream([]const u8)
opcode:u8

Expressions can be evaluated in different contexts, each requiring its own set of inputs.

Types

#
Context
Expressions can be evaluated in different contexts, each requiring its own set of inputs.

A stack machine that can decode and run DWARF expressions.

Functions

#
StackMachine
A stack machine that can decode and run DWARF expressions.

Error sets in this namespace

Error Sets

#

Source

Implementation

#
pub fn readOperand(stream: *std.io.FixedBufferStream([]const u8), opcode: u8, context: Context) !?Operand {
    const reader = stream.reader();
    return switch (opcode) {
        OP.addr => generic(try reader.readInt(addr_type, options.endian)),
        OP.call_ref => switch (context.format) {
            .@"32" => generic(try reader.readInt(u32, options.endian)),
            .@"64" => generic(try reader.readInt(u64, options.endian)),
        },
        OP.const1u,
        OP.pick,
        => generic(try reader.readByte()),
        OP.deref_size,
        OP.xderef_size,
        => .{ .type_size = try reader.readByte() },
        OP.const1s => generic(try reader.readByteSigned()),
        OP.const2u,
        OP.call2,
        => generic(try reader.readInt(u16, options.endian)),
        OP.call4 => generic(try reader.readInt(u32, options.endian)),
        OP.const2s => generic(try reader.readInt(i16, options.endian)),
        OP.bra,
        OP.skip,
        => .{ .branch_offset = try reader.readInt(i16, options.endian) },
        OP.const4u => generic(try reader.readInt(u32, options.endian)),
        OP.const4s => generic(try reader.readInt(i32, options.endian)),
        OP.const8u => generic(try reader.readInt(u64, options.endian)),
        OP.const8s => generic(try reader.readInt(i64, options.endian)),
        OP.constu,
        OP.plus_uconst,
        OP.addrx,
        OP.constx,
        OP.convert,
        OP.reinterpret,
        => generic(try leb.readUleb128(u64, reader)),
        OP.consts,
        OP.fbreg,
        => generic(try leb.readIleb128(i64, reader)),
        OP.lit0...OP.lit31 => |n| generic(n - OP.lit0),
        OP.reg0...OP.reg31 => |n| .{ .register = n - OP.reg0 },
        OP.breg0...OP.breg31 => |n| .{ .base_register = .{
            .base_register = n - OP.breg0,
            .offset = try leb.readIleb128(i64, reader),
        } },
        OP.regx => .{ .register = try leb.readUleb128(u8, reader) },
        OP.bregx => blk: {
            const base_register = try leb.readUleb128(u8, reader);
            const offset = try leb.readIleb128(i64, reader);
            break :blk .{ .base_register = .{
                .base_register = base_register,
                .offset = offset,
            } };
        },
        OP.regval_type => blk: {
            const register = try leb.readUleb128(u8, reader);
            const type_offset = try leb.readUleb128(addr_type, reader);
            break :blk .{ .register_type = .{
                .register = register,
                .type_offset = type_offset,
            } };
        },
        OP.piece => .{
            .composite_location = .{
                .size = try leb.readUleb128(u8, reader),
                .offset = 0,
            },
        },
        OP.bit_piece => blk: {
            const size = try leb.readUleb128(u8, reader);
            const offset = try leb.readIleb128(i64, reader);
            break :blk .{ .composite_location = .{
                .size = size,
                .offset = offset,
            } };
        },
        OP.implicit_value, OP.entry_value => blk: {
            const size = try leb.readUleb128(u8, reader);
            if (stream.pos + size > stream.buffer.len) return error.InvalidExpression;
            const block = stream.buffer[stream.pos..][0..size];
            stream.pos += size;
            break :blk .{
                .block = block,
            };
        },
        OP.const_type => blk: {
            const type_offset = try leb.readUleb128(addr_type, reader);
            const size = try reader.readByte();
            if (stream.pos + size > stream.buffer.len) return error.InvalidExpression;
            const value_bytes = stream.buffer[stream.pos..][0..size];
            stream.pos += size;
            break :blk .{ .const_type = .{
                .type_offset = type_offset,
                .value_bytes = value_bytes,
            } };
        },
        OP.deref_type,
        OP.xderef_type,
        => .{
            .deref_type = .{
                .size = try reader.readByte(),
                .type_offset = try leb.readUleb128(addr_type, reader),
            },
        },
        OP.lo_user...OP.hi_user => return error.UnimplementedUserOpcode,
        else => null,
    };
}