Type Function Builder [src]

Prototype

pub fn Builder(comptime options: Options) type

Parameters

options: Options

Source

pub fn Builder(comptime options: Options) type { const addr_type = switch (options.addr_size) { 2 => u16, 4 => u32, 8 => u64, else => @compileError("Unsupported address size of " ++ options.addr_size), }; return struct { /// Zero-operand instructions pub fn writeOpcode(writer: *Writer, comptime opcode: u8) !void { if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode; switch (opcode) { OP.dup, OP.drop, OP.over, OP.swap, OP.rot, OP.deref, OP.xderef, OP.push_object_address, OP.form_tls_address, OP.call_frame_cfa, OP.abs, OP.@"and", OP.div, OP.minus, OP.mod, OP.mul, OP.neg, OP.not, OP.@"or", OP.plus, OP.shl, OP.shr, OP.shra, OP.xor, OP.le, OP.ge, OP.eq, OP.lt, OP.gt, OP.ne, OP.nop, OP.stack_value, => try writer.writeByte(opcode), else => @compileError("This opcode requires operands, use `write()` instead"), } } // 2.5.1.1: Literal Encodings pub fn writeLiteral(writer: *Writer, literal: u8) !void { switch (literal) { 0...31 => |n| try writer.writeByte(n + OP.lit0), else => return error.InvalidLiteral, } } pub fn writeConst(writer: *Writer, comptime T: type, value: T) !void { if (@typeInfo(T) != .int) @compileError("Constants must be integers"); switch (T) { u8, i8, u16, i16, u32, i32, u64, i64 => { try writer.writeByte(switch (T) { u8 => OP.const1u, i8 => OP.const1s, u16 => OP.const2u, i16 => OP.const2s, u32 => OP.const4u, i32 => OP.const4s, u64 => OP.const8u, i64 => OP.const8s, else => unreachable, }); try writer.writeInt(T, value, options.endian); }, else => switch (@typeInfo(T).int.signedness) { .unsigned => { try writer.writeByte(OP.constu); try writer.writeUleb128(value); }, .signed => { try writer.writeByte(OP.consts); try writer.writeLeb128(value); }, }, } } pub fn writeConstx(writer: *Writer, debug_addr_offset: anytype) !void { try writer.writeByte(OP.constx); try writer.writeUleb128(debug_addr_offset); } pub fn writeConstType(writer: *Writer, die_offset: anytype, value_bytes: []const u8) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; if (value_bytes.len > 0xff) return error.InvalidTypeLength; try writer.writeByte(OP.const_type); try writer.writeUleb128(die_offset); try writer.writeByte(@intCast(value_bytes.len)); try writer.writeAll(value_bytes); } pub fn writeAddr(writer: *Writer, value: addr_type) !void { try writer.writeByte(OP.addr); try writer.writeInt(addr_type, value, options.endian); } pub fn writeAddrx(writer: *Writer, debug_addr_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.addrx); try writer.writeUleb128(debug_addr_offset); } // 2.5.1.2: Register Values pub fn writeFbreg(writer: *Writer, offset: anytype) !void { try writer.writeByte(OP.fbreg); try writer.writeSleb128(offset); } pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void { if (register > 31) return error.InvalidRegister; try writer.writeByte(OP.breg0 + register); try writer.writeSleb128(offset); } pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void { try writer.writeByte(OP.bregx); try writer.writeUleb128(register); try writer.writeSleb128(offset); } pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.regval_type); try writer.writeUleb128(register); try writer.writeUleb128(offset); } // 2.5.1.3: Stack Operations pub fn writePick(writer: *Writer, index: u8) !void { try writer.writeByte(OP.pick); try writer.writeByte(index); } pub fn writeDerefSize(writer: *Writer, size: u8) !void { try writer.writeByte(OP.deref_size); try writer.writeByte(size); } pub fn writeXDerefSize(writer: *Writer, size: u8) !void { try writer.writeByte(OP.xderef_size); try writer.writeByte(size); } pub fn writeDerefType(writer: *Writer, size: u8, die_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.deref_type); try writer.writeByte(size); try writer.writeUleb128(die_offset); } pub fn writeXDerefType(writer: *Writer, size: u8, die_offset: anytype) !void { try writer.writeByte(OP.xderef_type); try writer.writeByte(size); try writer.writeUleb128(die_offset); } // 2.5.1.4: Arithmetic and Logical Operations pub fn writePlusUconst(writer: *Writer, uint_value: anytype) !void { try writer.writeByte(OP.plus_uconst); try writer.writeUleb128(uint_value); } // 2.5.1.5: Control Flow Operations pub fn writeSkip(writer: *Writer, offset: i16) !void { try writer.writeByte(OP.skip); try writer.writeInt(i16, offset, options.endian); } pub fn writeBra(writer: *Writer, offset: i16) !void { try writer.writeByte(OP.bra); try writer.writeInt(i16, offset, options.endian); } pub fn writeCall(writer: *Writer, comptime T: type, offset: T) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; switch (T) { u16 => try writer.writeByte(OP.call2), u32 => try writer.writeByte(OP.call4), else => @compileError("Call operand must be a 2 or 4 byte offset"), } try writer.writeInt(T, offset, options.endian); } pub fn writeCallRef(writer: *Writer, comptime is_64: bool, value: if (is_64) u64 else u32) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.call_ref); try writer.writeInt(if (is_64) u64 else u32, value, options.endian); } pub fn writeConvert(writer: *Writer, die_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.convert); try writer.writeUleb128(die_offset); } pub fn writeReinterpret(writer: *Writer, die_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.reinterpret); try writer.writeUleb128(die_offset); } // 2.5.1.7: Special Operations pub fn writeEntryValue(writer: *Writer, expression: []const u8) !void { try writer.writeByte(OP.entry_value); try writer.writeUleb128(expression.len); try writer.writeAll(expression); } // 2.6: Location Descriptions pub fn writeReg(writer: *Writer, register: u8) !void { try writer.writeByte(OP.reg0 + register); } pub fn writeRegx(writer: *Writer, register: anytype) !void { try writer.writeByte(OP.regx); try writer.writeUleb128(register); } pub fn writeImplicitValue(writer: *Writer, value_bytes: []const u8) !void { try writer.writeByte(OP.implicit_value); try writer.writeUleb128(value_bytes.len); try writer.writeAll(value_bytes); } }; }