| author | |
| committer | |
| log | d76c8d0bd2305ff5c45653702dd92505e3fb8f6a |
| tree | f21b7848886a367fc9b2add1ac54f54ab4682373 |
| parent | 9dc0b4a98f8efe2d249db74ebe52c6880570b7cc |
5 files changed, 256 insertions(+), 363 deletions(-)
lib/std/debug/Dwarf/call_frame.zig+81-130| ... | ... | @@ -51,17 +51,6 @@ const Opcode = enum(u8) { |
| 51 | 51 | pub const hi_user = 0x3f; |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | fn readBlock(stream: *std.io.FixedBufferStream) ![]const u8 { | |
| 55 | const reader = stream.reader(); | |
| 56 | const block_len = try leb.readUleb128(usize, reader); | |
| 57 | if (stream.pos + block_len > stream.buffer.len) return error.InvalidOperand; | |
| 58 | ||
| 59 | const block = stream.buffer[stream.pos..][0..block_len]; | |
| 60 | reader.context.pos += block_len; | |
| 61 | ||
| 62 | return block; | |
| 63 | } | |
| 64 | ||
| 65 | 54 | pub const Instruction = union(Opcode) { |
| 66 | 55 | advance_loc: struct { |
| 67 | 56 | delta: u8, |
| ... | ... | @@ -147,12 +136,11 @@ pub const Instruction = union(Opcode) { |
| 147 | 136 | }, |
| 148 | 137 | |
| 149 | 138 | pub fn read( |
| 150 | stream: *std.io.FixedBufferStream, | |
| 139 | reader: *std.io.BufferedReader, | |
| 151 | 140 | addr_size_bytes: u8, |
| 152 | 141 | endian: std.builtin.Endian, |
| 153 | 142 | ) !Instruction { |
| 154 | const reader = stream.reader(); | |
| 155 | switch (try reader.readByte()) { | |
| 143 | switch (try reader.takeByte()) { | |
| 156 | 144 | Opcode.lo_inline...Opcode.hi_inline => |opcode| { |
| 157 | 145 | const e: Opcode = @enumFromInt(opcode & 0b11000000); |
| 158 | 146 | const value: u6 = @intCast(opcode & 0b111111); |
| ... | ... | @@ -163,7 +151,7 @@ pub const Instruction = union(Opcode) { |
| 163 | 151 | .offset => .{ |
| 164 | 152 | .offset = .{ |
| 165 | 153 | .register = value, |
| 166 | .offset = try leb.readUleb128(u64, reader), | |
| 154 | .offset = try reader.takeLeb128(u64), | |
| 167 | 155 | }, |
| 168 | 156 | }, |
| 169 | 157 | .restore => .{ |
| ... | ... | @@ -175,121 +163,84 @@ pub const Instruction = union(Opcode) { |
| 175 | 163 | Opcode.lo_reserved...Opcode.hi_reserved => |opcode| { |
| 176 | 164 | const e: Opcode = @enumFromInt(opcode); |
| 177 | 165 | return switch (e) { |
| 178 | .advance_loc, | |
| 179 | .offset, | |
| 180 | .restore, | |
| 181 | => unreachable, | |
| 182 | .nop => .{ .nop = {} }, | |
| 183 | .set_loc => .{ | |
| 184 | .set_loc = .{ | |
| 185 | .address = switch (addr_size_bytes) { | |
| 186 | 2 => try reader.readInt(u16, endian), | |
| 187 | 4 => try reader.readInt(u32, endian), | |
| 188 | 8 => try reader.readInt(u64, endian), | |
| 189 | else => return error.InvalidAddrSize, | |
| 190 | }, | |
| 191 | }, | |
| 192 | }, | |
| 193 | .advance_loc1 => .{ | |
| 194 | .advance_loc1 = .{ .delta = try reader.readByte() }, | |
| 195 | }, | |
| 196 | .advance_loc2 => .{ | |
| 197 | .advance_loc2 = .{ .delta = try reader.readInt(u16, endian) }, | |
| 198 | }, | |
| 199 | .advance_loc4 => .{ | |
| 200 | .advance_loc4 = .{ .delta = try reader.readInt(u32, endian) }, | |
| 201 | }, | |
| 202 | .offset_extended => .{ | |
| 203 | .offset_extended = .{ | |
| 204 | .register = try leb.readUleb128(u8, reader), | |
| 205 | .offset = try leb.readUleb128(u64, reader), | |
| 206 | }, | |
| 207 | }, | |
| 208 | .restore_extended => .{ | |
| 209 | .restore_extended = .{ | |
| 210 | .register = try leb.readUleb128(u8, reader), | |
| 211 | }, | |
| 212 | }, | |
| 213 | .undefined => .{ | |
| 214 | .undefined = .{ | |
| 215 | .register = try leb.readUleb128(u8, reader), | |
| 216 | }, | |
| 217 | }, | |
| 218 | .same_value => .{ | |
| 219 | .same_value = .{ | |
| 220 | .register = try leb.readUleb128(u8, reader), | |
| 221 | }, | |
| 222 | }, | |
| 223 | .register => .{ | |
| 224 | .register = .{ | |
| 225 | .register = try leb.readUleb128(u8, reader), | |
| 226 | .target_register = try leb.readUleb128(u8, reader), | |
| 227 | }, | |
| 228 | }, | |
| 229 | .remember_state => .{ .remember_state = {} }, | |
| 230 | .restore_state => .{ .restore_state = {} }, | |
| 231 | .def_cfa => .{ | |
| 232 | .def_cfa = .{ | |
| 233 | .register = try leb.readUleb128(u8, reader), | |
| 234 | .offset = try leb.readUleb128(u64, reader), | |
| 235 | }, | |
| 236 | }, | |
| 237 | .def_cfa_register => .{ | |
| 238 | .def_cfa_register = .{ | |
| 239 | .register = try leb.readUleb128(u8, reader), | |
| 240 | }, | |
| 241 | }, | |
| 242 | .def_cfa_offset => .{ | |
| 243 | .def_cfa_offset = .{ | |
| 244 | .offset = try leb.readUleb128(u64, reader), | |
| 245 | }, | |
| 246 | }, | |
| 247 | .def_cfa_expression => .{ | |
| 248 | .def_cfa_expression = .{ | |
| 249 | .block = try readBlock(stream), | |
| 250 | }, | |
| 251 | }, | |
| 252 | .expression => .{ | |
| 253 | .expression = .{ | |
| 254 | .register = try leb.readUleb128(u8, reader), | |
| 255 | .block = try readBlock(stream), | |
| 256 | }, | |
| 257 | }, | |
| 258 | .offset_extended_sf => .{ | |
| 259 | .offset_extended_sf = .{ | |
| 260 | .register = try leb.readUleb128(u8, reader), | |
| 261 | .offset = try leb.readIleb128(i64, reader), | |
| 262 | }, | |
| 263 | }, | |
| 264 | .def_cfa_sf => .{ | |
| 265 | .def_cfa_sf = .{ | |
| 266 | .register = try leb.readUleb128(u8, reader), | |
| 267 | .offset = try leb.readIleb128(i64, reader), | |
| 268 | }, | |
| 269 | }, | |
| 270 | .def_cfa_offset_sf => .{ | |
| 271 | .def_cfa_offset_sf = .{ | |
| 272 | .offset = try leb.readIleb128(i64, reader), | |
| 273 | }, | |
| 274 | }, | |
| 275 | .val_offset => .{ | |
| 276 | .val_offset = .{ | |
| 277 | .register = try leb.readUleb128(u8, reader), | |
| 278 | .offset = try leb.readUleb128(u64, reader), | |
| 279 | }, | |
| 280 | }, | |
| 281 | .val_offset_sf => .{ | |
| 282 | .val_offset_sf = .{ | |
| 283 | .register = try leb.readUleb128(u8, reader), | |
| 284 | .offset = try leb.readIleb128(i64, reader), | |
| 285 | }, | |
| 286 | }, | |
| 287 | .val_expression => .{ | |
| 288 | .val_expression = .{ | |
| 289 | .register = try leb.readUleb128(u8, reader), | |
| 290 | .block = try readBlock(stream), | |
| 291 | }, | |
| 292 | }, | |
| 166 | .advance_loc, .offset, .restore => unreachable, | |
| 167 | .nop => .nop, | |
| 168 | .set_loc => .{ .set_loc = .{ | |
| 169 | .address = switch (addr_size_bytes) { | |
| 170 | 2 => try reader.takeInt(u16, endian), | |
| 171 | 4 => try reader.takeInt(u32, endian), | |
| 172 | 8 => try reader.takeInt(u64, endian), | |
| 173 | else => return error.InvalidAddrSize, | |
| 174 | }, | |
| 175 | } }, | |
| 176 | .advance_loc1 => .{ .advance_loc1 = .{ | |
| 177 | .delta = try reader.takeByte(), | |
| 178 | } }, | |
| 179 | .advance_loc2 => .{ .advance_loc2 = .{ | |
| 180 | .delta = try reader.takeInt(u16, endian), | |
| 181 | } }, | |
| 182 | .advance_loc4 => .{ .advance_loc4 = .{ | |
| 183 | .delta = try reader.takeInt(u32, endian), | |
| 184 | } }, | |
| 185 | .offset_extended => .{ .offset_extended = .{ | |
| 186 | .register = try reader.takeLeb128(u8), | |
| 187 | .offset = try reader.takeLeb128(u64), | |
| 188 | } }, | |
| 189 | .restore_extended => .{ .restore_extended = .{ | |
| 190 | .register = try reader.takeLeb128(u8), | |
| 191 | } }, | |
| 192 | .undefined => .{ .undefined = .{ | |
| 193 | .register = try reader.takeLeb128(u8), | |
| 194 | } }, | |
| 195 | .same_value => .{ .same_value = .{ | |
| 196 | .register = try reader.takeLeb128(u8), | |
| 197 | } }, | |
| 198 | .register => .{ .register = .{ | |
| 199 | .register = try reader.takeLeb128(u8), | |
| 200 | .target_register = try reader.takeLeb128(u8), | |
| 201 | } }, | |
| 202 | .remember_state => .remember_state, | |
| 203 | .restore_state => .restore_state, | |
| 204 | .def_cfa => .{ .def_cfa = .{ | |
| 205 | .register = try reader.takeLeb128(u8), | |
| 206 | .offset = try reader.takeLeb128(u64), | |
| 207 | } }, | |
| 208 | .def_cfa_register => .{ .def_cfa_register = .{ | |
| 209 | .register = try reader.takeLeb128(u8), | |
| 210 | } }, | |
| 211 | .def_cfa_offset => .{ .def_cfa_offset = .{ | |
| 212 | .offset = try reader.takeLeb128(u64), | |
| 213 | } }, | |
| 214 | .def_cfa_expression => .{ .def_cfa_expression = .{ | |
| 215 | .block = try reader.take(try reader.takeLeb128(usize)), | |
| 216 | } }, | |
| 217 | .expression => .{ .expression = .{ | |
| 218 | .register = try reader.takeLeb128(u8), | |
| 219 | .block = try reader.take(try reader.takeLeb128(usize)), | |
| 220 | } }, | |
| 221 | .offset_extended_sf => .{ .offset_extended_sf = .{ | |
| 222 | .register = try reader.takeLeb128(u8), | |
| 223 | .offset = try reader.takeLeb128(i64), | |
| 224 | } }, | |
| 225 | .def_cfa_sf => .{ .def_cfa_sf = .{ | |
| 226 | .register = try reader.takeLeb128(u8), | |
| 227 | .offset = try reader.takeLeb128(i64), | |
| 228 | } }, | |
| 229 | .def_cfa_offset_sf => .{ .def_cfa_offset_sf = .{ | |
| 230 | .offset = try reader.takeLeb128(i64), | |
| 231 | } }, | |
| 232 | .val_offset => .{ .val_offset = .{ | |
| 233 | .register = try reader.takeLeb128(u8), | |
| 234 | .offset = try reader.takeLeb128(u64), | |
| 235 | } }, | |
| 236 | .val_offset_sf => .{ .val_offset_sf = .{ | |
| 237 | .register = try reader.takeLeb128(u8), | |
| 238 | .offset = try reader.takeLeb128(i64), | |
| 239 | } }, | |
| 240 | .val_expression => .{ .val_expression = .{ | |
| 241 | .register = try reader.takeLeb128(u8), | |
| 242 | .block = try reader.take(try reader.takeLeb128(usize)), | |
| 243 | } }, | |
| 293 | 244 | }; |
| 294 | 245 | }, |
| 295 | 246 | Opcode.lo_user...Opcode.hi_user => return error.UnimplementedUserOpcode, |
lib/std/debug/Dwarf/expression.zig+86-122| ... | ... | @@ -68,14 +68,14 @@ pub const Error = error{ |
| 68 | 68 | /// Expressions can be decoded for non-native address size and endianness, |
| 69 | 69 | /// but can only be executed if the current target matches the configuration. |
| 70 | 70 | pub fn StackMachine(comptime options: Options) type { |
| 71 | const addr_type = switch (options.addr_size) { | |
| 71 | const Address = switch (options.addr_size) { | |
| 72 | 72 | 2 => u16, |
| 73 | 73 | 4 => u32, |
| 74 | 74 | 8 => u64, |
| 75 | 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 | 79 | 2 => i16, |
| 80 | 80 | 4 => i32, |
| 81 | 81 | 8 => i64, |
| ... | ... | @@ -86,7 +86,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 86 | 86 | const Self = @This(); |
| 87 | 87 | |
| 88 | 88 | const Operand = union(enum) { |
| 89 | generic: addr_type, | |
| 89 | generic: Address, | |
| 90 | 90 | register: u8, |
| 91 | 91 | type_size: u8, |
| 92 | 92 | branch_offset: i16, |
| ... | ... | @@ -101,38 +101,38 @@ pub fn StackMachine(comptime options: Options) type { |
| 101 | 101 | block: []const u8, |
| 102 | 102 | register_type: struct { |
| 103 | 103 | register: u8, |
| 104 | type_offset: addr_type, | |
| 104 | type_offset: Address, | |
| 105 | 105 | }, |
| 106 | 106 | const_type: struct { |
| 107 | type_offset: addr_type, | |
| 107 | type_offset: Address, | |
| 108 | 108 | value_bytes: []const u8, |
| 109 | 109 | }, |
| 110 | 110 | deref_type: struct { |
| 111 | 111 | size: u8, |
| 112 | type_offset: addr_type, | |
| 112 | type_offset: Address, | |
| 113 | 113 | }, |
| 114 | 114 | }; |
| 115 | 115 | |
| 116 | 116 | const Value = union(enum) { |
| 117 | generic: addr_type, | |
| 117 | generic: Address, | |
| 118 | 118 | |
| 119 | 119 | // Typed value with a maximum size of a register |
| 120 | 120 | regval_type: struct { |
| 121 | 121 | // Offset of DW_TAG_base_type DIE |
| 122 | type_offset: addr_type, | |
| 122 | type_offset: Address, | |
| 123 | 123 | type_size: u8, |
| 124 | value: addr_type, | |
| 124 | value: Address, | |
| 125 | 125 | }, |
| 126 | 126 | |
| 127 | 127 | // Typed value specified directly in the instruction stream |
| 128 | 128 | const_type: struct { |
| 129 | 129 | // Offset of DW_TAG_base_type DIE |
| 130 | type_offset: addr_type, | |
| 130 | type_offset: Address, | |
| 131 | 131 | // Backed by the instruction stream |
| 132 | 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 | 136 | return switch (self) { |
| 137 | 137 | .generic => |v| v, |
| 138 | 138 | |
| ... | ... | @@ -147,7 +147,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 147 | 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 | 167 | const int_info = @typeInfo(@TypeOf(value)).int; |
| 168 | 168 | if (@sizeOf(@TypeOf(value)) > options.addr_size) { |
| 169 | 169 | return .{ .generic = switch (int_info.signedness) { |
| 170 | .signed => @bitCast(@as(addr_type_signed, @truncate(value))), | |
| 170 | .signed => @bitCast(@as(SignedAddress, @truncate(value))), | |
| 171 | 171 | .unsigned => @truncate(value), |
| 172 | 172 | } }; |
| 173 | 173 | } else { |
| 174 | 174 | return .{ .generic = switch (int_info.signedness) { |
| 175 | .signed => @bitCast(@as(addr_type_signed, @intCast(value))), | |
| 175 | .signed => @bitCast(@as(SignedAddress, @intCast(value))), | |
| 176 | 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 { | |
| 182 | const reader = stream.reader(); | |
| 181 | pub fn readOperand(reader: *std.io.BufferedReader, opcode: u8, context: Context) !?Operand { | |
| 183 | 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 | 184 | OP.call_ref => switch (context.format) { |
| 186 | .@"32" => generic(try reader.readInt(u32, options.endian)), | |
| 187 | .@"64" => generic(try reader.readInt(u64, options.endian)), | |
| 185 | .@"32" => generic(try reader.takeInt(u32, options.endian)), | |
| 186 | .@"64" => generic(try reader.takeInt(u64, options.endian)), | |
| 188 | 187 | }, |
| 189 | 188 | OP.const1u, |
| 190 | 189 | OP.pick, |
| 191 | => generic(try reader.readByte()), | |
| 190 | => generic(try reader.takeByte()), | |
| 192 | 191 | OP.deref_size, |
| 193 | 192 | OP.xderef_size, |
| 194 | => .{ .type_size = try reader.readByte() }, | |
| 195 | OP.const1s => generic(try reader.readByteSigned()), | |
| 193 | => .{ .type_size = try reader.takeByte() }, | |
| 194 | OP.const1s => generic(try reader.takeByteSigned()), | |
| 196 | 195 | OP.const2u, |
| 197 | 196 | OP.call2, |
| 198 | => generic(try reader.readInt(u16, options.endian)), | |
| 199 | OP.call4 => generic(try reader.readInt(u32, options.endian)), | |
| 200 | OP.const2s => generic(try reader.readInt(i16, options.endian)), | |
| 197 | => generic(try reader.takeInt(u16, options.endian)), | |
| 198 | OP.call4 => generic(try reader.takeInt(u32, options.endian)), | |
| 199 | OP.const2s => generic(try reader.takeInt(i16, options.endian)), | |
| 201 | 200 | OP.bra, |
| 202 | 201 | OP.skip, |
| 203 | => .{ .branch_offset = try reader.readInt(i16, options.endian) }, | |
| 204 | OP.const4u => generic(try reader.readInt(u32, options.endian)), | |
| 205 | OP.const4s => generic(try reader.readInt(i32, options.endian)), | |
| 206 | OP.const8u => generic(try reader.readInt(u64, options.endian)), | |
| 207 | OP.const8s => generic(try reader.readInt(i64, options.endian)), | |
| 202 | => .{ .branch_offset = try reader.takeInt(i16, options.endian) }, | |
| 203 | OP.const4u => generic(try reader.takeInt(u32, options.endian)), | |
| 204 | OP.const4s => generic(try reader.takeInt(i32, options.endian)), | |
| 205 | OP.const8u => generic(try reader.takeInt(u64, options.endian)), | |
| 206 | OP.const8s => generic(try reader.takeInt(i64, options.endian)), | |
| 208 | 207 | OP.constu, |
| 209 | 208 | OP.plus_uconst, |
| 210 | 209 | OP.addrx, |
| 211 | 210 | OP.constx, |
| 212 | 211 | OP.convert, |
| 213 | 212 | OP.reinterpret, |
| 214 | => generic(try leb.readUleb128(u64, reader)), | |
| 213 | => generic(try reader.takeLeb128(u64)), | |
| 215 | 214 | OP.consts, |
| 216 | 215 | OP.fbreg, |
| 217 | => generic(try leb.readIleb128(i64, reader)), | |
| 216 | => generic(try reader.takeLeb128(i64)), | |
| 218 | 217 | OP.lit0...OP.lit31 => |n| generic(n - OP.lit0), |
| 219 | 218 | OP.reg0...OP.reg31 => |n| .{ .register = n - OP.reg0 }, |
| 220 | 219 | OP.breg0...OP.breg31 => |n| .{ .base_register = .{ |
| 221 | 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) }, | |
| 225 | OP.bregx => blk: { | |
| 226 | const base_register = try leb.readUleb128(u8, reader); | |
| 227 | const offset = try leb.readIleb128(i64, reader); | |
| 228 | break :blk .{ .base_register = .{ | |
| 229 | .base_register = base_register, | |
| 230 | .offset = offset, | |
| 231 | } }; | |
| 232 | }, | |
| 233 | OP.regval_type => blk: { | |
| 234 | const register = try leb.readUleb128(u8, reader); | |
| 235 | const type_offset = try leb.readUleb128(addr_type, reader); | |
| 236 | break :blk .{ .register_type = .{ | |
| 237 | .register = register, | |
| 238 | .type_offset = type_offset, | |
| 239 | } }; | |
| 240 | }, | |
| 241 | OP.piece => .{ | |
| 242 | .composite_location = .{ | |
| 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 | }, | |
| 223 | OP.regx => .{ .register = try reader.takeLeb128(u8) }, | |
| 224 | OP.bregx => .{ .base_register = .{ | |
| 225 | .base_register = try reader.takeLeb128(u8), | |
| 226 | .offset = try reader.takeLeb128(i64), | |
| 227 | } }, | |
| 228 | OP.regval_type => .{ .register_type = .{ | |
| 229 | .register = try reader.takeLeb128(u8), | |
| 230 | .type_offset = try reader.takeLeb128(Address), | |
| 231 | } }, | |
| 232 | OP.piece => .{ .composite_location = .{ | |
| 233 | .size = try reader.takeLeb128(u64), | |
| 234 | .offset = 0, | |
| 235 | } }, | |
| 236 | OP.bit_piece => .{ .composite_location = .{ | |
| 237 | .size = try reader.takeLeb128(u64), | |
| 238 | .offset = try reader.takeLeb128(i64), | |
| 239 | } }, | |
| 240 | OP.implicit_value, OP.entry_value => .{ | |
| 241 | .block = try reader.take(try reader.takeLeb128(usize)), | |
| 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 | 251 | OP.lo_user...OP.hi_user => return error.UnimplementedUserOpcode, |
| 284 | 252 | else => null, |
| 285 | 253 | }; |
| ... | ... | @@ -291,10 +259,11 @@ pub fn StackMachine(comptime options: Options) type { |
| 291 | 259 | allocator: std.mem.Allocator, |
| 292 | 260 | context: Context, |
| 293 | 261 | initial_value: ?usize, |
| 294 | ) Error!?Value { | |
| 262 | ) anyerror!?Value { | |
| 295 | 263 | if (initial_value) |i| try self.stack.append(allocator, .{ .generic = i }); |
| 296 | var stream: std.io.FixedBufferStream = .{ .buffer = expression }; | |
| 297 | while (try self.step(&stream, allocator, context)) {} | |
| 264 | var reader: std.io.BufferedReader = undefined; | |
| 265 | reader.initFixed(expression); | |
| 266 | while (try self.step(&reader, allocator, context)) {} | |
| 298 | 267 | if (self.stack.items.len == 0) return null; |
| 299 | 268 | return self.stack.items[self.stack.items.len - 1]; |
| 300 | 269 | } |
| ... | ... | @@ -302,16 +271,19 @@ pub fn StackMachine(comptime options: Options) type { |
| 302 | 271 | /// Reads an opcode and its operands from `stream`, then executes it |
| 303 | 272 | pub fn step( |
| 304 | 273 | self: *Self, |
| 305 | stream: *std.io.FixedBufferStream, | |
| 274 | reader: *std.io.BufferedReader, | |
| 306 | 275 | allocator: std.mem.Allocator, |
| 307 | 276 | context: Context, |
| 308 | ) Error!bool { | |
| 309 | if (@sizeOf(usize) != @sizeOf(addr_type) or options.endian != native_endian) | |
| 277 | ) anyerror!bool { | |
| 278 | if (@sizeOf(usize) != @sizeOf(Address) or options.endian != native_endian) | |
| 310 | 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 | 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 | 287 | switch (opcode) { |
| 316 | 288 | |
| 317 | 289 | // 2.5.1.1: Literal Encodings |
| ... | ... | @@ -397,7 +369,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 397 | 369 | try self.stack.append(allocator, .{ |
| 398 | 370 | .regval_type = .{ |
| 399 | 371 | .type_offset = register_type.type_offset, |
| 400 | .type_size = @sizeOf(addr_type), | |
| 372 | .type_size = @sizeOf(Address), | |
| 401 | 373 | .value = value, |
| 402 | 374 | }, |
| 403 | 375 | }); |
| ... | ... | @@ -455,7 +427,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 455 | 427 | const size = switch (opcode) { |
| 456 | 428 | OP.deref, |
| 457 | 429 | OP.xderef, |
| 458 | => @sizeOf(addr_type), | |
| 430 | => @sizeOf(Address), | |
| 459 | 431 | OP.deref_size, |
| 460 | 432 | OP.xderef_size, |
| 461 | 433 | => operand.?.type_size, |
| ... | ... | @@ -475,7 +447,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 475 | 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 | 451 | 1 => @as(*const u8, @ptrFromInt(addr)).*, |
| 480 | 452 | 2 => @as(*const u16, @ptrFromInt(addr)).*, |
| 481 | 453 | 4 => @as(*const u32, @ptrFromInt(addr)).*, |
| ... | ... | @@ -544,7 +516,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 544 | 516 | if (self.stack.items.len < 2) return error.InvalidExpression; |
| 545 | 517 | const b = try self.stack.pop().?.asIntegral(); |
| 546 | 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 | 522 | OP.mod => { |
| ... | ... | @@ -590,14 +562,14 @@ pub fn StackMachine(comptime options: Options) type { |
| 590 | 562 | if (self.stack.items.len < 2) return error.InvalidExpression; |
| 591 | 563 | const b = try self.stack.pop().?.asIntegral(); |
| 592 | 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 | 568 | OP.plus_uconst => { |
| 597 | 569 | if (self.stack.items.len == 0) return error.InvalidExpression; |
| 598 | 570 | const constant = operand.?.generic; |
| 599 | 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 | 575 | OP.shl => { |
| ... | ... | @@ -670,15 +642,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 670 | 642 | break :blk try self.stack.pop().?.asIntegral() != 0; |
| 671 | 643 | } else true; |
| 672 | 644 | |
| 673 | if (condition) { | |
| 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 | } | |
| 645 | if (condition) reader.seekBy(branch_offset) catch return error.InvalidExpression; | |
| 682 | 646 | }, |
| 683 | 647 | OP.call2, |
| 684 | 648 | OP.call4, |
| ... | ... | @@ -722,7 +686,7 @@ pub fn StackMachine(comptime options: Options) type { |
| 722 | 686 | .generic => |v| .{ |
| 723 | 687 | .regval_type = .{ |
| 724 | 688 | .type_offset = type_offset, |
| 725 | .type_size = @sizeOf(addr_type), | |
| 689 | .type_size = @sizeOf(Address), | |
| 726 | 690 | .value = v, |
| 727 | 691 | }, |
| 728 | 692 | }, |
| ... | ... | @@ -756,8 +720,9 @@ pub fn StackMachine(comptime options: Options) type { |
| 756 | 720 | if (isOpcodeRegisterLocation(block[0])) { |
| 757 | 721 | if (context.thread_context == null) return error.IncompleteExpressionContext; |
| 758 | 722 | |
| 759 | var block_stream: std.io.FixedBufferStream = .{ .buffer = block }; | |
| 760 | const register = (try readOperand(&block_stream, block[0], context)).?.register; | |
| 723 | var block_reader: std.io.BufferedReader = undefined; | |
| 724 | block_reader.initFixed(block); | |
| 725 | const register = (try readOperand(&block_reader, block[0], context)).?.register; | |
| 761 | 726 | const value = mem.readInt(usize, (try abi.regBytes(context.thread_context.?, register, context.reg_context))[0..@sizeOf(usize)], native_endian); |
| 762 | 727 | try self.stack.append(allocator, .{ .generic = value }); |
| 763 | 728 | } else { |
| ... | ... | @@ -778,14 +743,13 @@ pub fn StackMachine(comptime options: Options) type { |
| 778 | 743 | return error.UnknownExpressionOpcode; |
| 779 | 744 | }, |
| 780 | 745 | } |
| 781 | ||
| 782 | return stream.pos < stream.buffer.len; | |
| 746 | return true; | |
| 783 | 747 | } |
| 784 | 748 | }; |
| 785 | 749 | } |
| 786 | 750 | |
| 787 | 751 | pub fn Builder(comptime options: Options) type { |
| 788 | const addr_type = switch (options.addr_size) { | |
| 752 | const Address = switch (options.addr_size) { | |
| 789 | 753 | 2 => u16, |
| 790 | 754 | 4 => u32, |
| 791 | 755 | 8 => u64, |
| ... | ... | @@ -888,9 +852,9 @@ pub fn Builder(comptime options: Options) type { |
| 888 | 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 | 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 | 860 | pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void { |
lib/std/debug/FixedBufferReader.zig+7-8| ... | ... | @@ -51,22 +51,21 @@ pub fn readIntChecked( |
| 51 | 51 | return fbr.readInt(T); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | pub fn readUleb128(fbr: *FixedBufferReader, comptime T: type) Error!T { | |
| 54 | pub fn readLeb128(fbr: *FixedBufferReader, comptime T: type) Error!T { | |
| 55 | 55 | var br: std.io.BufferedReader = undefined; |
| 56 | 56 | br.initFixed(fbr.buf); |
| 57 | 57 | br.seek = fbr.pos; |
| 58 | const result = br.takeUleb128(T); | |
| 58 | const result = br.takeLeb128(T); | |
| 59 | 59 | fbr.pos = br.seek; |
| 60 | 60 | return @errorCast(result); |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | pub fn readUleb128(fbr: *FixedBufferReader, comptime T: type) Error!T { | |
| 64 | return fbr.readLeb128(T); | |
| 65 | } | |
| 66 | ||
| 63 | 67 | pub fn readIleb128(fbr: *FixedBufferReader, comptime T: type) Error!T { |
| 64 | var br: std.io.BufferedReader = undefined; | |
| 65 | br.initFixed(fbr.buf); | |
| 66 | br.seek = fbr.pos; | |
| 67 | const result = br.takeIleb128(T); | |
| 68 | fbr.pos = br.seek; | |
| 69 | return @errorCast(result); | |
| 68 | return fbr.readLeb128(T); | |
| 70 | 69 | } |
| 71 | 70 | |
| 72 | 71 | pub fn readAddress(fbr: *FixedBufferReader, format: std.dwarf.Format) Error!u64 { |
lib/std/debug/SelfInfo.zig+8-11| ... | ... | @@ -2025,18 +2025,15 @@ pub const VirtualMachine = struct { |
| 2025 | 2025 | assert(self.cie_row == null); |
| 2026 | 2026 | if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return error.AddressOutOfRange; |
| 2027 | 2027 | |
| 2028 | var prev_row: Row = self.current_row; | |
| 2029 | ||
| 2030 | var cie_stream: std.io.BufferedReader = undefined; | |
| 2031 | cie_stream.initFixed(cie.initial_instructions); | |
| 2032 | var fde_stream: std.io.BufferedReader = undefined; | |
| 2033 | fde_stream.initFixed(fde.instructions); | |
| 2034 | const streams: [2]*std.io.BufferedReader = .{ &cie_stream, &fde_stream }; | |
| 2028 | var readers: [2]std.io.BufferedReader = undefined; | |
| 2029 | readers[0].initFixed(cie.initial_instructions); | |
| 2030 | readers[1].initFixed(fde.instructions); | |
| 2035 | 2031 | |
| 2036 | for (&streams, 0..) |stream, i| { | |
| 2037 | while (stream.seek < stream.storageBuffer().len) { | |
| 2038 | const instruction = try std.debug.Dwarf.call_frame.Instruction.read(stream, addr_size_bytes, endian); | |
| 2039 | prev_row = try self.step(allocator, cie, i == 0, instruction); | |
| 2032 | var prev_row: Row = self.current_row; | |
| 2033 | for (&readers, [2]bool{ true, false }) |*reader, is_initial| { | |
| 2034 | while (reader.seek < reader.storageBuffer().len) { | |
| 2035 | const instruction = try std.debug.Dwarf.call_frame.Instruction.read(reader, addr_size_bytes, endian); | |
| 2036 | prev_row = try self.step(allocator, cie, is_initial, instruction); | |
| 2040 | 2037 | if (pc < fde.pc_begin + self.current_row.offset) return prev_row; |
| 2041 | 2038 | } |
| 2042 | 2039 | } |
lib/std/io/BufferedReader.zig+74-92| ... | ... | @@ -164,6 +164,21 @@ fn passthru_posReadVec(ctx: ?*anyopaque, data: []const []u8, off: u64) anyerror! |
| 164 | 164 | @panic("TODO"); |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | pub fn seekBy(br: *BufferedReader, seek_by: i64) anyerror!void { | |
| 168 | if (seek_by < 0) try br.seekBackwardBy(@abs(seek_by)) else try br.seekForwardBy(@abs(seek_by)); | |
| 169 | } | |
| 170 | ||
| 171 | pub fn seekBackwardBy(br: *BufferedReader, seek_by: u64) anyerror!void { | |
| 172 | if (seek_by > br.storage.buffer.items.len - br.seek) return error.Unseekable; // TODO | |
| 173 | br.seek += @abs(seek_by); | |
| 174 | } | |
| 175 | ||
| 176 | pub fn seekForwardBy(br: *BufferedReader, seek_by: u64) anyerror!void { | |
| 177 | const seek, const need_unbuffered_seek = @subWithOverflow(br.seek, @abs(seek_by)); | |
| 178 | if (need_unbuffered_seek > 0) return error.Unseekable; // TODO | |
| 179 | br.seek = seek; | |
| 180 | } | |
| 181 | ||
| 167 | 182 | /// Returns the next `n` bytes from `unbuffered_reader`, filling the buffer as |
| 168 | 183 | /// necessary. |
| 169 | 184 | /// |
| ... | ... | @@ -176,12 +191,31 @@ fn passthru_posReadVec(ctx: ?*anyopaque, data: []const []u8, off: u64) anyerror! |
| 176 | 191 | /// is returned instead. |
| 177 | 192 | /// |
| 178 | 193 | /// See also: |
| 194 | /// * `peekAll` | |
| 179 | 195 | /// * `toss` |
| 180 | 196 | pub fn peek(br: *BufferedReader, n: usize) anyerror![]u8 { |
| 197 | return (try br.peekAll(n))[0..n]; | |
| 198 | } | |
| 199 | ||
| 200 | /// Returns the next buffered bytes from `unbuffered_reader`, after filling the buffer | |
| 201 | /// with at least `n` bytes. | |
| 202 | /// | |
| 203 | /// Invalidates previously returned values from `peek`. | |
| 204 | /// | |
| 205 | /// Asserts that the `BufferedReader` was initialized with a buffer capacity at | |
| 206 | /// least as big as `n`. | |
| 207 | /// | |
| 208 | /// If there are fewer than `n` bytes left in the stream, `error.EndOfStream` | |
| 209 | /// is returned instead. | |
| 210 | /// | |
| 211 | /// See also: | |
| 212 | /// * `peek` | |
| 213 | /// * `toss` | |
| 214 | pub fn peekAll(br: *BufferedReader, n: usize) anyerror![]u8 { | |
| 181 | 215 | const list = &br.storage.buffer; |
| 182 | 216 | assert(n <= list.capacity); |
| 183 | try fill(br, n); | |
| 184 | return list.items[br.seek..][0..n]; | |
| 217 | try br.fill(n); | |
| 218 | return list.items[br.seek..]; | |
| 185 | 219 | } |
| 186 | 220 | |
| 187 | 221 | /// Skips the next `n` bytes from the stream, advancing the seek position. This |
| ... | ... | @@ -563,93 +597,41 @@ pub fn takeEnum(br: *BufferedReader, comptime Enum: type, endian: std.builtin.En |
| 563 | 597 | return std.meta.intToEnum(Enum, int); |
| 564 | 598 | } |
| 565 | 599 | |
| 566 | /// Read a single unsigned LEB128 value from the given reader as type T, | |
| 567 | /// or error.Overflow if the value cannot fit. | |
| 568 | pub fn takeUleb128(br: *std.io.BufferedReader, comptime T: type) anyerror!T { | |
| 569 | const U = if (@typeInfo(T).int.bits < 8) u8 else T; | |
| 570 | const ShiftT = std.math.Log2Int(U); | |
| 571 | ||
| 572 | const max_group = (@typeInfo(U).int.bits + 6) / 7; | |
| 573 | ||
| 574 | var value: U = 0; | |
| 575 | var group: ShiftT = 0; | |
| 576 | ||
| 577 | while (group < max_group) : (group += 1) { | |
| 578 | const byte = try br.takeByte(); | |
| 579 | ||
| 580 | const ov = @shlWithOverflow(@as(U, byte & 0x7f), group * 7); | |
| 581 | if (ov[1] != 0) return error.Overflow; | |
| 582 | ||
| 583 | value |= ov[0]; | |
| 584 | if (byte & 0x80 == 0) break; | |
| 585 | } else { | |
| 586 | return error.Overflow; | |
| 587 | } | |
| 588 | ||
| 589 | // only applies in the case that we extended to u8 | |
| 590 | if (U != T) { | |
| 591 | if (value > std.math.maxInt(T)) return error.Overflow; | |
| 592 | } | |
| 593 | ||
| 594 | return @truncate(value); | |
| 595 | } | |
| 596 | ||
| 597 | /// Read a single signed LEB128 value from the given reader as type T, | |
| 598 | /// or `error.Overflow` if the value cannot fit. | |
| 599 | pub fn takeIleb128(br: *std.io.BufferedReader, comptime T: type) anyerror!T { | |
| 600 | const S = if (@typeInfo(T).int.bits < 8) i8 else T; | |
| 601 | const U = std.meta.Int(.unsigned, @typeInfo(S).int.bits); | |
| 602 | const ShiftU = std.math.Log2Int(U); | |
| 603 | ||
| 604 | const max_group = (@typeInfo(U).int.bits + 6) / 7; | |
| 605 | ||
| 606 | var value = @as(U, 0); | |
| 607 | var group = @as(ShiftU, 0); | |
| 608 | ||
| 609 | while (group < max_group) : (group += 1) { | |
| 610 | const byte = try br.takeByte(); | |
| 611 | ||
| 612 | const shift = group * 7; | |
| 613 | const ov = @shlWithOverflow(@as(U, byte & 0x7f), shift); | |
| 614 | if (ov[1] != 0) { | |
| 615 | // Overflow is ok so long as the sign bit is set and this is the last byte | |
| 616 | if (byte & 0x80 != 0) return error.Overflow; | |
| 617 | if (@as(S, @bitCast(ov[0])) >= 0) return error.Overflow; | |
| 618 | ||
| 619 | // and all the overflowed bits are 1 | |
| 620 | const remaining_shift = @as(u3, @intCast(@typeInfo(U).int.bits - @as(u16, shift))); | |
| 621 | const remaining_bits = @as(i8, @bitCast(byte | 0x80)) >> remaining_shift; | |
| 622 | if (remaining_bits != -1) return error.Overflow; | |
| 623 | } else { | |
| 624 | // If we don't overflow and this is the last byte and the number being decoded | |
| 625 | // is negative, check that the remaining bits are 1 | |
| 626 | if ((byte & 0x80 == 0) and (@as(S, @bitCast(ov[0])) < 0)) { | |
| 627 | const remaining_shift = @as(u3, @intCast(@typeInfo(U).int.bits - @as(u16, shift))); | |
| 628 | const remaining_bits = @as(i8, @bitCast(byte | 0x80)) >> remaining_shift; | |
| 629 | if (remaining_bits != -1) return error.Overflow; | |
| 630 | } | |
| 631 | } | |
| 632 | ||
| 633 | value |= ov[0]; | |
| 634 | if (byte & 0x80 == 0) { | |
| 635 | const needs_sign_ext = group + 1 < max_group; | |
| 636 | if (byte & 0x40 != 0 and needs_sign_ext) { | |
| 637 | const ones = @as(S, -1); | |
| 638 | value |= @as(U, @bitCast(ones)) << (shift + 7); | |
| 639 | } | |
| 640 | break; | |
| 600 | /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. | |
| 601 | pub fn takeLeb128(br: *BufferedReader, comptime Result: type) anyerror!Result { | |
| 602 | const result_info = @typeInfo(Result).int; | |
| 603 | return std.math.cast(Result, try br.takeMultipleOf7Leb128(@Type(.{ .int = .{ | |
| 604 | .signedness = result_info.signedness, | |
| 605 | .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7), | |
| 606 | } }))) orelse error.Overflow; | |
| 607 | } | |
| 608 | ||
| 609 | fn takeMultipleOf7Leb128(br: *BufferedReader, comptime Result: type) anyerror!Result { | |
| 610 | const result_info = @typeInfo(Result).int; | |
| 611 | comptime assert(result_info.bits % 7 == 0); | |
| 612 | var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits; | |
| 613 | const UnsignedResult = @Type(.{ .int = .{ | |
| 614 | .signedness = .unsigned, | |
| 615 | .bits = result_info.bits, | |
| 616 | } }); | |
| 617 | var result: UnsignedResult = 0; | |
| 618 | var fits = true; | |
| 619 | while (true) { | |
| 620 | const buffer: []const packed struct(u8) { bits: u7, more: bool } = @ptrCast(try br.peekAll(1)); | |
| 621 | for (buffer, 1..) |byte, len| { | |
| 622 | if (remaining_bits > 0) { | |
| 623 | result = @shlExact(@as(UnsignedResult, byte.bits), result_info.bits - 7) | @shrExact(result, 7); | |
| 624 | remaining_bits -= 7; | |
| 625 | } else if (fits) fits = switch (result_info.signedness) { | |
| 626 | .signed => @as(i7, @bitCast(byte.bits)) == @as(i7, @truncate(@as(Result, @bitCast(result)) >> (result_info.bits - 1))), | |
| 627 | .unsigned => byte.bits == 0, | |
| 628 | }; | |
| 629 | if (byte.more) continue; | |
| 630 | br.toss(len); | |
| 631 | return if (fits) @as(Result, @bitCast(result)) >> remaining_bits else error.Overflow; | |
| 641 | 632 | } |
| 642 | } else { | |
| 643 | return error.Overflow; | |
| 644 | } | |
| 645 | ||
| 646 | const result = @as(S, @bitCast(value)); | |
| 647 | // Only applies if we extended to i8 | |
| 648 | if (S != T) { | |
| 649 | if (result > std.math.maxInt(T) or result < std.math.minInt(T)) return error.Overflow; | |
| 633 | br.toss(buffer.len); | |
| 650 | 634 | } |
| 651 | ||
| 652 | return @truncate(result); | |
| 653 | 635 | } |
| 654 | 636 | |
| 655 | 637 | test initFixed { |
| ... | ... | @@ -669,6 +651,10 @@ test peek { |
| 669 | 651 | return error.Unimplemented; |
| 670 | 652 | } |
| 671 | 653 | |
| 654 | test peekAll { | |
| 655 | return error.Unimplemented; | |
| 656 | } | |
| 657 | ||
| 672 | 658 | test toss { |
| 673 | 659 | return error.Unimplemented; |
| 674 | 660 | } |
| ... | ... | @@ -766,10 +752,6 @@ test takeEnum { |
| 766 | 752 | return error.Unimplemented; |
| 767 | 753 | } |
| 768 | 754 | |
| 769 | test takeUleb128 { | |
| 770 | return error.Unimplemented; | |
| 771 | } | |
| 772 | ||
| 773 | test takeIleb128 { | |
| 755 | test takeLeb128 { | |
| 774 | 756 | return error.Unimplemented; |
| 775 | 757 | } |