| ... | @@ -68,14 +68,14 @@ pub const Error = error{ | ... | @@ -68,14 +68,14 @@ pub const Error = error{ |
| 68 | /// Expressions can be decoded for non-native address size and endianness, | 68 | /// Expressions can be decoded for non-native address size and endianness, |
| 69 | /// but can only be executed if the current target matches the configuration. | 69 | /// but can only be executed if the current target matches the configuration. |
| 70 | pub fn StackMachine(comptime options: Options) type { | 70 | pub fn StackMachine(comptime options: Options) type { |
| 71 | const addr_type = switch (options.addr_size) { | 71 | const Address = switch (options.addr_size) { |
| 72 | 2 => u16, | 72 | 2 => u16, |
| 73 | 4 => u32, | 73 | 4 => u32, |
| 74 | 8 => u64, | 74 | 8 => u64, |
| 75 | else => @compileError("Unsupported address size of " ++ options.addr_size), | 75 | else => @compileError("Unsupported address size of " ++ options.addr_size), |
| 76 | }; | 76 | }; |
| 77 | | 77 | |
| 78 | const addr_type_signed = switch (options.addr_size) { | 78 | const SignedAddress = switch (options.addr_size) { |
| 79 | 2 => i16, | 79 | 2 => i16, |
| 80 | 4 => i32, | 80 | 4 => i32, |
| 81 | 8 => i64, | 81 | 8 => i64, |
| ... | @@ -86,7 +86,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -86,7 +86,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 86 | const Self = @This(); | 86 | const Self = @This(); |
| 87 | | 87 | |
| 88 | const Operand = union(enum) { | 88 | const Operand = union(enum) { |
| 89 | generic: addr_type, | 89 | generic: Address, |
| 90 | register: u8, | 90 | register: u8, |
| 91 | type_size: u8, | 91 | type_size: u8, |
| 92 | branch_offset: i16, | 92 | branch_offset: i16, |
| ... | @@ -101,38 +101,38 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -101,38 +101,38 @@ pub fn StackMachine(comptime options: Options) type { |
| 101 | block: []const u8, | 101 | block: []const u8, |
| 102 | register_type: struct { | 102 | register_type: struct { |
| 103 | register: u8, | 103 | register: u8, |
| 104 | type_offset: addr_type, | 104 | type_offset: Address, |
| 105 | }, | 105 | }, |
| 106 | const_type: struct { | 106 | const_type: struct { |
| 107 | type_offset: addr_type, | 107 | type_offset: Address, |
| 108 | value_bytes: []const u8, | 108 | value_bytes: []const u8, |
| 109 | }, | 109 | }, |
| 110 | deref_type: struct { | 110 | deref_type: struct { |
| 111 | size: u8, | 111 | size: u8, |
| 112 | type_offset: addr_type, | 112 | type_offset: Address, |
| 113 | }, | 113 | }, |
| 114 | }; | 114 | }; |
| 115 | | 115 | |
| 116 | const Value = union(enum) { | 116 | const Value = union(enum) { |
| 117 | generic: addr_type, | 117 | generic: Address, |
| 118 | | 118 | |
| 119 | // Typed value with a maximum size of a register | 119 | // Typed value with a maximum size of a register |
| 120 | regval_type: struct { | 120 | regval_type: struct { |
| 121 | // Offset of DW_TAG_base_type DIE | 121 | // Offset of DW_TAG_base_type DIE |
| 122 | type_offset: addr_type, | 122 | type_offset: Address, |
| 123 | type_size: u8, | 123 | type_size: u8, |
| 124 | value: addr_type, | 124 | value: Address, |
| 125 | }, | 125 | }, |
| 126 | | 126 | |
| 127 | // Typed value specified directly in the instruction stream | 127 | // Typed value specified directly in the instruction stream |
| 128 | const_type: struct { | 128 | const_type: struct { |
| 129 | // Offset of DW_TAG_base_type DIE | 129 | // Offset of DW_TAG_base_type DIE |
| 130 | type_offset: addr_type, | 130 | type_offset: Address, |
| 131 | // Backed by the instruction stream | 131 | // Backed by the instruction stream |
| 132 | value_bytes: []const u8, | 132 | value_bytes: []const u8, |
| 133 | }, | 133 | }, |
| 134 | | 134 | |
| 135 | pub fn asIntegral(self: Value) !addr_type { | 135 | pub fn asIntegral(self: Value) !Address { |
| 136 | return switch (self) { | 136 | return switch (self) { |
| 137 | .generic => |v| v, | 137 | .generic => |v| v, |
| 138 | | 138 | |
| ... | @@ -147,7 +147,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -147,7 +147,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 147 | else => return error.InvalidIntegralTypeSize, | 147 | else => return error.InvalidIntegralTypeSize, |
| 148 | }; | 148 | }; |
| 149 | | 149 | |
| 150 | return std.math.cast(addr_type, value) orelse error.TruncatedIntegralType; | 150 | return std.math.cast(Address, value) orelse error.TruncatedIntegralType; |
| 151 | }, | 151 | }, |
| 152 | }; | 152 | }; |
| 153 | } | 153 | } |
| ... | @@ -167,119 +167,87 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -167,119 +167,87 @@ pub fn StackMachine(comptime options: Options) type { |
| 167 | const int_info = @typeInfo(@TypeOf(value)).int; | 167 | const int_info = @typeInfo(@TypeOf(value)).int; |
| 168 | if (@sizeOf(@TypeOf(value)) > options.addr_size) { | 168 | if (@sizeOf(@TypeOf(value)) > options.addr_size) { |
| 169 | return .{ .generic = switch (int_info.signedness) { | 169 | return .{ .generic = switch (int_info.signedness) { |
| 170 | .signed => @bitCast(@as(addr_type_signed, @truncate(value))), | 170 | .signed => @bitCast(@as(SignedAddress, @truncate(value))), |
| 171 | .unsigned => @truncate(value), | 171 | .unsigned => @truncate(value), |
| 172 | } }; | 172 | } }; |
| 173 | } else { | 173 | } else { |
| 174 | return .{ .generic = switch (int_info.signedness) { | 174 | return .{ .generic = switch (int_info.signedness) { |
| 175 | .signed => @bitCast(@as(addr_type_signed, @intCast(value))), | 175 | .signed => @bitCast(@as(SignedAddress, @intCast(value))), |
| 176 | .unsigned => @intCast(value), | 176 | .unsigned => @intCast(value), |
| 177 | } }; | 177 | } }; |
| 178 | } | 178 | } |
| 179 | } | 179 | } |
| 180 | | 180 | |
| 181 | pub fn readOperand(stream: *std.io.FixedBufferStream, opcode: u8, context: Context) !?Operand { | 181 | pub fn readOperand(reader: *std.io.BufferedReader, opcode: u8, context: Context) !?Operand { |
| 182 | const reader = stream.reader(); | | |
| 183 | return switch (opcode) { | 182 | return switch (opcode) { |
| 184 | OP.addr => generic(try reader.readInt(addr_type, options.endian)), | 183 | OP.addr => generic(try reader.takeInt(Address, options.endian)), |
| 185 | OP.call_ref => switch (context.format) { | 184 | OP.call_ref => switch (context.format) { |
| 186 | .@"32" => generic(try reader.readInt(u32, options.endian)), | 185 | .@"32" => generic(try reader.takeInt(u32, options.endian)), |
| 187 | .@"64" => generic(try reader.readInt(u64, options.endian)), | 186 | .@"64" => generic(try reader.takeInt(u64, options.endian)), |
| 188 | }, | 187 | }, |
| 189 | OP.const1u, | 188 | OP.const1u, |
| 190 | OP.pick, | 189 | OP.pick, |
| 191 | => generic(try reader.readByte()), | 190 | => generic(try reader.takeByte()), |
| 192 | OP.deref_size, | 191 | OP.deref_size, |
| 193 | OP.xderef_size, | 192 | OP.xderef_size, |
| 194 | => .{ .type_size = try reader.readByte() }, | 193 | => .{ .type_size = try reader.takeByte() }, |
| 195 | OP.const1s => generic(try reader.readByteSigned()), | 194 | OP.const1s => generic(try reader.takeByteSigned()), |
| 196 | OP.const2u, | 195 | OP.const2u, |
| 197 | OP.call2, | 196 | OP.call2, |
| 198 | => generic(try reader.readInt(u16, options.endian)), | 197 | => generic(try reader.takeInt(u16, options.endian)), |
| 199 | OP.call4 => generic(try reader.readInt(u32, options.endian)), | 198 | OP.call4 => generic(try reader.takeInt(u32, options.endian)), |
| 200 | OP.const2s => generic(try reader.readInt(i16, options.endian)), | 199 | OP.const2s => generic(try reader.takeInt(i16, options.endian)), |
| 201 | OP.bra, | 200 | OP.bra, |
| 202 | OP.skip, | 201 | OP.skip, |
| 203 | => .{ .branch_offset = try reader.readInt(i16, options.endian) }, | 202 | => .{ .branch_offset = try reader.takeInt(i16, options.endian) }, |
| 204 | OP.const4u => generic(try reader.readInt(u32, options.endian)), | 203 | OP.const4u => generic(try reader.takeInt(u32, options.endian)), |
| 205 | OP.const4s => generic(try reader.readInt(i32, options.endian)), | 204 | OP.const4s => generic(try reader.takeInt(i32, options.endian)), |
| 206 | OP.const8u => generic(try reader.readInt(u64, options.endian)), | 205 | OP.const8u => generic(try reader.takeInt(u64, options.endian)), |
| 207 | OP.const8s => generic(try reader.readInt(i64, options.endian)), | 206 | OP.const8s => generic(try reader.takeInt(i64, options.endian)), |
| 208 | OP.constu, | 207 | OP.constu, |
| 209 | OP.plus_uconst, | 208 | OP.plus_uconst, |
| 210 | OP.addrx, | 209 | OP.addrx, |
| 211 | OP.constx, | 210 | OP.constx, |
| 212 | OP.convert, | 211 | OP.convert, |
| 213 | OP.reinterpret, | 212 | OP.reinterpret, |
| 214 | => generic(try leb.readUleb128(u64, reader)), | 213 | => generic(try reader.takeLeb128(u64)), |
| 215 | OP.consts, | 214 | OP.consts, |
| 216 | OP.fbreg, | 215 | OP.fbreg, |
| 217 | => generic(try leb.readIleb128(i64, reader)), | 216 | => generic(try reader.takeLeb128(i64)), |
| 218 | OP.lit0...OP.lit31 => |n| generic(n - OP.lit0), | 217 | OP.lit0...OP.lit31 => |n| generic(n - OP.lit0), |
| 219 | OP.reg0...OP.reg31 => |n| .{ .register = n - OP.reg0 }, | 218 | OP.reg0...OP.reg31 => |n| .{ .register = n - OP.reg0 }, |
| 220 | OP.breg0...OP.breg31 => |n| .{ .base_register = .{ | 219 | OP.breg0...OP.breg31 => |n| .{ .base_register = .{ |
| 221 | .base_register = n - OP.breg0, | 220 | .base_register = n - OP.breg0, |
| 222 | .offset = try leb.readIleb128(i64, reader), | 221 | .offset = try reader.takeLeb128(i64), |
| 223 | } }, | 222 | } }, |
| 224 | OP.regx => .{ .register = try leb.readUleb128(u8, reader) }, | 223 | OP.regx => .{ .register = try reader.takeLeb128(u8) }, |
| 225 | OP.bregx => blk: { | 224 | OP.bregx => .{ .base_register = .{ |
| 226 | const base_register = try leb.readUleb128(u8, reader); | 225 | .base_register = try reader.takeLeb128(u8), |
| 227 | const offset = try leb.readIleb128(i64, reader); | 226 | .offset = try reader.takeLeb128(i64), |
| 228 | break :blk .{ .base_register = .{ | 227 | } }, |
| 229 | .base_register = base_register, | 228 | OP.regval_type => .{ .register_type = .{ |
| 230 | .offset = offset, | 229 | .register = try reader.takeLeb128(u8), |
| 231 | } }; | 230 | .type_offset = try reader.takeLeb128(Address), |
| 232 | }, | 231 | } }, |
| 233 | OP.regval_type => blk: { | 232 | OP.piece => .{ .composite_location = .{ |
| 234 | const register = try leb.readUleb128(u8, reader); | 233 | .size = try reader.takeLeb128(u64), |
| 235 | const type_offset = try leb.readUleb128(addr_type, reader); | 234 | .offset = 0, |
| 236 | break :blk .{ .register_type = .{ | 235 | } }, |
| 237 | .register = register, | 236 | OP.bit_piece => .{ .composite_location = .{ |
| 238 | .type_offset = type_offset, | 237 | .size = try reader.takeLeb128(u64), |
| 239 | } }; | 238 | .offset = try reader.takeLeb128(i64), |
| 240 | }, | 239 | } }, |
| 241 | OP.piece => .{ | 240 | OP.implicit_value, OP.entry_value => .{ |
| 242 | .composite_location = .{ | 241 | .block = try reader.take(try reader.takeLeb128(usize)), |
| 243 | .size = try leb.readUleb128(u8, reader), | | |
| 244 | .offset = 0, | | |
| 245 | }, | | |
| 246 | }, | | |
| 247 | OP.bit_piece => blk: { | | |
| 248 | const size = try leb.readUleb128(u8, reader); | | |
| 249 | const offset = try leb.readIleb128(i64, reader); | | |
| 250 | break :blk .{ .composite_location = .{ | | |
| 251 | .size = size, | | |
| 252 | .offset = offset, | | |
| 253 | } }; | | |
| 254 | }, | | |
| 255 | OP.implicit_value, OP.entry_value => blk: { | | |
| 256 | const size = try leb.readUleb128(u8, reader); | | |
| 257 | if (stream.pos + size > stream.buffer.len) return error.InvalidExpression; | | |
| 258 | const block = stream.buffer[stream.pos..][0..size]; | | |
| 259 | stream.pos += size; | | |
| 260 | break :blk .{ | | |
| 261 | .block = block, | | |
| 262 | }; | | |
| 263 | }, | | |
| 264 | OP.const_type => blk: { | | |
| 265 | const type_offset = try leb.readUleb128(addr_type, reader); | | |
| 266 | const size = try reader.readByte(); | | |
| 267 | if (stream.pos + size > stream.buffer.len) return error.InvalidExpression; | | |
| 268 | const value_bytes = stream.buffer[stream.pos..][0..size]; | | |
| 269 | stream.pos += size; | | |
| 270 | break :blk .{ .const_type = .{ | | |
| 271 | .type_offset = type_offset, | | |
| 272 | .value_bytes = value_bytes, | | |
| 273 | } }; | | |
| 274 | }, | | |
| 275 | OP.deref_type, | | |
| 276 | OP.xderef_type, | | |
| 277 | => .{ | | |
| 278 | .deref_type = .{ | | |
| 279 | .size = try reader.readByte(), | | |
| 280 | .type_offset = try leb.readUleb128(addr_type, reader), | | |
| 281 | }, | | |
| 282 | }, | 242 | }, |
| | 243 | OP.const_type => .{ .const_type = .{ |
| | 244 | .type_offset = try reader.takeLeb128(Address), |
| | 245 | .value_bytes = try reader.take(try reader.takeByte()), |
| | 246 | } }, |
| | 247 | OP.deref_type, OP.xderef_type => .{ .deref_type = .{ |
| | 248 | .size = try reader.takeByte(), |
| | 249 | .type_offset = try reader.takeLeb128(Address), |
| | 250 | } }, |
| 283 | OP.lo_user...OP.hi_user => return error.UnimplementedUserOpcode, | 251 | OP.lo_user...OP.hi_user => return error.UnimplementedUserOpcode, |
| 284 | else => null, | 252 | else => null, |
| 285 | }; | 253 | }; |
| ... | @@ -291,10 +259,11 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -291,10 +259,11 @@ pub fn StackMachine(comptime options: Options) type { |
| 291 | allocator: std.mem.Allocator, | 259 | allocator: std.mem.Allocator, |
| 292 | context: Context, | 260 | context: Context, |
| 293 | initial_value: ?usize, | 261 | initial_value: ?usize, |
| 294 | ) Error!?Value { | 262 | ) anyerror!?Value { |
| 295 | if (initial_value) |i| try self.stack.append(allocator, .{ .generic = i }); | 263 | if (initial_value) |i| try self.stack.append(allocator, .{ .generic = i }); |
| 296 | var stream: std.io.FixedBufferStream = .{ .buffer = expression }; | 264 | var reader: std.io.BufferedReader = undefined; |
| 297 | while (try self.step(&stream, allocator, context)) {} | 265 | reader.initFixed(expression); |
| | 266 | while (try self.step(&reader, allocator, context)) {} |
| 298 | if (self.stack.items.len == 0) return null; | 267 | if (self.stack.items.len == 0) return null; |
| 299 | return self.stack.items[self.stack.items.len - 1]; | 268 | return self.stack.items[self.stack.items.len - 1]; |
| 300 | } | 269 | } |
| ... | @@ -302,16 +271,19 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -302,16 +271,19 @@ pub fn StackMachine(comptime options: Options) type { |
| 302 | /// Reads an opcode and its operands from `stream`, then executes it | 271 | /// Reads an opcode and its operands from `stream`, then executes it |
| 303 | pub fn step( | 272 | pub fn step( |
| 304 | self: *Self, | 273 | self: *Self, |
| 305 | stream: *std.io.FixedBufferStream, | 274 | reader: *std.io.BufferedReader, |
| 306 | allocator: std.mem.Allocator, | 275 | allocator: std.mem.Allocator, |
| 307 | context: Context, | 276 | context: Context, |
| 308 | ) Error!bool { | 277 | ) anyerror!bool { |
| 309 | if (@sizeOf(usize) != @sizeOf(addr_type) or options.endian != native_endian) | 278 | if (@sizeOf(usize) != @sizeOf(Address) or options.endian != native_endian) |
| 310 | @compileError("Execution of non-native address sizes / endianness is not supported"); | 279 | @compileError("Execution of non-native address sizes / endianness is not supported"); |
| 311 | | 280 | |
| 312 | const opcode = try stream.reader().readByte(); | 281 | const opcode = reader.takeByte() catch |err| switch (err) { |
| | 282 | error.EndOfStream => return false, |
| | 283 | else => |e| return @errorCast(e), |
| | 284 | }; |
| 313 | if (options.call_frame_context and !isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode; | 285 | if (options.call_frame_context and !isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode; |
| 314 | const operand = try readOperand(stream, opcode, context); | 286 | const operand = try readOperand(reader, opcode, context); |
| 315 | switch (opcode) { | 287 | switch (opcode) { |
| 316 | | 288 | |
| 317 | // 2.5.1.1: Literal Encodings | 289 | // 2.5.1.1: Literal Encodings |
| ... | @@ -397,7 +369,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -397,7 +369,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 397 | try self.stack.append(allocator, .{ | 369 | try self.stack.append(allocator, .{ |
| 398 | .regval_type = .{ | 370 | .regval_type = .{ |
| 399 | .type_offset = register_type.type_offset, | 371 | .type_offset = register_type.type_offset, |
| 400 | .type_size = @sizeOf(addr_type), | 372 | .type_size = @sizeOf(Address), |
| 401 | .value = value, | 373 | .value = value, |
| 402 | }, | 374 | }, |
| 403 | }); | 375 | }); |
| ... | @@ -455,7 +427,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -455,7 +427,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 455 | const size = switch (opcode) { | 427 | const size = switch (opcode) { |
| 456 | OP.deref, | 428 | OP.deref, |
| 457 | OP.xderef, | 429 | OP.xderef, |
| 458 | => @sizeOf(addr_type), | 430 | => @sizeOf(Address), |
| 459 | OP.deref_size, | 431 | OP.deref_size, |
| 460 | OP.xderef_size, | 432 | OP.xderef_size, |
| 461 | => operand.?.type_size, | 433 | => operand.?.type_size, |
| ... | @@ -475,7 +447,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -475,7 +447,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 475 | }) return error.InvalidExpression; | 447 | }) return error.InvalidExpression; |
| 476 | } | 448 | } |
| 477 | | 449 | |
| 478 | const value: addr_type = std.math.cast(addr_type, @as(u64, switch (size) { | 450 | const value: Address = std.math.cast(Address, @as(u64, switch (size) { |
| 479 | 1 => @as(*const u8, @ptrFromInt(addr)).*, | 451 | 1 => @as(*const u8, @ptrFromInt(addr)).*, |
| 480 | 2 => @as(*const u16, @ptrFromInt(addr)).*, | 452 | 2 => @as(*const u16, @ptrFromInt(addr)).*, |
| 481 | 4 => @as(*const u32, @ptrFromInt(addr)).*, | 453 | 4 => @as(*const u32, @ptrFromInt(addr)).*, |
| ... | @@ -544,7 +516,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -544,7 +516,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 544 | if (self.stack.items.len < 2) return error.InvalidExpression; | 516 | if (self.stack.items.len < 2) return error.InvalidExpression; |
| 545 | const b = try self.stack.pop().?.asIntegral(); | 517 | const b = try self.stack.pop().?.asIntegral(); |
| 546 | self.stack.items[self.stack.items.len - 1] = .{ | 518 | self.stack.items[self.stack.items.len - 1] = .{ |
| 547 | .generic = try std.math.sub(addr_type, try self.stack.items[self.stack.items.len - 1].asIntegral(), b), | 519 | .generic = try std.math.sub(Address, try self.stack.items[self.stack.items.len - 1].asIntegral(), b), |
| 548 | }; | 520 | }; |
| 549 | }, | 521 | }, |
| 550 | OP.mod => { | 522 | OP.mod => { |
| ... | @@ -590,14 +562,14 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -590,14 +562,14 @@ pub fn StackMachine(comptime options: Options) type { |
| 590 | if (self.stack.items.len < 2) return error.InvalidExpression; | 562 | if (self.stack.items.len < 2) return error.InvalidExpression; |
| 591 | const b = try self.stack.pop().?.asIntegral(); | 563 | const b = try self.stack.pop().?.asIntegral(); |
| 592 | self.stack.items[self.stack.items.len - 1] = .{ | 564 | self.stack.items[self.stack.items.len - 1] = .{ |
| 593 | .generic = try std.math.add(addr_type, try self.stack.items[self.stack.items.len - 1].asIntegral(), b), | 565 | .generic = try std.math.add(Address, try self.stack.items[self.stack.items.len - 1].asIntegral(), b), |
| 594 | }; | 566 | }; |
| 595 | }, | 567 | }, |
| 596 | OP.plus_uconst => { | 568 | OP.plus_uconst => { |
| 597 | if (self.stack.items.len == 0) return error.InvalidExpression; | 569 | if (self.stack.items.len == 0) return error.InvalidExpression; |
| 598 | const constant = operand.?.generic; | 570 | const constant = operand.?.generic; |
| 599 | self.stack.items[self.stack.items.len - 1] = .{ | 571 | self.stack.items[self.stack.items.len - 1] = .{ |
| 600 | .generic = try std.math.add(addr_type, try self.stack.items[self.stack.items.len - 1].asIntegral(), constant), | 572 | .generic = try std.math.add(Address, try self.stack.items[self.stack.items.len - 1].asIntegral(), constant), |
| 601 | }; | 573 | }; |
| 602 | }, | 574 | }, |
| 603 | OP.shl => { | 575 | OP.shl => { |
| ... | @@ -670,15 +642,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -670,15 +642,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 670 | break :blk try self.stack.pop().?.asIntegral() != 0; | 642 | break :blk try self.stack.pop().?.asIntegral() != 0; |
| 671 | } else true; | 643 | } else true; |
| 672 | | 644 | |
| 673 | if (condition) { | 645 | if (condition) reader.seekBy(branch_offset) catch return error.InvalidExpression; |
| 674 | const new_pos = std.math.cast( | | |
| 675 | usize, | | |
| 676 | try std.math.add(isize, @as(isize, @intCast(stream.pos)), branch_offset), | | |
| 677 | ) orelse return error.InvalidExpression; | | |
| 678 | | | |
| 679 | if (new_pos < 0 or new_pos > stream.buffer.len) return error.InvalidExpression; | | |
| 680 | stream.pos = new_pos; | | |
| 681 | } | | |
| 682 | }, | 646 | }, |
| 683 | OP.call2, | 647 | OP.call2, |
| 684 | OP.call4, | 648 | OP.call4, |
| ... | @@ -722,7 +686,7 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -722,7 +686,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 722 | .generic => |v| .{ | 686 | .generic => |v| .{ |
| 723 | .regval_type = .{ | 687 | .regval_type = .{ |
| 724 | .type_offset = type_offset, | 688 | .type_offset = type_offset, |
| 725 | .type_size = @sizeOf(addr_type), | 689 | .type_size = @sizeOf(Address), |
| 726 | .value = v, | 690 | .value = v, |
| 727 | }, | 691 | }, |
| 728 | }, | 692 | }, |
| ... | @@ -756,8 +720,9 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -756,8 +720,9 @@ pub fn StackMachine(comptime options: Options) type { |
| 756 | if (isOpcodeRegisterLocation(block[0])) { | 720 | if (isOpcodeRegisterLocation(block[0])) { |
| 757 | if (context.thread_context == null) return error.IncompleteExpressionContext; | 721 | if (context.thread_context == null) return error.IncompleteExpressionContext; |
| 758 | | 722 | |
| 759 | var block_stream: std.io.FixedBufferStream = .{ .buffer = block }; | 723 | var block_reader: std.io.BufferedReader = undefined; |
| 760 | const register = (try readOperand(&block_stream, block[0], context)).?.register; | 724 | block_reader.initFixed(block); |
| | 725 | const register = (try readOperand(&block_reader, block[0], context)).?.register; |
| 761 | const value = mem.readInt(usize, (try abi.regBytes(context.thread_context.?, register, context.reg_context))[0..@sizeOf(usize)], native_endian); | 726 | const value = mem.readInt(usize, (try abi.regBytes(context.thread_context.?, register, context.reg_context))[0..@sizeOf(usize)], native_endian); |
| 762 | try self.stack.append(allocator, .{ .generic = value }); | 727 | try self.stack.append(allocator, .{ .generic = value }); |
| 763 | } else { | 728 | } else { |
| ... | @@ -778,14 +743,13 @@ pub fn StackMachine(comptime options: Options) type { | ... | @@ -778,14 +743,13 @@ pub fn StackMachine(comptime options: Options) type { |
| 778 | return error.UnknownExpressionOpcode; | 743 | return error.UnknownExpressionOpcode; |
| 779 | }, | 744 | }, |
| 780 | } | 745 | } |
| 781 | | 746 | return true; |
| 782 | return stream.pos < stream.buffer.len; | | |
| 783 | } | 747 | } |
| 784 | }; | 748 | }; |
| 785 | } | 749 | } |
| 786 | | 750 | |
| 787 | pub fn Builder(comptime options: Options) type { | 751 | pub fn Builder(comptime options: Options) type { |
| 788 | const addr_type = switch (options.addr_size) { | 752 | const Address = switch (options.addr_size) { |
| 789 | 2 => u16, | 753 | 2 => u16, |
| 790 | 4 => u32, | 754 | 4 => u32, |
| 791 | 8 => u64, | 755 | 8 => u64, |
| ... | @@ -888,9 +852,9 @@ pub fn Builder(comptime options: Options) type { | ... | @@ -888,9 +852,9 @@ pub fn Builder(comptime options: Options) type { |
| 888 | try writer.writeAll(value_bytes); | 852 | try writer.writeAll(value_bytes); |
| 889 | } | 853 | } |
| 890 | | 854 | |
| 891 | pub fn writeAddr(writer: anytype, value: addr_type) !void { | 855 | pub fn writeAddr(writer: anytype, value: Address) !void { |
| 892 | try writer.writeByte(OP.addr); | 856 | try writer.writeByte(OP.addr); |
| 893 | try writer.writeInt(addr_type, value, options.endian); | 857 | try writer.writeInt(Address, value, options.endian); |
| 894 | } | 858 | } |
| 895 | | 859 | |
| 896 | pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void { | 860 | pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void { |