diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-02-04 14:17:47 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-02-04 14:17:47 -0700 |
| commit | 09cee1d5e34dd4187242a693c2d7b5a9d1e689b1 (patch) | |
| tree | 70be147cdf59171bda9079abb3c5fe318ffad72b /lib/std | |
| parent | fab9b7110ed1fa7bb082aad5e095047441db2b24 (diff) | |
| parent | b7c96c3bbdc0e2172cf9edb0c9c7c52f86c2311e (diff) | |
| download | zig-09cee1d5e34dd4187242a693c2d7b5a9d1e689b1.tar.gz zig-09cee1d5e34dd4187242a693c2d7b5a9d1e689b1.zip | |
Merge remote-tracking branch 'origin/master' into llvm16
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/Build.zig | 130 | ||||
| -rw-r--r-- | lib/std/Build/CompileStep.zig | 111 | ||||
| -rw-r--r-- | lib/std/Build/OptionsStep.zig | 7 | ||||
| -rw-r--r-- | lib/std/array_list.zig | 32 | ||||
| -rw-r--r-- | lib/std/math/big.zig | 1 | ||||
| -rw-r--r-- | lib/std/math/big/int.zig | 11 | ||||
| -rw-r--r-- | lib/std/os/linux.zig | 2 | ||||
| -rw-r--r-- | lib/std/os/linux/mips64.zig | 413 | ||||
| -rw-r--r-- | lib/std/os/linux/syscalls.zig | 355 | ||||
| -rw-r--r-- | lib/std/os/linux/tls.zig | 10 | ||||
| -rw-r--r-- | lib/std/start.zig | 2 |
11 files changed, 912 insertions, 162 deletions
diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 6846007443..15c1647957 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -109,6 +109,8 @@ host: NativeTargetInfo, dep_prefix: []const u8 = "", +modules: std.StringArrayHashMap(*Module), + pub const ExecError = error{ ReadFailure, ExitCodeFailure, @@ -232,6 +234,7 @@ pub fn create( .install_path = undefined, .args = null, .host = host, + .modules = std.StringArrayHashMap(*Module).init(allocator), }; try self.top_level_steps.append(&self.install_tls); try self.top_level_steps.append(&self.uninstall_tls); @@ -305,6 +308,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: []const u8) .glibc_runtimes_dir = parent.glibc_runtimes_dir, .host = parent.host, .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), + .modules = std.StringArrayHashMap(*Module).init(allocator), }; try child.top_level_steps.append(&child.install_tls); try child.top_level_steps.append(&child.uninstall_tls); @@ -539,6 +543,49 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *CompileStep { return obj_step; } +pub const AddModuleOptions = struct { + name: []const u8, + source_file: FileSource, + dependencies: []const ModuleDependency = &.{}, +}; + +pub fn addModule(b: *Build, options: AddModuleOptions) void { + b.modules.put(b.dupe(options.name), b.createModule(.{ + .source_file = options.source_file, + .dependencies = options.dependencies, + })) catch @panic("OOM"); +} + +pub const ModuleDependency = struct { + name: []const u8, + module: *Module, +}; + +pub const CreateModuleOptions = struct { + source_file: FileSource, + dependencies: []const ModuleDependency = &.{}, +}; + +/// Prefer to use `addModule` which will make the module available to other +/// packages which depend on this package. +pub fn createModule(b: *Build, options: CreateModuleOptions) *Module { + const module = b.allocator.create(Module) catch @panic("OOM"); + module.* = .{ + .builder = b, + .source_file = options.source_file, + .dependencies = moduleDependenciesToArrayHashMap(b.allocator, options.dependencies), + }; + return module; +} + +fn moduleDependenciesToArrayHashMap(arena: Allocator, deps: []const ModuleDependency) std.StringArrayHashMap(*Module) { + var result = std.StringArrayHashMap(*Module).init(arena); + for (deps) |dep| { + result.put(dep.name, dep.module) catch @panic("OOM"); + } + return result; +} + /// Initializes a RunStep with argv, which must at least have the path to the /// executable. More command line arguments can be added with `addArg`, /// `addArgs`, and `addArtifactArg`. @@ -588,24 +635,6 @@ pub fn dupePath(self: *Build, bytes: []const u8) []u8 { return the_copy; } -/// Duplicates a package recursively. -pub fn dupePkg(self: *Build, package: Pkg) Pkg { - var the_copy = Pkg{ - .name = self.dupe(package.name), - .source = package.source.dupe(self), - }; - - if (package.dependencies) |dependencies| { - const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch @panic("OOM"); - the_copy.dependencies = new_dependencies; - - for (dependencies) |dep_package, i| { - new_dependencies[i] = self.dupePkg(dep_package); - } - } - return the_copy; -} - pub fn addWriteFile(self: *Build, file_path: []const u8, data: []const u8) *WriteFileStep { const write_file_step = self.addWriteFiles(); write_file_step.add(file_path, data); @@ -1479,6 +1508,12 @@ pub const Dependency = struct { panic("unable to find artifact '{s}'", .{name}); }; } + + pub fn module(d: *Dependency, name: []const u8) *Module { + return d.builder.modules.get(name) orelse { + panic("unable to find module '{s}'", .{name}); + }; + } }; pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { @@ -1548,10 +1583,13 @@ test "builder.findProgram compiles" { _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null; } -pub const Pkg = struct { - name: []const u8, - source: FileSource, - dependencies: ?[]const Pkg = null, +pub const Module = struct { + builder: *Build, + /// This could either be a generated file, in which case the module + /// contains exactly one file, or it could be a path to the root source + /// file of directory of files which constitute the module. + source_file: FileSource, + dependencies: std.StringArrayHashMap(*Module), }; /// A file that is generated by a build step. @@ -1713,54 +1751,6 @@ pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { } } -test "dupePkg()" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - - const host = try NativeTargetInfo.detect(.{}); - - var builder = try Build.create( - arena.allocator(), - "test", - "test", - "test", - "test", - host, - ); - defer builder.destroy(); - - var pkg_dep = Pkg{ - .name = "pkg_dep", - .source = .{ .path = "/not/a/pkg_dep.zig" }, - }; - var pkg_top = Pkg{ - .name = "pkg_top", - .source = .{ .path = "/not/a/pkg_top.zig" }, - .dependencies = &[_]Pkg{pkg_dep}, - }; - const duped = builder.dupePkg(pkg_top); - - const original_deps = pkg_top.dependencies.?; - const dupe_deps = duped.dependencies.?; - - // probably the same top level package details - try std.testing.expectEqualStrings(pkg_top.name, duped.name); - - // probably the same dependencies - try std.testing.expectEqual(original_deps.len, dupe_deps.len); - try std.testing.expectEqual(original_deps[0].name, pkg_dep.name); - - // could segfault otherwise if pointers in duplicated package's fields are - // the same as those in stack allocated package's fields - try std.testing.expect(dupe_deps.ptr != original_deps.ptr); - try std.testing.expect(duped.name.ptr != pkg_top.name.ptr); - try std.testing.expect(duped.source.path.ptr != pkg_top.source.path.ptr); - try std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr); - try std.testing.expect(dupe_deps[0].source.path.ptr != pkg_dep.source.path.ptr); -} - test { _ = CheckFileStep; _ = CheckObjectStep; diff --git a/lib/std/Build/CompileStep.zig b/lib/std/Build/CompileStep.zig index 12c73bdba6..879793f781 100644 --- a/lib/std/Build/CompileStep.zig +++ b/lib/std/Build/CompileStep.zig @@ -16,7 +16,7 @@ const FileSource = std.Build.FileSource; const PkgConfigPkg = std.Build.PkgConfigPkg; const PkgConfigError = std.Build.PkgConfigError; const ExecError = std.Build.ExecError; -const Pkg = std.Build.Pkg; +const Module = std.Build.Module; const VcpkgRoot = std.Build.VcpkgRoot; const InstallDir = std.Build.InstallDir; const InstallArtifactStep = std.Build.InstallArtifactStep; @@ -99,7 +99,7 @@ root_src: ?FileSource, out_h_filename: []const u8, out_lib_filename: []const u8, out_pdb_filename: []const u8, -packages: ArrayList(Pkg), +modules: std.StringArrayHashMap(*Module), object_src: []const u8, @@ -334,7 +334,7 @@ pub fn create(builder: *std.Build, options: Options) *CompileStep { .out_pdb_filename = builder.fmt("{s}.pdb", .{name}), .major_only_filename = null, .name_only_filename = null, - .packages = ArrayList(Pkg).init(builder.allocator), + .modules = std.StringArrayHashMap(*Module).init(builder.allocator), .include_dirs = ArrayList(IncludeDir).init(builder.allocator), .link_objects = ArrayList(LinkObject).init(builder.allocator), .c_macros = ArrayList([]const u8).init(builder.allocator), @@ -946,29 +946,29 @@ pub fn addFrameworkPath(self: *CompileStep, dir_path: []const u8) void { self.framework_dirs.append(self.builder.dupe(dir_path)) catch @panic("OOM"); } -pub fn addPackage(self: *CompileStep, package: Pkg) void { - self.packages.append(self.builder.dupePkg(package)) catch @panic("OOM"); - self.addRecursiveBuildDeps(package); +/// Adds a module to be used with `@import` and exposing it in the current +/// package's module table using `name`. +pub fn addModule(cs: *CompileStep, name: []const u8, module: *Module) void { + cs.modules.put(cs.builder.dupe(name), module) catch @panic("OOM"); + cs.addRecursiveBuildDeps(module); } -pub fn addOptions(self: *CompileStep, package_name: []const u8, options: *OptionsStep) void { - self.addPackage(options.getPackage(package_name)); +/// Adds a module to be used with `@import` without exposing it in the current +/// package's module table. +pub fn addAnonymousModule(cs: *CompileStep, name: []const u8, options: std.Build.CreateModuleOptions) void { + const module = cs.builder.createModule(options); + return addModule(cs, name, module); } -fn addRecursiveBuildDeps(self: *CompileStep, package: Pkg) void { - package.source.addStepDependencies(&self.step); - if (package.dependencies) |deps| { - for (deps) |dep| { - self.addRecursiveBuildDeps(dep); - } - } +pub fn addOptions(cs: *CompileStep, module_name: []const u8, options: *OptionsStep) void { + addModule(cs, module_name, options.createModule()); } -pub fn addPackagePath(self: *CompileStep, name: []const u8, pkg_index_path: []const u8) void { - self.addPackage(Pkg{ - .name = self.builder.dupe(name), - .source = .{ .path = self.builder.dupe(pkg_index_path) }, - }); +fn addRecursiveBuildDeps(cs: *CompileStep, module: *Module) void { + module.source_file.addStepDependencies(&cs.step); + for (module.dependencies.values()) |dep| { + cs.addRecursiveBuildDeps(dep); + } } /// If Vcpkg was found on the system, it will be added to include and lib @@ -1023,16 +1023,21 @@ fn linkLibraryOrObject(self: *CompileStep, other: *CompileStep) void { self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM"); } -fn makePackageCmd(self: *CompileStep, pkg: Pkg, zig_args: *ArrayList([]const u8)) error{OutOfMemory}!void { - const builder = self.builder; - +fn appendModuleArgs( + cs: *CompileStep, + zig_args: *ArrayList([]const u8), + name: []const u8, + module: *Module, +) error{OutOfMemory}!void { try zig_args.append("--pkg-begin"); - try zig_args.append(pkg.name); - try zig_args.append(builder.pathFromRoot(pkg.source.getPath(self.builder))); - - if (pkg.dependencies) |dependencies| { - for (dependencies) |sub_pkg| { - try self.makePackageCmd(sub_pkg, zig_args); + try zig_args.append(name); + try zig_args.append(module.builder.pathFromRoot(module.source_file.getPath(module.builder))); + + { + const keys = module.dependencies.keys(); + for (module.dependencies.values()) |sub_module, i| { + const sub_name = keys[i]; + try cs.appendModuleArgs(zig_args, sub_name, sub_module); } } @@ -1563,8 +1568,12 @@ fn make(step: *Step) !void { try zig_args.append("--test-no-exec"); } - for (self.packages.items) |pkg| { - try self.makePackageCmd(pkg, &zig_args); + { + const keys = self.modules.keys(); + for (self.modules.values()) |module, i| { + const name = keys[i]; + try self.appendModuleArgs(&zig_args, name, module); + } } for (self.include_dirs.items) |include_dir| { @@ -1942,46 +1951,6 @@ fn getPkgConfigList(self: *std.Build) ![]const PkgConfigPkg { } } -test "addPackage" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - - const host = try NativeTargetInfo.detect(.{}); - - var builder = try std.Build.create( - arena.allocator(), - "test", - "test", - "test", - "test", - host, - ); - defer builder.destroy(); - - const pkg_dep = Pkg{ - .name = "pkg_dep", - .source = .{ .path = "/not/a/pkg_dep.zig" }, - }; - const pkg_top = Pkg{ - .name = "pkg_dep", - .source = .{ .path = "/not/a/pkg_top.zig" }, - .dependencies = &[_]Pkg{pkg_dep}, - }; - - var exe = builder.addExecutable(.{ - .name = "not_an_executable", - .root_source_file = .{ .path = "/not/an/executable.zig" }, - }); - exe.addPackage(pkg_top); - - try std.testing.expectEqual(@as(usize, 1), exe.packages.items.len); - - const dupe = exe.packages.items[0]; - try std.testing.expectEqualStrings(pkg_top.name, dupe.name); -} - fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) !void { const cond = opt orelse return; try args.ensureUnusedCapacity(1); diff --git a/lib/std/Build/OptionsStep.zig b/lib/std/Build/OptionsStep.zig index c1d2c8454a..8a50456539 100644 --- a/lib/std/Build/OptionsStep.zig +++ b/lib/std/Build/OptionsStep.zig @@ -204,8 +204,11 @@ pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *Compil self.step.dependOn(&artifact.step); } -pub fn getPackage(self: *OptionsStep, package_name: []const u8) std.Build.Pkg { - return .{ .name = package_name, .source = self.getSource() }; +pub fn createModule(self: *OptionsStep) *std.Build.Module { + return self.builder.createModule(.{ + .source_file = self.getSource(), + .dependencies = &.{}, + }); } pub fn getSource(self: *OptionsStep) FileSource { diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index b6e78b07bd..2485668417 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -482,14 +482,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { /// Return the last element from the list. /// Asserts the list has at least one item. - pub fn getLast(self: *Self) T { + pub fn getLast(self: Self) T { const val = self.items[self.items.len - 1]; return val; } /// Return the last element from the list, or /// return `null` if list is empty. - pub fn getLastOrNull(self: *Self) ?T { + pub fn getLastOrNull(self: Self) ?T { if (self.items.len == 0) return null; return self.getLast(); } @@ -961,14 +961,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ /// Return the last element from the list. /// Asserts the list has at least one item. - pub fn getLast(self: *Self) T { + pub fn getLast(self: Self) T { const val = self.items[self.items.len - 1]; return val; } /// Return the last element from the list, or /// return `null` if list is empty. - pub fn getLastOrNull(self: *Self) ?T { + pub fn getLastOrNull(self: Self) ?T { if (self.items.len == 0) return null; return self.getLast(); } @@ -1719,3 +1719,27 @@ test "std.ArrayList(?u32).popOrNull()" { try testing.expect(list.popOrNull().? == null); try testing.expect(list.popOrNull() == null); } + +test "std.ArrayList(u32).getLast()" { + const a = testing.allocator; + + var list = ArrayList(u32).init(a); + defer list.deinit(); + + try list.append(2); + const const_list = list; + try testing.expectEqual(const_list.getLast(), 2); +} + +test "std.ArrayList(u32).getLastOrNull()" { + const a = testing.allocator; + + var list = ArrayList(u32).init(a); + defer list.deinit(); + + try testing.expectEqual(list.getLastOrNull(), null); + + try list.append(2); + const const_list = list; + try testing.expectEqual(const_list.getLastOrNull().?, 2); +} diff --git a/lib/std/math/big.zig b/lib/std/math/big.zig index c7fc0b17f5..c0d8e74eb2 100644 --- a/lib/std/math/big.zig +++ b/lib/std/math/big.zig @@ -13,7 +13,6 @@ pub const Log2Limb = std.math.Log2Int(Limb); comptime { assert(std.math.floorPowerOfTwo(usize, limb_info.bits) == limb_info.bits); - assert(limb_info.bits <= 64); // u128 set is unsupported assert(limb_info.signedness == .unsigned); } diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index d222d6913b..21f5015c6c 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -30,7 +30,7 @@ pub fn calcLimbLen(scalar: anytype) usize { } const w_value = std.math.absCast(scalar); - return @divFloor(@intCast(Limb, math.log2(w_value)), limb_bits) + 1; + return @intCast(usize, @divFloor(@intCast(Limb, math.log2(w_value)), limb_bits) + 1); } pub fn calcToStringLimbsBufferLen(a_len: usize, base: u8) usize { @@ -238,10 +238,7 @@ pub const Mutable = struct { var i: usize = 0; while (true) : (i += 1) { self.limbs[i] = @truncate(Limb, w_value); - - // TODO: shift == 64 at compile-time fails. Fails on u128 limbs. - w_value >>= limb_bits / 2; - w_value >>= limb_bits / 2; + w_value >>= limb_bits; if (w_value == 0) break; } @@ -258,9 +255,7 @@ pub const Mutable = struct { comptime var i = 0; inline while (true) : (i += 1) { self.limbs[i] = w_value & mask; - - w_value >>= limb_bits / 2; - w_value >>= limb_bits / 2; + w_value >>= limb_bits; if (w_value == 0) break; } diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index d9d5fb3204..5d6c9f5cc9 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -40,6 +40,7 @@ const arch_bits = switch (native_arch) { .riscv64 => @import("linux/riscv64.zig"), .sparc64 => @import("linux/sparc64.zig"), .mips, .mipsel => @import("linux/mips.zig"), + .mips64, .mips64el => @import("linux/mips64.zig"), .powerpc => @import("linux/powerpc.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), else => struct {}, @@ -101,6 +102,7 @@ pub const SYS = switch (@import("builtin").cpu.arch) { .riscv64 => syscalls.RiscV64, .sparc64 => syscalls.Sparc64, .mips, .mipsel => syscalls.Mips, + .mips64, .mips64el => syscalls.Mips64, .powerpc => syscalls.PowerPC, .powerpc64, .powerpc64le => syscalls.PowerPC64, else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"), diff --git a/lib/std/os/linux/mips64.zig b/lib/std/os/linux/mips64.zig new file mode 100644 index 0000000000..dfc1c9b576 --- /dev/null +++ b/lib/std/os/linux/mips64.zig @@ -0,0 +1,413 @@ +const std = @import("../../std.zig"); +const maxInt = std.math.maxInt; +const linux = std.os.linux; +const SYS = linux.SYS; +const socklen_t = linux.socklen_t; +const iovec = std.os.iovec; +const iovec_const = std.os.iovec_const; +const uid_t = linux.uid_t; +const gid_t = linux.gid_t; +const pid_t = linux.pid_t; +const sockaddr = linux.sockaddr; +const timespec = linux.timespec; + +pub fn syscall0(number: SYS) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall_pipe(fd: *[2]i32) usize { + return asm volatile ( + \\ .set noat + \\ .set noreorder + \\ syscall + \\ blez $7, 1f + \\ nop + \\ b 2f + \\ subu $2, $0, $2 + \\ 1: + \\ sw $2, 0($4) + \\ sw $3, 4($4) + \\ 2: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(SYS.pipe)), + [fd] "{$4}" (fd), + : "$1", "$3", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + : "$1", "$3", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + : "$1", "$3", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + : "$1", "$3", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + [arg5] "{$8}" (arg5), + : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +// NOTE: The o32 calling convention requires the callee to reserve 16 bytes for +// the first four arguments even though they're passed in $a0-$a3. + +pub fn syscall6( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + [arg5] "{$8}" (arg5), + [arg6] "{$9}" (arg6), + : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn syscall7( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, + arg7: usize, +) usize { + return asm volatile ( + \\ syscall + \\ blez $7, 1f + \\ dsubu $2, $0, $2 + \\ 1: + : [ret] "={$2}" (-> usize), + : [number] "{$2}" (@enumToInt(number)), + [arg1] "{$4}" (arg1), + [arg2] "{$5}" (arg2), + [arg3] "{$6}" (arg3), + [arg4] "{$7}" (arg4), + [arg5] "{$8}" (arg5), + [arg6] "{$9}" (arg6), + [arg7] "{$10}" (arg7), + : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +const CloneFn = *const fn (arg: usize) callconv(.C) u8; + +/// This matches the libc clone function. +pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; + +pub fn restore() callconv(.Naked) void { + return asm volatile ("syscall" + : + : [number] "{$2}" (@enumToInt(SYS.rt_sigreturn)), + : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub fn restore_rt() callconv(.Naked) void { + return asm volatile ("syscall" + : + : [number] "{$2}" (@enumToInt(SYS.rt_sigreturn)), + : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory" + ); +} + +pub const O = struct { + pub const CREAT = 0o0400; + pub const EXCL = 0o02000; + pub const NOCTTY = 0o04000; + pub const TRUNC = 0o01000; + pub const APPEND = 0o0010; + pub const NONBLOCK = 0o0200; + pub const DSYNC = 0o0020; + pub const SYNC = 0o040020; + pub const RSYNC = 0o040020; + pub const DIRECTORY = 0o0200000; + pub const NOFOLLOW = 0o0400000; + pub const CLOEXEC = 0o02000000; + + pub const ASYNC = 0o010000; + pub const DIRECT = 0o0100000; + pub const LARGEFILE = 0o020000; + pub const NOATIME = 0o01000000; + pub const PATH = 0o010000000; + pub const TMPFILE = 0o020200000; + pub const NDELAY = NONBLOCK; +}; + +pub const F = struct { + pub const DUPFD = 0; + pub const GETFD = 1; + pub const SETFD = 2; + pub const GETFL = 3; + pub const SETFL = 4; + + pub const SETOWN = 24; + pub const GETOWN = 23; + pub const SETSIG = 10; + pub const GETSIG = 11; + + pub const GETLK = 33; + pub const SETLK = 34; + pub const SETLKW = 35; + + pub const RDLCK = 0; + pub const WRLCK = 1; + pub const UNLCK = 2; + + pub const SETOWN_EX = 15; + pub const GETOWN_EX = 16; + + pub const GETOWNER_UIDS = 17; +}; + +pub const LOCK = struct { + pub const SH = 1; + pub const EX = 2; + pub const UN = 8; + pub const NB = 4; +}; + +pub const MMAP2_UNIT = 4096; + +pub const MAP = struct { + pub const NORESERVE = 0x0400; + pub const GROWSDOWN = 0x1000; + pub const DENYWRITE = 0x2000; + pub const EXECUTABLE = 0x4000; + pub const LOCKED = 0x8000; + pub const @"32BIT" = 0x40; +}; + +pub const VDSO = struct { + pub const CGT_SYM = "__kernel_clock_gettime"; + pub const CGT_VER = "LINUX_2.6.39"; +}; + +pub const Flock = extern struct { + type: i16, + whence: i16, + __pad0: [4]u8, + start: off_t, + len: off_t, + pid: pid_t, + __unused: [4]u8, +}; + +pub const msghdr = extern struct { + name: ?*sockaddr, + namelen: socklen_t, + iov: [*]iovec, + iovlen: i32, + control: ?*anyopaque, + controllen: socklen_t, + flags: i32, +}; + +pub const msghdr_const = extern struct { + name: ?*const sockaddr, + namelen: socklen_t, + iov: [*]const iovec_const, + iovlen: i32, + control: ?*const anyopaque, + controllen: socklen_t, + flags: i32, +}; + +pub const blksize_t = i32; +pub const nlink_t = u32; +pub const time_t = i32; +pub const mode_t = u32; +pub const off_t = i64; +pub const ino_t = u64; +pub const dev_t = u64; +pub const blkcnt_t = i64; + +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: u32, + __pad0: [3]u32, // Reserved for st_dev expansion + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + rdev: u32, + __pad1: [3]u32, + size: off_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + blksize: blksize_t, + __pad3: u32, + blocks: blkcnt_t, + __pad4: [14]usize, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) timespec { + return self.ctim; + } +}; + +pub const timeval = extern struct { + tv_sec: isize, + tv_usec: isize, +}; + +pub const timezone = extern struct { + tz_minuteswest: i32, + tz_dsttime: i32, +}; + +pub const Elf_Symndx = u32; + +pub const rlimit_resource = enum(c_int) { + /// Per-process CPU limit, in seconds. + CPU, + + /// Largest file that can be created, in bytes. + FSIZE, + + /// Maximum size of data segment, in bytes. + DATA, + + /// Maximum size of stack segment, in bytes. + STACK, + + /// Largest core file that can be created, in bytes. + CORE, + + /// Number of open files. + NOFILE, + + /// Address space limit. + AS, + + /// Largest resident set size, in bytes. + /// This affects swapping; processes that are exceeding their + /// resident set size will be more likely to have physical memory + /// taken from them. + RSS, + + /// Number of processes. + NPROC, + + /// Locked-in-memory address space. + MEMLOCK, + + /// Maximum number of file locks. + LOCKS, + + /// Maximum number of pending signals. + SIGPENDING, + + /// Maximum bytes in POSIX message queues. + MSGQUEUE, + + /// Maximum nice priority allowed to raise to. + /// Nice levels 19 .. -20 correspond to 0 .. 39 + /// values of this resource limit. + NICE, + + /// Maximum realtime priority allowed for non-priviledged + /// processes. + RTPRIO, + + /// Maximum CPU time in µs that a process scheduled under a real-time + /// scheduling policy may consume without making a blocking system + /// call before being forcibly descheduled. + RTTIME, + + _, +}; diff --git a/lib/std/os/linux/syscalls.zig b/lib/std/os/linux/syscalls.zig index 6e8cee7b84..36a8bae04c 100644 --- a/lib/std/os/linux/syscalls.zig +++ b/lib/std/os/linux/syscalls.zig @@ -2032,6 +2032,361 @@ pub const Mips = enum(usize) { set_mempolicy_home_node = Linux + 450, }; +pub const Mips64 = enum(usize) { + pub const Linux = 5000; + + read = Linux + 0, + write = Linux + 1, + open = Linux + 2, + close = Linux + 3, + stat = Linux + 4, + fstat = Linux + 5, + lstat = Linux + 6, + poll = Linux + 7, + lseek = Linux + 8, + mmap = Linux + 9, + mprotect = Linux + 10, + munmap = Linux + 11, + brk = Linux + 12, + rt_sigaction = Linux + 13, + rt_sigprocmask = Linux + 14, + ioctl = Linux + 15, + pread64 = Linux + 16, + pwrite64 = Linux + 17, + readv = Linux + 18, + writev = Linux + 19, + access = Linux + 20, + pipe = Linux + 21, + select = Linux + 22, + sched_yield = Linux + 23, + mremap = Linux + 24, + msync = Linux + 25, + mincore = Linux + 26, + madvise = Linux + 27, + shmget = Linux + 28, + shmat = Linux + 29, + shmctl = Linux + 30, + dup = Linux + 31, + dup2 = Linux + 32, + pause = Linux + 33, + nanosleep = Linux + 34, + getitimer = Linux + 35, + alarm = Linux + 36, + setitimer = Linux + 37, + getpid = Linux + 38, + sendfile = Linux + 39, + socket = Linux + 40, + connect = Linux + 41, + accept = Linux + 42, + sendto = Linux + 43, + recvfrom = Linux + 44, + sendmsg = Linux + 45, + recvmsg = Linux + 46, + shutdown = Linux + 47, + bind = Linux + 48, + listen = Linux + 49, + getsockname = Linux + 50, + getpeername = Linux + 51, + socketpair = Linux + 52, + setsockopt = Linux + 53, + getsockopt = Linux + 54, + clone = Linux + 55, + fork = Linux + 56, + execve = Linux + 57, + exit = Linux + 58, + wait4 = Linux + 59, + kill = Linux + 60, + uname = Linux + 61, + semget = Linux + 62, + semop = Linux + 63, + semctl = Linux + 64, + shmdt = Linux + 65, + msgget = Linux + 66, + msgsnd = Linux + 67, + msgrcv = Linux + 68, + msgctl = Linux + 69, + fcntl = Linux + 70, + flock = Linux + 71, + fsync = Linux + 72, + fdatasync = Linux + 73, + truncate = Linux + 74, + ftruncate = Linux + 75, + getdents = Linux + 76, + getcwd = Linux + 77, + chdir = Linux + 78, + fchdir = Linux + 79, + rename = Linux + 80, + mkdir = Linux + 81, + rmdir = Linux + 82, + creat = Linux + 83, + link = Linux + 84, + unlink = Linux + 85, + symlink = Linux + 86, + readlink = Linux + 87, + chmod = Linux + 88, + fchmod = Linux + 89, + chown = Linux + 90, + fchown = Linux + 91, + lchown = Linux + 92, + umask = Linux + 93, + gettimeofday = Linux + 94, + getrlimit = Linux + 95, + getrusage = Linux + 96, + sysinfo = Linux + 97, + times = Linux + 98, + ptrace = Linux + 99, + getuid = Linux + 100, + syslog = Linux + 101, + getgid = Linux + 102, + setuid = Linux + 103, + setgid = Linux + 104, + geteuid = Linux + 105, + getegid = Linux + 106, + setpgid = Linux + 107, + getppid = Linux + 108, + getpgrp = Linux + 109, + setsid = Linux + 110, + setreuid = Linux + 111, + setregid = Linux + 112, + getgroups = Linux + 113, + setgroups = Linux + 114, + setresuid = Linux + 115, + getresuid = Linux + 116, + setresgid = Linux + 117, + getresgid = Linux + 118, + getpgid = Linux + 119, + setfsuid = Linux + 120, + setfsgid = Linux + 121, + getsid = Linux + 122, + capget = Linux + 123, + capset = Linux + 124, + rt_sigpending = Linux + 125, + rt_sigtimedwait = Linux + 126, + rt_sigqueueinfo = Linux + 127, + rt_sigsuspend = Linux + 128, + sigaltstack = Linux + 129, + utime = Linux + 130, + mknod = Linux + 131, + personality = Linux + 132, + ustat = Linux + 133, + statfs = Linux + 134, + fstatfs = Linux + 135, + sysfs = Linux + 136, + getpriority = Linux + 137, + setpriority = Linux + 138, + sched_setparam = Linux + 139, + sched_getparam = Linux + 140, + sched_setscheduler = Linux + 141, + sched_getscheduler = Linux + 142, + sched_get_priority_max = Linux + 143, + sched_get_priority_min = Linux + 144, + sched_rr_get_interval = Linux + 145, + mlock = Linux + 146, + munlock = Linux + 147, + mlockall = Linux + 148, + munlockall = Linux + 149, + vhangup = Linux + 150, + pivot_root = Linux + 151, + _sysctl = Linux + 152, + prctl = Linux + 153, + adjtimex = Linux + 154, + setrlimit = Linux + 155, + chroot = Linux + 156, + sync = Linux + 157, + acct = Linux + 158, + settimeofday = Linux + 159, + mount = Linux + 160, + umount2 = Linux + 161, + swapon = Linux + 162, + swapoff = Linux + 163, + reboot = Linux + 164, + sethostname = Linux + 165, + setdomainname = Linux + 166, + create_module = Linux + 167, + init_module = Linux + 168, + delete_module = Linux + 169, + get_kernel_syms = Linux + 170, + query_module = Linux + 171, + quotactl = Linux + 172, + nfsservctl = Linux + 173, + getpmsg = Linux + 174, + putpmsg = Linux + 175, + afs_syscall = Linux + 176, + reserved177 = Linux + 177, + gettid = Linux + 178, + readahead = Linux + 179, + setxattr = Linux + 180, + lsetxattr = Linux + 181, + fsetxattr = Linux + 182, + getxattr = Linux + 183, + lgetxattr = Linux + 184, + fgetxattr = Linux + 185, + listxattr = Linux + 186, + llistxattr = Linux + 187, + flistxattr = Linux + 188, + removexattr = Linux + 189, + lremovexattr = Linux + 190, + fremovexattr = Linux + 191, + tkill = Linux + 192, + reserved193 = Linux + 193, + futex = Linux + 194, + sched_setaffinity = Linux + 195, + sched_getaffinity = Linux + 196, + cacheflush = Linux + 197, + cachectl = Linux + 198, + sysmips = Linux + 199, + io_setup = Linux + 200, + io_destroy = Linux + 201, + io_getevents = Linux + 202, + io_submit = Linux + 203, + io_cancel = Linux + 204, + exit_group = Linux + 205, + lookup_dcookie = Linux + 206, + epoll_create = Linux + 207, + epoll_ctl = Linux + 208, + epoll_wait = Linux + 209, + remap_file_pages = Linux + 210, + rt_sigreturn = Linux + 211, + set_tid_address = Linux + 212, + restart_syscall = Linux + 213, + semtimedop = Linux + 214, + fadvise64 = Linux + 215, + timer_create = Linux + 216, + timer_settime = Linux + 217, + timer_gettime = Linux + 218, + timer_getoverrun = Linux + 219, + timer_delete = Linux + 220, + clock_settime = Linux + 221, + clock_gettime = Linux + 222, + clock_getres = Linux + 223, + clock_nanosleep = Linux + 224, + tgkill = Linux + 225, + utimes = Linux + 226, + mbind = Linux + 227, + get_mempolicy = Linux + 228, + set_mempolicy = Linux + 229, + mq_open = Linux + 230, + mq_unlink = Linux + 231, + mq_timedsend = Linux + 232, + mq_timedreceive = Linux + 233, + mq_notify = Linux + 234, + mq_getsetattr = Linux + 235, + vserver = Linux + 236, + waitid = Linux + 237, + add_key = Linux + 239, + request_key = Linux + 240, + keyctl = Linux + 241, + set_thread_area = Linux + 242, + inotify_init = Linux + 243, + inotify_add_watch = Linux + 244, + inotify_rm_watch = Linux + 245, + migrate_pages = Linux + 246, + openat = Linux + 247, + mkdirat = Linux + 248, + mknodat = Linux + 249, + fchownat = Linux + 250, + futimesat = Linux + 251, + newfstatat = Linux + 252, + unlinkat = Linux + 253, + renameat = Linux + 254, + linkat = Linux + 255, + symlinkat = Linux + 256, + readlinkat = Linux + 257, + fchmodat = Linux + 258, + faccessat = Linux + 259, + pselect6 = Linux + 260, + ppoll = Linux + 261, + unshare = Linux + 262, + splice = Linux + 263, + sync_file_range = Linux + 264, + tee = Linux + 265, + vmsplice = Linux + 266, + move_pages = Linux + 267, + set_robust_list = Linux + 268, + get_robust_list = Linux + 269, + kexec_load = Linux + 270, + getcpu = Linux + 271, + epoll_pwait = Linux + 272, + ioprio_set = Linux + 273, + ioprio_get = Linux + 274, + utimensat = Linux + 275, + signalfd = Linux + 276, + timerfd = Linux + 277, + eventfd = Linux + 278, + fallocate = Linux + 279, + timerfd_create = Linux + 280, + timerfd_settime = Linux + 281, + timerfd_gettime = Linux + 282, + signalfd4 = Linux + 283, + eventfd2 = Linux + 284, + epoll_create1 = Linux + 285, + dup3 = Linux + 286, + pipe2 = Linux + 287, + inotify_init1 = Linux + 288, + preadv = Linux + 289, + pwritev = Linux + 290, + rt_tgsigqueueinfo = Linux + 291, + perf_event_open = Linux + 292, + accept4 = Linux + 293, + recvmmsg = Linux + 294, + fanotify_init = Linux + 295, + fanotify_mark = Linux + 296, + prlimit64 = Linux + 297, + name_to_handle_at = Linux + 298, + open_by_handle_at = Linux + 299, + clock_adjtime = Linux + 300, + syncfs = Linux + 301, + sendmmsg = Linux + 302, + setns = Linux + 303, + process_vm_readv = Linux + 304, + process_vm_writev = Linux + 305, + kcmp = Linux + 306, + finit_module = Linux + 307, + getdents64 = Linux + 308, + sched_setattr = Linux + 309, + sched_getattr = Linux + 310, + renameat2 = Linux + 311, + seccomp = Linux + 312, + getrandom = Linux + 313, + memfd_create = Linux + 314, + bpf = Linux + 315, + execveat = Linux + 316, + userfaultfd = Linux + 317, + membarrier = Linux + 318, + mlock2 = Linux + 319, + copy_file_range = Linux + 320, + preadv2 = Linux + 321, + pwritev2 = Linux + 322, + pkey_mprotect = Linux + 323, + pkey_alloc = Linux + 324, + pkey_free = Linux + 325, + statx = Linux + 326, + rseq = Linux + 327, + io_pgetevents = Linux + 328, + pidfd_send_signal = Linux + 424, + io_uring_setup = Linux + 425, + io_uring_enter = Linux + 426, + io_uring_register = Linux + 427, + open_tree = Linux + 428, + move_mount = Linux + 429, + fsopen = Linux + 430, + fsconfig = Linux + 431, + fsmount = Linux + 432, + fspick = Linux + 433, + pidfd_open = Linux + 434, + clone3 = Linux + 435, + close_range = Linux + 436, + openat2 = Linux + 437, + pidfd_getfd = Linux + 438, + faccessat2 = Linux + 439, + process_madvise = Linux + 440, + epoll_pwait2 = Linux + 441, + mount_setattr = Linux + 442, + landlock_create_ruleset = Linux + 444, + landlock_add_rule = Linux + 445, + landlock_restrict_self = Linux + 446, +}; + pub const PowerPC = enum(usize) { restart_syscall = 0, exit = 1, diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index d487530f55..cffdec0424 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -48,7 +48,7 @@ const TLSVariant = enum { }; const tls_variant = switch (native_arch) { - .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, + .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, .x86_64, .x86, .sparc64 => TLSVariant.VariantII, else => @compileError("undefined tls_variant for this architecture"), }; @@ -64,7 +64,7 @@ const tls_tcb_size = switch (native_arch) { // Controls if the TP points to the end of the TCB instead of its beginning const tls_tp_points_past_tcb = switch (native_arch) { - .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => true, + .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => true, else => false, }; @@ -72,12 +72,12 @@ const tls_tp_points_past_tcb = switch (native_arch) { // make the generated code more efficient const tls_tp_offset = switch (native_arch) { - .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000, + .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => 0x7000, else => 0, }; const tls_dtv_offset = switch (native_arch) { - .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000, + .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => 0x8000, .riscv32, .riscv64 => 0x800, else => 0, }; @@ -156,7 +156,7 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr), ); }, - .mips, .mipsel => { + .mips, .mipsel, .mips64, .mips64el => { const rc = std.os.linux.syscall1(.set_thread_area, addr); assert(rc == 0); }, diff --git a/lib/std/start.zig b/lib/std/start.zig index 8aef63332d..ea221d1539 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -327,7 +327,7 @@ fn _start() callconv(.Naked) noreturn { : [argc] "={sp}" (-> [*]usize), ); }, - .mips, .mipsel => { + .mips, .mipsel, .mips64, .mips64el => { // The lr is already zeroed on entry, as specified by the ABI. argc_argv_ptr = asm volatile ( \\ move $fp, $0 |
