aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-01-25 23:25:29 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-01-25 23:25:29 -0500
commit9dffc369f1720fabb0a996b5af3c67fe3e4fd830 (patch)
tree409a609e55426c864bfe8a336fc0fa7e06e8f35a /lib/std
parentfbfda7f00edbbf4eb623898d53c3faf43ab874ce (diff)
parent4e9b1f5479e3b7ce47d059e0e6f3d62cd4ee7254 (diff)
downloadzig-9dffc369f1720fabb0a996b5af3c67fe3e4fd830.tar.gz
zig-9dffc369f1720fabb0a996b5af3c67fe3e4fd830.zip
Merge remote-tracking branch 'origin/master' into layneson-cpus_and_features
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/build.zig4
-rw-r--r--lib/std/debug.zig288
-rw-r--r--lib/std/fmt.zig17
-rw-r--r--lib/std/io/out_stream.zig12
-rw-r--r--lib/std/special/compiler_rt.zig1
-rw-r--r--lib/std/special/compiler_rt/int.zig60
6 files changed, 202 insertions, 180 deletions
diff --git a/lib/std/build.zig b/lib/std/build.zig
index ac6ca30494..560f82961c 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -1689,7 +1689,9 @@ pub const LibExeObjStep = struct {
}
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
- self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable;
+ self.link_objects.append(LinkObject{
+ .AssemblyFile = .{ .path = self.builder.dupe(path) },
+ }) catch unreachable;
}
pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void {
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index dfdaca6d3f..33b062db23 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -379,16 +379,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
}
} else {
// we have no information to add to the address
- if (tty_color) {
- try out_stream.print("???:?:?: ", .{});
- setTtyColor(TtyColor.Dim);
- try out_stream.print("0x{x} in ??? (???)", .{relocated_address});
- setTtyColor(TtyColor.Reset);
- try out_stream.print("\n\n\n", .{});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{relocated_address});
- }
- return;
+ return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_color, printLineFromFileAnyOs);
};
const mod = &di.modules[mod_index];
@@ -510,66 +501,15 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
}
};
- if (tty_color) {
- setTtyColor(TtyColor.White);
- if (opt_line_info) |li| {
- try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
- } else {
- try out_stream.print("???:?:?", .{});
- }
- setTtyColor(TtyColor.Reset);
- try out_stream.print(": ", .{});
- setTtyColor(TtyColor.Dim);
- try out_stream.print("0x{x} in {} ({})", .{ relocated_address, symbol_name, obj_basename });
- setTtyColor(TtyColor.Reset);
-
- if (opt_line_info) |line_info| {
- try out_stream.print("\n", .{});
- if (printLineFromFileAnyOs(out_stream, line_info)) {
- if (line_info.column == 0) {
- try out_stream.write("\n");
- } else {
- {
- var col_i: usize = 1;
- while (col_i < line_info.column) : (col_i += 1) {
- try out_stream.writeByte(' ');
- }
- }
- setTtyColor(TtyColor.Green);
- try out_stream.write("^");
- setTtyColor(TtyColor.Reset);
- try out_stream.write("\n");
- }
- } else |err| switch (err) {
- error.EndOfFile => {},
- error.FileNotFound => {
- setTtyColor(TtyColor.Dim);
- try out_stream.write("file not found\n\n");
- setTtyColor(TtyColor.White);
- },
- else => return err,
- }
- } else {
- try out_stream.print("\n\n\n", .{});
- }
- } else {
- if (opt_line_info) |li| {
- try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n\n\n", .{
- li.file_name,
- li.line,
- li.column,
- relocated_address,
- symbol_name,
- obj_basename,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{
- relocated_address,
- symbol_name,
- obj_basename,
- });
- }
- }
+ try printLineInfo(
+ out_stream,
+ opt_line_info,
+ relocated_address,
+ symbol_name,
+ obj_basename,
+ tty_color,
+ printLineFromFileAnyOs,
+ );
}
const TtyColor = enum {
@@ -605,7 +545,11 @@ fn setTtyColor(tty_color: TtyColor) void {
stderr_file.write(RESET) catch return;
},
}
- } else {
+
+ return;
+ }
+
+ if (builtin.os == .windows) {
const S = struct {
var attrs: windows.WORD = undefined;
var init_attrs = false;
@@ -711,12 +655,7 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
const adjusted_addr = 0x100000000 + (address - base_addr);
const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
- }
- return;
+ return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFileAnyOs);
};
const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
@@ -724,29 +663,22 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
break :blk fs.path.basename(ofile_path);
} else "???";
- if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
- defer line_info.deinit();
- try printLineInfo(
- out_stream,
- line_info,
- address,
- symbol_name,
- compile_unit_name,
- tty_color,
- printLineFromFileAnyOs,
- );
- } else |err| switch (err) {
- error.MissingDebugInfo, error.InvalidDebugInfo => {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n\n\n", .{
- address, symbol_name, compile_unit_name,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{ address, symbol_name, compile_unit_name });
- }
- },
+
+ const line_info = getLineNumberInfoMacOs(di, symbol.*, adjusted_addr) catch |err| switch (err) {
+ error.MissingDebugInfo, error.InvalidDebugInfo => null,
else => return err,
- }
+ };
+ defer if (line_info) |li| li.deinit();
+
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_color,
+ printLineFromFileAnyOs,
+ );
}
pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
@@ -755,47 +687,46 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres
fn printLineInfo(
out_stream: var,
- line_info: LineInfo,
+ line_info: ?LineInfo,
address: usize,
symbol_name: []const u8,
compile_unit_name: []const u8,
tty_color: bool,
comptime printLineFromFile: var,
) !void {
- if (tty_color) {
- try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n", .{
- line_info.file_name,
- line_info.line,
- line_info.column,
- address,
- symbol_name,
- compile_unit_name,
- });
- if (printLineFromFile(out_stream, line_info)) {
- if (line_info.column == 0) {
- try out_stream.write("\n");
- } else {
- {
- var col_i: usize = 1;
- while (col_i < line_info.column) : (col_i += 1) {
- try out_stream.writeByte(' ');
- }
- }
- try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
+ if (tty_color) setTtyColor(.White);
+
+ if (line_info) |*li| {
+ try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
+ } else {
+ try out_stream.print("???:?:?", .{});
+ }
+
+ if (tty_color) setTtyColor(.Reset);
+ try out_stream.write(": ");
+ if (tty_color) setTtyColor(.Dim);
+ try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
+ if (tty_color) setTtyColor(.Reset);
+ try out_stream.write("\n");
+
+ // Show the matching source code line if possible
+ if (line_info) |li| {
+ if (noasync printLineFromFile(out_stream, li)) {
+ if (li.column > 0) {
+ // The caret already takes one char
+ const space_needed = @intCast(usize, li.column - 1);
+
+ try out_stream.writeByteNTimes(' ', space_needed);
+ if (tty_color) setTtyColor(.Green);
+ try out_stream.write("^");
+ if (tty_color) setTtyColor(.Reset);
}
+ try out_stream.write("\n");
} else |err| switch (err) {
error.EndOfFile, error.FileNotFound => {},
+ error.BadPathName => {},
else => return err,
}
- } else {
- try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n", .{
- line_info.file_name,
- line_info.line,
- line_info.column,
- address,
- symbol_name,
- compile_unit_name,
- });
}
}
@@ -1240,38 +1171,26 @@ pub const DwarfInfo = struct {
comptime printLineFromFile: var,
) !void {
const compile_unit = self.findCompileUnit(address) catch {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
- }
- return;
+ return printLineInfo(out_stream, null, address, "???", "???", tty_color, printLineFromFile);
};
+
const compile_unit_name = try compile_unit.die.getAttrString(self, DW.AT_name);
- if (self.getLineNumberInfo(compile_unit.*, address)) |line_info| {
- defer line_info.deinit();
- const symbol_name = self.getSymbolName(address) orelse "???";
- try printLineInfo(
- out_stream,
- line_info,
- address,
- symbol_name,
- compile_unit_name,
- tty_color,
- printLineFromFile,
- );
- } else |err| switch (err) {
- error.MissingDebugInfo, error.InvalidDebugInfo => {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? ({})" ++ RESET ++ "\n\n\n", .{
- address, compile_unit_name,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? ({})\n\n\n", .{ address, compile_unit_name });
- }
- },
+ const symbol_name = self.getSymbolName(address) orelse "???";
+ const line_info = self.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
+ error.MissingDebugInfo, error.InvalidDebugInfo => null,
else => return err,
- }
+ };
+ defer if (line_info) |li| li.deinit();
+
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_color,
+ printLineFromFile,
+ );
}
fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 {
@@ -1458,9 +1377,13 @@ pub const DwarfInfo = struct {
if (compile_unit.pc_range) |range| {
if (target_address >= range.start and target_address < range.end) return compile_unit;
}
- if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
- var base_address: usize = 0;
- if (di.debug_ranges) |debug_ranges| {
+ if (di.debug_ranges) |debug_ranges| {
+ if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
+ // All the addresses in the list are relative to the value
+ // specified by DW_AT_low_pc or to some other value encoded
+ // in the list itself
+ var base_address = try compile_unit.die.getAttrAddr(DW.AT_low_pc);
+
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
while (true) {
const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
@@ -1468,18 +1391,21 @@ pub const DwarfInfo = struct {
if (begin_addr == 0 and end_addr == 0) {
break;
}
+ // This entry selects a new value for the base address
if (begin_addr == maxInt(usize)) {
- base_address = begin_addr;
+ base_address = end_addr;
continue;
}
- if (target_address >= begin_addr and target_address < end_addr) {
+ if (target_address >= base_address + begin_addr and target_address < base_address + end_addr) {
return compile_unit;
}
}
+
+ return error.InvalidDebugInfo;
+ } else |err| {
+ if (err != error.MissingDebugInfo) return err;
+ continue;
}
- } else |err| {
- if (err != error.MissingDebugInfo) return err;
- continue;
}
}
return error.MissingDebugInfo;
@@ -1552,7 +1478,8 @@ pub const DwarfInfo = struct {
assert(line_info_offset < di.debug_line.size);
- try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset);
+ const this_unit_offset = di.debug_line.offset + line_info_offset;
+ try di.dwarf_seekable_stream.seekTo(this_unit_offset);
var is_64: bool = undefined;
const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
@@ -1620,7 +1547,9 @@ pub const DwarfInfo = struct {
try di.dwarf_seekable_stream.seekTo(prog_start_offset);
- while (true) {
+ const next_unit_pos = this_unit_offset + next_offset;
+
+ while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
const opcode = try di.dwarf_in_stream.readByte();
if (opcode == DW.LNS_extended_op) {
@@ -1631,7 +1560,7 @@ pub const DwarfInfo = struct {
DW.LNE_end_sequence => {
prog.end_sequence = true;
if (try prog.checkLineMatch()) |info| return info;
- return error.MissingDebugInfo;
+ prog.reset();
},
DW.LNE_set_address => {
const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
@@ -1888,6 +1817,7 @@ const LineNumberProgram = struct {
basic_block: bool,
end_sequence: bool,
+ default_is_stmt: bool,
target_address: usize,
include_dirs: []const []const u8,
file_entries: *ArrayList(FileEntry),
@@ -1900,6 +1830,25 @@ const LineNumberProgram = struct {
prev_basic_block: bool,
prev_end_sequence: bool,
+ // Reset the state machine following the DWARF specification
+ pub fn reset(self: *LineNumberProgram) void {
+ self.address = 0;
+ self.file = 1;
+ self.line = 1;
+ self.column = 0;
+ self.is_stmt = self.default_is_stmt;
+ self.basic_block = false;
+ self.end_sequence = false;
+ // Invalidate all the remaining fields
+ self.prev_address = 0;
+ self.prev_file = undefined;
+ self.prev_line = undefined;
+ self.prev_column = undefined;
+ self.prev_is_stmt = undefined;
+ self.prev_basic_block = undefined;
+ self.prev_end_sequence = undefined;
+ }
+
pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram {
return LineNumberProgram{
.address = 0,
@@ -1911,6 +1860,7 @@ const LineNumberProgram = struct {
.end_sequence = false,
.include_dirs = include_dirs,
.file_entries = file_entries,
+ .default_is_stmt = is_stmt,
.target_address = target_address,
.prev_address = 0,
.prev_file = undefined,
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index adbf409baa..cf3322a995 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -431,7 +431,7 @@ pub fn formatType(
},
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
},
- .Many => {
+ .Many, .C => {
if (ptr_info.child == u8) {
if (fmt.len > 0 and fmt[0] == 's') {
const len = mem.len(u8, value);
@@ -449,9 +449,6 @@ pub fn formatType(
}
return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
},
- .C => {
- return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
- },
},
.Array => |info| {
const Slice = @Type(builtin.TypeInfo{
@@ -1290,8 +1287,16 @@ test "pointer" {
}
test "cstr" {
- try testFmt("cstr: Test C\n", "cstr: {s}\n", .{"Test C"});
- try testFmt("cstr: Test C \n", "cstr: {s:10}\n", .{"Test C"});
+ try testFmt(
+ "cstr: Test C\n",
+ "cstr: {s}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
+ try testFmt(
+ "cstr: Test C \n",
+ "cstr: {s:10}\n",
+ .{@ptrCast([*c]const u8, "Test C")},
+ );
}
test "filesize" {
diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig
index b8f5db6fff..265be066a1 100644
--- a/lib/std/io/out_stream.zig
+++ b/lib/std/io/out_stream.zig
@@ -45,10 +45,14 @@ pub fn OutStream(comptime WriteError: type) type {
}
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void {
- const slice = @as(*const [1]u8, &byte)[0..];
- var i: usize = 0;
- while (i < n) : (i += 1) {
- try self.writeFn(self, slice);
+ var bytes: [256]u8 = undefined;
+ mem.set(u8, bytes[0..], byte);
+
+ var remaining: usize = n;
+ while (remaining > 0) {
+ const to_write = std.math.min(remaining, bytes.len);
+ try self.writeFn(self, bytes[0..to_write]);
+ remaining -= to_write;
}
}
diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig
index 90dbf0cdf4..f5e83b5278 100644
--- a/lib/std/special/compiler_rt.zig
+++ b/lib/std/special/compiler_rt.zig
@@ -130,6 +130,7 @@ comptime {
@export(@import("compiler_rt/int.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage });
@export(@import("compiler_rt/popcountdi2.zig").__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage });
+ @export(@import("compiler_rt/int.zig").__mulsi3, .{ .name = "__mulsi3", .linkage = linkage });
@export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__muldi3", .linkage = linkage });
@export(@import("compiler_rt/int.zig").__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage });
@export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__divsi3", .linkage = linkage });
diff --git a/lib/std/special/compiler_rt/int.zig b/lib/std/special/compiler_rt/int.zig
index 88f4d66966..eb731ee898 100644
--- a/lib/std/special/compiler_rt/int.zig
+++ b/lib/std/special/compiler_rt/int.zig
@@ -1,6 +1,8 @@
// Builtin functions that operate on integer types
const builtin = @import("builtin");
const testing = @import("std").testing;
+const maxInt = @import("std").math.maxInt;
+const minInt = @import("std").math.minInt;
const udivmod = @import("udivmod.zig").udivmod;
@@ -578,3 +580,61 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void {
const r: u32 = __umodsi3(a, b);
testing.expect(r == expected_r);
}
+
+pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
+ @setRuntimeSafety(builtin.is_test);
+
+ var ua = @bitCast(u32, a);
+ var ub = @bitCast(u32, b);
+ var r: u32 = 0;
+
+ while (ua > 0) {
+ if ((ua & 1) != 0) r +%= ub;
+ ua >>= 1;
+ ub <<= 1;
+ }
+
+ return @bitCast(i32, r);
+}
+
+fn test_one_mulsi3(a: i32, b: i32, result: i32) void {
+ testing.expectEqual(result, __mulsi3(a, b));
+}
+
+test "mulsi3" {
+ test_one_mulsi3(0, 0, 0);
+ test_one_mulsi3(0, 1, 0);
+ test_one_mulsi3(1, 0, 0);
+ test_one_mulsi3(0, 10, 0);
+ test_one_mulsi3(10, 0, 0);
+ test_one_mulsi3(0, maxInt(i32), 0);
+ test_one_mulsi3(maxInt(i32), 0, 0);
+ test_one_mulsi3(0, -1, 0);
+ test_one_mulsi3(-1, 0, 0);
+ test_one_mulsi3(0, -10, 0);
+ test_one_mulsi3(-10, 0, 0);
+ test_one_mulsi3(0, minInt(i32), 0);
+ test_one_mulsi3(minInt(i32), 0, 0);
+ test_one_mulsi3(1, 1, 1);
+ test_one_mulsi3(1, 10, 10);
+ test_one_mulsi3(10, 1, 10);
+ test_one_mulsi3(1, maxInt(i32), maxInt(i32));
+ test_one_mulsi3(maxInt(i32), 1, maxInt(i32));
+ test_one_mulsi3(1, -1, -1);
+ test_one_mulsi3(1, -10, -10);
+ test_one_mulsi3(-10, 1, -10);
+ test_one_mulsi3(1, minInt(i32), minInt(i32));
+ test_one_mulsi3(minInt(i32), 1, minInt(i32));
+ test_one_mulsi3(46340, 46340, 2147395600);
+ test_one_mulsi3(-46340, 46340, -2147395600);
+ test_one_mulsi3(46340, -46340, -2147395600);
+ test_one_mulsi3(-46340, -46340, 2147395600);
+ test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
+ test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
+ test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
+ test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
+ test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
+ test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
+ test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
+ test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
+}