| ... | @@ -10,7 +10,12 @@ const zig = std.zig; | ... | @@ -10,7 +10,12 @@ const zig = std.zig; |
| 10 | const fs = std.fs; | 10 | const fs = std.fs; |
| 11 | | 11 | |
| 12 | const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ | 12 | const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ |
| | 13 | // Remove underscore prefix. |
| | 14 | .{ "_llseek", "llseek" }, |
| | 15 | .{ "_newselect", "newselect" }, |
| | 16 | .{ "_sysctl", "sysctl" }, |
| 13 | // Most 64-bit archs. | 17 | // Most 64-bit archs. |
| | 18 | .{ "newfstat", "fstat64" }, |
| 14 | .{ "newfstatat", "fstatat64" }, | 19 | .{ "newfstatat", "fstatat64" }, |
| 15 | // POWER. | 20 | // POWER. |
| 16 | .{ "sync_file_range2", "sync_file_range" }, | 21 | .{ "sync_file_range2", "sync_file_range" }, |
| ... | @@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ | ... | @@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ |
| 19 | .{ "arm_fadvise64_64", "fadvise64_64" }, | 24 | .{ "arm_fadvise64_64", "fadvise64_64" }, |
| 20 | }); | 25 | }); |
| 21 | | 26 | |
| | 27 | // Only for newer architectures where we use the C preprocessor. |
| | 28 | const stdlib_renames_new = std.StaticStringMap([]const u8).initComptime(.{ |
| | 29 | .{ "newuname", "uname" }, |
| | 30 | .{ "umount", "umount2" }, |
| | 31 | }); |
| | 32 | |
| | 33 | // We use this to deal with the fact that multiple syscalls can be mapped to sys_ni_syscall. |
| | 34 | // Thankfully it's only 2 well-known syscalls in newer kernel ports at the moment. |
| | 35 | fn getOverridenNameNew(value: []const u8) ?[]const u8 { |
| | 36 | if (mem.eql(u8, value, "18")) { |
| | 37 | return "sys_lookup_dcookie"; |
| | 38 | } else if (mem.eql(u8, value, "42")) { |
| | 39 | return "sys_nfsservctl"; |
| | 40 | } else { |
| | 41 | return null; |
| | 42 | } |
| | 43 | } |
| | 44 | |
| 22 | pub fn main() !void { | 45 | pub fn main() !void { |
| 23 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 46 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); |
| 24 | defer arena.deinit(); | 47 | defer arena.deinit(); |
| ... | @@ -60,8 +83,9 @@ pub fn main() !void { | ... | @@ -60,8 +83,9 @@ pub fn main() !void { |
| 60 | // abi is always i386 | 83 | // abi is always i386 |
| 61 | _ = fields.next() orelse return error.Incomplete; | 84 | _ = fields.next() orelse return error.Incomplete; |
| 62 | const name = fields.next() orelse return error.Incomplete; | 85 | const name = fields.next() orelse return error.Incomplete; |
| | 86 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; |
| 63 | | 87 | |
| 64 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number }); | 88 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); |
| 65 | } | 89 | } |
| 66 | | 90 | |
| 67 | try writer.writeAll("};\n\n"); | 91 | try writer.writeAll("};\n\n"); |
| ... | @@ -80,8 +104,8 @@ pub fn main() !void { | ... | @@ -80,8 +104,8 @@ pub fn main() !void { |
| 80 | // The x32 abi syscalls are always at the end. | 104 | // The x32 abi syscalls are always at the end. |
| 81 | if (mem.eql(u8, abi, "x32")) break; | 105 | if (mem.eql(u8, abi, "x32")) break; |
| 82 | const name = fields.next() orelse return error.Incomplete; | 106 | const name = fields.next() orelse return error.Incomplete; |
| 83 | | | |
| 84 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; | 107 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; |
| | 108 | |
| 85 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); | 109 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); |
| 86 | } | 110 | } |
| 87 | | 111 | |
| ... | @@ -105,8 +129,8 @@ pub fn main() !void { | ... | @@ -105,8 +129,8 @@ pub fn main() !void { |
| 105 | const abi = fields.next() orelse return error.Incomplete; | 129 | const abi = fields.next() orelse return error.Incomplete; |
| 106 | if (mem.eql(u8, abi, "oabi")) continue; | 130 | if (mem.eql(u8, abi, "oabi")) continue; |
| 107 | const name = fields.next() orelse return error.Incomplete; | 131 | const name = fields.next() orelse return error.Incomplete; |
| 108 | | | |
| 109 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; | 132 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; |
| | 133 | |
| 110 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); | 134 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); |
| 111 | } | 135 | } |
| 112 | | 136 | |
| ... | @@ -136,8 +160,9 @@ pub fn main() !void { | ... | @@ -136,8 +160,9 @@ pub fn main() !void { |
| 136 | const abi = fields.next() orelse return error.Incomplete; | 160 | const abi = fields.next() orelse return error.Incomplete; |
| 137 | if (mem.eql(u8, abi, "32")) continue; | 161 | if (mem.eql(u8, abi, "32")) continue; |
| 138 | const name = fields.next() orelse return error.Incomplete; | 162 | const name = fields.next() orelse return error.Incomplete; |
| | 163 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; |
| 139 | | 164 | |
| 140 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number }); | 165 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); |
| 141 | } | 166 | } |
| 142 | | 167 | |
| 143 | try writer.writeAll("};\n\n"); | 168 | try writer.writeAll("};\n\n"); |
| ... | @@ -161,8 +186,9 @@ pub fn main() !void { | ... | @@ -161,8 +186,9 @@ pub fn main() !void { |
| 161 | _ = fields.next() orelse return error.Incomplete; | 186 | _ = fields.next() orelse return error.Incomplete; |
| 162 | const name = fields.next() orelse return error.Incomplete; | 187 | const name = fields.next() orelse return error.Incomplete; |
| 163 | if (mem.startsWith(u8, name, "unused")) continue; | 188 | if (mem.startsWith(u8, name, "unused")) continue; |
| | 189 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; |
| 164 | | 190 | |
| 165 | try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(name), number }); | 191 | try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(fixed_name), number }); |
| 166 | } | 192 | } |
| 167 | | 193 | |
| 168 | try writer.writeAll("};\n\n"); | 194 | try writer.writeAll("};\n\n"); |
| ... | @@ -232,11 +258,6 @@ pub fn main() !void { | ... | @@ -232,11 +258,6 @@ pub fn main() !void { |
| 232 | // Newer architectures (starting with aarch64 c. 2012) now use the same C | 258 | // Newer architectures (starting with aarch64 c. 2012) now use the same C |
| 233 | // header file for their syscall numbers. Arch-specific headers are used to | 259 | // header file for their syscall numbers. Arch-specific headers are used to |
| 234 | // define pre-proc. vars that add additional (usually obsolete) syscalls. | 260 | // define pre-proc. vars that add additional (usually obsolete) syscalls. |
| 235 | // | | |
| 236 | // TODO: | | |
| 237 | // - It would be better to use libclang/translate-c directly to extract the definitions. | | |
| 238 | // - The `-dD` option only does minimal pre-processing and doesn't resolve addition, | | |
| 239 | // so arch specific syscalls are dealt with manually. | | |
| 240 | { | 261 | { |
| 241 | try writer.writeAll("pub const Arm64 = enum(usize) {\n"); | 262 | try writer.writeAll("pub const Arm64 = enum(usize) {\n"); |
| 242 | | 263 | |
| ... | @@ -254,6 +275,8 @@ pub fn main() !void { | ... | @@ -254,6 +275,8 @@ pub fn main() !void { |
| 254 | // Using -I=[dir] includes the zig linux headers, which we don't want. | 275 | // Using -I=[dir] includes the zig linux headers, which we don't want. |
| 255 | "-Iinclude", | 276 | "-Iinclude", |
| 256 | "-Iinclude/uapi", | 277 | "-Iinclude/uapi", |
| | 278 | // Output the syscall in a format we can easily recognize. |
| | 279 | "-D __SYSCALL(nr, nm)=zigsyscall nm nr", |
| 257 | "arch/arm64/include/uapi/asm/unistd.h", | 280 | "arch/arm64/include/uapi/asm/unistd.h", |
| 258 | }; | 281 | }; |
| 259 | | 282 | |
| ... | @@ -277,32 +300,24 @@ pub fn main() !void { | ... | @@ -277,32 +300,24 @@ pub fn main() !void { |
| 277 | }; | 300 | }; |
| 278 | | 301 | |
| 279 | var lines = mem.tokenizeScalar(u8, defines, '\n'); | 302 | var lines = mem.tokenizeScalar(u8, defines, '\n'); |
| 280 | loop: while (lines.next()) |line| { | 303 | while (lines.next()) |line| { |
| 281 | var fields = mem.tokenizeAny(u8, line, " \t"); | 304 | var fields = mem.tokenizeAny(u8, line, " "); |
| 282 | const cmd = fields.next() orelse return error.Incomplete; | 305 | const prefix = fields.next() orelse return error.Incomplete; |
| 283 | if (!mem.eql(u8, cmd, "#define")) continue; | | |
| 284 | const define = fields.next() orelse return error.Incomplete; | | |
| 285 | const number = fields.next() orelse continue; | | |
| 286 | | 306 | |
| 287 | if (!std.ascii.isDigit(number[0])) continue; | 307 | if (!mem.eql(u8, prefix, "zigsyscall")) continue; |
| 288 | if (!mem.startsWith(u8, define, "__NR")) continue; | | |
| 289 | const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_"); | | |
| 290 | if (mem.eql(u8, name, "arch_specific_syscall")) continue; | | |
| 291 | if (mem.eql(u8, name, "syscalls")) break :loop; | | |
| 292 | | 308 | |
| 293 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; | 309 | const sys_name = fields.next() orelse return error.Incomplete; |
| 294 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); | 310 | const value = fields.rest(); |
| | 311 | const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..]; |
| | 312 | const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name; |
| | 313 | |
| | 314 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value }); |
| 295 | } | 315 | } |
| 296 | | 316 | |
| 297 | try writer.writeAll("};\n\n"); | 317 | try writer.writeAll("};\n\n"); |
| 298 | } | 318 | } |
| 299 | { | 319 | { |
| 300 | try writer.writeAll( | 320 | try writer.writeAll("pub const RiscV32 = enum(usize) {\n"); |
| 301 | \\pub const RiscV32 = enum(usize) { | | |
| 302 | \\ pub const arch_specific_syscall = 244; | | |
| 303 | \\ | | |
| 304 | \\ | | |
| 305 | ); | | |
| 306 | | 321 | |
| 307 | const child_args = [_][]const u8{ | 322 | const child_args = [_][]const u8{ |
| 308 | zig_exe, | 323 | zig_exe, |
| ... | @@ -316,6 +331,7 @@ pub fn main() !void { | ... | @@ -316,6 +331,7 @@ pub fn main() !void { |
| 316 | "-Iinclude", | 331 | "-Iinclude", |
| 317 | "-Iinclude/uapi", | 332 | "-Iinclude/uapi", |
| 318 | "-Iarch/riscv/include/uapi", | 333 | "-Iarch/riscv/include/uapi", |
| | 334 | "-D __SYSCALL(nr, nm)=zigsyscall nm nr", |
| 319 | "arch/riscv/include/uapi/asm/unistd.h", | 335 | "arch/riscv/include/uapi/asm/unistd.h", |
| 320 | }; | 336 | }; |
| 321 | | 337 | |
| ... | @@ -339,38 +355,24 @@ pub fn main() !void { | ... | @@ -339,38 +355,24 @@ pub fn main() !void { |
| 339 | }; | 355 | }; |
| 340 | | 356 | |
| 341 | var lines = mem.tokenizeScalar(u8, defines, '\n'); | 357 | var lines = mem.tokenizeScalar(u8, defines, '\n'); |
| 342 | loop: while (lines.next()) |line| { | 358 | while (lines.next()) |line| { |
| 343 | var fields = mem.tokenizeAny(u8, line, " \t"); | 359 | var fields = mem.tokenizeAny(u8, line, " "); |
| 344 | const cmd = fields.next() orelse return error.Incomplete; | 360 | const prefix = fields.next() orelse return error.Incomplete; |
| 345 | if (!mem.eql(u8, cmd, "#define")) continue; | | |
| 346 | const define = fields.next() orelse return error.Incomplete; | | |
| 347 | const number = fields.next() orelse continue; | | |
| 348 | | 361 | |
| 349 | if (!std.ascii.isDigit(number[0])) continue; | 362 | if (!mem.eql(u8, prefix, "zigsyscall")) continue; |
| 350 | if (!mem.startsWith(u8, define, "__NR")) continue; | | |
| 351 | const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_"); | | |
| 352 | if (mem.eql(u8, name, "arch_specific_syscall")) continue; | | |
| 353 | if (mem.eql(u8, name, "syscalls")) break :loop; | | |
| 354 | | 363 | |
| 355 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; | 364 | const sys_name = fields.next() orelse return error.Incomplete; |
| 356 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); | 365 | const value = fields.rest(); |
| | 366 | const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..]; |
| | 367 | const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name; |
| | 368 | |
| | 369 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value }); |
| 357 | } | 370 | } |
| 358 | | 371 | |
| 359 | try writer.writeAll( | 372 | try writer.writeAll("};\n\n"); |
| 360 | \\ | | |
| 361 | \\ riscv_flush_icache = arch_specific_syscall + 15, | | |
| 362 | \\ riscv_hwprobe = arch_specific_syscall + 14, | | |
| 363 | \\}; | | |
| 364 | \\ | | |
| 365 | ); | | |
| 366 | } | 373 | } |
| 367 | { | 374 | { |
| 368 | try writer.writeAll( | 375 | try writer.writeAll("pub const RiscV64 = enum(usize) {\n"); |
| 369 | \\pub const RiscV64 = enum(usize) { | | |
| 370 | \\ pub const arch_specific_syscall = 244; | | |
| 371 | \\ | | |
| 372 | \\ | | |
| 373 | ); | | |
| 374 | | 376 | |
| 375 | const child_args = [_][]const u8{ | 377 | const child_args = [_][]const u8{ |
| 376 | zig_exe, | 378 | zig_exe, |
| ... | @@ -384,6 +386,7 @@ pub fn main() !void { | ... | @@ -384,6 +386,7 @@ pub fn main() !void { |
| 384 | "-Iinclude", | 386 | "-Iinclude", |
| 385 | "-Iinclude/uapi", | 387 | "-Iinclude/uapi", |
| 386 | "-Iarch/riscv/include/uapi", | 388 | "-Iarch/riscv/include/uapi", |
| | 389 | "-D __SYSCALL(nr, nm)=zigsyscall nm nr", |
| 387 | "arch/riscv/include/uapi/asm/unistd.h", | 390 | "arch/riscv/include/uapi/asm/unistd.h", |
| 388 | }; | 391 | }; |
| 389 | | 392 | |
| ... | @@ -407,30 +410,21 @@ pub fn main() !void { | ... | @@ -407,30 +410,21 @@ pub fn main() !void { |
| 407 | }; | 410 | }; |
| 408 | | 411 | |
| 409 | var lines = mem.tokenizeScalar(u8, defines, '\n'); | 412 | var lines = mem.tokenizeScalar(u8, defines, '\n'); |
| 410 | loop: while (lines.next()) |line| { | 413 | while (lines.next()) |line| { |
| 411 | var fields = mem.tokenizeAny(u8, line, " \t"); | 414 | var fields = mem.tokenizeAny(u8, line, " "); |
| 412 | const cmd = fields.next() orelse return error.Incomplete; | 415 | const prefix = fields.next() orelse return error.Incomplete; |
| 413 | if (!mem.eql(u8, cmd, "#define")) continue; | | |
| 414 | const define = fields.next() orelse return error.Incomplete; | | |
| 415 | const number = fields.next() orelse continue; | | |
| 416 | | 416 | |
| 417 | if (!std.ascii.isDigit(number[0])) continue; | 417 | if (!mem.eql(u8, prefix, "zigsyscall")) continue; |
| 418 | if (!mem.startsWith(u8, define, "__NR")) continue; | | |
| 419 | const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_"); | | |
| 420 | if (mem.eql(u8, name, "arch_specific_syscall")) continue; | | |
| 421 | if (mem.eql(u8, name, "syscalls")) break :loop; | | |
| 422 | | 418 | |
| 423 | const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name; | 419 | const sys_name = fields.next() orelse return error.Incomplete; |
| 424 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number }); | 420 | const value = fields.rest(); |
| | 421 | const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..]; |
| | 422 | const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name; |
| | 423 | |
| | 424 | try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value }); |
| 425 | } | 425 | } |
| 426 | | 426 | |
| 427 | try writer.writeAll( | 427 | try writer.writeAll("};\n\n"); |
| 428 | \\ | | |
| 429 | \\ riscv_flush_icache = arch_specific_syscall + 15, | | |
| 430 | \\ riscv_hwprobe = arch_specific_syscall + 14, | | |
| 431 | \\}; | | |
| 432 | \\ | | |
| 433 | ); | | |
| 434 | } | 428 | } |
| 435 | { | 429 | { |
| 436 | try writer.writeAll( | 430 | try writer.writeAll( |