authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-12 10:48:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-12 10:48:38-07:00
logaf4cc20ce275aeb0e59eee3d893b2f310c1f0239
treecc3ff8fa792c20ff0fc0f1e19e98998cc76c07c2
parent03a23418ff13e6ff64cdeed3ef4b54f99c533d88
parent9fe4c89230df2d78c8bf37b4b1d7a9bedb92677b

Merge remote-tracking branch 'origin/master' into stage2-zig-cc

Master branch added in the concept of library versioning being optional to main.cpp. It will need to be re-added into this branch before merging back into master.

34 files changed, 1680 insertions(+), 119 deletions(-)

README.md+18
......@@ -76,3 +76,21 @@ Hopefully this will be fixed upstream with LLVM 10.0.1.
7676##### Windows
7777
7878See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
79
80## License
81
82The ultimate goal of the Zig project is to serve users. As a first-order
83effect, this means users of the compiler, helping programmers to write better
84code. Even more important, however, are the end users.
85
86Zig is intended to be used to help end users accomplish their goals. For
87example, it would be inappropriate and offensive to use Zig to implement
88[dark patterns](https://en.wikipedia.org/wiki/Dark_pattern) and it would be
89shameful to utilize Zig to exploit people instead of benefit them.
90
91However, such problems are best solved with social norms, not with software
92licenses. Any attempt to complicate the software license of Zig would risk
93compromising the value Zig provides to users.
94
95Therefore, Zig is available under the MIT (Expat) License, and comes with a
96humble request: use it to make software better serve the needs of end users.
build.zig+1
......@@ -65,6 +65,7 @@ pub fn build(b: *Builder) !void {
6565 "README.md",
6666 ".z.0",
6767 ".z.9",
68 ".gz",
6869 "rfc1951.txt",
6970 },
7071 });
lib/std/build.zig+80-44
......@@ -258,9 +258,14 @@ pub const Builder = struct {
258258 }));
259259 }
260260
261 pub fn addSharedLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
261 pub fn addSharedLibrary(
262 self: *Builder,
263 name: []const u8,
264 root_src: ?[]const u8,
265 kind: LibExeObjStep.SharedLibKind,
266 ) *LibExeObjStep {
262267 const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null;
263 return LibExeObjStep.createSharedLibrary(self, name, root_src_param, ver);
268 return LibExeObjStep.createSharedLibrary(self, name, root_src_param, kind);
264269 }
265270
266271 pub fn addStaticLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
......@@ -338,11 +343,13 @@ pub const Builder = struct {
338343 return TranslateCStep.create(self, source);
339344 }
340345
341 pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {
342 return Version{
343 .major = major,
344 .minor = minor,
345 .patch = patch,
346 pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) LibExeObjStep.SharedLibKind {
347 return .{
348 .versioned = .{
349 .major = major,
350 .minor = minor,
351 .patch = patch,
352 },
346353 };
347354 }
348355
......@@ -1048,6 +1055,7 @@ pub const Builder = struct {
10481055 .Bin => self.exe_dir,
10491056 .Lib => self.lib_dir,
10501057 .Header => self.h_dir,
1058 .Custom => |path| fs.path.join(self.allocator, &[_][]const u8{ self.install_path, path }) catch unreachable,
10511059 };
10521060 return fs.path.resolve(
10531061 self.allocator,
......@@ -1166,7 +1174,7 @@ pub const LibExeObjStep = struct {
11661174 version_script: ?[]const u8 = null,
11671175 out_filename: []const u8,
11681176 is_dynamic: bool,
1169 version: Version,
1177 version: ?Version,
11701178 build_mode: builtin.Mode,
11711179 kind: Kind,
11721180 major_only_filename: []const u8,
......@@ -1212,6 +1220,8 @@ pub const LibExeObjStep = struct {
12121220 is_linking_libc: bool = false,
12131221 vcpkg_bin_path: ?[]const u8 = null,
12141222
1223 /// This may be set in order to override the default install directory
1224 override_dest_dir: ?InstallDir,
12151225 installed_path: ?[]const u8,
12161226 install_step: ?*InstallArtifactStep,
12171227
......@@ -1268,33 +1278,41 @@ pub const LibExeObjStep = struct {
12681278 Test,
12691279 };
12701280
1271 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, ver: Version) *LibExeObjStep {
1281 const SharedLibKind = union(enum) {
1282 versioned: Version,
1283 unversioned: void,
1284 };
1285
1286 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, kind: SharedLibKind) *LibExeObjStep {
12721287 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
1273 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, ver);
1288 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, switch (kind) {
1289 .versioned => |ver| ver,
1290 .unversioned => null,
1291 });
12741292 return self;
12751293 }
12761294
12771295 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
12781296 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
1279 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, builder.version(0, 0, 0));
1297 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, null);
12801298 return self;
12811299 }
12821300
12831301 pub fn createObject(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
12841302 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
1285 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
1303 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, null);
12861304 return self;
12871305 }
12881306
12891307 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?FileSource, is_dynamic: bool) *LibExeObjStep {
12901308 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
1291 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, builder.version(0, 0, 0));
1309 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, null);
12921310 return self;
12931311 }
12941312
12951313 pub fn createTest(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
12961314 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
1297 self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, builder.version(0, 0, 0));
1315 self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, null);
12981316 return self;
12991317 }
13001318
......@@ -1304,7 +1322,7 @@ pub const LibExeObjStep = struct {
13041322 root_src: ?FileSource,
13051323 kind: Kind,
13061324 is_dynamic: bool,
1307 ver: Version,
1325 ver: ?Version,
13081326 ) LibExeObjStep {
13091327 if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {
13101328 panic("invalid name: '{}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
......@@ -1348,6 +1366,7 @@ pub const LibExeObjStep = struct {
13481366 .rdynamic = false,
13491367 .output_dir = null,
13501368 .single_threaded = false,
1369 .override_dest_dir = null,
13511370 .installed_path = null,
13521371 .install_step = null,
13531372 };
......@@ -1375,17 +1394,17 @@ pub const LibExeObjStep = struct {
13751394 self.target.staticLibSuffix(),
13761395 });
13771396 self.out_lib_filename = self.out_filename;
1378 } else {
1397 } else if (self.version) |version| {
13791398 if (self.target.isDarwin()) {
13801399 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", .{
13811400 self.name,
1382 self.version.major,
1383 self.version.minor,
1384 self.version.patch,
1401 version.major,
1402 version.minor,
1403 version.patch,
13851404 });
13861405 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{
13871406 self.name,
1388 self.version.major,
1407 version.major,
13891408 });
13901409 self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name});
13911410 self.out_lib_filename = self.out_filename;
......@@ -1395,14 +1414,25 @@ pub const LibExeObjStep = struct {
13951414 } else {
13961415 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", .{
13971416 self.name,
1398 self.version.major,
1399 self.version.minor,
1400 self.version.patch,
1417 version.major,
1418 version.minor,
1419 version.patch,
14011420 });
1402 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, self.version.major });
1421 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major });
14031422 self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name});
14041423 self.out_lib_filename = self.out_filename;
14051424 }
1425 } else {
1426 if (self.target.isDarwin()) {
1427 self.out_filename = self.builder.fmt("lib{}.dylib", .{self.name});
1428 self.out_lib_filename = self.out_filename;
1429 } else if (self.target.isWindows()) {
1430 self.out_filename = self.builder.fmt("{}.dll", .{self.name});
1431 self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
1432 } else {
1433 self.out_filename = self.builder.fmt("lib{}.so", .{self.name});
1434 self.out_lib_filename = self.out_filename;
1435 }
14061436 }
14071437 },
14081438 }
......@@ -2037,14 +2067,16 @@ pub const LibExeObjStep = struct {
20372067 zig_args.append(self.name) catch unreachable;
20382068
20392069 if (self.kind == Kind.Lib and self.is_dynamic) {
2040 zig_args.append("--ver-major") catch unreachable;
2041 zig_args.append(builder.fmt("{}", .{self.version.major})) catch unreachable;
2070 if (self.version) |version| {
2071 zig_args.append("--ver-major") catch unreachable;
2072 zig_args.append(builder.fmt("{}", .{version.major})) catch unreachable;
20422073
2043 zig_args.append("--ver-minor") catch unreachable;
2044 zig_args.append(builder.fmt("{}", .{self.version.minor})) catch unreachable;
2074 zig_args.append("--ver-minor") catch unreachable;
2075 zig_args.append(builder.fmt("{}", .{version.minor})) catch unreachable;
20452076
2046 zig_args.append("--ver-patch") catch unreachable;
2047 zig_args.append(builder.fmt("{}", .{self.version.patch})) catch unreachable;
2077 zig_args.append("--ver-patch") catch unreachable;
2078 zig_args.append(builder.fmt("{}", .{version.patch})) catch unreachable;
2079 }
20482080 }
20492081 if (self.is_dynamic) {
20502082 try zig_args.append("-dynamic");
......@@ -2285,7 +2317,7 @@ pub const LibExeObjStep = struct {
22852317 }
22862318 }
22872319
2288 if (self.kind == Kind.Lib and self.is_dynamic and self.target.wantSharedLibSymLinks()) {
2320 if (self.kind == Kind.Lib and self.is_dynamic and self.version != null and self.target.wantSharedLibSymLinks()) {
22892321 try doAtomicSymLinks(builder.allocator, self.getOutputPath(), self.major_only_filename, self.name_only_filename);
22902322 }
22912323 }
......@@ -2309,17 +2341,17 @@ pub const InstallArtifactStep = struct {
23092341 .builder = builder,
23102342 .step = Step.init(.InstallArtifact, builder.fmt("install {}", .{artifact.step.name}), builder.allocator, make),
23112343 .artifact = artifact,
2312 .dest_dir = switch (artifact.kind) {
2344 .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) {
23132345 .Obj => unreachable,
23142346 .Test => unreachable,
2315 .Exe => .Bin,
2316 .Lib => .Lib,
2347 .Exe => InstallDir{ .Bin = {} },
2348 .Lib => InstallDir{ .Lib = {} },
23172349 },
23182350 .pdb_dir = if (artifact.producesPdbFile()) blk: {
23192351 if (artifact.kind == .Exe) {
2320 break :blk InstallDir.Bin;
2352 break :blk InstallDir{ .Bin = {} };
23212353 } else {
2322 break :blk InstallDir.Lib;
2354 break :blk InstallDir{ .Lib = {} };
23232355 }
23242356 } else null,
23252357 .h_dir = if (artifact.kind == .Lib and artifact.emit_h) .Header else null,
......@@ -2329,8 +2361,10 @@ pub const InstallArtifactStep = struct {
23292361
23302362 builder.pushInstalledFile(self.dest_dir, artifact.out_filename);
23312363 if (self.artifact.isDynamicLibrary()) {
2332 builder.pushInstalledFile(.Lib, artifact.major_only_filename);
2333 builder.pushInstalledFile(.Lib, artifact.name_only_filename);
2364 if (self.artifact.version != null) {
2365 builder.pushInstalledFile(.Lib, artifact.major_only_filename);
2366 builder.pushInstalledFile(.Lib, artifact.name_only_filename);
2367 }
23342368 if (self.artifact.target.isWindows()) {
23352369 builder.pushInstalledFile(.Lib, artifact.out_lib_filename);
23362370 }
......@@ -2350,7 +2384,7 @@ pub const InstallArtifactStep = struct {
23502384
23512385 const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename);
23522386 try builder.updateFile(self.artifact.getOutputPath(), full_dest_path);
2353 if (self.artifact.isDynamicLibrary() and self.artifact.target.wantSharedLibSymLinks()) {
2387 if (self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) {
23542388 try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename, self.artifact.name_only_filename);
23552389 }
23562390 if (self.pdb_dir) |pdb_dir| {
......@@ -2615,11 +2649,13 @@ const VcpkgRootStatus = enum {
26152649
26162650pub const VcpkgLinkage = std.builtin.LinkMode;
26172651
2618pub const InstallDir = enum {
2619 Prefix,
2620 Lib,
2621 Bin,
2622 Header,
2652pub const InstallDir = union(enum) {
2653 Prefix: void,
2654 Lib: void,
2655 Bin: void,
2656 Header: void,
2657 /// A path relative to the prefix
2658 Custom: []const u8,
26232659};
26242660
26252661pub const InstalledFile = struct {
lib/std/c.zig+11-4
......@@ -132,8 +132,6 @@ pub usingnamespace switch (builtin.os.tag) {
132132 },
133133};
134134
135pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
136pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;
137135pub extern "c" fn rmdir(path: [*:0]const u8) c_int;
138136pub extern "c" fn getenv(name: [*:0]const u8) ?[*:0]u8;
139137pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
......@@ -237,8 +235,15 @@ pub usingnamespace switch (builtin.os.tag) {
237235
238236pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
239237pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
240pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
241pub extern "c" fn setuid(uid: c_uint) c_int;
238
239pub extern "c" fn setuid(uid: uid_t) c_int;
240pub extern "c" fn setgid(gid: gid_t) c_int;
241pub extern "c" fn seteuid(euid: uid_t) c_int;
242pub extern "c" fn setegid(egid: gid_t) c_int;
243pub extern "c" fn setreuid(ruid: uid_t, euid: uid_t) c_int;
244pub extern "c" fn setregid(rgid: gid_t, egid: gid_t) c_int;
245pub extern "c" fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) c_int;
246pub extern "c" fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) c_int;
242247
243248pub extern "c" fn aligned_alloc(alignment: usize, size: usize) ?*c_void;
244249pub extern "c" fn malloc(usize) ?*c_void;
......@@ -335,3 +340,5 @@ pub extern "c" fn sync() void;
335340pub extern "c" fn syncfs(fd: c_int) c_int;
336341pub extern "c" fn fsync(fd: c_int) c_int;
337342pub extern "c" fn fdatasync(fd: c_int) c_int;
343
344pub extern "c" fn prctl(option: c_int, ...) c_int;
lib/std/compress.zig+2
......@@ -6,8 +6,10 @@
66const std = @import("std.zig");
77
88pub const deflate = @import("compress/deflate.zig");
9pub const gzip = @import("compress/gzip.zig");
910pub const zlib = @import("compress/zlib.zig");
1011
1112test "" {
13 _ = gzip;
1214 _ = zlib;
1315}
lib/std/compress/deflate.zig+149-35
......@@ -21,48 +21,121 @@ const MAXDCODES = 30;
2121const MAXCODES = MAXLCODES + MAXDCODES;
2222const FIXLCODES = 288;
2323
24// The maximum length of a Huffman code's prefix we can decode using the fast
25// path. The factor 9 is inherited from Zlib, tweaking the value showed little
26// or no changes in the profiler output.
27const PREFIX_LUT_BITS = 9;
28
2429const Huffman = struct {
30 // Number of codes for each possible length
2531 count: [MAXBITS + 1]u16,
32 // Mapping between codes and symbols
2633 symbol: [MAXCODES]u16,
2734
28 fn construct(self: *Huffman, length: []const u16) !void {
35 // The decoding process uses a trick explained by Mark Adler in [1].
36 // We basically precompute for a fixed number of codes (0 <= x <= 2^N-1)
37 // the symbol and the effective code length we'd get if the decoder was run
38 // on the given N-bit sequence.
39 // A code with length 0 means the sequence is not a valid prefix for this
40 // canonical Huffman code and we have to decode it using a slower method.
41 //
42 // [1] https://github.com/madler/zlib/blob/v1.2.11/doc/algorithm.txt#L58
43 prefix_lut: [1 << PREFIX_LUT_BITS]u16,
44 prefix_lut_len: [1 << PREFIX_LUT_BITS]u16,
45 // The following info refer to the codes of length PREFIX_LUT_BITS+1 and are
46 // used to bootstrap the bit-by-bit reading method if the fast-path fails.
47 last_code: u16,
48 last_index: u16,
49
50 fn construct(self: *Huffman, code_length: []const u16) !void {
2951 for (self.count) |*val| {
3052 val.* = 0;
3153 }
3254
33 for (length) |val| {
34 self.count[val] += 1;
55 for (code_length) |len| {
56 self.count[len] += 1;
3557 }
3658
37 if (self.count[0] == length.len)
59 // All zero.
60 if (self.count[0] == code_length.len)
3861 return;
3962
4063 var left: isize = 1;
4164 for (self.count[1..]) |val| {
65 // Each added bit doubles the amount of codes.
4266 left *= 2;
67 // Make sure the number of codes with this length isn't too high.
4368 left -= @as(isize, @bitCast(i16, val));
4469 if (left < 0)
4570 return error.InvalidTree;
4671 }
4772
48 var offs: [MAXBITS + 1]u16 = undefined;
73 // Compute the offset of the first symbol represented by a code of a
74 // given length in the symbol table, together with the first canonical
75 // Huffman code for that length.
76 var offset: [MAXBITS + 1]u16 = undefined;
77 var codes: [MAXBITS + 1]u16 = undefined;
4978 {
79 offset[1] = 0;
80 codes[1] = 0;
5081 var len: usize = 1;
51 offs[1] = 0;
5282 while (len < MAXBITS) : (len += 1) {
53 offs[len + 1] = offs[len] + self.count[len];
83 offset[len + 1] = offset[len] + self.count[len];
84 codes[len + 1] = (codes[len] + self.count[len]) << 1;
5485 }
5586 }
5687
57 for (length) |val, symbol| {
58 if (val != 0) {
59 self.symbol[offs[val]] = @truncate(u16, symbol);
60 offs[val] += 1;
88 self.prefix_lut_len = mem.zeroes(@TypeOf(self.prefix_lut_len));
89
90 for (code_length) |len, symbol| {
91 if (len != 0) {
92 // Fill the symbol table.
93 // The symbols are assigned sequentially for each length.
94 self.symbol[offset[len]] = @truncate(u16, symbol);
95 // Track the last assigned offset
96 offset[len] += 1;
97 }
98
99 if (len == 0 or len > PREFIX_LUT_BITS)
100 continue;
101
102 // Given a Huffman code of length N we have to massage it so
103 // that it becomes an index in the lookup table.
104 // The bit order is reversed as the fast path reads the bit
105 // sequence MSB to LSB using an &, the order is flipped wrt the
106 // one obtained by reading bit-by-bit.
107 // The codes are prefix-free, if the prefix matches we can
108 // safely ignore the trail bits. We do so by replicating the
109 // symbol info for each combination of the trailing bits.
110 const bits_to_fill = @intCast(u5, PREFIX_LUT_BITS - len);
111 const rev_code = bitReverse(codes[len], len);
112 // Track the last used code, but only for lengths < PREFIX_LUT_BITS
113 codes[len] += 1;
114
115 var j: usize = 0;
116 while (j < @as(usize, 1) << bits_to_fill) : (j += 1) {
117 const index = rev_code | (j << @intCast(u5, len));
118 assert(self.prefix_lut_len[index] == 0);
119 self.prefix_lut[index] = @truncate(u16, symbol);
120 self.prefix_lut_len[index] = @truncate(u16, len);
61121 }
62122 }
123
124 self.last_code = codes[PREFIX_LUT_BITS + 1];
125 self.last_index = offset[PREFIX_LUT_BITS + 1] - self.count[PREFIX_LUT_BITS + 1];
63126 }
64127};
65128
129// Reverse bit-by-bit a N-bit value
130fn bitReverse(x: usize, N: usize) usize {
131 var tmp: usize = 0;
132 var i: usize = 0;
133 while (i < N) : (i += 1) {
134 tmp |= ((x >> @intCast(u5, i)) & 1) << @intCast(u5, N - i - 1);
135 }
136 return tmp;
137}
138
66139pub fn InflateStream(comptime ReaderType: type) type {
67140 return struct {
68141 const Self = @This();
......@@ -83,7 +156,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
83156 };
84157 pub const Reader = io.Reader(*Self, Error, read);
85158
86 bit_reader: io.BitReader(.Little, ReaderType),
159 inner_reader: ReaderType,
87160
88161 // True if the decoder met the end of the compressed stream, no further
89162 // data can be decompressed
......@@ -135,7 +208,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
135208
136209 // Insert a single byte into the window.
137210 // Assumes there's enough space.
138 fn appendUnsafe(self: *WSelf, value: u8) void {
211 inline fn appendUnsafe(self: *WSelf, value: u8) void {
139212 self.buf[self.wi] = value;
140213 self.wi = (self.wi + 1) & (self.buf.len - 1);
141214 self.el += 1;
......@@ -180,7 +253,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
180253 // of the window memory for the non-overlapping case.
181254 var i: usize = 0;
182255 while (i < N) : (i += 1) {
183 const index = (self.wi -% distance) % self.buf.len;
256 const index = (self.wi -% distance) & (self.buf.len - 1);
184257 self.appendUnsafe(self.buf[index]);
185258 }
186259
......@@ -196,13 +269,36 @@ pub fn InflateStream(comptime ReaderType: type) type {
196269 hdist: *Huffman,
197270 hlen: *Huffman,
198271
272 // Temporary buffer for the bitstream, only bits 0..`bits_left` are
273 // considered valid.
274 bits: u32,
275 bits_left: usize,
276
277 fn peekBits(self: *Self, bits: usize) !u32 {
278 while (self.bits_left < bits) {
279 const byte = try self.inner_reader.readByte();
280 self.bits |= @as(u32, byte) << @intCast(u5, self.bits_left);
281 self.bits_left += 8;
282 }
283 return self.bits & ((@as(u32, 1) << @intCast(u5, bits)) - 1);
284 }
285 fn readBits(self: *Self, bits: usize) !u32 {
286 const val = self.peekBits(bits);
287 self.discardBits(bits);
288 return val;
289 }
290 fn discardBits(self: *Self, bits: usize) void {
291 self.bits >>= @intCast(u5, bits);
292 self.bits_left -= bits;
293 }
294
199295 fn stored(self: *Self) !void {
200296 // Discard the remaining bits, the lenght field is always
201297 // byte-aligned (and so is the data)
202 self.bit_reader.alignToByte();
298 self.discardBits(self.bits_left);
203299
204 const length = (try self.bit_reader.readBitsNoEof(u16, 16));
205 const length_cpl = (try self.bit_reader.readBitsNoEof(u16, 16));
300 const length = try self.inner_reader.readIntLittle(u16);
301 const length_cpl = try self.inner_reader.readIntLittle(u16);
206302
207303 if (length != ~length_cpl)
208304 return error.InvalidStoredSize;
......@@ -237,11 +333,11 @@ pub fn InflateStream(comptime ReaderType: type) type {
237333
238334 fn dynamic(self: *Self) !void {
239335 // Number of length codes
240 const nlen = (try self.bit_reader.readBitsNoEof(usize, 5)) + 257;
336 const nlen = (try self.readBits(5)) + 257;
241337 // Number of distance codes
242 const ndist = (try self.bit_reader.readBitsNoEof(usize, 5)) + 1;
338 const ndist = (try self.readBits(5)) + 1;
243339 // Number of code length codes
244 const ncode = (try self.bit_reader.readBitsNoEof(usize, 4)) + 4;
340 const ncode = (try self.readBits(4)) + 4;
245341
246342 if (nlen > MAXLCODES or ndist > MAXDCODES)
247343 return error.BadCounts;
......@@ -259,7 +355,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
259355
260356 // Read the code lengths, missing ones are left as zero
261357 for (ORDER[0..ncode]) |val| {
262 lengths[val] = try self.bit_reader.readBitsNoEof(u16, 3);
358 lengths[val] = @intCast(u16, try self.readBits(3));
263359 }
264360
265361 try lencode.construct(lengths[0..]);
......@@ -284,7 +380,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
284380 if (i == 0) return error.NoLastLength;
285381
286382 const last_length = lengths[i - 1];
287 const repeat = 3 + (try self.bit_reader.readBitsNoEof(usize, 2));
383 const repeat = 3 + (try self.readBits(2));
288384 const last_index = i + repeat;
289385 while (i < last_index) : (i += 1) {
290386 lengths[i] = last_length;
......@@ -292,11 +388,11 @@ pub fn InflateStream(comptime ReaderType: type) type {
292388 },
293389 17 => {
294390 // repeat zero 3..10 times
295 i += 3 + (try self.bit_reader.readBitsNoEof(usize, 3));
391 i += 3 + (try self.readBits(3));
296392 },
297393 18 => {
298394 // repeat zero 11..138 times
299 i += 11 + (try self.bit_reader.readBitsNoEof(usize, 7));
395 i += 11 + (try self.readBits(7));
300396 },
301397 else => return error.InvalidSymbol,
302398 }
......@@ -359,11 +455,11 @@ pub fn InflateStream(comptime ReaderType: type) type {
359455 // Length/distance pair
360456 const length_symbol = symbol - 257;
361457 const length = LENS[length_symbol] +
362 try self.bit_reader.readBitsNoEof(u16, LEXT[length_symbol]);
458 @intCast(u16, try self.readBits(LEXT[length_symbol]));
363459
364460 const distance_symbol = try self.decode(distcode);
365461 const distance = DISTS[distance_symbol] +
366 try self.bit_reader.readBitsNoEof(u16, DEXT[distance_symbol]);
462 @intCast(u16, try self.readBits(DEXT[distance_symbol]));
367463
368464 if (distance > self.window.buf.len)
369465 return error.InvalidDistance;
......@@ -385,13 +481,29 @@ pub fn InflateStream(comptime ReaderType: type) type {
385481 }
386482
387483 fn decode(self: *Self, h: *Huffman) !u16 {
388 var len: usize = 1;
389 var code: usize = 0;
390 var first: usize = 0;
391 var index: usize = 0;
484 // Fast path, read some bits and hope they're prefixes of some code
485 const prefix = try self.peekBits(PREFIX_LUT_BITS);
486 if (h.prefix_lut_len[prefix] != 0) {
487 self.discardBits(h.prefix_lut_len[prefix]);
488 return h.prefix_lut[prefix];
489 }
490
491 // The sequence we've read is not a prefix of any code of length <=
492 // PREFIX_LUT_BITS, keep decoding it using a slower method
493 self.discardBits(PREFIX_LUT_BITS);
494
495 // Speed up the decoding by starting from the first code length
496 // that's not covered by the table
497 var len: usize = PREFIX_LUT_BITS + 1;
498 var first: usize = h.last_code;
499 var index: usize = h.last_index;
500
501 // Reverse the prefix so that the LSB becomes the MSB and make space
502 // for the next bit
503 var code = bitReverse(prefix, PREFIX_LUT_BITS + 1);
392504
393505 while (len <= MAXBITS) : (len += 1) {
394 code |= try self.bit_reader.readBitsNoEof(usize, 1);
506 code |= try self.readBits(1);
395507 const count = h.count[len];
396508 if (code < first + count)
397509 return h.symbol[index + (code - first)];
......@@ -411,8 +523,8 @@ pub fn InflateStream(comptime ReaderType: type) type {
411523 // The compressed stream is done
412524 if (self.seen_eos) return;
413525
414 const last = try self.bit_reader.readBitsNoEof(u1, 1);
415 const kind = try self.bit_reader.readBitsNoEof(u2, 2);
526 const last = @intCast(u1, try self.readBits(1));
527 const kind = @intCast(u2, try self.readBits(2));
416528
417529 self.seen_eos = last != 0;
418530
......@@ -439,7 +551,7 @@ pub fn InflateStream(comptime ReaderType: type) type {
439551 var i: usize = 0;
440552 while (i < N) : (i += 1) {
441553 var tmp: [1]u8 = undefined;
442 if ((try self.bit_reader.read(&tmp)) != 1) {
554 if ((try self.inner_reader.read(&tmp)) != 1) {
443555 // Unexpected end of stream, keep this error
444556 // consistent with the use of readBitsNoEof
445557 return error.EndOfStream;
......@@ -478,12 +590,14 @@ pub fn InflateStream(comptime ReaderType: type) type {
478590 assert(math.isPowerOfTwo(window_slice.len));
479591
480592 return Self{
481 .bit_reader = io.bitReader(.Little, source),
593 .inner_reader = source,
482594 .window = .{ .buf = window_slice },
483595 .seen_eos = false,
484596 .state = .DecodeBlockHeader,
485597 .hdist = undefined,
486598 .hlen = undefined,
599 .bits = 0,
600 .bits_left = 0,
487601 };
488602 }
489603
lib/std/compress/gzip.zig created+248
......@@ -0,0 +1,248 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6//
7// Decompressor for GZIP data streams (RFC1952)
8
9const std = @import("std");
10const io = std.io;
11const fs = std.fs;
12const testing = std.testing;
13const mem = std.mem;
14const deflate = std.compress.deflate;
15
16// Flags for the FLG field in the header
17const FTEXT = 1 << 0;
18const FHCRC = 1 << 1;
19const FEXTRA = 1 << 2;
20const FNAME = 1 << 3;
21const FCOMMENT = 1 << 4;
22
23pub fn GzipStream(comptime ReaderType: type) type {
24 return struct {
25 const Self = @This();
26
27 pub const Error = ReaderType.Error ||
28 deflate.InflateStream(ReaderType).Error ||
29 error{ CorruptedData, WrongChecksum };
30 pub const Reader = io.Reader(*Self, Error, read);
31
32 allocator: *mem.Allocator,
33 inflater: deflate.InflateStream(ReaderType),
34 in_reader: ReaderType,
35 hasher: std.hash.Crc32,
36 window_slice: []u8,
37 read_amt: usize,
38
39 info: struct {
40 filename: ?[]const u8,
41 comment: ?[]const u8,
42 modification_time: u32,
43 },
44
45 fn init(allocator: *mem.Allocator, source: ReaderType) !Self {
46 // gzip header format is specified in RFC1952
47 const header = try source.readBytesNoEof(10);
48
49 // Check the ID1/ID2 fields
50 if (header[0] != 0x1f or header[1] != 0x8b)
51 return error.BadHeader;
52
53 const CM = header[2];
54 // The CM field must be 8 to indicate the use of DEFLATE
55 if (CM != 8) return error.InvalidCompression;
56 // Flags
57 const FLG = header[3];
58 // Modification time, as a Unix timestamp.
59 // If zero there's no timestamp available.
60 const MTIME = mem.readIntLittle(u32, header[4..8]);
61 // Extra flags
62 const XFL = header[8];
63 // Operating system where the compression took place
64 const OS = header[9];
65
66 if (FLG & FEXTRA != 0) {
67 // Skip the extra data, we could read and expose it to the user
68 // if somebody needs it.
69 const len = try source.readIntLittle(u16);
70 try source.skipBytes(len, .{});
71 }
72
73 var filename: ?[]const u8 = null;
74 if (FLG & FNAME != 0) {
75 filename = try source.readUntilDelimiterAlloc(
76 allocator,
77 0,
78 std.math.maxInt(usize),
79 );
80 }
81 errdefer if (filename) |p| allocator.free(p);
82
83 var comment: ?[]const u8 = null;
84 if (FLG & FCOMMENT != 0) {
85 comment = try source.readUntilDelimiterAlloc(
86 allocator,
87 0,
88 std.math.maxInt(usize),
89 );
90 }
91 errdefer if (comment) |p| allocator.free(p);
92
93 if (FLG & FHCRC != 0) {
94 // TODO: Evaluate and check the header checksum. The stdlib has
95 // no CRC16 yet :(
96 _ = try source.readIntLittle(u16);
97 }
98
99 // The RFC doesn't say anything about the DEFLATE window size to be
100 // used, default to 32K.
101 var window_slice = try allocator.alloc(u8, 32 * 1024);
102
103 return Self{
104 .allocator = allocator,
105 .inflater = deflate.inflateStream(source, window_slice),
106 .in_reader = source,
107 .hasher = std.hash.Crc32.init(),
108 .window_slice = window_slice,
109 .info = .{
110 .filename = filename,
111 .comment = comment,
112 .modification_time = MTIME,
113 },
114 .read_amt = 0,
115 };
116 }
117
118 pub fn deinit(self: *Self) void {
119 self.allocator.free(self.window_slice);
120 if (self.info.filename) |filename|
121 self.allocator.free(filename);
122 if (self.info.comment) |comment|
123 self.allocator.free(comment);
124 }
125
126 // Implements the io.Reader interface
127 pub fn read(self: *Self, buffer: []u8) Error!usize {
128 if (buffer.len == 0)
129 return 0;
130
131 // Read from the compressed stream and update the computed checksum
132 const r = try self.inflater.read(buffer);
133 if (r != 0) {
134 self.hasher.update(buffer[0..r]);
135 self.read_amt += r;
136 return r;
137 }
138
139 // We've reached the end of stream, check if the checksum matches
140 const hash = try self.in_reader.readIntLittle(u32);
141 if (hash != self.hasher.final())
142 return error.WrongChecksum;
143
144 // The ISIZE field is the size of the uncompressed input modulo 2^32
145 const input_size = try self.in_reader.readIntLittle(u32);
146 if (self.read_amt & 0xffffffff != input_size)
147 return error.CorruptedData;
148
149 return 0;
150 }
151
152 pub fn reader(self: *Self) Reader {
153 return .{ .context = self };
154 }
155 };
156}
157
158pub fn gzipStream(allocator: *mem.Allocator, reader: anytype) !GzipStream(@TypeOf(reader)) {
159 return GzipStream(@TypeOf(reader)).init(allocator, reader);
160}
161
162fn testReader(data: []const u8, comptime expected: []const u8) !void {
163 var in_stream = io.fixedBufferStream(data);
164
165 var gzip_stream = try gzipStream(testing.allocator, in_stream.reader());
166 defer gzip_stream.deinit();
167
168 // Read and decompress the whole file
169 const buf = try gzip_stream.reader().readAllAlloc(testing.allocator, std.math.maxInt(usize));
170 defer testing.allocator.free(buf);
171 // Calculate its SHA256 hash and check it against the reference
172 var hash: [32]u8 = undefined;
173 std.crypto.hash.sha2.Sha256.hash(buf, hash[0..], .{});
174
175 assertEqual(expected, &hash);
176}
177
178// Assert `expected` == `input` where `input` is a bytestring.
179pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
180 var expected_bytes: [expected.len / 2]u8 = undefined;
181 for (expected_bytes) |*r, i| {
182 r.* = std.fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
183 }
184
185 testing.expectEqualSlices(u8, &expected_bytes, input);
186}
187
188// All the test cases are obtained by compressing the RFC1952 text
189//
190// https://tools.ietf.org/rfc/rfc1952.txt length=25037 bytes
191// SHA256=164ef0897b4cbec63abf1b57f069f3599bd0fb7c72c2a4dee21bd7e03ec9af67
192test "compressed data" {
193 try testReader(
194 @embedFile("rfc1952.txt.gz"),
195 "164ef0897b4cbec63abf1b57f069f3599bd0fb7c72c2a4dee21bd7e03ec9af67",
196 );
197}
198
199test "sanity checks" {
200 // Truncated header
201 testing.expectError(
202 error.EndOfStream,
203 testReader(&[_]u8{ 0x1f, 0x8B }, ""),
204 );
205 // Wrong CM
206 testing.expectError(
207 error.InvalidCompression,
208 testReader(&[_]u8{
209 0x1f, 0x8b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x03,
211 }, ""),
212 );
213 // Wrong checksum
214 testing.expectError(
215 error.WrongChecksum,
216 testReader(&[_]u8{
217 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01,
219 0x00, 0x00, 0x00, 0x00,
220 }, ""),
221 );
222 // Truncated checksum
223 testing.expectError(
224 error.EndOfStream,
225 testReader(&[_]u8{
226 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
228 }, ""),
229 );
230 // Wrong initial size
231 testing.expectError(
232 error.CorruptedData,
233 testReader(&[_]u8{
234 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x01,
237 }, ""),
238 );
239 // Truncated initial size field
240 testing.expectError(
241 error.EndOfStream,
242 testReader(&[_]u8{
243 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00,
246 }, ""),
247 );
248}
lib/std/compress/rfc1952.txt.gz created
Binary files /dev/null and b/lib/std/compress/rfc1952.txt.gz differ
lib/std/event/loop.zig+2-1
......@@ -112,7 +112,8 @@ pub const Loop = struct {
112112 /// have the correct pointer value.
113113 /// https://github.com/ziglang/zig/issues/2761 and https://github.com/ziglang/zig/issues/2765
114114 pub fn init(self: *Loop) !void {
115 if (builtin.single_threaded) {
115 if (builtin.single_threaded
116 or (@hasDecl(root, "event_loop_mode") and root.event_loop_mode == .single_threaded)) {
116117 return self.initSingleThreaded();
117118 } else {
118119 return self.initMultiThreaded();
lib/std/fs/file.zig+5-3
......@@ -728,7 +728,7 @@ pub const File = struct {
728728 }
729729 var i: usize = 0;
730730 while (i < trailers.len) {
731 while (amt >= headers[i].iov_len) {
731 while (amt >= trailers[i].iov_len) {
732732 amt -= trailers[i].iov_len;
733733 i += 1;
734734 if (i >= trailers.len) return;
......@@ -740,14 +740,16 @@ pub const File = struct {
740740 }
741741
742742 pub const Reader = io.Reader(File, ReadError, read);
743
743744 /// Deprecated: use `Reader`
744745 pub const InStream = Reader;
745746
746 pub fn reader(file: File) io.Reader(File, ReadError, read) {
747 pub fn reader(file: File) Reader {
747748 return .{ .context = file };
748749 }
750
749751 /// Deprecated: use `reader`
750 pub fn inStream(file: File) io.InStream(File, ReadError, read) {
752 pub fn inStream(file: File) Reader {
751753 return .{ .context = file };
752754 }
753755
lib/std/os.zig+41-2
......@@ -2515,9 +2515,9 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
25152515pub const SetEidError = error{
25162516 InvalidUserId,
25172517 PermissionDenied,
2518};
2518} || UnexpectedError;
25192519
2520pub const SetIdError = error{ResourceLimitReached} || SetEidError || UnexpectedError;
2520pub const SetIdError = error{ResourceLimitReached} || SetEidError;
25212521
25222522pub fn setuid(uid: uid_t) SetIdError!void {
25232523 switch (errno(system.setuid(uid))) {
......@@ -5418,3 +5418,42 @@ pub fn fdatasync(fd: fd_t) SyncError!void {
54185418 else => |err| return std.os.unexpectedErrno(err),
54195419 }
54205420}
5421
5422pub const PrctlError = error{
5423 /// Can only occur with PR_SET_SECCOMP/SECCOMP_MODE_FILTER or
5424 /// PR_SET_MM/PR_SET_MM_EXE_FILE
5425 AccessDenied,
5426 /// Can only occur with PR_SET_MM/PR_SET_MM_EXE_FILE
5427 InvalidFileDescriptor,
5428 InvalidAddress,
5429 /// Can only occur with PR_SET_SPECULATION_CTRL, PR_MPX_ENABLE_MANAGEMENT,
5430 /// or PR_MPX_DISABLE_MANAGEMENT
5431 UnsupportedFeature,
5432 /// Can only occur wih PR_SET_FP_MODE
5433 OperationNotSupported,
5434 PermissionDenied,
5435} || UnexpectedError;
5436
5437pub fn prctl(option: i32, args: anytype) PrctlError!u31 {
5438 if (@typeInfo(@TypeOf(args)) != .Struct)
5439 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
5440 if (args.len > 4)
5441 @compileError("prctl takes a maximum of 4 optional arguments");
5442
5443 var buf: [4]usize = undefined;
5444 inline for (args) |arg, i| buf[i] = arg;
5445
5446 const rc = system.prctl(option, buf[0], buf[1], buf[2], buf[3]);
5447 switch (errno(rc)) {
5448 0 => return @intCast(u31, rc),
5449 EACCES => return error.AccessDenied,
5450 EBADF => return error.InvalidFileDescriptor,
5451 EFAULT => return error.InvalidAddress,
5452 EINVAL => unreachable,
5453 ENODEV, ENXIO => return error.UnsupportedFeature,
5454 EOPNOTSUPP => return error.OperationNotSupported,
5455 EPERM, EBUSY => return error.PermissionDenied,
5456 ERANGE => unreachable,
5457 else => |err| return std.os.unexpectedErrno(err),
5458 }
5459}
lib/std/os/bits/linux.zig+3
......@@ -20,10 +20,13 @@ pub usingnamespace switch (builtin.arch) {
2020 .arm => @import("linux/arm-eabi.zig"),
2121 .riscv64 => @import("linux/riscv64.zig"),
2222 .mips, .mipsel => @import("linux/mips.zig"),
23 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
2324 else => struct {},
2425};
2526
2627pub usingnamespace @import("linux/netlink.zig");
28pub usingnamespace @import("linux/prctl.zig");
29pub usingnamespace @import("linux/securebits.zig");
2730
2831const is_mips = builtin.arch.isMIPS();
2932
lib/std/os/bits/linux/powerpc64.zig created+602
......@@ -0,0 +1,602 @@
1const std = @import("../../../std.zig");
2const linux = std.os.linux;
3const socklen_t = linux.socklen_t;
4const iovec = linux.iovec;
5const iovec_const = linux.iovec_const;
6const uid_t = linux.uid_t;
7const gid_t = linux.gid_t;
8const pid_t = linux.pid_t;
9const stack_t = linux.stack_t;
10const sigset_t = linux.sigset_t;
11pub const SYS = extern enum(usize) {
12 restart_syscall = 0,
13 exit = 1,
14 fork = 2,
15 read = 3,
16 write = 4,
17 open = 5,
18 close = 6,
19 waitpid = 7,
20 creat = 8,
21 link = 9,
22 unlink = 10,
23 execve = 11,
24 chdir = 12,
25 time = 13,
26 mknod = 14,
27 chmod = 15,
28 lchown = 16,
29 @"break" = 17,
30 oldstat = 18,
31 lseek = 19,
32 getpid = 20,
33 mount = 21,
34 umount = 22,
35 setuid = 23,
36 getuid = 24,
37 stime = 25,
38 ptrace = 26,
39 alarm = 27,
40 oldfstat = 28,
41 pause = 29,
42 utime = 30,
43 stty = 31,
44 gtty = 32,
45 access = 33,
46 nice = 34,
47 ftime = 35,
48 sync = 36,
49 kill = 37,
50 rename = 38,
51 mkdir = 39,
52 rmdir = 40,
53 dup = 41,
54 pipe = 42,
55 times = 43,
56 prof = 44,
57 brk = 45,
58 setgid = 46,
59 getgid = 47,
60 signal = 48,
61 geteuid = 49,
62 getegid = 50,
63 acct = 51,
64 umount2 = 52,
65 lock = 53,
66 ioctl = 54,
67 fcntl = 55,
68 mpx = 56,
69 setpgid = 57,
70 ulimit = 58,
71 oldolduname = 59,
72 umask = 60,
73 chroot = 61,
74 ustat = 62,
75 dup2 = 63,
76 getppid = 64,
77 getpgrp = 65,
78 setsid = 66,
79 sigaction = 67,
80 sgetmask = 68,
81 ssetmask = 69,
82 setreuid = 70,
83 setregid = 71,
84 sigsuspend = 72,
85 sigpending = 73,
86 sethostname = 74,
87 setrlimit = 75,
88 getrlimit = 76,
89 getrusage = 77,
90 gettimeofday = 78,
91 settimeofday = 79,
92 getgroups = 80,
93 setgroups = 81,
94 select = 82,
95 symlink = 83,
96 oldlstat = 84,
97 readlink = 85,
98 uselib = 86,
99 swapon = 87,
100 reboot = 88,
101 readdir = 89,
102 mmap = 90,
103 munmap = 91,
104 truncate = 92,
105 ftruncate = 93,
106 fchmod = 94,
107 fchown = 95,
108 getpriority = 96,
109 setpriority = 97,
110 profil = 98,
111 statfs = 99,
112 fstatfs = 100,
113 ioperm = 101,
114 socketcall = 102,
115 syslog = 103,
116 setitimer = 104,
117 getitimer = 105,
118 stat = 106,
119 lstat = 107,
120 fstat = 108,
121 olduname = 109,
122 iopl = 110,
123 vhangup = 111,
124 idle = 112,
125 vm86 = 113,
126 wait4 = 114,
127 swapoff = 115,
128 sysinfo = 116,
129 ipc = 117,
130 fsync = 118,
131 sigreturn = 119,
132 clone = 120,
133 setdomainname = 121,
134 uname = 122,
135 modify_ldt = 123,
136 adjtimex = 124,
137 mprotect = 125,
138 sigprocmask = 126,
139 create_module = 127,
140 init_module = 128,
141 delete_module = 129,
142 get_kernel_syms = 130,
143 quotactl = 131,
144 getpgid = 132,
145 fchdir = 133,
146 bdflush = 134,
147 sysfs = 135,
148 personality = 136,
149 afs_syscall = 137,
150 setfsuid = 138,
151 setfsgid = 139,
152 _llseek = 140,
153 getdents = 141,
154 _newselect = 142,
155 flock = 143,
156 msync = 144,
157 readv = 145,
158 writev = 146,
159 getsid = 147,
160 fdatasync = 148,
161 _sysctl = 149,
162 mlock = 150,
163 munlock = 151,
164 mlockall = 152,
165 munlockall = 153,
166 sched_setparam = 154,
167 sched_getparam = 155,
168 sched_setscheduler = 156,
169 sched_getscheduler = 157,
170 sched_yield = 158,
171 sched_get_priority_max = 159,
172 sched_get_priority_min = 160,
173 sched_rr_get_interval = 161,
174 nanosleep = 162,
175 mremap = 163,
176 setresuid = 164,
177 getresuid = 165,
178 query_module = 166,
179 poll = 167,
180 nfsservctl = 168,
181 setresgid = 169,
182 getresgid = 170,
183 prctl = 171,
184 rt_sigreturn = 172,
185 rt_sigaction = 173,
186 rt_sigprocmask = 174,
187 rt_sigpending = 175,
188 rt_sigtimedwait = 176,
189 rt_sigqueueinfo = 177,
190 rt_sigsuspend = 178,
191 pread64 = 179,
192 pwrite64 = 180,
193 chown = 181,
194 getcwd = 182,
195 capget = 183,
196 capset = 184,
197 sigaltstack = 185,
198 sendfile = 186,
199 getpmsg = 187,
200 putpmsg = 188,
201 vfork = 189,
202 ugetrlimit = 190,
203 readahead = 191,
204 pciconfig_read = 198,
205 pciconfig_write = 199,
206 pciconfig_iobase = 200,
207 multiplexer = 201,
208 getdents64 = 202,
209 pivot_root = 203,
210 madvise = 205,
211 mincore = 206,
212 gettid = 207,
213 tkill = 208,
214 setxattr = 209,
215 lsetxattr = 210,
216 fsetxattr = 211,
217 getxattr = 212,
218 lgetxattr = 213,
219 fgetxattr = 214,
220 listxattr = 215,
221 llistxattr = 216,
222 flistxattr = 217,
223 removexattr = 218,
224 lremovexattr = 219,
225 fremovexattr = 220,
226 futex = 221,
227 sched_setaffinity = 222,
228 sched_getaffinity = 223,
229 tuxcall = 225,
230 io_setup = 227,
231 io_destroy = 228,
232 io_getevents = 229,
233 io_submit = 230,
234 io_cancel = 231,
235 set_tid_address = 232,
236 fadvise64 = 233,
237 exit_group = 234,
238 lookup_dcookie = 235,
239 epoll_create = 236,
240 epoll_ctl = 237,
241 epoll_wait = 238,
242 remap_file_pages = 239,
243 timer_create = 240,
244 timer_settime = 241,
245 timer_gettime = 242,
246 timer_getoverrun = 243,
247 timer_delete = 244,
248 clock_settime = 245,
249 clock_gettime = 246,
250 clock_getres = 247,
251 clock_nanosleep = 248,
252 swapcontext = 249,
253 tgkill = 250,
254 utimes = 251,
255 statfs64 = 252,
256 fstatfs64 = 253,
257 rtas = 255,
258 sys_debug_setcontext = 256,
259 migrate_pages = 258,
260 mbind = 259,
261 get_mempolicy = 260,
262 set_mempolicy = 261,
263 mq_open = 262,
264 mq_unlink = 263,
265 mq_timedsend = 264,
266 mq_timedreceive = 265,
267 mq_notify = 266,
268 mq_getsetattr = 267,
269 kexec_load = 268,
270 add_key = 269,
271 request_key = 270,
272 keyctl = 271,
273 waitid = 272,
274 ioprio_set = 273,
275 ioprio_get = 274,
276 inotify_init = 275,
277 inotify_add_watch = 276,
278 inotify_rm_watch = 277,
279 spu_run = 278,
280 spu_create = 279,
281 pselect6 = 280,
282 ppoll = 281,
283 unshare = 282,
284 splice = 283,
285 tee = 284,
286 vmsplice = 285,
287 openat = 286,
288 mkdirat = 287,
289 mknodat = 288,
290 fchownat = 289,
291 futimesat = 290,
292 newfstatat = 291,
293 unlinkat = 292,
294 renameat = 293,
295 linkat = 294,
296 symlinkat = 295,
297 readlinkat = 296,
298 fchmodat = 297,
299 faccessat = 298,
300 get_robust_list = 299,
301 set_robust_list = 300,
302 move_pages = 301,
303 getcpu = 302,
304 epoll_pwait = 303,
305 utimensat = 304,
306 signalfd = 305,
307 timerfd_create = 306,
308 eventfd = 307,
309 sync_file_range2 = 308,
310 fallocate = 309,
311 subpage_prot = 310,
312 timerfd_settime = 311,
313 timerfd_gettime = 312,
314 signalfd4 = 313,
315 eventfd2 = 314,
316 epoll_create1 = 315,
317 dup3 = 316,
318 pipe2 = 317,
319 inotify_init1 = 318,
320 perf_event_open = 319,
321 preadv = 320,
322 pwritev = 321,
323 rt_tgsigqueueinfo = 322,
324 fanotify_init = 323,
325 fanotify_mark = 324,
326 prlimit64 = 325,
327 socket = 326,
328 bind = 327,
329 connect = 328,
330 listen = 329,
331 accept = 330,
332 getsockname = 331,
333 getpeername = 332,
334 socketpair = 333,
335 send = 334,
336 sendto = 335,
337 recv = 336,
338 recvfrom = 337,
339 shutdown = 338,
340 setsockopt = 339,
341 getsockopt = 340,
342 sendmsg = 341,
343 recvmsg = 342,
344 recvmmsg = 343,
345 accept4 = 344,
346 name_to_handle_at = 345,
347 open_by_handle_at = 346,
348 clock_adjtime = 347,
349 syncfs = 348,
350 sendmmsg = 349,
351 setns = 350,
352 process_vm_readv = 351,
353 process_vm_writev = 352,
354 finit_module = 353,
355 kcmp = 354,
356 sched_setattr = 355,
357 sched_getattr = 356,
358 renameat2 = 357,
359 seccomp = 358,
360 getrandom = 359,
361 memfd_create = 360,
362 bpf = 361,
363 execveat = 362,
364 switch_endian = 363,
365 userfaultfd = 364,
366 membarrier = 365,
367 mlock2 = 378,
368 copy_file_range = 379,
369 preadv2 = 380,
370 pwritev2 = 381,
371 kexec_file_load = 382,
372 statx = 383,
373 pkey_alloc = 384,
374 pkey_free = 385,
375 pkey_mprotect = 386,
376 rseq = 387,
377 io_pgetevents = 388,
378 semtimedop = 392,
379 semget = 393,
380 semctl = 394,
381 shmget = 395,
382 shmctl = 396,
383 shmat = 397,
384 shmdt = 398,
385 msgget = 399,
386 msgsnd = 400,
387 msgrcv = 401,
388 msgctl = 402,
389 pidfd_send_signal = 424,
390 io_uring_setup = 425,
391 io_uring_enter = 426,
392 io_uring_register = 427,
393 open_tree = 428,
394 move_mount = 429,
395 fsopen = 430,
396 fsconfig = 431,
397 fsmount = 432,
398 fspick = 433,
399 pidfd_open = 434,
400 clone3 = 435,
401 openat2 = 437,
402 pidfd_getfd = 438,
403
404 _,
405};
406
407pub const O_CREAT = 0o100;
408pub const O_EXCL = 0o200;
409pub const O_NOCTTY = 0o400;
410pub const O_TRUNC = 0o1000;
411pub const O_APPEND = 0o2000;
412pub const O_NONBLOCK = 0o4000;
413pub const O_DSYNC = 0o10000;
414pub const O_SYNC = 0o4010000;
415pub const O_RSYNC = 0o4010000;
416pub const O_DIRECTORY = 0o40000;
417pub const O_NOFOLLOW = 0o100000;
418pub const O_CLOEXEC = 0o2000000;
419
420pub const O_ASYNC = 0o20000;
421pub const O_DIRECT = 0o400000;
422pub const O_LARGEFILE = 0o200000;
423pub const O_NOATIME = 0o1000000;
424pub const O_PATH = 0o10000000;
425pub const O_TMPFILE = 0o20200000;
426pub const O_NDELAY = O_NONBLOCK;
427
428pub const F_DUPFD = 0;
429pub const F_GETFD = 1;
430pub const F_SETFD = 2;
431pub const F_GETFL = 3;
432pub const F_SETFL = 4;
433
434pub const F_SETOWN = 8;
435pub const F_GETOWN = 9;
436pub const F_SETSIG = 10;
437pub const F_GETSIG = 11;
438
439pub const F_GETLK = 5;
440pub const F_SETLK = 6;
441pub const F_SETLKW = 7;
442
443pub const F_RDLCK = 0;
444pub const F_WRLCK = 1;
445pub const F_UNLCK = 2;
446
447pub const LOCK_SH = 1;
448pub const LOCK_EX = 2;
449pub const LOCK_UN = 8;
450pub const LOCK_NB = 4;
451
452pub const F_SETOWN_EX = 15;
453pub const F_GETOWN_EX = 16;
454
455pub const F_GETOWNER_UIDS = 17;
456
457/// stack-like segment
458pub const MAP_GROWSDOWN = 0x0100;
459
460/// ETXTBSY
461pub const MAP_DENYWRITE = 0x0800;
462
463/// mark it as an executable
464pub const MAP_EXECUTABLE = 0x1000;
465
466/// pages are locked
467pub const MAP_LOCKED = 0x0080;
468
469/// don't check for reservations
470pub const MAP_NORESERVE = 0x0040;
471
472pub const VDSO_CGT_SYM = "__kernel_clock_gettime";
473pub const VDSO_CGT_VER = "LINUX_2.6.15";
474
475pub const Flock = extern struct {
476 l_type: i16,
477 l_whence: i16,
478 l_start: off_t,
479 l_len: off_t,
480 l_pid: pid_t,
481 __unused: [4]u8,
482};
483
484pub const msghdr = extern struct {
485 msg_name: ?*sockaddr,
486 msg_namelen: socklen_t,
487 msg_iov: [*]iovec,
488 msg_iovlen: usize,
489 msg_control: ?*c_void,
490 msg_controllen: usize,
491 msg_flags: i32,
492};
493
494pub const msghdr_const = extern struct {
495 msg_name: ?*const sockaddr,
496 msg_namelen: socklen_t,
497 msg_iov: [*]iovec_const,
498 msg_iovlen: usize,
499 msg_control: ?*c_void,
500 msg_controllen: usize,
501 msg_flags: i32,
502};
503
504pub const blksize_t = i64;
505pub const nlink_t = u64;
506pub const time_t = i64;
507pub const mode_t = u32;
508pub const off_t = i64;
509pub const ino_t = u64;
510pub const dev_t = u64;
511pub const blkcnt_t = i64;
512
513/// Renamed to Stat to not conflict with the stat function.
514/// atime, mtime, and ctime have functions to return `timespec`,
515/// because although this is a POSIX API, the layout and names of
516/// the structs are inconsistent across operating systems, and
517/// in C, macros are used to hide the differences. Here we use
518/// methods to accomplish this.
519pub const Stat = extern struct {
520 dev: dev_t,
521 ino: ino_t,
522 nlink: nlink_t,
523 mode: mode_t,
524 uid: uid_t,
525 gid: gid_t,
526 rdev: dev_t,
527 size: off_t,
528 blksize: blksize_t,
529 blocks: blkcnt_t,
530 atim: timespec,
531 mtim: timespec,
532 ctim: timespec,
533 __unused: [3]u64,
534
535 pub fn atime(self: Stat) timespec {
536 return self.atim;
537 }
538
539 pub fn mtime(self: Stat) timespec {
540 return self.mtim;
541 }
542
543 pub fn ctime(self: Stat) timespec {
544 return self.ctim;
545 }
546};
547
548pub const timespec = extern struct {
549 tv_sec: time_t,
550 tv_nsec: isize,
551};
552
553pub const timeval = extern struct {
554 tv_sec: isize,
555 tv_usec: isize,
556};
557
558pub const timezone = extern struct {
559 tz_minuteswest: i32,
560 tz_dsttime: i32,
561};
562
563pub const greg_t = u64;
564pub const gregset_t = [48]greg_t;
565pub const fpregset_t = [33]f64;
566
567/// The position of the vscr register depends on endianness.
568/// On C, macros are used to change vscr_word's offset to
569/// account for this. Here we'll just define vscr_word_le
570/// and vscr_word_be. Code must take care to use the correct one.
571pub const vrregset = extern struct {
572 vrregs: [32][4]u32 align(16),
573 vscr_word_le: u32,
574 _pad1: [2]u32,
575 vscr_word_be: u32,
576 vrsave: u32,
577 _pad2: [3]u32,
578};
579pub const vrregset_t = vrregset;
580
581pub const mcontext_t = extern struct {
582 __unused: [4]u64,
583 signal: i32,
584 _pad0: i32,
585 handler: u64,
586 oldmask: u64,
587 regs: ?*c_void,
588 gp_regs: gregset_t,
589 fp_regs: fpregset_t,
590 v_regs: *vrregset_t,
591 vmx_reserve: [34 + 34 + 32 + 1]i64,
592};
593
594pub const ucontext_t = extern struct {
595 flags: u32,
596 link: *ucontext_t,
597 stack: stack_t,
598 sigmask: sigset_t,
599 mcontext: mcontext_t,
600};
601
602pub const Elf_Symndx = u32;
lib/std/os/bits/linux/prctl.zig created+158
......@@ -0,0 +1,158 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6
7pub const PR_SET_PDEATHSIG = 1;
8pub const PR_GET_PDEATHSIG = 2;
9
10pub const PR_GET_DUMPABLE = 3;
11pub const PR_SET_DUMPABLE = 4;
12
13pub const PR_GET_UNALIGN = 5;
14pub const PR_SET_UNALIGN = 6;
15pub const PR_UNALIGN_NOPRINT = 1;
16pub const PR_UNALIGN_SIGBUS = 2;
17
18pub const PR_GET_KEEPCAPS = 7;
19pub const PR_SET_KEEPCAPS = 8;
20
21pub const PR_GET_FPEMU = 9;
22pub const PR_SET_FPEMU = 10;
23pub const PR_FPEMU_NOPRINT = 1;
24pub const PR_FPEMU_SIGFPE = 2;
25
26pub const PR_GET_FPEXC = 11;
27pub const PR_SET_FPEXC = 12;
28pub const PR_FP_EXC_SW_ENABLE = 0x80;
29pub const PR_FP_EXC_DIV = 0x010000;
30pub const PR_FP_EXC_OVF = 0x020000;
31pub const PR_FP_EXC_UND = 0x040000;
32pub const PR_FP_EXC_RES = 0x080000;
33pub const PR_FP_EXC_INV = 0x100000;
34pub const PR_FP_EXC_DISABLED = 0;
35pub const PR_FP_EXC_NONRECOV = 1;
36pub const PR_FP_EXC_ASYNC = 2;
37pub const PR_FP_EXC_PRECISE = 3;
38
39pub const PR_GET_TIMING = 13;
40pub const PR_SET_TIMING = 14;
41pub const PR_TIMING_STATISTICAL = 0;
42pub const PR_TIMING_TIMESTAMP = 1;
43
44pub const PR_SET_NAME = 15;
45pub const PR_GET_NAME = 16;
46
47pub const PR_GET_ENDIAN = 19;
48pub const PR_SET_ENDIAN = 20;
49pub const PR_ENDIAN_BIG = 0;
50pub const PR_ENDIAN_LITTLE = 1;
51pub const PR_ENDIAN_PPC_LITTLE = 2;
52
53pub const PR_GET_SECCOMP = 21;
54pub const PR_SET_SECCOMP = 22;
55
56pub const PR_CAPBSET_READ = 23;
57pub const PR_CAPBSET_DROP = 24;
58
59pub const PR_GET_TSC = 25;
60pub const PR_SET_TSC = 26;
61pub const PR_TSC_ENABLE = 1;
62pub const PR_TSC_SIGSEGV = 2;
63
64pub const PR_GET_SECUREBITS = 27;
65pub const PR_SET_SECUREBITS = 28;
66
67pub const PR_SET_TIMERSLACK = 29;
68pub const PR_GET_TIMERSLACK = 30;
69
70pub const PR_TASK_PERF_EVENTS_DISABLE = 31;
71pub const PR_TASK_PERF_EVENTS_ENABLE = 32;
72
73pub const PR_MCE_KILL = 33;
74pub const PR_MCE_KILL_CLEAR = 0;
75pub const PR_MCE_KILL_SET = 1;
76
77pub const PR_MCE_KILL_LATE = 0;
78pub const PR_MCE_KILL_EARLY = 1;
79pub const PR_MCE_KILL_DEFAULT = 2;
80
81pub const PR_MCE_KILL_GET = 34;
82
83pub const PR_SET_MM = 35;
84pub const PR_SET_MM_START_CODE = 1;
85pub const PR_SET_MM_END_CODE = 2;
86pub const PR_SET_MM_START_DATA = 3;
87pub const PR_SET_MM_END_DATA = 4;
88pub const PR_SET_MM_START_STACK = 5;
89pub const PR_SET_MM_START_BRK = 6;
90pub const PR_SET_MM_BRK = 7;
91pub const PR_SET_MM_ARG_START = 8;
92pub const PR_SET_MM_ARG_END = 9;
93pub const PR_SET_MM_ENV_START = 10;
94pub const PR_SET_MM_ENV_END = 11;
95pub const PR_SET_MM_AUXV = 12;
96pub const PR_SET_MM_EXE_FILE = 13;
97pub const PR_SET_MM_MAP = 14;
98pub const PR_SET_MM_MAP_SIZE = 15;
99
100pub const prctl_mm_map = extern struct {
101 start_code: u64,
102 end_code: u64,
103 start_data: u64,
104 end_data: u64,
105 start_brk: u64,
106 brk: u64,
107 start_stack: u64,
108 arg_start: u64,
109 arg_end: u64,
110 env_start: u64,
111 env_end: u64,
112 auxv: *u64,
113 auxv_size: u32,
114 exe_fd: u32,
115};
116
117pub const PR_SET_PTRACER = 0x59616d61;
118pub const PR_SET_PTRACER_ANY = std.math.maxInt(c_ulong);
119
120pub const PR_SET_CHILD_SUBREAPER = 36;
121pub const PR_GET_CHILD_SUBREAPER = 37;
122
123pub const PR_SET_NO_NEW_PRIVS = 38;
124pub const PR_GET_NO_NEW_PRIVS = 39;
125
126pub const PR_GET_TID_ADDRESS = 40;
127
128pub const PR_SET_THP_DISABLE = 41;
129pub const PR_GET_THP_DISABLE = 42;
130
131pub const PR_MPX_ENABLE_MANAGEMENT = 43;
132pub const PR_MPX_DISABLE_MANAGEMENT = 44;
133
134pub const PR_SET_FP_MODE = 45;
135pub const PR_GET_FP_MODE = 46;
136pub const PR_FP_MODE_FR = 1 << 0;
137pub const PR_FP_MODE_FRE = 1 << 1;
138
139pub const PR_CAP_AMBIENT = 47;
140pub const PR_CAP_AMBIENT_IS_SET = 1;
141pub const PR_CAP_AMBIENT_RAISE = 2;
142pub const PR_CAP_AMBIENT_LOWER = 3;
143pub const PR_CAP_AMBIENT_CLEAR_ALL = 4;
144
145pub const PR_SVE_SET_VL = 50;
146pub const PR_SVE_SET_VL_ONEXEC = 1 << 18;
147pub const PR_SVE_GET_VL = 51;
148pub const PR_SVE_VL_LEN_MASK = 0xffff;
149pub const PR_SVE_VL_INHERIT = 1 << 17;
150
151pub const PR_GET_SPECULATION_CTRL = 52;
152pub const PR_SET_SPECULATION_CTRL = 53;
153pub const PR_SPEC_STORE_BYPASS = 0;
154pub const PR_SPEC_NOT_AFFECTED = 0;
155pub const PR_SPEC_PRCTL = 1 << 0;
156pub const PR_SPEC_ENABLE = 1 << 1;
157pub const PR_SPEC_DISABLE = 1 << 2;
158pub const PR_SPEC_FORCE_DISABLE = 1 << 3;
lib/std/os/bits/linux/securebits.zig created+41
......@@ -0,0 +1,41 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6
7fn issecure_mask(comptime x: comptime_int) comptime_int {
8 return 1 << x;
9}
10
11pub const SECUREBITS_DEFAULT = 0x00000000;
12
13pub const SECURE_NOROOT = 0;
14pub const SECURE_NOROOT_LOCKED = 1;
15
16pub const SECBIT_NOROOT = issecure_mask(SECURE_NOROOT);
17pub const SECBIT_NOROOT_LOCKED = issecure_mask(SECURE_NOROOT_LOCKED);
18
19pub const SECURE_NO_SETUID_FIXUP = 2;
20pub const SECURE_NO_SETUID_FIXUP_LOCKED = 3;
21
22pub const SECBIT_NO_SETUID_FIXUP = issecure_mask(SECURE_NO_SETUID_FIXUP);
23pub const SECBIT_NO_SETUID_FIXUP_LOCKED = issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED);
24
25pub const SECURE_KEEP_CAPS = 4;
26pub const SECURE_KEEP_CAPS_LOCKED = 5;
27
28pub const SECBIT_KEEP_CAPS = issecure_mask(SECURE_KEEP_CAPS);
29pub const SECBIT_KEEP_CAPS_LOCKED = issecure_mask(SECURE_KEEP_CAPS_LOCKED);
30
31pub const SECURE_NO_CAP_AMBIENT_RAISE = 6;
32pub const SECURE_NO_CAP_AMBIENT_RAISE_LOCKED = 7;
33
34pub const SECBIT_NO_CAP_AMBIENT_RAISE = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE);
35pub const SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED = issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED);
36
37pub const SECURE_ALL_BITS = issecure_mask(SECURE_NOROOT) |
38 issecure_mask(SECURE_NO_SETUID_FIXUP) |
39 issecure_mask(SECURE_KEEP_CAPS) |
40 issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE);
41pub const SECURE_ALL_LOCKS = SECURE_ALL_BITS << 1;
lib/std/os/linux.zig+5
......@@ -25,6 +25,7 @@ pub usingnamespace switch (builtin.arch) {
2525 .arm => @import("linux/arm-eabi.zig"),
2626 .riscv64 => @import("linux/riscv64.zig"),
2727 .mips, .mipsel => @import("linux/mips.zig"),
28 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
2829 else => struct {},
2930};
3031pub usingnamespace @import("bits.zig");
......@@ -1258,6 +1259,10 @@ pub fn fdatasync(fd: fd_t) usize {
12581259 return syscall1(.fdatasync, @bitCast(usize, @as(isize, fd)));
12591260}
12601261
1262pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
1263 return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5);
1264}
1265
12611266test "" {
12621267 if (builtin.os.tag == .linux) {
12631268 _ = @import("linux/test.zig");
lib/std/os/linux/powerpc64.zig created+127
......@@ -0,0 +1,127 @@
1usingnamespace @import("../bits.zig");
2
3pub fn syscall0(number: SYS) usize {
4 return asm volatile (
5 \\ sc
6 \\ bns+ 1f
7 \\ neg 3, 3
8 \\ 1:
9 : [ret] "={r3}" (-> usize)
10 : [number] "{r0}" (@enumToInt(number))
11 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
12 );
13}
14
15pub fn syscall1(number: SYS, arg1: usize) usize {
16 return asm volatile (
17 \\ sc
18 \\ bns+ 1f
19 \\ neg 3, 3
20 \\ 1:
21 : [ret] "={r3}" (-> usize)
22 : [number] "{r0}" (@enumToInt(number)),
23 [arg1] "{r3}" (arg1)
24 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
25 );
26}
27
28pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
29 return asm volatile (
30 \\ sc
31 \\ bns+ 1f
32 \\ neg 3, 3
33 \\ 1:
34 : [ret] "={r3}" (-> usize)
35 : [number] "{r0}" (@enumToInt(number)),
36 [arg1] "{r3}" (arg1),
37 [arg2] "{r4}" (arg2)
38 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
39 );
40}
41
42pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
43 return asm volatile (
44 \\ sc
45 \\ bns+ 1f
46 \\ neg 3, 3
47 \\ 1:
48 : [ret] "={r3}" (-> usize)
49 : [number] "{r0}" (@enumToInt(number)),
50 [arg1] "{r3}" (arg1),
51 [arg2] "{r4}" (arg2),
52 [arg3] "{r5}" (arg3)
53 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
54 );
55}
56
57pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
58 return asm volatile (
59 \\ sc
60 \\ bns+ 1f
61 \\ neg 3, 3
62 \\ 1:
63 : [ret] "={r3}" (-> usize)
64 : [number] "{r0}" (@enumToInt(number)),
65 [arg1] "{r3}" (arg1),
66 [arg2] "{r4}" (arg2),
67 [arg3] "{r5}" (arg3),
68 [arg4] "{r6}" (arg4)
69 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
70 );
71}
72
73pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
74 return asm volatile (
75 \\ sc
76 \\ bns+ 1f
77 \\ neg 3, 3
78 \\ 1:
79 : [ret] "={r3}" (-> usize)
80 : [number] "{r0}" (@enumToInt(number)),
81 [arg1] "{r3}" (arg1),
82 [arg2] "{r4}" (arg2),
83 [arg3] "{r5}" (arg3),
84 [arg4] "{r6}" (arg4),
85 [arg5] "{r7}" (arg5)
86 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
87 );
88}
89
90pub fn syscall6(
91 number: SYS,
92 arg1: usize,
93 arg2: usize,
94 arg3: usize,
95 arg4: usize,
96 arg5: usize,
97 arg6: usize,
98) usize {
99 return asm volatile (
100 \\ sc
101 \\ bns+ 1f
102 \\ neg 3, 3
103 \\ 1:
104 : [ret] "={r3}" (-> usize)
105 : [number] "{r0}" (@enumToInt(number)),
106 [arg1] "{r3}" (arg1),
107 [arg2] "{r4}" (arg2),
108 [arg3] "{r5}" (arg3),
109 [arg4] "{r6}" (arg4),
110 [arg5] "{r7}" (arg5),
111 [arg6] "{r8}" (arg6)
112 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
113 );
114}
115
116/// This matches the libc clone function.
117pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
118
119pub const restore = restore_rt;
120
121pub fn restore_rt() callconv(.Naked) void {
122 return asm volatile ("sc"
123 :
124 : [number] "{r0}" (@enumToInt(SYS.rt_sigreturn))
125 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
126 );
127}
lib/std/os/linux/tls.zig+10-3
......@@ -53,7 +53,7 @@ const TLSVariant = enum {
5353};
5454
5555const tls_variant = switch (builtin.arch) {
56 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel => TLSVariant.VariantI,
56 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,
5757 .x86_64, .i386 => TLSVariant.VariantII,
5858 else => @compileError("undefined tls_variant for this architecture"),
5959};
......@@ -77,12 +77,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) {
7777// make the generated code more efficient
7878
7979const tls_tp_offset = switch (builtin.arch) {
80 .mips, .mipsel => 0x7000,
80 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000,
8181 else => 0,
8282};
8383
8484const tls_dtv_offset = switch (builtin.arch) {
85 .mips, .mipsel => 0x8000,
85 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000,
8686 .riscv32, .riscv64 => 0x800,
8787 else => 0,
8888};
......@@ -165,6 +165,13 @@ pub fn setThreadPointer(addr: usize) void {
165165 const rc = std.os.linux.syscall1(.set_thread_area, addr);
166166 assert(rc == 0);
167167 },
168 .powerpc, .powerpc64, .powerpc64le => {
169 asm volatile (
170 \\ mr 13, %[addr]
171 :
172 : [addr] "r" (addr)
173 );
174 },
168175 else => @compileError("Unsupported architecture"),
169176 }
170177}
lib/std/priority_queue.zig+10-1
......@@ -195,7 +195,7 @@ pub fn PriorityQueue(comptime T: type) type {
195195 count: usize,
196196
197197 pub fn next(it: *Iterator) ?T {
198 if (it.count > it.queue.len - 1) return null;
198 if (it.count >= it.queue.len) return null;
199199 const out = it.count;
200200 it.count += 1;
201201 return it.queue.items[out];
......@@ -428,3 +428,12 @@ test "std.PriorityQueue: remove at index" {
428428 expectEqual(queue.remove(), 3);
429429 expectEqual(queue.removeOrNull(), null);
430430}
431
432test "std.PriorityQueue: iterator while empty" {
433 var queue = PQ.init(testing.allocator, lessThan);
434 defer queue.deinit();
435
436 var it = queue.iterator();
437
438 expectEqual(it.next(), null);
439}
lib/std/process.zig+8-6
......@@ -593,8 +593,10 @@ pub fn getUserInfo(name: []const u8) !UserInfo {
593593/// TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else
594594/// like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`.
595595pub fn posixGetUserInfo(name: []const u8) !UserInfo {
596 var reader = try io.Reader.open("/etc/passwd", null);
597 defer reader.close();
596 const file = try std.fs.openFileAbsolute("/etc/passwd", .{});
597 defer file.close();
598
599 const reader = file.reader();
598600
599601 const State = enum {
600602 Start,
......@@ -650,8 +652,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
650652 '0'...'9' => byte - '0',
651653 else => return error.CorruptPasswordFile,
652654 };
653 if (@mulWithOverflow(u32, uid, 10, *uid)) return error.CorruptPasswordFile;
654 if (@addWithOverflow(u32, uid, digit, *uid)) return error.CorruptPasswordFile;
655 if (@mulWithOverflow(u32, uid, 10, &uid)) return error.CorruptPasswordFile;
656 if (@addWithOverflow(u32, uid, digit, &uid)) return error.CorruptPasswordFile;
655657 },
656658 },
657659 .ReadGroupId => switch (byte) {
......@@ -666,8 +668,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
666668 '0'...'9' => byte - '0',
667669 else => return error.CorruptPasswordFile,
668670 };
669 if (@mulWithOverflow(u32, gid, 10, *gid)) return error.CorruptPasswordFile;
670 if (@addWithOverflow(u32, gid, digit, *gid)) return error.CorruptPasswordFile;
671 if (@mulWithOverflow(u32, gid, 10, &gid)) return error.CorruptPasswordFile;
672 if (@addWithOverflow(u32, gid, digit, &gid)) return error.CorruptPasswordFile;
671673 },
672674 },
673675 }
lib/std/special/c.zig+55
......@@ -394,6 +394,61 @@ fn clone() callconv(.Naked) void {
394394 \\ syscall
395395 );
396396 },
397
398 .powerpc64, .powerpc64le => {
399 asm volatile (
400 \\ # store non-volatile regs r30, r31 on stack in order to put our
401 \\ # start func and its arg there
402 \\ stwu 30, -16(1)
403 \\ stw 31, 4(1)
404 \\ # save r3 (func) into r30, and r6(arg) into r31
405 \\ mr 30, 3
406 \\ mr 31, 6
407 \\ # create initial stack frame for new thread
408 \\ clrrwi 4, 4, 4
409 \\ li 0, 0
410 \\ stwu 0, -16(4)
411 \\ #move c into first arg
412 \\ mr 3, 5
413 \\ mr 5, 7
414 \\ mr 6, 8
415 \\ mr 7, 9
416 \\ # move syscall number into r0
417 \\ li 0, 120
418 \\ sc
419
420 \\ # check for syscall error
421 \\ bns+ 1f # jump to label 1 if no summary overflow.
422 \\ #else
423 \\ neg 3, 3 #negate the result (errno)
424 \\1:
425 \\ # compare sc result with 0
426 \\ cmpwi cr7, 3, 0
427
428 \\ # if not 0, jump to end
429 \\ bne cr7, 2f
430
431 \\ #else: we're the child
432 \\ #call funcptr: move arg (d) into r3
433 \\ mr 3, 31
434 \\ #move r30 (funcptr) into CTR reg
435 \\ mtctr 30
436 \\ # call CTR reg
437 \\ bctrl
438 \\ # mov SYS_exit into r0 (the exit param is already in r3)
439 \\ li 0, 1
440 \\ sc
441
442 \\2:
443 \\ # restore stack
444 \\ lwz 30, 0(1)
445 \\ lwz 31, 4(1)
446 \\ addi 1, 1, 16
447
448 \\ blr
449 );
450 },
451
397452 else => @compileError("Implement clone() for this arch."),
398453 }
399454}
lib/std/start.zig+15
......@@ -121,6 +121,21 @@ fn _start() callconv(.Naked) noreturn {
121121 : [argc] "=r" (-> [*]usize)
122122 );
123123 },
124 .powerpc64le => {
125 // Before returning the stack pointer, we have to set up a backchain
126 // and a few other registers required by the ELFv2 ABI.
127 // TODO: Support powerpc64 (big endian) on ELFv2.
128 starting_stack_ptr = asm (
129 \\ mr 4, 1
130 \\ subi 1, 1, 32
131 \\ li 5, 0
132 \\ std 5, 0(1)
133 \\ mr %[argc], 4
134 : [argc] "=r" (-> [*]usize)
135 :
136 : "r4", "r5"
137 );
138 },
124139 else => @compileError("unsupported arch"),
125140 }
126141 // If LLVM inlines stack variables into _start, they will overwrite
src-self-hosted/translate_c.zig+38
......@@ -5899,6 +5899,10 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.N
58995899 saw_l_paren = true;
59005900 _ = m.next();
59015901 },
5902 // (type)sizeof(x)
5903 .Keyword_sizeof,
5904 // (type)alignof(x)
5905 .Keyword_alignof,
59025906 // (type)identifier
59035907 .Identifier => {},
59045908 // (type)integer
......@@ -6309,6 +6313,40 @@ fn parseCPrefixOpExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.
63096313 node.rhs = try parseCPrefixOpExpr(c, m, scope);
63106314 return &node.base;
63116315 },
6316 .Keyword_sizeof => {
6317 const inner = if (m.peek().? == .LParen) blk: {
6318 _ = m.next();
6319 const inner = try parseCExpr(c, m, scope);
6320 if (m.next().? != .RParen) {
6321 try m.fail(c, "unable to translate C expr: expected ')'", .{});
6322 return error.ParseError;
6323 }
6324 break :blk inner;
6325 } else try parseCPrefixOpExpr(c, m, scope);
6326
6327 const builtin_call = try c.createBuiltinCall("@sizeOf", 1);
6328 builtin_call.params()[0] = inner;
6329 builtin_call.rparen_token = try appendToken(c, .RParen, ")");
6330 return &builtin_call.base;
6331 },
6332 .Keyword_alignof => {
6333 // TODO this won't work if using <stdalign.h>'s
6334 // #define alignof _Alignof
6335 if (m.next().? != .LParen) {
6336 try m.fail(c, "unable to translate C expr: expected '('", .{});
6337 return error.ParseError;
6338 }
6339 const inner = try parseCExpr(c, m, scope);
6340 if (m.next().? != .RParen) {
6341 try m.fail(c, "unable to translate C expr: expected ')'", .{});
6342 return error.ParseError;
6343 }
6344
6345 const builtin_call = try c.createBuiltinCall("@alignOf", 1);
6346 builtin_call.params()[0] = inner;
6347 builtin_call.rparen_token = try appendToken(c, .RParen, ")");
6348 return &builtin_call.base;
6349 },
63126350 else => {
63136351 m.i -= 1;
63146352 return try parseCSuffixOpExpr(c, m, scope);
src/all_types.hpp+1
......@@ -2265,6 +2265,7 @@ struct CodeGen {
22652265
22662266 Stage2LibCInstallation *libc;
22672267
2268 bool is_versioned;
22682269 size_t version_major;
22692270 size_t version_minor;
22702271 size_t version_patch;
src/analyze.cpp+2-1
......@@ -1009,7 +1009,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
10091009 g->zig_target->arch == ZigLLVM_x86_64 ||
10101010 target_is_arm(g->zig_target) ||
10111011 target_is_riscv(g->zig_target) ||
1012 target_is_wasm(g->zig_target))
1012 target_is_wasm(g->zig_target) ||
1013 target_is_ppc(g->zig_target))
10131014 {
10141015 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
10151016 return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval;
src/codegen.cpp+4-2
......@@ -90,7 +90,8 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix) {
9090 g->test_name_prefix = prefix;
9191}
9292
93void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch) {
93void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch) {
94 g->is_versioned = is_versioned;
9495 g->version_major = major;
9596 g->version_minor = minor;
9697 g->version_patch = patch;
......@@ -10823,6 +10824,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1082310824 cache_bool(ch, g->emit_bin);
1082410825 cache_bool(ch, g->emit_llvm_ir);
1082510826 cache_bool(ch, g->emit_asm);
10827 cache_bool(ch, g->is_versioned);
1082610828 cache_usize(ch, g->version_major);
1082710829 cache_usize(ch, g->version_minor);
1082810830 cache_usize(ch, g->version_patch);
......@@ -10893,7 +10895,7 @@ static void resolve_out_paths(CodeGen *g) {
1089310895 buf_resize(out_basename, 0);
1089410896 buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
1089510897 buf_append_buf(out_basename, g->root_out_name);
10896 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
10898 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, g->is_versioned,
1089710899 g->version_major, g->version_minor, g->version_patch));
1089810900 break;
1089910901 }
src/codegen.hpp+1-1
......@@ -38,7 +38,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
3838void codegen_set_linker_script(CodeGen *g, const char *linker_script);
3939void codegen_set_test_filter(CodeGen *g, Buf *filter);
4040void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
41void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
41void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch);
4242void codegen_add_time_event(CodeGen *g, const char *name);
4343void codegen_print_timing_report(CodeGen *g, FILE *f);
4444void codegen_link(CodeGen *g);
src/glibc.cpp+1-1
......@@ -335,7 +335,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
335335 bool is_ld = (strcmp(lib->name, "ld") == 0);
336336
337337 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
338 codegen_set_lib_version(child_gen, lib->sover, 0, 0);
338 codegen_set_lib_version(child_gen, true, lib->sover, 0, 0);
339339 child_gen->is_dynamic = true;
340340 child_gen->is_dummy_so = true;
341341 child_gen->version_script_path = map_file_path;
src/main.cpp+5-1
......@@ -415,6 +415,7 @@ static int main0(int argc, char **argv) {
415415 const char *test_filter = nullptr;
416416 const char *test_name_prefix = nullptr;
417417 bool test_evented_io = false;
418 bool is_versioned = false;
418419 size_t ver_major = 0;
419420 size_t ver_minor = 0;
420421 size_t ver_patch = 0;
......@@ -870,10 +871,13 @@ static int main0(int argc, char **argv) {
870871 } else if (strcmp(arg, "--test-name-prefix") == 0) {
871872 test_name_prefix = argv[i];
872873 } else if (strcmp(arg, "--ver-major") == 0) {
874 is_versioned = true;
873875 ver_major = atoi(argv[i]);
874876 } else if (strcmp(arg, "--ver-minor") == 0) {
877 is_versioned = true;
875878 ver_minor = atoi(argv[i]);
876879 } else if (strcmp(arg, "--ver-patch") == 0) {
880 is_versioned = true;
877881 ver_patch = atoi(argv[i]);
878882 } else if (strcmp(arg, "--test-cmd") == 0) {
879883 test_exec_args.append(argv[i]);
......@@ -1223,7 +1227,7 @@ static int main0(int argc, char **argv) {
12231227 g->emit_llvm_ir = emit_llvm_ir;
12241228
12251229 codegen_set_out_name(g, buf_out_name);
1226 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
1230 codegen_set_lib_version(g, is_versioned, ver_major, ver_minor, ver_patch);
12271231 g->want_single_threaded = want_single_threaded;
12281232 codegen_set_linker_script(g, linker_script);
12291233 g->version_script_path = version_script;
src/target.cpp+21-8
......@@ -779,7 +779,7 @@ const char *target_lib_file_prefix(const ZigTarget *target) {
779779 }
780780}
781781
782const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
782const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned,
783783 size_t version_major, size_t version_minor, size_t version_patch)
784784{
785785 if (target_is_wasm(target)) {
......@@ -799,11 +799,19 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
799799 if (is_static) {
800800 return ".a";
801801 } else if (target_os_is_darwin(target->os)) {
802 return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
803 version_major, version_minor, version_patch));
802 if (is_versioned) {
803 return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
804 version_major, version_minor, version_patch));
805 } else {
806 return ".dylib";
807 }
804808 } else {
805 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
806 version_major, version_minor, version_patch));
809 if (is_versioned) {
810 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
811 version_major, version_minor, version_patch));
812 } else {
813 return ".so";
814 }
807815 }
808816 }
809817}
......@@ -853,6 +861,9 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
853861 case ZigLLVM_riscv32:
854862 case ZigLLVM_riscv64:
855863 case ZigLLVM_mipsel:
864 case ZigLLVM_ppc:
865 case ZigLLVM_ppc64:
866 case ZigLLVM_ppc64le:
856867 return "sp";
857868
858869 case ZigLLVM_wasm32:
......@@ -879,7 +890,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
879890 case ZigLLVM_msp430:
880891 case ZigLLVM_nvptx:
881892 case ZigLLVM_nvptx64:
882 case ZigLLVM_ppc64le:
883893 case ZigLLVM_r600:
884894 case ZigLLVM_renderscript32:
885895 case ZigLLVM_renderscript64:
......@@ -893,8 +903,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
893903 case ZigLLVM_tce:
894904 case ZigLLVM_tcele:
895905 case ZigLLVM_xcore:
896 case ZigLLVM_ppc:
897 case ZigLLVM_ppc64:
898906 case ZigLLVM_ve:
899907 zig_panic("TODO populate this table with stack pointer register name for this CPU architecture");
900908 }
......@@ -1325,6 +1333,11 @@ bool target_is_mips(const ZigTarget *target) {
13251333 target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el;
13261334}
13271335
1336bool target_is_ppc(const ZigTarget *target) {
1337 return target->arch == ZigLLVM_ppc || target->arch == ZigLLVM_ppc64 ||
1338 target->arch == ZigLLVM_ppc64le;
1339}
1340
13281341unsigned target_fn_align(const ZigTarget *target) {
13291342 return 16;
13301343}
src/target.hpp+2-1
......@@ -87,7 +87,7 @@ const char *target_asm_file_ext(const ZigTarget *target);
8787const char *target_llvm_ir_file_ext(const ZigTarget *target);
8888const char *target_exe_file_ext(const ZigTarget *target);
8989const char *target_lib_file_prefix(const ZigTarget *target);
90const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
90const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned,
9191 size_t version_major, size_t version_minor, size_t version_patch);
9292
9393bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
......@@ -95,6 +95,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type);
9595
9696bool target_is_arm(const ZigTarget *target);
9797bool target_is_mips(const ZigTarget *target);
98bool target_is_ppc(const ZigTarget *target);
9899bool target_allows_addr_zero(const ZigTarget *target);
99100bool target_has_valgrind_support(const ZigTarget *target);
100101bool target_os_is_darwin(Os os);
test/stack_traces.zig+3-3
......@@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
282282 \\source.zig:10:8: [address] in main (test)
283283 \\ foo();
284284 \\ ^
285 \\start.zig:254:29: [address] in std.start.posixCallMainAndExit (test)
285 \\start.zig:269:29: [address] in std.start.posixCallMainAndExit (test)
286286 \\ return root.main();
287287 \\ ^
288 \\start.zig:128:5: [address] in std.start._start (test)
288 \\start.zig:143:5: [address] in std.start._start (test)
289289 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
290290 \\ ^
291291 \\
......@@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
294294 switch (std.Target.current.cpu.arch) {
295295 .aarch64 => "", // TODO disabled; results in segfault
296296 else =>
297 \\start.zig:128:5: [address] in std.start._start (test)
297 \\start.zig:143:5: [address] in std.start._start (test)
298298 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
299299 \\ ^
300300 \\
test/stage1/behavior/translate_c_macros.h+4-1
......@@ -6,4 +6,7 @@ typedef struct Color {
66 unsigned char a;
77} Color;
88#define CLITERAL(type) (type)
9#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
\ No newline at end of file
9#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
10
11#define MY_SIZEOF(x) ((int)sizeof(x))
12#define MY_SIZEOF2(x) ((int)sizeof x)
test/stage1/behavior/translate_c_macros.zig+7-1
......@@ -1,12 +1,18 @@
11const expect = @import("std").testing.expect;
2const expectEqual = @import("std").testing.expectEqual;
23
34const h = @cImport(@cInclude("stage1/behavior/translate_c_macros.h"));
45
56test "initializer list expression" {
6 @import("std").testing.expectEqual(h.Color{
7 expectEqual(h.Color{
78 .r = 200,
89 .g = 200,
910 .b = 200,
1011 .a = 255,
1112 }, h.LIGHTGRAY);
1213}
14
15test "sizeof in macros" {
16 expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
17 expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
18}