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: anytype, 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: anytype, literal: u8) !void { switch (literal) { 0...31 => |n| try writer.writeByte(n + OP.lit0), else => return error.InvalidLiteral, } } pub fn writeConst(writer: anytype, 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 leb.writeUleb128(writer, value); }, .signed => { try writer.writeByte(OP.consts); try leb.writeIleb128(writer, value); }, }, } } pub fn writeConstx(writer: anytype, debug_addr_offset: anytype) !void { try writer.writeByte(OP.constx); try leb.writeUleb128(writer, debug_addr_offset); } pub fn writeConstType(writer: anytype, 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 leb.writeUleb128(writer, die_offset); try writer.writeByte(@intCast(value_bytes.len)); try writer.writeAll(value_bytes); } pub fn writeAddr(writer: anytype, value: addr_type) !void { try writer.writeByte(OP.addr); try writer.writeInt(addr_type, value, options.endian); } pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.addrx); try leb.writeUleb128(writer, debug_addr_offset); } // 2.5.1.2: Register Values pub fn writeFbreg(writer: anytype, offset: anytype) !void { try writer.writeByte(OP.fbreg); try leb.writeIleb128(writer, offset); } pub fn writeBreg(writer: anytype, register: u8, offset: anytype) !void { if (register > 31) return error.InvalidRegister; try writer.writeByte(OP.breg0 + register); try leb.writeIleb128(writer, offset); } pub fn writeBregx(writer: anytype, register: anytype, offset: anytype) !void { try writer.writeByte(OP.bregx); try leb.writeUleb128(writer, register); try leb.writeIleb128(writer, offset); } pub fn writeRegvalType(writer: anytype, register: anytype, offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.regval_type); try leb.writeUleb128(writer, register); try leb.writeUleb128(writer, offset); } // 2.5.1.3: Stack Operations pub fn writePick(writer: anytype, index: u8) !void { try writer.writeByte(OP.pick); try writer.writeByte(index); } pub fn writeDerefSize(writer: anytype, size: u8) !void { try writer.writeByte(OP.deref_size); try writer.writeByte(size); } pub fn writeXDerefSize(writer: anytype, size: u8) !void { try writer.writeByte(OP.xderef_size); try writer.writeByte(size); } pub fn writeDerefType(writer: anytype, 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 leb.writeUleb128(writer, die_offset); } pub fn writeXDerefType(writer: anytype, size: u8, die_offset: anytype) !void { try writer.writeByte(OP.xderef_type); try writer.writeByte(size); try leb.writeUleb128(writer, die_offset); } // 2.5.1.4: Arithmetic and Logical Operations pub fn writePlusUconst(writer: anytype, uint_value: anytype) !void { try writer.writeByte(OP.plus_uconst); try leb.writeUleb128(writer, uint_value); } // 2.5.1.5: Control Flow Operations pub fn writeSkip(writer: anytype, offset: i16) !void { try writer.writeByte(OP.skip); try writer.writeInt(i16, offset, options.endian); } pub fn writeBra(writer: anytype, offset: i16) !void { try writer.writeByte(OP.bra); try writer.writeInt(i16, offset, options.endian); } pub fn writeCall(writer: anytype, 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: anytype, 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: anytype, die_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.convert); try leb.writeUleb128(writer, die_offset); } pub fn writeReinterpret(writer: anytype, die_offset: anytype) !void { if (options.call_frame_context) return error.InvalidCFAOpcode; try writer.writeByte(OP.reinterpret); try leb.writeUleb128(writer, die_offset); } // 2.5.1.7: Special Operations pub fn writeEntryValue(writer: anytype, expression: []const u8) !void { try writer.writeByte(OP.entry_value); try leb.writeUleb128(writer, expression.len); try writer.writeAll(expression); } // 2.6: Location Descriptions pub fn writeReg(writer: anytype, register: u8) !void { try writer.writeByte(OP.reg0 + register); } pub fn writeRegx(writer: anytype, register: anytype) !void { try writer.writeByte(OP.regx); try leb.writeUleb128(writer, register); } pub fn writeImplicitValue(writer: anytype, value_bytes: []const u8) !void { try writer.writeByte(OP.implicit_value); try leb.writeUleb128(writer, value_bytes.len); try writer.writeAll(value_bytes); } }; }