diff --git a/git.zig b/git.zig index d2f24bf04f8856b8a8faaa304681e57870e553ea..dbd37411fe9d5dc137d0e305661adbefa4386260 100644 --- a/git.zig +++ b/git.zig @@ -602,6 +602,17 @@ pub fn parseTreeDiff(alloc: std.mem.Allocator, input: string) !TreeDiff { }); } + const S = struct { + fn eql(comptime a: u8) fn (u8) bool { + const SS = struct { + fn actual(b: u8) bool { + return a == b; + } + }; + return SS.actual; + } + }; + // diff --git a/notes/all_packages.txt b/notes/all_packages.txt // index c06b41d..e8f91cf 100644 // --- a/notes/all_packages.txt @@ -611,77 +622,99 @@ pub fn parseTreeDiff(alloc: std.mem.Allocator, input: string) !TreeDiff { // freedesktop/xorg/libxmu // ncompress // +freedesktop/xorg/libxpm - std.debug.assert(std.mem.startsWith(u8, lineiter.next() orelse return std.mem.zeroes(TreeDiff), "diff --git")); blk: while (true) { - while (lineiter.next()) |lin| { - if (std.mem.startsWith(u8, lin, "index")) break; - if (std.mem.startsWith(u8, lin, "new file mode")) continue; - if (std.mem.startsWith(u8, lin, "deleted file mode")) continue; - if (std.mem.startsWith(u8, lin, "old mode")) continue; - if (std.mem.startsWith(u8, lin, "new mode")) continue; + const first_line = lineiter.next().?; + std.debug.assert(std.mem.startsWith(u8, first_line, "diff --git")); + const i = diffs.items.len; + try diffs.append(.{ .before_path = overview.items[i].sub_path, .after_path = overview.items[i].sub_path, .content = "" }); + if (extras.matchesAll(u8, overview.items[i].before.blob.id, S.eql('0'))) diffs.items[i].before_path = "/dev/null"; + if (extras.matchesAll(u8, overview.items[i].after.blob.id, S.eql('0'))) diffs.items[i].after_path = "/dev/null"; - std.log.err("{s}", .{lin}); - unreachable; + while (true) { + if (lineiter.index.? >= input.len) { + break :blk; + } + if (lineiter.peek()) |lin| { + if (std.mem.startsWith(u8, lin, "index")) { + lineiter.index.? += lin.len + 1; + break; + } + if (std.mem.startsWith(u8, lin, "new file mode")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "deleted file mode")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "old mode")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "new mode")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "diff --git")) { + continue :blk; + } + std.log.err("{s}", .{lin}); + unreachable; + } } - const before_path_raw = lineiter.next() orelse { - // empty file diff has nothing after 'index' line and this branch handles when its the last item - try diffs.append(.{ - .before_path = overview.items[diffs.items.len].sub_path, - .after_path = overview.items[diffs.items.len].sub_path, - .content = "", - }); - break; - }; - if (std.mem.startsWith(u8, before_path_raw, "Binary files")) { - try diffs.append(.{ - .before_path = overview.items[diffs.items.len].sub_path, - .after_path = overview.items[diffs.items.len].sub_path, - .content = before_path_raw, - }); - _ = lineiter.index orelse break :blk; - std.debug.assert(std.mem.startsWith(u8, lineiter.next().?, "diff --git")); - continue :blk; + var content_start: usize = 0; + + while (true) { + if (lineiter.index.? >= input.len) { + break :blk; + } + if (lineiter.peek()) |lin| { + if (std.mem.startsWith(u8, lin, "--- ")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "+++ ")) { + lineiter.index.? += lin.len + 1; + continue; + } + if (std.mem.startsWith(u8, lin, "@@ ")) { + content_start = lineiter.index.?; + lineiter.index.? += lin.len + 1; + break; + } + if (std.mem.startsWith(u8, lin, "Binary files ")) { + content_start = lineiter.index.?; + lineiter.index.? += lin.len + 1; + break; + } + if (std.mem.startsWith(u8, lin, "diff --git")) { + continue :blk; + } + std.log.err("{s}", .{lin}); + unreachable; + } } - if (std.mem.startsWith(u8, before_path_raw, "diff --git")) { - // empty file in the middle, no diff - try diffs.append(.{ - .before_path = overview.items[diffs.items.len].sub_path, - .after_path = overview.items[diffs.items.len].sub_path, - .content = "", - }); - continue :blk; + if (lineiter.index.? >= input.len) { + diffs.items[diffs.items.len - 1].content = input[content_start..]; + break :blk; } - const before_path = extras.trimPrefixEnsure(before_path_raw, "--- a/") orelse extras.trimPrefixEnsure(before_path_raw, "--- ") orelse @panic(before_path_raw); - - const after_path_raw = lineiter.next().?; - const after_path = extras.trimPrefixEnsure(after_path_raw, "+++ b/") orelse extras.trimPrefixEnsure(after_path_raw, "+++ ") orelse @panic(after_path_raw); - const start_index = lineiter.index.?; + while (true) { + if (lineiter.peek()) |lin| { + if (std.mem.startsWith(u8, lin, "diff --git")) { + const content_end = lineiter.index.? - 1; + diffs.items[diffs.items.len - 1].content = input[content_start..content_end]; + continue :blk; + } + lineiter.index.? += lin.len + 1; - while (lineiter.next()) |lin| { - if (std.mem.startsWith(u8, lin, "diff --git")) { - const end_index = lineiter.index.? - lin.len - 2; - const content = input[start_index..end_index]; - overview.items[diffs.items.len].adds = @intCast(std.mem.count(u8, content, "\n+")); - overview.items[diffs.items.len].subs = @intCast(std.mem.count(u8, content, "\n-")); - try diffs.append(.{ - .before_path = before_path, - .after_path = after_path, - .content = content, - }); - continue :blk; + if (lineiter.index.? >= input.len) { + diffs.items[diffs.items.len - 1].content = input[content_start..]; + break :blk; + } } } - const content = input[start_index..]; - overview.items[diffs.items.len].adds = @intCast(std.mem.count(u8, content, "\n+")); - overview.items[diffs.items.len].subs = @intCast(std.mem.count(u8, content, "\n-")); - try diffs.append(.{ - .before_path = before_path, - .after_path = after_path, - .content = content, - }); - break :blk; } return TreeDiff{ diff --git a/test.zig b/test.zig index 766bd53fa182b3604ff16e8f12c79808193d2a4d..ace270801cd0168cb12f52303a20ca442d11074a 100644 --- a/test.zig +++ b/test.zig @@ -189,3 +189,58 @@ test { const t = try git.parseTreeDiff(alloc, try git.getTreeDiff(alloc, git_dir, .{ .id = "a542da41f1f0c59fdd0e1527cf5ff9de3f6a0c8e" }, .{ .id = "c39f57f6bb01664a7146ddbfc3debe76ec135f44" })); _ = t; // TODO: test fields when we upgrade to 0.14 and have decl literals } + +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-9feb6b667c77c187f547deaf10cd1f04e92fe192")); // magnolia-desktop +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-f2ccd4d1333aad1175550daf616b061388e1864f")); // magnolia-desktop +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-47ed809ce10bdfa99351c72935467c9afae47e36")); // magnolia-desktop +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-15700f9e1c919a3f0c492415d982a09f5e8122cd")); // magnolia-desktop +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-8480815a00f341a9058a26bf86f34368184615d6")); // magnolia-desktop +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-c37d23f45ae6bd0db6b072180d7b84566c7dc8a2")); // zig +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-f58200e3f2967a06f343c9fc9dcae9de18def92a")); // zig +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-d9165aacce3629d503f87cd2c3f612629127641b")); // zig +} +test { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + const alloc = arena.allocator(); + _ = try git.parseTreeDiff(alloc, @embedFile("./testdata/diff-1f7390f3999e80f775dbc0e62f1dcb071c3bed77")); // zig +} diff --git a/testdata/diff-15700f9e1c919a3f0c492415d982a09f5e8122cd b/testdata/diff-15700f9e1c919a3f0c492415d982a09f5e8122cd new file mode 100644 index 0000000000000000000000000000000000000000..3587818012a089ee5430e63afc52e491dcf07b63 --- /dev/null +++ b/testdata/diff-15700f9e1c919a3f0c492415d982a09f5e8122cd @@ -0,0 +1,5 @@ +:100644 100644 1e5a5a99eb7fe12e6ea2f48fb2ff3e8de186efa0 8aff424ddd2f434448b73c0bf62dca382e783be7 M test/images/demo-border.png + +diff --git a/test/images/demo-border.png b/test/images/demo-border.png +index 1e5a5a9..8aff424 100644 +Binary files a/test/images/demo-border.png and b/test/images/demo-border.png differ diff --git a/testdata/diff-1f7390f3999e80f775dbc0e62f1dcb071c3bed77 b/testdata/diff-1f7390f3999e80f775dbc0e62f1dcb071c3bed77 new file mode 100644 index 0000000000000000000000000000000000000000..925cf0ca78756aed631dd9108205fa310b2f76cd --- /dev/null +++ b/testdata/diff-1f7390f3999e80f775dbc0e62f1dcb071c3bed77 @@ -0,0 +1,96 @@ +:100644 100644 e09b8f18abe0652043301349ece259daec0c6241 8f265f9eb61ae03e0b5ab80545fa1ce9aab961aa M src/Compilation.zig +:100644 100644 af972ccb8665085991070de3235a6da537423dc6 81eb1b00428e9e2c3ef5fdf8b532255ed2e66867 M test/standalone.zig +:000000 100644 0000000000000000000000000000000000000000 f5e07d8903268bec8527dd555c7c6955af5ff879 A test/standalone/issue_13970/build.zig +:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A test/standalone/issue_13970/empty.zig +:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A test/standalone/issue_13970/src/empty.zig +:000000 100644 0000000000000000000000000000000000000000 d71320d46a61a74ccc3e5908ab46c4d0a1fea69a A test/standalone/issue_13970/src/main.zig +:000000 100644 0000000000000000000000000000000000000000 4f6037b38dab0c9b800046b0477dc64f3c3b55e8 A test/standalone/issue_13970/src/package.zig +:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A test/standalone/issue_13970/test_root/empty.zig + +diff --git a/src/Compilation.zig b/src/Compilation.zig +index e09b8f18ab..8f265f9eb6 100644 +--- a/src/Compilation.zig ++++ b/src/Compilation.zig +@@ -1621,8 +1621,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { + const root_pkg = if (options.is_test) root_pkg: { + // TODO: we currently have two packages named 'root' here, which is weird. This + // should be changed as part of the resolution of #12201 +- const test_pkg = if (options.test_runner_path) |test_runner| +- try Package.create(gpa, "root", null, test_runner) ++ const test_pkg = if (options.test_runner_path) |test_runner| test_pkg: { ++ const test_dir = std.fs.path.dirname(test_runner); ++ const basename = std.fs.path.basename(test_runner); ++ break :test_pkg try Package.create(gpa, "root", test_dir, basename); ++ } + else + try Package.createWithDir( + gpa, +diff --git a/test/standalone.zig b/test/standalone.zig +index af972ccb86..81eb1b0042 100644 +--- a/test/standalone.zig ++++ b/test/standalone.zig +@@ -27,6 +27,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { + cases.add("test/standalone/noreturn_call/inline.zig"); + cases.add("test/standalone/noreturn_call/as_arg.zig"); + cases.addBuildFile("test/standalone/test_runner_path/build.zig", .{ .requires_stage2 = true }); ++ cases.addBuildFile("test/standalone/issue_13970/build.zig", .{}); + cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); + cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); + cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); +diff --git a/test/standalone/issue_13970/build.zig b/test/standalone/issue_13970/build.zig +new file mode 100644 +index 0000000000..f5e07d8903 +--- /dev/null ++++ b/test/standalone/issue_13970/build.zig +@@ -0,0 +1,21 @@ ++const std = @import("std"); ++ ++pub fn build(b: *std.Build) void { ++ const test1 = b.addTest(.{ ++ .root_source_file = .{ .path = "test_root/empty.zig" }, ++ }); ++ const test2 = b.addTest(.{ ++ .root_source_file = .{ .path = "src/empty.zig" }, ++ }); ++ const test3 = b.addTest(.{ ++ .root_source_file = .{ .path = "empty.zig" }, ++ }); ++ test1.setTestRunner("src/main.zig"); ++ test2.setTestRunner("src/main.zig"); ++ test3.setTestRunner("src/main.zig"); ++ ++ const test_step = b.step("test", "Test package path resolution of custom test runner"); ++ test_step.dependOn(&test1.step); ++ test_step.dependOn(&test2.step); ++ test_step.dependOn(&test3.step); ++} +diff --git a/test/standalone/issue_13970/empty.zig b/test/standalone/issue_13970/empty.zig +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/test/standalone/issue_13970/src/empty.zig b/test/standalone/issue_13970/src/empty.zig +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/test/standalone/issue_13970/src/main.zig b/test/standalone/issue_13970/src/main.zig +new file mode 100644 +index 0000000000..d71320d46a +--- /dev/null ++++ b/test/standalone/issue_13970/src/main.zig +@@ -0,0 +1,8 @@ ++const std = @import("std"); ++const package = @import("package.zig"); ++const root = @import("root"); ++const builtin = @import("builtin"); ++ ++pub fn main() !void { ++ _ = package.decl; ++} +diff --git a/test/standalone/issue_13970/src/package.zig b/test/standalone/issue_13970/src/package.zig +new file mode 100644 +index 0000000000..4f6037b38d +--- /dev/null ++++ b/test/standalone/issue_13970/src/package.zig +@@ -0,0 +1 @@ ++pub const decl = 0; +diff --git a/test/standalone/issue_13970/test_root/empty.zig b/test/standalone/issue_13970/test_root/empty.zig +new file mode 100644 +index 0000000000..e69de29bb2 diff --git a/testdata/diff-47ed809ce10bdfa99351c72935467c9afae47e36 b/testdata/diff-47ed809ce10bdfa99351c72935467c9afae47e36 new file mode 100644 index 0000000000000000000000000000000000000000..14ca60f8aee3d1c714280df5952407ec165da549 --- /dev/null +++ b/testdata/diff-47ed809ce10bdfa99351c72935467c9afae47e36 @@ -0,0 +1,2384 @@ +:100644 100644 6fee2fedb0a46b84e4cbb6e32f9ca5af821b2b67 49e0a31d4964dca501ce61740340bf8058821781 M Cozette/.version +:100644 100644 9371252d0bfb5b2ee220f63dbd1431d11abe266a fdbcc86d16227019361b52ab614b3d9667bd48f7 M Cozette/cozette.bdf +:100644 100644 1d2119c3c794f127a5b366d8db1015dcb6c21e1a 83309362d0d4efa1f7c4a70ef66f2c91d1606b97 M src/e/Label.zig +:100644 100644 0110829e4de23a2c4f1ae0e66958dfe9ca0fe9ff c669969722abb19329aca3b91037ecc6ae7965ef M test/images/demo-bdf-cozette.png +:100644 100644 dedbfa87fb441cf6f8aee13537b8654dc18ac38e e0e46496176d0dc5aaa70a4d95837212dd2cf3d7 M test/images/demo-menubar.png +:100644 100644 94df3421d8f57f38e11f8dc592c6eb123f287d23 5d33be25f2c4e5950780859892cb73b6a3c31e23 M test/layout/demo-bdf-cozette.txt +:100644 100644 8885fcc94eca961702dc7e7f7dff2f67328dd3e1 9e2be559f6ca6d5c4e1ce86858587db3a68c5c27 M test/layout/demo-menubar.txt + +diff --git a/Cozette/.version b/Cozette/.version +index 6fee2fe..49e0a31 100644 +--- a/Cozette/.version ++++ b/Cozette/.version +@@ -1 +1 @@ +-1.22.2 ++1.23.1 +diff --git a/Cozette/cozette.bdf b/Cozette/cozette.bdf +index 9371252..fdbcc86 100644 +--- a/Cozette/cozette.bdf ++++ b/Cozette/cozette.bdf +@@ -1,7 +1,7 @@ + STARTFONT 2.1 + FONT -slavfox-Cozette-Medium-R-Normal--13-120-75-75-M-60-ISO10646-1 + SIZE 12 75 75 +-FONTBOUNDINGBOX 17 28 -5 -3 ++FONTBOUNDINGBOX 13 13 -1 -3 + COMMENT "Generated by fontforge, http://fontforge.sourceforge.net" + COMMENT "(c) 2020-2023 Slavfox" + STARTPROPERTIES 40 +@@ -23,7 +23,7 @@ FONTNAME_REGISTRY "" + FONT_NAME "Cozette" + FACE_NAME "Cozette" + COPYRIGHT "(c) 2020-2023 Slavfox" +-FONT_VERSION "1.222" ++FONT_VERSION "1.231" + FONT_ASCENT 10 + FONT_DESCENT 3 + UNDERLINE_POSITION -19 +@@ -46,7 +46,7 @@ FIGURE_WIDTH 6 + AVG_LOWERCASE_WIDTH 60 + AVG_UPPERCASE_WIDTH 60 + ENDPROPERTIES +-CHARS 3062 ++CHARS 3144 + STARTCHAR uni0000 + ENCODING 0 + SWIDTH 500 0 +@@ -10485,120 +10485,108 @@ STARTCHAR Alphatonos + ENCODING 902 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 8 0 0 + BITMAP +-10 +-20 +-00 +-20 +-50 + 50 +-70 +-88 +-88 +-88 ++90 ++28 ++28 ++38 ++44 ++44 ++44 + ENDCHAR + STARTCHAR Epsilontonos + ENCODING 904 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 8 0 0 + BITMAP ++5C ++90 + 10 +-20 +-00 +-F8 +-80 +-F8 +-80 +-80 +-80 +-F8 ++18 ++10 ++10 ++10 ++1C + ENDCHAR + STARTCHAR Etatonos + ENCODING 905 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 9 0 0 + BITMAP +-10 +-20 +-00 +-88 +-88 +-F8 +-88 +-88 +-88 +-88 ++40 ++A4 ++24 ++24 ++3C ++24 ++24 ++24 ++24 + ENDCHAR + STARTCHAR Iotatonos + ENCODING 906 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 3 10 2 0 ++BBX 5 9 0 0 + BITMAP +-20 + 40 +-00 +-E0 +-40 +-40 +-40 +-40 +-40 +-E0 ++B8 ++10 ++10 ++10 ++10 ++10 ++10 ++38 + ENDCHAR + STARTCHAR Omicrontonos + ENCODING 908 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 8 0 0 + BITMAP +-10 +-20 +-00 +-70 +-88 +-88 +-88 +-88 +-88 +-70 ++58 ++A4 ++24 ++24 ++24 ++24 ++24 ++18 + ENDCHAR + STARTCHAR Upsilontonos + ENCODING 910 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 8 0 0 + BITMAP +-10 +-20 +-00 +-88 +-88 +-50 +-20 +-20 +-20 +-20 ++54 ++94 ++14 ++14 ++08 ++08 ++08 ++08 + ENDCHAR + STARTCHAR Omegatonos + ENCODING 911 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 6 8 0 0 + BITMAP +-10 +-20 +-00 +-70 +-88 +-88 +-88 +-D8 +-50 +-D8 ++40 ++B8 ++28 ++44 ++44 ++28 ++28 ++6C + ENDCHAR + STARTCHAR iotadieresistonos + ENCODING 912 +@@ -18145,10 +18133,12 @@ STARTCHAR uni1E66 + ENCODING 7782 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 10 1 0 ++BBX 5 12 1 -2 + BITMAP +-28 +-90 ++20 ++00 ++50 ++20 + 00 + 70 + 88 +@@ -18162,10 +18152,12 @@ STARTCHAR uni1E67 + ENCODING 7783 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 9 1 0 ++BBX 5 11 1 -1 + BITMAP +-28 +-90 ++20 ++00 ++50 ++20 + 00 + 78 + 80 +@@ -19148,10 +19140,10 @@ BBX 5 10 1 0 + BITMAP + 70 + 10 ++20 + 70 + 88 + 88 +-88 + F8 + 88 + 88 +@@ -19161,11 +19153,12 @@ STARTCHAR uni1EA3 + ENCODING 7843 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 9 1 0 ++BBX 5 10 1 0 + BITMAP + 70 + 10 + 20 ++00 + 78 + 88 + 88 +@@ -19194,10 +19187,11 @@ STARTCHAR uni1EA5 + ENCODING 7845 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 6 9 0 0 ++BBX 6 10 0 0 + BITMAP +-44 +-A8 ++04 ++48 ++A0 + 00 + 3C + 44 +@@ -19227,29 +19221,65 @@ STARTCHAR uni1EA7 + ENCODING 7847 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 6 9 0 0 ++BBX 5 10 1 0 + BITMAP +-88 +-54 ++10 ++48 ++A0 + 00 +-3C +-44 +-44 +-44 +-4C +-34 ++78 ++88 ++88 ++88 ++98 ++68 + ENDCHAR +-STARTCHAR uni1EAA +-ENCODING 7850 ++STARTCHAR uni1EA8 ++ENCODING 7848 + SWIDTH 500 0 + DWIDTH 6 0 + BBX 5 12 1 -2 + BITMAP ++70 ++10 ++20 ++50 ++00 ++70 ++88 ++88 ++F8 ++88 ++88 ++88 ++ENDCHAR ++STARTCHAR uni1EA9 ++ENCODING 7849 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 10 1 -1 ++BITMAP ++70 ++10 + 20 + 50 + 00 ++78 ++88 ++88 ++98 ++68 ++ENDCHAR ++STARTCHAR uni1EAA ++ENCODING 7850 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 12 1 -2 ++BITMAP + 68 + B0 ++20 ++50 + 00 + 70 + 88 +@@ -19257,6 +19287,7 @@ B0 + F8 + 88 + 88 ++88 + ENDCHAR + STARTCHAR uni1EAB + ENCODING 7851 +@@ -19536,24 +19567,25 @@ BBX 5 10 1 0 + BITMAP + 70 + 10 ++20 + F8 + 80 + 80 + F0 + 80 + 80 +-80 + F8 + ENDCHAR + STARTCHAR uni1EBB + ENCODING 7867 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 9 1 0 ++BBX 5 10 1 0 + BITMAP + 70 + 10 + 20 ++00 + 70 + 88 + F8 +@@ -19660,27 +19692,73 @@ BITMAP + 44 + 38 + ENDCHAR ++STARTCHAR uni1EC2 ++ENCODING 7874 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 12 1 -2 ++BITMAP ++70 ++10 ++20 ++50 ++00 ++F8 ++80 ++80 ++F0 ++80 ++80 ++F8 ++ENDCHAR ++STARTCHAR uni1EC3 ++ENCODING 7875 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 11 1 -1 ++BITMAP ++70 ++10 ++20 ++50 ++00 ++70 ++88 ++F8 ++80 ++88 ++70 ++ENDCHAR + STARTCHAR uni1EC4 + ENCODING 7876 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 8 1 0 ++BBX 5 12 1 -2 + BITMAP ++68 ++B0 ++20 ++50 ++00 + F8 + 80 + 80 + F0 + 80 + 80 +-80 + F8 + ENDCHAR + STARTCHAR uni1EC5 + ENCODING 7877 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 6 1 0 ++BBX 5 11 1 -1 + BITMAP ++68 ++B0 ++20 ++50 ++00 + 70 + 88 + F8 +@@ -19833,24 +19911,25 @@ BBX 5 10 1 0 + BITMAP + 70 + 10 ++20 + 70 + 88 + 88 + 88 + 88 + 88 +-88 + 70 + ENDCHAR + STARTCHAR uni1ECF + ENCODING 7887 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 5 9 1 0 ++BBX 5 10 1 0 + BITMAP + 70 + 10 + 20 ++00 + 70 + 88 + 88 +@@ -19899,8 +19978,9 @@ SWIDTH 500 0 + DWIDTH 6 0 + BBX 6 12 0 -2 + BITMAP +-88 +-54 ++80 ++48 ++14 + 00 + 38 + 44 +@@ -19909,24 +19989,60 @@ BITMAP + 44 + 44 + 44 +-44 + 38 + ENDCHAR + STARTCHAR uni1ED3 + ENCODING 7891 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 6 9 0 0 ++BBX 5 10 1 0 + BITMAP ++10 ++48 ++A0 ++00 ++70 + 88 +-54 ++88 ++88 ++88 ++70 ++ENDCHAR ++STARTCHAR uni1ED4 ++ENCODING 7892 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 12 1 -2 ++BITMAP ++70 ++10 ++20 ++50 + 00 +-38 +-44 +-44 +-44 +-44 +-38 ++70 ++88 ++88 ++88 ++88 ++88 ++70 ++ENDCHAR ++STARTCHAR uni1ED5 ++ENCODING 7893 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 10 1 0 ++BITMAP ++70 ++10 ++20 ++50 ++00 ++70 ++88 ++88 ++88 ++70 + ENDCHAR + STARTCHAR uni1ED6 + ENCODING 7894 +@@ -25668,6 +25784,23 @@ A8 + 08 + 10 + ENDCHAR ++STARTCHAR uni21AF ++ENCODING 8623 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 10 0 0 ++BITMAP ++20 ++20 ++4C ++54 ++A8 ++C8 ++10 ++54 ++38 ++10 ++ENDCHAR + STARTCHAR uni21B0 + ENCODING 8624 + SWIDTH 500 0 +@@ -25788,6 +25921,19 @@ A0 + 90 + 08 + ENDCHAR ++STARTCHAR uni21B9 ++ENCODING 8633 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 0 ++BITMAP ++A4 ++FC ++A4 ++94 ++FC ++94 ++ENDCHAR + STARTCHAR uni21BA + ENCODING 8634 + SWIDTH 500 0 +@@ -26708,6 +26854,66 @@ BITMAP + AA00 + D400 + ENDCHAR ++STARTCHAR therefore ++ENCODING 8756 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 5 1 1 ++BITMAP ++20 ++00 ++00 ++00 ++88 ++ENDCHAR ++STARTCHAR uni2235 ++ENCODING 8757 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 5 1 1 ++BITMAP ++88 ++00 ++00 ++00 ++20 ++ENDCHAR ++STARTCHAR uni2236 ++ENCODING 8758 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 1 5 3 1 ++BITMAP ++80 ++00 ++00 ++00 ++80 ++ENDCHAR ++STARTCHAR uni2237 ++ENCODING 8759 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 5 1 1 ++BITMAP ++88 ++00 ++00 ++00 ++88 ++ENDCHAR ++STARTCHAR uni223A ++ENCODING 8762 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 5 1 1 ++BITMAP ++88 ++00 ++F8 ++00 ++88 ++ENDCHAR + STARTCHAR uni223E + ENCODING 8766 + SWIDTH 500 0 +@@ -26718,6 +26924,19 @@ BITMAP + B4 + 98 + ENDCHAR ++STARTCHAR congruent ++ENCODING 8773 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 6 1 2 ++BITMAP ++68 ++B0 ++00 ++F8 ++00 ++F8 ++ENDCHAR + STARTCHAR approxequal + ENCODING 8776 + SWIDTH 500 0 +@@ -27068,6 +27287,20 @@ F8 + 88 + 70 + ENDCHAR ++STARTCHAR circlemultiply ++ENCODING 8855 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++38 ++44 ++AA ++92 ++AA ++44 ++38 ++ENDCHAR + STARTCHAR uni2298 + ENCODING 8856 + SWIDTH 500 0 +@@ -27080,6 +27313,34 @@ A8 + C8 + 70 + ENDCHAR ++STARTCHAR uni229B ++ENCODING 8859 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++38 ++54 ++BA ++FE ++BA ++54 ++38 ++ENDCHAR ++STARTCHAR uni229C ++ENCODING 8860 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++38 ++44 ++BA ++82 ++BA ++44 ++38 ++ENDCHAR + STARTCHAR uni229D + ENCODING 8861 + SWIDTH 500 0 +@@ -27116,6 +27377,20 @@ F8 + 88 + F8 + ENDCHAR ++STARTCHAR uni22A0 ++ENCODING 8864 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++FE ++C6 ++AA ++92 ++AA ++C6 ++FE ++ENDCHAR + STARTCHAR uni22A1 + ENCODING 8865 + SWIDTH 500 0 +@@ -27546,6 +27821,18 @@ BITMAP + 00 + E0 + ENDCHAR ++STARTCHAR uni2315 ++ENCODING 8981 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 5 1 1 ++BITMAP ++30 ++48 ++48 ++70 ++80 ++ENDCHAR + STARTCHAR uni2318 + ENCODING 8984 + SWIDTH 500 0 +@@ -27669,6 +27956,16 @@ BITMAP + 80 + 80 + ENDCHAR ++STARTCHAR uni2335 ++ENCODING 9013 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 3 1 0 ++BITMAP ++88 ++50 ++20 ++ENDCHAR + STARTCHAR uni2336 + ENCODING 9014 + SWIDTH 500 0 +@@ -27931,6 +28228,23 @@ A8 + 20 + 20 + ENDCHAR ++STARTCHAR uni2358 ++ENCODING 9048 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 10 1 -1 ++BITMAP ++20 ++20 ++00 ++00 ++00 ++00 ++00 ++00 ++00 ++F8 ++ENDCHAR + STARTCHAR uni2359 + ENCODING 9049 + SWIDTH 500 0 +@@ -27946,6 +28260,20 @@ F8 + 00 + F8 + ENDCHAR ++STARTCHAR uni235A ++ENCODING 9050 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 7 1 -1 ++BITMAP ++20 ++50 ++88 ++50 ++20 ++00 ++F8 ++ENDCHAR + STARTCHAR uni235B + ENCODING 9051 + SWIDTH 500 0 +@@ -27959,6 +28287,20 @@ BITMAP + 00 + F8 + ENDCHAR ++STARTCHAR uni235C ++ENCODING 9052 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 5 7 1 -1 ++BITMAP ++70 ++88 ++88 ++88 ++70 ++00 ++F8 ++ENDCHAR + STARTCHAR uni235D + ENCODING 9053 + SWIDTH 500 0 +@@ -28410,6 +28752,19 @@ AA + 54 + 38 + ENDCHAR ++STARTCHAR uni238B ++ENCODING 9099 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 1 ++BITMAP ++E0 ++C8 ++A4 ++14 ++44 ++38 ++ENDCHAR + STARTCHAR uni2395 + ENCODING 9109 + SWIDTH 500 0 +@@ -31549,6 +31904,20 @@ BITMAP + FE + FE + ENDCHAR ++STARTCHAR uni25B3 ++ENCODING 9651 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++10 ++28 ++28 ++44 ++44 ++82 ++FE ++ENDCHAR + STARTCHAR uni25B6 + ENCODING 9654 + SWIDTH 500 0 +@@ -31579,6 +31948,20 @@ FE + 38 + 10 + ENDCHAR ++STARTCHAR uni25BD ++ENCODING 9661 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++FE ++82 ++44 ++44 ++28 ++28 ++10 ++ENDCHAR + STARTCHAR uni25C0 + ENCODING 9664 + SWIDTH 500 0 +@@ -31775,6 +32158,20 @@ FE + 7C + 38 + ENDCHAR ++STARTCHAR uni25EB ++ENCODING 9707 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++FE ++92 ++92 ++92 ++92 ++92 ++FE ++ENDCHAR + STARTCHAR uni25F0 + ENCODING 9712 + SWIDTH 500 0 +@@ -31887,6 +32284,20 @@ BITMAP + 44 + 38 + ENDCHAR ++STARTCHAR uni25FF ++ENCODING 9727 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++02 ++06 ++0A ++12 ++22 ++42 ++FE ++ENDCHAR + STARTCHAR uni2601 + ENCODING 9729 + SWIDTH 500 0 +@@ -37562,6 +37973,18 @@ FC + 08 + 10 + ENDCHAR ++STARTCHAR uni29FB ++ENCODING 10747 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 5 0 1 ++BITMAP ++54 ++54 ++FE ++54 ++54 ++ENDCHAR + STARTCHAR uni2B22 + ENCODING 11042 + SWIDTH 500 0 +@@ -37780,6 +38203,16 @@ BITMAP + 00 + 80 + ENDCHAR ++STARTCHAR uni3002 ++ENCODING 12290 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 3 3 1 -1 ++BITMAP ++40 ++A0 ++40 ++ENDCHAR + STARTCHAR uni33D1 + ENCODING 13265 + SWIDTH 500 0 +@@ -38210,7 +38643,7 @@ STARTCHAR uniE0B8 + ENCODING 57528 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 7 13 0 -3 ++BBX 6 13 0 -3 + BITMAP + 80 + 80 +@@ -38219,12 +38652,12 @@ C0 + E0 + E0 + F0 ++F0 ++F0 + F8 + F8 + FC + FC +-FE +-FE + ENDCHAR + STARTCHAR uniE0B9 + ENCODING 57529 +@@ -38250,21 +38683,21 @@ STARTCHAR uniE0BA + ENCODING 57530 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 7 13 0 -3 ++BBX 6 13 0 -3 + BITMAP +-02 +-02 +-06 +-06 +-0E +-0E +-1E +-3E +-3E +-7E +-7E +-FE +-FE ++04 ++04 ++0C ++0C ++1C ++1C ++3C ++3C ++3C ++7C ++7C ++FC ++FC + ENDCHAR + STARTCHAR uniE0BB + ENCODING 57531 +@@ -38290,15 +38723,15 @@ STARTCHAR uniE0BC + ENCODING 57532 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 7 13 0 -3 ++BBX 6 13 0 -3 + BITMAP +-FE +-FE + FC + FC + F8 + F8 + F0 ++F0 ++E0 + E0 + E0 + C0 +@@ -38330,21 +38763,21 @@ STARTCHAR uniE0BE + ENCODING 57534 + SWIDTH 500 0 + DWIDTH 6 0 +-BBX 7 13 0 -3 ++BBX 6 13 0 -3 + BITMAP +-FE +-FE +-7E +-7E +-3E +-3E +-1E +-0E +-0E +-06 +-06 +-02 +-02 ++FC ++FC ++7C ++7C ++3C ++3C ++1C ++1C ++1C ++0C ++0C ++04 ++04 + ENDCHAR + STARTCHAR uniE0BF + ENCODING 57535 +@@ -38582,13 +39015,26 @@ F4 + F4 + FC + ENDCHAR ++STARTCHAR uniE5FA ++ENCODING 58874 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 1 ++BITMAP ++F8 ++FC ++84 ++94 ++94 ++FC ++ENDCHAR + STARTCHAR uniE5FB + ENCODING 58875 + SWIDTH 500 0 + DWIDTH 6 0 + BBX 5 5 1 1 + BITMAP +-E0 ++F0 + D8 + A8 + D8 +@@ -38600,11 +39046,24 @@ SWIDTH 500 0 + DWIDTH 6 0 + BBX 5 5 1 1 + BITMAP +-E0 +-D8 ++F0 + A8 + D8 ++A8 ++F8 ++ENDCHAR ++STARTCHAR uniE5FD ++ENCODING 58877 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 1 ++BITMAP + F8 ++B4 ++84 ++B4 ++CC ++FC + ENDCHAR + STARTCHAR uniE5FE + ENCODING 58878 +@@ -39295,6 +39754,23 @@ FC + BC + 78 + ENDCHAR ++STARTCHAR uniE634 ++ENCODING 58932 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 10 0 0 ++BITMAP ++FE ++FC ++F8 ++F0 ++E0 ++E0 ++F0 ++F8 ++FC ++FE ++ENDCHAR + STARTCHAR uniE64E + ENCODING 58958 + SWIDTH 500 0 +@@ -39323,6 +39799,36 @@ BITMAP + 52 + 8C + ENDCHAR ++STARTCHAR uniE697 ++ENCODING 59031 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 6 8 0 -1 ++BITMAP ++18 ++64 ++80 ++98 ++64 ++04 ++98 ++60 ++ENDCHAR ++STARTCHAR uniE6A9 ++ENCODING 59049 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 8 0 -1 ++BITMAP ++02 ++DE ++8C ++9A ++B2 ++62 ++F6 ++80 ++ENDCHAR + STARTCHAR uniE702 + ENCODING 59138 + SWIDTH 461 0 +@@ -39891,6 +40397,20 @@ BITMAP + 40 + 80 + ENDCHAR ++STARTCHAR uniE764 ++ENCODING 59236 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++CE ++BA ++64 ++D6 ++64 ++BA ++CE ++ENDCHAR + STARTCHAR uniE768 + ENCODING 59240 + SWIDTH 500 0 +@@ -39932,6 +40452,22 @@ D6 + 78 + 38 + ENDCHAR ++STARTCHAR uniE76D ++ENCODING 59245 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 -1 ++BITMAP ++10 ++7C ++FE ++7C ++92 ++6C ++92 ++6C ++10 ++ENDCHAR + STARTCHAR uniE76E + ENCODING 59246 + SWIDTH 500 0 +@@ -39959,6 +40495,26 @@ B8 + A8 + AC + ENDCHAR ++STARTCHAR uniE779 ++ENCODING 59257 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 4 13 1 -3 ++BITMAP ++60 ++90 ++80 ++B0 ++60 ++00 ++E0 ++90 ++90 ++00 ++90 ++90 ++70 ++ENDCHAR + STARTCHAR uniE77B + ENCODING 59259 + SWIDTH 500 0 +@@ -40001,6 +40557,18 @@ BITMAP + 52 + 8C + ENDCHAR ++STARTCHAR uniE786 ++ENCODING 59270 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 5 0 1 ++BITMAP ++F8 ++54 ++54 ++54 ++FE ++ENDCHAR + STARTCHAR uniE791 + ENCODING 59281 + SWIDTH 500 0 +@@ -40305,6 +40873,21 @@ BITMAP + E4 + 40 + ENDCHAR ++STARTCHAR uniF005 ++ENCODING 61445 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 8 0 0 ++BITMAP ++10 ++10 ++38 ++FE ++7C ++38 ++6C ++44 ++ENDCHAR + STARTCHAR uniF008 + ENCODING 61448 + SWIDTH 461 0 +@@ -40641,6 +41224,20 @@ FF + FF + 81 + ENDCHAR ++STARTCHAR uniF03A ++ENCODING 61498 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++BE ++00 ++BE ++00 ++BE ++00 ++BE ++ENDCHAR + STARTCHAR uniF03D + ENCODING 61501 + SWIDTH 500 0 +@@ -40654,6 +41251,19 @@ FE + F6 + 72 + ENDCHAR ++STARTCHAR uniF03E ++ENCODING 61502 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 6 0 0 ++BITMAP ++FE ++82 ++AA ++8E ++FE ++FE ++ENDCHAR + STARTCHAR uniF040 + ENCODING 61504 + SWIDTH 500 0 +@@ -40911,6 +41521,19 @@ EE + 44 + 38 + ENDCHAR ++STARTCHAR uniF064 ++ENCODING 61540 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 6 0 0 ++BITMAP ++08 ++0C ++7E ++8C ++88 ++80 ++ENDCHAR + STARTCHAR uniF067 + ENCODING 61543 + SWIDTH 500 0 +@@ -41002,6 +41625,21 @@ FE + 60 + C0 + ENDCHAR ++STARTCHAR uniF076 ++ENCODING 61558 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 6 8 0 -1 ++BITMAP ++CC ++CC ++00 ++CC ++CC ++CC ++FC ++78 ++ENDCHAR + STARTCHAR uniF07B + ENCODING 61563 + SWIDTH 461 0 +@@ -41053,6 +41691,22 @@ F0 + 1C + 0C + ENDCHAR ++STARTCHAR uniF085 ++ENCODING 61573 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 -1 ++BITMAP ++04 ++0E ++54 ++F8 ++50 ++F8 ++54 ++0E ++04 ++ENDCHAR + STARTCHAR uniF09C + ENCODING 61596 + SWIDTH 461 0 +@@ -41239,6 +41893,20 @@ BITMAP + FE + 10 + ENDCHAR ++STARTCHAR uniF0F4 ++ENCODING 61684 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 8 7 0 -1 ++BITMAP ++7E ++7D ++7D ++7E ++7C ++00 ++FE ++ENDCHAR + STARTCHAR uniF0FD + ENCODING 61693 + SWIDTH 461 0 +@@ -41320,6 +41988,18 @@ BE + C2 + FC + ENDCHAR ++STARTCHAR uniF11C ++ENCODING 61724 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 5 0 1 ++BITMAP ++FE ++82 ++FE ++8A ++FE ++ENDCHAR + STARTCHAR uniF120 + ENCODING 61728 + SWIDTH 500 0 +@@ -41408,6 +42088,21 @@ FE + 82 + FE + ENDCHAR ++STARTCHAR uniF13B ++ENCODING 61755 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 8 0 0 ++BITMAP ++FE ++82 ++BE ++82 ++FA ++82 ++7C ++10 ++ENDCHAR + STARTCHAR uniF13E + ENCODING 61758 + SWIDTH 500 0 +@@ -41632,6 +42327,20 @@ EE + 7C + 82 + ENDCHAR ++STARTCHAR uniF18D ++ENCODING 61837 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 6 7 0 0 ++BITMAP ++FC ++00 ++FC ++00 ++FC ++08 ++10 ++ENDCHAR + STARTCHAR uniF198 + ENCODING 61848 + SWIDTH 500 0 +@@ -41901,6 +42610,22 @@ FC + B4 + FC + ENDCHAR ++STARTCHAR uniF1FA ++ENCODING 61946 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 0 ++BITMAP ++38 ++44 ++82 ++BA ++AA ++BC ++80 ++42 ++3C ++ENDCHAR + STARTCHAR uniF1FE + ENCODING 61950 + SWIDTH 500 0 +@@ -41956,6 +42681,24 @@ FE + 38 + 10 + ENDCHAR ++STARTCHAR uniF233 ++ENCODING 62003 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 11 0 -2 ++BITMAP ++FE ++8A ++FE ++00 ++FE ++8A ++FE ++00 ++FE ++8A ++FE ++ENDCHAR + STARTCHAR uniF240 + ENCODING 62016 + SWIDTH 500 0 +@@ -42170,6 +42913,21 @@ BITMAP + 86 + 7A + ENDCHAR ++STARTCHAR uniF292 ++ENCODING 62098 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 8 0 0 ++BITMAP ++14 ++14 ++7E ++28 ++28 ++FC ++50 ++50 ++ENDCHAR + STARTCHAR uniF293 + ENCODING 62099 + SWIDTH 500 0 +@@ -42344,6 +43102,22 @@ FC + FC + 78 + ENDCHAR ++STARTCHAR uniF2DC ++ENCODING 62172 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 -1 ++BITMAP ++10 ++38 ++D6 ++D6 ++38 ++D6 ++D6 ++38 ++10 ++ENDCHAR + STARTCHAR uniF300 + ENCODING 62208 + SWIDTH 500 0 +@@ -42372,6 +43146,21 @@ BE + 4C + 38 + ENDCHAR ++STARTCHAR uniF302 ++ENCODING 62210 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 8 0 0 ++BITMAP ++08 ++10 ++7C ++F8 ++F8 ++F8 ++7C ++6C ++ENDCHAR + STARTCHAR uniF303 + ENCODING 62211 + SWIDTH 500 0 +@@ -42771,6 +43560,33 @@ F8 + F8 + F8 + ENDCHAR ++STARTCHAR uniF415 ++ENCODING 62485 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 10 0 0 ++BITMAP ++38 ++44 ++82 ++82 ++82 ++44 ++38 ++44 ++82 ++82 ++ENDCHAR ++STARTCHAR uniF417 ++ENCODING 62487 ++SWIDTH 461 0 ++DWIDTH 6 0 ++BBX 7 3 0 2 ++BITMAP ++38 ++EE ++38 ++ENDCHAR + STARTCHAR uniF423 + ENCODING 62499 + SWIDTH 461 0 +@@ -42966,6 +43782,21 @@ BITMAP + 44 + 38 + ENDCHAR ++STARTCHAR uniF471 ++ENCODING 62577 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 8 0 0 ++BITMAP ++F0 ++98 ++9C ++84 ++D4 ++D4 ++84 ++FC ++ENDCHAR + STARTCHAR uniF475 + ENCODING 62581 + SWIDTH 500 0 +@@ -45663,6 +46494,23 @@ A000 + 07C0 + 0BC0 + ENDCHAR ++STARTCHAR u1F429 ++ENCODING 128041 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 11 10 1 -1 ++BITMAP ++3000 ++5840 ++F860 ++1E60 ++3F80 ++3F80 ++3E40 ++0840 ++0820 ++1860 ++ENDCHAR + STARTCHAR u1F42A + ENCODING 128042 + SWIDTH 922 0 +@@ -45693,6 +46541,23 @@ EF80 + 1040 + 1040 + ENDCHAR ++STARTCHAR u1F42C ++ENCODING 128044 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 9 10 2 -1 ++BITMAP ++0180 ++3F00 ++7F00 ++5F80 ++7F80 ++FF80 ++0780 ++4380 ++2700 ++7C00 ++ENDCHAR + STARTCHAR u1F439 + ENCODING 128057 + SWIDTH 461 0 +@@ -45736,6 +46601,24 @@ FA + 22 + 1C + ENDCHAR ++STARTCHAR u1F469 ++ENCODING 128105 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 11 11 1 -2 ++BITMAP ++1F00 ++3F80 ++73C0 ++E1E0 ++C060 ++D160 ++C060 ++D160 ++CE60 ++E0E0 ++DF60 ++ENDCHAR + STARTCHAR u1F47D + ENCODING 128125 + SWIDTH 922 0 +@@ -45818,6 +46701,23 @@ F700 + 4600 + 0200 + ENDCHAR ++STARTCHAR u1F4A9 ++ENCODING 128169 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 10 10 1 -2 ++BITMAP ++1000 ++1C00 ++1200 ++2100 ++2100 ++5280 ++4080 ++9240 ++8C40 ++7F80 ++ENDCHAR + STARTCHAR u1F4BC + ENCODING 128188 + SWIDTH 922 0 +@@ -45833,6 +46733,23 @@ F780 + FF80 + FF80 + ENDCHAR ++STARTCHAR u1F4C4 ++ENCODING 128196 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 8 10 2 -1 ++BITMAP ++FC ++8A ++89 ++AF ++81 ++BD ++81 ++BD ++81 ++FF ++ENDCHAR + STARTCHAR u1F4D6 + ENCODING 128214 + SWIDTH 922 0 +@@ -45898,6 +46815,24 @@ C2 + 82 + FE + ENDCHAR ++STARTCHAR u1F4E9 ++ENCODING 128233 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 11 11 1 -2 ++BITMAP ++0E00 ++0A00 ++1B00 ++F1E0 ++CA60 ++A4A0 ++9120 ++9B20 ++A4A0 ++C060 ++FFE0 ++ENDCHAR + STARTCHAR u1F50B + ENCODING 128267 + SWIDTH 500 0 +@@ -45996,6 +46931,24 @@ F800 + 0180 + 00C0 + ENDCHAR ++STARTCHAR u1F52C ++ENCODING 128300 ++SWIDTH 922 0 ++DWIDTH 12 0 ++BBX 10 11 1 -2 ++BITMAP ++0080 ++01C0 ++0780 ++0F00 ++1F00 ++8E80 ++4480 ++2080 ++1100 ++3F80 ++7FC0 ++ENDCHAR + STARTCHAR u1F52E + ENCODING 128302 + SWIDTH 500 0 +@@ -46049,69 +47002,37 @@ STARTCHAR u1F60A + ENCODING 128522 + SWIDTH 922 0 + DWIDTH 12 0 +-BBX 17 27 -5 -2 +-BITMAP +-800000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-007C00 +-008200 +-010100 +-024480 +-02AA80 +-020080 +-020080 +-024480 +-013900 +-008200 +-007C00 ++BBX 11 11 1 -2 ++BITMAP ++1F00 ++2080 ++4040 ++9120 ++AAA0 ++8020 ++8020 ++9120 ++4E40 ++2080 ++1F00 + ENDCHAR + STARTCHAR u1F60E + ENCODING 128526 + SWIDTH 922 0 + DWIDTH 12 0 +-BBX 17 27 -5 -2 +-BITMAP +-800000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-000000 +-007C00 +-008200 +-010100 +-03FF80 +-03EF80 +-02EE80 +-020080 +-024480 +-013900 +-008200 +-007C00 ++BBX 11 11 1 -2 ++BITMAP ++1F00 ++2080 ++4040 ++FFE0 ++FBE0 ++BBA0 ++8020 ++9120 ++4E40 ++2080 ++1F00 + ENDCHAR + STARTCHAR u1F680 + ENCODING 128640 +@@ -46233,6 +47154,91 @@ BFA0 + 1B00 + 0E00 + ENDCHAR ++STARTCHAR uF0002 ++ENCODING 983042 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 10 0 -1 ++BITMAP ++44 ++82 ++AA ++BA ++AA ++82 ++54 ++10 ++FE ++38 ++ENDCHAR ++STARTCHAR uF006F ++ENCODING 983151 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++38 ++44 ++82 ++92 ++C2 ++84 ++38 ++ENDCHAR ++STARTCHAR uF0172 ++ENCODING 983410 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 9 0 -1 ++BITMAP ++48 ++48 ++84 ++84 ++84 ++84 ++84 ++48 ++48 ++ENDCHAR ++STARTCHAR uF01A8 ++ENCODING 983464 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 8 5 0 0 ++BITMAP ++E4 ++0A ++51 ++0A ++24 ++ENDCHAR ++STARTCHAR uF01F0 ++ENCODING 983536 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 6 0 0 ++BITMAP ++FE ++C6 ++AA ++92 ++82 ++FE ++ENDCHAR ++STARTCHAR uF0232 ++ENCODING 983602 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 0 ++BITMAP ++FC ++78 ++30 ++30 ++30 ++10 ++ENDCHAR + STARTCHAR uF02D1 + ENCODING 983761 + SWIDTH 500 0 +@@ -46259,4 +47265,170 @@ EE + 28 + 10 + ENDCHAR ++STARTCHAR uF0306 ++ENCODING 983814 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 3 0 2 ++BITMAP ++E0 ++BE ++E4 ++ENDCHAR ++STARTCHAR uF031B ++ENCODING 983835 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 -1 ++BITMAP ++70 ++80 ++94 ++BE ++94 ++BE ++94 ++80 ++70 ++ENDCHAR ++STARTCHAR uF0320 ++ENCODING 983840 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++38 ++18 ++FA ++C6 ++BE ++30 ++38 ++ENDCHAR ++STARTCHAR uF0411 ++ENCODING 984081 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 -2 ++BITMAP ++FE ++00 ++FE ++00 ++E8 ++0C ++EE ++0C ++08 ++ENDCHAR ++STARTCHAR uF048D ++ENCODING 984205 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 10 0 -1 ++BITMAP ++FE ++AE ++FE ++00 ++FE ++AE ++FE ++10 ++FE ++38 ++ENDCHAR ++STARTCHAR uF05C6 ++ENCODING 984518 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 6 0 0 ++BITMAP ++CC ++FC ++48 ++48 ++FC ++CC ++ENDCHAR ++STARTCHAR uF0645 ++ENCODING 984645 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 6 8 0 -1 ++BITMAP ++C0 ++C0 ++00 ++8C ++EC ++80 ++EC ++0C ++ENDCHAR ++STARTCHAR uF06A9 ++ENCODING 984745 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++10 ++38 ++10 ++38 ++7C ++D6 ++7C ++ENDCHAR ++STARTCHAR uF072B ++ENCODING 984875 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 9 0 0 ++BITMAP ++10 ++38 ++7C ++BA ++D6 ++EE ++6C ++28 ++10 ++ENDCHAR ++STARTCHAR uF07D4 ++ENCODING 985044 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 6 0 1 ++BITMAP ++78 ++C4 ++8E ++CA ++7C ++0A ++ENDCHAR ++STARTCHAR uF0844 ++ENCODING 985156 ++SWIDTH 500 0 ++DWIDTH 6 0 ++BBX 7 7 0 0 ++BITMAP ++AA ++AA ++54 ++54 ++28 ++28 ++10 ++ENDCHAR ++STARTCHAR uF1417 ++ENCODING 988183 ++SWIDTH 461 0 ++DWIDTH 0 0 ++BBX 1 1 0 0 ++BITMAP ++00 ++ENDCHAR + ENDFONT +diff --git a/src/e/Label.zig b/src/e/Label.zig +index 1d2119c..8330936 100644 +--- a/src/e/Label.zig ++++ b/src/e/Label.zig +@@ -113,7 +113,7 @@ pub fn handleMessage(app: *root.App, ele: mag.Element, msg: mag.Message, extra: + } + }, + .get_height => { +- if (font == .bdf) return extras.safeAdd(@as(u32, 12), -font.bdf.bbox[3]); ++ if (font == .bdf) return font.bdf.bbox[1]; + return self.size; + }, + .enter => {}, +diff --git a/test/images/demo-bdf-cozette.png b/test/images/demo-bdf-cozette.png +index 0110829..c669969 100644 +Binary files a/test/images/demo-bdf-cozette.png and b/test/images/demo-bdf-cozette.png differ +diff --git a/test/images/demo-menubar.png b/test/images/demo-menubar.png +index dedbfa8..e0e4649 100644 +Binary files a/test/images/demo-menubar.png and b/test/images/demo-menubar.png differ +diff --git a/test/layout/demo-bdf-cozette.txt b/test/layout/demo-bdf-cozette.txt +index 94df342..5d33be2 100644 +--- a/test/layout/demo-bdf-cozette.txt ++++ b/test/layout/demo-bdf-cozette.txt +@@ -1,13 +1,13 @@ + 0 e.Panel @ [0,800,0,600] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,800,0,600] bg_color=#cccccc + 1 e.Box @ [325,475,0,50] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[325,475,0,50] bg_color=null +- 2 e.Label @ [325,475,50,65] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[325,475,50,65] bg_color=null +- 3 e.Label @ [169,631,65,80] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[169,631,65,80] bg_color=null +- 4 e.Label @ [343,457,80,95] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[343,457,80,95] bg_color=null +- 5 e.Label @ [268,532,95,110] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[268,532,95,110] bg_color=null +- 6 e.Label @ [223,577,110,125] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[223,577,110,125] bg_color=null +- 7 e.Label @ [352,448,125,140] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,125,140] bg_color=null +- 8 e.Label @ [352,448,140,155] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,140,155] bg_color=null +- 9 e.Label @ [352,448,155,170] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,155,170] bg_color=null +- 10 e.Label @ [352,448,170,185] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,170,185] bg_color=null +- 11 e.Label @ [352,448,185,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,185,200] bg_color=null +- 12 e.Label @ [352,448,200,215] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,200,215] bg_color=null ++ 2 e.Label @ [325,475,50,63] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[325,475,50,63] bg_color=null ++ 3 e.Label @ [169,631,63,76] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[169,631,63,76] bg_color=null ++ 4 e.Label @ [343,457,76,89] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[343,457,76,89] bg_color=null ++ 5 e.Label @ [268,532,89,102] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[268,532,89,102] bg_color=null ++ 6 e.Label @ [223,577,102,115] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[223,577,102,115] bg_color=null ++ 7 e.Label @ [352,448,115,128] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,115,128] bg_color=null ++ 8 e.Label @ [352,448,128,141] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,128,141] bg_color=null ++ 9 e.Label @ [352,448,141,154] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,141,154] bg_color=null ++ 10 e.Label @ [352,448,154,167] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,154,167] bg_color=null ++ 11 e.Label @ [352,448,167,180] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,167,180] bg_color=null ++ 12 e.Label @ [352,448,180,193] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[352,448,180,193] bg_color=null +diff --git a/test/layout/demo-menubar.txt b/test/layout/demo-menubar.txt +index 8885fcc..9e2be55 100644 +--- a/test/layout/demo-menubar.txt ++++ b/test/layout/demo-menubar.txt +@@ -1,24 +1,24 @@ + 23 menubar.A @ [0,300,0,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,300,0,200] bg_color=null + 22 e.Panel @ [0,300,0,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,300,0,200] bg_color=null +- 21 e.MenuBar @ [0,300,0,26] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,300,0,26] bg_color=null +- 20 e.Panel @ [0,300,0,26] margin=[0,0,0,0] border=[0,0,0,1] padding=[0,0,0,0] bounds=[0,300,0,25] bg_color=#f6f5f4 +- 4 e.Menu @ [0,40,0,25] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,40,0,25] bg_color=null +- 1 e.Panel @ [0,40,0,25] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[8,32,5,20] bg_color=null +- 0 e.Label @ [8,32,5,20] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[8,32,5,20] bg_color=null +- 3 e.Panel @ [0,100,25,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,100,25,200] bg_color=null +- 2 e.Panel @ [0,100,25,35] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[1,99,30,30] bg_color=#f6f5f4 +- 9 e.Menu @ [40,80,0,25] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[40,80,0,25] bg_color=null +- 6 e.Panel @ [40,80,0,25] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[48,72,5,20] bg_color=null +- 5 e.Label @ [48,72,5,20] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[48,72,5,20] bg_color=null +- 8 e.Panel @ [40,140,25,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[40,140,25,200] bg_color=null +- 7 e.Panel @ [40,140,25,35] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[41,139,30,30] bg_color=#f6f5f4 +- 14 e.Menu @ [80,120,0,25] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[80,120,0,25] bg_color=null +- 11 e.Panel @ [80,120,0,25] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[88,112,5,20] bg_color=null +- 10 e.Label @ [88,112,5,20] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[88,112,5,20] bg_color=null +- 13 e.Panel @ [80,180,25,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[80,180,25,200] bg_color=null +- 12 e.Panel @ [80,180,25,35] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[81,179,30,30] bg_color=#f6f5f4 +- 19 e.Menu @ [120,160,0,25] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[120,160,0,25] bg_color=null +- 16 e.Panel @ [120,160,0,25] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[128,152,5,20] bg_color=null +- 15 e.Label @ [128,152,5,20] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[128,152,5,20] bg_color=null +- 18 e.Panel @ [120,220,25,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[120,220,25,200] bg_color=null +- 17 e.Panel @ [120,220,25,35] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[121,219,30,30] bg_color=#f6f5f4 ++ 21 e.MenuBar @ [0,300,0,24] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,300,0,24] bg_color=null ++ 20 e.Panel @ [0,300,0,24] margin=[0,0,0,0] border=[0,0,0,1] padding=[0,0,0,0] bounds=[0,300,0,23] bg_color=#f6f5f4 ++ 4 e.Menu @ [0,40,0,23] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,40,0,23] bg_color=null ++ 1 e.Panel @ [0,40,0,23] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[8,32,5,18] bg_color=null ++ 0 e.Label @ [8,32,5,18] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[8,32,5,18] bg_color=null ++ 3 e.Panel @ [0,100,23,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[0,100,23,200] bg_color=null ++ 2 e.Panel @ [0,100,23,33] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[1,99,28,28] bg_color=#f6f5f4 ++ 9 e.Menu @ [40,80,0,23] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[40,80,0,23] bg_color=null ++ 6 e.Panel @ [40,80,0,23] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[48,72,5,18] bg_color=null ++ 5 e.Label @ [48,72,5,18] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[48,72,5,18] bg_color=null ++ 8 e.Panel @ [40,140,23,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[40,140,23,200] bg_color=null ++ 7 e.Panel @ [40,140,23,33] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[41,139,28,28] bg_color=#f6f5f4 ++ 14 e.Menu @ [80,120,0,23] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[80,120,0,23] bg_color=null ++ 11 e.Panel @ [80,120,0,23] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[88,112,5,18] bg_color=null ++ 10 e.Label @ [88,112,5,18] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[88,112,5,18] bg_color=null ++ 13 e.Panel @ [80,180,23,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[80,180,23,200] bg_color=null ++ 12 e.Panel @ [80,180,23,33] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[81,179,28,28] bg_color=#f6f5f4 ++ 19 e.Menu @ [120,160,0,23] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[120,160,0,23] bg_color=null ++ 16 e.Panel @ [120,160,0,23] margin=[0,0,0,0] border=[0,0,3,3] padding=[8,8,2,2] bounds=[128,152,5,18] bg_color=null ++ 15 e.Label @ [128,152,5,18] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[128,152,5,18] bg_color=null ++ 18 e.Panel @ [120,220,23,200] margin=[0,0,0,0] border=[0,0,0,0] padding=[0,0,0,0] bounds=[120,220,23,200] bg_color=null ++ 17 e.Panel @ [120,220,23,33] margin=[0,0,0,0] border=[1,1,1,1] padding=[0,0,4,4] bounds=[121,219,28,28] bg_color=#f6f5f4 diff --git a/testdata/diff-8480815a00f341a9058a26bf86f34368184615d6 b/testdata/diff-8480815a00f341a9058a26bf86f34368184615d6 new file mode 100644 index 0000000000000000000000000000000000000000..6b7c57d01b201833af27323fe2aefd45f2002a47 --- /dev/null +++ b/testdata/diff-8480815a00f341a9058a26bf86f34368184615d6 @@ -0,0 +1,33 @@ +:100644 100644 fef6239d0dfd8daafcfd62a17a137e3da9c2d8dd 9f1d9c9b30f503c1a0731f31c8b6892990b65746 M notes/potential apps.txt + +diff --git a/notes/potential apps.txt b/notes/potential apps.txt +index fef6239..9f1d9c9 100644 +--- a/notes/potential apps.txt ++++ b/notes/potential apps.txt +@@ -116,10 +116,18 @@ system utilities + + developer tools + code debugger ++ program profiler ++ alt for renderdoc https://renderdoc.org/ ++ strace gui ++ valgrind gui ++ alt for https://unicode.link/ ++ alt for https://www.wireshark.org/ ++ + svg path explorer + font explorer + sqlite client + postgresql client ++ font maker + + file formats + .psd https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ +@@ -179,3 +187,7 @@ linux distro stuff + wm/bar (we like i3) + screensaver + lockscreen ++ ++handle printing ++ ++handle faxing diff --git a/testdata/diff-9feb6b667c77c187f547deaf10cd1f04e92fe192 b/testdata/diff-9feb6b667c77c187f547deaf10cd1f04e92fe192 new file mode 100644 index 0000000000000000000000000000000000000000..b71fbddee5028f1dd3beb22e174cde7bd3eab8b5 --- /dev/null +++ b/testdata/diff-9feb6b667c77c187f547deaf10cd1f04e92fe192 @@ -0,0 +1,196 @@ +:100644 100644 d49352c9c20cea1ca91beb90979e8d4a1670a01c 5b519a35eb2ea8842573d82f13ab965ca8724b69 M README.md +:100644 100644 b301658a8bea70ef336e7f426c284017b6f48465 9c975af044191b87fcd54769c29bf94a22f9123f M apps/Calculator/main.zig +:100644 100644 f6990eea8b8db29a2ab4113d5d3d422454108ec9 90c6e9a60ff739b96f9ba78b65e2c6584cbaa2fe M apps/ImageViewer/main.zig +:100644 100644 30850c59cddc295497c3939b6076bb09c8d36de7 cf55d583ce85b9e026f94f6eabcf1490a450c9fb M build.zig +:100644 100644 731b5b15f743db7aa587fc5f8b8d98d16df106d8 c2d6942489853658391c971988c85317e0da07d2 M demos/7guis/1counter.zig +:100644 100644 c6121d73b6adfe4e03889291ca323d0842187b22 da65c9ce2b7ba832d1b748e2ea0bbb6f363f94f4 M demos/logl/hello-window.zig +:100644 100644 49c152d836ca8470b153957ba90a4376aa2bbbf0 13704daad693cc0054559ff70f5f3e242ecad273 M src/main.zig +:100644 100644 55ee6c75e23a130d4cca5825925c92438e3c3865 8044e605443388554cecc57cf4fb2b5c4f41987e M zigmod.lock +:100644 100644 1ce887547a4c312badf1429dc2afbfb2c5647776 e24cb55669911d7502b4e7e9add98995586834cf M zigmod.yml + +diff --git a/README.md b/README.md +index d49352c..5b519a3 100644 +--- a/README.md ++++ b/README.md +@@ -21,7 +21,7 @@ Source-Available, All rights reserved. (c) 2023 Meghan Denny + Will likely be MPL-2.0 in the future. + + ## Credits +-- Zig 0.13.0 ++- Zig 0.14.1 + - See [`zigmod.yml`](./zigmod.yml) and [`zigmod.lock`](./zigmod.lock) + + ## Building +diff --git a/apps/Calculator/main.zig b/apps/Calculator/main.zig +index b301658..9c975af 100644 +--- a/apps/Calculator/main.zig ++++ b/apps/Calculator/main.zig +@@ -201,7 +201,7 @@ pub const SquareButton = struct { + fn onclickNum(comptime n: f64) mag.e.Button.OnClickFn { + const S = struct { + fn onclick(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + if (b.active_operator) |_| { + b.active_num = .two; + +@@ -231,7 +231,7 @@ fn onclickNum(comptime n: f64) mag.e.Button.OnClickFn { + } + + fn onclickDot(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + b.dot = 0; + b.update(app); + return 1; +@@ -240,7 +240,7 @@ fn onclickDot(app: *App, state: ?*anyopaque) u32 { + fn onclickOp(comptime o: BadTextbox.Op) mag.e.Button.OnClickFn { + const S = struct { + fn onclick(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + toggleOpButton(app, b, o); + b.active_operator = o; + b.dot = null; +@@ -281,7 +281,7 @@ fn toggleOpButtonOnly(app: *const App, op: BadTextbox.Op, to: enum { on, off }) + } + + fn onclickNeg(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + switch (b.active_num) { + .one => b.num1 *= -1, + .two => b.num2 *= -1, +@@ -291,7 +291,7 @@ fn onclickNeg(app: *App, state: ?*anyopaque) u32 { + } + + fn onclickRoot2(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + switch (b.active_num) { + .one => b.num1 = @sqrt(b.num1), + .two => b.num2 = @sqrt(b.num2), +@@ -301,7 +301,7 @@ fn onclickRoot2(app: *App, state: ?*anyopaque) u32 { + } + + fn onclickRoot3(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + switch (b.active_num) { + .one => b.num1 = std.math.cbrt(b.num1), + .two => b.num2 = std.math.cbrt(b.num2), +@@ -311,7 +311,7 @@ fn onclickRoot3(app: *App, state: ?*anyopaque) u32 { + } + + fn onclickEql(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + if (b.active_num == .one) { + return 0; + } +@@ -338,7 +338,7 @@ fn onclickEql(app: *App, state: ?*anyopaque) u32 { + } + + fn onclickClear(app: *App, state: ?*anyopaque) u32 { +- const b = extras.ptrCast(BadTextbox, state.?); ++ const b: *BadTextbox = @ptrCast(@alignCast(state.?)); + b.active_num = .one; + b.num1 = 0; + b.num2 = 0; +diff --git a/apps/ImageViewer/main.zig b/apps/ImageViewer/main.zig +index f6990ee..90c6e9a 100644 +--- a/apps/ImageViewer/main.zig ++++ b/apps/ImageViewer/main.zig +@@ -16,7 +16,7 @@ pub fn main() !void { + + extras.assertLog(std.os.argv.len == 2, "must pass a file to open as an argument", .{}); + const file_name = std.mem.sliceTo(std.os.argv[1], 0); +- extras.assertLog(file_name.len <= std.fs.MAX_PATH_BYTES, "file argument longer than MAX_PATH_BYTES", .{}); ++ extras.assertLog(file_name.len <= std.fs.max_path_bytes, "file argument longer than max_path_bytes", .{}); + + var app = try App.init(alloc, 300, 200, try std.fmt.allocPrintZ(alloc, "{s} — {s}", .{ file_name, build_options.name })); + defer app.deinit(); +diff --git a/build.zig b/build.zig +index 30850c5..cf55d58 100644 +--- a/build.zig ++++ b/build.zig +@@ -3,6 +3,8 @@ const string = []const u8; + const deps = @import("./deps.zig"); + + pub fn build(b: *std.Build) void { ++ b.reference_trace = 256; ++ + const target = b.standardTargetOptions(.{}); + const mode = b.option(std.builtin.Mode, "mode", "") orelse .Debug; + const doall = b.option(bool, "all", "Build all apps, default only selected steps") orelse false; +diff --git a/demos/7guis/1counter.zig b/demos/7guis/1counter.zig +index 731b5b1..c2d6942 100644 +--- a/demos/7guis/1counter.zig ++++ b/demos/7guis/1counter.zig +@@ -72,7 +72,7 @@ pub const A = struct { + + fn onclick(app: *const App, state: ?*anyopaque) u32 { + _ = app; +- const a = extras.ptrCast(A, state.?); ++ const a: *A = @ptrCast(@alignCast(state.?)); + a.count += 1; + return 1; + } +diff --git a/demos/logl/hello-window.zig b/demos/logl/hello-window.zig +index c6121d7..da65c9c 100644 +--- a/demos/logl/hello-window.zig ++++ b/demos/logl/hello-window.zig +@@ -167,7 +167,7 @@ fn WhitePixel(dpy: *c.Display, scr: c_int) c_ulong { + return ScreenOfDisplay(dpy, scr).*.white_pixel; + } + +-// #define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root) ++// #define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root) + fn RootWindow(dpy: *c.Display, scr: c_int) c.Window { + return ScreenOfDisplay(dpy, scr).*.root; + } +diff --git a/src/main.zig b/src/main.zig +index 49c152d..13704da 100644 +--- a/src/main.zig ++++ b/src/main.zig +@@ -860,7 +860,7 @@ pub fn App2() type { + } + + pub fn get(self: *const Self, element: Element, comptime T: type) *T { +- return extras.ptrCast(T, self.attr(element, .data)); ++ return @ptrCast(@alignCast(self.attr(element, .data))); + } + + pub fn bounds(self: *const Self, element: Element) Rectangle { +diff --git a/zigmod.lock b/zigmod.lock +index 55ee6c7..8044e60 100644 +--- a/zigmod.lock ++++ b/zigmod.lock +@@ -1,8 +1,8 @@ + 2 +-git https://github.com/nektro/zig-color commit-b1df1f0d3561f2ff59ccddacd9b5c8efdaec2cf2 +-git https://github.com/nektro/zig-extras commit-100510135aa7be25b8b465ac32450678de009103 +-git https://github.com/nektro/zig-time commit-b9a93152af3ba73e5f681f73a67f0d676e2ad433 +-git https://github.com/nektro/zig-tracer commit-662774eedca41771f9ebd1ab45cfdc8e4319d4b4 +-git https://github.com/nektro/zig-xml commit-05aeff20237e0ea0556e4ac0f519a278e45b0cfb +-git https://github.com/ziglibs/known-folders commit-aa24df42183ad415d10bc0a33e6238c437fc0f59 ++git https://github.com/nektro/zig-color commit-eaf93f7c177e4bd0d6a258e88998e442cd905a69 ++git https://github.com/nektro/zig-extras commit-cc8fb7cb1654df835a48473d67c001a44d2a6ea9 ++git https://github.com/nektro/zig-time commit-25165db8e626434ab6eae2cff64ba5e72e4fa062 ++git https://github.com/nektro/zig-tracer commit-cc75b7f652c7cd51cbfa6e3c7e8155cd153bb68b ++git https://github.com/nektro/zig-xml commit-fc07c763a98fa7961b65b0a2b95a2d0fa061fafb ++git https://github.com/ziglibs/known-folders commit-ab5cf5feb936fa3b72c95d3ad0c0c67791937ba1 + git https://github.com/zigimg/zigimg commit-d9dbbe22b5f7b5f1f4772169ed93ffeed8e8124d +diff --git a/zigmod.yml b/zigmod.yml +index 1ce8875..e24cb55 100644 +--- a/zigmod.yml ++++ b/zigmod.yml +@@ -1,7 +1,7 @@ + id: l862p8h05u3xp3w5ydtuhks9wtd961ktm8ivzhdkso0ylf1i + name: magnolia + main: src/main.zig +-min_zig_version: 0.13.0 ++min_zig_version: 0.14.1 + + root_dependencies: + - src: git https://github.com/nektro/zig-extras diff --git a/testdata/diff-c37d23f45ae6bd0db6b072180d7b84566c7dc8a2 b/testdata/diff-c37d23f45ae6bd0db6b072180d7b84566c7dc8a2 new file mode 100644 index 0000000000000000000000000000000000000000..2db33d584f2e7958fe09d99f8764c008ecf2af63 --- /dev/null +++ b/testdata/diff-c37d23f45ae6bd0db6b072180d7b84566c7dc8a2 @@ -0,0 +1,5 @@ +:100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D crt.c + +diff --git a/crt.c b/crt.c +deleted file mode 100644 +index e69de29bb2..0000000000 diff --git a/testdata/diff-d9165aacce3629d503f87cd2c3f612629127641b b/testdata/diff-d9165aacce3629d503f87cd2c3f612629127641b new file mode 100644 index 0000000000000000000000000000000000000000..deb5879d55c6de9d00b2b900a6b1a9186b78b989 --- /dev/null +++ b/testdata/diff-d9165aacce3629d503f87cd2c3f612629127641b @@ -0,0 +1,9 @@ +:100644 100755 220aaf12d9f74e95c2ed898a3046d23bc4792369 220aaf12d9f74e95c2ed898a3046d23bc4792369 M ci/aarch64-linux-debug.sh +:100644 100755 69eed679e3c6041d9fff2d591bac7e2fa110debd 69eed679e3c6041d9fff2d591bac7e2fa110debd M ci/aarch64-linux-release.sh + +diff --git a/ci/aarch64-linux-debug.sh b/ci/aarch64-linux-debug.sh +old mode 100644 +new mode 100755 +diff --git a/ci/aarch64-linux-release.sh b/ci/aarch64-linux-release.sh +old mode 100644 +new mode 100755 diff --git a/testdata/diff-f2ccd4d1333aad1175550daf616b061388e1864f b/testdata/diff-f2ccd4d1333aad1175550daf616b061388e1864f new file mode 100644 index 0000000000000000000000000000000000000000..215af12aebc721b68c0738a1f713658961729794 --- /dev/null +++ b/testdata/diff-f2ccd4d1333aad1175550daf616b061388e1864f @@ -0,0 +1,2160 @@ +:000000 100644 0000000000000000000000000000000000000000 e237a22bbc214f03dfa0a99ecd3368eee2bbc22c A src/x11.Keysym.zig +:100644 100644 9b8cbd2d7cee62cdec69e8febc75ff090cefdd8c a0a2cf47cd45489c5630a351b553aaeae5efad87 M src/x11.zig + +diff --git a/src/x11.Keysym.zig b/src/x11.Keysym.zig +new file mode 100644 +index 0000000..e237a22 +--- /dev/null ++++ b/src/x11.Keysym.zig +@@ -0,0 +1,2141 @@ ++/// https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/keysymdef.h ++// Last retrieved at f7176375692e47275e89c3064da4cd3a0f8dd1e7 ++pub const Keysym = enum(c_uint) { ++ XK_VoidSymbol = 0xffffff, // Void symbol ++ ++ XK_BackSpace = 0xff08, // U+0008 BACKSPACE ++ XK_Tab = 0xff09, // U+0009 CHARACTER TABULATION ++ XK_Linefeed = 0xff0a, // U+000A LINE FEED ++ XK_Clear = 0xff0b, // U+000B LINE TABULATION ++ XK_Return = 0xff0d, // U+000D CARRIAGE RETURN ++ XK_Pause = 0xff13, // Pause, hold ++ XK_Scroll_Lock = 0xff14, ++ XK_Sys_Req = 0xff15, ++ XK_Escape = 0xff1b, // U+001B ESCAPE ++ XK_Delete = 0xffff, // U+007F DELETE ++ XK_Multi_key = 0xff20, // Multi-key character compose ++ XK_Codeinput = 0xff37, ++ XK_SingleCandidate = 0xff3c, ++ XK_MultipleCandidate = 0xff3d, ++ XK_PreviousCandidate = 0xff3e, ++ XK_Kanji = 0xff21, // Kanji, Kanji convert ++ XK_Muhenkan = 0xff22, // Cancel Conversion ++ XK_Henkan_Mode = 0xff23, // Start/Stop Conversion ++ // XK_Henkan = 0xff23, // non-deprecated alias for Henkan_Mode ++ XK_Romaji = 0xff24, // to Romaji ++ XK_Hiragana = 0xff25, // to Hiragana ++ XK_Katakana = 0xff26, // to Katakana ++ XK_Hiragana_Katakana = 0xff27, // Hiragana/Katakana toggle ++ XK_Zenkaku = 0xff28, // to Zenkaku ++ XK_Hankaku = 0xff29, // to Hankaku ++ XK_Zenkaku_Hankaku = 0xff2a, // Zenkaku/Hankaku toggle ++ XK_Touroku = 0xff2b, // Add to Dictionary ++ XK_Massyo = 0xff2c, // Delete from Dictionary ++ XK_Kana_Lock = 0xff2d, // Kana Lock ++ XK_Kana_Shift = 0xff2e, // Kana Shift ++ XK_Eisu_Shift = 0xff2f, // Alphanumeric Shift ++ XK_Eisu_toggle = 0xff30, // Alphanumeric toggle ++ // XK_Kanji_Bangou = 0xff37, // Codeinput ++ // XK_Zen_Koho = 0xff3d, // Multiple/All Candidate(s) ++ // XK_Mae_Koho = 0xff3e, // Previous Candidate ++ XK_Home = 0xff50, ++ XK_Left = 0xff51, // Move left, left arrow ++ XK_Up = 0xff52, // Move up, up arrow ++ XK_Right = 0xff53, // Move right, right arrow ++ XK_Down = 0xff54, // Move down, down arrow ++ XK_Prior = 0xff55, // Prior, previous ++ // XK_Page_Up = 0xff55, // deprecated alias for Prior ++ XK_Next = 0xff56, // Next ++ // XK_Page_Down = 0xff56, // deprecated alias for Next ++ XK_End = 0xff57, // EOL ++ XK_Begin = 0xff58, // BOL ++ XK_Select = 0xff60, // Select, mark ++ XK_Print = 0xff61, ++ XK_Execute = 0xff62, // Execute, run, do ++ XK_Insert = 0xff63, // Insert, insert here ++ XK_Undo = 0xff65, ++ XK_Redo = 0xff66, // Redo, again ++ XK_Menu = 0xff67, ++ XK_Find = 0xff68, // Find, search ++ XK_Cancel = 0xff69, // Cancel, stop, abort, exit ++ XK_Help = 0xff6a, // Help ++ XK_Break = 0xff6b, ++ XK_Mode_switch = 0xff7e, // Character set switch ++ // XK_script_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ XK_Num_Lock = 0xff7f, ++ XK_KP_Space = 0xff80, // ++ XK_KP_Tab = 0xff89, // ++ XK_KP_Enter = 0xff8d, // ++ XK_KP_F1 = 0xff91, // PF1, KP_A, ... ++ XK_KP_F2 = 0xff92, ++ XK_KP_F3 = 0xff93, ++ XK_KP_F4 = 0xff94, ++ XK_KP_Home = 0xff95, ++ XK_KP_Left = 0xff96, ++ XK_KP_Up = 0xff97, ++ XK_KP_Right = 0xff98, ++ XK_KP_Down = 0xff99, ++ XK_KP_Prior = 0xff9a, ++ // XK_KP_Page_Up = 0xff9a, // deprecated alias for KP_Prior ++ XK_KP_Next = 0xff9b, ++ // XK_KP_Page_Down = 0xff9b, // deprecated alias for KP_Next ++ XK_KP_End = 0xff9c, ++ XK_KP_Begin = 0xff9d, ++ XK_KP_Insert = 0xff9e, ++ XK_KP_Delete = 0xff9f, ++ XK_KP_Equal = 0xffbd, // ++ XK_KP_Multiply = 0xffaa, // ++ XK_KP_Add = 0xffab, // ++ XK_KP_Separator = 0xffac, // ++ XK_KP_Subtract = 0xffad, // ++ XK_KP_Decimal = 0xffae, // ++ XK_KP_Divide = 0xffaf, // ++ XK_KP_0 = 0xffb0, // ++ XK_KP_1 = 0xffb1, // ++ XK_KP_2 = 0xffb2, // ++ XK_KP_3 = 0xffb3, // ++ XK_KP_4 = 0xffb4, // ++ XK_KP_5 = 0xffb5, // ++ XK_KP_6 = 0xffb6, // ++ XK_KP_7 = 0xffb7, // ++ XK_KP_8 = 0xffb8, // ++ XK_KP_9 = 0xffb9, // ++ XK_F1 = 0xffbe, ++ XK_F2 = 0xffbf, ++ XK_F3 = 0xffc0, ++ XK_F4 = 0xffc1, ++ XK_F5 = 0xffc2, ++ XK_F6 = 0xffc3, ++ XK_F7 = 0xffc4, ++ XK_F8 = 0xffc5, ++ XK_F9 = 0xffc6, ++ XK_F10 = 0xffc7, ++ XK_F11 = 0xffc8, ++ // XK_L1 = 0xffc8, // deprecated alias for F11 ++ XK_F12 = 0xffc9, ++ // XK_L2 = 0xffc9, // deprecated alias for F12 ++ XK_F13 = 0xffca, ++ // XK_L3 = 0xffca, // deprecated alias for F13 ++ XK_F14 = 0xffcb, ++ // XK_L4 = 0xffcb, // deprecated alias for F14 ++ XK_F15 = 0xffcc, ++ // XK_L5 = 0xffcc, // deprecated alias for F15 ++ XK_F16 = 0xffcd, ++ // XK_L6 = 0xffcd, // deprecated alias for F16 ++ XK_F17 = 0xffce, ++ // XK_L7 = 0xffce, // deprecated alias for F17 ++ XK_F18 = 0xffcf, ++ // XK_L8 = 0xffcf, // deprecated alias for F18 ++ XK_F19 = 0xffd0, ++ // XK_L9 = 0xffd0, // deprecated alias for F19 ++ XK_F20 = 0xffd1, ++ // XK_L10 = 0xffd1, // deprecated alias for F20 ++ XK_F21 = 0xffd2, ++ // XK_R1 = 0xffd2, // deprecated alias for F21 ++ XK_F22 = 0xffd3, ++ // XK_R2 = 0xffd3, // deprecated alias for F22 ++ XK_F23 = 0xffd4, ++ // XK_R3 = 0xffd4, // deprecated alias for F23 ++ XK_F24 = 0xffd5, ++ // XK_R4 = 0xffd5, // deprecated alias for F24 ++ XK_F25 = 0xffd6, ++ // XK_R5 = 0xffd6, // deprecated alias for F25 ++ XK_F26 = 0xffd7, ++ // XK_R6 = 0xffd7, // deprecated alias for F26 ++ XK_F27 = 0xffd8, ++ // XK_R7 = 0xffd8, // deprecated alias for F27 ++ XK_F28 = 0xffd9, ++ // XK_R8 = 0xffd9, // deprecated alias for F28 ++ XK_F29 = 0xffda, ++ // XK_R9 = 0xffda, // deprecated alias for F29 ++ XK_F30 = 0xffdb, ++ // XK_R10 = 0xffdb, // deprecated alias for F30 ++ XK_F31 = 0xffdc, ++ // XK_R11 = 0xffdc, // deprecated alias for F31 ++ XK_F32 = 0xffdd, ++ // XK_R12 = 0xffdd, // deprecated alias for F32 ++ XK_F33 = 0xffde, ++ // XK_R13 = 0xffde, // deprecated alias for F33 ++ XK_F34 = 0xffdf, ++ // XK_R14 = 0xffdf, // deprecated alias for F34 ++ XK_F35 = 0xffe0, ++ // XK_R15 = 0xffe0, // deprecated alias for F35 ++ XK_Shift_L = 0xffe1, // Left shift ++ XK_Shift_R = 0xffe2, // Right shift ++ XK_Control_L = 0xffe3, // Left control ++ XK_Control_R = 0xffe4, // Right control ++ XK_Caps_Lock = 0xffe5, // Caps lock ++ XK_Shift_Lock = 0xffe6, // Shift lock ++ XK_Meta_L = 0xffe7, // Left meta ++ XK_Meta_R = 0xffe8, // Right meta ++ XK_Alt_L = 0xffe9, // Left alt ++ XK_Alt_R = 0xffea, // Right alt ++ XK_Super_L = 0xffeb, // Left super ++ XK_Super_R = 0xffec, // Right super ++ XK_Hyper_L = 0xffed, // Left hyper ++ XK_Hyper_R = 0xffee, // Right hyper ++ ++ XK_ISO_Lock = 0xfe01, ++ XK_ISO_Level2_Latch = 0xfe02, ++ XK_ISO_Level3_Shift = 0xfe03, ++ XK_ISO_Level3_Latch = 0xfe04, ++ XK_ISO_Level3_Lock = 0xfe05, ++ XK_ISO_Level5_Shift = 0xfe11, ++ XK_ISO_Level5_Latch = 0xfe12, ++ XK_ISO_Level5_Lock = 0xfe13, ++ // XK_ISO_Group_Shift = 0xff7e, // non-deprecated alias for Mode_switch ++ XK_ISO_Group_Latch = 0xfe06, ++ XK_ISO_Group_Lock = 0xfe07, ++ XK_ISO_Next_Group = 0xfe08, ++ XK_ISO_Next_Group_Lock = 0xfe09, ++ XK_ISO_Prev_Group = 0xfe0a, ++ XK_ISO_Prev_Group_Lock = 0xfe0b, ++ XK_ISO_First_Group = 0xfe0c, ++ XK_ISO_First_Group_Lock = 0xfe0d, ++ XK_ISO_Last_Group = 0xfe0e, ++ XK_ISO_Last_Group_Lock = 0xfe0f, ++ XK_ISO_Left_Tab = 0xfe20, ++ XK_ISO_Move_Line_Up = 0xfe21, ++ XK_ISO_Move_Line_Down = 0xfe22, ++ XK_ISO_Partial_Line_Up = 0xfe23, ++ XK_ISO_Partial_Line_Down = 0xfe24, ++ XK_ISO_Partial_Space_Left = 0xfe25, ++ XK_ISO_Partial_Space_Right = 0xfe26, ++ XK_ISO_Set_Margin_Left = 0xfe27, ++ XK_ISO_Set_Margin_Right = 0xfe28, ++ XK_ISO_Release_Margin_Left = 0xfe29, ++ XK_ISO_Release_Margin_Right = 0xfe2a, ++ XK_ISO_Release_Both_Margins = 0xfe2b, ++ XK_ISO_Fast_Cursor_Left = 0xfe2c, ++ XK_ISO_Fast_Cursor_Right = 0xfe2d, ++ XK_ISO_Fast_Cursor_Up = 0xfe2e, ++ XK_ISO_Fast_Cursor_Down = 0xfe2f, ++ XK_ISO_Continuous_Underline = 0xfe30, ++ XK_ISO_Discontinuous_Underline = 0xfe31, ++ XK_ISO_Emphasize = 0xfe32, ++ XK_ISO_Center_Object = 0xfe33, ++ XK_ISO_Enter = 0xfe34, ++ XK_dead_grave = 0xfe50, ++ XK_dead_acute = 0xfe51, ++ XK_dead_circumflex = 0xfe52, ++ XK_dead_tilde = 0xfe53, ++ // XK_dead_perispomeni = 0xfe53, // non-deprecated alias for dead_tilde ++ XK_dead_macron = 0xfe54, ++ XK_dead_breve = 0xfe55, ++ XK_dead_abovedot = 0xfe56, ++ XK_dead_diaeresis = 0xfe57, ++ XK_dead_abovering = 0xfe58, ++ XK_dead_doubleacute = 0xfe59, ++ XK_dead_caron = 0xfe5a, ++ XK_dead_cedilla = 0xfe5b, ++ XK_dead_ogonek = 0xfe5c, ++ XK_dead_iota = 0xfe5d, ++ XK_dead_voiced_sound = 0xfe5e, ++ XK_dead_semivoiced_sound = 0xfe5f, ++ XK_dead_belowdot = 0xfe60, ++ XK_dead_hook = 0xfe61, ++ XK_dead_horn = 0xfe62, ++ XK_dead_stroke = 0xfe63, ++ XK_dead_abovecomma = 0xfe64, ++ // XK_dead_psili = 0xfe64, // non-deprecated alias for dead_abovecomma ++ XK_dead_abovereversedcomma = 0xfe65, ++ // XK_dead_dasia = 0xfe65, // non-deprecated alias for dead_abovereversedcomma ++ XK_dead_doublegrave = 0xfe66, ++ XK_dead_belowring = 0xfe67, ++ XK_dead_belowmacron = 0xfe68, ++ XK_dead_belowcircumflex = 0xfe69, ++ XK_dead_belowtilde = 0xfe6a, ++ XK_dead_belowbreve = 0xfe6b, ++ XK_dead_belowdiaeresis = 0xfe6c, ++ XK_dead_invertedbreve = 0xfe6d, ++ XK_dead_belowcomma = 0xfe6e, ++ XK_dead_currency = 0xfe6f, ++ XK_dead_lowline = 0xfe90, ++ XK_dead_aboveverticalline = 0xfe91, ++ XK_dead_belowverticalline = 0xfe92, ++ XK_dead_longsolidusoverlay = 0xfe93, ++ XK_dead_a = 0xfe80, ++ XK_dead_A = 0xfe81, ++ XK_dead_e = 0xfe82, ++ XK_dead_E = 0xfe83, ++ XK_dead_i = 0xfe84, ++ XK_dead_I = 0xfe85, ++ XK_dead_o = 0xfe86, ++ XK_dead_O = 0xfe87, ++ XK_dead_u = 0xfe88, ++ XK_dead_U = 0xfe89, ++ // XK_dead_small_schwa = 0xfe8a, // deprecated alias for dead_schwa ++ XK_dead_schwa = 0xfe8a, ++ // XK_dead_capital_schwa = 0xfe8b, // deprecated alias for dead_SCHWA ++ XK_dead_SCHWA = 0xfe8b, ++ XK_dead_greek = 0xfe8c, ++ XK_dead_hamza = 0xfe8d, ++ XK_First_Virtual_Screen = 0xfed0, ++ XK_Prev_Virtual_Screen = 0xfed1, ++ XK_Next_Virtual_Screen = 0xfed2, ++ XK_Last_Virtual_Screen = 0xfed4, ++ XK_Terminate_Server = 0xfed5, ++ XK_AccessX_Enable = 0xfe70, ++ XK_AccessX_Feedback_Enable = 0xfe71, ++ XK_RepeatKeys_Enable = 0xfe72, ++ XK_SlowKeys_Enable = 0xfe73, ++ XK_BounceKeys_Enable = 0xfe74, ++ XK_StickyKeys_Enable = 0xfe75, ++ XK_MouseKeys_Enable = 0xfe76, ++ XK_MouseKeys_Accel_Enable = 0xfe77, ++ XK_Overlay1_Enable = 0xfe78, ++ XK_Overlay2_Enable = 0xfe79, ++ XK_AudibleBell_Enable = 0xfe7a, ++ XK_Pointer_Left = 0xfee0, ++ XK_Pointer_Right = 0xfee1, ++ XK_Pointer_Up = 0xfee2, ++ XK_Pointer_Down = 0xfee3, ++ XK_Pointer_UpLeft = 0xfee4, ++ XK_Pointer_UpRight = 0xfee5, ++ XK_Pointer_DownLeft = 0xfee6, ++ XK_Pointer_DownRight = 0xfee7, ++ XK_Pointer_Button_Dflt = 0xfee8, ++ XK_Pointer_Button1 = 0xfee9, ++ XK_Pointer_Button2 = 0xfeea, ++ XK_Pointer_Button3 = 0xfeeb, ++ XK_Pointer_Button4 = 0xfeec, ++ XK_Pointer_Button5 = 0xfeed, ++ XK_Pointer_DblClick_Dflt = 0xfeee, ++ XK_Pointer_DblClick1 = 0xfeef, ++ XK_Pointer_DblClick2 = 0xfef0, ++ XK_Pointer_DblClick3 = 0xfef1, ++ XK_Pointer_DblClick4 = 0xfef2, ++ XK_Pointer_DblClick5 = 0xfef3, ++ XK_Pointer_Drag_Dflt = 0xfef4, ++ XK_Pointer_Drag1 = 0xfef5, ++ XK_Pointer_Drag2 = 0xfef6, ++ XK_Pointer_Drag3 = 0xfef7, ++ XK_Pointer_Drag4 = 0xfef8, ++ XK_Pointer_Drag5 = 0xfefd, ++ XK_Pointer_EnableKeys = 0xfef9, ++ XK_Pointer_Accelerate = 0xfefa, ++ XK_Pointer_DfltBtnNext = 0xfefb, ++ XK_Pointer_DfltBtnPrev = 0xfefc, ++ XK_ch = 0xfea0, ++ XK_Ch = 0xfea1, ++ XK_CH = 0xfea2, ++ XK_c_h = 0xfea3, ++ XK_C_h = 0xfea4, ++ XK_C_H = 0xfea5, ++ ++ XK_3270_Duplicate = 0xfd01, ++ XK_3270_FieldMark = 0xfd02, ++ XK_3270_Right2 = 0xfd03, ++ XK_3270_Left2 = 0xfd04, ++ XK_3270_BackTab = 0xfd05, ++ XK_3270_EraseEOF = 0xfd06, ++ XK_3270_EraseInput = 0xfd07, ++ XK_3270_Reset = 0xfd08, ++ XK_3270_Quit = 0xfd09, ++ XK_3270_PA1 = 0xfd0a, ++ XK_3270_PA2 = 0xfd0b, ++ XK_3270_PA3 = 0xfd0c, ++ XK_3270_Test = 0xfd0d, ++ XK_3270_Attn = 0xfd0e, ++ XK_3270_CursorBlink = 0xfd0f, ++ XK_3270_AltCursor = 0xfd10, ++ XK_3270_KeyClick = 0xfd11, ++ XK_3270_Jump = 0xfd12, ++ XK_3270_Ident = 0xfd13, ++ XK_3270_Rule = 0xfd14, ++ XK_3270_Copy = 0xfd15, ++ XK_3270_Play = 0xfd16, ++ XK_3270_Setup = 0xfd17, ++ XK_3270_Record = 0xfd18, ++ XK_3270_ChangeScreen = 0xfd19, ++ XK_3270_DeleteWord = 0xfd1a, ++ XK_3270_ExSelect = 0xfd1b, ++ XK_3270_CursorSelect = 0xfd1c, ++ XK_3270_PrintScreen = 0xfd1d, ++ XK_3270_Enter = 0xfd1e, ++ ++ XK_space = 0x0020, // U+0020 SPACE ++ XK_exclam = 0x0021, // U+0021 EXCLAMATION MARK ++ XK_quotedbl = 0x0022, // U+0022 QUOTATION MARK ++ XK_numbersign = 0x0023, // U+0023 NUMBER SIGN ++ XK_dollar = 0x0024, // U+0024 DOLLAR SIGN ++ XK_percent = 0x0025, // U+0025 PERCENT SIGN ++ XK_ampersand = 0x0026, // U+0026 AMPERSAND ++ XK_apostrophe = 0x0027, // U+0027 APOSTROPHE ++ // XK_quoteright = 0x0027, // deprecated ++ XK_parenleft = 0x0028, // U+0028 LEFT PARENTHESIS ++ XK_parenright = 0x0029, // U+0029 RIGHT PARENTHESIS ++ XK_asterisk = 0x002a, // U+002A ASTERISK ++ XK_plus = 0x002b, // U+002B PLUS SIGN ++ XK_comma = 0x002c, // U+002C COMMA ++ XK_minus = 0x002d, // U+002D HYPHEN-MINUS ++ XK_period = 0x002e, // U+002E FULL STOP ++ XK_slash = 0x002f, // U+002F SOLIDUS ++ XK_0 = 0x0030, // U+0030 DIGIT ZERO ++ XK_1 = 0x0031, // U+0031 DIGIT ONE ++ XK_2 = 0x0032, // U+0032 DIGIT TWO ++ XK_3 = 0x0033, // U+0033 DIGIT THREE ++ XK_4 = 0x0034, // U+0034 DIGIT FOUR ++ XK_5 = 0x0035, // U+0035 DIGIT FIVE ++ XK_6 = 0x0036, // U+0036 DIGIT SIX ++ XK_7 = 0x0037, // U+0037 DIGIT SEVEN ++ XK_8 = 0x0038, // U+0038 DIGIT EIGHT ++ XK_9 = 0x0039, // U+0039 DIGIT NINE ++ XK_colon = 0x003a, // U+003A COLON ++ XK_semicolon = 0x003b, // U+003B SEMICOLON ++ XK_less = 0x003c, // U+003C LESS-THAN SIGN ++ XK_equal = 0x003d, // U+003D EQUALS SIGN ++ XK_greater = 0x003e, // U+003E GREATER-THAN SIGN ++ XK_question = 0x003f, // U+003F QUESTION MARK ++ XK_at = 0x0040, // U+0040 COMMERCIAL AT ++ XK_A = 0x0041, // U+0041 LATIN CAPITAL LETTER A ++ XK_B = 0x0042, // U+0042 LATIN CAPITAL LETTER B ++ XK_C = 0x0043, // U+0043 LATIN CAPITAL LETTER C ++ XK_D = 0x0044, // U+0044 LATIN CAPITAL LETTER D ++ XK_E = 0x0045, // U+0045 LATIN CAPITAL LETTER E ++ XK_F = 0x0046, // U+0046 LATIN CAPITAL LETTER F ++ XK_G = 0x0047, // U+0047 LATIN CAPITAL LETTER G ++ XK_H = 0x0048, // U+0048 LATIN CAPITAL LETTER H ++ XK_I = 0x0049, // U+0049 LATIN CAPITAL LETTER I ++ XK_J = 0x004a, // U+004A LATIN CAPITAL LETTER J ++ XK_K = 0x004b, // U+004B LATIN CAPITAL LETTER K ++ XK_L = 0x004c, // U+004C LATIN CAPITAL LETTER L ++ XK_M = 0x004d, // U+004D LATIN CAPITAL LETTER M ++ XK_N = 0x004e, // U+004E LATIN CAPITAL LETTER N ++ XK_O = 0x004f, // U+004F LATIN CAPITAL LETTER O ++ XK_P = 0x0050, // U+0050 LATIN CAPITAL LETTER P ++ XK_Q = 0x0051, // U+0051 LATIN CAPITAL LETTER Q ++ XK_R = 0x0052, // U+0052 LATIN CAPITAL LETTER R ++ XK_S = 0x0053, // U+0053 LATIN CAPITAL LETTER S ++ XK_T = 0x0054, // U+0054 LATIN CAPITAL LETTER T ++ XK_U = 0x0055, // U+0055 LATIN CAPITAL LETTER U ++ XK_V = 0x0056, // U+0056 LATIN CAPITAL LETTER V ++ XK_W = 0x0057, // U+0057 LATIN CAPITAL LETTER W ++ XK_X = 0x0058, // U+0058 LATIN CAPITAL LETTER X ++ XK_Y = 0x0059, // U+0059 LATIN CAPITAL LETTER Y ++ XK_Z = 0x005a, // U+005A LATIN CAPITAL LETTER Z ++ XK_bracketleft = 0x005b, // U+005B LEFT SQUARE BRACKET ++ XK_backslash = 0x005c, // U+005C REVERSE SOLIDUS ++ XK_bracketright = 0x005d, // U+005D RIGHT SQUARE BRACKET ++ XK_asciicircum = 0x005e, // U+005E CIRCUMFLEX ACCENT ++ XK_underscore = 0x005f, // U+005F LOW LINE ++ XK_grave = 0x0060, // U+0060 GRAVE ACCENT ++ // XK_quoteleft = 0x0060, // deprecated ++ XK_a = 0x0061, // U+0061 LATIN SMALL LETTER A ++ XK_b = 0x0062, // U+0062 LATIN SMALL LETTER B ++ XK_c = 0x0063, // U+0063 LATIN SMALL LETTER C ++ XK_d = 0x0064, // U+0064 LATIN SMALL LETTER D ++ XK_e = 0x0065, // U+0065 LATIN SMALL LETTER E ++ XK_f = 0x0066, // U+0066 LATIN SMALL LETTER F ++ XK_g = 0x0067, // U+0067 LATIN SMALL LETTER G ++ XK_h = 0x0068, // U+0068 LATIN SMALL LETTER H ++ XK_i = 0x0069, // U+0069 LATIN SMALL LETTER I ++ XK_j = 0x006a, // U+006A LATIN SMALL LETTER J ++ XK_k = 0x006b, // U+006B LATIN SMALL LETTER K ++ XK_l = 0x006c, // U+006C LATIN SMALL LETTER L ++ XK_m = 0x006d, // U+006D LATIN SMALL LETTER M ++ XK_n = 0x006e, // U+006E LATIN SMALL LETTER N ++ XK_o = 0x006f, // U+006F LATIN SMALL LETTER O ++ XK_p = 0x0070, // U+0070 LATIN SMALL LETTER P ++ XK_q = 0x0071, // U+0071 LATIN SMALL LETTER Q ++ XK_r = 0x0072, // U+0072 LATIN SMALL LETTER R ++ XK_s = 0x0073, // U+0073 LATIN SMALL LETTER S ++ XK_t = 0x0074, // U+0074 LATIN SMALL LETTER T ++ XK_u = 0x0075, // U+0075 LATIN SMALL LETTER U ++ XK_v = 0x0076, // U+0076 LATIN SMALL LETTER V ++ XK_w = 0x0077, // U+0077 LATIN SMALL LETTER W ++ XK_x = 0x0078, // U+0078 LATIN SMALL LETTER X ++ XK_y = 0x0079, // U+0079 LATIN SMALL LETTER Y ++ XK_z = 0x007a, // U+007A LATIN SMALL LETTER Z ++ XK_braceleft = 0x007b, // U+007B LEFT CURLY BRACKET ++ XK_bar = 0x007c, // U+007C VERTICAL LINE ++ XK_braceright = 0x007d, // U+007D RIGHT CURLY BRACKET ++ XK_asciitilde = 0x007e, // U+007E TILDE ++ XK_nobreakspace = 0x00a0, // U+00A0 NO-BREAK SPACE ++ XK_exclamdown = 0x00a1, // U+00A1 INVERTED EXCLAMATION MARK ++ XK_cent = 0x00a2, // U+00A2 CENT SIGN ++ XK_sterling = 0x00a3, // U+00A3 POUND SIGN ++ XK_currency = 0x00a4, // U+00A4 CURRENCY SIGN ++ XK_yen = 0x00a5, // U+00A5 YEN SIGN ++ XK_brokenbar = 0x00a6, // U+00A6 BROKEN BAR ++ XK_section = 0x00a7, // U+00A7 SECTION SIGN ++ XK_diaeresis = 0x00a8, // U+00A8 DIAERESIS ++ XK_copyright = 0x00a9, // U+00A9 COPYRIGHT SIGN ++ XK_ordfeminine = 0x00aa, // U+00AA FEMININE ORDINAL INDICATOR ++ // XK_guillemotleft = 0x00ab, // deprecated alias for guillemetleft (misspelling) ++ XK_guillemetleft = 0x00ab, // U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK ++ XK_notsign = 0x00ac, // U+00AC NOT SIGN ++ XK_hyphen = 0x00ad, // U+00AD SOFT HYPHEN ++ XK_registered = 0x00ae, // U+00AE REGISTERED SIGN ++ XK_macron = 0x00af, // U+00AF MACRON ++ XK_degree = 0x00b0, // U+00B0 DEGREE SIGN ++ XK_plusminus = 0x00b1, // U+00B1 PLUS-MINUS SIGN ++ XK_twosuperior = 0x00b2, // U+00B2 SUPERSCRIPT TWO ++ XK_threesuperior = 0x00b3, // U+00B3 SUPERSCRIPT THREE ++ XK_acute = 0x00b4, // U+00B4 ACUTE ACCENT ++ XK_mu = 0x00b5, // U+00B5 MICRO SIGN ++ XK_paragraph = 0x00b6, // U+00B6 PILCROW SIGN ++ XK_periodcentered = 0x00b7, // U+00B7 MIDDLE DOT ++ XK_cedilla = 0x00b8, // U+00B8 CEDILLA ++ XK_onesuperior = 0x00b9, // U+00B9 SUPERSCRIPT ONE ++ // XK_masculine = 0x00ba, // deprecated alias for ordmasculine (inconsistent name) ++ XK_ordmasculine = 0x00ba, // U+00BA MASCULINE ORDINAL INDICATOR ++ // XK_guillemotright = 0x00bb, // deprecated alias for guillemetright (misspelling) ++ XK_guillemetright = 0x00bb, // U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK ++ XK_onequarter = 0x00bc, // U+00BC VULGAR FRACTION ONE QUARTER ++ XK_onehalf = 0x00bd, // U+00BD VULGAR FRACTION ONE HALF ++ XK_threequarters = 0x00be, // U+00BE VULGAR FRACTION THREE QUARTERS ++ XK_questiondown = 0x00bf, // U+00BF INVERTED QUESTION MARK ++ XK_Agrave = 0x00c0, // U+00C0 LATIN CAPITAL LETTER A WITH GRAVE ++ XK_Aacute = 0x00c1, // U+00C1 LATIN CAPITAL LETTER A WITH ACUTE ++ XK_Acircumflex = 0x00c2, // U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX ++ XK_Atilde = 0x00c3, // U+00C3 LATIN CAPITAL LETTER A WITH TILDE ++ XK_Adiaeresis = 0x00c4, // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS ++ XK_Aring = 0x00c5, // U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE ++ XK_AE = 0x00c6, // U+00C6 LATIN CAPITAL LETTER AE ++ XK_Ccedilla = 0x00c7, // U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA ++ XK_Egrave = 0x00c8, // U+00C8 LATIN CAPITAL LETTER E WITH GRAVE ++ XK_Eacute = 0x00c9, // U+00C9 LATIN CAPITAL LETTER E WITH ACUTE ++ XK_Ecircumflex = 0x00ca, // U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX ++ XK_Ediaeresis = 0x00cb, // U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS ++ XK_Igrave = 0x00cc, // U+00CC LATIN CAPITAL LETTER I WITH GRAVE ++ XK_Iacute = 0x00cd, // U+00CD LATIN CAPITAL LETTER I WITH ACUTE ++ XK_Icircumflex = 0x00ce, // U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX ++ XK_Idiaeresis = 0x00cf, // U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS ++ XK_ETH = 0x00d0, // U+00D0 LATIN CAPITAL LETTER ETH ++ // XK_Eth = 0x00d0, // deprecated ++ XK_Ntilde = 0x00d1, // U+00D1 LATIN CAPITAL LETTER N WITH TILDE ++ XK_Ograve = 0x00d2, // U+00D2 LATIN CAPITAL LETTER O WITH GRAVE ++ XK_Oacute = 0x00d3, // U+00D3 LATIN CAPITAL LETTER O WITH ACUTE ++ XK_Ocircumflex = 0x00d4, // U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX ++ XK_Otilde = 0x00d5, // U+00D5 LATIN CAPITAL LETTER O WITH TILDE ++ XK_Odiaeresis = 0x00d6, // U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS ++ XK_multiply = 0x00d7, // U+00D7 MULTIPLICATION SIGN ++ XK_Oslash = 0x00d8, // U+00D8 LATIN CAPITAL LETTER O WITH STROKE ++ // XK_Ooblique = 0x00d8, // deprecated alias for Oslash ++ XK_Ugrave = 0x00d9, // U+00D9 LATIN CAPITAL LETTER U WITH GRAVE ++ XK_Uacute = 0x00da, // U+00DA LATIN CAPITAL LETTER U WITH ACUTE ++ XK_Ucircumflex = 0x00db, // U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX ++ XK_Udiaeresis = 0x00dc, // U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS ++ XK_Yacute = 0x00dd, // U+00DD LATIN CAPITAL LETTER Y WITH ACUTE ++ XK_THORN = 0x00de, // U+00DE LATIN CAPITAL LETTER THORN ++ // XK_Thorn = 0x00de, // deprecated ++ XK_ssharp = 0x00df, // U+00DF LATIN SMALL LETTER SHARP S ++ XK_agrave = 0x00e0, // U+00E0 LATIN SMALL LETTER A WITH GRAVE ++ XK_aacute = 0x00e1, // U+00E1 LATIN SMALL LETTER A WITH ACUTE ++ XK_acircumflex = 0x00e2, // U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX ++ XK_atilde = 0x00e3, // U+00E3 LATIN SMALL LETTER A WITH TILDE ++ XK_adiaeresis = 0x00e4, // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS ++ XK_aring = 0x00e5, // U+00E5 LATIN SMALL LETTER A WITH RING ABOVE ++ XK_ae = 0x00e6, // U+00E6 LATIN SMALL LETTER AE ++ XK_ccedilla = 0x00e7, // U+00E7 LATIN SMALL LETTER C WITH CEDILLA ++ XK_egrave = 0x00e8, // U+00E8 LATIN SMALL LETTER E WITH GRAVE ++ XK_eacute = 0x00e9, // U+00E9 LATIN SMALL LETTER E WITH ACUTE ++ XK_ecircumflex = 0x00ea, // U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX ++ XK_ediaeresis = 0x00eb, // U+00EB LATIN SMALL LETTER E WITH DIAERESIS ++ XK_igrave = 0x00ec, // U+00EC LATIN SMALL LETTER I WITH GRAVE ++ XK_iacute = 0x00ed, // U+00ED LATIN SMALL LETTER I WITH ACUTE ++ XK_icircumflex = 0x00ee, // U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX ++ XK_idiaeresis = 0x00ef, // U+00EF LATIN SMALL LETTER I WITH DIAERESIS ++ XK_eth = 0x00f0, // U+00F0 LATIN SMALL LETTER ETH ++ XK_ntilde = 0x00f1, // U+00F1 LATIN SMALL LETTER N WITH TILDE ++ XK_ograve = 0x00f2, // U+00F2 LATIN SMALL LETTER O WITH GRAVE ++ XK_oacute = 0x00f3, // U+00F3 LATIN SMALL LETTER O WITH ACUTE ++ XK_ocircumflex = 0x00f4, // U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX ++ XK_otilde = 0x00f5, // U+00F5 LATIN SMALL LETTER O WITH TILDE ++ XK_odiaeresis = 0x00f6, // U+00F6 LATIN SMALL LETTER O WITH DIAERESIS ++ XK_division = 0x00f7, // U+00F7 DIVISION SIGN ++ XK_oslash = 0x00f8, // U+00F8 LATIN SMALL LETTER O WITH STROKE ++ // XK_ooblique = 0x00f8, // deprecated alias for oslash ++ XK_ugrave = 0x00f9, // U+00F9 LATIN SMALL LETTER U WITH GRAVE ++ XK_uacute = 0x00fa, // U+00FA LATIN SMALL LETTER U WITH ACUTE ++ XK_ucircumflex = 0x00fb, // U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX ++ XK_udiaeresis = 0x00fc, // U+00FC LATIN SMALL LETTER U WITH DIAERESIS ++ XK_yacute = 0x00fd, // U+00FD LATIN SMALL LETTER Y WITH ACUTE ++ XK_thorn = 0x00fe, // U+00FE LATIN SMALL LETTER THORN ++ XK_ydiaeresis = 0x00ff, // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS ++ ++ XK_Aogonek = 0x01a1, // U+0104 LATIN CAPITAL LETTER A WITH OGONEK ++ XK_breve = 0x01a2, // U+02D8 BREVE ++ XK_Lstroke = 0x01a3, // U+0141 LATIN CAPITAL LETTER L WITH STROKE ++ XK_Lcaron = 0x01a5, // U+013D LATIN CAPITAL LETTER L WITH CARON ++ XK_Sacute = 0x01a6, // U+015A LATIN CAPITAL LETTER S WITH ACUTE ++ XK_Scaron = 0x01a9, // U+0160 LATIN CAPITAL LETTER S WITH CARON ++ XK_Scedilla = 0x01aa, // U+015E LATIN CAPITAL LETTER S WITH CEDILLA ++ XK_Tcaron = 0x01ab, // U+0164 LATIN CAPITAL LETTER T WITH CARON ++ XK_Zacute = 0x01ac, // U+0179 LATIN CAPITAL LETTER Z WITH ACUTE ++ XK_Zcaron = 0x01ae, // U+017D LATIN CAPITAL LETTER Z WITH CARON ++ XK_Zabovedot = 0x01af, // U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE ++ XK_aogonek = 0x01b1, // U+0105 LATIN SMALL LETTER A WITH OGONEK ++ XK_ogonek = 0x01b2, // U+02DB OGONEK ++ XK_lstroke = 0x01b3, // U+0142 LATIN SMALL LETTER L WITH STROKE ++ XK_lcaron = 0x01b5, // U+013E LATIN SMALL LETTER L WITH CARON ++ XK_sacute = 0x01b6, // U+015B LATIN SMALL LETTER S WITH ACUTE ++ XK_caron = 0x01b7, // U+02C7 CARON ++ XK_scaron = 0x01b9, // U+0161 LATIN SMALL LETTER S WITH CARON ++ XK_scedilla = 0x01ba, // U+015F LATIN SMALL LETTER S WITH CEDILLA ++ XK_tcaron = 0x01bb, // U+0165 LATIN SMALL LETTER T WITH CARON ++ XK_zacute = 0x01bc, // U+017A LATIN SMALL LETTER Z WITH ACUTE ++ XK_doubleacute = 0x01bd, // U+02DD DOUBLE ACUTE ACCENT ++ XK_zcaron = 0x01be, // U+017E LATIN SMALL LETTER Z WITH CARON ++ XK_zabovedot = 0x01bf, // U+017C LATIN SMALL LETTER Z WITH DOT ABOVE ++ XK_Racute = 0x01c0, // U+0154 LATIN CAPITAL LETTER R WITH ACUTE ++ XK_Abreve = 0x01c3, // U+0102 LATIN CAPITAL LETTER A WITH BREVE ++ XK_Lacute = 0x01c5, // U+0139 LATIN CAPITAL LETTER L WITH ACUTE ++ XK_Cacute = 0x01c6, // U+0106 LATIN CAPITAL LETTER C WITH ACUTE ++ XK_Ccaron = 0x01c8, // U+010C LATIN CAPITAL LETTER C WITH CARON ++ XK_Eogonek = 0x01ca, // U+0118 LATIN CAPITAL LETTER E WITH OGONEK ++ XK_Ecaron = 0x01cc, // U+011A LATIN CAPITAL LETTER E WITH CARON ++ XK_Dcaron = 0x01cf, // U+010E LATIN CAPITAL LETTER D WITH CARON ++ XK_Dstroke = 0x01d0, // U+0110 LATIN CAPITAL LETTER D WITH STROKE ++ XK_Nacute = 0x01d1, // U+0143 LATIN CAPITAL LETTER N WITH ACUTE ++ XK_Ncaron = 0x01d2, // U+0147 LATIN CAPITAL LETTER N WITH CARON ++ XK_Odoubleacute = 0x01d5, // U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE ++ XK_Rcaron = 0x01d8, // U+0158 LATIN CAPITAL LETTER R WITH CARON ++ XK_Uring = 0x01d9, // U+016E LATIN CAPITAL LETTER U WITH RING ABOVE ++ XK_Udoubleacute = 0x01db, // U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE ++ XK_Tcedilla = 0x01de, // U+0162 LATIN CAPITAL LETTER T WITH CEDILLA ++ XK_racute = 0x01e0, // U+0155 LATIN SMALL LETTER R WITH ACUTE ++ XK_abreve = 0x01e3, // U+0103 LATIN SMALL LETTER A WITH BREVE ++ XK_lacute = 0x01e5, // U+013A LATIN SMALL LETTER L WITH ACUTE ++ XK_cacute = 0x01e6, // U+0107 LATIN SMALL LETTER C WITH ACUTE ++ XK_ccaron = 0x01e8, // U+010D LATIN SMALL LETTER C WITH CARON ++ XK_eogonek = 0x01ea, // U+0119 LATIN SMALL LETTER E WITH OGONEK ++ XK_ecaron = 0x01ec, // U+011B LATIN SMALL LETTER E WITH CARON ++ XK_dcaron = 0x01ef, // U+010F LATIN SMALL LETTER D WITH CARON ++ XK_dstroke = 0x01f0, // U+0111 LATIN SMALL LETTER D WITH STROKE ++ XK_nacute = 0x01f1, // U+0144 LATIN SMALL LETTER N WITH ACUTE ++ XK_ncaron = 0x01f2, // U+0148 LATIN SMALL LETTER N WITH CARON ++ XK_odoubleacute = 0x01f5, // U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE ++ XK_rcaron = 0x01f8, // U+0159 LATIN SMALL LETTER R WITH CARON ++ XK_uring = 0x01f9, // U+016F LATIN SMALL LETTER U WITH RING ABOVE ++ XK_udoubleacute = 0x01fb, // U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE ++ XK_tcedilla = 0x01fe, // U+0163 LATIN SMALL LETTER T WITH CEDILLA ++ XK_abovedot = 0x01ff, // U+02D9 DOT ABOVE ++ ++ XK_Hstroke = 0x02a1, // U+0126 LATIN CAPITAL LETTER H WITH STROKE ++ XK_Hcircumflex = 0x02a6, // U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX ++ XK_Iabovedot = 0x02a9, // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE ++ XK_Gbreve = 0x02ab, // U+011E LATIN CAPITAL LETTER G WITH BREVE ++ XK_Jcircumflex = 0x02ac, // U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX ++ XK_hstroke = 0x02b1, // U+0127 LATIN SMALL LETTER H WITH STROKE ++ XK_hcircumflex = 0x02b6, // U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX ++ XK_idotless = 0x02b9, // U+0131 LATIN SMALL LETTER DOTLESS I ++ XK_gbreve = 0x02bb, // U+011F LATIN SMALL LETTER G WITH BREVE ++ XK_jcircumflex = 0x02bc, // U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX ++ XK_Cabovedot = 0x02c5, // U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE ++ XK_Ccircumflex = 0x02c6, // U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX ++ XK_Gabovedot = 0x02d5, // U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE ++ XK_Gcircumflex = 0x02d8, // U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX ++ XK_Ubreve = 0x02dd, // U+016C LATIN CAPITAL LETTER U WITH BREVE ++ XK_Scircumflex = 0x02de, // U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX ++ XK_cabovedot = 0x02e5, // U+010B LATIN SMALL LETTER C WITH DOT ABOVE ++ XK_ccircumflex = 0x02e6, // U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX ++ XK_gabovedot = 0x02f5, // U+0121 LATIN SMALL LETTER G WITH DOT ABOVE ++ XK_gcircumflex = 0x02f8, // U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX ++ XK_ubreve = 0x02fd, // U+016D LATIN SMALL LETTER U WITH BREVE ++ XK_scircumflex = 0x02fe, // U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX ++ ++ XK_kra = 0x03a2, // U+0138 LATIN SMALL LETTER KRA ++ // XK_kappa = 0x03a2, // deprecated ++ XK_Rcedilla = 0x03a3, // U+0156 LATIN CAPITAL LETTER R WITH CEDILLA ++ XK_Itilde = 0x03a5, // U+0128 LATIN CAPITAL LETTER I WITH TILDE ++ XK_Lcedilla = 0x03a6, // U+013B LATIN CAPITAL LETTER L WITH CEDILLA ++ XK_Emacron = 0x03aa, // U+0112 LATIN CAPITAL LETTER E WITH MACRON ++ XK_Gcedilla = 0x03ab, // U+0122 LATIN CAPITAL LETTER G WITH CEDILLA ++ XK_Tslash = 0x03ac, // U+0166 LATIN CAPITAL LETTER T WITH STROKE ++ XK_rcedilla = 0x03b3, // U+0157 LATIN SMALL LETTER R WITH CEDILLA ++ XK_itilde = 0x03b5, // U+0129 LATIN SMALL LETTER I WITH TILDE ++ XK_lcedilla = 0x03b6, // U+013C LATIN SMALL LETTER L WITH CEDILLA ++ XK_emacron = 0x03ba, // U+0113 LATIN SMALL LETTER E WITH MACRON ++ XK_gcedilla = 0x03bb, // U+0123 LATIN SMALL LETTER G WITH CEDILLA ++ XK_tslash = 0x03bc, // U+0167 LATIN SMALL LETTER T WITH STROKE ++ XK_ENG = 0x03bd, // U+014A LATIN CAPITAL LETTER ENG ++ XK_eng = 0x03bf, // U+014B LATIN SMALL LETTER ENG ++ XK_Amacron = 0x03c0, // U+0100 LATIN CAPITAL LETTER A WITH MACRON ++ XK_Iogonek = 0x03c7, // U+012E LATIN CAPITAL LETTER I WITH OGONEK ++ XK_Eabovedot = 0x03cc, // U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE ++ XK_Imacron = 0x03cf, // U+012A LATIN CAPITAL LETTER I WITH MACRON ++ XK_Ncedilla = 0x03d1, // U+0145 LATIN CAPITAL LETTER N WITH CEDILLA ++ XK_Omacron = 0x03d2, // U+014C LATIN CAPITAL LETTER O WITH MACRON ++ XK_Kcedilla = 0x03d3, // U+0136 LATIN CAPITAL LETTER K WITH CEDILLA ++ XK_Uogonek = 0x03d9, // U+0172 LATIN CAPITAL LETTER U WITH OGONEK ++ XK_Utilde = 0x03dd, // U+0168 LATIN CAPITAL LETTER U WITH TILDE ++ XK_Umacron = 0x03de, // U+016A LATIN CAPITAL LETTER U WITH MACRON ++ XK_amacron = 0x03e0, // U+0101 LATIN SMALL LETTER A WITH MACRON ++ XK_iogonek = 0x03e7, // U+012F LATIN SMALL LETTER I WITH OGONEK ++ XK_eabovedot = 0x03ec, // U+0117 LATIN SMALL LETTER E WITH DOT ABOVE ++ XK_imacron = 0x03ef, // U+012B LATIN SMALL LETTER I WITH MACRON ++ XK_ncedilla = 0x03f1, // U+0146 LATIN SMALL LETTER N WITH CEDILLA ++ XK_omacron = 0x03f2, // U+014D LATIN SMALL LETTER O WITH MACRON ++ XK_kcedilla = 0x03f3, // U+0137 LATIN SMALL LETTER K WITH CEDILLA ++ XK_uogonek = 0x03f9, // U+0173 LATIN SMALL LETTER U WITH OGONEK ++ XK_utilde = 0x03fd, // U+0169 LATIN SMALL LETTER U WITH TILDE ++ XK_umacron = 0x03fe, // U+016B LATIN SMALL LETTER U WITH MACRON ++ ++ XK_Wcircumflex = 0x1000174, // U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX ++ XK_wcircumflex = 0x1000175, // U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX ++ XK_Ycircumflex = 0x1000176, // U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX ++ XK_ycircumflex = 0x1000177, // U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX ++ XK_Babovedot = 0x1001e02, // U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE ++ XK_babovedot = 0x1001e03, // U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE ++ XK_Dabovedot = 0x1001e0a, // U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE ++ XK_dabovedot = 0x1001e0b, // U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE ++ XK_Fabovedot = 0x1001e1e, // U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE ++ XK_fabovedot = 0x1001e1f, // U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE ++ XK_Mabovedot = 0x1001e40, // U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE ++ XK_mabovedot = 0x1001e41, // U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE ++ XK_Pabovedot = 0x1001e56, // U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE ++ XK_pabovedot = 0x1001e57, // U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE ++ XK_Sabovedot = 0x1001e60, // U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE ++ XK_sabovedot = 0x1001e61, // U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE ++ XK_Tabovedot = 0x1001e6a, // U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE ++ XK_tabovedot = 0x1001e6b, // U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE ++ XK_Wgrave = 0x1001e80, // U+1E80 LATIN CAPITAL LETTER W WITH GRAVE ++ XK_wgrave = 0x1001e81, // U+1E81 LATIN SMALL LETTER W WITH GRAVE ++ XK_Wacute = 0x1001e82, // U+1E82 LATIN CAPITAL LETTER W WITH ACUTE ++ XK_wacute = 0x1001e83, // U+1E83 LATIN SMALL LETTER W WITH ACUTE ++ XK_Wdiaeresis = 0x1001e84, // U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS ++ XK_wdiaeresis = 0x1001e85, // U+1E85 LATIN SMALL LETTER W WITH DIAERESIS ++ XK_Ygrave = 0x1001ef2, // U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE ++ XK_ygrave = 0x1001ef3, // U+1EF3 LATIN SMALL LETTER Y WITH GRAVE ++ ++ XK_OE = 0x13bc, // U+0152 LATIN CAPITAL LIGATURE OE ++ XK_oe = 0x13bd, // U+0153 LATIN SMALL LIGATURE OE ++ XK_Ydiaeresis = 0x13be, // U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS ++ ++ XK_overline = 0x047e, // U+203E OVERLINE ++ XK_kana_fullstop = 0x04a1, // U+3002 IDEOGRAPHIC FULL STOP ++ XK_kana_openingbracket = 0x04a2, // U+300C LEFT CORNER BRACKET ++ XK_kana_closingbracket = 0x04a3, // U+300D RIGHT CORNER BRACKET ++ XK_kana_comma = 0x04a4, // U+3001 IDEOGRAPHIC COMMA ++ XK_kana_conjunctive = 0x04a5, // U+30FB KATAKANA MIDDLE DOT ++ // XK_kana_middledot = 0x04a5, // deprecated ++ XK_kana_WO = 0x04a6, // U+30F2 KATAKANA LETTER WO ++ XK_kana_a = 0x04a7, // U+30A1 KATAKANA LETTER SMALL A ++ XK_kana_i = 0x04a8, // U+30A3 KATAKANA LETTER SMALL I ++ XK_kana_u = 0x04a9, // U+30A5 KATAKANA LETTER SMALL U ++ XK_kana_e = 0x04aa, // U+30A7 KATAKANA LETTER SMALL E ++ XK_kana_o = 0x04ab, // U+30A9 KATAKANA LETTER SMALL O ++ XK_kana_ya = 0x04ac, // U+30E3 KATAKANA LETTER SMALL YA ++ XK_kana_yu = 0x04ad, // U+30E5 KATAKANA LETTER SMALL YU ++ XK_kana_yo = 0x04ae, // U+30E7 KATAKANA LETTER SMALL YO ++ XK_kana_tsu = 0x04af, // U+30C3 KATAKANA LETTER SMALL TU ++ // XK_kana_tu = 0x04af, // deprecated ++ XK_prolongedsound = 0x04b0, // U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK ++ XK_kana_A = 0x04b1, // U+30A2 KATAKANA LETTER A ++ XK_kana_I = 0x04b2, // U+30A4 KATAKANA LETTER I ++ XK_kana_U = 0x04b3, // U+30A6 KATAKANA LETTER U ++ XK_kana_E = 0x04b4, // U+30A8 KATAKANA LETTER E ++ XK_kana_O = 0x04b5, // U+30AA KATAKANA LETTER O ++ XK_kana_KA = 0x04b6, // U+30AB KATAKANA LETTER KA ++ XK_kana_KI = 0x04b7, // U+30AD KATAKANA LETTER KI ++ XK_kana_KU = 0x04b8, // U+30AF KATAKANA LETTER KU ++ XK_kana_KE = 0x04b9, // U+30B1 KATAKANA LETTER KE ++ XK_kana_KO = 0x04ba, // U+30B3 KATAKANA LETTER KO ++ XK_kana_SA = 0x04bb, // U+30B5 KATAKANA LETTER SA ++ XK_kana_SHI = 0x04bc, // U+30B7 KATAKANA LETTER SI ++ XK_kana_SU = 0x04bd, // U+30B9 KATAKANA LETTER SU ++ XK_kana_SE = 0x04be, // U+30BB KATAKANA LETTER SE ++ XK_kana_SO = 0x04bf, // U+30BD KATAKANA LETTER SO ++ XK_kana_TA = 0x04c0, // U+30BF KATAKANA LETTER TA ++ XK_kana_CHI = 0x04c1, // U+30C1 KATAKANA LETTER TI ++ // XK_kana_TI = 0x04c1, // deprecated ++ XK_kana_TSU = 0x04c2, // U+30C4 KATAKANA LETTER TU ++ // XK_kana_TU = 0x04c2, // deprecated ++ XK_kana_TE = 0x04c3, // U+30C6 KATAKANA LETTER TE ++ XK_kana_TO = 0x04c4, // U+30C8 KATAKANA LETTER TO ++ XK_kana_NA = 0x04c5, // U+30CA KATAKANA LETTER NA ++ XK_kana_NI = 0x04c6, // U+30CB KATAKANA LETTER NI ++ XK_kana_NU = 0x04c7, // U+30CC KATAKANA LETTER NU ++ XK_kana_NE = 0x04c8, // U+30CD KATAKANA LETTER NE ++ XK_kana_NO = 0x04c9, // U+30CE KATAKANA LETTER NO ++ XK_kana_HA = 0x04ca, // U+30CF KATAKANA LETTER HA ++ XK_kana_HI = 0x04cb, // U+30D2 KATAKANA LETTER HI ++ XK_kana_FU = 0x04cc, // U+30D5 KATAKANA LETTER HU ++ // XK_kana_HU = 0x04cc, // deprecated ++ XK_kana_HE = 0x04cd, // U+30D8 KATAKANA LETTER HE ++ XK_kana_HO = 0x04ce, // U+30DB KATAKANA LETTER HO ++ XK_kana_MA = 0x04cf, // U+30DE KATAKANA LETTER MA ++ XK_kana_MI = 0x04d0, // U+30DF KATAKANA LETTER MI ++ XK_kana_MU = 0x04d1, // U+30E0 KATAKANA LETTER MU ++ XK_kana_ME = 0x04d2, // U+30E1 KATAKANA LETTER ME ++ XK_kana_MO = 0x04d3, // U+30E2 KATAKANA LETTER MO ++ XK_kana_YA = 0x04d4, // U+30E4 KATAKANA LETTER YA ++ XK_kana_YU = 0x04d5, // U+30E6 KATAKANA LETTER YU ++ XK_kana_YO = 0x04d6, // U+30E8 KATAKANA LETTER YO ++ XK_kana_RA = 0x04d7, // U+30E9 KATAKANA LETTER RA ++ XK_kana_RI = 0x04d8, // U+30EA KATAKANA LETTER RI ++ XK_kana_RU = 0x04d9, // U+30EB KATAKANA LETTER RU ++ XK_kana_RE = 0x04da, // U+30EC KATAKANA LETTER RE ++ XK_kana_RO = 0x04db, // U+30ED KATAKANA LETTER RO ++ XK_kana_WA = 0x04dc, // U+30EF KATAKANA LETTER WA ++ XK_kana_N = 0x04dd, // U+30F3 KATAKANA LETTER N ++ XK_voicedsound = 0x04de, // U+309B KATAKANA-HIRAGANA VOICED SOUND MARK ++ XK_semivoicedsound = 0x04df, // U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK ++ // XK_kana_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ ++ XK_Farsi_0 = 0x10006f0, // U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO ++ XK_Farsi_1 = 0x10006f1, // U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE ++ XK_Farsi_2 = 0x10006f2, // U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO ++ XK_Farsi_3 = 0x10006f3, // U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE ++ XK_Farsi_4 = 0x10006f4, // U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR ++ XK_Farsi_5 = 0x10006f5, // U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE ++ XK_Farsi_6 = 0x10006f6, // U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX ++ XK_Farsi_7 = 0x10006f7, // U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN ++ XK_Farsi_8 = 0x10006f8, // U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT ++ XK_Farsi_9 = 0x10006f9, // U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE ++ XK_Arabic_percent = 0x100066a, // U+066A ARABIC PERCENT SIGN ++ XK_Arabic_superscript_alef = 0x1000670, // U+0670 ARABIC LETTER SUPERSCRIPT ALEF ++ XK_Arabic_tteh = 0x1000679, // U+0679 ARABIC LETTER TTEH ++ XK_Arabic_peh = 0x100067e, // U+067E ARABIC LETTER PEH ++ XK_Arabic_tcheh = 0x1000686, // U+0686 ARABIC LETTER TCHEH ++ XK_Arabic_ddal = 0x1000688, // U+0688 ARABIC LETTER DDAL ++ XK_Arabic_rreh = 0x1000691, // U+0691 ARABIC LETTER RREH ++ XK_Arabic_comma = 0x05ac, // U+060C ARABIC COMMA ++ XK_Arabic_fullstop = 0x10006d4, // U+06D4 ARABIC FULL STOP ++ XK_Arabic_0 = 0x1000660, // U+0660 ARABIC-INDIC DIGIT ZERO ++ XK_Arabic_1 = 0x1000661, // U+0661 ARABIC-INDIC DIGIT ONE ++ XK_Arabic_2 = 0x1000662, // U+0662 ARABIC-INDIC DIGIT TWO ++ XK_Arabic_3 = 0x1000663, // U+0663 ARABIC-INDIC DIGIT THREE ++ XK_Arabic_4 = 0x1000664, // U+0664 ARABIC-INDIC DIGIT FOUR ++ XK_Arabic_5 = 0x1000665, // U+0665 ARABIC-INDIC DIGIT FIVE ++ XK_Arabic_6 = 0x1000666, // U+0666 ARABIC-INDIC DIGIT SIX ++ XK_Arabic_7 = 0x1000667, // U+0667 ARABIC-INDIC DIGIT SEVEN ++ XK_Arabic_8 = 0x1000668, // U+0668 ARABIC-INDIC DIGIT EIGHT ++ XK_Arabic_9 = 0x1000669, // U+0669 ARABIC-INDIC DIGIT NINE ++ XK_Arabic_semicolon = 0x05bb, // U+061B ARABIC SEMICOLON ++ XK_Arabic_question_mark = 0x05bf, // U+061F ARABIC QUESTION MARK ++ XK_Arabic_hamza = 0x05c1, // U+0621 ARABIC LETTER HAMZA ++ XK_Arabic_maddaonalef = 0x05c2, // U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE ++ XK_Arabic_hamzaonalef = 0x05c3, // U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE ++ XK_Arabic_hamzaonwaw = 0x05c4, // U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE ++ XK_Arabic_hamzaunderalef = 0x05c5, // U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW ++ XK_Arabic_hamzaonyeh = 0x05c6, // U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE ++ XK_Arabic_alef = 0x05c7, // U+0627 ARABIC LETTER ALEF ++ XK_Arabic_beh = 0x05c8, // U+0628 ARABIC LETTER BEH ++ XK_Arabic_tehmarbuta = 0x05c9, // U+0629 ARABIC LETTER TEH MARBUTA ++ XK_Arabic_teh = 0x05ca, // U+062A ARABIC LETTER TEH ++ XK_Arabic_theh = 0x05cb, // U+062B ARABIC LETTER THEH ++ XK_Arabic_jeem = 0x05cc, // U+062C ARABIC LETTER JEEM ++ XK_Arabic_hah = 0x05cd, // U+062D ARABIC LETTER HAH ++ XK_Arabic_khah = 0x05ce, // U+062E ARABIC LETTER KHAH ++ XK_Arabic_dal = 0x05cf, // U+062F ARABIC LETTER DAL ++ XK_Arabic_thal = 0x05d0, // U+0630 ARABIC LETTER THAL ++ XK_Arabic_ra = 0x05d1, // U+0631 ARABIC LETTER REH ++ XK_Arabic_zain = 0x05d2, // U+0632 ARABIC LETTER ZAIN ++ XK_Arabic_seen = 0x05d3, // U+0633 ARABIC LETTER SEEN ++ XK_Arabic_sheen = 0x05d4, // U+0634 ARABIC LETTER SHEEN ++ XK_Arabic_sad = 0x05d5, // U+0635 ARABIC LETTER SAD ++ XK_Arabic_dad = 0x05d6, // U+0636 ARABIC LETTER DAD ++ XK_Arabic_tah = 0x05d7, // U+0637 ARABIC LETTER TAH ++ XK_Arabic_zah = 0x05d8, // U+0638 ARABIC LETTER ZAH ++ XK_Arabic_ain = 0x05d9, // U+0639 ARABIC LETTER AIN ++ XK_Arabic_ghain = 0x05da, // U+063A ARABIC LETTER GHAIN ++ XK_Arabic_tatweel = 0x05e0, // U+0640 ARABIC TATWEEL ++ XK_Arabic_feh = 0x05e1, // U+0641 ARABIC LETTER FEH ++ XK_Arabic_qaf = 0x05e2, // U+0642 ARABIC LETTER QAF ++ XK_Arabic_kaf = 0x05e3, // U+0643 ARABIC LETTER KAF ++ XK_Arabic_lam = 0x05e4, // U+0644 ARABIC LETTER LAM ++ XK_Arabic_meem = 0x05e5, // U+0645 ARABIC LETTER MEEM ++ XK_Arabic_noon = 0x05e6, // U+0646 ARABIC LETTER NOON ++ XK_Arabic_ha = 0x05e7, // U+0647 ARABIC LETTER HEH ++ // XK_Arabic_heh = 0x05e7, // deprecated ++ XK_Arabic_waw = 0x05e8, // U+0648 ARABIC LETTER WAW ++ XK_Arabic_alefmaksura = 0x05e9, // U+0649 ARABIC LETTER ALEF MAKSURA ++ XK_Arabic_yeh = 0x05ea, // U+064A ARABIC LETTER YEH ++ XK_Arabic_fathatan = 0x05eb, // U+064B ARABIC FATHATAN ++ XK_Arabic_dammatan = 0x05ec, // U+064C ARABIC DAMMATAN ++ XK_Arabic_kasratan = 0x05ed, // U+064D ARABIC KASRATAN ++ XK_Arabic_fatha = 0x05ee, // U+064E ARABIC FATHA ++ XK_Arabic_damma = 0x05ef, // U+064F ARABIC DAMMA ++ XK_Arabic_kasra = 0x05f0, // U+0650 ARABIC KASRA ++ XK_Arabic_shadda = 0x05f1, // U+0651 ARABIC SHADDA ++ XK_Arabic_sukun = 0x05f2, // U+0652 ARABIC SUKUN ++ XK_Arabic_madda_above = 0x1000653, // U+0653 ARABIC MADDAH ABOVE ++ XK_Arabic_hamza_above = 0x1000654, // U+0654 ARABIC HAMZA ABOVE ++ XK_Arabic_hamza_below = 0x1000655, // U+0655 ARABIC HAMZA BELOW ++ XK_Arabic_jeh = 0x1000698, // U+0698 ARABIC LETTER JEH ++ XK_Arabic_veh = 0x10006a4, // U+06A4 ARABIC LETTER VEH ++ XK_Arabic_keheh = 0x10006a9, // U+06A9 ARABIC LETTER KEHEH ++ XK_Arabic_gaf = 0x10006af, // U+06AF ARABIC LETTER GAF ++ XK_Arabic_noon_ghunna = 0x10006ba, // U+06BA ARABIC LETTER NOON GHUNNA ++ XK_Arabic_heh_doachashmee = 0x10006be, // U+06BE ARABIC LETTER HEH DOACHASHMEE ++ XK_Farsi_yeh = 0x10006cc, // U+06CC ARABIC LETTER FARSI YEH ++ // XK_Arabic_farsi_yeh = 0x10006cc, // deprecated alias for Farsi_yeh ++ XK_Arabic_yeh_baree = 0x10006d2, // U+06D2 ARABIC LETTER YEH BARREE ++ XK_Arabic_heh_goal = 0x10006c1, // U+06C1 ARABIC LETTER HEH GOAL ++ // XK_Arabic_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ ++ XK_Cyrillic_GHE_bar = 0x1000492, // U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE ++ XK_Cyrillic_ghe_bar = 0x1000493, // U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE ++ XK_Cyrillic_ZHE_descender = 0x1000496, // U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER ++ XK_Cyrillic_zhe_descender = 0x1000497, // U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER ++ XK_Cyrillic_KA_descender = 0x100049a, // U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER ++ XK_Cyrillic_ka_descender = 0x100049b, // U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER ++ XK_Cyrillic_KA_vertstroke = 0x100049c, // U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE ++ XK_Cyrillic_ka_vertstroke = 0x100049d, // U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE ++ XK_Cyrillic_EN_descender = 0x10004a2, // U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER ++ XK_Cyrillic_en_descender = 0x10004a3, // U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER ++ XK_Cyrillic_U_straight = 0x10004ae, // U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U ++ XK_Cyrillic_u_straight = 0x10004af, // U+04AF CYRILLIC SMALL LETTER STRAIGHT U ++ XK_Cyrillic_U_straight_bar = 0x10004b0, // U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE ++ XK_Cyrillic_u_straight_bar = 0x10004b1, // U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE ++ XK_Cyrillic_HA_descender = 0x10004b2, // U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER ++ XK_Cyrillic_ha_descender = 0x10004b3, // U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER ++ XK_Cyrillic_CHE_descender = 0x10004b6, // U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER ++ XK_Cyrillic_che_descender = 0x10004b7, // U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER ++ XK_Cyrillic_CHE_vertstroke = 0x10004b8, // U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE ++ XK_Cyrillic_che_vertstroke = 0x10004b9, // U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE ++ XK_Cyrillic_SHHA = 0x10004ba, // U+04BA CYRILLIC CAPITAL LETTER SHHA ++ XK_Cyrillic_shha = 0x10004bb, // U+04BB CYRILLIC SMALL LETTER SHHA ++ XK_Cyrillic_SCHWA = 0x10004d8, // U+04D8 CYRILLIC CAPITAL LETTER SCHWA ++ XK_Cyrillic_schwa = 0x10004d9, // U+04D9 CYRILLIC SMALL LETTER SCHWA ++ XK_Cyrillic_I_macron = 0x10004e2, // U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON ++ XK_Cyrillic_i_macron = 0x10004e3, // U+04E3 CYRILLIC SMALL LETTER I WITH MACRON ++ XK_Cyrillic_O_bar = 0x10004e8, // U+04E8 CYRILLIC CAPITAL LETTER BARRED O ++ XK_Cyrillic_o_bar = 0x10004e9, // U+04E9 CYRILLIC SMALL LETTER BARRED O ++ XK_Cyrillic_U_macron = 0x10004ee, // U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON ++ XK_Cyrillic_u_macron = 0x10004ef, // U+04EF CYRILLIC SMALL LETTER U WITH MACRON ++ XK_Serbian_dje = 0x06a1, // U+0452 CYRILLIC SMALL LETTER DJE ++ XK_Macedonia_gje = 0x06a2, // U+0453 CYRILLIC SMALL LETTER GJE ++ XK_Cyrillic_io = 0x06a3, // U+0451 CYRILLIC SMALL LETTER IO ++ XK_Ukrainian_ie = 0x06a4, // U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE ++ // XK_Ukranian_je = 0x06a4, // deprecated ++ XK_Macedonia_dse = 0x06a5, // U+0455 CYRILLIC SMALL LETTER DZE ++ XK_Ukrainian_i = 0x06a6, // U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I ++ // XK_Ukranian_i = 0x06a6, // deprecated ++ XK_Ukrainian_yi = 0x06a7, // U+0457 CYRILLIC SMALL LETTER YI ++ // XK_Ukranian_yi = 0x06a7, // deprecated ++ XK_Cyrillic_je = 0x06a8, // U+0458 CYRILLIC SMALL LETTER JE ++ // XK_Serbian_je = 0x06a8, // deprecated ++ XK_Cyrillic_lje = 0x06a9, // U+0459 CYRILLIC SMALL LETTER LJE ++ // XK_Serbian_lje = 0x06a9, // deprecated ++ XK_Cyrillic_nje = 0x06aa, // U+045A CYRILLIC SMALL LETTER NJE ++ // XK_Serbian_nje = 0x06aa, // deprecated ++ XK_Serbian_tshe = 0x06ab, // U+045B CYRILLIC SMALL LETTER TSHE ++ XK_Macedonia_kje = 0x06ac, // U+045C CYRILLIC SMALL LETTER KJE ++ XK_Ukrainian_ghe_with_upturn = 0x06ad, // U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN ++ XK_Byelorussian_shortu = 0x06ae, // U+045E CYRILLIC SMALL LETTER SHORT U ++ XK_Cyrillic_dzhe = 0x06af, // U+045F CYRILLIC SMALL LETTER DZHE ++ // XK_Serbian_dze = 0x06af, // deprecated ++ XK_numerosign = 0x06b0, // U+2116 NUMERO SIGN ++ XK_Serbian_DJE = 0x06b1, // U+0402 CYRILLIC CAPITAL LETTER DJE ++ XK_Macedonia_GJE = 0x06b2, // U+0403 CYRILLIC CAPITAL LETTER GJE ++ XK_Cyrillic_IO = 0x06b3, // U+0401 CYRILLIC CAPITAL LETTER IO ++ XK_Ukrainian_IE = 0x06b4, // U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE ++ // XK_Ukranian_JE = 0x06b4, // deprecated ++ XK_Macedonia_DSE = 0x06b5, // U+0405 CYRILLIC CAPITAL LETTER DZE ++ XK_Ukrainian_I = 0x06b6, // U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I ++ // XK_Ukranian_I = 0x06b6, // deprecated ++ XK_Ukrainian_YI = 0x06b7, // U+0407 CYRILLIC CAPITAL LETTER YI ++ // XK_Ukranian_YI = 0x06b7, // deprecated ++ XK_Cyrillic_JE = 0x06b8, // U+0408 CYRILLIC CAPITAL LETTER JE ++ // XK_Serbian_JE = 0x06b8, // deprecated ++ XK_Cyrillic_LJE = 0x06b9, // U+0409 CYRILLIC CAPITAL LETTER LJE ++ // XK_Serbian_LJE = 0x06b9, // deprecated ++ XK_Cyrillic_NJE = 0x06ba, // U+040A CYRILLIC CAPITAL LETTER NJE ++ // XK_Serbian_NJE = 0x06ba, // deprecated ++ XK_Serbian_TSHE = 0x06bb, // U+040B CYRILLIC CAPITAL LETTER TSHE ++ XK_Macedonia_KJE = 0x06bc, // U+040C CYRILLIC CAPITAL LETTER KJE ++ XK_Ukrainian_GHE_WITH_UPTURN = 0x06bd, // U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN ++ XK_Byelorussian_SHORTU = 0x06be, // U+040E CYRILLIC CAPITAL LETTER SHORT U ++ XK_Cyrillic_DZHE = 0x06bf, // U+040F CYRILLIC CAPITAL LETTER DZHE ++ // XK_Serbian_DZE = 0x06bf, // deprecated ++ XK_Cyrillic_yu = 0x06c0, // U+044E CYRILLIC SMALL LETTER YU ++ XK_Cyrillic_a = 0x06c1, // U+0430 CYRILLIC SMALL LETTER A ++ XK_Cyrillic_be = 0x06c2, // U+0431 CYRILLIC SMALL LETTER BE ++ XK_Cyrillic_tse = 0x06c3, // U+0446 CYRILLIC SMALL LETTER TSE ++ XK_Cyrillic_de = 0x06c4, // U+0434 CYRILLIC SMALL LETTER DE ++ XK_Cyrillic_ie = 0x06c5, // U+0435 CYRILLIC SMALL LETTER IE ++ XK_Cyrillic_ef = 0x06c6, // U+0444 CYRILLIC SMALL LETTER EF ++ XK_Cyrillic_ghe = 0x06c7, // U+0433 CYRILLIC SMALL LETTER GHE ++ XK_Cyrillic_ha = 0x06c8, // U+0445 CYRILLIC SMALL LETTER HA ++ XK_Cyrillic_i = 0x06c9, // U+0438 CYRILLIC SMALL LETTER I ++ XK_Cyrillic_shorti = 0x06ca, // U+0439 CYRILLIC SMALL LETTER SHORT I ++ XK_Cyrillic_ka = 0x06cb, // U+043A CYRILLIC SMALL LETTER KA ++ XK_Cyrillic_el = 0x06cc, // U+043B CYRILLIC SMALL LETTER EL ++ XK_Cyrillic_em = 0x06cd, // U+043C CYRILLIC SMALL LETTER EM ++ XK_Cyrillic_en = 0x06ce, // U+043D CYRILLIC SMALL LETTER EN ++ XK_Cyrillic_o = 0x06cf, // U+043E CYRILLIC SMALL LETTER O ++ XK_Cyrillic_pe = 0x06d0, // U+043F CYRILLIC SMALL LETTER PE ++ XK_Cyrillic_ya = 0x06d1, // U+044F CYRILLIC SMALL LETTER YA ++ XK_Cyrillic_er = 0x06d2, // U+0440 CYRILLIC SMALL LETTER ER ++ XK_Cyrillic_es = 0x06d3, // U+0441 CYRILLIC SMALL LETTER ES ++ XK_Cyrillic_te = 0x06d4, // U+0442 CYRILLIC SMALL LETTER TE ++ XK_Cyrillic_u = 0x06d5, // U+0443 CYRILLIC SMALL LETTER U ++ XK_Cyrillic_zhe = 0x06d6, // U+0436 CYRILLIC SMALL LETTER ZHE ++ XK_Cyrillic_ve = 0x06d7, // U+0432 CYRILLIC SMALL LETTER VE ++ XK_Cyrillic_softsign = 0x06d8, // U+044C CYRILLIC SMALL LETTER SOFT SIGN ++ XK_Cyrillic_yeru = 0x06d9, // U+044B CYRILLIC SMALL LETTER YERU ++ XK_Cyrillic_ze = 0x06da, // U+0437 CYRILLIC SMALL LETTER ZE ++ XK_Cyrillic_sha = 0x06db, // U+0448 CYRILLIC SMALL LETTER SHA ++ XK_Cyrillic_e = 0x06dc, // U+044D CYRILLIC SMALL LETTER E ++ XK_Cyrillic_shcha = 0x06dd, // U+0449 CYRILLIC SMALL LETTER SHCHA ++ XK_Cyrillic_che = 0x06de, // U+0447 CYRILLIC SMALL LETTER CHE ++ XK_Cyrillic_hardsign = 0x06df, // U+044A CYRILLIC SMALL LETTER HARD SIGN ++ XK_Cyrillic_YU = 0x06e0, // U+042E CYRILLIC CAPITAL LETTER YU ++ XK_Cyrillic_A = 0x06e1, // U+0410 CYRILLIC CAPITAL LETTER A ++ XK_Cyrillic_BE = 0x06e2, // U+0411 CYRILLIC CAPITAL LETTER BE ++ XK_Cyrillic_TSE = 0x06e3, // U+0426 CYRILLIC CAPITAL LETTER TSE ++ XK_Cyrillic_DE = 0x06e4, // U+0414 CYRILLIC CAPITAL LETTER DE ++ XK_Cyrillic_IE = 0x06e5, // U+0415 CYRILLIC CAPITAL LETTER IE ++ XK_Cyrillic_EF = 0x06e6, // U+0424 CYRILLIC CAPITAL LETTER EF ++ XK_Cyrillic_GHE = 0x06e7, // U+0413 CYRILLIC CAPITAL LETTER GHE ++ XK_Cyrillic_HA = 0x06e8, // U+0425 CYRILLIC CAPITAL LETTER HA ++ XK_Cyrillic_I = 0x06e9, // U+0418 CYRILLIC CAPITAL LETTER I ++ XK_Cyrillic_SHORTI = 0x06ea, // U+0419 CYRILLIC CAPITAL LETTER SHORT I ++ XK_Cyrillic_KA = 0x06eb, // U+041A CYRILLIC CAPITAL LETTER KA ++ XK_Cyrillic_EL = 0x06ec, // U+041B CYRILLIC CAPITAL LETTER EL ++ XK_Cyrillic_EM = 0x06ed, // U+041C CYRILLIC CAPITAL LETTER EM ++ XK_Cyrillic_EN = 0x06ee, // U+041D CYRILLIC CAPITAL LETTER EN ++ XK_Cyrillic_O = 0x06ef, // U+041E CYRILLIC CAPITAL LETTER O ++ XK_Cyrillic_PE = 0x06f0, // U+041F CYRILLIC CAPITAL LETTER PE ++ XK_Cyrillic_YA = 0x06f1, // U+042F CYRILLIC CAPITAL LETTER YA ++ XK_Cyrillic_ER = 0x06f2, // U+0420 CYRILLIC CAPITAL LETTER ER ++ XK_Cyrillic_ES = 0x06f3, // U+0421 CYRILLIC CAPITAL LETTER ES ++ XK_Cyrillic_TE = 0x06f4, // U+0422 CYRILLIC CAPITAL LETTER TE ++ XK_Cyrillic_U = 0x06f5, // U+0423 CYRILLIC CAPITAL LETTER U ++ XK_Cyrillic_ZHE = 0x06f6, // U+0416 CYRILLIC CAPITAL LETTER ZHE ++ XK_Cyrillic_VE = 0x06f7, // U+0412 CYRILLIC CAPITAL LETTER VE ++ XK_Cyrillic_SOFTSIGN = 0x06f8, // U+042C CYRILLIC CAPITAL LETTER SOFT SIGN ++ XK_Cyrillic_YERU = 0x06f9, // U+042B CYRILLIC CAPITAL LETTER YERU ++ XK_Cyrillic_ZE = 0x06fa, // U+0417 CYRILLIC CAPITAL LETTER ZE ++ XK_Cyrillic_SHA = 0x06fb, // U+0428 CYRILLIC CAPITAL LETTER SHA ++ XK_Cyrillic_E = 0x06fc, // U+042D CYRILLIC CAPITAL LETTER E ++ XK_Cyrillic_SHCHA = 0x06fd, // U+0429 CYRILLIC CAPITAL LETTER SHCHA ++ XK_Cyrillic_CHE = 0x06fe, // U+0427 CYRILLIC CAPITAL LETTER CHE ++ XK_Cyrillic_HARDSIGN = 0x06ff, // U+042A CYRILLIC CAPITAL LETTER HARD SIGN ++ ++ XK_Greek_ALPHAaccent = 0x07a1, // U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS ++ XK_Greek_EPSILONaccent = 0x07a2, // U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS ++ XK_Greek_ETAaccent = 0x07a3, // U+0389 GREEK CAPITAL LETTER ETA WITH TONOS ++ XK_Greek_IOTAaccent = 0x07a4, // U+038A GREEK CAPITAL LETTER IOTA WITH TONOS ++ XK_Greek_IOTAdieresis = 0x07a5, // U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA ++ // XK_Greek_IOTAdiaeresis = 0x07a5, // deprecated (old typo) ++ XK_Greek_OMICRONaccent = 0x07a7, // U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS ++ XK_Greek_UPSILONaccent = 0x07a8, // U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS ++ XK_Greek_UPSILONdieresis = 0x07a9, // U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA ++ XK_Greek_OMEGAaccent = 0x07ab, // U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS ++ XK_Greek_accentdieresis = 0x07ae, // U+0385 GREEK DIALYTIKA TONOS ++ XK_Greek_horizbar = 0x07af, // U+2015 HORIZONTAL BAR ++ XK_Greek_alphaaccent = 0x07b1, // U+03AC GREEK SMALL LETTER ALPHA WITH TONOS ++ XK_Greek_epsilonaccent = 0x07b2, // U+03AD GREEK SMALL LETTER EPSILON WITH TONOS ++ XK_Greek_etaaccent = 0x07b3, // U+03AE GREEK SMALL LETTER ETA WITH TONOS ++ XK_Greek_iotaaccent = 0x07b4, // U+03AF GREEK SMALL LETTER IOTA WITH TONOS ++ XK_Greek_iotadieresis = 0x07b5, // U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA ++ XK_Greek_iotaaccentdieresis = 0x07b6, // U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS ++ XK_Greek_omicronaccent = 0x07b7, // U+03CC GREEK SMALL LETTER OMICRON WITH TONOS ++ XK_Greek_upsilonaccent = 0x07b8, // U+03CD GREEK SMALL LETTER UPSILON WITH TONOS ++ XK_Greek_upsilondieresis = 0x07b9, // U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA ++ XK_Greek_upsilonaccentdieresis = 0x07ba, // U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS ++ XK_Greek_omegaaccent = 0x07bb, // U+03CE GREEK SMALL LETTER OMEGA WITH TONOS ++ XK_Greek_ALPHA = 0x07c1, // U+0391 GREEK CAPITAL LETTER ALPHA ++ XK_Greek_BETA = 0x07c2, // U+0392 GREEK CAPITAL LETTER BETA ++ XK_Greek_GAMMA = 0x07c3, // U+0393 GREEK CAPITAL LETTER GAMMA ++ XK_Greek_DELTA = 0x07c4, // U+0394 GREEK CAPITAL LETTER DELTA ++ XK_Greek_EPSILON = 0x07c5, // U+0395 GREEK CAPITAL LETTER EPSILON ++ XK_Greek_ZETA = 0x07c6, // U+0396 GREEK CAPITAL LETTER ZETA ++ XK_Greek_ETA = 0x07c7, // U+0397 GREEK CAPITAL LETTER ETA ++ XK_Greek_THETA = 0x07c8, // U+0398 GREEK CAPITAL LETTER THETA ++ XK_Greek_IOTA = 0x07c9, // U+0399 GREEK CAPITAL LETTER IOTA ++ XK_Greek_KAPPA = 0x07ca, // U+039A GREEK CAPITAL LETTER KAPPA ++ XK_Greek_LAMDA = 0x07cb, // U+039B GREEK CAPITAL LETTER LAMDA ++ // XK_Greek_LAMBDA = 0x07cb, // non-deprecated alias for Greek_LAMDA ++ XK_Greek_MU = 0x07cc, // U+039C GREEK CAPITAL LETTER MU ++ XK_Greek_NU = 0x07cd, // U+039D GREEK CAPITAL LETTER NU ++ XK_Greek_XI = 0x07ce, // U+039E GREEK CAPITAL LETTER XI ++ XK_Greek_OMICRON = 0x07cf, // U+039F GREEK CAPITAL LETTER OMICRON ++ XK_Greek_PI = 0x07d0, // U+03A0 GREEK CAPITAL LETTER PI ++ XK_Greek_RHO = 0x07d1, // U+03A1 GREEK CAPITAL LETTER RHO ++ XK_Greek_SIGMA = 0x07d2, // U+03A3 GREEK CAPITAL LETTER SIGMA ++ XK_Greek_TAU = 0x07d4, // U+03A4 GREEK CAPITAL LETTER TAU ++ XK_Greek_UPSILON = 0x07d5, // U+03A5 GREEK CAPITAL LETTER UPSILON ++ XK_Greek_PHI = 0x07d6, // U+03A6 GREEK CAPITAL LETTER PHI ++ XK_Greek_CHI = 0x07d7, // U+03A7 GREEK CAPITAL LETTER CHI ++ XK_Greek_PSI = 0x07d8, // U+03A8 GREEK CAPITAL LETTER PSI ++ XK_Greek_OMEGA = 0x07d9, // U+03A9 GREEK CAPITAL LETTER OMEGA ++ XK_Greek_alpha = 0x07e1, // U+03B1 GREEK SMALL LETTER ALPHA ++ XK_Greek_beta = 0x07e2, // U+03B2 GREEK SMALL LETTER BETA ++ XK_Greek_gamma = 0x07e3, // U+03B3 GREEK SMALL LETTER GAMMA ++ XK_Greek_delta = 0x07e4, // U+03B4 GREEK SMALL LETTER DELTA ++ XK_Greek_epsilon = 0x07e5, // U+03B5 GREEK SMALL LETTER EPSILON ++ XK_Greek_zeta = 0x07e6, // U+03B6 GREEK SMALL LETTER ZETA ++ XK_Greek_eta = 0x07e7, // U+03B7 GREEK SMALL LETTER ETA ++ XK_Greek_theta = 0x07e8, // U+03B8 GREEK SMALL LETTER THETA ++ XK_Greek_iota = 0x07e9, // U+03B9 GREEK SMALL LETTER IOTA ++ XK_Greek_kappa = 0x07ea, // U+03BA GREEK SMALL LETTER KAPPA ++ XK_Greek_lamda = 0x07eb, // U+03BB GREEK SMALL LETTER LAMDA ++ // XK_Greek_lambda = 0x07eb, // non-deprecated alias for Greek_lamda ++ XK_Greek_mu = 0x07ec, // U+03BC GREEK SMALL LETTER MU ++ XK_Greek_nu = 0x07ed, // U+03BD GREEK SMALL LETTER NU ++ XK_Greek_xi = 0x07ee, // U+03BE GREEK SMALL LETTER XI ++ XK_Greek_omicron = 0x07ef, // U+03BF GREEK SMALL LETTER OMICRON ++ XK_Greek_pi = 0x07f0, // U+03C0 GREEK SMALL LETTER PI ++ XK_Greek_rho = 0x07f1, // U+03C1 GREEK SMALL LETTER RHO ++ XK_Greek_sigma = 0x07f2, // U+03C3 GREEK SMALL LETTER SIGMA ++ XK_Greek_finalsmallsigma = 0x07f3, // U+03C2 GREEK SMALL LETTER FINAL SIGMA ++ XK_Greek_tau = 0x07f4, // U+03C4 GREEK SMALL LETTER TAU ++ XK_Greek_upsilon = 0x07f5, // U+03C5 GREEK SMALL LETTER UPSILON ++ XK_Greek_phi = 0x07f6, // U+03C6 GREEK SMALL LETTER PHI ++ XK_Greek_chi = 0x07f7, // U+03C7 GREEK SMALL LETTER CHI ++ XK_Greek_psi = 0x07f8, // U+03C8 GREEK SMALL LETTER PSI ++ XK_Greek_omega = 0x07f9, // U+03C9 GREEK SMALL LETTER OMEGA ++ // XK_Greek_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ ++ XK_leftradical = 0x08a1, // U+23B7 RADICAL SYMBOL BOTTOM ++ XK_topleftradical = 0x08a2, // (U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT) ++ XK_horizconnector = 0x08a3, // (U+2500 BOX DRAWINGS LIGHT HORIZONTAL) ++ XK_topintegral = 0x08a4, // U+2320 TOP HALF INTEGRAL ++ XK_botintegral = 0x08a5, // U+2321 BOTTOM HALF INTEGRAL ++ XK_vertconnector = 0x08a6, // (U+2502 BOX DRAWINGS LIGHT VERTICAL) ++ XK_topleftsqbracket = 0x08a7, // U+23A1 LEFT SQUARE BRACKET UPPER CORNER ++ XK_botleftsqbracket = 0x08a8, // U+23A3 LEFT SQUARE BRACKET LOWER CORNER ++ XK_toprightsqbracket = 0x08a9, // U+23A4 RIGHT SQUARE BRACKET UPPER CORNER ++ XK_botrightsqbracket = 0x08aa, // U+23A6 RIGHT SQUARE BRACKET LOWER CORNER ++ XK_topleftparens = 0x08ab, // U+239B LEFT PARENTHESIS UPPER HOOK ++ XK_botleftparens = 0x08ac, // U+239D LEFT PARENTHESIS LOWER HOOK ++ XK_toprightparens = 0x08ad, // U+239E RIGHT PARENTHESIS UPPER HOOK ++ XK_botrightparens = 0x08ae, // U+23A0 RIGHT PARENTHESIS LOWER HOOK ++ XK_leftmiddlecurlybrace = 0x08af, // U+23A8 LEFT CURLY BRACKET MIDDLE PIECE ++ XK_rightmiddlecurlybrace = 0x08b0, // U+23AC RIGHT CURLY BRACKET MIDDLE PIECE ++ XK_topleftsummation = 0x08b1, ++ XK_botleftsummation = 0x08b2, ++ XK_topvertsummationconnector = 0x08b3, ++ XK_botvertsummationconnector = 0x08b4, ++ XK_toprightsummation = 0x08b5, ++ XK_botrightsummation = 0x08b6, ++ XK_rightmiddlesummation = 0x08b7, ++ XK_lessthanequal = 0x08bc, // U+2264 LESS-THAN OR EQUAL TO ++ XK_notequal = 0x08bd, // U+2260 NOT EQUAL TO ++ XK_greaterthanequal = 0x08be, // U+2265 GREATER-THAN OR EQUAL TO ++ XK_integral = 0x08bf, // U+222B INTEGRAL ++ XK_therefore = 0x08c0, // U+2234 THEREFORE ++ XK_variation = 0x08c1, // U+221D PROPORTIONAL TO ++ XK_infinity = 0x08c2, // U+221E INFINITY ++ XK_nabla = 0x08c5, // U+2207 NABLA ++ XK_approximate = 0x08c8, // U+223C TILDE OPERATOR ++ XK_similarequal = 0x08c9, // U+2243 ASYMPTOTICALLY EQUAL TO ++ XK_ifonlyif = 0x08cd, // U+21D4 LEFT RIGHT DOUBLE ARROW ++ XK_implies = 0x08ce, // U+21D2 RIGHTWARDS DOUBLE ARROW ++ XK_identical = 0x08cf, // U+2261 IDENTICAL TO ++ XK_radical = 0x08d6, // U+221A SQUARE ROOT ++ XK_includedin = 0x08da, // U+2282 SUBSET OF ++ XK_includes = 0x08db, // U+2283 SUPERSET OF ++ XK_intersection = 0x08dc, // U+2229 INTERSECTION ++ XK_union = 0x08dd, // U+222A UNION ++ XK_logicaland = 0x08de, // U+2227 LOGICAL AND ++ XK_logicalor = 0x08df, // U+2228 LOGICAL OR ++ XK_partialderivative = 0x08ef, // U+2202 PARTIAL DIFFERENTIAL ++ XK_function = 0x08f6, // U+0192 LATIN SMALL LETTER F WITH HOOK ++ XK_leftarrow = 0x08fb, // U+2190 LEFTWARDS ARROW ++ XK_uparrow = 0x08fc, // U+2191 UPWARDS ARROW ++ XK_rightarrow = 0x08fd, // U+2192 RIGHTWARDS ARROW ++ XK_downarrow = 0x08fe, // U+2193 DOWNWARDS ARROW ++ ++ XK_blank = 0x09df, ++ XK_soliddiamond = 0x09e0, // U+25C6 BLACK DIAMOND ++ XK_checkerboard = 0x09e1, // U+2592 MEDIUM SHADE ++ XK_ht = 0x09e2, // U+2409 SYMBOL FOR HORIZONTAL TABULATION ++ XK_ff = 0x09e3, // U+240C SYMBOL FOR FORM FEED ++ XK_cr = 0x09e4, // U+240D SYMBOL FOR CARRIAGE RETURN ++ XK_lf = 0x09e5, // U+240A SYMBOL FOR LINE FEED ++ XK_nl = 0x09e8, // U+2424 SYMBOL FOR NEWLINE ++ XK_vt = 0x09e9, // U+240B SYMBOL FOR VERTICAL TABULATION ++ XK_lowrightcorner = 0x09ea, // U+2518 BOX DRAWINGS LIGHT UP AND LEFT ++ XK_uprightcorner = 0x09eb, // U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT ++ XK_upleftcorner = 0x09ec, // U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT ++ XK_lowleftcorner = 0x09ed, // U+2514 BOX DRAWINGS LIGHT UP AND RIGHT ++ XK_crossinglines = 0x09ee, // U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL ++ XK_horizlinescan1 = 0x09ef, // U+23BA HORIZONTAL SCAN LINE-1 ++ XK_horizlinescan3 = 0x09f0, // U+23BB HORIZONTAL SCAN LINE-3 ++ XK_horizlinescan5 = 0x09f1, // U+2500 BOX DRAWINGS LIGHT HORIZONTAL ++ XK_horizlinescan7 = 0x09f2, // U+23BC HORIZONTAL SCAN LINE-7 ++ XK_horizlinescan9 = 0x09f3, // U+23BD HORIZONTAL SCAN LINE-9 ++ XK_leftt = 0x09f4, // U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT ++ XK_rightt = 0x09f5, // U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT ++ XK_bott = 0x09f6, // U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL ++ XK_topt = 0x09f7, // U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL ++ XK_vertbar = 0x09f8, // U+2502 BOX DRAWINGS LIGHT VERTICAL ++ ++ XK_emspace = 0x0aa1, // U+2003 EM SPACE ++ XK_enspace = 0x0aa2, // U+2002 EN SPACE ++ XK_em3space = 0x0aa3, // U+2004 THREE-PER-EM SPACE ++ XK_em4space = 0x0aa4, // U+2005 FOUR-PER-EM SPACE ++ XK_digitspace = 0x0aa5, // U+2007 FIGURE SPACE ++ XK_punctspace = 0x0aa6, // U+2008 PUNCTUATION SPACE ++ XK_thinspace = 0x0aa7, // U+2009 THIN SPACE ++ XK_hairspace = 0x0aa8, // U+200A HAIR SPACE ++ XK_emdash = 0x0aa9, // U+2014 EM DASH ++ XK_endash = 0x0aaa, // U+2013 EN DASH ++ XK_signifblank = 0x0aac, // (U+2423 OPEN BOX) ++ XK_ellipsis = 0x0aae, // U+2026 HORIZONTAL ELLIPSIS ++ XK_doubbaselinedot = 0x0aaf, // U+2025 TWO DOT LEADER ++ XK_onethird = 0x0ab0, // U+2153 VULGAR FRACTION ONE THIRD ++ XK_twothirds = 0x0ab1, // U+2154 VULGAR FRACTION TWO THIRDS ++ XK_onefifth = 0x0ab2, // U+2155 VULGAR FRACTION ONE FIFTH ++ XK_twofifths = 0x0ab3, // U+2156 VULGAR FRACTION TWO FIFTHS ++ XK_threefifths = 0x0ab4, // U+2157 VULGAR FRACTION THREE FIFTHS ++ XK_fourfifths = 0x0ab5, // U+2158 VULGAR FRACTION FOUR FIFTHS ++ XK_onesixth = 0x0ab6, // U+2159 VULGAR FRACTION ONE SIXTH ++ XK_fivesixths = 0x0ab7, // U+215A VULGAR FRACTION FIVE SIXTHS ++ XK_careof = 0x0ab8, // U+2105 CARE OF ++ XK_figdash = 0x0abb, // U+2012 FIGURE DASH ++ XK_leftanglebracket = 0x0abc, // (U+2329 LEFT-POINTING ANGLE BRACKET) ++ XK_decimalpoint = 0x0abd, // (U+002E FULL STOP) ++ XK_rightanglebracket = 0x0abe, // (U+232A RIGHT-POINTING ANGLE BRACKET) ++ XK_marker = 0x0abf, ++ XK_oneeighth = 0x0ac3, // U+215B VULGAR FRACTION ONE EIGHTH ++ XK_threeeighths = 0x0ac4, // U+215C VULGAR FRACTION THREE EIGHTHS ++ XK_fiveeighths = 0x0ac5, // U+215D VULGAR FRACTION FIVE EIGHTHS ++ XK_seveneighths = 0x0ac6, // U+215E VULGAR FRACTION SEVEN EIGHTHS ++ XK_trademark = 0x0ac9, // U+2122 TRADE MARK SIGN ++ XK_signaturemark = 0x0aca, // (U+2613 SALTIRE) ++ XK_trademarkincircle = 0x0acb, ++ XK_leftopentriangle = 0x0acc, // (U+25C1 WHITE LEFT-POINTING TRIANGLE) ++ XK_rightopentriangle = 0x0acd, // (U+25B7 WHITE RIGHT-POINTING TRIANGLE) ++ XK_emopencircle = 0x0ace, // (U+25CB WHITE CIRCLE) ++ XK_emopenrectangle = 0x0acf, // (U+25AF WHITE VERTICAL RECTANGLE) ++ XK_leftsinglequotemark = 0x0ad0, // U+2018 LEFT SINGLE QUOTATION MARK ++ XK_rightsinglequotemark = 0x0ad1, // U+2019 RIGHT SINGLE QUOTATION MARK ++ XK_leftdoublequotemark = 0x0ad2, // U+201C LEFT DOUBLE QUOTATION MARK ++ XK_rightdoublequotemark = 0x0ad3, // U+201D RIGHT DOUBLE QUOTATION MARK ++ XK_prescription = 0x0ad4, // U+211E PRESCRIPTION TAKE ++ XK_permille = 0x0ad5, // U+2030 PER MILLE SIGN ++ XK_minutes = 0x0ad6, // U+2032 PRIME ++ XK_seconds = 0x0ad7, // U+2033 DOUBLE PRIME ++ XK_latincross = 0x0ad9, // U+271D LATIN CROSS ++ XK_hexagram = 0x0ada, ++ XK_filledrectbullet = 0x0adb, // (U+25AC BLACK RECTANGLE) ++ XK_filledlefttribullet = 0x0adc, // (U+25C0 BLACK LEFT-POINTING TRIANGLE) ++ XK_filledrighttribullet = 0x0add, // (U+25B6 BLACK RIGHT-POINTING TRIANGLE) ++ XK_emfilledcircle = 0x0ade, // (U+25CF BLACK CIRCLE) ++ XK_emfilledrect = 0x0adf, // (U+25AE BLACK VERTICAL RECTANGLE) ++ XK_enopencircbullet = 0x0ae0, // (U+25E6 WHITE BULLET) ++ XK_enopensquarebullet = 0x0ae1, // (U+25AB WHITE SMALL SQUARE) ++ XK_openrectbullet = 0x0ae2, // (U+25AD WHITE RECTANGLE) ++ XK_opentribulletup = 0x0ae3, // (U+25B3 WHITE UP-POINTING TRIANGLE) ++ XK_opentribulletdown = 0x0ae4, // (U+25BD WHITE DOWN-POINTING TRIANGLE) ++ XK_openstar = 0x0ae5, // (U+2606 WHITE STAR) ++ XK_enfilledcircbullet = 0x0ae6, // (U+2022 BULLET) ++ XK_enfilledsqbullet = 0x0ae7, // (U+25AA BLACK SMALL SQUARE) ++ XK_filledtribulletup = 0x0ae8, // (U+25B2 BLACK UP-POINTING TRIANGLE) ++ XK_filledtribulletdown = 0x0ae9, // (U+25BC BLACK DOWN-POINTING TRIANGLE) ++ XK_leftpointer = 0x0aea, // (U+261C WHITE LEFT POINTING INDEX) ++ XK_rightpointer = 0x0aeb, // (U+261E WHITE RIGHT POINTING INDEX) ++ XK_club = 0x0aec, // U+2663 BLACK CLUB SUIT ++ XK_diamond = 0x0aed, // U+2666 BLACK DIAMOND SUIT ++ XK_heart = 0x0aee, // U+2665 BLACK HEART SUIT ++ XK_maltesecross = 0x0af0, // U+2720 MALTESE CROSS ++ XK_dagger = 0x0af1, // U+2020 DAGGER ++ XK_doubledagger = 0x0af2, // U+2021 DOUBLE DAGGER ++ XK_checkmark = 0x0af3, // U+2713 CHECK MARK ++ XK_ballotcross = 0x0af4, // U+2717 BALLOT X ++ XK_musicalsharp = 0x0af5, // U+266F MUSIC SHARP SIGN ++ XK_musicalflat = 0x0af6, // U+266D MUSIC FLAT SIGN ++ XK_malesymbol = 0x0af7, // U+2642 MALE SIGN ++ XK_femalesymbol = 0x0af8, // U+2640 FEMALE SIGN ++ XK_telephone = 0x0af9, // U+260E BLACK TELEPHONE ++ XK_telephonerecorder = 0x0afa, // U+2315 TELEPHONE RECORDER ++ XK_phonographcopyright = 0x0afb, // U+2117 SOUND RECORDING COPYRIGHT ++ XK_caret = 0x0afc, // U+2038 CARET ++ XK_singlelowquotemark = 0x0afd, // U+201A SINGLE LOW-9 QUOTATION MARK ++ XK_doublelowquotemark = 0x0afe, // U+201E DOUBLE LOW-9 QUOTATION MARK ++ XK_cursor = 0x0aff, ++ ++ XK_leftcaret = 0x0ba3, // (U+003C LESS-THAN SIGN) ++ XK_rightcaret = 0x0ba6, // (U+003E GREATER-THAN SIGN) ++ XK_downcaret = 0x0ba8, // (U+2228 LOGICAL OR) ++ XK_upcaret = 0x0ba9, // (U+2227 LOGICAL AND) ++ XK_overbar = 0x0bc0, // (U+00AF MACRON) ++ XK_downtack = 0x0bc2, // U+22A4 DOWN TACK ++ XK_upshoe = 0x0bc3, // (U+2229 INTERSECTION) ++ XK_downstile = 0x0bc4, // U+230A LEFT FLOOR ++ XK_underbar = 0x0bc6, // (U+005F LOW LINE) ++ XK_jot = 0x0bca, // U+2218 RING OPERATOR ++ XK_quad = 0x0bcc, // U+2395 APL FUNCTIONAL SYMBOL QUAD ++ XK_uptack = 0x0bce, // U+22A5 UP TACK ++ XK_circle = 0x0bcf, // U+25CB WHITE CIRCLE ++ XK_upstile = 0x0bd3, // U+2308 LEFT CEILING ++ XK_downshoe = 0x0bd6, // (U+222A UNION) ++ XK_rightshoe = 0x0bd8, // (U+2283 SUPERSET OF) ++ XK_leftshoe = 0x0bda, // (U+2282 SUBSET OF) ++ XK_lefttack = 0x0bdc, // U+22A3 LEFT TACK ++ XK_righttack = 0x0bfc, // U+22A2 RIGHT TACK ++ ++ XK_hebrew_doublelowline = 0x0cdf, // U+2017 DOUBLE LOW LINE ++ XK_hebrew_aleph = 0x0ce0, // U+05D0 HEBREW LETTER ALEF ++ XK_hebrew_bet = 0x0ce1, // U+05D1 HEBREW LETTER BET ++ // XK_hebrew_beth = 0x0ce1, // deprecated ++ XK_hebrew_gimel = 0x0ce2, // U+05D2 HEBREW LETTER GIMEL ++ // XK_hebrew_gimmel = 0x0ce2, // deprecated ++ XK_hebrew_dalet = 0x0ce3, // U+05D3 HEBREW LETTER DALET ++ // XK_hebrew_daleth = 0x0ce3, // deprecated ++ XK_hebrew_he = 0x0ce4, // U+05D4 HEBREW LETTER HE ++ XK_hebrew_waw = 0x0ce5, // U+05D5 HEBREW LETTER VAV ++ XK_hebrew_zain = 0x0ce6, // U+05D6 HEBREW LETTER ZAYIN ++ // XK_hebrew_zayin = 0x0ce6, // deprecated ++ XK_hebrew_chet = 0x0ce7, // U+05D7 HEBREW LETTER HET ++ // XK_hebrew_het = 0x0ce7, // deprecated ++ XK_hebrew_tet = 0x0ce8, // U+05D8 HEBREW LETTER TET ++ // XK_hebrew_teth = 0x0ce8, // deprecated ++ XK_hebrew_yod = 0x0ce9, // U+05D9 HEBREW LETTER YOD ++ XK_hebrew_finalkaph = 0x0cea, // U+05DA HEBREW LETTER FINAL KAF ++ XK_hebrew_kaph = 0x0ceb, // U+05DB HEBREW LETTER KAF ++ XK_hebrew_lamed = 0x0cec, // U+05DC HEBREW LETTER LAMED ++ XK_hebrew_finalmem = 0x0ced, // U+05DD HEBREW LETTER FINAL MEM ++ XK_hebrew_mem = 0x0cee, // U+05DE HEBREW LETTER MEM ++ XK_hebrew_finalnun = 0x0cef, // U+05DF HEBREW LETTER FINAL NUN ++ XK_hebrew_nun = 0x0cf0, // U+05E0 HEBREW LETTER NUN ++ XK_hebrew_samech = 0x0cf1, // U+05E1 HEBREW LETTER SAMEKH ++ // XK_hebrew_samekh = 0x0cf1, // deprecated ++ XK_hebrew_ayin = 0x0cf2, // U+05E2 HEBREW LETTER AYIN ++ XK_hebrew_finalpe = 0x0cf3, // U+05E3 HEBREW LETTER FINAL PE ++ XK_hebrew_pe = 0x0cf4, // U+05E4 HEBREW LETTER PE ++ XK_hebrew_finalzade = 0x0cf5, // U+05E5 HEBREW LETTER FINAL TSADI ++ // XK_hebrew_finalzadi = 0x0cf5, // deprecated ++ XK_hebrew_zade = 0x0cf6, // U+05E6 HEBREW LETTER TSADI ++ // XK_hebrew_zadi = 0x0cf6, // deprecated ++ XK_hebrew_qoph = 0x0cf7, // U+05E7 HEBREW LETTER QOF ++ // XK_hebrew_kuf = 0x0cf7, // deprecated ++ XK_hebrew_resh = 0x0cf8, // U+05E8 HEBREW LETTER RESH ++ XK_hebrew_shin = 0x0cf9, // U+05E9 HEBREW LETTER SHIN ++ XK_hebrew_taw = 0x0cfa, // U+05EA HEBREW LETTER TAV ++ // XK_hebrew_taf = 0x0cfa, // deprecated ++ // XK_Hebrew_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ ++ XK_Thai_kokai = 0x0da1, // U+0E01 THAI CHARACTER KO KAI ++ XK_Thai_khokhai = 0x0da2, // U+0E02 THAI CHARACTER KHO KHAI ++ XK_Thai_khokhuat = 0x0da3, // U+0E03 THAI CHARACTER KHO KHUAT ++ XK_Thai_khokhwai = 0x0da4, // U+0E04 THAI CHARACTER KHO KHWAI ++ XK_Thai_khokhon = 0x0da5, // U+0E05 THAI CHARACTER KHO KHON ++ XK_Thai_khorakhang = 0x0da6, // U+0E06 THAI CHARACTER KHO RAKHANG ++ XK_Thai_ngongu = 0x0da7, // U+0E07 THAI CHARACTER NGO NGU ++ XK_Thai_chochan = 0x0da8, // U+0E08 THAI CHARACTER CHO CHAN ++ XK_Thai_choching = 0x0da9, // U+0E09 THAI CHARACTER CHO CHING ++ XK_Thai_chochang = 0x0daa, // U+0E0A THAI CHARACTER CHO CHANG ++ XK_Thai_soso = 0x0dab, // U+0E0B THAI CHARACTER SO SO ++ XK_Thai_chochoe = 0x0dac, // U+0E0C THAI CHARACTER CHO CHOE ++ XK_Thai_yoying = 0x0dad, // U+0E0D THAI CHARACTER YO YING ++ XK_Thai_dochada = 0x0dae, // U+0E0E THAI CHARACTER DO CHADA ++ XK_Thai_topatak = 0x0daf, // U+0E0F THAI CHARACTER TO PATAK ++ XK_Thai_thothan = 0x0db0, // U+0E10 THAI CHARACTER THO THAN ++ XK_Thai_thonangmontho = 0x0db1, // U+0E11 THAI CHARACTER THO NANGMONTHO ++ XK_Thai_thophuthao = 0x0db2, // U+0E12 THAI CHARACTER THO PHUTHAO ++ XK_Thai_nonen = 0x0db3, // U+0E13 THAI CHARACTER NO NEN ++ XK_Thai_dodek = 0x0db4, // U+0E14 THAI CHARACTER DO DEK ++ XK_Thai_totao = 0x0db5, // U+0E15 THAI CHARACTER TO TAO ++ XK_Thai_thothung = 0x0db6, // U+0E16 THAI CHARACTER THO THUNG ++ XK_Thai_thothahan = 0x0db7, // U+0E17 THAI CHARACTER THO THAHAN ++ XK_Thai_thothong = 0x0db8, // U+0E18 THAI CHARACTER THO THONG ++ XK_Thai_nonu = 0x0db9, // U+0E19 THAI CHARACTER NO NU ++ XK_Thai_bobaimai = 0x0dba, // U+0E1A THAI CHARACTER BO BAIMAI ++ XK_Thai_popla = 0x0dbb, // U+0E1B THAI CHARACTER PO PLA ++ XK_Thai_phophung = 0x0dbc, // U+0E1C THAI CHARACTER PHO PHUNG ++ XK_Thai_fofa = 0x0dbd, // U+0E1D THAI CHARACTER FO FA ++ XK_Thai_phophan = 0x0dbe, // U+0E1E THAI CHARACTER PHO PHAN ++ XK_Thai_fofan = 0x0dbf, // U+0E1F THAI CHARACTER FO FAN ++ XK_Thai_phosamphao = 0x0dc0, // U+0E20 THAI CHARACTER PHO SAMPHAO ++ XK_Thai_moma = 0x0dc1, // U+0E21 THAI CHARACTER MO MA ++ XK_Thai_yoyak = 0x0dc2, // U+0E22 THAI CHARACTER YO YAK ++ XK_Thai_rorua = 0x0dc3, // U+0E23 THAI CHARACTER RO RUA ++ XK_Thai_ru = 0x0dc4, // U+0E24 THAI CHARACTER RU ++ XK_Thai_loling = 0x0dc5, // U+0E25 THAI CHARACTER LO LING ++ XK_Thai_lu = 0x0dc6, // U+0E26 THAI CHARACTER LU ++ XK_Thai_wowaen = 0x0dc7, // U+0E27 THAI CHARACTER WO WAEN ++ XK_Thai_sosala = 0x0dc8, // U+0E28 THAI CHARACTER SO SALA ++ XK_Thai_sorusi = 0x0dc9, // U+0E29 THAI CHARACTER SO RUSI ++ XK_Thai_sosua = 0x0dca, // U+0E2A THAI CHARACTER SO SUA ++ XK_Thai_hohip = 0x0dcb, // U+0E2B THAI CHARACTER HO HIP ++ XK_Thai_lochula = 0x0dcc, // U+0E2C THAI CHARACTER LO CHULA ++ XK_Thai_oang = 0x0dcd, // U+0E2D THAI CHARACTER O ANG ++ XK_Thai_honokhuk = 0x0dce, // U+0E2E THAI CHARACTER HO NOKHUK ++ XK_Thai_paiyannoi = 0x0dcf, // U+0E2F THAI CHARACTER PAIYANNOI ++ XK_Thai_saraa = 0x0dd0, // U+0E30 THAI CHARACTER SARA A ++ XK_Thai_maihanakat = 0x0dd1, // U+0E31 THAI CHARACTER MAI HAN-AKAT ++ XK_Thai_saraaa = 0x0dd2, // U+0E32 THAI CHARACTER SARA AA ++ XK_Thai_saraam = 0x0dd3, // U+0E33 THAI CHARACTER SARA AM ++ XK_Thai_sarai = 0x0dd4, // U+0E34 THAI CHARACTER SARA I ++ XK_Thai_saraii = 0x0dd5, // U+0E35 THAI CHARACTER SARA II ++ XK_Thai_saraue = 0x0dd6, // U+0E36 THAI CHARACTER SARA UE ++ XK_Thai_sarauee = 0x0dd7, // U+0E37 THAI CHARACTER SARA UEE ++ XK_Thai_sarau = 0x0dd8, // U+0E38 THAI CHARACTER SARA U ++ XK_Thai_sarauu = 0x0dd9, // U+0E39 THAI CHARACTER SARA UU ++ XK_Thai_phinthu = 0x0dda, // U+0E3A THAI CHARACTER PHINTHU ++ XK_Thai_maihanakat_maitho = 0x0dde, // (U+0E3E Unassigned code point) ++ XK_Thai_baht = 0x0ddf, // U+0E3F THAI CURRENCY SYMBOL BAHT ++ XK_Thai_sarae = 0x0de0, // U+0E40 THAI CHARACTER SARA E ++ XK_Thai_saraae = 0x0de1, // U+0E41 THAI CHARACTER SARA AE ++ XK_Thai_sarao = 0x0de2, // U+0E42 THAI CHARACTER SARA O ++ XK_Thai_saraaimaimuan = 0x0de3, // U+0E43 THAI CHARACTER SARA AI MAIMUAN ++ XK_Thai_saraaimaimalai = 0x0de4, // U+0E44 THAI CHARACTER SARA AI MAIMALAI ++ XK_Thai_lakkhangyao = 0x0de5, // U+0E45 THAI CHARACTER LAKKHANGYAO ++ XK_Thai_maiyamok = 0x0de6, // U+0E46 THAI CHARACTER MAIYAMOK ++ XK_Thai_maitaikhu = 0x0de7, // U+0E47 THAI CHARACTER MAITAIKHU ++ XK_Thai_maiek = 0x0de8, // U+0E48 THAI CHARACTER MAI EK ++ XK_Thai_maitho = 0x0de9, // U+0E49 THAI CHARACTER MAI THO ++ XK_Thai_maitri = 0x0dea, // U+0E4A THAI CHARACTER MAI TRI ++ XK_Thai_maichattawa = 0x0deb, // U+0E4B THAI CHARACTER MAI CHATTAWA ++ XK_Thai_thanthakhat = 0x0dec, // U+0E4C THAI CHARACTER THANTHAKHAT ++ XK_Thai_nikhahit = 0x0ded, // U+0E4D THAI CHARACTER NIKHAHIT ++ XK_Thai_leksun = 0x0df0, // U+0E50 THAI DIGIT ZERO ++ XK_Thai_leknung = 0x0df1, // U+0E51 THAI DIGIT ONE ++ XK_Thai_leksong = 0x0df2, // U+0E52 THAI DIGIT TWO ++ XK_Thai_leksam = 0x0df3, // U+0E53 THAI DIGIT THREE ++ XK_Thai_leksi = 0x0df4, // U+0E54 THAI DIGIT FOUR ++ XK_Thai_lekha = 0x0df5, // U+0E55 THAI DIGIT FIVE ++ XK_Thai_lekhok = 0x0df6, // U+0E56 THAI DIGIT SIX ++ XK_Thai_lekchet = 0x0df7, // U+0E57 THAI DIGIT SEVEN ++ XK_Thai_lekpaet = 0x0df8, // U+0E58 THAI DIGIT EIGHT ++ XK_Thai_lekkao = 0x0df9, // U+0E59 THAI DIGIT NINE ++ ++ XK_Hangul = 0xff31, // Hangul start/stop(toggle) ++ XK_Hangul_Start = 0xff32, // Hangul start ++ XK_Hangul_End = 0xff33, // Hangul end, English start ++ XK_Hangul_Hanja = 0xff34, // Start Hangul->Hanja Conversion ++ XK_Hangul_Jamo = 0xff35, // Hangul Jamo mode ++ XK_Hangul_Romaja = 0xff36, // Hangul Romaja mode ++ // XK_Hangul_Codeinput = 0xff37, // Hangul code input mode ++ XK_Hangul_Jeonja = 0xff38, // Jeonja mode ++ XK_Hangul_Banja = 0xff39, // Banja mode ++ XK_Hangul_PreHanja = 0xff3a, // Pre Hanja conversion ++ XK_Hangul_PostHanja = 0xff3b, // Post Hanja conversion ++ // XK_Hangul_SingleCandidate = 0xff3c, // Single candidate ++ // XK_Hangul_MultipleCandidate = 0xff3d, // Multiple candidate ++ // XK_Hangul_PreviousCandidate = 0xff3e, // Previous candidate ++ XK_Hangul_Special = 0xff3f, // Special symbols ++ // XK_Hangul_switch = 0xff7e, // non-deprecated alias for Mode_switch ++ XK_Hangul_Kiyeog = 0x0ea1, // U+3131 HANGUL LETTER KIYEOK ++ XK_Hangul_SsangKiyeog = 0x0ea2, // U+3132 HANGUL LETTER SSANGKIYEOK ++ XK_Hangul_KiyeogSios = 0x0ea3, // U+3133 HANGUL LETTER KIYEOK-SIOS ++ XK_Hangul_Nieun = 0x0ea4, // U+3134 HANGUL LETTER NIEUN ++ XK_Hangul_NieunJieuj = 0x0ea5, // U+3135 HANGUL LETTER NIEUN-CIEUC ++ XK_Hangul_NieunHieuh = 0x0ea6, // U+3136 HANGUL LETTER NIEUN-HIEUH ++ XK_Hangul_Dikeud = 0x0ea7, // U+3137 HANGUL LETTER TIKEUT ++ XK_Hangul_SsangDikeud = 0x0ea8, // U+3138 HANGUL LETTER SSANGTIKEUT ++ XK_Hangul_Rieul = 0x0ea9, // U+3139 HANGUL LETTER RIEUL ++ XK_Hangul_RieulKiyeog = 0x0eaa, // U+313A HANGUL LETTER RIEUL-KIYEOK ++ XK_Hangul_RieulMieum = 0x0eab, // U+313B HANGUL LETTER RIEUL-MIEUM ++ XK_Hangul_RieulPieub = 0x0eac, // U+313C HANGUL LETTER RIEUL-PIEUP ++ XK_Hangul_RieulSios = 0x0ead, // U+313D HANGUL LETTER RIEUL-SIOS ++ XK_Hangul_RieulTieut = 0x0eae, // U+313E HANGUL LETTER RIEUL-THIEUTH ++ XK_Hangul_RieulPhieuf = 0x0eaf, // U+313F HANGUL LETTER RIEUL-PHIEUPH ++ XK_Hangul_RieulHieuh = 0x0eb0, // U+3140 HANGUL LETTER RIEUL-HIEUH ++ XK_Hangul_Mieum = 0x0eb1, // U+3141 HANGUL LETTER MIEUM ++ XK_Hangul_Pieub = 0x0eb2, // U+3142 HANGUL LETTER PIEUP ++ XK_Hangul_SsangPieub = 0x0eb3, // U+3143 HANGUL LETTER SSANGPIEUP ++ XK_Hangul_PieubSios = 0x0eb4, // U+3144 HANGUL LETTER PIEUP-SIOS ++ XK_Hangul_Sios = 0x0eb5, // U+3145 HANGUL LETTER SIOS ++ XK_Hangul_SsangSios = 0x0eb6, // U+3146 HANGUL LETTER SSANGSIOS ++ XK_Hangul_Ieung = 0x0eb7, // U+3147 HANGUL LETTER IEUNG ++ XK_Hangul_Jieuj = 0x0eb8, // U+3148 HANGUL LETTER CIEUC ++ XK_Hangul_SsangJieuj = 0x0eb9, // U+3149 HANGUL LETTER SSANGCIEUC ++ XK_Hangul_Cieuc = 0x0eba, // U+314A HANGUL LETTER CHIEUCH ++ XK_Hangul_Khieuq = 0x0ebb, // U+314B HANGUL LETTER KHIEUKH ++ XK_Hangul_Tieut = 0x0ebc, // U+314C HANGUL LETTER THIEUTH ++ XK_Hangul_Phieuf = 0x0ebd, // U+314D HANGUL LETTER PHIEUPH ++ XK_Hangul_Hieuh = 0x0ebe, // U+314E HANGUL LETTER HIEUH ++ XK_Hangul_A = 0x0ebf, // U+314F HANGUL LETTER A ++ XK_Hangul_AE = 0x0ec0, // U+3150 HANGUL LETTER AE ++ XK_Hangul_YA = 0x0ec1, // U+3151 HANGUL LETTER YA ++ XK_Hangul_YAE = 0x0ec2, // U+3152 HANGUL LETTER YAE ++ XK_Hangul_EO = 0x0ec3, // U+3153 HANGUL LETTER EO ++ XK_Hangul_E = 0x0ec4, // U+3154 HANGUL LETTER E ++ XK_Hangul_YEO = 0x0ec5, // U+3155 HANGUL LETTER YEO ++ XK_Hangul_YE = 0x0ec6, // U+3156 HANGUL LETTER YE ++ XK_Hangul_O = 0x0ec7, // U+3157 HANGUL LETTER O ++ XK_Hangul_WA = 0x0ec8, // U+3158 HANGUL LETTER WA ++ XK_Hangul_WAE = 0x0ec9, // U+3159 HANGUL LETTER WAE ++ XK_Hangul_OE = 0x0eca, // U+315A HANGUL LETTER OE ++ XK_Hangul_YO = 0x0ecb, // U+315B HANGUL LETTER YO ++ XK_Hangul_U = 0x0ecc, // U+315C HANGUL LETTER U ++ XK_Hangul_WEO = 0x0ecd, // U+315D HANGUL LETTER WEO ++ XK_Hangul_WE = 0x0ece, // U+315E HANGUL LETTER WE ++ XK_Hangul_WI = 0x0ecf, // U+315F HANGUL LETTER WI ++ XK_Hangul_YU = 0x0ed0, // U+3160 HANGUL LETTER YU ++ XK_Hangul_EU = 0x0ed1, // U+3161 HANGUL LETTER EU ++ XK_Hangul_YI = 0x0ed2, // U+3162 HANGUL LETTER YI ++ XK_Hangul_I = 0x0ed3, // U+3163 HANGUL LETTER I ++ XK_Hangul_J_Kiyeog = 0x0ed4, // U+11A8 HANGUL JONGSEONG KIYEOK ++ XK_Hangul_J_SsangKiyeog = 0x0ed5, // U+11A9 HANGUL JONGSEONG SSANGKIYEOK ++ XK_Hangul_J_KiyeogSios = 0x0ed6, // U+11AA HANGUL JONGSEONG KIYEOK-SIOS ++ XK_Hangul_J_Nieun = 0x0ed7, // U+11AB HANGUL JONGSEONG NIEUN ++ XK_Hangul_J_NieunJieuj = 0x0ed8, // U+11AC HANGUL JONGSEONG NIEUN-CIEUC ++ XK_Hangul_J_NieunHieuh = 0x0ed9, // U+11AD HANGUL JONGSEONG NIEUN-HIEUH ++ XK_Hangul_J_Dikeud = 0x0eda, // U+11AE HANGUL JONGSEONG TIKEUT ++ XK_Hangul_J_Rieul = 0x0edb, // U+11AF HANGUL JONGSEONG RIEUL ++ XK_Hangul_J_RieulKiyeog = 0x0edc, // U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK ++ XK_Hangul_J_RieulMieum = 0x0edd, // U+11B1 HANGUL JONGSEONG RIEUL-MIEUM ++ XK_Hangul_J_RieulPieub = 0x0ede, // U+11B2 HANGUL JONGSEONG RIEUL-PIEUP ++ XK_Hangul_J_RieulSios = 0x0edf, // U+11B3 HANGUL JONGSEONG RIEUL-SIOS ++ XK_Hangul_J_RieulTieut = 0x0ee0, // U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH ++ XK_Hangul_J_RieulPhieuf = 0x0ee1, // U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH ++ XK_Hangul_J_RieulHieuh = 0x0ee2, // U+11B6 HANGUL JONGSEONG RIEUL-HIEUH ++ XK_Hangul_J_Mieum = 0x0ee3, // U+11B7 HANGUL JONGSEONG MIEUM ++ XK_Hangul_J_Pieub = 0x0ee4, // U+11B8 HANGUL JONGSEONG PIEUP ++ XK_Hangul_J_PieubSios = 0x0ee5, // U+11B9 HANGUL JONGSEONG PIEUP-SIOS ++ XK_Hangul_J_Sios = 0x0ee6, // U+11BA HANGUL JONGSEONG SIOS ++ XK_Hangul_J_SsangSios = 0x0ee7, // U+11BB HANGUL JONGSEONG SSANGSIOS ++ XK_Hangul_J_Ieung = 0x0ee8, // U+11BC HANGUL JONGSEONG IEUNG ++ XK_Hangul_J_Jieuj = 0x0ee9, // U+11BD HANGUL JONGSEONG CIEUC ++ XK_Hangul_J_Cieuc = 0x0eea, // U+11BE HANGUL JONGSEONG CHIEUCH ++ XK_Hangul_J_Khieuq = 0x0eeb, // U+11BF HANGUL JONGSEONG KHIEUKH ++ XK_Hangul_J_Tieut = 0x0eec, // U+11C0 HANGUL JONGSEONG THIEUTH ++ XK_Hangul_J_Phieuf = 0x0eed, // U+11C1 HANGUL JONGSEONG PHIEUPH ++ XK_Hangul_J_Hieuh = 0x0eee, // U+11C2 HANGUL JONGSEONG HIEUH ++ XK_Hangul_RieulYeorinHieuh = 0x0eef, // U+316D HANGUL LETTER RIEUL-YEORINHIEUH ++ XK_Hangul_SunkyeongeumMieum = 0x0ef0, // U+3171 HANGUL LETTER KAPYEOUNMIEUM ++ XK_Hangul_SunkyeongeumPieub = 0x0ef1, // U+3178 HANGUL LETTER KAPYEOUNPIEUP ++ XK_Hangul_PanSios = 0x0ef2, // U+317F HANGUL LETTER PANSIOS ++ XK_Hangul_KkogjiDalrinIeung = 0x0ef3, // U+3181 HANGUL LETTER YESIEUNG ++ XK_Hangul_SunkyeongeumPhieuf = 0x0ef4, // U+3184 HANGUL LETTER KAPYEOUNPHIEUPH ++ XK_Hangul_YeorinHieuh = 0x0ef5, // U+3186 HANGUL LETTER YEORINHIEUH ++ XK_Hangul_AraeA = 0x0ef6, // U+318D HANGUL LETTER ARAEA ++ XK_Hangul_AraeAE = 0x0ef7, // U+318E HANGUL LETTER ARAEAE ++ XK_Hangul_J_PanSios = 0x0ef8, // U+11EB HANGUL JONGSEONG PANSIOS ++ XK_Hangul_J_KkogjiDalrinIeung = 0x0ef9, // U+11F0 HANGUL JONGSEONG YESIEUNG ++ XK_Hangul_J_YeorinHieuh = 0x0efa, // U+11F9 HANGUL JONGSEONG YEORINHIEUH ++ XK_Korean_Won = 0x0eff, // (U+20A9 WON SIGN) ++ XK_Armenian_ligature_ew = 0x1000587, // U+0587 ARMENIAN SMALL LIGATURE ECH YIWN ++ XK_Armenian_full_stop = 0x1000589, // U+0589 ARMENIAN FULL STOP ++ // XK_Armenian_verjaket = 0x1000589, // deprecated alias for Armenian_full_stop ++ XK_Armenian_separation_mark = 0x100055d, // U+055D ARMENIAN COMMA ++ // XK_Armenian_but = 0x100055d, // deprecated alias for Armenian_separation_mark ++ XK_Armenian_hyphen = 0x100058a, // U+058A ARMENIAN HYPHEN ++ // XK_Armenian_yentamna = 0x100058a, // deprecated alias for Armenian_hyphen ++ XK_Armenian_exclam = 0x100055c, // U+055C ARMENIAN EXCLAMATION MARK ++ // XK_Armenian_amanak = 0x100055c, // deprecated alias for Armenian_exclam ++ XK_Armenian_accent = 0x100055b, // U+055B ARMENIAN EMPHASIS MARK ++ // XK_Armenian_shesht = 0x100055b, // deprecated alias for Armenian_accent ++ XK_Armenian_question = 0x100055e, // U+055E ARMENIAN QUESTION MARK ++ // XK_Armenian_paruyk = 0x100055e, // deprecated alias for Armenian_question ++ XK_Armenian_AYB = 0x1000531, // U+0531 ARMENIAN CAPITAL LETTER AYB ++ XK_Armenian_ayb = 0x1000561, // U+0561 ARMENIAN SMALL LETTER AYB ++ XK_Armenian_BEN = 0x1000532, // U+0532 ARMENIAN CAPITAL LETTER BEN ++ XK_Armenian_ben = 0x1000562, // U+0562 ARMENIAN SMALL LETTER BEN ++ XK_Armenian_GIM = 0x1000533, // U+0533 ARMENIAN CAPITAL LETTER GIM ++ XK_Armenian_gim = 0x1000563, // U+0563 ARMENIAN SMALL LETTER GIM ++ XK_Armenian_DA = 0x1000534, // U+0534 ARMENIAN CAPITAL LETTER DA ++ XK_Armenian_da = 0x1000564, // U+0564 ARMENIAN SMALL LETTER DA ++ XK_Armenian_YECH = 0x1000535, // U+0535 ARMENIAN CAPITAL LETTER ECH ++ XK_Armenian_yech = 0x1000565, // U+0565 ARMENIAN SMALL LETTER ECH ++ XK_Armenian_ZA = 0x1000536, // U+0536 ARMENIAN CAPITAL LETTER ZA ++ XK_Armenian_za = 0x1000566, // U+0566 ARMENIAN SMALL LETTER ZA ++ XK_Armenian_E = 0x1000537, // U+0537 ARMENIAN CAPITAL LETTER EH ++ XK_Armenian_e = 0x1000567, // U+0567 ARMENIAN SMALL LETTER EH ++ XK_Armenian_AT = 0x1000538, // U+0538 ARMENIAN CAPITAL LETTER ET ++ XK_Armenian_at = 0x1000568, // U+0568 ARMENIAN SMALL LETTER ET ++ XK_Armenian_TO = 0x1000539, // U+0539 ARMENIAN CAPITAL LETTER TO ++ XK_Armenian_to = 0x1000569, // U+0569 ARMENIAN SMALL LETTER TO ++ XK_Armenian_ZHE = 0x100053a, // U+053A ARMENIAN CAPITAL LETTER ZHE ++ XK_Armenian_zhe = 0x100056a, // U+056A ARMENIAN SMALL LETTER ZHE ++ XK_Armenian_INI = 0x100053b, // U+053B ARMENIAN CAPITAL LETTER INI ++ XK_Armenian_ini = 0x100056b, // U+056B ARMENIAN SMALL LETTER INI ++ XK_Armenian_LYUN = 0x100053c, // U+053C ARMENIAN CAPITAL LETTER LIWN ++ XK_Armenian_lyun = 0x100056c, // U+056C ARMENIAN SMALL LETTER LIWN ++ XK_Armenian_KHE = 0x100053d, // U+053D ARMENIAN CAPITAL LETTER XEH ++ XK_Armenian_khe = 0x100056d, // U+056D ARMENIAN SMALL LETTER XEH ++ XK_Armenian_TSA = 0x100053e, // U+053E ARMENIAN CAPITAL LETTER CA ++ XK_Armenian_tsa = 0x100056e, // U+056E ARMENIAN SMALL LETTER CA ++ XK_Armenian_KEN = 0x100053f, // U+053F ARMENIAN CAPITAL LETTER KEN ++ XK_Armenian_ken = 0x100056f, // U+056F ARMENIAN SMALL LETTER KEN ++ XK_Armenian_HO = 0x1000540, // U+0540 ARMENIAN CAPITAL LETTER HO ++ XK_Armenian_ho = 0x1000570, // U+0570 ARMENIAN SMALL LETTER HO ++ XK_Armenian_DZA = 0x1000541, // U+0541 ARMENIAN CAPITAL LETTER JA ++ XK_Armenian_dza = 0x1000571, // U+0571 ARMENIAN SMALL LETTER JA ++ XK_Armenian_GHAT = 0x1000542, // U+0542 ARMENIAN CAPITAL LETTER GHAD ++ XK_Armenian_ghat = 0x1000572, // U+0572 ARMENIAN SMALL LETTER GHAD ++ XK_Armenian_TCHE = 0x1000543, // U+0543 ARMENIAN CAPITAL LETTER CHEH ++ XK_Armenian_tche = 0x1000573, // U+0573 ARMENIAN SMALL LETTER CHEH ++ XK_Armenian_MEN = 0x1000544, // U+0544 ARMENIAN CAPITAL LETTER MEN ++ XK_Armenian_men = 0x1000574, // U+0574 ARMENIAN SMALL LETTER MEN ++ XK_Armenian_HI = 0x1000545, // U+0545 ARMENIAN CAPITAL LETTER YI ++ XK_Armenian_hi = 0x1000575, // U+0575 ARMENIAN SMALL LETTER YI ++ XK_Armenian_NU = 0x1000546, // U+0546 ARMENIAN CAPITAL LETTER NOW ++ XK_Armenian_nu = 0x1000576, // U+0576 ARMENIAN SMALL LETTER NOW ++ XK_Armenian_SHA = 0x1000547, // U+0547 ARMENIAN CAPITAL LETTER SHA ++ XK_Armenian_sha = 0x1000577, // U+0577 ARMENIAN SMALL LETTER SHA ++ XK_Armenian_VO = 0x1000548, // U+0548 ARMENIAN CAPITAL LETTER VO ++ XK_Armenian_vo = 0x1000578, // U+0578 ARMENIAN SMALL LETTER VO ++ XK_Armenian_CHA = 0x1000549, // U+0549 ARMENIAN CAPITAL LETTER CHA ++ XK_Armenian_cha = 0x1000579, // U+0579 ARMENIAN SMALL LETTER CHA ++ XK_Armenian_PE = 0x100054a, // U+054A ARMENIAN CAPITAL LETTER PEH ++ XK_Armenian_pe = 0x100057a, // U+057A ARMENIAN SMALL LETTER PEH ++ XK_Armenian_JE = 0x100054b, // U+054B ARMENIAN CAPITAL LETTER JHEH ++ XK_Armenian_je = 0x100057b, // U+057B ARMENIAN SMALL LETTER JHEH ++ XK_Armenian_RA = 0x100054c, // U+054C ARMENIAN CAPITAL LETTER RA ++ XK_Armenian_ra = 0x100057c, // U+057C ARMENIAN SMALL LETTER RA ++ XK_Armenian_SE = 0x100054d, // U+054D ARMENIAN CAPITAL LETTER SEH ++ XK_Armenian_se = 0x100057d, // U+057D ARMENIAN SMALL LETTER SEH ++ XK_Armenian_VEV = 0x100054e, // U+054E ARMENIAN CAPITAL LETTER VEW ++ XK_Armenian_vev = 0x100057e, // U+057E ARMENIAN SMALL LETTER VEW ++ XK_Armenian_TYUN = 0x100054f, // U+054F ARMENIAN CAPITAL LETTER TIWN ++ XK_Armenian_tyun = 0x100057f, // U+057F ARMENIAN SMALL LETTER TIWN ++ XK_Armenian_RE = 0x1000550, // U+0550 ARMENIAN CAPITAL LETTER REH ++ XK_Armenian_re = 0x1000580, // U+0580 ARMENIAN SMALL LETTER REH ++ XK_Armenian_TSO = 0x1000551, // U+0551 ARMENIAN CAPITAL LETTER CO ++ XK_Armenian_tso = 0x1000581, // U+0581 ARMENIAN SMALL LETTER CO ++ XK_Armenian_VYUN = 0x1000552, // U+0552 ARMENIAN CAPITAL LETTER YIWN ++ XK_Armenian_vyun = 0x1000582, // U+0582 ARMENIAN SMALL LETTER YIWN ++ XK_Armenian_PYUR = 0x1000553, // U+0553 ARMENIAN CAPITAL LETTER PIWR ++ XK_Armenian_pyur = 0x1000583, // U+0583 ARMENIAN SMALL LETTER PIWR ++ XK_Armenian_KE = 0x1000554, // U+0554 ARMENIAN CAPITAL LETTER KEH ++ XK_Armenian_ke = 0x1000584, // U+0584 ARMENIAN SMALL LETTER KEH ++ XK_Armenian_O = 0x1000555, // U+0555 ARMENIAN CAPITAL LETTER OH ++ XK_Armenian_o = 0x1000585, // U+0585 ARMENIAN SMALL LETTER OH ++ XK_Armenian_FE = 0x1000556, // U+0556 ARMENIAN CAPITAL LETTER FEH ++ XK_Armenian_fe = 0x1000586, // U+0586 ARMENIAN SMALL LETTER FEH ++ XK_Armenian_apostrophe = 0x100055a, // U+055A ARMENIAN APOSTROPHE ++ ++ XK_Georgian_an = 0x10010d0, // U+10D0 GEORGIAN LETTER AN ++ XK_Georgian_ban = 0x10010d1, // U+10D1 GEORGIAN LETTER BAN ++ XK_Georgian_gan = 0x10010d2, // U+10D2 GEORGIAN LETTER GAN ++ XK_Georgian_don = 0x10010d3, // U+10D3 GEORGIAN LETTER DON ++ XK_Georgian_en = 0x10010d4, // U+10D4 GEORGIAN LETTER EN ++ XK_Georgian_vin = 0x10010d5, // U+10D5 GEORGIAN LETTER VIN ++ XK_Georgian_zen = 0x10010d6, // U+10D6 GEORGIAN LETTER ZEN ++ XK_Georgian_tan = 0x10010d7, // U+10D7 GEORGIAN LETTER TAN ++ XK_Georgian_in = 0x10010d8, // U+10D8 GEORGIAN LETTER IN ++ XK_Georgian_kan = 0x10010d9, // U+10D9 GEORGIAN LETTER KAN ++ XK_Georgian_las = 0x10010da, // U+10DA GEORGIAN LETTER LAS ++ XK_Georgian_man = 0x10010db, // U+10DB GEORGIAN LETTER MAN ++ XK_Georgian_nar = 0x10010dc, // U+10DC GEORGIAN LETTER NAR ++ XK_Georgian_on = 0x10010dd, // U+10DD GEORGIAN LETTER ON ++ XK_Georgian_par = 0x10010de, // U+10DE GEORGIAN LETTER PAR ++ XK_Georgian_zhar = 0x10010df, // U+10DF GEORGIAN LETTER ZHAR ++ XK_Georgian_rae = 0x10010e0, // U+10E0 GEORGIAN LETTER RAE ++ XK_Georgian_san = 0x10010e1, // U+10E1 GEORGIAN LETTER SAN ++ XK_Georgian_tar = 0x10010e2, // U+10E2 GEORGIAN LETTER TAR ++ XK_Georgian_un = 0x10010e3, // U+10E3 GEORGIAN LETTER UN ++ XK_Georgian_phar = 0x10010e4, // U+10E4 GEORGIAN LETTER PHAR ++ XK_Georgian_khar = 0x10010e5, // U+10E5 GEORGIAN LETTER KHAR ++ XK_Georgian_ghan = 0x10010e6, // U+10E6 GEORGIAN LETTER GHAN ++ XK_Georgian_qar = 0x10010e7, // U+10E7 GEORGIAN LETTER QAR ++ XK_Georgian_shin = 0x10010e8, // U+10E8 GEORGIAN LETTER SHIN ++ XK_Georgian_chin = 0x10010e9, // U+10E9 GEORGIAN LETTER CHIN ++ XK_Georgian_can = 0x10010ea, // U+10EA GEORGIAN LETTER CAN ++ XK_Georgian_jil = 0x10010eb, // U+10EB GEORGIAN LETTER JIL ++ XK_Georgian_cil = 0x10010ec, // U+10EC GEORGIAN LETTER CIL ++ XK_Georgian_char = 0x10010ed, // U+10ED GEORGIAN LETTER CHAR ++ XK_Georgian_xan = 0x10010ee, // U+10EE GEORGIAN LETTER XAN ++ XK_Georgian_jhan = 0x10010ef, // U+10EF GEORGIAN LETTER JHAN ++ XK_Georgian_hae = 0x10010f0, // U+10F0 GEORGIAN LETTER HAE ++ XK_Georgian_he = 0x10010f1, // U+10F1 GEORGIAN LETTER HE ++ XK_Georgian_hie = 0x10010f2, // U+10F2 GEORGIAN LETTER HIE ++ XK_Georgian_we = 0x10010f3, // U+10F3 GEORGIAN LETTER WE ++ XK_Georgian_har = 0x10010f4, // U+10F4 GEORGIAN LETTER HAR ++ XK_Georgian_hoe = 0x10010f5, // U+10F5 GEORGIAN LETTER HOE ++ XK_Georgian_fi = 0x10010f6, // U+10F6 GEORGIAN LETTER FI ++ ++ XK_Xabovedot = 0x1001e8a, // U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE ++ XK_Ibreve = 0x100012c, // U+012C LATIN CAPITAL LETTER I WITH BREVE ++ XK_Zstroke = 0x10001b5, // U+01B5 LATIN CAPITAL LETTER Z WITH STROKE ++ XK_Gcaron = 0x10001e6, // U+01E6 LATIN CAPITAL LETTER G WITH CARON ++ XK_Ocaron = 0x10001d1, // U+01D1 LATIN CAPITAL LETTER O WITH CARON ++ XK_Obarred = 0x100019f, // U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE ++ XK_xabovedot = 0x1001e8b, // U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE ++ XK_ibreve = 0x100012d, // U+012D LATIN SMALL LETTER I WITH BREVE ++ XK_zstroke = 0x10001b6, // U+01B6 LATIN SMALL LETTER Z WITH STROKE ++ XK_gcaron = 0x10001e7, // U+01E7 LATIN SMALL LETTER G WITH CARON ++ XK_ocaron = 0x10001d2, // U+01D2 LATIN SMALL LETTER O WITH CARON ++ XK_obarred = 0x1000275, // U+0275 LATIN SMALL LETTER BARRED O ++ XK_SCHWA = 0x100018f, // U+018F LATIN CAPITAL LETTER SCHWA ++ XK_schwa = 0x1000259, // U+0259 LATIN SMALL LETTER SCHWA ++ XK_EZH = 0x10001b7, // U+01B7 LATIN CAPITAL LETTER EZH ++ XK_ezh = 0x1000292, // U+0292 LATIN SMALL LETTER EZH ++ XK_Lbelowdot = 0x1001e36, // U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW ++ XK_lbelowdot = 0x1001e37, // U+1E37 LATIN SMALL LETTER L WITH DOT BELOW ++ ++ XK_Abelowdot = 0x1001ea0, // U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW ++ XK_abelowdot = 0x1001ea1, // U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW ++ XK_Ahook = 0x1001ea2, // U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE ++ XK_ahook = 0x1001ea3, // U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE ++ XK_Acircumflexacute = 0x1001ea4, // U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE ++ XK_acircumflexacute = 0x1001ea5, // U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE ++ XK_Acircumflexgrave = 0x1001ea6, // U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE ++ XK_acircumflexgrave = 0x1001ea7, // U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE ++ XK_Acircumflexhook = 0x1001ea8, // U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_acircumflexhook = 0x1001ea9, // U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_Acircumflextilde = 0x1001eaa, // U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE ++ XK_acircumflextilde = 0x1001eab, // U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE ++ XK_Acircumflexbelowdot = 0x1001eac, // U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW ++ XK_acircumflexbelowdot = 0x1001ead, // U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW ++ XK_Abreveacute = 0x1001eae, // U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE ++ XK_abreveacute = 0x1001eaf, // U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE ++ XK_Abrevegrave = 0x1001eb0, // U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE ++ XK_abrevegrave = 0x1001eb1, // U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE ++ XK_Abrevehook = 0x1001eb2, // U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE ++ XK_abrevehook = 0x1001eb3, // U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE ++ XK_Abrevetilde = 0x1001eb4, // U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE ++ XK_abrevetilde = 0x1001eb5, // U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE ++ XK_Abrevebelowdot = 0x1001eb6, // U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW ++ XK_abrevebelowdot = 0x1001eb7, // U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW ++ XK_Ebelowdot = 0x1001eb8, // U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW ++ XK_ebelowdot = 0x1001eb9, // U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW ++ XK_Ehook = 0x1001eba, // U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE ++ XK_ehook = 0x1001ebb, // U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE ++ XK_Etilde = 0x1001ebc, // U+1EBC LATIN CAPITAL LETTER E WITH TILDE ++ XK_etilde = 0x1001ebd, // U+1EBD LATIN SMALL LETTER E WITH TILDE ++ XK_Ecircumflexacute = 0x1001ebe, // U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE ++ XK_ecircumflexacute = 0x1001ebf, // U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE ++ XK_Ecircumflexgrave = 0x1001ec0, // U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE ++ XK_ecircumflexgrave = 0x1001ec1, // U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE ++ XK_Ecircumflexhook = 0x1001ec2, // U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_ecircumflexhook = 0x1001ec3, // U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_Ecircumflextilde = 0x1001ec4, // U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE ++ XK_ecircumflextilde = 0x1001ec5, // U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE ++ XK_Ecircumflexbelowdot = 0x1001ec6, // U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW ++ XK_ecircumflexbelowdot = 0x1001ec7, // U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW ++ XK_Ihook = 0x1001ec8, // U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE ++ XK_ihook = 0x1001ec9, // U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE ++ XK_Ibelowdot = 0x1001eca, // U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW ++ XK_ibelowdot = 0x1001ecb, // U+1ECB LATIN SMALL LETTER I WITH DOT BELOW ++ XK_Obelowdot = 0x1001ecc, // U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW ++ XK_obelowdot = 0x1001ecd, // U+1ECD LATIN SMALL LETTER O WITH DOT BELOW ++ XK_Ohook = 0x1001ece, // U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE ++ XK_ohook = 0x1001ecf, // U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE ++ XK_Ocircumflexacute = 0x1001ed0, // U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE ++ XK_ocircumflexacute = 0x1001ed1, // U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE ++ XK_Ocircumflexgrave = 0x1001ed2, // U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE ++ XK_ocircumflexgrave = 0x1001ed3, // U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE ++ XK_Ocircumflexhook = 0x1001ed4, // U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_ocircumflexhook = 0x1001ed5, // U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE ++ XK_Ocircumflextilde = 0x1001ed6, // U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE ++ XK_ocircumflextilde = 0x1001ed7, // U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE ++ XK_Ocircumflexbelowdot = 0x1001ed8, // U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW ++ XK_ocircumflexbelowdot = 0x1001ed9, // U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW ++ XK_Ohornacute = 0x1001eda, // U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE ++ XK_ohornacute = 0x1001edb, // U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE ++ XK_Ohorngrave = 0x1001edc, // U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE ++ XK_ohorngrave = 0x1001edd, // U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE ++ XK_Ohornhook = 0x1001ede, // U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE ++ XK_ohornhook = 0x1001edf, // U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE ++ XK_Ohorntilde = 0x1001ee0, // U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE ++ XK_ohorntilde = 0x1001ee1, // U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE ++ XK_Ohornbelowdot = 0x1001ee2, // U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW ++ XK_ohornbelowdot = 0x1001ee3, // U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW ++ XK_Ubelowdot = 0x1001ee4, // U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW ++ XK_ubelowdot = 0x1001ee5, // U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW ++ XK_Uhook = 0x1001ee6, // U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE ++ XK_uhook = 0x1001ee7, // U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE ++ XK_Uhornacute = 0x1001ee8, // U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE ++ XK_uhornacute = 0x1001ee9, // U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE ++ XK_Uhorngrave = 0x1001eea, // U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE ++ XK_uhorngrave = 0x1001eeb, // U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE ++ XK_Uhornhook = 0x1001eec, // U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE ++ XK_uhornhook = 0x1001eed, // U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE ++ XK_Uhorntilde = 0x1001eee, // U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE ++ XK_uhorntilde = 0x1001eef, // U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE ++ XK_Uhornbelowdot = 0x1001ef0, // U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW ++ XK_uhornbelowdot = 0x1001ef1, // U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW ++ XK_Ybelowdot = 0x1001ef4, // U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW ++ XK_ybelowdot = 0x1001ef5, // U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW ++ XK_Yhook = 0x1001ef6, // U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE ++ XK_yhook = 0x1001ef7, // U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE ++ XK_Ytilde = 0x1001ef8, // U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE ++ XK_ytilde = 0x1001ef9, // U+1EF9 LATIN SMALL LETTER Y WITH TILDE ++ XK_Ohorn = 0x10001a0, // U+01A0 LATIN CAPITAL LETTER O WITH HORN ++ XK_ohorn = 0x10001a1, // U+01A1 LATIN SMALL LETTER O WITH HORN ++ XK_Uhorn = 0x10001af, // U+01AF LATIN CAPITAL LETTER U WITH HORN ++ XK_uhorn = 0x10001b0, // U+01B0 LATIN SMALL LETTER U WITH HORN ++ XK_combining_tilde = 0x1000303, // U+0303 COMBINING TILDE ++ XK_combining_grave = 0x1000300, // U+0300 COMBINING GRAVE ACCENT ++ XK_combining_acute = 0x1000301, // U+0301 COMBINING ACUTE ACCENT ++ XK_combining_hook = 0x1000309, // U+0309 COMBINING HOOK ABOVE ++ XK_combining_belowdot = 0x1000323, // U+0323 COMBINING DOT BELOW ++ ++ XK_EcuSign = 0x10020a0, // U+20A0 EURO-CURRENCY SIGN ++ XK_ColonSign = 0x10020a1, // U+20A1 COLON SIGN ++ XK_CruzeiroSign = 0x10020a2, // U+20A2 CRUZEIRO SIGN ++ XK_FFrancSign = 0x10020a3, // U+20A3 FRENCH FRANC SIGN ++ XK_LiraSign = 0x10020a4, // U+20A4 LIRA SIGN ++ XK_MillSign = 0x10020a5, // U+20A5 MILL SIGN ++ XK_NairaSign = 0x10020a6, // U+20A6 NAIRA SIGN ++ XK_PesetaSign = 0x10020a7, // U+20A7 PESETA SIGN ++ XK_RupeeSign = 0x10020a8, // U+20A8 RUPEE SIGN ++ XK_WonSign = 0x10020a9, // U+20A9 WON SIGN ++ XK_NewSheqelSign = 0x10020aa, // U+20AA NEW SHEQEL SIGN ++ XK_DongSign = 0x10020ab, // U+20AB DONG SIGN ++ XK_EuroSign = 0x20ac, // U+20AC EURO SIGN ++ ++ XK_zerosuperior = 0x1002070, // U+2070 SUPERSCRIPT ZERO ++ XK_foursuperior = 0x1002074, // U+2074 SUPERSCRIPT FOUR ++ XK_fivesuperior = 0x1002075, // U+2075 SUPERSCRIPT FIVE ++ XK_sixsuperior = 0x1002076, // U+2076 SUPERSCRIPT SIX ++ XK_sevensuperior = 0x1002077, // U+2077 SUPERSCRIPT SEVEN ++ XK_eightsuperior = 0x1002078, // U+2078 SUPERSCRIPT EIGHT ++ XK_ninesuperior = 0x1002079, // U+2079 SUPERSCRIPT NINE ++ XK_zerosubscript = 0x1002080, // U+2080 SUBSCRIPT ZERO ++ XK_onesubscript = 0x1002081, // U+2081 SUBSCRIPT ONE ++ XK_twosubscript = 0x1002082, // U+2082 SUBSCRIPT TWO ++ XK_threesubscript = 0x1002083, // U+2083 SUBSCRIPT THREE ++ XK_foursubscript = 0x1002084, // U+2084 SUBSCRIPT FOUR ++ XK_fivesubscript = 0x1002085, // U+2085 SUBSCRIPT FIVE ++ XK_sixsubscript = 0x1002086, // U+2086 SUBSCRIPT SIX ++ XK_sevensubscript = 0x1002087, // U+2087 SUBSCRIPT SEVEN ++ XK_eightsubscript = 0x1002088, // U+2088 SUBSCRIPT EIGHT ++ XK_ninesubscript = 0x1002089, // U+2089 SUBSCRIPT NINE ++ XK_partdifferential = 0x1002202, // U+2202 PARTIAL DIFFERENTIAL ++ XK_emptyset = 0x1002205, // U+2205 EMPTY SET ++ XK_elementof = 0x1002208, // U+2208 ELEMENT OF ++ XK_notelementof = 0x1002209, // U+2209 NOT AN ELEMENT OF ++ XK_containsas = 0x100220b, // U+220B CONTAINS AS MEMBER ++ XK_squareroot = 0x100221a, // U+221A SQUARE ROOT ++ XK_cuberoot = 0x100221b, // U+221B CUBE ROOT ++ XK_fourthroot = 0x100221c, // U+221C FOURTH ROOT ++ XK_dintegral = 0x100222c, // U+222C DOUBLE INTEGRAL ++ XK_tintegral = 0x100222d, // U+222D TRIPLE INTEGRAL ++ XK_because = 0x1002235, // U+2235 BECAUSE ++ XK_approxeq = 0x1002248, // (U+2248 ALMOST EQUAL TO) ++ XK_notapproxeq = 0x1002247, // (U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO) ++ XK_notidentical = 0x1002262, // U+2262 NOT IDENTICAL TO ++ XK_stricteq = 0x1002263, // U+2263 STRICTLY EQUIVALENT TO ++ ++ XK_braille_dot_1 = 0xfff1, ++ XK_braille_dot_2 = 0xfff2, ++ XK_braille_dot_3 = 0xfff3, ++ XK_braille_dot_4 = 0xfff4, ++ XK_braille_dot_5 = 0xfff5, ++ XK_braille_dot_6 = 0xfff6, ++ XK_braille_dot_7 = 0xfff7, ++ XK_braille_dot_8 = 0xfff8, ++ XK_braille_dot_9 = 0xfff9, ++ XK_braille_dot_10 = 0xfffa, ++ XK_braille_blank = 0x1002800, // U+2800 BRAILLE PATTERN BLANK ++ XK_braille_dots_1 = 0x1002801, // U+2801 BRAILLE PATTERN DOTS-1 ++ XK_braille_dots_2 = 0x1002802, // U+2802 BRAILLE PATTERN DOTS-2 ++ XK_braille_dots_12 = 0x1002803, // U+2803 BRAILLE PATTERN DOTS-12 ++ XK_braille_dots_3 = 0x1002804, // U+2804 BRAILLE PATTERN DOTS-3 ++ XK_braille_dots_13 = 0x1002805, // U+2805 BRAILLE PATTERN DOTS-13 ++ XK_braille_dots_23 = 0x1002806, // U+2806 BRAILLE PATTERN DOTS-23 ++ XK_braille_dots_123 = 0x1002807, // U+2807 BRAILLE PATTERN DOTS-123 ++ XK_braille_dots_4 = 0x1002808, // U+2808 BRAILLE PATTERN DOTS-4 ++ XK_braille_dots_14 = 0x1002809, // U+2809 BRAILLE PATTERN DOTS-14 ++ XK_braille_dots_24 = 0x100280a, // U+280A BRAILLE PATTERN DOTS-24 ++ XK_braille_dots_124 = 0x100280b, // U+280B BRAILLE PATTERN DOTS-124 ++ XK_braille_dots_34 = 0x100280c, // U+280C BRAILLE PATTERN DOTS-34 ++ XK_braille_dots_134 = 0x100280d, // U+280D BRAILLE PATTERN DOTS-134 ++ XK_braille_dots_234 = 0x100280e, // U+280E BRAILLE PATTERN DOTS-234 ++ XK_braille_dots_1234 = 0x100280f, // U+280F BRAILLE PATTERN DOTS-1234 ++ XK_braille_dots_5 = 0x1002810, // U+2810 BRAILLE PATTERN DOTS-5 ++ XK_braille_dots_15 = 0x1002811, // U+2811 BRAILLE PATTERN DOTS-15 ++ XK_braille_dots_25 = 0x1002812, // U+2812 BRAILLE PATTERN DOTS-25 ++ XK_braille_dots_125 = 0x1002813, // U+2813 BRAILLE PATTERN DOTS-125 ++ XK_braille_dots_35 = 0x1002814, // U+2814 BRAILLE PATTERN DOTS-35 ++ XK_braille_dots_135 = 0x1002815, // U+2815 BRAILLE PATTERN DOTS-135 ++ XK_braille_dots_235 = 0x1002816, // U+2816 BRAILLE PATTERN DOTS-235 ++ XK_braille_dots_1235 = 0x1002817, // U+2817 BRAILLE PATTERN DOTS-1235 ++ XK_braille_dots_45 = 0x1002818, // U+2818 BRAILLE PATTERN DOTS-45 ++ XK_braille_dots_145 = 0x1002819, // U+2819 BRAILLE PATTERN DOTS-145 ++ XK_braille_dots_245 = 0x100281a, // U+281A BRAILLE PATTERN DOTS-245 ++ XK_braille_dots_1245 = 0x100281b, // U+281B BRAILLE PATTERN DOTS-1245 ++ XK_braille_dots_345 = 0x100281c, // U+281C BRAILLE PATTERN DOTS-345 ++ XK_braille_dots_1345 = 0x100281d, // U+281D BRAILLE PATTERN DOTS-1345 ++ XK_braille_dots_2345 = 0x100281e, // U+281E BRAILLE PATTERN DOTS-2345 ++ XK_braille_dots_12345 = 0x100281f, // U+281F BRAILLE PATTERN DOTS-12345 ++ XK_braille_dots_6 = 0x1002820, // U+2820 BRAILLE PATTERN DOTS-6 ++ XK_braille_dots_16 = 0x1002821, // U+2821 BRAILLE PATTERN DOTS-16 ++ XK_braille_dots_26 = 0x1002822, // U+2822 BRAILLE PATTERN DOTS-26 ++ XK_braille_dots_126 = 0x1002823, // U+2823 BRAILLE PATTERN DOTS-126 ++ XK_braille_dots_36 = 0x1002824, // U+2824 BRAILLE PATTERN DOTS-36 ++ XK_braille_dots_136 = 0x1002825, // U+2825 BRAILLE PATTERN DOTS-136 ++ XK_braille_dots_236 = 0x1002826, // U+2826 BRAILLE PATTERN DOTS-236 ++ XK_braille_dots_1236 = 0x1002827, // U+2827 BRAILLE PATTERN DOTS-1236 ++ XK_braille_dots_46 = 0x1002828, // U+2828 BRAILLE PATTERN DOTS-46 ++ XK_braille_dots_146 = 0x1002829, // U+2829 BRAILLE PATTERN DOTS-146 ++ XK_braille_dots_246 = 0x100282a, // U+282A BRAILLE PATTERN DOTS-246 ++ XK_braille_dots_1246 = 0x100282b, // U+282B BRAILLE PATTERN DOTS-1246 ++ XK_braille_dots_346 = 0x100282c, // U+282C BRAILLE PATTERN DOTS-346 ++ XK_braille_dots_1346 = 0x100282d, // U+282D BRAILLE PATTERN DOTS-1346 ++ XK_braille_dots_2346 = 0x100282e, // U+282E BRAILLE PATTERN DOTS-2346 ++ XK_braille_dots_12346 = 0x100282f, // U+282F BRAILLE PATTERN DOTS-12346 ++ XK_braille_dots_56 = 0x1002830, // U+2830 BRAILLE PATTERN DOTS-56 ++ XK_braille_dots_156 = 0x1002831, // U+2831 BRAILLE PATTERN DOTS-156 ++ XK_braille_dots_256 = 0x1002832, // U+2832 BRAILLE PATTERN DOTS-256 ++ XK_braille_dots_1256 = 0x1002833, // U+2833 BRAILLE PATTERN DOTS-1256 ++ XK_braille_dots_356 = 0x1002834, // U+2834 BRAILLE PATTERN DOTS-356 ++ XK_braille_dots_1356 = 0x1002835, // U+2835 BRAILLE PATTERN DOTS-1356 ++ XK_braille_dots_2356 = 0x1002836, // U+2836 BRAILLE PATTERN DOTS-2356 ++ XK_braille_dots_12356 = 0x1002837, // U+2837 BRAILLE PATTERN DOTS-12356 ++ XK_braille_dots_456 = 0x1002838, // U+2838 BRAILLE PATTERN DOTS-456 ++ XK_braille_dots_1456 = 0x1002839, // U+2839 BRAILLE PATTERN DOTS-1456 ++ XK_braille_dots_2456 = 0x100283a, // U+283A BRAILLE PATTERN DOTS-2456 ++ XK_braille_dots_12456 = 0x100283b, // U+283B BRAILLE PATTERN DOTS-12456 ++ XK_braille_dots_3456 = 0x100283c, // U+283C BRAILLE PATTERN DOTS-3456 ++ XK_braille_dots_13456 = 0x100283d, // U+283D BRAILLE PATTERN DOTS-13456 ++ XK_braille_dots_23456 = 0x100283e, // U+283E BRAILLE PATTERN DOTS-23456 ++ XK_braille_dots_123456 = 0x100283f, // U+283F BRAILLE PATTERN DOTS-123456 ++ XK_braille_dots_7 = 0x1002840, // U+2840 BRAILLE PATTERN DOTS-7 ++ XK_braille_dots_17 = 0x1002841, // U+2841 BRAILLE PATTERN DOTS-17 ++ XK_braille_dots_27 = 0x1002842, // U+2842 BRAILLE PATTERN DOTS-27 ++ XK_braille_dots_127 = 0x1002843, // U+2843 BRAILLE PATTERN DOTS-127 ++ XK_braille_dots_37 = 0x1002844, // U+2844 BRAILLE PATTERN DOTS-37 ++ XK_braille_dots_137 = 0x1002845, // U+2845 BRAILLE PATTERN DOTS-137 ++ XK_braille_dots_237 = 0x1002846, // U+2846 BRAILLE PATTERN DOTS-237 ++ XK_braille_dots_1237 = 0x1002847, // U+2847 BRAILLE PATTERN DOTS-1237 ++ XK_braille_dots_47 = 0x1002848, // U+2848 BRAILLE PATTERN DOTS-47 ++ XK_braille_dots_147 = 0x1002849, // U+2849 BRAILLE PATTERN DOTS-147 ++ XK_braille_dots_247 = 0x100284a, // U+284A BRAILLE PATTERN DOTS-247 ++ XK_braille_dots_1247 = 0x100284b, // U+284B BRAILLE PATTERN DOTS-1247 ++ XK_braille_dots_347 = 0x100284c, // U+284C BRAILLE PATTERN DOTS-347 ++ XK_braille_dots_1347 = 0x100284d, // U+284D BRAILLE PATTERN DOTS-1347 ++ XK_braille_dots_2347 = 0x100284e, // U+284E BRAILLE PATTERN DOTS-2347 ++ XK_braille_dots_12347 = 0x100284f, // U+284F BRAILLE PATTERN DOTS-12347 ++ XK_braille_dots_57 = 0x1002850, // U+2850 BRAILLE PATTERN DOTS-57 ++ XK_braille_dots_157 = 0x1002851, // U+2851 BRAILLE PATTERN DOTS-157 ++ XK_braille_dots_257 = 0x1002852, // U+2852 BRAILLE PATTERN DOTS-257 ++ XK_braille_dots_1257 = 0x1002853, // U+2853 BRAILLE PATTERN DOTS-1257 ++ XK_braille_dots_357 = 0x1002854, // U+2854 BRAILLE PATTERN DOTS-357 ++ XK_braille_dots_1357 = 0x1002855, // U+2855 BRAILLE PATTERN DOTS-1357 ++ XK_braille_dots_2357 = 0x1002856, // U+2856 BRAILLE PATTERN DOTS-2357 ++ XK_braille_dots_12357 = 0x1002857, // U+2857 BRAILLE PATTERN DOTS-12357 ++ XK_braille_dots_457 = 0x1002858, // U+2858 BRAILLE PATTERN DOTS-457 ++ XK_braille_dots_1457 = 0x1002859, // U+2859 BRAILLE PATTERN DOTS-1457 ++ XK_braille_dots_2457 = 0x100285a, // U+285A BRAILLE PATTERN DOTS-2457 ++ XK_braille_dots_12457 = 0x100285b, // U+285B BRAILLE PATTERN DOTS-12457 ++ XK_braille_dots_3457 = 0x100285c, // U+285C BRAILLE PATTERN DOTS-3457 ++ XK_braille_dots_13457 = 0x100285d, // U+285D BRAILLE PATTERN DOTS-13457 ++ XK_braille_dots_23457 = 0x100285e, // U+285E BRAILLE PATTERN DOTS-23457 ++ XK_braille_dots_123457 = 0x100285f, // U+285F BRAILLE PATTERN DOTS-123457 ++ XK_braille_dots_67 = 0x1002860, // U+2860 BRAILLE PATTERN DOTS-67 ++ XK_braille_dots_167 = 0x1002861, // U+2861 BRAILLE PATTERN DOTS-167 ++ XK_braille_dots_267 = 0x1002862, // U+2862 BRAILLE PATTERN DOTS-267 ++ XK_braille_dots_1267 = 0x1002863, // U+2863 BRAILLE PATTERN DOTS-1267 ++ XK_braille_dots_367 = 0x1002864, // U+2864 BRAILLE PATTERN DOTS-367 ++ XK_braille_dots_1367 = 0x1002865, // U+2865 BRAILLE PATTERN DOTS-1367 ++ XK_braille_dots_2367 = 0x1002866, // U+2866 BRAILLE PATTERN DOTS-2367 ++ XK_braille_dots_12367 = 0x1002867, // U+2867 BRAILLE PATTERN DOTS-12367 ++ XK_braille_dots_467 = 0x1002868, // U+2868 BRAILLE PATTERN DOTS-467 ++ XK_braille_dots_1467 = 0x1002869, // U+2869 BRAILLE PATTERN DOTS-1467 ++ XK_braille_dots_2467 = 0x100286a, // U+286A BRAILLE PATTERN DOTS-2467 ++ XK_braille_dots_12467 = 0x100286b, // U+286B BRAILLE PATTERN DOTS-12467 ++ XK_braille_dots_3467 = 0x100286c, // U+286C BRAILLE PATTERN DOTS-3467 ++ XK_braille_dots_13467 = 0x100286d, // U+286D BRAILLE PATTERN DOTS-13467 ++ XK_braille_dots_23467 = 0x100286e, // U+286E BRAILLE PATTERN DOTS-23467 ++ XK_braille_dots_123467 = 0x100286f, // U+286F BRAILLE PATTERN DOTS-123467 ++ XK_braille_dots_567 = 0x1002870, // U+2870 BRAILLE PATTERN DOTS-567 ++ XK_braille_dots_1567 = 0x1002871, // U+2871 BRAILLE PATTERN DOTS-1567 ++ XK_braille_dots_2567 = 0x1002872, // U+2872 BRAILLE PATTERN DOTS-2567 ++ XK_braille_dots_12567 = 0x1002873, // U+2873 BRAILLE PATTERN DOTS-12567 ++ XK_braille_dots_3567 = 0x1002874, // U+2874 BRAILLE PATTERN DOTS-3567 ++ XK_braille_dots_13567 = 0x1002875, // U+2875 BRAILLE PATTERN DOTS-13567 ++ XK_braille_dots_23567 = 0x1002876, // U+2876 BRAILLE PATTERN DOTS-23567 ++ XK_braille_dots_123567 = 0x1002877, // U+2877 BRAILLE PATTERN DOTS-123567 ++ XK_braille_dots_4567 = 0x1002878, // U+2878 BRAILLE PATTERN DOTS-4567 ++ XK_braille_dots_14567 = 0x1002879, // U+2879 BRAILLE PATTERN DOTS-14567 ++ XK_braille_dots_24567 = 0x100287a, // U+287A BRAILLE PATTERN DOTS-24567 ++ XK_braille_dots_124567 = 0x100287b, // U+287B BRAILLE PATTERN DOTS-124567 ++ XK_braille_dots_34567 = 0x100287c, // U+287C BRAILLE PATTERN DOTS-34567 ++ XK_braille_dots_134567 = 0x100287d, // U+287D BRAILLE PATTERN DOTS-134567 ++ XK_braille_dots_234567 = 0x100287e, // U+287E BRAILLE PATTERN DOTS-234567 ++ XK_braille_dots_1234567 = 0x100287f, // U+287F BRAILLE PATTERN DOTS-1234567 ++ XK_braille_dots_8 = 0x1002880, // U+2880 BRAILLE PATTERN DOTS-8 ++ XK_braille_dots_18 = 0x1002881, // U+2881 BRAILLE PATTERN DOTS-18 ++ XK_braille_dots_28 = 0x1002882, // U+2882 BRAILLE PATTERN DOTS-28 ++ XK_braille_dots_128 = 0x1002883, // U+2883 BRAILLE PATTERN DOTS-128 ++ XK_braille_dots_38 = 0x1002884, // U+2884 BRAILLE PATTERN DOTS-38 ++ XK_braille_dots_138 = 0x1002885, // U+2885 BRAILLE PATTERN DOTS-138 ++ XK_braille_dots_238 = 0x1002886, // U+2886 BRAILLE PATTERN DOTS-238 ++ XK_braille_dots_1238 = 0x1002887, // U+2887 BRAILLE PATTERN DOTS-1238 ++ XK_braille_dots_48 = 0x1002888, // U+2888 BRAILLE PATTERN DOTS-48 ++ XK_braille_dots_148 = 0x1002889, // U+2889 BRAILLE PATTERN DOTS-148 ++ XK_braille_dots_248 = 0x100288a, // U+288A BRAILLE PATTERN DOTS-248 ++ XK_braille_dots_1248 = 0x100288b, // U+288B BRAILLE PATTERN DOTS-1248 ++ XK_braille_dots_348 = 0x100288c, // U+288C BRAILLE PATTERN DOTS-348 ++ XK_braille_dots_1348 = 0x100288d, // U+288D BRAILLE PATTERN DOTS-1348 ++ XK_braille_dots_2348 = 0x100288e, // U+288E BRAILLE PATTERN DOTS-2348 ++ XK_braille_dots_12348 = 0x100288f, // U+288F BRAILLE PATTERN DOTS-12348 ++ XK_braille_dots_58 = 0x1002890, // U+2890 BRAILLE PATTERN DOTS-58 ++ XK_braille_dots_158 = 0x1002891, // U+2891 BRAILLE PATTERN DOTS-158 ++ XK_braille_dots_258 = 0x1002892, // U+2892 BRAILLE PATTERN DOTS-258 ++ XK_braille_dots_1258 = 0x1002893, // U+2893 BRAILLE PATTERN DOTS-1258 ++ XK_braille_dots_358 = 0x1002894, // U+2894 BRAILLE PATTERN DOTS-358 ++ XK_braille_dots_1358 = 0x1002895, // U+2895 BRAILLE PATTERN DOTS-1358 ++ XK_braille_dots_2358 = 0x1002896, // U+2896 BRAILLE PATTERN DOTS-2358 ++ XK_braille_dots_12358 = 0x1002897, // U+2897 BRAILLE PATTERN DOTS-12358 ++ XK_braille_dots_458 = 0x1002898, // U+2898 BRAILLE PATTERN DOTS-458 ++ XK_braille_dots_1458 = 0x1002899, // U+2899 BRAILLE PATTERN DOTS-1458 ++ XK_braille_dots_2458 = 0x100289a, // U+289A BRAILLE PATTERN DOTS-2458 ++ XK_braille_dots_12458 = 0x100289b, // U+289B BRAILLE PATTERN DOTS-12458 ++ XK_braille_dots_3458 = 0x100289c, // U+289C BRAILLE PATTERN DOTS-3458 ++ XK_braille_dots_13458 = 0x100289d, // U+289D BRAILLE PATTERN DOTS-13458 ++ XK_braille_dots_23458 = 0x100289e, // U+289E BRAILLE PATTERN DOTS-23458 ++ XK_braille_dots_123458 = 0x100289f, // U+289F BRAILLE PATTERN DOTS-123458 ++ XK_braille_dots_68 = 0x10028a0, // U+28A0 BRAILLE PATTERN DOTS-68 ++ XK_braille_dots_168 = 0x10028a1, // U+28A1 BRAILLE PATTERN DOTS-168 ++ XK_braille_dots_268 = 0x10028a2, // U+28A2 BRAILLE PATTERN DOTS-268 ++ XK_braille_dots_1268 = 0x10028a3, // U+28A3 BRAILLE PATTERN DOTS-1268 ++ XK_braille_dots_368 = 0x10028a4, // U+28A4 BRAILLE PATTERN DOTS-368 ++ XK_braille_dots_1368 = 0x10028a5, // U+28A5 BRAILLE PATTERN DOTS-1368 ++ XK_braille_dots_2368 = 0x10028a6, // U+28A6 BRAILLE PATTERN DOTS-2368 ++ XK_braille_dots_12368 = 0x10028a7, // U+28A7 BRAILLE PATTERN DOTS-12368 ++ XK_braille_dots_468 = 0x10028a8, // U+28A8 BRAILLE PATTERN DOTS-468 ++ XK_braille_dots_1468 = 0x10028a9, // U+28A9 BRAILLE PATTERN DOTS-1468 ++ XK_braille_dots_2468 = 0x10028aa, // U+28AA BRAILLE PATTERN DOTS-2468 ++ XK_braille_dots_12468 = 0x10028ab, // U+28AB BRAILLE PATTERN DOTS-12468 ++ XK_braille_dots_3468 = 0x10028ac, // U+28AC BRAILLE PATTERN DOTS-3468 ++ XK_braille_dots_13468 = 0x10028ad, // U+28AD BRAILLE PATTERN DOTS-13468 ++ XK_braille_dots_23468 = 0x10028ae, // U+28AE BRAILLE PATTERN DOTS-23468 ++ XK_braille_dots_123468 = 0x10028af, // U+28AF BRAILLE PATTERN DOTS-123468 ++ XK_braille_dots_568 = 0x10028b0, // U+28B0 BRAILLE PATTERN DOTS-568 ++ XK_braille_dots_1568 = 0x10028b1, // U+28B1 BRAILLE PATTERN DOTS-1568 ++ XK_braille_dots_2568 = 0x10028b2, // U+28B2 BRAILLE PATTERN DOTS-2568 ++ XK_braille_dots_12568 = 0x10028b3, // U+28B3 BRAILLE PATTERN DOTS-12568 ++ XK_braille_dots_3568 = 0x10028b4, // U+28B4 BRAILLE PATTERN DOTS-3568 ++ XK_braille_dots_13568 = 0x10028b5, // U+28B5 BRAILLE PATTERN DOTS-13568 ++ XK_braille_dots_23568 = 0x10028b6, // U+28B6 BRAILLE PATTERN DOTS-23568 ++ XK_braille_dots_123568 = 0x10028b7, // U+28B7 BRAILLE PATTERN DOTS-123568 ++ XK_braille_dots_4568 = 0x10028b8, // U+28B8 BRAILLE PATTERN DOTS-4568 ++ XK_braille_dots_14568 = 0x10028b9, // U+28B9 BRAILLE PATTERN DOTS-14568 ++ XK_braille_dots_24568 = 0x10028ba, // U+28BA BRAILLE PATTERN DOTS-24568 ++ XK_braille_dots_124568 = 0x10028bb, // U+28BB BRAILLE PATTERN DOTS-124568 ++ XK_braille_dots_34568 = 0x10028bc, // U+28BC BRAILLE PATTERN DOTS-34568 ++ XK_braille_dots_134568 = 0x10028bd, // U+28BD BRAILLE PATTERN DOTS-134568 ++ XK_braille_dots_234568 = 0x10028be, // U+28BE BRAILLE PATTERN DOTS-234568 ++ XK_braille_dots_1234568 = 0x10028bf, // U+28BF BRAILLE PATTERN DOTS-1234568 ++ XK_braille_dots_78 = 0x10028c0, // U+28C0 BRAILLE PATTERN DOTS-78 ++ XK_braille_dots_178 = 0x10028c1, // U+28C1 BRAILLE PATTERN DOTS-178 ++ XK_braille_dots_278 = 0x10028c2, // U+28C2 BRAILLE PATTERN DOTS-278 ++ XK_braille_dots_1278 = 0x10028c3, // U+28C3 BRAILLE PATTERN DOTS-1278 ++ XK_braille_dots_378 = 0x10028c4, // U+28C4 BRAILLE PATTERN DOTS-378 ++ XK_braille_dots_1378 = 0x10028c5, // U+28C5 BRAILLE PATTERN DOTS-1378 ++ XK_braille_dots_2378 = 0x10028c6, // U+28C6 BRAILLE PATTERN DOTS-2378 ++ XK_braille_dots_12378 = 0x10028c7, // U+28C7 BRAILLE PATTERN DOTS-12378 ++ XK_braille_dots_478 = 0x10028c8, // U+28C8 BRAILLE PATTERN DOTS-478 ++ XK_braille_dots_1478 = 0x10028c9, // U+28C9 BRAILLE PATTERN DOTS-1478 ++ XK_braille_dots_2478 = 0x10028ca, // U+28CA BRAILLE PATTERN DOTS-2478 ++ XK_braille_dots_12478 = 0x10028cb, // U+28CB BRAILLE PATTERN DOTS-12478 ++ XK_braille_dots_3478 = 0x10028cc, // U+28CC BRAILLE PATTERN DOTS-3478 ++ XK_braille_dots_13478 = 0x10028cd, // U+28CD BRAILLE PATTERN DOTS-13478 ++ XK_braille_dots_23478 = 0x10028ce, // U+28CE BRAILLE PATTERN DOTS-23478 ++ XK_braille_dots_123478 = 0x10028cf, // U+28CF BRAILLE PATTERN DOTS-123478 ++ XK_braille_dots_578 = 0x10028d0, // U+28D0 BRAILLE PATTERN DOTS-578 ++ XK_braille_dots_1578 = 0x10028d1, // U+28D1 BRAILLE PATTERN DOTS-1578 ++ XK_braille_dots_2578 = 0x10028d2, // U+28D2 BRAILLE PATTERN DOTS-2578 ++ XK_braille_dots_12578 = 0x10028d3, // U+28D3 BRAILLE PATTERN DOTS-12578 ++ XK_braille_dots_3578 = 0x10028d4, // U+28D4 BRAILLE PATTERN DOTS-3578 ++ XK_braille_dots_13578 = 0x10028d5, // U+28D5 BRAILLE PATTERN DOTS-13578 ++ XK_braille_dots_23578 = 0x10028d6, // U+28D6 BRAILLE PATTERN DOTS-23578 ++ XK_braille_dots_123578 = 0x10028d7, // U+28D7 BRAILLE PATTERN DOTS-123578 ++ XK_braille_dots_4578 = 0x10028d8, // U+28D8 BRAILLE PATTERN DOTS-4578 ++ XK_braille_dots_14578 = 0x10028d9, // U+28D9 BRAILLE PATTERN DOTS-14578 ++ XK_braille_dots_24578 = 0x10028da, // U+28DA BRAILLE PATTERN DOTS-24578 ++ XK_braille_dots_124578 = 0x10028db, // U+28DB BRAILLE PATTERN DOTS-124578 ++ XK_braille_dots_34578 = 0x10028dc, // U+28DC BRAILLE PATTERN DOTS-34578 ++ XK_braille_dots_134578 = 0x10028dd, // U+28DD BRAILLE PATTERN DOTS-134578 ++ XK_braille_dots_234578 = 0x10028de, // U+28DE BRAILLE PATTERN DOTS-234578 ++ XK_braille_dots_1234578 = 0x10028df, // U+28DF BRAILLE PATTERN DOTS-1234578 ++ XK_braille_dots_678 = 0x10028e0, // U+28E0 BRAILLE PATTERN DOTS-678 ++ XK_braille_dots_1678 = 0x10028e1, // U+28E1 BRAILLE PATTERN DOTS-1678 ++ XK_braille_dots_2678 = 0x10028e2, // U+28E2 BRAILLE PATTERN DOTS-2678 ++ XK_braille_dots_12678 = 0x10028e3, // U+28E3 BRAILLE PATTERN DOTS-12678 ++ XK_braille_dots_3678 = 0x10028e4, // U+28E4 BRAILLE PATTERN DOTS-3678 ++ XK_braille_dots_13678 = 0x10028e5, // U+28E5 BRAILLE PATTERN DOTS-13678 ++ XK_braille_dots_23678 = 0x10028e6, // U+28E6 BRAILLE PATTERN DOTS-23678 ++ XK_braille_dots_123678 = 0x10028e7, // U+28E7 BRAILLE PATTERN DOTS-123678 ++ XK_braille_dots_4678 = 0x10028e8, // U+28E8 BRAILLE PATTERN DOTS-4678 ++ XK_braille_dots_14678 = 0x10028e9, // U+28E9 BRAILLE PATTERN DOTS-14678 ++ XK_braille_dots_24678 = 0x10028ea, // U+28EA BRAILLE PATTERN DOTS-24678 ++ XK_braille_dots_124678 = 0x10028eb, // U+28EB BRAILLE PATTERN DOTS-124678 ++ XK_braille_dots_34678 = 0x10028ec, // U+28EC BRAILLE PATTERN DOTS-34678 ++ XK_braille_dots_134678 = 0x10028ed, // U+28ED BRAILLE PATTERN DOTS-134678 ++ XK_braille_dots_234678 = 0x10028ee, // U+28EE BRAILLE PATTERN DOTS-234678 ++ XK_braille_dots_1234678 = 0x10028ef, // U+28EF BRAILLE PATTERN DOTS-1234678 ++ XK_braille_dots_5678 = 0x10028f0, // U+28F0 BRAILLE PATTERN DOTS-5678 ++ XK_braille_dots_15678 = 0x10028f1, // U+28F1 BRAILLE PATTERN DOTS-15678 ++ XK_braille_dots_25678 = 0x10028f2, // U+28F2 BRAILLE PATTERN DOTS-25678 ++ XK_braille_dots_125678 = 0x10028f3, // U+28F3 BRAILLE PATTERN DOTS-125678 ++ XK_braille_dots_35678 = 0x10028f4, // U+28F4 BRAILLE PATTERN DOTS-35678 ++ XK_braille_dots_135678 = 0x10028f5, // U+28F5 BRAILLE PATTERN DOTS-135678 ++ XK_braille_dots_235678 = 0x10028f6, // U+28F6 BRAILLE PATTERN DOTS-235678 ++ XK_braille_dots_1235678 = 0x10028f7, // U+28F7 BRAILLE PATTERN DOTS-1235678 ++ XK_braille_dots_45678 = 0x10028f8, // U+28F8 BRAILLE PATTERN DOTS-45678 ++ XK_braille_dots_145678 = 0x10028f9, // U+28F9 BRAILLE PATTERN DOTS-145678 ++ XK_braille_dots_245678 = 0x10028fa, // U+28FA BRAILLE PATTERN DOTS-245678 ++ XK_braille_dots_1245678 = 0x10028fb, // U+28FB BRAILLE PATTERN DOTS-1245678 ++ XK_braille_dots_345678 = 0x10028fc, // U+28FC BRAILLE PATTERN DOTS-345678 ++ XK_braille_dots_1345678 = 0x10028fd, // U+28FD BRAILLE PATTERN DOTS-1345678 ++ XK_braille_dots_2345678 = 0x10028fe, // U+28FE BRAILLE PATTERN DOTS-2345678 ++ XK_braille_dots_12345678 = 0x10028ff, // U+28FF BRAILLE PATTERN DOTS-12345678 ++ ++ XK_Sinh_ng = 0x1000d82, // U+0D82 SINHALA SIGN ANUSVARAYA ++ XK_Sinh_h2 = 0x1000d83, // U+0D83 SINHALA SIGN VISARGAYA ++ XK_Sinh_a = 0x1000d85, // U+0D85 SINHALA LETTER AYANNA ++ XK_Sinh_aa = 0x1000d86, // U+0D86 SINHALA LETTER AAYANNA ++ XK_Sinh_ae = 0x1000d87, // U+0D87 SINHALA LETTER AEYANNA ++ XK_Sinh_aee = 0x1000d88, // U+0D88 SINHALA LETTER AEEYANNA ++ XK_Sinh_i = 0x1000d89, // U+0D89 SINHALA LETTER IYANNA ++ XK_Sinh_ii = 0x1000d8a, // U+0D8A SINHALA LETTER IIYANNA ++ XK_Sinh_u = 0x1000d8b, // U+0D8B SINHALA LETTER UYANNA ++ XK_Sinh_uu = 0x1000d8c, // U+0D8C SINHALA LETTER UUYANNA ++ XK_Sinh_ri = 0x1000d8d, // U+0D8D SINHALA LETTER IRUYANNA ++ XK_Sinh_rii = 0x1000d8e, // U+0D8E SINHALA LETTER IRUUYANNA ++ XK_Sinh_lu = 0x1000d8f, // U+0D8F SINHALA LETTER ILUYANNA ++ XK_Sinh_luu = 0x1000d90, // U+0D90 SINHALA LETTER ILUUYANNA ++ XK_Sinh_e = 0x1000d91, // U+0D91 SINHALA LETTER EYANNA ++ XK_Sinh_ee = 0x1000d92, // U+0D92 SINHALA LETTER EEYANNA ++ XK_Sinh_ai = 0x1000d93, // U+0D93 SINHALA LETTER AIYANNA ++ XK_Sinh_o = 0x1000d94, // U+0D94 SINHALA LETTER OYANNA ++ XK_Sinh_oo = 0x1000d95, // U+0D95 SINHALA LETTER OOYANNA ++ XK_Sinh_au = 0x1000d96, // U+0D96 SINHALA LETTER AUYANNA ++ XK_Sinh_ka = 0x1000d9a, // U+0D9A SINHALA LETTER ALPAPRAANA KAYANNA ++ XK_Sinh_kha = 0x1000d9b, // U+0D9B SINHALA LETTER MAHAAPRAANA KAYANNA ++ XK_Sinh_ga = 0x1000d9c, // U+0D9C SINHALA LETTER ALPAPRAANA GAYANNA ++ XK_Sinh_gha = 0x1000d9d, // U+0D9D SINHALA LETTER MAHAAPRAANA GAYANNA ++ XK_Sinh_ng2 = 0x1000d9e, // U+0D9E SINHALA LETTER KANTAJA NAASIKYAYA ++ XK_Sinh_nga = 0x1000d9f, // U+0D9F SINHALA LETTER SANYAKA GAYANNA ++ XK_Sinh_ca = 0x1000da0, // U+0DA0 SINHALA LETTER ALPAPRAANA CAYANNA ++ XK_Sinh_cha = 0x1000da1, // U+0DA1 SINHALA LETTER MAHAAPRAANA CAYANNA ++ XK_Sinh_ja = 0x1000da2, // U+0DA2 SINHALA LETTER ALPAPRAANA JAYANNA ++ XK_Sinh_jha = 0x1000da3, // U+0DA3 SINHALA LETTER MAHAAPRAANA JAYANNA ++ XK_Sinh_nya = 0x1000da4, // U+0DA4 SINHALA LETTER TAALUJA NAASIKYAYA ++ XK_Sinh_jnya = 0x1000da5, // U+0DA5 SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA ++ XK_Sinh_nja = 0x1000da6, // U+0DA6 SINHALA LETTER SANYAKA JAYANNA ++ XK_Sinh_tta = 0x1000da7, // U+0DA7 SINHALA LETTER ALPAPRAANA TTAYANNA ++ XK_Sinh_ttha = 0x1000da8, // U+0DA8 SINHALA LETTER MAHAAPRAANA TTAYANNA ++ XK_Sinh_dda = 0x1000da9, // U+0DA9 SINHALA LETTER ALPAPRAANA DDAYANNA ++ XK_Sinh_ddha = 0x1000daa, // U+0DAA SINHALA LETTER MAHAAPRAANA DDAYANNA ++ XK_Sinh_nna = 0x1000dab, // U+0DAB SINHALA LETTER MUURDHAJA NAYANNA ++ XK_Sinh_ndda = 0x1000dac, // U+0DAC SINHALA LETTER SANYAKA DDAYANNA ++ XK_Sinh_tha = 0x1000dad, // U+0DAD SINHALA LETTER ALPAPRAANA TAYANNA ++ XK_Sinh_thha = 0x1000dae, // U+0DAE SINHALA LETTER MAHAAPRAANA TAYANNA ++ XK_Sinh_dha = 0x1000daf, // U+0DAF SINHALA LETTER ALPAPRAANA DAYANNA ++ XK_Sinh_dhha = 0x1000db0, // U+0DB0 SINHALA LETTER MAHAAPRAANA DAYANNA ++ XK_Sinh_na = 0x1000db1, // U+0DB1 SINHALA LETTER DANTAJA NAYANNA ++ XK_Sinh_ndha = 0x1000db3, // U+0DB3 SINHALA LETTER SANYAKA DAYANNA ++ XK_Sinh_pa = 0x1000db4, // U+0DB4 SINHALA LETTER ALPAPRAANA PAYANNA ++ XK_Sinh_pha = 0x1000db5, // U+0DB5 SINHALA LETTER MAHAAPRAANA PAYANNA ++ XK_Sinh_ba = 0x1000db6, // U+0DB6 SINHALA LETTER ALPAPRAANA BAYANNA ++ XK_Sinh_bha = 0x1000db7, // U+0DB7 SINHALA LETTER MAHAAPRAANA BAYANNA ++ XK_Sinh_ma = 0x1000db8, // U+0DB8 SINHALA LETTER MAYANNA ++ XK_Sinh_mba = 0x1000db9, // U+0DB9 SINHALA LETTER AMBA BAYANNA ++ XK_Sinh_ya = 0x1000dba, // U+0DBA SINHALA LETTER YAYANNA ++ XK_Sinh_ra = 0x1000dbb, // U+0DBB SINHALA LETTER RAYANNA ++ XK_Sinh_la = 0x1000dbd, // U+0DBD SINHALA LETTER DANTAJA LAYANNA ++ XK_Sinh_va = 0x1000dc0, // U+0DC0 SINHALA LETTER VAYANNA ++ XK_Sinh_sha = 0x1000dc1, // U+0DC1 SINHALA LETTER TAALUJA SAYANNA ++ XK_Sinh_ssha = 0x1000dc2, // U+0DC2 SINHALA LETTER MUURDHAJA SAYANNA ++ XK_Sinh_sa = 0x1000dc3, // U+0DC3 SINHALA LETTER DANTAJA SAYANNA ++ XK_Sinh_ha = 0x1000dc4, // U+0DC4 SINHALA LETTER HAYANNA ++ XK_Sinh_lla = 0x1000dc5, // U+0DC5 SINHALA LETTER MUURDHAJA LAYANNA ++ XK_Sinh_fa = 0x1000dc6, // U+0DC6 SINHALA LETTER FAYANNA ++ XK_Sinh_al = 0x1000dca, // U+0DCA SINHALA SIGN AL-LAKUNA ++ XK_Sinh_aa2 = 0x1000dcf, // U+0DCF SINHALA VOWEL SIGN AELA-PILLA ++ XK_Sinh_ae2 = 0x1000dd0, // U+0DD0 SINHALA VOWEL SIGN KETTI AEDA-PILLA ++ XK_Sinh_aee2 = 0x1000dd1, // U+0DD1 SINHALA VOWEL SIGN DIGA AEDA-PILLA ++ XK_Sinh_i2 = 0x1000dd2, // U+0DD2 SINHALA VOWEL SIGN KETTI IS-PILLA ++ XK_Sinh_ii2 = 0x1000dd3, // U+0DD3 SINHALA VOWEL SIGN DIGA IS-PILLA ++ XK_Sinh_u2 = 0x1000dd4, // U+0DD4 SINHALA VOWEL SIGN KETTI PAA-PILLA ++ XK_Sinh_uu2 = 0x1000dd6, // U+0DD6 SINHALA VOWEL SIGN DIGA PAA-PILLA ++ XK_Sinh_ru2 = 0x1000dd8, // U+0DD8 SINHALA VOWEL SIGN GAETTA-PILLA ++ XK_Sinh_e2 = 0x1000dd9, // U+0DD9 SINHALA VOWEL SIGN KOMBUVA ++ XK_Sinh_ee2 = 0x1000dda, // U+0DDA SINHALA VOWEL SIGN DIGA KOMBUVA ++ XK_Sinh_ai2 = 0x1000ddb, // U+0DDB SINHALA VOWEL SIGN KOMBU DEKA ++ XK_Sinh_o2 = 0x1000ddc, // U+0DDC SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA ++ XK_Sinh_oo2 = 0x1000ddd, // U+0DDD SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA ++ XK_Sinh_au2 = 0x1000dde, // U+0DDE SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA ++ XK_Sinh_lu2 = 0x1000ddf, // U+0DDF SINHALA VOWEL SIGN GAYANUKITTA ++ XK_Sinh_ruu2 = 0x1000df2, // U+0DF2 SINHALA VOWEL SIGN DIGA GAETTA-PILLA ++ XK_Sinh_luu2 = 0x1000df3, // U+0DF3 SINHALA VOWEL SIGN DIGA GAYANUKITTA ++ XK_Sinh_kunddaliya = 0x1000df4, // U+0DF4 SINHALA PUNCTUATION KUNDDALIYA ++}; +diff --git a/src/x11.zig b/src/x11.zig +index 9b8cbd2..a0a2cf4 100644 +--- a/src/x11.zig ++++ b/src/x11.zig +@@ -37,3 +37,5 @@ pub const EventType = enum(c_int) { + mapping_notify = 34, + generic_event = 35, + }; ++ ++pub const Keysym = @import("./x11.Keysym.zig").Keysym; diff --git a/testdata/diff-f58200e3f2967a06f343c9fc9dcae9de18def92a b/testdata/diff-f58200e3f2967a06f343c9fc9dcae9de18def92a new file mode 100644 index 0000000000000000000000000000000000000000..edbbee493d584bf1faea926fb70f95bf218017b1 --- /dev/null +++ b/testdata/diff-f58200e3f2967a06f343c9fc9dcae9de18def92a @@ -0,0 +1,6888 @@ +:100644 100644 41bc62cead176f9307835337b00615e2e1f74f6b d21ea2791c62f3b912f586e56882346c00321647 M CMakeLists.txt +:100644 100644 0466b79bf2dbeb803d653eff2f2a48880da3669b e8d54cc0cd314cc8a7e8e2cf2fb1c20106b33078 M build.zig +:100644 100755 0a7ba5d277c3ccdc6357f92807b80bb7eb855bc7 0a7ba5d277c3ccdc6357f92807b80bb7eb855bc7 M ci/x86_64-linux-debug-llvm.sh +:100644 100644 578139c5ac08a4d7eb4e298ea3354e4b9c1ee72d 79a120d5a2ccdde4c037297e677420b065a24b04 M lib/compiler_rt/fma.zig +:100644 100644 dad60b725bc267a906e5c88abeb1ee342f818160 0f47a0b64781e423ec680cb162eb33e3ec51eddb M lib/std/Build/Step/Compile.zig +:100644 100644 bef80d782b20e759701c73a3fe85909985415f42 43b542c09e047ff0ae723f710750f396e18bbf08 M lib/std/elf.zig +:100644 100644 b2116c1a7429b5791d8e39d66dd7e66ad64337e0 55f1fd14cb6cfa8421a142a142802710c9944bd5 M lib/std/zig/system.zig +:100644 100644 34953ed11a12e334a1ecd995de399421a896a5bb bf7246b8d8b8fe3df2c4ac1c4fb6124fe55e134b M src/Compilation.zig +:100644 100644 d8751251da9e24db98c79f7964e0ea1a9bde78c8 45f7e509de609a4ab10651d27e49a1cb645eb2b6 M src/Compilation/Config.zig +:100644 100644 996549774294455b642ef3286d3d20be0bd404f5 f4344af86d46be017beacf31e90c581493517b0f M src/InternPool.zig +:100644 100644 946e890ea3566e0cc1ab2aae453d389ecfab702b d0576de33d4d3077f7fa177ba4e0b8e9b438ee69 M src/Sema.zig +:100644 100644 8de562176107ae28fb15ce2e6ed241aa7f176e16 381eacf45ab2389c950aad0dd9f0ed886e9a8bcb M src/Value.zig +:100644 100644 706bdb51655409a6e2c23e36d580d0c81c01f350 8e9e9c29025c4e82af1d14ece0eca9b7d9bd06e4 M src/Zcu.zig +:100644 100644 77cddb204e82eeeba3b349b0ed2216974d06f14c 32782e7e8952462d2991ff0b3bf3bbe8e0b72c64 M src/Zcu/PerThread.zig +:100644 100644 7b13cfc90d68b760251c236bd43890858a088dd9 fe40ba4bbb16ffcbcc2768af9a6f8a57600c1e4f M src/arch/riscv64/CodeGen.zig +:100644 100644 2e72aff941072c7e5d7164eace99b5d919dc4ece 64a476007cf9881e5101c5c945158252b1ba5b86 M src/arch/riscv64/Emit.zig +:100644 100644 6fb8e23a98c3b0e89ee5139429fc11626fb2ecc7 204ab6a3c06226635b1619b60c205f02f8447884 M src/arch/riscv64/Mir.zig +:100644 100644 d41f1cdf07aa54b3c55a9917826a7b55a7da23b0 26282b09ab4f5c831cea32e9c9dbf8d6e0b2256a M src/arch/sparc64/Emit.zig +:100644 100644 842ac10fed1af8fbaeadb7b2c0404a20f806abc0 41d135eb831fefe51afd3fde7925596fce9d441b M src/arch/sparc64/Mir.zig +:100644 100644 b5760c95ac2b54f5e03c32e3d61a4c32e01f3a46 1827b50d61a06e05f525461fb8261922f36920bf M src/arch/x86_64/CodeGen.zig +:100644 100644 84bb325322ac20c100da1e85c715a99f7e251deb c2b38d8e6d45b3439d2f8bb6cf9e518ac17784cc M src/arch/x86_64/Emit.zig +:100644 100644 e70018850d621aff1a360044014f1ea1e8516a44 caf41ffb392d07b8a455f09181c77ffb8a679d7e M src/arch/x86_64/Mir.zig +:100644 100644 835093d11ab8d38f622252233101c1a3c9d8904d 05048109335e0256d91c5f350d7fa900ce08e402 M src/arch/x86_64/bits.zig +:100644 100644 03ff7134f62d04025081f06b50248545433130ec 1d9c67175ef204933a5463393cad189d0e59e7fa M src/arch/x86_64/encoder.zig +:100644 100644 56e6e7c99fb3bd8208ce92e912c03f3d2404f2c1 4cbf3f56169ec9227f961a72720898cc23df3f96 M src/codegen.zig +:100644 100644 318a51da95bfe1c047447f96cde8a83f993c9f80 be6478eae896f3d70d874e609d3c3d263946872a M src/codegen/aarch64/Mir.zig +:100644 100644 ac30cedecd8318da8f38e96e45d763fc2d70bc1f 266796a2dc2dda022bd7c4c3027c950a446d9dc9 M src/dev.zig +:100644 100644 27cd6620e359284f0a6398aa23a5f8ade66446d7 277013efb3094cee331db13b15fd1e5d2d08d7e4 M src/link.zig +:100644 100644 e016473531aede3998c41f42a85745fbf017c63c f3e3b3d0b530d498f1b8d4518c1d9c06d4a69baa M src/link/Coff.zig +:100644 100644 f4af5f4148ad11f2eeb0688ccd11a39120404d6b 595e3583d5d540bdd0fe0ce1727d0a25eed72f50 M src/link/Dwarf.zig +:100644 100644 b74406c368d5cc4eb3da41365236bc79387bf7c2 d7e3cf62f3a378970682797fb538227d9c70795d M src/link/Elf/LinkerDefined.zig +:100644 100644 8c79def16bff14a9878ab22cea2ee6e1aca7c160 4dce40e37094e9a48db41d35ce189af38b63c287 M src/link/Elf/SharedObject.zig +:100644 100644 bf65d04e4a13b3980749bfcc1af24f52d4ac3b49 a3ede11dc4003cd0f9d1f671dfccc5c095b16a82 M src/link/Elf/ZigObject.zig +:000000 100644 0000000000000000000000000000000000000000 e43ebf2639ad88db8d125d2a79877173d771f73d A src/link/Elf2.zig +:100644 100644 b1fc6528d5808663942b0428869f0c72efda1931 5a0a71f380c8a83c66b4f4e5391e4ec54469033e M src/link/MachO/ZigObject.zig +:000000 100644 0000000000000000000000000000000000000000 d04a8d533a03f8934a8546311007b867bde353d0 A src/link/MappedFile.zig +:100644 100644 9f4535e1fe4ef7c6458ee94b571b4157ba422dc8 742b4664f178955b4668f130ebbacab0b9ac2550 M src/link/Queue.zig +:100644 100644 a125a70aae790e7b750c96304bae1bdb3c86376c d60b91c30f93695076b8299c7e92d8f734812d32 M src/link/Wasm.zig +:100644 100644 26d44c4463be802e0e7dea899980b28010b8ffc7 9d43e47ea2dbd949122ab7abfdf285ade21bc987 M src/main.zig +:100644 100644 e999d2ae22663bcd84a9eb1fc112a317b12a9c02 1cf5c9b08274a55f6cd956ae433e4fb7141e1abd M src/target.zig +:100644 100644 01605bdeeb36e4d51e986526e94c9a36e2cf07fa e492930031e7fb5d22d68402bc3e59299a084402 M test/incremental/change_exports +:100644 100644 3e400b854eb60b4a81a3c9b2f0e3511e11ec3b26 699134100eec6942bc2414d29ab7188332f3a45a M test/incremental/change_panic_handler +:100644 100644 9f7eb6c12f10b42d80e998f352ac9a0a1d5d0842 2d068d593eeb77a07b9c249fc0d7542f1cee4c6c M test/incremental/change_panic_handler_explicit +:100644 100644 97049a1fc03ae2d9dfbdd07e6c06a9e756f133aa f3bfbbdd6922a0266e42c41f8e92cc96e15bc9fc M test/incremental/change_struct_same_fields +:100644 100644 5c5d3329750eadc813f892bce6e05234ad563242 3bcae1cd211281cc29d4b970240174c40613fdd6 M test/incremental/type_becomes_comptime_only + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 41bc62cead..d21ea2791c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -583,6 +583,7 @@ set(ZIG_STAGE2_SOURCES + src/link/Elf/relocatable.zig + src/link/Elf/relocation.zig + src/link/Elf/synthetic_sections.zig ++ src/link/Elf2.zig + src/link/Goff.zig + src/link/LdScript.zig + src/link/Lld.zig +@@ -612,6 +613,7 @@ set(ZIG_STAGE2_SOURCES + src/link/MachO/synthetic.zig + src/link/MachO/Thunk.zig + src/link/MachO/uuid.zig ++ src/link/MappedFile.zig + src/link/Queue.zig + src/link/StringTable.zig + src/link/Wasm.zig +diff --git a/build.zig b/build.zig +index 0466b79bf2..e8d54cc0cd 100644 +--- a/build.zig ++++ b/build.zig +@@ -202,6 +202,7 @@ pub fn build(b: *std.Build) !void { + }); + exe.pie = pie; + exe.entitlements = entitlements; ++ exe.use_new_linker = b.option(bool, "new-linker", "Use the new linker"); + + const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend"); + exe.use_llvm = use_llvm; +diff --git a/ci/x86_64-linux-debug-llvm.sh b/ci/x86_64-linux-debug-llvm.sh +old mode 100644 +new mode 100755 +diff --git a/lib/compiler_rt/fma.zig b/lib/compiler_rt/fma.zig +index 578139c5ac..79a120d5a2 100644 +--- a/lib/compiler_rt/fma.zig ++++ b/lib/compiler_rt/fma.zig +@@ -203,7 +203,7 @@ fn add_adjusted(a: f64, b: f64) f64 { + if (uhii & 1 == 0) { + // hibits += copysign(1.0, sum.hi, sum.lo) + const uloi: u64 = @bitCast(sum.lo); +- uhii += 1 - ((uhii ^ uloi) >> 62); ++ uhii = uhii + 1 - ((uhii ^ uloi) >> 62); + sum.hi = @bitCast(uhii); + } + } +@@ -217,7 +217,7 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 { + const bits_lost = -@as(i32, @intCast((uhii >> 52) & 0x7FF)) - scale + 1; + if ((bits_lost != 1) == (uhii & 1 != 0)) { + const uloi: u64 = @bitCast(sum.lo); +- uhii += 1 - (((uhii ^ uloi) >> 62) & 2); ++ uhii = uhii + 1 - (((uhii ^ uloi) >> 62) & 2); + sum.hi = @bitCast(uhii); + } + } +@@ -259,7 +259,7 @@ fn add_adjusted128(a: f128, b: f128) f128 { + if (uhii & 1 == 0) { + // hibits += copysign(1.0, sum.hi, sum.lo) + const uloi: u128 = @bitCast(sum.lo); +- uhii += 1 - ((uhii ^ uloi) >> 126); ++ uhii = uhii + 1 - ((uhii ^ uloi) >> 126); + sum.hi = @bitCast(uhii); + } + } +@@ -284,7 +284,7 @@ fn add_and_denorm128(a: f128, b: f128, scale: i32) f128 { + const bits_lost = -@as(i32, @intCast((uhii >> 112) & 0x7FFF)) - scale + 1; + if ((bits_lost != 1) == (uhii & 1 != 0)) { + const uloi: u128 = @bitCast(sum.lo); +- uhii += 1 - (((uhii ^ uloi) >> 126) & 2); ++ uhii = uhii + 1 - (((uhii ^ uloi) >> 126) & 2); + sum.hi = @bitCast(uhii); + } + } +diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig +index dad60b725b..0f47a0b647 100644 +--- a/lib/std/Build/Step/Compile.zig ++++ b/lib/std/Build/Step/Compile.zig +@@ -192,6 +192,7 @@ want_lto: ?bool = null, + + use_llvm: ?bool, + use_lld: ?bool, ++use_new_linker: ?bool, + + /// Corresponds to the `-fallow-so-scripts` / `-fno-allow-so-scripts` CLI + /// flags, overriding the global user setting provided to the `zig build` +@@ -441,6 +442,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { + + .use_llvm = options.use_llvm, + .use_lld = options.use_lld, ++ .use_new_linker = null, + + .zig_process = null, + }; +@@ -1096,6 +1098,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { + + try addFlag(&zig_args, "llvm", compile.use_llvm); + try addFlag(&zig_args, "lld", compile.use_lld); ++ try addFlag(&zig_args, "new-linker", compile.use_new_linker); + + if (compile.root_module.resolved_target.?.query.ofmt) |ofmt| { + try zig_args.append(try std.fmt.allocPrint(arena, "-ofmt={s}", .{@tagName(ofmt)})); +diff --git a/lib/std/elf.zig b/lib/std/elf.zig +index bef80d782b..43b542c09e 100644 +--- a/lib/std/elf.zig ++++ b/lib/std/elf.zig +@@ -323,6 +323,8 @@ pub const PT_LOPROC = 0x70000000; + /// End of processor-specific + pub const PT_HIPROC = 0x7fffffff; + ++pub const PN_XNUM = 0xffff; ++ + /// Section header table entry unused + pub const SHT_NULL = 0; + /// Program data +@@ -385,63 +387,149 @@ pub const SHT_HIUSER = 0xffffffff; + // Note type for .note.gnu.build_id + pub const NT_GNU_BUILD_ID = 3; + +-/// Local symbol +-pub const STB_LOCAL = 0; +-/// Global symbol +-pub const STB_GLOBAL = 1; +-/// Weak symbol +-pub const STB_WEAK = 2; +-/// Number of defined types +-pub const STB_NUM = 3; +-/// Start of OS-specific +-pub const STB_LOOS = 10; +-/// Unique symbol +-pub const STB_GNU_UNIQUE = 10; +-/// End of OS-specific +-pub const STB_HIOS = 12; +-/// Start of processor-specific +-pub const STB_LOPROC = 13; +-/// End of processor-specific +-pub const STB_HIPROC = 15; +- +-pub const STB_MIPS_SPLIT_COMMON = 13; +- +-/// Symbol type is unspecified +-pub const STT_NOTYPE = 0; +-/// Symbol is a data object +-pub const STT_OBJECT = 1; +-/// Symbol is a code object +-pub const STT_FUNC = 2; +-/// Symbol associated with a section +-pub const STT_SECTION = 3; +-/// Symbol's name is file name +-pub const STT_FILE = 4; +-/// Symbol is a common data object +-pub const STT_COMMON = 5; +-/// Symbol is thread-local data object +-pub const STT_TLS = 6; +-/// Number of defined types +-pub const STT_NUM = 7; +-/// Start of OS-specific +-pub const STT_LOOS = 10; +-/// Symbol is indirect code object +-pub const STT_GNU_IFUNC = 10; +-/// End of OS-specific +-pub const STT_HIOS = 12; +-/// Start of processor-specific +-pub const STT_LOPROC = 13; +-/// End of processor-specific +-pub const STT_HIPROC = 15; ++/// Deprecated, use `@intFromEnum(std.elf.STB.LOCAL)` ++pub const STB_LOCAL = @intFromEnum(STB.LOCAL); ++/// Deprecated, use `@intFromEnum(std.elf.STB.GLOBAL)` ++pub const STB_GLOBAL = @intFromEnum(STB.GLOBAL); ++/// Deprecated, use `@intFromEnum(std.elf.STB.WEAK)` ++pub const STB_WEAK = @intFromEnum(STB.WEAK); ++/// Deprecated, use `std.elf.STB.NUM` ++pub const STB_NUM = STB.NUM; ++/// Deprecated, use `@intFromEnum(std.elf.STB.LOOS)` ++pub const STB_LOOS = @intFromEnum(STB.LOOS); ++/// Deprecated, use `@intFromEnum(std.elf.STB.GNU_UNIQUE)` ++pub const STB_GNU_UNIQUE = @intFromEnum(STB.GNU_UNIQUE); ++/// Deprecated, use `@intFromEnum(std.elf.STB.HIOS)` ++pub const STB_HIOS = @intFromEnum(STB.HIOS); ++/// Deprecated, use `@intFromEnum(std.elf.STB.LOPROC)` ++pub const STB_LOPROC = @intFromEnum(STB.LOPROC); ++/// Deprecated, use `@intFromEnum(std.elf.STB.HIPROC)` ++pub const STB_HIPROC = @intFromEnum(STB.HIPROC); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STB.MIPS_SPLIT_COMMON)` ++pub const STB_MIPS_SPLIT_COMMON = @intFromEnum(STB.MIBS_SPLIT_COMMON); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STT.NOTYPE)` ++pub const STT_NOTYPE = @intFromEnum(STT.NOTYPE); ++/// Deprecated, use `@intFromEnum(std.elf.STT.OBJECT)` ++pub const STT_OBJECT = @intFromEnum(STT.OBJECT); ++/// Deprecated, use `@intFromEnum(std.elf.STT.FUNC)` ++pub const STT_FUNC = @intFromEnum(STT.FUNC); ++/// Deprecated, use `@intFromEnum(std.elf.STT.SECTION)` ++pub const STT_SECTION = @intFromEnum(STT.SECTION); ++/// Deprecated, use `@intFromEnum(std.elf.STT.FILE)` ++pub const STT_FILE = @intFromEnum(STT.FILE); ++/// Deprecated, use `@intFromEnum(std.elf.STT.COMMON)` ++pub const STT_COMMON = @intFromEnum(STT.COMMON); ++/// Deprecated, use `@intFromEnum(std.elf.STT.TLS)` ++pub const STT_TLS = @intFromEnum(STT.TLS); ++/// Deprecated, use `std.elf.STT.NUM` ++pub const STT_NUM = STT.NUM; ++/// Deprecated, use `@intFromEnum(std.elf.STT.LOOS)` ++pub const STT_LOOS = @intFromEnum(STT.LOOS); ++/// Deprecated, use `@intFromEnum(std.elf.STT.GNU_IFUNC)` ++pub const STT_GNU_IFUNC = @intFromEnum(STT.GNU_IFUNC); ++/// Deprecated, use `@intFromEnum(std.elf.STT.HIOS)` ++pub const STT_HIOS = @intFromEnum(STT.HIOS); ++/// Deprecated, use `@intFromEnum(std.elf.STT.LOPROC)` ++pub const STT_LOPROC = @intFromEnum(STT.LOPROC); ++/// Deprecated, use `@intFromEnum(std.elf.STT.HIPROC)` ++pub const STT_HIPROC = @intFromEnum(STT.HIPROC); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STT.SPARC_REGISTER)` ++pub const STT_SPARC_REGISTER = @intFromEnum(STT.SPARC_REGISTER); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STT.PARISC_MILLICODE)` ++pub const STT_PARISC_MILLICODE = @intFromEnum(STT.PARISC_MILLICODE); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STT.HP_OPAQUE)` ++pub const STT_HP_OPAQUE = @intFromEnum(STT.HP_OPAQUE); ++/// Deprecated, use `@intFromEnum(std.elf.STT.HP_STUB)` ++pub const STT_HP_STUB = @intFromEnum(STT.HP_STUB); ++ ++/// Deprecated, use `@intFromEnum(std.elf.STT.ARM_TFUNC)` ++pub const STT_ARM_TFUNC = @intFromEnum(STT.ARM_TFUNC); ++/// Deprecated, use `@intFromEnum(std.elf.STT.ARM_16BIT)` ++pub const STT_ARM_16BIT = @intFromEnum(STT.ARM_16BIT); ++ ++pub const STB = enum(u4) { ++ /// Local symbol ++ LOCAL = 0, ++ /// Global symbol ++ GLOBAL = 1, ++ /// Weak symbol ++ WEAK = 2, ++ _, ++ ++ /// Number of defined types ++ pub const NUM = @typeInfo(STB).@"enum".fields.len; ++ ++ /// Start of OS-specific ++ pub const LOOS: STB = @enumFromInt(10); ++ /// End of OS-specific ++ pub const HIOS: STB = @enumFromInt(12); ++ ++ /// Unique symbol ++ pub const GNU_UNIQUE: STB = @enumFromInt(@intFromEnum(LOOS) + 0); ++ ++ /// Start of processor-specific ++ pub const LOPROC: STB = @enumFromInt(13); ++ /// End of processor-specific ++ pub const HIPROC: STB = @enumFromInt(15); ++ ++ pub const MIPS_SPLIT_COMMON: STB = @enumFromInt(@intFromEnum(LOPROC) + 0); ++}; ++ ++pub const STT = enum(u4) { ++ /// Symbol type is unspecified ++ NOTYPE = 0, ++ /// Symbol is a data object ++ OBJECT = 1, ++ /// Symbol is a code object ++ FUNC = 2, ++ /// Symbol associated with a section ++ SECTION = 3, ++ /// Symbol's name is file name ++ FILE = 4, ++ /// Symbol is a common data object ++ COMMON = 5, ++ /// Symbol is thread-local data object ++ TLS = 6, ++ _, ++ ++ /// Number of defined types ++ pub const NUM = @typeInfo(STT).@"enum".fields.len; ++ ++ /// Start of OS-specific ++ pub const LOOS: STT = @enumFromInt(10); ++ /// End of OS-specific ++ pub const HIOS: STT = @enumFromInt(12); + +-pub const STT_SPARC_REGISTER = 13; ++ /// Symbol is indirect code object ++ pub const GNU_IFUNC: STT = @enumFromInt(@intFromEnum(LOOS) + 0); + +-pub const STT_PARISC_MILLICODE = 13; ++ pub const HP_OPAQUE: STT = @enumFromInt(@intFromEnum(LOOS) + 1); ++ pub const HP_STUB: STT = @enumFromInt(@intFromEnum(LOOS) + 2); + +-pub const STT_HP_OPAQUE = (STT_LOOS + 0x1); +-pub const STT_HP_STUB = (STT_LOOS + 0x2); ++ /// Start of processor-specific ++ pub const LOPROC: STT = @enumFromInt(13); ++ /// End of processor-specific ++ pub const HIPROC: STT = @enumFromInt(15); + +-pub const STT_ARM_TFUNC = STT_LOPROC; +-pub const STT_ARM_16BIT = STT_HIPROC; ++ pub const SPARC_REGISTER: STT = @enumFromInt(@intFromEnum(LOPROC) + 0); ++ ++ pub const PARISC_MILLICODE: STT = @enumFromInt(@intFromEnum(LOPROC) + 0); ++ ++ pub const ARM_TFUNC: STT = @enumFromInt(@intFromEnum(LOPROC) + 0); ++ pub const ARM_16BIT: STT = @enumFromInt(@intFromEnum(HIPROC) + 2); ++}; ++ ++pub const STV = enum(u3) { ++ DEFAULT = 0, ++ INTERNAL = 1, ++ HIDDEN = 2, ++ PROTECTED = 3, ++}; + + pub const MAGIC = "\x7fELF"; + +@@ -534,15 +622,15 @@ pub const Header = struct { + const buf = try r.peek(@sizeOf(Elf64_Ehdr)); + + if (!mem.eql(u8, buf[0..4], MAGIC)) return error.InvalidElfMagic; +- if (buf[EI_VERSION] != 1) return error.InvalidElfVersion; ++ if (buf[EI.VERSION] != 1) return error.InvalidElfVersion; + +- const endian: std.builtin.Endian = switch (buf[EI_DATA]) { ++ const endian: std.builtin.Endian = switch (buf[EI.DATA]) { + ELFDATA2LSB => .little, + ELFDATA2MSB => .big, + else => return error.InvalidElfEndian, + }; + +- return switch (buf[EI_CLASS]) { ++ return switch (buf[EI.CLASS]) { + ELFCLASS32 => .init(try r.takeStruct(Elf32_Ehdr, endian), endian), + ELFCLASS64 => .init(try r.takeStruct(Elf64_Ehdr, endian), endian), + else => return error.InvalidElfClass, +@@ -559,8 +647,8 @@ pub const Header = struct { + else => @compileError("bad type"), + }, + .endian = endian, +- .os_abi = @enumFromInt(hdr.e_ident[EI_OSABI]), +- .abi_version = hdr.e_ident[EI_ABIVERSION], ++ .os_abi = @enumFromInt(hdr.e_ident[EI.OSABI]), ++ .abi_version = hdr.e_ident[EI.ABIVERSION], + .type = hdr.e_type, + .machine = hdr.e_machine, + .entry = hdr.e_entry, +@@ -683,38 +771,200 @@ fn takeShdr(reader: *std.Io.Reader, elf_header: Header) !?Elf64_Shdr { + }; + } + +-pub const ELFCLASSNONE = 0; +-pub const ELFCLASS32 = 1; +-pub const ELFCLASS64 = 2; +-pub const ELFCLASSNUM = 3; +- +-pub const ELFDATANONE = 0; +-pub const ELFDATA2LSB = 1; +-pub const ELFDATA2MSB = 2; +-pub const ELFDATANUM = 3; +- +-pub const EI_CLASS = 4; +-pub const EI_DATA = 5; +-pub const EI_VERSION = 6; +-pub const EI_OSABI = 7; +-pub const EI_ABIVERSION = 8; +-pub const EI_PAD = 9; +- +-pub const EI_NIDENT = 16; ++pub const EI = struct { ++ pub const CLASS = 4; ++ pub const DATA = 5; ++ pub const VERSION = 6; ++ pub const OSABI = 7; ++ pub const ABIVERSION = 8; ++ pub const PAD = 9; ++ pub const NIDENT = 16; ++}; ++ ++/// Deprecated, use `std.elf.EI.CLASS` ++pub const EI_CLASS = EI.CLASS; ++/// Deprecated, use `std.elf.EI.DATA` ++pub const EI_DATA = EI.DATA; ++/// Deprecated, use `std.elf.EI.VERSION` ++pub const EI_VERSION = EI.VERSION; ++/// Deprecated, use `std.elf.EI.OSABI` ++pub const EI_OSABI = EI.OSABI; ++/// Deprecated, use `std.elf.EI.ABIVERSION` ++pub const EI_ABIVERSION = EI.ABIVERSION; ++/// Deprecated, use `std.elf.EI.PAD` ++pub const EI_PAD = EI.PAD; ++/// Deprecated, use `std.elf.EI.NIDENT` ++pub const EI_NIDENT = EI.NIDENT; + + pub const Half = u16; + pub const Word = u32; + pub const Sword = i32; +-pub const Elf32_Xword = u64; +-pub const Elf32_Sxword = i64; +-pub const Elf64_Xword = u64; ++pub const Xword = u64; ++pub const Sxword = i64; ++pub const Section = u16; ++pub const Elf32 = struct { ++ pub const Addr = u32; ++ pub const Off = u32; ++ pub const Ehdr = extern struct { ++ ident: [EI.NIDENT]u8, ++ type: ET, ++ machine: EM, ++ version: Word, ++ entry: Elf32.Addr, ++ phoff: Elf32.Off, ++ shoff: Elf32.Off, ++ flags: Word, ++ ehsize: Half, ++ phentsize: Half, ++ phnum: Half, ++ shentsize: Half, ++ shnum: Half, ++ shstrndx: Half, ++ }; ++ pub const Phdr = extern struct { ++ type: Word, ++ offset: Elf32.Off, ++ vaddr: Elf32.Addr, ++ paddr: Elf32.Addr, ++ filesz: Word, ++ memsz: Word, ++ flags: PF, ++ @"align": Word, ++ }; ++ pub const Shdr = extern struct { ++ name: Word, ++ type: Word, ++ flags: packed struct { shf: SHF }, ++ addr: Elf32.Addr, ++ offset: Elf32.Off, ++ size: Word, ++ link: Word, ++ info: Word, ++ addralign: Word, ++ entsize: Word, ++ }; ++ pub const Chdr = extern struct { ++ type: COMPRESS, ++ size: Word, ++ addralign: Word, ++ }; ++ pub const Sym = extern struct { ++ name: Word, ++ value: Elf32.Addr, ++ size: Word, ++ info: Info, ++ other: Other, ++ shndx: Section, ++ ++ pub const Info = packed struct(u8) { ++ type: STT, ++ bind: STB, ++ }; ++ ++ pub const Other = packed struct(u8) { ++ visibility: STV, ++ unused: u5 = 0, ++ }; ++ }; ++ comptime { ++ assert(@sizeOf(Elf32.Ehdr) == 52); ++ assert(@sizeOf(Elf32.Phdr) == 32); ++ assert(@sizeOf(Elf32.Shdr) == 40); ++ assert(@sizeOf(Elf32.Sym) == 16); ++ } ++}; ++pub const Elf64 = struct { ++ pub const Addr = u64; ++ pub const Off = u64; ++ pub const Ehdr = extern struct { ++ ident: [EI.NIDENT]u8, ++ type: ET, ++ machine: EM, ++ version: Word, ++ entry: Elf64.Addr, ++ phoff: Elf64.Off, ++ shoff: Elf64.Off, ++ flags: Word, ++ ehsize: Half, ++ phentsize: Half, ++ phnum: Half, ++ shentsize: Half, ++ shnum: Half, ++ shstrndx: Half, ++ }; ++ pub const Phdr = extern struct { ++ type: Word, ++ flags: PF, ++ offset: Elf64.Off, ++ vaddr: Elf64.Addr, ++ paddr: Elf64.Addr, ++ filesz: Xword, ++ memsz: Xword, ++ @"align": Xword, ++ }; ++ pub const Shdr = extern struct { ++ name: Word, ++ type: Word, ++ flags: packed struct { shf: SHF, unused: Word = 0 }, ++ addr: Elf64.Addr, ++ offset: Elf64.Off, ++ size: Xword, ++ link: Word, ++ info: Word, ++ addralign: Xword, ++ entsize: Xword, ++ }; ++ pub const Chdr = extern struct { ++ type: COMPRESS, ++ reserved: Word = 0, ++ size: Xword, ++ addralign: Xword, ++ }; ++ pub const Sym = extern struct { ++ name: Word, ++ info: Info, ++ other: Other, ++ shndx: Section, ++ value: Elf64.Addr, ++ size: Xword, ++ ++ pub const Info = Elf32.Sym.Info; ++ pub const Other = Elf32.Sym.Other; ++ }; ++ comptime { ++ assert(@sizeOf(Elf64.Ehdr) == 64); ++ assert(@sizeOf(Elf64.Phdr) == 56); ++ assert(@sizeOf(Elf64.Shdr) == 64); ++ assert(@sizeOf(Elf64.Sym) == 24); ++ } ++}; ++pub const ElfN = switch (@sizeOf(usize)) { ++ 4 => Elf32, ++ 8 => Elf64, ++ else => @compileError("expected pointer size of 32 or 64"), ++}; ++ ++/// Deprecated, use `std.elf.Xword` ++pub const Elf32_Xword = Xword; ++/// Deprecated, use `std.elf.Sxword` ++pub const Elf32_Sxword = Sxword; ++/// Deprecated, use `std.elf.Xword` ++pub const Elf64_Xword = Xword; ++/// Deprecated, use `std.elf.Sxword` + pub const Elf64_Sxword = i64; ++/// Deprecated, use `std.elf.Elf32.Addr` + pub const Elf32_Addr = u32; ++/// Deprecated, use `std.elf.Elf64.Addr` + pub const Elf64_Addr = u64; ++/// Deprecated, use `std.elf.Elf32.Off` + pub const Elf32_Off = u32; ++/// Deprecated, use `std.elf.Elf64.Off` + pub const Elf64_Off = u64; ++/// Deprecated, use `std.elf.Section` + pub const Elf32_Section = u16; ++/// Deprecated, use `std.elf.Section` + pub const Elf64_Section = u16; ++/// Deprecated, use `std.elf.Elf32.Ehdr` + pub const Elf32_Ehdr = extern struct { + e_ident: [EI_NIDENT]u8, + e_type: ET, +@@ -731,8 +981,9 @@ pub const Elf32_Ehdr = extern struct { + e_shnum: Half, + e_shstrndx: Half, + }; ++/// Deprecated, use `std.elf.Elf64.Ehdr` + pub const Elf64_Ehdr = extern struct { +- e_ident: [EI_NIDENT]u8, ++ e_ident: [EI.NIDENT]u8, + e_type: ET, + e_machine: EM, + e_version: Word, +@@ -747,6 +998,7 @@ pub const Elf64_Ehdr = extern struct { + e_shnum: Half, + e_shstrndx: Half, + }; ++/// Deprecated, use `std.elf.Elf32.Phdr` + pub const Elf32_Phdr = extern struct { + p_type: Word, + p_offset: Elf32_Off, +@@ -757,6 +1009,7 @@ pub const Elf32_Phdr = extern struct { + p_flags: Word, + p_align: Word, + }; ++/// Deprecated, use `std.elf.Elf64.Phdr` + pub const Elf64_Phdr = extern struct { + p_type: Word, + p_flags: Word, +@@ -767,6 +1020,7 @@ pub const Elf64_Phdr = extern struct { + p_memsz: Elf64_Xword, + p_align: Elf64_Xword, + }; ++/// Deprecated, use `std.elf.Elf32.Shdr` + pub const Elf32_Shdr = extern struct { + sh_name: Word, + sh_type: Word, +@@ -779,6 +1033,7 @@ pub const Elf32_Shdr = extern struct { + sh_addralign: Word, + sh_entsize: Word, + }; ++/// Deprecated, use `std.elf.Elf64.Shdr` + pub const Elf64_Shdr = extern struct { + sh_name: Word, + sh_type: Word, +@@ -791,17 +1046,20 @@ pub const Elf64_Shdr = extern struct { + sh_addralign: Elf64_Xword, + sh_entsize: Elf64_Xword, + }; ++/// Deprecated, use `std.elf.Elf32.Chdr` + pub const Elf32_Chdr = extern struct { + ch_type: COMPRESS, + ch_size: Word, + ch_addralign: Word, + }; ++/// Deprecated, use `std.elf.Elf64.Chdr` + pub const Elf64_Chdr = extern struct { + ch_type: COMPRESS, + ch_reserved: Word = 0, + ch_size: Elf64_Xword, + ch_addralign: Elf64_Xword, + }; ++/// Deprecated, use `std.elf.Elf32.Sym` + pub const Elf32_Sym = extern struct { + st_name: Word, + st_value: Elf32_Addr, +@@ -817,6 +1075,7 @@ pub const Elf32_Sym = extern struct { + return @truncate(self.st_info >> 4); + } + }; ++/// Deprecated, use `std.elf.Elf64.Sym` + pub const Elf64_Sym = extern struct { + st_name: Word, + st_info: u8, +@@ -1020,27 +1279,18 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { + flags2: Word, + }; + +-comptime { +- assert(@sizeOf(Elf32_Ehdr) == 52); +- assert(@sizeOf(Elf64_Ehdr) == 64); +- +- assert(@sizeOf(Elf32_Phdr) == 32); +- assert(@sizeOf(Elf64_Phdr) == 56); +- +- assert(@sizeOf(Elf32_Shdr) == 40); +- assert(@sizeOf(Elf64_Shdr) == 64); +-} +- + pub const Auxv = switch (@sizeOf(usize)) { + 4 => Elf32_auxv_t, + 8 => Elf64_auxv_t, + else => @compileError("expected pointer size of 32 or 64"), + }; ++/// Deprecated, use `std.elf.ElfN.Ehdr` + pub const Ehdr = switch (@sizeOf(usize)) { + 4 => Elf32_Ehdr, + 8 => Elf64_Ehdr, + else => @compileError("expected pointer size of 32 or 64"), + }; ++/// Deprecated, use `std.elf.ElfN.Phdr` + pub const Phdr = switch (@sizeOf(usize)) { + 4 => Elf32_Phdr, + 8 => Elf64_Phdr, +@@ -1071,20 +1321,53 @@ pub const Shdr = switch (@sizeOf(usize)) { + 8 => Elf64_Shdr, + else => @compileError("expected pointer size of 32 or 64"), + }; ++/// Deprecated, use `std.elf.ElfN.Chdr` + pub const Chdr = switch (@sizeOf(usize)) { + 4 => Elf32_Chdr, + 8 => Elf64_Chdr, + else => @compileError("expected pointer size of 32 or 64"), + }; ++/// Deprecated, use `std.elf.ElfN.Sym` + pub const Sym = switch (@sizeOf(usize)) { + 4 => Elf32_Sym, + 8 => Elf64_Sym, + else => @compileError("expected pointer size of 32 or 64"), + }; +-pub const Addr = switch (@sizeOf(usize)) { +- 4 => Elf32_Addr, +- 8 => Elf64_Addr, +- else => @compileError("expected pointer size of 32 or 64"), ++/// Deprecated, use `std.elf.ElfN.Addr` ++pub const Addr = ElfN.Addr; ++ ++/// Deprecated, use `@intFromEnum(std.elf.CLASS.NONE)` ++pub const ELFCLASSNONE = @intFromEnum(CLASS.NONE); ++/// Deprecated, use `@intFromEnum(std.elf.CLASS.@"32")` ++pub const ELFCLASS32 = @intFromEnum(CLASS.@"32"); ++/// Deprecated, use `@intFromEnum(std.elf.CLASS.@"64")` ++pub const ELFCLASS64 = @intFromEnum(CLASS.@"64"); ++/// Deprecated, use `@intFromEnum(std.elf.CLASS.NUM)` ++pub const ELFCLASSNUM = CLASS.NUM; ++pub const CLASS = enum(u8) { ++ NONE = 0, ++ @"32" = 1, ++ @"64" = 2, ++ _, ++ ++ pub const NUM = @typeInfo(CLASS).@"enum".fields.len; ++}; ++ ++/// Deprecated, use `@intFromEnum(std.elf.DATA.NONE)` ++pub const ELFDATANONE = @intFromEnum(DATA.NONE); ++/// Deprecated, use `@intFromEnum(std.elf.DATA.@"2LSB")` ++pub const ELFDATA2LSB = @intFromEnum(DATA.@"2LSB"); ++/// Deprecated, use `@intFromEnum(std.elf.DATA.@"2MSB")` ++pub const ELFDATA2MSB = @intFromEnum(DATA.@"2MSB"); ++/// Deprecated, use `@intFromEnum(std.elf.DATA.NUM)` ++pub const ELFDATANUM = DATA.NUM; ++pub const DATA = enum(u8) { ++ NONE = 0, ++ @"2LSB" = 1, ++ @"2MSB" = 2, ++ _, ++ ++ pub const NUM = @typeInfo(DATA).@"enum".fields.len; + }; + + pub const OSABI = enum(u8) { +@@ -1718,6 +2001,108 @@ pub const SHF_MIPS_STRING = 0x80000000; + /// Make code section unreadable when in execute-only mode + pub const SHF_ARM_PURECODE = 0x2000000; + ++pub const SHF = packed struct(Word) { ++ /// Section data should be writable during execution. ++ WRITE: bool = false, ++ /// Section occupies memory during program execution. ++ ALLOC: bool = false, ++ /// Section contains executable machine instructions. ++ EXECINSTR: bool = false, ++ unused3: u1 = 0, ++ /// The data in this section may be merged. ++ MERGE: bool = false, ++ /// The data in this section is null-terminated strings. ++ STRINGS: bool = false, ++ /// A field in this section holds a section header table index. ++ INFO_LINK: bool = false, ++ /// Adds special ordering requirements for link editors. ++ LINK_ORDER: bool = false, ++ /// This section requires special OS-specific processing to avoid incorrect behavior. ++ OS_NONCONFORMING: bool = false, ++ /// This section is a member of a section group. ++ GROUP: bool = false, ++ /// This section holds Thread-Local Storage. ++ TLS: bool = false, ++ /// Identifies a section containing compressed data. ++ COMPRESSED: bool = false, ++ unused12: u8 = 0, ++ OS: packed union { ++ MASK: u8, ++ GNU: packed struct(u8) { ++ unused0: u1 = 0, ++ /// Not to be GCed by the linker ++ RETAIN: bool = false, ++ unused2: u6 = 0, ++ }, ++ MIPS: packed struct(u8) { ++ unused0: u4 = 0, ++ /// Section contains text/data which may be replicated in other sections. ++ /// Linker must retain only one copy. ++ NODUPES: bool = false, ++ /// Linker must generate implicit hidden weak names. ++ NAMES: bool = false, ++ /// Section data local to process. ++ LOCAL: bool = false, ++ /// Do not strip this section. ++ NOSTRIP: bool = false, ++ }, ++ ARM: packed struct(u8) { ++ unused0: u5 = 0, ++ /// Make code section unreadable when in execute-only mode ++ PURECODE: bool = false, ++ unused6: u2 = 0, ++ }, ++ } = .{ .MASK = 0 }, ++ PROC: packed union { ++ MASK: u4, ++ XCORE: packed struct(u4) { ++ /// All sections with the "d" flag are grouped together by the linker to form ++ /// the data section and the dp register is set to the start of the section by ++ /// the boot code. ++ DP_SECTION: bool = false, ++ /// All sections with the "c" flag are grouped together by the linker to form ++ /// the constant pool and the cp register is set to the start of the constant ++ /// pool by the boot code. ++ CP_SECTION: bool = false, ++ unused2: u1 = 0, ++ /// This section is excluded from the final executable or shared library. ++ EXCLUDE: bool = false, ++ }, ++ X86_64: packed struct(u4) { ++ /// If an object file section does not have this flag set, then it may not hold ++ /// more than 2GB and can be freely referred to in objects using smaller code ++ /// models. Otherwise, only objects using larger code models can refer to them. ++ /// For example, a medium code model object can refer to data in a section that ++ /// sets this flag besides being able to refer to data in a section that does ++ /// not set it; likewise, a small code model object can refer only to code in a ++ /// section that does not set this flag. ++ LARGE: bool = false, ++ unused1: u2 = 0, ++ /// This section is excluded from the final executable or shared library. ++ EXCLUDE: bool = false, ++ }, ++ HEX: packed struct(u4) { ++ /// All sections with the GPREL flag are grouped into a global data area ++ /// for faster accesses ++ GPREL: bool = false, ++ unused1: u2 = 0, ++ /// This section is excluded from the final executable or shared library. ++ EXCLUDE: bool = false, ++ }, ++ MIPS: packed struct(u4) { ++ /// All sections with the GPREL flag are grouped into a global data area ++ /// for faster accesses ++ GPREL: bool = false, ++ /// This section should be merged. ++ MERGE: bool = false, ++ /// Address size to be inferred from section entry size. ++ ADDR: bool = false, ++ /// Section data is string data by default. ++ STRING: bool = false, ++ }, ++ } = .{ .MASK = 0 }, ++}; ++ + /// Execute + pub const PF_X = 1; + +@@ -1733,6 +2118,19 @@ pub const PF_MASKOS = 0x0ff00000; + /// Bits for processor-specific semantics. + pub const PF_MASKPROC = 0xf0000000; + ++pub const PF = packed struct(Word) { ++ X: bool = false, ++ W: bool = false, ++ R: bool = false, ++ unused3: u17 = 0, ++ OS: packed union { ++ MASK: u8, ++ } = .{ .MASK = 0 }, ++ PROC: packed union { ++ MASK: u4, ++ } = .{ .MASK = 0 }, ++}; ++ + /// Undefined section + pub const SHN_UNDEF = 0; + /// Start of reserved indices +@@ -2303,13 +2701,6 @@ pub const R_PPC64 = enum(u32) { + _, + }; + +-pub const STV = enum(u3) { +- DEFAULT = 0, +- INTERNAL = 1, +- HIDDEN = 2, +- PROTECTED = 3, +-}; +- + pub const ar_hdr = extern struct { + /// Member file name, sometimes / terminated. + ar_name: [16]u8, +diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig +index b2116c1a74..55f1fd14cb 100644 +--- a/lib/std/zig/system.zig ++++ b/lib/std/zig/system.zig +@@ -516,15 +516,15 @@ pub fn abiAndDynamicLinkerFromFile( + const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf); + const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf); + if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; +- const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { ++ const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI.DATA]) { + elf.ELFDATA2LSB => .little, + elf.ELFDATA2MSB => .big, + else => return error.InvalidElfEndian, + }; + const need_bswap = elf_endian != native_endian; +- if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; ++ if (hdr32.e_ident[elf.EI.VERSION] != 1) return error.InvalidElfVersion; + +- const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { ++ const is_64 = switch (hdr32.e_ident[elf.EI.CLASS]) { + elf.ELFCLASS32 => false, + elf.ELFCLASS64 => true, + else => return error.InvalidElfClass, +@@ -920,15 +920,15 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { + const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf); + const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf); + if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic; +- const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) { ++ const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI.DATA]) { + elf.ELFDATA2LSB => .little, + elf.ELFDATA2MSB => .big, + else => return error.InvalidElfEndian, + }; + const need_bswap = elf_endian != native_endian; +- if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion; ++ if (hdr32.e_ident[elf.EI.VERSION] != 1) return error.InvalidElfVersion; + +- const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) { ++ const is_64 = switch (hdr32.e_ident[elf.EI.CLASS]) { + elf.ELFCLASS32 => false, + elf.ELFCLASS64 => true, + else => return error.InvalidElfClass, +diff --git a/src/Compilation.zig b/src/Compilation.zig +index 34953ed11a..bf7246b8d8 100644 +--- a/src/Compilation.zig ++++ b/src/Compilation.zig +@@ -177,7 +177,6 @@ debug_compiler_runtime_libs: bool, + debug_compile_errors: bool, + /// Do not check this field directly. Instead, use the `debugIncremental` wrapper function. + debug_incremental: bool, +-incremental: bool, + alloc_failure_occurred: bool = false, + last_update_was_cache_hit: bool = false, + +@@ -256,7 +255,9 @@ mutex: if (builtin.single_threaded) struct { + test_filters: []const []const u8, + + link_task_wait_group: WaitGroup = .{}, +-link_prog_node: std.Progress.Node = std.Progress.Node.none, ++link_prog_node: std.Progress.Node = .none, ++link_uav_prog_node: std.Progress.Node = .none, ++link_lazy_prog_node: std.Progress.Node = .none, + + llvm_opt_bisect_limit: c_int, + +@@ -1746,7 +1747,6 @@ pub const CreateOptions = struct { + debug_compiler_runtime_libs: bool = false, + debug_compile_errors: bool = false, + debug_incremental: bool = false, +- incremental: bool = false, + /// Normally when you create a `Compilation`, Zig will automatically build + /// and link in required dependencies, such as compiler-rt and libc. When + /// building such dependencies themselves, this flag must be set to avoid +@@ -1982,6 +1982,7 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options + }; + if (have_zcu and (!need_llvm or use_llvm)) { + if (output_mode == .Obj) break :s .zcu; ++ if (options.config.use_new_linker) break :s .zcu; + switch (target_util.zigBackend(target, use_llvm)) { + else => {}, + .stage2_aarch64, .stage2_x86_64 => if (target.ofmt == .coff) { +@@ -2188,8 +2189,8 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options + .inherited = .{}, + .global = options.config, + .parent = options.root_mod, +- }) catch |err| return switch (err) { +- error.OutOfMemory => |e| return e, ++ }) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, + // None of these are possible because the configuration matches the root module + // which already passed these checks. + error.ValgrindUnsupportedOnTarget => unreachable, +@@ -2266,7 +2267,6 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options + .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, + .debug_compile_errors = options.debug_compile_errors, + .debug_incremental = options.debug_incremental, +- .incremental = options.incremental, + .root_name = root_name, + .sysroot = sysroot, + .windows_libs = .empty, +@@ -2409,6 +2409,8 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options + // Synchronize with other matching comments: ZigOnlyHashStuff + hash.add(use_llvm); + hash.add(options.config.use_lib_llvm); ++ hash.add(options.config.use_lld); ++ hash.add(options.config.use_new_linker); + hash.add(options.config.dll_export_fns); + hash.add(options.config.is_test); + hash.addListOfBytes(options.test_filters); +@@ -3075,14 +3077,29 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE + + // The linker progress node is set up here instead of in `performAllTheWork`, because + // we also want it around during `flush`. +- const have_link_node = comp.bin_file != null; +- if (have_link_node) { ++ if (comp.bin_file) |lf| { + comp.link_prog_node = main_progress_node.start("Linking", 0); ++ if (lf.cast(.elf2)) |elf| { ++ comp.link_prog_node.increaseEstimatedTotalItems(3); ++ comp.link_uav_prog_node = comp.link_prog_node.start("Constants", 0); ++ comp.link_lazy_prog_node = comp.link_prog_node.start("Synthetics", 0); ++ elf.mf.update_prog_node = comp.link_prog_node.start("Relocations", elf.mf.updates.items.len); ++ } + } +- defer if (have_link_node) { ++ defer { + comp.link_prog_node.end(); + comp.link_prog_node = .none; +- }; ++ comp.link_uav_prog_node.end(); ++ comp.link_uav_prog_node = .none; ++ comp.link_lazy_prog_node.end(); ++ comp.link_lazy_prog_node = .none; ++ if (comp.bin_file) |lf| { ++ if (lf.cast(.elf2)) |elf| { ++ elf.mf.update_prog_node.end(); ++ elf.mf.update_prog_node = .none; ++ } ++ } ++ } + + try comp.performAllTheWork(main_progress_node); + +@@ -3100,6 +3117,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE + try pt.populateTestFunctions(); + } + ++ link.updateErrorData(pt); ++ + try pt.processExports(); + } + +@@ -3474,6 +3493,8 @@ fn addNonIncrementalStuffToCacheManifest( + + man.hash.add(comp.config.use_llvm); + man.hash.add(comp.config.use_lib_llvm); ++ man.hash.add(comp.config.use_lld); ++ man.hash.add(comp.config.use_new_linker); + man.hash.add(comp.config.is_test); + man.hash.add(comp.config.import_memory); + man.hash.add(comp.config.export_memory); +@@ -4073,7 +4094,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { + defer sorted_failed_analysis.deinit(gpa); + var added_any_analysis_error = false; + for (sorted_failed_analysis.items(.key), sorted_failed_analysis.items(.value)) |anal_unit, error_msg| { +- if (comp.incremental) { ++ if (comp.config.incremental) { + const refs = try zcu.resolveReferences(); + if (!refs.contains(anal_unit)) continue; + } +@@ -4240,7 +4261,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { + + // TODO: eventually, this should be behind `std.debug.runtime_safety`. But right now, this is a + // very common way for incremental compilation bugs to manifest, so let's always check it. +- if (comp.zcu) |zcu| if (comp.incremental and bundle.root_list.items.len == 0) { ++ if (comp.zcu) |zcu| if (comp.config.incremental and bundle.root_list.items.len == 0) { + for (zcu.transitive_failed_analysis.keys()) |failed_unit| { + const refs = try zcu.resolveReferences(); + var ref = refs.get(failed_unit) orelse continue; +@@ -4949,7 +4970,7 @@ fn performAllTheWork( + tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); + } + +- if (comp.incremental) { ++ if (comp.config.incremental) { + const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); + defer update_zir_refs_node.end(); + try pt.updateZirRefs(); +diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig +index d8751251da..45f7e509de 100644 +--- a/src/Compilation/Config.zig ++++ b/src/Compilation/Config.zig +@@ -49,6 +49,8 @@ use_lib_llvm: bool, + use_lld: bool, + c_frontend: CFrontend, + lto: std.zig.LtoMode, ++use_new_linker: bool, ++incremental: bool, + /// WASI-only. Type of WASI execution model ("command" or "reactor"). + /// Always set to `command` for non-WASI targets. + wasi_exec_model: std.builtin.WasiExecModel, +@@ -104,6 +106,8 @@ pub const Options = struct { + use_lld: ?bool = null, + use_clang: ?bool = null, + lto: ?std.zig.LtoMode = null, ++ use_new_linker: ?bool = null, ++ incremental: bool = false, + /// WASI-only. Type of WASI execution model ("command" or "reactor"). + wasi_exec_model: ?std.builtin.WasiExecModel = null, + import_memory: ?bool = null, +@@ -147,6 +151,8 @@ pub const ResolveError = error{ + LldUnavailable, + ClangUnavailable, + DllExportFnsRequiresWindows, ++ NewLinkerIncompatibleWithLld, ++ NewLinkerIncompatibleObjectFormat, + }; + + pub fn resolve(options: Options) ResolveError!Config { +@@ -458,6 +464,22 @@ pub fn resolve(options: Options) ResolveError!Config { + break :b .none; + }; + ++ const use_new_linker = b: { ++ if (use_lld) { ++ if (options.use_new_linker == true) return error.NewLinkerIncompatibleWithLld; ++ break :b false; ++ } ++ ++ if (!target_util.hasNewLinkerSupport(target.ofmt)) { ++ if (options.use_new_linker == true) return error.NewLinkerIncompatibleObjectFormat; ++ break :b false; ++ } ++ ++ if (options.use_new_linker) |x| break :b x; ++ ++ break :b options.incremental; ++ }; ++ + const root_strip = b: { + if (options.root_strip) |x| break :b x; + if (root_optimize_mode == .ReleaseSmall) break :b true; +@@ -531,6 +553,8 @@ pub fn resolve(options: Options) ResolveError!Config { + .root_error_tracing = root_error_tracing, + .pie = pie, + .lto = lto, ++ .use_new_linker = use_new_linker, ++ .incremental = options.incremental, + .import_memory = import_memory, + .export_memory = export_memory, + .shared_memory = shared_memory, +diff --git a/src/InternPool.zig b/src/InternPool.zig +index 9965497742..f4344af86d 100644 +--- a/src/InternPool.zig ++++ b/src/InternPool.zig +@@ -6424,14 +6424,25 @@ pub const Alignment = enum(u6) { + return n + 1; + } + ++ pub fn toStdMem(a: Alignment) std.mem.Alignment { ++ assert(a != .none); ++ return @enumFromInt(@intFromEnum(a)); ++ } ++ ++ pub fn fromStdMem(a: std.mem.Alignment) Alignment { ++ const r: Alignment = @enumFromInt(@intFromEnum(a)); ++ assert(r != .none); ++ return r; ++ } ++ + const LlvmBuilderAlignment = std.zig.llvm.Builder.Alignment; + +- pub fn toLlvm(this: @This()) LlvmBuilderAlignment { +- return @enumFromInt(@intFromEnum(this)); ++ pub fn toLlvm(a: Alignment) LlvmBuilderAlignment { ++ return @enumFromInt(@intFromEnum(a)); + } + +- pub fn fromLlvm(other: LlvmBuilderAlignment) @This() { +- return @enumFromInt(@intFromEnum(other)); ++ pub fn fromLlvm(a: LlvmBuilderAlignment) Alignment { ++ return @enumFromInt(@intFromEnum(a)); + } + }; + +diff --git a/src/Sema.zig b/src/Sema.zig +index 946e890ea3..d0576de33d 100644 +--- a/src/Sema.zig ++++ b/src/Sema.zig +@@ -3032,7 +3032,7 @@ fn zirStructDecl( + }); + errdefer pt.destroyNamespace(new_namespace_index); + +- if (pt.zcu.comp.incremental) { ++ if (pt.zcu.comp.config.incremental) { + try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); + } + +@@ -3430,7 +3430,7 @@ fn zirUnionDecl( + }); + errdefer pt.destroyNamespace(new_namespace_index); + +- if (pt.zcu.comp.incremental) { ++ if (pt.zcu.comp.config.incremental) { + try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); + } + +@@ -6217,7 +6217,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void + if (ptr_info.byte_offset != 0) { + return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); + } +- if (options.linkage == .internal) return; ++ if (zcu.llvm_object != null and options.linkage == .internal) return; + const export_ty = Value.fromInterned(uav.val).typeOf(zcu); + if (!try sema.validateExternType(export_ty, .other)) { + return sema.failWithOwnedErrorMsg(block, msg: { +@@ -6256,7 +6256,7 @@ pub fn analyzeExport( + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + +- if (options.linkage == .internal) ++ if (zcu.llvm_object != null and options.linkage == .internal) + return; + + try sema.ensureNavResolved(block, src, orig_nav_index, .fully); +@@ -7709,7 +7709,7 @@ fn analyzeCall( + // TODO: comptime call memoization is currently not supported under incremental compilation + // since dependencies are not marked on callers. If we want to keep this around (we should + // check that it's worthwhile first!), each memoized call needs an `AnalUnit`. +- if (zcu.comp.incremental) break :m false; ++ if (zcu.comp.config.incremental) break :m false; + if (!block.isComptime()) break :m false; + for (args) |a| { + const val = (try sema.resolveValue(a)).?; +@@ -31208,7 +31208,7 @@ fn addReferenceEntry( + .func => |f| assert(ip.unwrapCoercedFunc(f) == f), // for `.{ .func = f }`, `f` must be uncoerced + else => {}, + } +- if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return; ++ if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; + const gop = try sema.references.getOrPut(sema.gpa, referenced_unit); + if (gop.found_existing) return; + try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: { +@@ -31225,7 +31225,7 @@ pub fn addTypeReferenceEntry( + referenced_type: InternPool.Index, + ) !void { + const zcu = sema.pt.zcu; +- if (!zcu.comp.incremental and zcu.comp.reference_trace == 0) return; ++ if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; + const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type); + if (gop.found_existing) return; + try zcu.addTypeReference(sema.owner, referenced_type, src); +@@ -36875,7 +36875,7 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool + + pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { + const pt = sema.pt; +- if (!pt.zcu.comp.incremental) return; ++ if (!pt.zcu.comp.config.incremental) return; + + const gop = try sema.dependencies.getOrPut(sema.gpa, dependee); + if (gop.found_existing) return; +diff --git a/src/Value.zig b/src/Value.zig +index 8de5621761..381eacf45a 100644 +--- a/src/Value.zig ++++ b/src/Value.zig +@@ -23,7 +23,7 @@ pub fn format(val: Value, writer: *std.Io.Writer) !void { + + /// This is a debug function. In order to print values in a meaningful way + /// we also need access to the type. +-pub fn dump(start_val: Value, w: std.Io.Writer) std.Io.Writer.Error!void { ++pub fn dump(start_val: Value, w: *std.Io.Writer) std.Io.Writer.Error!void { + try w.print("(interned: {})", .{start_val.toIntern()}); + } + +diff --git a/src/Zcu.zig b/src/Zcu.zig +index 706bdb5165..8e9e9c2902 100644 +--- a/src/Zcu.zig ++++ b/src/Zcu.zig +@@ -3166,7 +3166,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni + } + + pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { +- if (!zcu.comp.incremental) return null; ++ if (!zcu.comp.config.incremental) return null; + + if (zcu.outdated.count() == 0) { + // Any units in `potentially_outdated` must just be stuck in loops with one another: none of those +diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig +index 77cddb204e..32782e7e89 100644 +--- a/src/Zcu/PerThread.zig ++++ b/src/Zcu/PerThread.zig +@@ -1815,7 +1815,7 @@ fn createFileRootStruct( + wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none); + ip.namespacePtr(namespace_index).owner_type = wip_ty.index; + +- if (zcu.comp.incremental) { ++ if (zcu.comp.config.incremental) { + try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); + } + +diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig +index 7b13cfc90d..fe40ba4bbb 100644 +--- a/src/arch/riscv64/CodeGen.zig ++++ b/src/arch/riscv64/CodeGen.zig +@@ -858,9 +858,11 @@ pub fn generateLazy( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, +-) CodeGenError!void { ++) (CodeGenError || std.Io.Writer.Error)!void { ++ _ = atom_index; + const comp = bin_file.comp; + const gpa = comp.gpa; + const mod = comp.root_mod; +@@ -914,7 +916,7 @@ pub fn generateLazy( + }, + .bin_file = bin_file, + .debug_output = debug_output, +- .code = code, ++ .w = w, + .prev_di_pc = undefined, // no debug info yet + .prev_di_line = undefined, // no debug info yet + .prev_di_column = undefined, // no debug info yet +diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig +index 2e72aff941..64a476007c 100644 +--- a/src/arch/riscv64/Emit.zig ++++ b/src/arch/riscv64/Emit.zig +@@ -3,7 +3,7 @@ + bin_file: *link.File, + lower: Lower, + debug_output: link.File.DebugInfoOutput, +-code: *std.ArrayListUnmanaged(u8), ++w: *std.Io.Writer, + + prev_di_line: u32, + prev_di_column: u32, +@@ -13,7 +13,7 @@ prev_di_pc: usize, + code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, + relocs: std.ArrayListUnmanaged(Reloc) = .empty, + +-pub const Error = Lower.Error || error{ ++pub const Error = Lower.Error || std.Io.Writer.Error || error{ + EmitFail, + }; + +@@ -25,13 +25,13 @@ pub fn emitMir(emit: *Emit) Error!void { + try emit.code_offset_mapping.putNoClobber( + emit.lower.allocator, + mir_index, +- @intCast(emit.code.items.len), ++ @intCast(emit.w.end), + ); + const lowered = try emit.lower.lowerMir(mir_index, .{ .allow_frame_locs = true }); + var lowered_relocs = lowered.relocs; + for (lowered.insts, 0..) |lowered_inst, lowered_index| { +- const start_offset: u32 = @intCast(emit.code.items.len); +- std.mem.writeInt(u32, try emit.code.addManyAsArray(gpa, 4), lowered_inst.toU32(), .little); ++ const start_offset: u32 = @intCast(emit.w.end); ++ try emit.w.writeInt(u32, lowered_inst.toU32(), .little); + + while (lowered_relocs.len > 0 and + lowered_relocs[0].lowered_inst_index == lowered_index) : ({ +@@ -175,7 +175,7 @@ fn fixupRelocs(emit: *Emit) Error!void { + return emit.fail("relocation target not found!", .{}); + + const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source)); +- const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4]; ++ const code = emit.w.buffered()[reloc.source + reloc.offset ..][0..4]; + + switch (reloc.fmt) { + .J => riscv_util.writeInstJ(code, @bitCast(disp)), +@@ -187,7 +187,7 @@ fn fixupRelocs(emit: *Emit) Error!void { + + fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { + const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line); +- const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; ++ const delta_pc: usize = emit.w.end - emit.prev_di_pc; + log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); + switch (emit.debug_output) { + .dwarf => |dw| { +@@ -196,7 +196,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { + try dw.advancePCAndLine(delta_line, delta_pc); + emit.prev_di_line = line; + emit.prev_di_column = column; +- emit.prev_di_pc = emit.code.items.len; ++ emit.prev_di_pc = emit.w.end; + }, + .none => {}, + } +diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig +index 6fb8e23a98..204ab6a3c0 100644 +--- a/src/arch/riscv64/Mir.zig ++++ b/src/arch/riscv64/Mir.zig +@@ -109,9 +109,11 @@ pub fn emit( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, +-) codegen.CodeGenError!void { ++) (codegen.CodeGenError || std.Io.Writer.Error)!void { ++ _ = atom_index; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; +@@ -132,7 +134,7 @@ pub fn emit( + }, + .bin_file = lf, + .debug_output = debug_output, +- .code = code, ++ .w = w, + .prev_di_pc = 0, + .prev_di_line = func.lbrace_line, + .prev_di_column = func.lbrace_column, +diff --git a/src/arch/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig +index d41f1cdf07..26282b09ab 100644 +--- a/src/arch/sparc64/Emit.zig ++++ b/src/arch/sparc64/Emit.zig +@@ -21,7 +21,7 @@ debug_output: link.File.DebugInfoOutput, + target: *const std.Target, + err_msg: ?*ErrorMsg = null, + src_loc: Zcu.LazySrcLoc, +-code: *std.ArrayListUnmanaged(u8), ++w: *std.Io.Writer, + + prev_di_line: u32, + prev_di_column: u32, +@@ -40,7 +40,7 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn + /// instruction + code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty, + +-const InnerError = error{ ++const InnerError = std.Io.Writer.Error || error{ + OutOfMemory, + EmitFail, + }; +@@ -292,7 +292,7 @@ fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void { + .bpcc => switch (tag) { + .bpcc => { + const branch_predict_int = emit.mir.instructions.items(.data)[inst].branch_predict_int; +- const offset = @as(i64, @intCast(emit.code_offset_mapping.get(branch_predict_int.inst).?)) - @as(i64, @intCast(emit.code.items.len)); ++ const offset = @as(i64, @intCast(emit.code_offset_mapping.get(branch_predict_int.inst).?)) - @as(i64, @intCast(emit.w.end)); + log.debug("mirConditionalBranch: {} offset={}", .{ inst, offset }); + + try emit.writeInstruction( +@@ -310,7 +310,7 @@ fn mirConditionalBranch(emit: *Emit, inst: Mir.Inst.Index) !void { + .bpr => switch (tag) { + .bpr => { + const branch_predict_reg = emit.mir.instructions.items(.data)[inst].branch_predict_reg; +- const offset = @as(i64, @intCast(emit.code_offset_mapping.get(branch_predict_reg.inst).?)) - @as(i64, @intCast(emit.code.items.len)); ++ const offset = @as(i64, @intCast(emit.code_offset_mapping.get(branch_predict_reg.inst).?)) - @as(i64, @intCast(emit.w.end)); + log.debug("mirConditionalBranch: {} offset={}", .{ inst, offset }); + + try emit.writeInstruction( +@@ -494,13 +494,13 @@ fn branchTarget(emit: *Emit, inst: Mir.Inst.Index) Mir.Inst.Index { + + fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void { + const delta_line = @as(i32, @intCast(line)) - @as(i32, @intCast(emit.prev_di_line)); +- const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; ++ const delta_pc: usize = emit.w.end - emit.prev_di_pc; + switch (emit.debug_output) { + .dwarf => |dbg_out| { + try dbg_out.advancePCAndLine(delta_line, delta_pc); + emit.prev_di_line = line; + emit.prev_di_column = column; +- emit.prev_di_pc = emit.code.items.len; ++ emit.prev_di_pc = emit.w.end; + }, + else => {}, + } +@@ -675,13 +675,8 @@ fn optimalBranchType(emit: *Emit, tag: Mir.Inst.Tag, offset: i64) !BranchType { + } + + fn writeInstruction(emit: *Emit, instruction: Instruction) !void { +- const comp = emit.bin_file.comp; +- const gpa = comp.gpa; +- + // SPARCv9 instructions are always arranged in BE regardless of the + // endianness mode the CPU is running in (Section 3.1 of the ISA specification). + // This is to ease porting in case someone wants to do a LE SPARCv9 backend. +- const endian: Endian = .big; +- +- std.mem.writeInt(u32, try emit.code.addManyAsArray(gpa, 4), instruction.toU32(), endian); ++ try emit.w.writeInt(u32, instruction.toU32(), .big); + } +diff --git a/src/arch/sparc64/Mir.zig b/src/arch/sparc64/Mir.zig +index 842ac10fed..41d135eb83 100644 +--- a/src/arch/sparc64/Mir.zig ++++ b/src/arch/sparc64/Mir.zig +@@ -380,9 +380,11 @@ pub fn emit( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, +-) codegen.CodeGenError!void { ++) (codegen.CodeGenError || std.Io.Writer.Error)!void { ++ _ = atom_index; + const zcu = pt.zcu; + const func = zcu.funcInfo(func_index); + const nav = func.owner_nav; +@@ -393,7 +395,7 @@ pub fn emit( + .debug_output = debug_output, + .target = &mod.resolved_target.result, + .src_loc = src_loc, +- .code = code, ++ .w = w, + .prev_di_pc = 0, + .prev_di_line = func.lbrace_line, + .prev_di_column = func.lbrace_column, +diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig +index b5760c95ac..1827b50d61 100644 +--- a/src/arch/x86_64/CodeGen.zig ++++ b/src/arch/x86_64/CodeGen.zig +@@ -550,9 +550,9 @@ pub const MCValue = union(enum) { + @tagName(pl.reg), + }), + .indirect => |pl| try w.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), +- .indirect_load_frame => |pl| try w.print("[[{} + 0x{x}]]", .{ pl.index, pl.off }), +- .load_frame => |pl| try w.print("[{} + 0x{x}]", .{ pl.index, pl.off }), +- .lea_frame => |pl| try w.print("{} + 0x{x}", .{ pl.index, pl.off }), ++ .indirect_load_frame => |pl| try w.print("[[{f} + 0x{x}]]", .{ pl.index, pl.off }), ++ .load_frame => |pl| try w.print("[{f} + 0x{x}]", .{ pl.index, pl.off }), ++ .lea_frame => |pl| try w.print("{f} + 0x{x}", .{ pl.index, pl.off }), + .load_nav => |pl| try w.print("[nav:{d}]", .{@intFromEnum(pl)}), + .lea_nav => |pl| try w.print("nav:{d}", .{@intFromEnum(pl)}), + .load_uav => |pl| try w.print("[uav:{d}]", .{@intFromEnum(pl.val)}), +@@ -561,10 +561,10 @@ pub const MCValue = union(enum) { + .lea_lazy_sym => |pl| try w.print("lazy:{s}:{d}", .{ @tagName(pl.kind), @intFromEnum(pl.ty) }), + .load_extern_func => |pl| try w.print("[extern:{d}]", .{@intFromEnum(pl)}), + .lea_extern_func => |pl| try w.print("extern:{d}", .{@intFromEnum(pl)}), +- .elementwise_args => |pl| try w.print("elementwise:{d}:[{} + 0x{x}]", .{ ++ .elementwise_args => |pl| try w.print("elementwise:{d}:[{f} + 0x{x}]", .{ + pl.regs, pl.frame_index, pl.frame_off, + }), +- .reserved_frame => |pl| try w.print("(dead:{})", .{pl}), ++ .reserved_frame => |pl| try w.print("(dead:{f})", .{pl}), + .air_ref => |pl| try w.print("(air:0x{x})", .{@intFromEnum(pl)}), + } + } +@@ -1038,7 +1038,8 @@ pub fn generateLazy( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, + ) codegen.CodeGenError!void { + const gpa = pt.zcu.gpa; +@@ -1081,7 +1082,7 @@ pub fn generateLazy( + else => |e| return e, + }; + +- try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, code, debug_output); ++ try function.getTmpMir().emitLazy(bin_file, pt, src_loc, lazy_sym, atom_index, w, debug_output); + } + + const FormatNavData = struct { +@@ -2022,7 +2023,7 @@ fn gen( + .{}, + ); + self.ret_mcv.long = .{ .load_frame = .{ .index = frame_index } }; +- tracking_log.debug("spill {f} to {}", .{ self.ret_mcv.long, frame_index }); ++ tracking_log.debug("spill {f} to {f}", .{ self.ret_mcv.long, frame_index }); + }, + else => unreachable, + } +diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig +index 84bb325322..c2b38d8e6d 100644 +--- a/src/arch/x86_64/Emit.zig ++++ b/src/arch/x86_64/Emit.zig +@@ -6,7 +6,7 @@ pt: Zcu.PerThread, + pic: bool, + atom_index: u32, + debug_output: link.File.DebugInfoOutput, +-code: *std.ArrayListUnmanaged(u8), ++w: *std.Io.Writer, + + prev_di_loc: Loc, + /// Relative to the beginning of `code`. +@@ -18,7 +18,8 @@ table_relocs: std.ArrayListUnmanaged(TableReloc), + + pub const Error = Lower.Error || error{ + EmitFail, +-} || link.File.UpdateDebugInfoError; ++ NotFile, ++} || std.posix.MMapError || std.posix.MRemapError || link.File.UpdateDebugInfoError; + + pub fn emitMir(emit: *Emit) Error!void { + const comp = emit.bin_file.comp; +@@ -29,12 +30,12 @@ pub fn emitMir(emit: *Emit) Error!void { + var local_index: usize = 0; + for (0..emit.lower.mir.instructions.len) |mir_i| { + const mir_index: Mir.Inst.Index = @intCast(mir_i); +- emit.code_offset_mapping.items[mir_index] = @intCast(emit.code.items.len); ++ emit.code_offset_mapping.items[mir_index] = @intCast(emit.w.end); + const lowered = try emit.lower.lowerMir(mir_index); + var lowered_relocs = lowered.relocs; + lowered_inst: for (lowered.insts, 0..) |lowered_inst, lowered_index| { + if (lowered_inst.prefix == .directive) { +- const start_offset: u32 = @intCast(emit.code.items.len); ++ const start_offset: u32 = @intCast(emit.w.end); + switch (emit.debug_output) { + .dwarf => |dwarf| switch (lowered_inst.encoding.mnemonic) { + .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{ +@@ -164,6 +165,8 @@ pub fn emitMir(emit: *Emit) Error!void { + .index = if (emit.bin_file.cast(.elf)) |elf_file| + elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, emit.pt, lazy_sym) catch |err| + return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) ++ else if (emit.bin_file.cast(.elf2)) |elf| ++ @intFromEnum(try elf.lazySymbol(lazy_sym)) + else if (emit.bin_file.cast(.macho)) |macho_file| + macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err| + return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) +@@ -180,12 +183,15 @@ pub fn emitMir(emit: *Emit) Error!void { + .extern_func => |extern_func| .{ + .index = if (emit.bin_file.cast(.elf)) |elf_file| + try elf_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null) +- else if (emit.bin_file.cast(.macho)) |macho_file| ++ else if (emit.bin_file.cast(.elf2)) |elf| @intFromEnum(try elf.globalSymbol(.{ ++ .name = extern_func.toSlice(&emit.lower.mir).?, ++ .type = .FUNC, ++ })) else if (emit.bin_file.cast(.macho)) |macho_file| + try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null) + else if (emit.bin_file.cast(.coff)) |coff_file| + try coff_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, "compiler_rt") + else +- return emit.fail("external symbols unimplemented for {s}", .{@tagName(emit.bin_file.tag)}), ++ return emit.fail("external symbol unimplemented for {s}", .{@tagName(emit.bin_file.tag)}), + .is_extern = true, + .type = .symbol, + }, +@@ -205,7 +211,7 @@ pub fn emitMir(emit: *Emit) Error!void { + }, + else => {}, + } +- if (emit.bin_file.cast(.elf)) |_| { ++ if (emit.bin_file.cast(.elf) != null or emit.bin_file.cast(.elf2) != null) { + if (!emit.pic) switch (lowered_inst.encoding.mnemonic) { + .lea => try emit.encodeInst(try .new(.none, .mov, &.{ + lowered_inst.ops[0], +@@ -315,7 +321,7 @@ pub fn emitMir(emit: *Emit) Error!void { + }, + .branch, .tls => unreachable, + .tlv => { +- if (emit.bin_file.cast(.elf)) |elf_file| { ++ if (emit.bin_file.cast(.elf) != null or emit.bin_file.cast(.elf2) != null) { + // TODO handle extern TLS vars, i.e., emit GD model + if (emit.pic) switch (lowered_inst.encoding.mnemonic) { + .lea, .mov => { +@@ -337,7 +343,12 @@ pub fn emitMir(emit: *Emit) Error!void { + }, emit.lower.target), &.{.{ + .op_index = 0, + .target = .{ +- .index = try elf_file.getGlobalSymbol("__tls_get_addr", null), ++ .index = if (emit.bin_file.cast(.elf)) |elf_file| ++ try elf_file.getGlobalSymbol("__tls_get_addr", null) ++ else if (emit.bin_file.cast(.elf2)) |elf| @intFromEnum(try elf.globalSymbol(.{ ++ .name = "__tls_get_addr", ++ .type = .FUNC, ++ })) else unreachable, + .is_extern = true, + .type = .branch, + }, +@@ -441,7 +452,7 @@ pub fn emitMir(emit: *Emit) Error!void { + log.debug("mirDbgEnterBlock (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); +- try dwarf.enterBlock(emit.code.items.len); ++ try dwarf.enterBlock(emit.w.end); + }, + .none => {}, + }, +@@ -450,7 +461,7 @@ pub fn emitMir(emit: *Emit) Error!void { + log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); +- try dwarf.leaveBlock(emit.code.items.len); ++ try dwarf.leaveBlock(emit.w.end); + }, + .none => {}, + }, +@@ -459,7 +470,7 @@ pub fn emitMir(emit: *Emit) Error!void { + log.debug("mirDbgEnterInline (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); +- try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column); ++ try dwarf.enterInlineFunc(mir_inst.data.ip_index, emit.w.end, emit.prev_di_loc.line, emit.prev_di_loc.column); + }, + .none => {}, + }, +@@ -468,7 +479,7 @@ pub fn emitMir(emit: *Emit) Error!void { + log.debug("mirDbgLeaveInline (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); +- try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.code.items.len); ++ try dwarf.leaveInlineFunc(mir_inst.data.ip_index, emit.w.end); + }, + .none => {}, + }, +@@ -634,7 +645,7 @@ pub fn emitMir(emit: *Emit) Error!void { + for (emit.relocs.items) |reloc| { + const target = emit.code_offset_mapping.items[reloc.target]; + const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.inst_offset + reloc.inst_length)) + reloc.target_offset; +- const inst_bytes = emit.code.items[reloc.inst_offset..][0..reloc.inst_length]; ++ const inst_bytes = emit.w.buffered()[reloc.inst_offset..][0..reloc.inst_length]; + switch (reloc.source_length) { + else => unreachable, + inline 1, 4 => |source_length| std.mem.writeInt( +@@ -646,12 +657,12 @@ pub fn emitMir(emit: *Emit) Error!void { + } + } + if (emit.lower.mir.table.len > 0) { ++ const ptr_size = @divExact(emit.lower.target.ptrBitWidth(), 8); ++ var table_offset = std.mem.alignForward(u32, @intCast(emit.w.end), ptr_size); + if (emit.bin_file.cast(.elf)) |elf_file| { + const zo = elf_file.zigObjectPtr().?; + const atom = zo.symbol(emit.atom_index).atom(elf_file).?; + +- const ptr_size = @divExact(emit.lower.target.ptrBitWidth(), 8); +- var table_offset = std.mem.alignForward(u32, @intCast(emit.code.items.len), ptr_size); + for (emit.table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{ + .r_offset = table_reloc.source_offset, + .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32"), +@@ -665,7 +676,26 @@ pub fn emitMir(emit: *Emit) Error!void { + }, zo); + table_offset += ptr_size; + } +- try emit.code.appendNTimes(gpa, 0, table_offset - emit.code.items.len); ++ try emit.w.splatByteAll(0, table_offset - emit.w.end); ++ } else if (emit.bin_file.cast(.elf2)) |elf| { ++ for (emit.table_relocs.items) |table_reloc| try elf.addReloc( ++ @enumFromInt(emit.atom_index), ++ table_reloc.source_offset, ++ @enumFromInt(emit.atom_index), ++ @as(i64, table_offset) + table_reloc.target_offset, ++ .{ .x86_64 = .@"32" }, ++ ); ++ for (emit.lower.mir.table) |entry| { ++ try elf.addReloc( ++ @enumFromInt(emit.atom_index), ++ table_offset, ++ @enumFromInt(emit.atom_index), ++ emit.code_offset_mapping.items[entry], ++ .{ .x86_64 = .@"64" }, ++ ); ++ table_offset += ptr_size; ++ } ++ try emit.w.splatByteAll(0, table_offset - emit.w.end); + } else unreachable; + } + } +@@ -696,16 +726,12 @@ const RelocInfo = struct { + fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocInfo) Error!void { + const comp = emit.bin_file.comp; + const gpa = comp.gpa; +- const start_offset: u32 = @intCast(emit.code.items.len); +- { +- var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, emit.code); +- defer emit.code.* = aw.toArrayList(); +- lowered_inst.encode(&aw.writer, .{}) catch |err| switch (err) { +- error.WriteFailed => return error.OutOfMemory, +- else => |e| return e, +- }; +- } +- const end_offset: u32 = @intCast(emit.code.items.len); ++ const start_offset: u32 = @intCast(emit.w.end); ++ lowered_inst.encode(emit.w, .{}) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const end_offset: u32 = @intCast(emit.w.end); + for (reloc_info) |reloc| switch (reloc.target.type) { + .inst => { + const inst_length: u4 = @intCast(end_offset - start_offset); +@@ -769,7 +795,13 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI + .symbolnum = @intCast(reloc.target.index), + }, + }); +- } else if (emit.bin_file.cast(.coff)) |coff_file| { ++ } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( ++ @enumFromInt(emit.atom_index), ++ end_offset - 4, ++ @enumFromInt(reloc.target.index), ++ reloc.off, ++ .{ .x86_64 = .@"32" }, ++ ) else if (emit.bin_file.cast(.coff)) |coff_file| { + const atom_index = coff_file.getAtomIndexForSymbol( + .{ .sym_index = emit.atom_index, .file = null }, + ).?; +@@ -794,7 +826,13 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI + .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type), + .r_addend = reloc.off - 4, + }, zo); +- } else if (emit.bin_file.cast(.macho)) |macho_file| { ++ } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( ++ @enumFromInt(emit.atom_index), ++ end_offset - 4, ++ @enumFromInt(reloc.target.index), ++ reloc.off - 4, ++ .{ .x86_64 = .PC32 }, ++ ) else if (emit.bin_file.cast(.macho)) |macho_file| { + const zo = macho_file.getZigObject().?; + const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; + try atom.addReloc(macho_file, .{ +@@ -849,7 +887,13 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI + .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type), + .r_addend = reloc.off, + }, zo); +- } else if (emit.bin_file.cast(.macho)) |macho_file| { ++ } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc( ++ @enumFromInt(emit.atom_index), ++ end_offset - 4, ++ @enumFromInt(reloc.target.index), ++ reloc.off, ++ .{ .x86_64 = .TPOFF32 }, ++ ) else if (emit.bin_file.cast(.macho)) |macho_file| { + const zo = macho_file.getZigObject().?; + const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; + try atom.addReloc(macho_file, .{ +@@ -908,7 +952,7 @@ const Loc = struct { + + fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void { + const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line); +- const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; ++ const delta_pc: usize = emit.w.end - emit.prev_di_pc; + log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); + switch (emit.debug_output) { + .dwarf => |dwarf| { +@@ -916,7 +960,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void { + if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column); + try dwarf.advancePCAndLine(delta_line, delta_pc); + emit.prev_di_loc = loc; +- emit.prev_di_pc = emit.code.items.len; ++ emit.prev_di_pc = emit.w.end; + }, + .none => {}, + } +diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig +index e70018850d..caf41ffb39 100644 +--- a/src/arch/x86_64/Mir.zig ++++ b/src/arch/x86_64/Mir.zig +@@ -1976,7 +1976,8 @@ pub fn emit( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, + ) codegen.CodeGenError!void { + const zcu = pt.zcu; +@@ -1997,17 +1998,9 @@ pub fn emit( + .bin_file = lf, + .pt = pt, + .pic = mod.pic, +- .atom_index = sym: { +- if (lf.cast(.elf)) |ef| break :sym try ef.zigObjectPtr().?.getOrCreateMetadataForNav(zcu, nav); +- if (lf.cast(.macho)) |mf| break :sym try mf.getZigObject().?.getOrCreateMetadataForNav(mf, nav); +- if (lf.cast(.coff)) |cf| { +- const atom = try cf.getOrCreateAtomForNav(nav); +- break :sym cf.getAtom(atom).getSymbolIndex().?; +- } +- unreachable; +- }, ++ .atom_index = atom_index, + .debug_output = debug_output, +- .code = code, ++ .w = w, + + .prev_di_loc = .{ + .line = func.lbrace_line, +@@ -2037,7 +2030,8 @@ pub fn emitLazy( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, + ) codegen.CodeGenError!void { + const zcu = pt.zcu; +@@ -2055,20 +2049,9 @@ pub fn emitLazy( + .bin_file = lf, + .pt = pt, + .pic = mod.pic, +- .atom_index = sym: { +- if (lf.cast(.elf)) |ef| break :sym ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_sym) catch |err| +- return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)}); +- if (lf.cast(.macho)) |mf| break :sym mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_sym) catch |err| +- return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)}); +- if (lf.cast(.coff)) |cf| { +- const atom = cf.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err| +- return zcu.codegenFailType(lazy_sym.ty, "{s} creating lazy symbol", .{@errorName(err)}); +- break :sym cf.getAtom(atom).getSymbolIndex().?; +- } +- unreachable; +- }, ++ .atom_index = atom_index, + .debug_output = debug_output, +- .code = code, ++ .w = w, + + .prev_di_loc = undefined, + .prev_di_pc = undefined, +diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig +index 835093d11a..0504810933 100644 +--- a/src/arch/x86_64/bits.zig ++++ b/src/arch/x86_64/bits.zig +@@ -727,6 +727,14 @@ pub const FrameIndex = enum(u32) { + pub fn isNamed(fi: FrameIndex) bool { + return @intFromEnum(fi) < named_count; + } ++ ++ pub fn format(fi: FrameIndex, writer: *std.Io.Writer) std.Io.Writer.Error!void { ++ if (fi.isNamed()) { ++ try writer.print("FrameIndex.{t}", .{fi}); ++ } else { ++ try writer.print("FrameIndex({d})", .{@intFromEnum(fi)}); ++ } ++ } + }; + + pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 }; +diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig +index 03ff7134f6..1d9c67175e 100644 +--- a/src/arch/x86_64/encoder.zig ++++ b/src/arch/x86_64/encoder.zig +@@ -259,7 +259,7 @@ pub const Instruction = struct { + switch (sib.base) { + .none => any = false, + .reg => |reg| try w.print("{s}", .{@tagName(reg)}), +- .frame => |frame_index| try w.print("{}", .{frame_index}), ++ .frame => |frame_index| try w.print("{f}", .{frame_index}), + .table => try w.print("Table", .{}), + .rip_inst => |inst_index| try w.print("RipInst({d})", .{inst_index}), + .nav => |nav| try w.print("Nav({d})", .{@intFromEnum(nav)}), +diff --git a/src/codegen.zig b/src/codegen.zig +index 56e6e7c99f..4cbf3f5616 100644 +--- a/src/codegen.zig ++++ b/src/codegen.zig +@@ -6,7 +6,6 @@ const link = @import("link.zig"); + const log = std.log.scoped(.codegen); + const mem = std.mem; + const math = std.math; +-const ArrayList = std.ArrayList; + const target_util = @import("target.zig"); + const trace = @import("tracy.zig").trace; + +@@ -179,10 +178,11 @@ pub fn emitFunction( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, ++ atom_index: u32, + any_mir: *const AnyMir, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, +-) CodeGenError!void { ++) (CodeGenError || std.Io.Writer.Error)!void { + const zcu = pt.zcu; + const func = zcu.funcInfo(func_index); + const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result; +@@ -195,7 +195,7 @@ pub fn emitFunction( + => |backend| { + dev.check(devFeatureForBackend(backend)); + const mir = &@field(any_mir, AnyMir.tag(backend)); +- return mir.emit(lf, pt, src_loc, func_index, code, debug_output); ++ return mir.emit(lf, pt, src_loc, func_index, atom_index, w, debug_output); + }, + } + } +@@ -205,9 +205,10 @@ pub fn generateLazyFunction( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + lazy_sym: link.File.LazySymbol, +- code: *ArrayList(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, +-) CodeGenError!void { ++) (CodeGenError || std.Io.Writer.Error)!void { + const zcu = pt.zcu; + const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index| + &zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result +@@ -217,19 +218,11 @@ pub fn generateLazyFunction( + else => unreachable, + inline .stage2_riscv64, .stage2_x86_64 => |backend| { + dev.check(devFeatureForBackend(backend)); +- return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output); ++ return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, atom_index, w, debug_output); + }, + } + } + +-fn writeFloat(comptime F: type, f: F, target: *const std.Target, endian: std.builtin.Endian, code: []u8) void { +- _ = target; +- const bits = @typeInfo(F).float.bits; +- const Int = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } }); +- const int: Int = @bitCast(f); +- mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian); +-} +- + pub fn generateLazySymbol( + bin_file: *link.File, + pt: Zcu.PerThread, +@@ -237,17 +230,14 @@ pub fn generateLazySymbol( + lazy_sym: link.File.LazySymbol, + // TODO don't use an "out" parameter like this; put it in the result instead + alignment: *Alignment, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, + reloc_parent: link.File.RelocInfo.Parent, +-) CodeGenError!void { +- _ = reloc_parent; +- ++) (CodeGenError || std.Io.Writer.Error)!void { + const tracy = trace(@src()); + defer tracy.end(); + + const comp = bin_file.comp; +- const gpa = comp.gpa; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const target = &comp.root_mod.resolved_target.result; +@@ -260,37 +250,36 @@ pub fn generateLazySymbol( + + if (lazy_sym.kind == .code) { + alignment.* = target_util.defaultFunctionAlignment(target); +- return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, code, debug_output); ++ return generateLazyFunction(bin_file, pt, src_loc, lazy_sym, reloc_parent.atom_index, w, debug_output); + } + + if (lazy_sym.ty == .anyerror_type) { + alignment.* = .@"4"; + const err_names = ip.global_error_set.getNamesFromMainThread(); +- var offset_index: u32 = @intCast(code.items.len); +- var string_index: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0))); +- try code.resize(gpa, offset_index + string_index); +- mem.writeInt(u32, code.items[offset_index..][0..4], @intCast(err_names.len), endian); ++ const strings_start: u32 = @intCast(4 * (1 + err_names.len + @intFromBool(err_names.len > 0))); ++ var string_index = strings_start; ++ try w.rebase(w.end, string_index); ++ w.writeInt(u32, @intCast(err_names.len), endian) catch unreachable; + if (err_names.len == 0) return; +- offset_index += 4; + for (err_names) |err_name_nts| { +- const err_name = err_name_nts.toSlice(ip); +- mem.writeInt(u32, code.items[offset_index..][0..4], string_index, endian); +- offset_index += 4; +- try code.ensureUnusedCapacity(gpa, err_name.len + 1); +- code.appendSliceAssumeCapacity(err_name); +- code.appendAssumeCapacity(0); +- string_index += @intCast(err_name.len + 1); ++ w.writeInt(u32, string_index, endian) catch unreachable; ++ string_index += @intCast(err_name_nts.toSlice(ip).len + 1); ++ } ++ w.writeInt(u32, string_index, endian) catch unreachable; ++ try w.rebase(w.end, string_index - strings_start); ++ for (err_names) |err_name_nts| { ++ w.writeAll(err_name_nts.toSlice(ip)) catch unreachable; ++ w.writeByte(0) catch unreachable; + } +- mem.writeInt(u32, code.items[offset_index..][0..4], string_index, endian); + } else if (Type.fromInterned(lazy_sym.ty).zigTypeTag(zcu) == .@"enum") { + alignment.* = .@"1"; + const enum_ty = Type.fromInterned(lazy_sym.ty); + const tag_names = enum_ty.enumFields(zcu); + for (0..tag_names.len) |tag_index| { + const tag_name = tag_names.get(ip)[tag_index].toSlice(ip); +- try code.ensureUnusedCapacity(gpa, tag_name.len + 1); +- code.appendSliceAssumeCapacity(tag_name); +- code.appendAssumeCapacity(0); ++ try w.rebase(w.end, tag_name.len + 1); ++ w.writeAll(tag_name) catch unreachable; ++ w.writeByte(0) catch unreachable; + } + } else { + return zcu.codegenFailType(lazy_sym.ty, "TODO implement generateLazySymbol for {s} {f}", .{ +@@ -312,14 +301,13 @@ pub fn generateSymbol( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + val: Value, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + reloc_parent: link.File.RelocInfo.Parent, +-) GenerateSymbolError!void { ++) (GenerateSymbolError || std.Io.Writer.Error)!void { + const tracy = trace(@src()); + defer tracy.end(); + + const zcu = pt.zcu; +- const gpa = zcu.gpa; + const ip = &zcu.intern_pool; + const ty = val.typeOf(zcu); + +@@ -330,7 +318,7 @@ pub fn generateSymbol( + + if (val.isUndef(zcu)) { + const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; +- try code.appendNTimes(gpa, 0xaa, abi_size); ++ try w.splatByteAll(0xaa, abi_size); + return; + } + +@@ -360,7 +348,7 @@ pub fn generateSymbol( + .null => unreachable, // non-runtime value + .@"unreachable" => unreachable, // non-runtime value + .empty_tuple => return, +- .false, .true => try code.append(gpa, switch (simple_value) { ++ .false, .true => try w.writeByte(switch (simple_value) { + .false => 0, + .true => 1, + else => unreachable, +@@ -376,11 +364,11 @@ pub fn generateSymbol( + const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; + var space: Value.BigIntSpace = undefined; + const int_val = val.toBigInt(&space, zcu); +- int_val.writeTwosComplement(try code.addManyAsSlice(gpa, abi_size), endian); ++ int_val.writeTwosComplement(try w.writableSlice(abi_size), endian); + }, + .err => |err| { + const int = try pt.getErrorValue(err.name); +- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), @intCast(int), endian); ++ try w.writeInt(u16, @intCast(int), endian); + }, + .error_union => |error_union| { + const payload_ty = ty.errorUnionPayload(zcu); +@@ -390,7 +378,7 @@ pub fn generateSymbol( + }; + + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { +- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); ++ try w.writeInt(u16, err_val, endian); + return; + } + +@@ -400,63 +388,63 @@ pub fn generateSymbol( + + // error value first when its type is larger than the error union's payload + if (error_align.order(payload_align) == .gt) { +- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); ++ try w.writeInt(u16, err_val, endian); + } + + // emit payload part of the error union + { +- const begin = code.items.len; ++ const begin = w.end; + try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(switch (error_union.val) { + .err_name => try pt.intern(.{ .undef = payload_ty.toIntern() }), + .payload => |payload| payload, +- }), code, reloc_parent); +- const unpadded_end = code.items.len - begin; ++ }), w, reloc_parent); ++ const unpadded_end = w.end - begin; + const padded_end = abi_align.forward(unpadded_end); + const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow; + + if (padding > 0) { +- try code.appendNTimes(gpa, 0, padding); ++ try w.splatByteAll(0, padding); + } + } + + // Payload size is larger than error set, so emit our error set last + if (error_align.compare(.lte, payload_align)) { +- const begin = code.items.len; +- mem.writeInt(u16, try code.addManyAsArray(gpa, 2), err_val, endian); +- const unpadded_end = code.items.len - begin; ++ const begin = w.end; ++ try w.writeInt(u16, err_val, endian); ++ const unpadded_end = w.end - begin; + const padded_end = abi_align.forward(unpadded_end); + const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow; + + if (padding > 0) { +- try code.appendNTimes(gpa, 0, padding); ++ try w.splatByteAll(0, padding); + } + } + }, + .enum_tag => |enum_tag| { + const int_tag_ty = ty.intTagType(zcu); +- try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, try pt.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), w, reloc_parent); + }, + .float => |float| storage: switch (float.storage) { +- .f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(gpa, 2)), +- .f32 => |f32_val| writeFloat(f32, f32_val, target, endian, try code.addManyAsArray(gpa, 4)), +- .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(gpa, 8)), ++ .f16 => |f16_val| try w.writeInt(u16, @bitCast(f16_val), endian), ++ .f32 => |f32_val| try w.writeInt(u32, @bitCast(f32_val), endian), ++ .f64 => |f64_val| try w.writeInt(u64, @bitCast(f64_val), endian), + .f80 => |f80_val| { +- writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(gpa, 10)); ++ try w.writeInt(u80, @bitCast(f80_val), endian); + const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; +- try code.appendNTimes(gpa, 0, abi_size - 10); ++ try w.splatByteAll(0, abi_size - 10); + }, + .f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) { + else => unreachable, + 16 => continue :storage .{ .f16 = @floatCast(f128_val) }, + 32 => continue :storage .{ .f32 = @floatCast(f128_val) }, + 64 => continue :storage .{ .f64 = @floatCast(f128_val) }, +- 128 => writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(gpa, 16)), ++ 128 => try w.writeInt(u128, @bitCast(f128_val), endian), + }, + }, +- .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), code, reloc_parent, 0), ++ .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), w, reloc_parent, 0), + .slice => |slice| { +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), code, reloc_parent); +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.ptr), w, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(slice.len), w, reloc_parent); + }, + .opt => { + const payload_type = ty.optionalChild(zcu); +@@ -465,9 +453,9 @@ pub fn generateSymbol( + + if (ty.optionalReprIsPayload(zcu)) { + if (payload_val) |value| { +- try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent); + } else { +- try code.appendNTimes(gpa, 0, abi_size); ++ try w.splatByteAll(0, abi_size); + } + } else { + const padding = abi_size - (math.cast(usize, payload_type.abiSize(zcu)) orelse return error.Overflow) - 1; +@@ -475,15 +463,15 @@ pub fn generateSymbol( + const value = payload_val orelse Value.fromInterned(try pt.intern(.{ + .undef = payload_type.toIntern(), + })); +- try generateSymbol(bin_file, pt, src_loc, value, code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, value, w, reloc_parent); + } +- try code.append(gpa, @intFromBool(payload_val != null)); +- try code.appendNTimes(gpa, 0, padding); ++ try w.writeByte(@intFromBool(payload_val != null)); ++ try w.splatByteAll(0, padding); + } + }, + .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { + .array_type => |array_type| switch (aggregate.storage) { +- .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(array_type.lenIncludingSentinel(), ip)), ++ .bytes => |bytes| try w.writeAll(bytes.toSlice(array_type.lenIncludingSentinel(), ip)), + .elems, .repeated_elem => { + var index: u64 = 0; + while (index < array_type.lenIncludingSentinel()) : (index += 1) { +@@ -494,14 +482,14 @@ pub fn generateSymbol( + elem + else + array_type.sentinel, +- }), code, reloc_parent); ++ }), w, reloc_parent); + } + }, + }, + .vector_type => |vector_type| { + const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; + if (vector_type.child == .bool_type) { +- const bytes = try code.addManyAsSlice(gpa, abi_size); ++ const bytes = try w.writableSlice(abi_size); + @memset(bytes, 0xaa); + var index: usize = 0; + const len = math.cast(usize, vector_type.len) orelse return error.Overflow; +@@ -540,7 +528,7 @@ pub fn generateSymbol( + } + } else { + switch (aggregate.storage) { +- .bytes => |bytes| try code.appendSlice(gpa, bytes.toSlice(vector_type.len, ip)), ++ .bytes => |bytes| try w.writeAll(bytes.toSlice(vector_type.len, ip)), + .elems, .repeated_elem => { + var index: u64 = 0; + while (index < vector_type.len) : (index += 1) { +@@ -550,7 +538,7 @@ pub fn generateSymbol( + math.cast(usize, index) orelse return error.Overflow + ], + .repeated_elem => |elem| elem, +- }), code, reloc_parent); ++ }), w, reloc_parent); + } + }, + } +@@ -558,11 +546,11 @@ pub fn generateSymbol( + const padding = abi_size - + (math.cast(usize, Type.fromInterned(vector_type.child).abiSize(zcu) * vector_type.len) orelse + return error.Overflow); +- if (padding > 0) try code.appendNTimes(gpa, 0, padding); ++ if (padding > 0) try w.splatByteAll(0, padding); + } + }, + .tuple_type => |tuple| { +- const struct_begin = code.items.len; ++ const struct_begin = w.end; + for ( + tuple.types.get(ip), + tuple.values.get(ip), +@@ -580,8 +568,8 @@ pub fn generateSymbol( + .repeated_elem => |elem| elem, + }; + +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent); +- const unpadded_field_end = code.items.len - struct_begin; ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); ++ const unpadded_field_end = w.end - struct_begin; + + // Pad struct members if required + const padded_field_end = ty.structFieldOffset(index + 1, zcu); +@@ -589,7 +577,7 @@ pub fn generateSymbol( + return error.Overflow; + + if (padding > 0) { +- try code.appendNTimes(gpa, 0, padding); ++ try w.splatByteAll(0, padding); + } + } + }, +@@ -598,8 +586,9 @@ pub fn generateSymbol( + switch (struct_type.layout) { + .@"packed" => { + const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; +- const current_pos = code.items.len; +- try code.appendNTimes(gpa, 0, abi_size); ++ const start = w.end; ++ const buffer = try w.writableSlice(abi_size); ++ @memset(buffer, 0); + var bits: u16 = 0; + + for (struct_type.field_types.get(ip), 0..) |field_ty, index| { +@@ -619,22 +608,20 @@ pub fn generateSymbol( + error.DivisionByZero => unreachable, + error.UnexpectedRemainder => return error.RelocationNotByteAligned, + }; +- code.items.len = current_pos + field_offset; +- // TODO: code.lockPointers(); ++ w.end = start + field_offset; + defer { +- assert(code.items.len == current_pos + field_offset + @divExact(target.ptrBitWidth(), 8)); +- // TODO: code.unlockPointers(); +- code.items.len = current_pos + abi_size; ++ assert(w.end == start + field_offset + @divExact(target.ptrBitWidth(), 8)); ++ w.end = start + abi_size; + } +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); + } else { +- Value.fromInterned(field_val).writeToPackedMemory(Type.fromInterned(field_ty), pt, code.items[current_pos..], bits) catch unreachable; ++ Value.fromInterned(field_val).writeToPackedMemory(.fromInterned(field_ty), pt, buffer, bits) catch unreachable; + } + bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu)); + } + }, + .auto, .@"extern" => { +- const struct_begin = code.items.len; ++ const struct_begin = w.end; + const field_types = struct_type.field_types.get(ip); + const offsets = struct_type.offsets.get(ip); + +@@ -654,11 +641,11 @@ pub fn generateSymbol( + + const padding = math.cast( + usize, +- offsets[field_index] - (code.items.len - struct_begin), ++ offsets[field_index] - (w.end - struct_begin), + ) orelse return error.Overflow; +- if (padding > 0) try code.appendNTimes(gpa, 0, padding); ++ if (padding > 0) try w.splatByteAll(0, padding); + +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); + } + + const size = struct_type.sizeUnordered(ip); +@@ -666,10 +653,9 @@ pub fn generateSymbol( + + const padding = math.cast( + usize, +- std.mem.alignForward(u64, size, @max(alignment, 1)) - +- (code.items.len - struct_begin), ++ std.mem.alignForward(u64, size, @max(alignment, 1)) - (w.end - struct_begin), + ) orelse return error.Overflow; +- if (padding > 0) try code.appendNTimes(gpa, 0, padding); ++ if (padding > 0) try w.splatByteAll(0, padding); + }, + } + }, +@@ -679,12 +665,12 @@ pub fn generateSymbol( + const layout = ty.unionGetLayout(zcu); + + if (layout.payload_size == 0) { +- return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent); ++ return generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent); + } + + // Check if we should store the tag first. + if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) { +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent); + } + + const union_obj = zcu.typeToUnion(ty).?; +@@ -692,24 +678,24 @@ pub fn generateSymbol( + const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?; + const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) { +- try code.appendNTimes(gpa, 0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); ++ try w.splatByteAll(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); + } else { +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent); + + const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(zcu)) orelse return error.Overflow; + if (padding > 0) { +- try code.appendNTimes(gpa, 0, padding); ++ try w.splatByteAll(0, padding); + } + } + } else { +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.val), w, reloc_parent); + } + + if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) { +- try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), code, reloc_parent); ++ try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(un.tag), w, reloc_parent); + + if (layout.padding > 0) { +- try code.appendNTimes(gpa, 0, layout.padding); ++ try w.splatByteAll(0, layout.padding); + } + } + }, +@@ -722,30 +708,30 @@ fn lowerPtr( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + ptr_val: InternPool.Index, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + reloc_parent: link.File.RelocInfo.Parent, + prev_offset: u64, +-) GenerateSymbolError!void { ++) (GenerateSymbolError || std.Io.Writer.Error)!void { + const zcu = pt.zcu; + const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; + const offset: u64 = prev_offset + ptr.byte_offset; + return switch (ptr.base_addr) { +- .nav => |nav| try lowerNavRef(bin_file, pt, nav, code, reloc_parent, offset), +- .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, code, reloc_parent, offset), +- .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), code, reloc_parent), ++ .nav => |nav| try lowerNavRef(bin_file, pt, nav, w, reloc_parent, offset), ++ .uav => |uav| try lowerUavRef(bin_file, pt, src_loc, uav, w, reloc_parent, offset), ++ .int => try generateSymbol(bin_file, pt, src_loc, try pt.intValue(Type.usize, offset), w, reloc_parent), + .eu_payload => |eu_ptr| try lowerPtr( + bin_file, + pt, + src_loc, + eu_ptr, +- code, ++ w, + reloc_parent, + offset + errUnionPayloadOffset( + Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu).errorUnionPayload(zcu), + zcu, + ), + ), +- .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, code, reloc_parent, offset), ++ .opt_payload => |opt_ptr| try lowerPtr(bin_file, pt, src_loc, opt_ptr, w, reloc_parent, offset), + .field => |field| { + const base_ptr = Value.fromInterned(field.base); + const base_ty = base_ptr.typeOf(zcu).childType(zcu); +@@ -764,7 +750,7 @@ fn lowerPtr( + }, + else => unreachable, + }; +- return lowerPtr(bin_file, pt, src_loc, field.base, code, reloc_parent, offset + field_off); ++ return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off); + }, + .arr_elem, .comptime_field, .comptime_alloc => unreachable, + }; +@@ -775,12 +761,11 @@ fn lowerUavRef( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + uav: InternPool.Key.Ptr.BaseAddr.Uav, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + reloc_parent: link.File.RelocInfo.Parent, + offset: u64, +-) GenerateSymbolError!void { ++) (GenerateSymbolError || std.Io.Writer.Error)!void { + const zcu = pt.zcu; +- const gpa = zcu.gpa; + const ip = &zcu.intern_pool; + const comp = lf.comp; + const target = &comp.root_mod.resolved_target.result; +@@ -790,10 +775,9 @@ fn lowerUavRef( + const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; + + log.debug("lowerUavRef: ty = {f}", .{uav_ty.fmt(pt)}); +- try code.ensureUnusedCapacity(gpa, ptr_width_bytes); + + if (!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) { +- code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes); ++ try w.splatByteAll(0xaa, ptr_width_bytes); + return; + } + +@@ -804,29 +788,32 @@ fn lowerUavRef( + dev.check(link.File.Tag.wasm.devFeature()); + const wasm = lf.cast(.wasm).?; + assert(reloc_parent == .none); +- try wasm.addUavReloc(code.items.len, uav.val, uav.orig_ty, @intCast(offset)); +- code.appendNTimesAssumeCapacity(0, ptr_width_bytes); ++ try wasm.addUavReloc(w.end, uav.val, uav.orig_ty, @intCast(offset)); ++ try w.splatByteAll(0, ptr_width_bytes); + return; + }, + else => {}, + } + +- const uav_align = ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment; ++ const uav_align = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu); + switch (try lf.lowerUav(pt, uav_val, uav_align, src_loc)) { + .sym_index => {}, + .fail => |em| std.debug.panic("TODO rework lowerUav. internal error: {s}", .{em.msg}), + } + +- const vaddr = try lf.getUavVAddr(uav_val, .{ ++ const vaddr = lf.getUavVAddr(uav_val, .{ + .parent = reloc_parent, +- .offset = code.items.len, ++ .offset = w.end, + .addend = @intCast(offset), +- }); ++ }) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ else => |e| std.debug.panic("TODO rework lowerUav. internal error: {t}", .{e}), ++ }; + const endian = target.cpu.arch.endian(); + switch (ptr_width_bytes) { +- 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), +- 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), +- 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), ++ 2 => try w.writeInt(u16, @intCast(vaddr), endian), ++ 4 => try w.writeInt(u32, @intCast(vaddr), endian), ++ 8 => try w.writeInt(u64, vaddr, endian), + else => unreachable, + } + } +@@ -835,10 +822,10 @@ fn lowerNavRef( + lf: *link.File, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, +- code: *ArrayList(u8), ++ w: *std.Io.Writer, + reloc_parent: link.File.RelocInfo.Parent, + offset: u64, +-) GenerateSymbolError!void { ++) (GenerateSymbolError || std.Io.Writer.Error)!void { + const zcu = pt.zcu; + const gpa = zcu.gpa; + const ip = &zcu.intern_pool; +@@ -848,10 +835,8 @@ fn lowerNavRef( + const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); + const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; + +- try code.ensureUnusedCapacity(gpa, ptr_width_bytes); +- + if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) { +- code.appendNTimesAssumeCapacity(0xaa, ptr_width_bytes); ++ try w.splatByteAll(0xaa, ptr_width_bytes); + return; + } + +@@ -870,13 +855,13 @@ fn lowerNavRef( + } else { + try wasm.func_table_fixups.append(gpa, .{ + .table_index = @enumFromInt(gop.index), +- .offset = @intCast(code.items.len), ++ .offset = @intCast(w.end), + }); + } + } else { + if (is_obj) { + try wasm.out_relocs.append(gpa, .{ +- .offset = @intCast(code.items.len), ++ .offset = @intCast(w.end), + .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, + .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, + .addend = @intCast(offset), +@@ -885,12 +870,12 @@ fn lowerNavRef( + try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); + wasm.nav_fixups.appendAssumeCapacity(.{ + .navs_exe_index = try wasm.refNavExe(nav_index), +- .offset = @intCast(code.items.len), ++ .offset = @intCast(w.end), + .addend = @intCast(offset), + }); + } + } +- code.appendNTimesAssumeCapacity(0, ptr_width_bytes); ++ try w.splatByteAll(0, ptr_width_bytes); + return; + }, + else => {}, +@@ -898,14 +883,14 @@ fn lowerNavRef( + + const vaddr = lf.getNavVAddr(pt, nav_index, .{ + .parent = reloc_parent, +- .offset = code.items.len, ++ .offset = w.end, + .addend = @intCast(offset), + }) catch @panic("TODO rework getNavVAddr"); + const endian = target.cpu.arch.endian(); + switch (ptr_width_bytes) { +- 2 => mem.writeInt(u16, code.addManyAsArrayAssumeCapacity(2), @intCast(vaddr), endian), +- 4 => mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), @intCast(vaddr), endian), +- 8 => mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), vaddr, endian), ++ 2 => try w.writeInt(u16, @intCast(vaddr), endian), ++ 4 => try w.writeInt(u32, @intCast(vaddr), endian), ++ 8 => try w.writeInt(u64, vaddr, endian), + else => unreachable, + } + } +@@ -962,6 +947,16 @@ pub fn genNavRef( + }, + .link_once => unreachable, + } ++ } else if (lf.cast(.elf2)) |elf| { ++ return .{ .sym_index = @intFromEnum(elf.navSymbol(zcu, nav_index) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ else => |e| return .{ .fail = try ErrorMsg.create( ++ zcu.gpa, ++ src_loc, ++ "linker failed to create a nav: {t}", ++ .{e}, ++ ) }, ++ }) }; + } else if (lf.cast(.macho)) |macho_file| { + const zo = macho_file.getZigObject().?; + switch (linkage) { +diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig +index 318a51da95..be6478eae8 100644 +--- a/src/codegen/aarch64/Mir.zig ++++ b/src/codegen/aarch64/Mir.zig +@@ -56,13 +56,13 @@ pub fn emit( + pt: Zcu.PerThread, + src_loc: Zcu.LazySrcLoc, + func_index: InternPool.Index, +- code: *std.ArrayListUnmanaged(u8), ++ atom_index: u32, ++ w: *std.Io.Writer, + debug_output: link.File.DebugInfoOutput, + ) !void { + _ = debug_output; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; +- const gpa = zcu.gpa; + const func = zcu.funcInfo(func_index); + const nav = ip.getNav(func.owner_nav); + const mod = zcu.navFileScope(func.owner_nav).mod.?; +@@ -81,20 +81,19 @@ pub fn emit( + @as(u5, @intCast(func_align.minStrict(.@"16").toByteUnits().?)), + Instruction.size, + ) - 1); +- try code.ensureUnusedCapacity(gpa, Instruction.size * +- (code_len + literals_align_gap + mir.literals.len)); +- emitInstructionsForward(code, mir.prologue); +- emitInstructionsBackward(code, mir.body); +- const body_end: u32 = @intCast(code.items.len); +- emitInstructionsBackward(code, mir.epilogue); +- code.appendNTimesAssumeCapacity(0, Instruction.size * literals_align_gap); +- code.appendSliceAssumeCapacity(@ptrCast(mir.literals)); ++ try w.rebase(w.end, Instruction.size * (code_len + literals_align_gap + mir.literals.len)); ++ emitInstructionsForward(w, mir.prologue) catch unreachable; ++ emitInstructionsBackward(w, mir.body) catch unreachable; ++ const body_end: u32 = @intCast(w.end); ++ emitInstructionsBackward(w, mir.epilogue) catch unreachable; ++ w.splatByteAll(0, Instruction.size * literals_align_gap) catch unreachable; ++ w.writeAll(@ptrCast(mir.literals)) catch unreachable; + mir_log.debug("", .{}); + + for (mir.nav_relocs) |nav_reloc| try emitReloc( + lf, + zcu, +- func.owner_nav, ++ atom_index, + switch (try @import("../../codegen.zig").genNavRef( + lf, + pt, +@@ -112,7 +111,7 @@ pub fn emit( + for (mir.uav_relocs) |uav_reloc| try emitReloc( + lf, + zcu, +- func.owner_nav, ++ atom_index, + switch (try lf.lowerUav( + pt, + uav_reloc.uav.val, +@@ -129,7 +128,7 @@ pub fn emit( + for (mir.lazy_relocs) |lazy_reloc| try emitReloc( + lf, + zcu, +- func.owner_nav, ++ atom_index, + if (lf.cast(.elf)) |ef| + ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_reloc.symbol) catch |err| + return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) +@@ -150,7 +149,7 @@ pub fn emit( + for (mir.global_relocs) |global_reloc| try emitReloc( + lf, + zcu, +- func.owner_nav, ++ atom_index, + if (lf.cast(.elf)) |ef| + try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null) + else if (lf.cast(.macho)) |mf| +@@ -168,30 +167,30 @@ pub fn emit( + var instruction = mir.body[literal_reloc.label]; + instruction.load_store.register_literal.group.imm19 += literal_reloc_offset; + instruction.write( +- code.items[body_end - Instruction.size * (1 + literal_reloc.label) ..][0..Instruction.size], ++ w.buffered()[body_end - Instruction.size * (1 + literal_reloc.label) ..][0..Instruction.size], + ); + } + } + +-fn emitInstructionsForward(code: *std.ArrayListUnmanaged(u8), instructions: []const Instruction) void { +- for (instructions) |instruction| emitInstruction(code, instruction); ++fn emitInstructionsForward(w: *std.Io.Writer, instructions: []const Instruction) !void { ++ for (instructions) |instruction| try emitInstruction(w, instruction); + } +-fn emitInstructionsBackward(code: *std.ArrayListUnmanaged(u8), instructions: []const Instruction) void { ++fn emitInstructionsBackward(w: *std.Io.Writer, instructions: []const Instruction) !void { + var instruction_index = instructions.len; + while (instruction_index > 0) { + instruction_index -= 1; +- emitInstruction(code, instructions[instruction_index]); ++ try emitInstruction(w, instructions[instruction_index]); + } + } +-fn emitInstruction(code: *std.ArrayListUnmanaged(u8), instruction: Instruction) void { ++fn emitInstruction(w: *std.Io.Writer, instruction: Instruction) !void { + mir_log.debug(" {f}", .{instruction}); +- instruction.write(code.addManyAsArrayAssumeCapacity(Instruction.size)); ++ instruction.write(try w.writableArray(Instruction.size)); + } + + fn emitReloc( + lf: *link.File, + zcu: *Zcu, +- owner_nav: InternPool.Nav.Index, ++ atom_index: u32, + sym_index: u32, + instruction: Instruction, + offset: u32, +@@ -202,7 +201,7 @@ fn emitReloc( + else => unreachable, + .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| { + const zo = ef.zigObjectPtr().?; +- const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; ++ const atom = zo.symbol(atom_index).atom(ef).?; + const r_type: std.elf.R_AARCH64 = switch (decoded.decode()) { + else => unreachable, + .pc_relative_addressing => |pc_relative_addressing| switch (pc_relative_addressing.group.op) { +@@ -221,7 +220,7 @@ fn emitReloc( + }, zo); + } else if (lf.cast(.macho)) |mf| { + const zo = mf.getZigObject().?; +- const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; ++ const atom = zo.symbols.items[atom_index].getAtom(mf).?; + switch (decoded.decode()) { + else => unreachable, + .pc_relative_addressing => |pc_relative_addressing| switch (pc_relative_addressing.group.op) { +@@ -260,7 +259,7 @@ fn emitReloc( + }, + .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| { + const zo = ef.zigObjectPtr().?; +- const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; ++ const atom = zo.symbol(atom_index).atom(ef).?; + const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) { + .b => .JUMP26, + .bl => .CALL26, +@@ -272,7 +271,7 @@ fn emitReloc( + }, zo); + } else if (lf.cast(.macho)) |mf| { + const zo = mf.getZigObject().?; +- const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; ++ const atom = zo.symbols.items[atom_index].getAtom(mf).?; + try atom.addReloc(mf, .{ + .tag = .@"extern", + .offset = offset, +@@ -289,7 +288,7 @@ fn emitReloc( + }, + .load_store => |decoded| if (lf.cast(.elf)) |ef| { + const zo = ef.zigObjectPtr().?; +- const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; ++ const atom = zo.symbol(atom_index).atom(ef).?; + const r_type: std.elf.R_AARCH64 = switch (decoded.decode().register_unsigned_immediate.decode()) { + .integer => |integer| switch (integer.decode()) { + .unallocated, .prfm => unreachable, +@@ -316,7 +315,7 @@ fn emitReloc( + }, zo); + } else if (lf.cast(.macho)) |mf| { + const zo = mf.getZigObject().?; +- const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; ++ const atom = zo.symbols.items[atom_index].getAtom(mf).?; + try atom.addReloc(mf, .{ + .tag = .@"extern", + .offset = offset, +diff --git a/src/dev.zig b/src/dev.zig +index ac30cedecd..266796a2dc 100644 +--- a/src/dev.zig ++++ b/src/dev.zig +@@ -97,6 +97,7 @@ pub const Env = enum { + .lld_linker, + .coff_linker, + .elf_linker, ++ .elf2_linker, + .macho_linker, + .c_linker, + .wasm_linker, +@@ -163,6 +164,7 @@ pub const Env = enum { + .incremental, + .aarch64_backend, + .elf_linker, ++ .elf2_linker, + => true, + else => Env.sema.supports(feature), + }, +@@ -210,6 +212,7 @@ pub const Env = enum { + .legalize, + .x86_64_backend, + .elf_linker, ++ .elf2_linker, + => true, + else => Env.sema.supports(feature), + }, +@@ -282,6 +285,7 @@ pub const Feature = enum { + lld_linker, + coff_linker, + elf_linker, ++ elf2_linker, + macho_linker, + c_linker, + wasm_linker, +diff --git a/src/link.zig b/src/link.zig +index 27cd6620e3..277013efb3 100644 +--- a/src/link.zig ++++ b/src/link.zig +@@ -219,6 +219,7 @@ pub const Diags = struct { + } + + pub fn addError(diags: *Diags, comptime format: []const u8, args: anytype) void { ++ @branchHint(.cold); + return addErrorSourceLocation(diags, .none, format, args); + } + +@@ -529,7 +530,7 @@ pub const File = struct { + const lld: *Lld = try .createEmpty(arena, comp, emit, options); + return &lld.base; + } +- switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { ++ switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt, comp.config.use_new_linker)) { + .plan9 => return error.UnsupportedObjectFormat, + inline else => |tag| { + dev.check(tag.devFeature()); +@@ -552,7 +553,7 @@ pub const File = struct { + const lld: *Lld = try .createEmpty(arena, comp, emit, options); + return &lld.base; + } +- switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { ++ switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt, comp.config.use_new_linker)) { + .plan9 => return error.UnsupportedObjectFormat, + inline else => |tag| { + dev.check(tag.devFeature()); +@@ -579,7 +580,8 @@ pub const File = struct { + const emit = base.emit; + if (base.child_pid) |pid| { + if (builtin.os.tag == .windows) { +- base.cast(.coff).?.ptraceAttach(pid) catch |err| { ++ const coff_file = base.cast(.coff).?; ++ coff_file.ptraceAttach(pid) catch |err| { + log.warn("attaching failed with error: {s}", .{@errorName(err)}); + }; + } else { +@@ -597,8 +599,11 @@ pub const File = struct { + .linux => std.posix.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0) catch |err| { + log.warn("ptrace failure: {s}", .{@errorName(err)}); + }, +- .macos => base.cast(.macho).?.ptraceAttach(pid) catch |err| { +- log.warn("attaching failed with error: {s}", .{@errorName(err)}); ++ .macos => { ++ const macho_file = base.cast(.macho).?; ++ macho_file.ptraceAttach(pid) catch |err| { ++ log.warn("attaching failed with error: {s}", .{@errorName(err)}); ++ }; + }, + .windows => unreachable, + else => return error.HotSwapUnavailableOnHostOperatingSystem, +@@ -613,6 +618,20 @@ pub const File = struct { + .mode = determineMode(output_mode, link_mode), + }); + }, ++ .elf2 => { ++ const elf = base.cast(.elf2).?; ++ if (base.file == null) { ++ elf.mf.file = try base.emit.root_dir.handle.createFile(base.emit.sub_path, .{ ++ .truncate = false, ++ .read = true, ++ .mode = determineMode(comp.config.output_mode, comp.config.link_mode), ++ }); ++ base.file = elf.mf.file; ++ try elf.mf.ensureTotalCapacity( ++ @intCast(elf.mf.nodes.items[0].location().resolve(&elf.mf)[1]), ++ ); ++ } ++ }, + .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }), + .plan9 => unreachable, + } +@@ -669,14 +688,30 @@ pub const File = struct { + + if (base.child_pid) |pid| { + switch (builtin.os.tag) { +- .macos => base.cast(.macho).?.ptraceDetach(pid) catch |err| { +- log.warn("detaching failed with error: {s}", .{@errorName(err)}); ++ .macos => { ++ const macho_file = base.cast(.macho).?; ++ macho_file.ptraceDetach(pid) catch |err| { ++ log.warn("detaching failed with error: {s}", .{@errorName(err)}); ++ }; ++ }, ++ .windows => { ++ const coff_file = base.cast(.coff).?; ++ coff_file.ptraceDetach(pid); + }, +- .windows => base.cast(.coff).?.ptraceDetach(pid), + else => return error.HotSwapUnavailableOnHostOperatingSystem, + } + } + }, ++ .elf2 => { ++ const elf = base.cast(.elf2).?; ++ if (base.file) |f| { ++ elf.mf.unmap(); ++ assert(elf.mf.file.handle == f.handle); ++ elf.mf.file = undefined; ++ f.close(); ++ base.file = null; ++ } ++ }, + .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }), + .plan9 => unreachable, + } +@@ -793,6 +828,7 @@ pub const File = struct { + .spirv => {}, + .goff, .xcoff => {}, + .plan9 => unreachable, ++ .elf2 => {}, + inline else => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id); +@@ -825,6 +861,26 @@ pub const File = struct { + } + } + ++ pub fn idle(base: *File, tid: Zcu.PerThread.Id) !bool { ++ switch (base.tag) { ++ else => return false, ++ inline .elf2 => |tag| { ++ dev.check(tag.devFeature()); ++ return @as(*tag.Type(), @fieldParentPtr("base", base)).idle(tid); ++ }, ++ } ++ } ++ ++ pub fn updateErrorData(base: *File, pt: Zcu.PerThread) !void { ++ switch (base.tag) { ++ else => {}, ++ inline .elf2 => |tag| { ++ dev.check(tag.devFeature()); ++ return @as(*tag.Type(), @fieldParentPtr("base", base)).updateErrorData(pt); ++ }, ++ } ++ } ++ + pub const FlushError = error{ + /// Indicates an error will be present in `Compilation.link_diags`. + LinkFailure, +@@ -1099,7 +1155,7 @@ pub const File = struct { + if (base.zcu_object_basename != null) return; + + switch (base.tag) { +- inline .wasm => |tag| { ++ inline .elf2, .wasm => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); + }, +@@ -1110,6 +1166,7 @@ pub const File = struct { + pub const Tag = enum { + coff, + elf, ++ elf2, + macho, + c, + wasm, +@@ -1123,6 +1180,7 @@ pub const File = struct { + return switch (tag) { + .coff => Coff, + .elf => Elf, ++ .elf2 => Elf2, + .macho => MachO, + .c => C, + .wasm => Wasm, +@@ -1134,10 +1192,10 @@ pub const File = struct { + }; + } + +- fn fromObjectFormat(ofmt: std.Target.ObjectFormat) Tag { ++ fn fromObjectFormat(ofmt: std.Target.ObjectFormat, use_new_linker: bool) Tag { + return switch (ofmt) { + .coff => .coff, +- .elf => .elf, ++ .elf => if (use_new_linker) .elf2 else .elf, + .macho => .macho, + .wasm => .wasm, + .plan9 => .plan9, +@@ -1223,6 +1281,7 @@ pub const File = struct { + pub const C = @import("link/C.zig"); + pub const Coff = @import("link/Coff.zig"); + pub const Elf = @import("link/Elf.zig"); ++ pub const Elf2 = @import("link/Elf2.zig"); + pub const MachO = @import("link/MachO.zig"); + pub const SpirV = @import("link/SpirV.zig"); + pub const Wasm = @import("link/Wasm.zig"); +@@ -1548,6 +1607,9 @@ pub fn doZcuTask(comp: *Compilation, tid: usize, task: ZcuTask) void { + } + } + } ++pub fn doIdleTask(comp: *Compilation, tid: usize) error{ OutOfMemory, LinkFailure }!bool { ++ return if (comp.bin_file) |lf| lf.idle(@enumFromInt(tid)) else false; ++} + /// After the main pipeline is done, but before flush, the compilation may need to link one final + /// `Nav` into the binary: the `builtin.test_functions` value. Since the link thread isn't running + /// by then, we expose this function which can be called directly. +@@ -1573,6 +1635,13 @@ pub fn linkTestFunctionsNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) + }; + } + } ++pub fn updateErrorData(pt: Zcu.PerThread) void { ++ const comp = pt.zcu.comp; ++ if (comp.bin_file) |lf| lf.updateErrorData(pt) catch |err| switch (err) { ++ error.OutOfMemory => comp.link_diags.setAllocFailure(), ++ error.LinkFailure => {}, ++ }; ++} + + /// Provided by the CLI, processed into `LinkInput` instances at the start of + /// the compilation pipeline. +diff --git a/src/link/Coff.zig b/src/link/Coff.zig +index e016473531..f3e3b3d0b5 100644 +--- a/src/link/Coff.zig ++++ b/src/link/Coff.zig +@@ -953,7 +953,7 @@ fn writeOffsetTableEntry(coff: *Coff, index: usize) !void { + } + + fn markRelocsDirtyByTarget(coff: *Coff, target: SymbolWithLoc) void { +- if (!coff.base.comp.incremental) return; ++ if (!coff.base.comp.config.incremental) return; + // TODO: reverse-lookup might come in handy here + for (coff.relocs.values()) |*relocs| { + for (relocs.items) |*reloc| { +@@ -964,7 +964,7 @@ fn markRelocsDirtyByTarget(coff: *Coff, target: SymbolWithLoc) void { + } + + fn markRelocsDirtyByAddress(coff: *Coff, addr: u32) void { +- if (!coff.base.comp.incremental) return; ++ if (!coff.base.comp.config.incremental) return; + const got_moved = blk: { + const sect_id = coff.got_section_index orelse break :blk false; + break :blk coff.sections.items(.header)[sect_id].virtual_address >= addr; +@@ -1111,20 +1111,24 @@ pub fn updateFunc( + + coff.navs.getPtr(func.owner_nav).?.section = coff.text_section_index.?; + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + +- try codegen.emitFunction( ++ codegen.emitFunction( + &coff.base, + pt, + zcu.navSrcLoc(nav_index), + func_index, ++ coff.getAtom(atom_index).getSymbolIndex().?, + mir, +- &code_buffer, ++ &aw.writer, + .none, +- ); ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; + +- try coff.updateNavCode(pt, nav_index, code_buffer.items, .FUNCTION); ++ try coff.updateNavCode(pt, nav_index, aw.written(), .FUNCTION); + + // Exports will be updated by `Zcu.processExports` after the update. + } +@@ -1145,18 +1149,18 @@ fn lowerConst( + ) !LowerConstResult { + const gpa = coff.base.comp.gpa; + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const atom_index = try coff.createAtom(); + const sym = coff.getAtom(atom_index).getSymbolPtr(coff); + try coff.setSymbolName(sym, name); + sym.section_number = @as(coff_util.SectionNumber, @enumFromInt(sect_id + 1)); + +- try codegen.generateSymbol(&coff.base, pt, src_loc, val, &code_buffer, .{ ++ try codegen.generateSymbol(&coff.base, pt, src_loc, val, &aw.writer, .{ + .atom_index = coff.getAtom(atom_index).getSymbolIndex().?, + }); +- const code = code_buffer.items; ++ const code = aw.written(); + + const atom = coff.getAtomPtr(atom_index); + atom.size = @intCast(code.len); +@@ -1170,7 +1174,7 @@ fn lowerConst( + log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(coff).value }); + log.debug(" (required alignment 0x{x})", .{required_alignment}); + +- try coff.writeAtom(atom_index, code, coff.base.comp.incremental); ++ try coff.writeAtom(atom_index, code, coff.base.comp.config.incremental); + + return .{ .ok = atom_index }; + } +@@ -1214,19 +1218,22 @@ pub fn updateNav( + + coff.navs.getPtr(nav_index).?.section = coff.getNavOutputSection(nav_index); + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + +- try codegen.generateSymbol( ++ codegen.generateSymbol( + &coff.base, + pt, + zcu.navSrcLoc(nav_index), + nav_init, +- &code_buffer, ++ &aw.writer, + .{ .atom_index = atom.getSymbolIndex().? }, +- ); ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; + +- try coff.updateNavCode(pt, nav_index, code_buffer.items, .NULL); ++ try coff.updateNavCode(pt, nav_index, aw.written(), .NULL); + } + + // Exports will be updated by `Zcu.processExports` after the update. +@@ -1244,8 +1251,8 @@ fn updateLazySymbolAtom( + const gpa = comp.gpa; + + var required_alignment: InternPool.Alignment = .none; +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const name = try allocPrint(gpa, "__lazy_{s}_{f}", .{ + @tagName(sym.kind), +@@ -1262,11 +1269,11 @@ fn updateLazySymbolAtom( + src, + sym, + &required_alignment, +- &code_buffer, ++ &aw.writer, + .none, + .{ .atom_index = local_sym_index }, + ); +- const code = code_buffer.items; ++ const code = aw.written(); + + const atom = coff.getAtomPtr(atom_index); + const symbol = atom.getSymbolPtr(coff); +@@ -1285,7 +1292,7 @@ fn updateLazySymbolAtom( + symbol.value = vaddr; + + try coff.addGotEntry(.{ .sym_index = local_sym_index }); +- try coff.writeAtom(atom_index, code, coff.base.comp.incremental); ++ try coff.writeAtom(atom_index, code, coff.base.comp.config.incremental); + } + + pub fn getOrCreateAtomForLazySymbol( +@@ -1437,7 +1444,7 @@ fn updateNavCode( + }; + } + +- coff.writeAtom(atom_index, code, coff.base.comp.incremental) catch |err| switch (err) { ++ coff.writeAtom(atom_index, code, coff.base.comp.config.incremental) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => |e| return coff.base.cgFail(nav_index, "failed to write atom: {s}", .{@errorName(e)}), + }; +@@ -1539,14 +1546,12 @@ pub fn updateExports( + sym.section_number = @as(coff_util.SectionNumber, @enumFromInt(metadata.section + 1)); + sym.type = atom.getSymbol(coff).type; + +- switch (exp.opts.linkage) { +- .strong => { +- sym.storage_class = .EXTERNAL; +- }, +- .internal => @panic("TODO Internal"), ++ sym.storage_class = switch (exp.opts.linkage) { ++ .internal => .EXTERNAL, ++ .strong => .EXTERNAL, + .weak => @panic("TODO WeakExternal"), + else => unreachable, +- } ++ }; + + try coff.resolveGlobalSymbol(sym_loc); + } +diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig +index f4af5f4148..595e3583d5 100644 +--- a/src/link/Dwarf.zig ++++ b/src/link/Dwarf.zig +@@ -2126,19 +2126,22 @@ pub const WipNav = struct { + const size = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0; + try diw.writeUleb128(size); + if (size == 0) return; +- var bytes = wip_nav.debug_info.toArrayList(); +- defer wip_nav.debug_info = .fromArrayList(wip_nav.dwarf.gpa, &bytes); +- const old_len = bytes.items.len; ++ const old_end = wip_nav.debug_info.writer.end; + try codegen.generateSymbol( + wip_nav.dwarf.bin_file, + wip_nav.pt, + src_loc, + val, +- &bytes, ++ &wip_nav.debug_info.writer, + .{ .debug_output = .{ .dwarf = wip_nav } }, + ); +- if (old_len + size != bytes.items.len) { +- std.debug.print("{f} [{}]: {} != {}\n", .{ ty.fmt(wip_nav.pt), ty.toIntern(), size, bytes.items.len - old_len }); ++ if (old_end + size != wip_nav.debug_info.writer.end) { ++ std.debug.print("{f} [{}]: {} != {}\n", .{ ++ ty.fmt(wip_nav.pt), ++ ty.toIntern(), ++ size, ++ wip_nav.debug_info.writer.end - old_end, ++ }); + unreachable; + } + } +@@ -6429,7 +6432,7 @@ fn sleb128Bytes(value: anytype) u32 { + /// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional + const force_incremental = false; + inline fn incremental(dwarf: Dwarf) bool { +- return force_incremental or dwarf.bin_file.comp.incremental; ++ return force_incremental or dwarf.bin_file.comp.config.incremental; + } + + const Allocator = std.mem.Allocator; +diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig +index b74406c368..d7e3cf62f3 100644 +--- a/src/link/Elf/LinkerDefined.zig ++++ b/src/link/Elf/LinkerDefined.zig +@@ -47,7 +47,7 @@ fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) + const esym = self.symtab.addOneAssumeCapacity(); + esym.* = .{ + .st_name = name_off, +- .st_info = elf.STB_WEAK << 4, ++ .st_info = @as(u8, elf.STB_WEAK) << 4, + .st_other = @intFromEnum(elf.STV.HIDDEN), + .st_shndx = elf.SHN_ABS, + .st_value = 0, +diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig +index 8c79def16b..4dce40e370 100644 +--- a/src/link/Elf/SharedObject.zig ++++ b/src/link/Elf/SharedObject.zig +@@ -105,7 +105,7 @@ pub fn parseHeader( + if (amt != buf.len) return error.UnexpectedEndOfFile; + } + if (!mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF")) return error.BadMagic; +- if (ehdr.e_ident[elf.EI_VERSION] != 1) return error.BadElfVersion; ++ if (ehdr.e_ident[elf.EI.VERSION] != 1) return error.BadElfVersion; + if (ehdr.e_type != elf.ET.DYN) return error.NotSharedObject; + + if (target.toElfMachine() != ehdr.e_machine) +diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig +index bf65d04e4a..a3ede11dc4 100644 +--- a/src/link/Elf/ZigObject.zig ++++ b/src/link/Elf/ZigObject.zig +@@ -277,8 +277,8 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { + pt, + .{ .kind = .code, .ty = .anyerror_type }, + metadata.text_symbol_index, +- ) catch |err| return switch (err) { +- error.CodegenFail => error.LinkFailure, ++ ) catch |err| switch (err) { ++ error.CodegenFail => return error.LinkFailure, + else => |e| return e, + }; + if (metadata.rodata_state != .unused) self.updateLazySymbol( +@@ -286,8 +286,8 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { + pt, + .{ .kind = .const_data, .ty = .anyerror_type }, + metadata.rodata_symbol_index, +- ) catch |err| return switch (err) { +- error.CodegenFail => error.LinkFailure, ++ ) catch |err| switch (err) { ++ error.CodegenFail => return error.LinkFailure, + else => |e| return e, + }; + } +@@ -1533,22 +1533,26 @@ pub fn updateFunc( + const sym_index = try self.getOrCreateMetadataForNav(zcu, func.owner_nav); + self.atom(self.symbol(sym_index).ref.index).?.freeRelocs(self); + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null; + defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit(); + +- try codegen.emitFunction( ++ codegen.emitFunction( + &elf_file.base, + pt, + zcu.navSrcLoc(func.owner_nav), + func_index, ++ sym_index, + mir, +- &code_buffer, ++ &aw.writer, + if (debug_wip_nav) |*dn| .{ .dwarf = dn } else .none, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code); + log.debug("setting shdr({x},{s}) for {f}", .{ +@@ -1663,21 +1667,24 @@ pub fn updateNav( + const sym_index = try self.getOrCreateMetadataForNav(zcu, nav_index); + self.symbol(sym_index).atom(elf_file).?.freeRelocs(self); + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(zcu.gpa); ++ var aw: std.Io.Writer.Allocating = .init(zcu.gpa); ++ defer aw.deinit(); + + var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, nav_index, sym_index) else null; + defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit(); + +- try codegen.generateSymbol( ++ codegen.generateSymbol( + &elf_file.base, + pt, + zcu.navSrcLoc(nav_index), + Value.fromInterned(nav_init), +- &code_buffer, ++ &aw.writer, + .{ .atom_index = sym_index }, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code); + log.debug("setting shdr({x},{s}) for {f}", .{ +@@ -1722,8 +1729,8 @@ fn updateLazySymbol( + const gpa = zcu.gpa; + + var required_alignment: InternPool.Alignment = .none; +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const name_str_index = blk: { + const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{ +@@ -1734,18 +1741,20 @@ fn updateLazySymbol( + break :blk try self.strtab.insert(gpa, name); + }; + +- const src = Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse Zcu.LazySrcLoc.unneeded; +- try codegen.generateLazySymbol( ++ codegen.generateLazySymbol( + &elf_file.base, + pt, +- src, ++ Type.fromInterned(sym.ty).srcLocOrNull(zcu) orelse .unneeded, + sym, + &required_alignment, +- &code_buffer, ++ &aw.writer, + .none, + .{ .atom_index = symbol_index }, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const output_section_index = switch (sym.kind) { + .code => if (self.text_index) |sym_index| +@@ -1807,21 +1816,24 @@ fn lowerConst( + ) !codegen.SymbolResult { + const gpa = pt.zcu.gpa; + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const name_off = try self.addString(gpa, name); + const sym_index = try self.newSymbolWithAtom(gpa, name_off); + +- try codegen.generateSymbol( ++ codegen.generateSymbol( + &elf_file.base, + pt, + src_loc, + val, +- &code_buffer, ++ &aw.writer, + .{ .atom_index = sym_index }, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const local_sym = self.symbol(sym_index); + const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index]; +diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig +new file mode 100644 +index 0000000000..e43ebf2639 +--- /dev/null ++++ b/src/link/Elf2.zig +@@ -0,0 +1,2036 @@ ++base: link.File, ++mf: MappedFile, ++nodes: std.MultiArrayList(Node), ++symtab: std.ArrayList(Symbol), ++shstrtab: StringTable, ++strtab: StringTable, ++globals: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index), ++navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Symbol.Index), ++uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index), ++lazy: std.EnumArray(link.File.LazySymbol.Kind, struct { ++ map: std.AutoArrayHashMapUnmanaged(InternPool.Index, Symbol.Index), ++ pending_index: u32, ++}), ++pending_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, struct { ++ alignment: InternPool.Alignment, ++ src_loc: Zcu.LazySrcLoc, ++}), ++relocs: std.ArrayList(Reloc), ++/// This is hiding actual bugs with global symbols! Reconsider once they are implemented correctly. ++entry_hack: Symbol.Index, ++ ++pub const Node = union(enum) { ++ file, ++ ehdr, ++ shdr, ++ segment: u32, ++ section: Symbol.Index, ++ nav: InternPool.Nav.Index, ++ uav: InternPool.Index, ++ lazy_code: InternPool.Index, ++ lazy_const_data: InternPool.Index, ++ ++ pub const Tag = @typeInfo(Node).@"union".tag_type.?; ++ ++ const known_count = @typeInfo(@TypeOf(known)).@"struct".fields.len; ++ const known = known: { ++ const Known = enum { ++ file, ++ seg_rodata, ++ ehdr, ++ phdr, ++ shdr, ++ seg_text, ++ seg_data, ++ }; ++ var mut_known: std.enums.EnumFieldStruct( ++ Known, ++ MappedFile.Node.Index, ++ null, ++ ) = undefined; ++ for (@typeInfo(Known).@"enum".fields) |field| ++ @field(mut_known, field.name) = @enumFromInt(field.value); ++ break :known mut_known; ++ }; ++ ++ comptime { ++ if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Node) == 8); ++ } ++}; ++ ++pub const StringTable = struct { ++ map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage), ++ size: u32, ++ ++ const Context = struct { ++ slice: []const u8, ++ ++ pub fn eql(_: Context, lhs_key: u32, rhs_key: u32) bool { ++ return lhs_key == rhs_key; ++ } ++ ++ pub fn hash(ctx: Context, key: u32) u64 { ++ return std.hash_map.hashString(std.mem.sliceTo(ctx.slice[key..], 0)); ++ } ++ }; ++ ++ const Adapter = struct { ++ slice: []const u8, ++ ++ pub fn eql(adapter: Adapter, lhs_key: []const u8, rhs_key: u32) bool { ++ return std.mem.startsWith(u8, adapter.slice[rhs_key..], lhs_key) and ++ adapter.slice[rhs_key + lhs_key.len] == 0; ++ } ++ ++ pub fn hash(_: Adapter, key: []const u8) u64 { ++ assert(std.mem.indexOfScalar(u8, key, 0) == null); ++ return std.hash_map.hashString(key); ++ } ++ }; ++ ++ pub fn get( ++ st: *StringTable, ++ gpa: std.mem.Allocator, ++ mf: *MappedFile, ++ ni: MappedFile.Node.Index, ++ key: []const u8, ++ ) !u32 { ++ const slice_const = ni.sliceConst(mf); ++ const gop = try st.map.getOrPutContextAdapted( ++ gpa, ++ key, ++ StringTable.Adapter{ .slice = slice_const }, ++ .{ .slice = slice_const }, ++ ); ++ if (gop.found_existing) return gop.key_ptr.*; ++ const old_size = st.size; ++ const new_size: u32 = @intCast(old_size + key.len + 1); ++ st.size = new_size; ++ try ni.resize(mf, gpa, new_size); ++ const slice = ni.slice(mf)[old_size..]; ++ @memcpy(slice[0..key.len], key); ++ slice[key.len] = 0; ++ gop.key_ptr.* = old_size; ++ return old_size; ++ } ++}; ++ ++pub const Symbol = struct { ++ ni: MappedFile.Node.Index, ++ /// Relocations contained within this symbol ++ loc_relocs: Reloc.Index, ++ /// Relocations targeting this symbol ++ target_relocs: Reloc.Index, ++ unused: u32 = 0, ++ ++ pub const Index = enum(u32) { ++ null, ++ symtab, ++ shstrtab, ++ strtab, ++ rodata, ++ text, ++ data, ++ tdata, ++ _, ++ ++ pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { ++ return &elf.symtab.items[@intFromEnum(si)]; ++ } ++ ++ pub fn node(si: Symbol.Index, elf: *Elf) MappedFile.Node.Index { ++ const ni = si.get(elf).ni; ++ assert(ni != .none); ++ return ni; ++ } ++ ++ pub const InitOptions = struct { ++ name: []const u8 = "", ++ size: std.elf.Word = 0, ++ type: std.elf.STT, ++ bind: std.elf.STB = .LOCAL, ++ visibility: std.elf.STV = .DEFAULT, ++ shndx: std.elf.Section = std.elf.SHN_UNDEF, ++ }; ++ pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { ++ const name_entry = try elf.string(.strtab, opts.name); ++ try Symbol.Index.symtab.node(elf).resize( ++ &elf.mf, ++ elf.base.comp.gpa, ++ @as(usize, switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ .@"32" => @sizeOf(std.elf.Elf32.Sym), ++ .@"64" => @sizeOf(std.elf.Elf64.Sym), ++ }) * elf.symtab.items.len, ++ ); ++ switch (elf.symPtr(si)) { ++ inline else => |sym| sym.* = .{ ++ .name = name_entry, ++ .value = 0, ++ .size = opts.size, ++ .info = .{ ++ .type = opts.type, ++ .bind = opts.bind, ++ }, ++ .other = .{ ++ .visibility = opts.visibility, ++ }, ++ .shndx = opts.shndx, ++ }, ++ } ++ } ++ ++ pub fn applyLocationRelocs(si: Symbol.Index, elf: *Elf) void { ++ for (elf.relocs.items[@intFromEnum(si.get(elf).loc_relocs)..]) |*reloc| { ++ if (reloc.loc != si) break; ++ reloc.apply(elf); ++ } ++ } ++ ++ pub fn applyTargetRelocs(si: Symbol.Index, elf: *Elf) void { ++ var ri = si.get(elf).target_relocs; ++ while (ri != .none) { ++ const reloc = ri.get(elf); ++ assert(reloc.target == si); ++ reloc.apply(elf); ++ ri = reloc.next; ++ } ++ } ++ ++ pub fn deleteLocationRelocs(si: Symbol.Index, elf: *Elf) void { ++ const sym = si.get(elf); ++ for (elf.relocs.items[@intFromEnum(sym.loc_relocs)..]) |*reloc| { ++ if (reloc.loc != si) break; ++ reloc.delete(elf); ++ } ++ sym.loc_relocs = .none; ++ } ++ }; ++ ++ comptime { ++ if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Symbol) == 16); ++ } ++}; ++ ++pub const Reloc = extern struct { ++ type: Reloc.Type, ++ prev: Reloc.Index, ++ next: Reloc.Index, ++ loc: Symbol.Index, ++ target: Symbol.Index, ++ unused: u32, ++ offset: u64, ++ addend: i64, ++ ++ pub const Type = extern union { ++ x86_64: std.elf.R_X86_64, ++ aarch64: std.elf.R_AARCH64, ++ riscv: std.elf.R_RISCV, ++ ppc64: std.elf.R_PPC64, ++ }; ++ ++ pub const Index = enum(u32) { ++ none = std.math.maxInt(u32), ++ _, ++ ++ pub fn get(si: Reloc.Index, elf: *Elf) *Reloc { ++ return &elf.relocs.items[@intFromEnum(si)]; ++ } ++ }; ++ ++ pub fn apply(reloc: *const Reloc, elf: *Elf) void { ++ const target_endian = elf.endian(); ++ switch (reloc.loc.get(elf).ni) { ++ .none => return, ++ else => |ni| if (ni.hasMoved(&elf.mf)) return, ++ } ++ switch (reloc.target.get(elf).ni) { ++ .none => return, ++ else => |ni| if (ni.hasMoved(&elf.mf)) return, ++ } ++ switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symSlice(), @tagName(class)); ++ const loc_sym = &sym[@intFromEnum(reloc.loc)]; ++ const loc_shndx = ++ std.mem.toNative(@TypeOf(loc_sym.shndx), loc_sym.shndx, target_endian); ++ assert(loc_shndx != std.elf.SHN_UNDEF); ++ const loc_sh = &shdr[loc_shndx]; ++ const loc_value = std.mem.toNative( ++ @TypeOf(loc_sym.value), ++ loc_sym.value, ++ target_endian, ++ ) + reloc.offset; ++ const loc_sh_addr = ++ std.mem.toNative(@TypeOf(loc_sh.addr), loc_sh.addr, target_endian); ++ const loc_sh_offset = ++ std.mem.toNative(@TypeOf(loc_sh.offset), loc_sh.offset, target_endian); ++ const loc_file_offset: usize = @intCast(loc_value - loc_sh_addr + loc_sh_offset); ++ const target_sym = &sym[@intFromEnum(reloc.target)]; ++ const target_value = std.mem.toNative( ++ @TypeOf(target_sym.value), ++ target_sym.value, ++ target_endian, ++ ) +% @as(u64, @bitCast(reloc.addend)); ++ switch (elf.ehdrField(.machine)) { ++ else => |machine| @panic(@tagName(machine)), ++ .X86_64 => switch (reloc.type.x86_64) { ++ else => |kind| @panic(@tagName(kind)), ++ .@"64" => std.mem.writeInt( ++ u64, ++ elf.mf.contents[loc_file_offset..][0..8], ++ target_value, ++ target_endian, ++ ), ++ .PC32 => std.mem.writeInt( ++ i32, ++ elf.mf.contents[loc_file_offset..][0..4], ++ @intCast(@as(i64, @bitCast(target_value -% loc_value))), ++ target_endian, ++ ), ++ .@"32" => std.mem.writeInt( ++ u32, ++ elf.mf.contents[loc_file_offset..][0..4], ++ @intCast(target_value), ++ target_endian, ++ ), ++ .TPOFF32 => { ++ const phdr = @field(elf.phdrSlice(), @tagName(class)); ++ const ph = &phdr[4]; ++ assert(std.mem.toNative( ++ @TypeOf(ph.type), ++ ph.type, ++ target_endian, ++ ) == std.elf.PT_TLS); ++ std.mem.writeInt( ++ i32, ++ elf.mf.contents[loc_file_offset..][0..4], ++ @intCast(@as(i64, @bitCast(target_value -% std.mem.toNative( ++ @TypeOf(ph.memsz), ++ ph.memsz, ++ target_endian, ++ )))), ++ target_endian, ++ ); ++ }, ++ }, ++ } ++ }, ++ } ++ } ++ ++ pub fn delete(reloc: *Reloc, elf: *Elf) void { ++ switch (reloc.prev) { ++ .none => { ++ const target = reloc.target.get(elf); ++ assert(target.target_relocs.get(elf) == reloc); ++ target.target_relocs = reloc.next; ++ }, ++ else => |prev| prev.get(elf).next = reloc.next, ++ } ++ switch (reloc.next) { ++ .none => {}, ++ else => |next| next.get(elf).prev = reloc.prev, ++ } ++ reloc.* = undefined; ++ } ++ ++ comptime { ++ if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Reloc) == 40); ++ } ++}; ++ ++pub fn open( ++ arena: std.mem.Allocator, ++ comp: *Compilation, ++ path: std.Build.Cache.Path, ++ options: link.File.OpenOptions, ++) !*Elf { ++ return create(arena, comp, path, options); ++} ++pub fn createEmpty( ++ arena: std.mem.Allocator, ++ comp: *Compilation, ++ path: std.Build.Cache.Path, ++ options: link.File.OpenOptions, ++) !*Elf { ++ return create(arena, comp, path, options); ++} ++fn create( ++ arena: std.mem.Allocator, ++ comp: *Compilation, ++ path: std.Build.Cache.Path, ++ options: link.File.OpenOptions, ++) !*Elf { ++ _ = options; ++ const target = &comp.root_mod.resolved_target.result; ++ assert(target.ofmt == .elf); ++ const class: std.elf.CLASS = switch (target.ptrBitWidth()) { ++ 0...32 => .@"32", ++ 33...64 => .@"64", ++ else => return error.UnsupportedELFArchitecture, ++ }; ++ const data: std.elf.DATA = switch (target.cpu.arch.endian()) { ++ .little => .@"2LSB", ++ .big => .@"2MSB", ++ }; ++ const osabi: std.elf.OSABI = switch (target.os.tag) { ++ else => .NONE, ++ .freestanding, .other => .STANDALONE, ++ .netbsd => .NETBSD, ++ .solaris => .SOLARIS, ++ .aix => .AIX, ++ .freebsd => .FREEBSD, ++ .cuda => .CUDA, ++ .amdhsa => .AMDGPU_HSA, ++ .amdpal => .AMDGPU_PAL, ++ .mesa3d => .AMDGPU_MESA3D, ++ }; ++ const @"type": std.elf.ET = switch (comp.config.output_mode) { ++ .Exe => if (comp.config.pie or target.os.tag == .haiku) .DYN else .EXEC, ++ .Lib => switch (comp.config.link_mode) { ++ .static => .REL, ++ .dynamic => .DYN, ++ }, ++ .Obj => .REL, ++ }; ++ const machine: std.elf.EM = switch (target.cpu.arch) { ++ .spirv32, .spirv64, .wasm32, .wasm64 => .NONE, ++ .sparc => .SPARC, ++ .x86 => .@"386", ++ .m68k => .@"68K", ++ .mips, .mipsel, .mips64, .mips64el => .MIPS, ++ .powerpc, .powerpcle => .PPC, ++ .powerpc64, .powerpc64le => .PPC64, ++ .s390x => .S390, ++ .arm, .armeb, .thumb, .thumbeb => .ARM, ++ .hexagon => .SH, ++ .sparc64 => .SPARCV9, ++ .arc => .ARC, ++ .x86_64 => .X86_64, ++ .or1k => .OR1K, ++ .xtensa => .XTENSA, ++ .msp430 => .MSP430, ++ .avr => .AVR, ++ .nvptx, .nvptx64 => .CUDA, ++ .kalimba => .CSR_KALIMBA, ++ .aarch64, .aarch64_be => .AARCH64, ++ .xcore => .XCORE, ++ .amdgcn => .AMDGPU, ++ .riscv32, .riscv32be, .riscv64, .riscv64be => .RISCV, ++ .lanai => .LANAI, ++ .bpfel, .bpfeb => .BPF, ++ .ve => .VE, ++ .csky => .CSKY, ++ .loongarch32, .loongarch64 => .LOONGARCH, ++ .propeller => if (target.cpu.has(.propeller, .p2)) .PROPELLER2 else .PROPELLER, ++ }; ++ const maybe_interp = switch (comp.config.output_mode) { ++ .Exe, .Lib => switch (comp.config.link_mode) { ++ .static => null, ++ .dynamic => target.dynamic_linker.get(), ++ }, ++ .Obj => null, ++ }; ++ ++ const elf = try arena.create(Elf); ++ const file = try path.root_dir.handle.createFile(path.sub_path, .{ ++ .read = true, ++ .mode = link.File.determineMode(comp.config.output_mode, comp.config.link_mode), ++ }); ++ errdefer file.close(); ++ elf.* = .{ ++ .base = .{ ++ .tag = .elf2, ++ ++ .comp = comp, ++ .emit = path, ++ ++ .file = file, ++ .gc_sections = false, ++ .print_gc_sections = false, ++ .build_id = .none, ++ .allow_shlib_undefined = false, ++ .stack_size = 0, ++ }, ++ .mf = try .init(file, comp.gpa), ++ .nodes = .empty, ++ .symtab = .empty, ++ .shstrtab = .{ ++ .map = .empty, ++ .size = 1, ++ }, ++ .strtab = .{ ++ .map = .empty, ++ .size = 1, ++ }, ++ .globals = .empty, ++ .navs = .empty, ++ .uavs = .empty, ++ .lazy = .initFill(.{ ++ .map = .empty, ++ .pending_index = 0, ++ }), ++ .pending_uavs = .empty, ++ .relocs = .empty, ++ .entry_hack = .null, ++ }; ++ errdefer elf.deinit(); ++ ++ switch (class) { ++ .NONE, _ => unreachable, ++ inline .@"32", .@"64" => |ct_class| try elf.initHeaders( ++ ct_class, ++ data, ++ osabi, ++ @"type", ++ machine, ++ maybe_interp, ++ ), ++ } ++ ++ return elf; ++} ++ ++pub fn deinit(elf: *Elf) void { ++ const gpa = elf.base.comp.gpa; ++ elf.mf.deinit(gpa); ++ elf.nodes.deinit(gpa); ++ elf.symtab.deinit(gpa); ++ elf.shstrtab.map.deinit(gpa); ++ elf.strtab.map.deinit(gpa); ++ elf.globals.deinit(gpa); ++ elf.navs.deinit(gpa); ++ elf.uavs.deinit(gpa); ++ for (&elf.lazy.values) |*lazy| lazy.map.deinit(gpa); ++ elf.pending_uavs.deinit(gpa); ++ elf.relocs.deinit(gpa); ++ elf.* = undefined; ++} ++ ++fn initHeaders( ++ elf: *Elf, ++ comptime class: std.elf.CLASS, ++ data: std.elf.DATA, ++ osabi: std.elf.OSABI, ++ @"type": std.elf.ET, ++ machine: std.elf.EM, ++ maybe_interp: ?[]const u8, ++) !void { ++ const comp = elf.base.comp; ++ const gpa = comp.gpa; ++ const ElfN = switch (class) { ++ .NONE, _ => comptime unreachable, ++ .@"32" => std.elf.Elf32, ++ .@"64" => std.elf.Elf64, ++ }; ++ const addr_align: std.mem.Alignment = comptime .fromByteUnits(@sizeOf(ElfN.Addr)); ++ const target_endian: std.builtin.Endian = switch (data) { ++ .NONE, _ => unreachable, ++ .@"2LSB" => .little, ++ .@"2MSB" => .big, ++ }; ++ ++ var phnum: u32 = 0; ++ const phdr_phndx = phnum; ++ phnum += 1; ++ const interp_phndx = if (maybe_interp) |_| phndx: { ++ defer phnum += 1; ++ break :phndx phnum; ++ } else undefined; ++ const rodata_phndx = phnum; ++ phnum += 1; ++ const text_phndx = phnum; ++ phnum += 1; ++ const data_phndx = phnum; ++ phnum += 1; ++ const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { ++ defer phnum += 1; ++ break :phndx phnum; ++ } else undefined; ++ ++ try elf.nodes.ensureTotalCapacity(gpa, Node.known_count); ++ elf.nodes.appendAssumeCapacity(.file); ++ ++ const seg_rodata_ni = Node.known.seg_rodata; ++ assert(seg_rodata_ni == try elf.mf.addOnlyChildNode(gpa, .root, .{ ++ .alignment = elf.mf.flags.block_size, ++ .fixed = true, ++ .moved = true, ++ })); ++ elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx }); ++ ++ const ehdr_ni = Node.known.ehdr; ++ assert(ehdr_ni == try elf.mf.addOnlyChildNode(gpa, seg_rodata_ni, .{ ++ .size = @sizeOf(ElfN.Ehdr), ++ .alignment = addr_align, ++ .fixed = true, ++ })); ++ elf.nodes.appendAssumeCapacity(.ehdr); ++ ++ const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(ehdr_ni.slice(&elf.mf))); ++ const EI = std.elf.EI; ++ @memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC); ++ ehdr.ident[EI.CLASS] = @intFromEnum(class); ++ ehdr.ident[EI.DATA] = @intFromEnum(data); ++ ehdr.ident[EI.VERSION] = 1; ++ ehdr.ident[EI.OSABI] = @intFromEnum(osabi); ++ ehdr.ident[EI.ABIVERSION] = 0; ++ @memset(ehdr.ident[EI.PAD..], 0); ++ ehdr.type = @"type"; ++ ehdr.machine = machine; ++ ehdr.version = 1; ++ ehdr.entry = 0; ++ ehdr.phoff = 0; ++ ehdr.shoff = 0; ++ ehdr.flags = 0; ++ ehdr.ehsize = @sizeOf(ElfN.Ehdr); ++ ehdr.phentsize = @sizeOf(ElfN.Phdr); ++ ehdr.phnum = @min(phnum, std.elf.PN_XNUM); ++ ehdr.shentsize = @sizeOf(ElfN.Shdr); ++ ehdr.shnum = 1; ++ ehdr.shstrndx = 0; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); ++ ++ const phdr_ni = Node.known.phdr; ++ assert(phdr_ni == try elf.mf.addLastChildNode(gpa, seg_rodata_ni, .{ ++ .size = @sizeOf(ElfN.Phdr) * phnum, ++ .alignment = addr_align, ++ .moved = true, ++ .resized = true, ++ })); ++ elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx }); ++ ++ const shdr_ni = Node.known.shdr; ++ assert(shdr_ni == try elf.mf.addLastChildNode(gpa, seg_rodata_ni, .{ ++ .size = @sizeOf(ElfN.Shdr), ++ .alignment = addr_align, ++ })); ++ elf.nodes.appendAssumeCapacity(.shdr); ++ ++ const seg_text_ni = Node.known.seg_text; ++ assert(seg_text_ni == try elf.mf.addLastChildNode(gpa, .root, .{ ++ .alignment = elf.mf.flags.block_size, ++ .moved = true, ++ })); ++ elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx }); ++ ++ const seg_data_ni = Node.known.seg_data; ++ assert(seg_data_ni == try elf.mf.addLastChildNode(gpa, .root, .{ ++ .alignment = elf.mf.flags.block_size, ++ .moved = true, ++ })); ++ elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); ++ ++ assert(elf.nodes.len == Node.known_count); ++ ++ { ++ const phdr: []ElfN.Phdr = @ptrCast(@alignCast(phdr_ni.slice(&elf.mf))); ++ const ph_phdr = &phdr[phdr_phndx]; ++ ph_phdr.* = .{ ++ .type = std.elf.PT_PHDR, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true }, ++ .@"align" = @intCast(phdr_ni.alignment(&elf.mf).toByteUnits()), ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_phdr); ++ ++ if (maybe_interp) |_| { ++ const ph_interp = &phdr[interp_phndx]; ++ ph_interp.* = .{ ++ .type = std.elf.PT_INTERP, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true }, ++ .@"align" = 1, ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_interp); ++ } ++ ++ const ph_rodata = &phdr[rodata_phndx]; ++ ph_rodata.* = .{ ++ .type = std.elf.PT_NULL, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true }, ++ .@"align" = @intCast(seg_rodata_ni.alignment(&elf.mf).toByteUnits()), ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); ++ ++ const ph_text = &phdr[text_phndx]; ++ ph_text.* = .{ ++ .type = std.elf.PT_NULL, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true, .X = true }, ++ .@"align" = @intCast(seg_text_ni.alignment(&elf.mf).toByteUnits()), ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); ++ ++ const ph_data = &phdr[data_phndx]; ++ ph_data.* = .{ ++ .type = std.elf.PT_NULL, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true, .W = true }, ++ .@"align" = @intCast(seg_data_ni.alignment(&elf.mf).toByteUnits()), ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); ++ ++ if (comp.config.any_non_single_threaded) { ++ const ph_tls = &phdr[tls_phndx]; ++ ph_tls.* = .{ ++ .type = std.elf.PT_TLS, ++ .offset = 0, ++ .vaddr = 0, ++ .paddr = 0, ++ .filesz = 0, ++ .memsz = 0, ++ .flags = .{ .R = true }, ++ .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()), ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_tls); ++ } ++ ++ const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(shdr_ni.slice(&elf.mf))); ++ sh_null.* = .{ ++ .name = try elf.string(.shstrtab, ""), ++ .type = std.elf.SHT_NULL, ++ .flags = .{ .shf = .{} }, ++ .addr = 0, ++ .offset = 0, ++ .size = 0, ++ .link = 0, ++ .info = if (phnum >= std.elf.PN_XNUM) phnum else 0, ++ .addralign = 0, ++ .entsize = 0, ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_null); ++ } ++ ++ try elf.symtab.ensureTotalCapacity(gpa, 1); ++ elf.symtab.addOneAssumeCapacity().* = .{ ++ .ni = .none, ++ .loc_relocs = .none, ++ .target_relocs = .none, ++ .unused = 0, ++ }; ++ assert(try elf.addSection(seg_rodata_ni, .{ ++ .type = std.elf.SHT_SYMTAB, ++ .addralign = addr_align, ++ .entsize = @sizeOf(ElfN.Sym), ++ }) == .symtab); ++ const symtab: *ElfN.Sym = @ptrCast(@alignCast(Symbol.Index.symtab.node(elf).slice(&elf.mf))); ++ symtab.* = .{ ++ .name = try elf.string(.strtab, ""), ++ .value = 0, ++ .size = 0, ++ .info = .{ ++ .type = .NOTYPE, ++ .bind = .LOCAL, ++ }, ++ .other = .{ ++ .visibility = .DEFAULT, ++ }, ++ .shndx = std.elf.SHN_UNDEF, ++ }; ++ ehdr.shstrndx = ehdr.shnum; ++ assert(try elf.addSection(seg_rodata_ni, .{ ++ .type = std.elf.SHT_STRTAB, ++ .addralign = elf.mf.flags.block_size, ++ .entsize = 1, ++ }) == .shstrtab); ++ assert(try elf.addSection(seg_rodata_ni, .{ ++ .type = std.elf.SHT_STRTAB, ++ .addralign = elf.mf.flags.block_size, ++ .entsize = 1, ++ }) == .strtab); ++ try elf.renameSection(.symtab, ".symtab"); ++ try elf.renameSection(.shstrtab, ".shstrtab"); ++ try elf.renameSection(.strtab, ".strtab"); ++ try elf.linkSections(.symtab, .strtab); ++ Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[0] = 0; ++ Symbol.Index.strtab.node(elf).slice(&elf.mf)[0] = 0; ++ ++ assert(try elf.addSection(seg_rodata_ni, .{ ++ .name = ".rodata", ++ .flags = .{ .ALLOC = true }, ++ .addralign = elf.mf.flags.block_size, ++ }) == .rodata); ++ assert(try elf.addSection(seg_text_ni, .{ ++ .name = ".text", ++ .flags = .{ .ALLOC = true, .EXECINSTR = true }, ++ .addralign = elf.mf.flags.block_size, ++ }) == .text); ++ assert(try elf.addSection(seg_data_ni, .{ ++ .name = ".data", ++ .flags = .{ .WRITE = true, .ALLOC = true }, ++ .addralign = elf.mf.flags.block_size, ++ }) == .data); ++ if (comp.config.any_non_single_threaded) { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const seg_tls_ni = try elf.mf.addLastChildNode(gpa, seg_data_ni, .{ ++ .alignment = elf.mf.flags.block_size, ++ .moved = true, ++ }); ++ elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx }); ++ ++ assert(try elf.addSection(seg_tls_ni, .{ ++ .name = ".tdata", ++ .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, ++ .addralign = elf.mf.flags.block_size, ++ }) == .tdata); ++ } ++ if (maybe_interp) |interp| { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const seg_interp_ni = try elf.mf.addLastChildNode(gpa, seg_rodata_ni, .{ ++ .size = interp.len + 1, ++ .moved = true, ++ .resized = true, ++ }); ++ elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx }); ++ ++ const sec_interp_si = try elf.addSection(seg_interp_ni, .{ ++ .name = ".interp", ++ .size = @intCast(interp.len + 1), ++ .flags = .{ .ALLOC = true }, ++ }); ++ const sec_interp = sec_interp_si.node(elf).slice(&elf.mf); ++ @memcpy(sec_interp[0..interp.len], interp); ++ sec_interp[interp.len] = 0; ++ } ++} ++ ++fn getNode(elf: *Elf, ni: MappedFile.Node.Index) Node { ++ return elf.nodes.get(@intFromEnum(ni)); ++} ++ ++pub const EhdrPtr = union(std.elf.CLASS) { ++ NONE: noreturn, ++ @"32": *std.elf.Elf32.Ehdr, ++ @"64": *std.elf.Elf64.Ehdr, ++}; ++pub fn ehdrPtr(elf: *Elf) EhdrPtr { ++ const slice = Node.known.ehdr.slice(&elf.mf); ++ return switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ inline .@"32", .@"64" => |class| @unionInit( ++ EhdrPtr, ++ @tagName(class), ++ @ptrCast(@alignCast(slice)), ++ ), ++ }; ++} ++pub fn ehdrField( ++ elf: *Elf, ++ comptime field: enum { type, machine }, ++) @FieldType(std.elf.Elf32.Ehdr, @tagName(field)) { ++ const Field = @FieldType(std.elf.Elf32.Ehdr, @tagName(field)); ++ comptime assert(@FieldType(std.elf.Elf64.Ehdr, @tagName(field)) == Field); ++ return @enumFromInt(std.mem.toNative( ++ @typeInfo(Field).@"enum".tag_type, ++ @intFromEnum(switch (elf.ehdrPtr()) { ++ inline else => |ehdr| @field(ehdr, @tagName(field)), ++ }), ++ elf.endian(), ++ )); ++} ++ ++pub fn identClass(elf: *Elf) std.elf.CLASS { ++ return @enumFromInt(elf.mf.contents[std.elf.EI.CLASS]); ++} ++ ++pub fn identData(elf: *Elf) std.elf.DATA { ++ return @enumFromInt(elf.mf.contents[std.elf.EI.DATA]); ++} ++fn endianForData(data: std.elf.DATA) std.builtin.Endian { ++ return switch (data) { ++ .NONE, _ => unreachable, ++ .@"2LSB" => .little, ++ .@"2MSB" => .big, ++ }; ++} ++pub fn endian(elf: *Elf) std.builtin.Endian { ++ return endianForData(elf.identData()); ++} ++ ++fn baseAddrForType(@"type": std.elf.ET) u64 { ++ return switch (@"type") { ++ else => 0, ++ .EXEC => 0x1000000, ++ }; ++} ++pub fn baseAddr(elf: *Elf) u64 { ++ return baseAddrForType(elf.ehdrField(.type)); ++} ++ ++pub const PhdrSlice = union(std.elf.CLASS) { ++ NONE: noreturn, ++ @"32": []std.elf.Elf32.Phdr, ++ @"64": []std.elf.Elf64.Phdr, ++}; ++pub fn phdrSlice(elf: *Elf) PhdrSlice { ++ const slice = Node.known.phdr.slice(&elf.mf); ++ return switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ inline .@"32", .@"64" => |class| @unionInit( ++ PhdrSlice, ++ @tagName(class), ++ @ptrCast(@alignCast(slice)), ++ ), ++ }; ++} ++ ++pub const ShdrSlice = union(std.elf.CLASS) { ++ NONE: noreturn, ++ @"32": []std.elf.Elf32.Shdr, ++ @"64": []std.elf.Elf64.Shdr, ++}; ++pub fn shdrSlice(elf: *Elf) ShdrSlice { ++ const slice = Node.known.shdr.slice(&elf.mf); ++ return switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ inline .@"32", .@"64" => |class| @unionInit( ++ ShdrSlice, ++ @tagName(class), ++ @ptrCast(@alignCast(slice)), ++ ), ++ }; ++} ++ ++pub const SymSlice = union(std.elf.CLASS) { ++ NONE: noreturn, ++ @"32": []std.elf.Elf32.Sym, ++ @"64": []std.elf.Elf64.Sym, ++}; ++pub fn symSlice(elf: *Elf) SymSlice { ++ const slice = Symbol.Index.symtab.node(elf).slice(&elf.mf); ++ return switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ inline .@"32", .@"64" => |class| @unionInit( ++ SymSlice, ++ @tagName(class), ++ @ptrCast(@alignCast(slice)), ++ ), ++ }; ++} ++ ++pub const SymPtr = union(std.elf.CLASS) { ++ NONE: noreturn, ++ @"32": *std.elf.Elf32.Sym, ++ @"64": *std.elf.Elf64.Sym, ++}; ++pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr { ++ return switch (elf.symSlice()) { ++ inline else => |sym, class| @unionInit(SymPtr, @tagName(class), &sym[@intFromEnum(si)]), ++ }; ++} ++ ++fn addSymbolAssumeCapacity(elf: *Elf) !Symbol.Index { ++ defer elf.symtab.addOneAssumeCapacity().* = .{ ++ .ni = .none, ++ .loc_relocs = .none, ++ .target_relocs = .none, ++ .unused = 0, ++ }; ++ return @enumFromInt(elf.symtab.items.len); ++} ++ ++fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.Index { ++ const si = try elf.addSymbolAssumeCapacity(); ++ try si.init(elf, opts); ++ return si; ++} ++ ++pub fn globalSymbol( ++ elf: *Elf, ++ opts: struct { ++ name: []const u8, ++ type: std.elf.STT, ++ bind: std.elf.STB = .GLOBAL, ++ visibility: std.elf.STV = .DEFAULT, ++ }, ++) !Symbol.Index { ++ const gpa = elf.base.comp.gpa; ++ try elf.symtab.ensureUnusedCapacity(gpa, 1); ++ const sym_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name)); ++ if (!sym_gop.found_existing) sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ ++ .name = opts.name, ++ .type = opts.type, ++ .bind = opts.bind, ++ .visibility = opts.visibility, ++ }); ++ return sym_gop.value_ptr.*; ++} ++ ++fn navType( ++ ip: *const InternPool, ++ nav_status: @FieldType(InternPool.Nav, "status"), ++ any_non_single_threaded: bool, ++) std.elf.STT { ++ return switch (nav_status) { ++ .unresolved => unreachable, ++ .type_resolved => |tr| if (any_non_single_threaded and tr.is_threadlocal) ++ .TLS ++ else if (ip.isFunctionType(tr.type)) ++ .FUNC ++ else ++ .OBJECT, ++ .fully_resolved => |fr| switch (ip.indexToKey(fr.val)) { ++ else => .OBJECT, ++ .variable => |variable| if (any_non_single_threaded and variable.is_threadlocal) ++ .TLS ++ else ++ .OBJECT, ++ .@"extern" => |@"extern"| if (any_non_single_threaded and @"extern".is_threadlocal) ++ .TLS ++ else if (ip.isFunctionType(@"extern".ty)) ++ .FUNC ++ else ++ .OBJECT, ++ .func => .FUNC, ++ }, ++ }; ++} ++pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.Index { ++ const gpa = zcu.gpa; ++ const ip = &zcu.intern_pool; ++ const nav = ip.getNav(nav_index); ++ if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{ ++ .name = @"extern".name.toSlice(ip), ++ .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), ++ .bind = switch (@"extern".linkage) { ++ .internal => .LOCAL, ++ .strong => .GLOBAL, ++ .weak => .WEAK, ++ .link_once => return error.LinkOnceUnsupported, ++ }, ++ .visibility = switch (@"extern".visibility) { ++ .default => .DEFAULT, ++ .hidden => .HIDDEN, ++ .protected => .PROTECTED, ++ }, ++ }); ++ try elf.symtab.ensureUnusedCapacity(gpa, 1); ++ const sym_gop = try elf.navs.getOrPut(gpa, nav_index); ++ if (!sym_gop.found_existing) { ++ sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ ++ .name = nav.fqn.toSlice(ip), ++ .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), ++ }); ++ } ++ return sym_gop.value_ptr.*; ++} ++ ++pub fn uavSymbol(elf: *Elf, uav_val: InternPool.Index) !Symbol.Index { ++ const gpa = elf.base.comp.gpa; ++ try elf.symtab.ensureUnusedCapacity(gpa, 1); ++ const sym_gop = try elf.uavs.getOrPut(gpa, uav_val); ++ if (!sym_gop.found_existing) ++ sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ .type = .OBJECT }); ++ return sym_gop.value_ptr.*; ++} ++ ++pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index { ++ const gpa = elf.base.comp.gpa; ++ try elf.symtab.ensureUnusedCapacity(gpa, 1); ++ const sym_gop = try elf.lazy.getPtr(lazy.kind).map.getOrPut(gpa, lazy.ty); ++ if (!sym_gop.found_existing) { ++ sym_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ ++ .type = switch (lazy.kind) { ++ .code => .FUNC, ++ .const_data => .OBJECT, ++ }, ++ }); ++ elf.base.comp.link_lazy_prog_node.increaseEstimatedTotalItems(1); ++ } ++ return sym_gop.value_ptr.*; ++} ++ ++pub fn getNavVAddr( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ nav: InternPool.Nav.Index, ++ reloc_info: link.File.RelocInfo, ++) !u64 { ++ return elf.getVAddr(reloc_info, try elf.navSymbol(pt.zcu, nav)); ++} ++ ++pub fn getUavVAddr( ++ elf: *Elf, ++ uav: InternPool.Index, ++ reloc_info: link.File.RelocInfo, ++) !u64 { ++ return elf.getVAddr(reloc_info, try elf.uavSymbol(uav)); ++} ++ ++pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.Index) !u64 { ++ try elf.addReloc( ++ @enumFromInt(reloc_info.parent.atom_index), ++ reloc_info.offset, ++ target_si, ++ reloc_info.addend, ++ switch (elf.ehdrField(.machine)) { ++ else => unreachable, ++ .X86_64 => .{ .x86_64 = switch (elf.identClass()) { ++ .NONE, _ => unreachable, ++ .@"32" => .@"32", ++ .@"64" => .@"64", ++ } }, ++ }, ++ ); ++ return 0; ++} ++ ++fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { ++ name: []const u8 = "", ++ type: std.elf.Word = std.elf.SHT_NULL, ++ size: std.elf.Word = 0, ++ flags: std.elf.SHF = .{}, ++ addralign: std.mem.Alignment = .@"1", ++ entsize: std.elf.Word = 0, ++}) !Symbol.Index { ++ const gpa = elf.base.comp.gpa; ++ const target_endian = elf.endian(); ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ try elf.symtab.ensureUnusedCapacity(gpa, 1); ++ ++ const shstrtab_entry = try elf.string(.shstrtab, opts.name); ++ const shndx, const shdr_size = shndx: switch (elf.ehdrPtr()) { ++ inline else => |ehdr| { ++ const shentsize = std.mem.toNative(@TypeOf(ehdr.shentsize), ehdr.shentsize, target_endian); ++ const shndx = std.mem.toNative(@TypeOf(ehdr.shnum), ehdr.shnum, target_endian); ++ const shnum = shndx + 1; ++ ehdr.shnum = std.mem.nativeTo(@TypeOf(ehdr.shnum), shnum, target_endian); ++ break :shndx .{ shndx, shentsize * shnum }; ++ }, ++ }; ++ try Node.known.shdr.resize(&elf.mf, gpa, shdr_size); ++ const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{ ++ .alignment = opts.addralign, ++ .size = opts.size, ++ .moved = true, ++ }); ++ const si = try elf.addSymbolAssumeCapacity(); ++ elf.nodes.appendAssumeCapacity(.{ .section = si }); ++ si.get(elf).ni = ni; ++ try si.init(elf, .{ ++ .name = opts.name, ++ .size = opts.size, ++ .type = .SECTION, ++ .shndx = shndx, ++ }); ++ switch (elf.shdrSlice()) { ++ inline else => |shdr| { ++ const sh = &shdr[shndx]; ++ sh.* = .{ ++ .name = shstrtab_entry, ++ .type = opts.type, ++ .flags = .{ .shf = opts.flags }, ++ .addr = 0, ++ .offset = 0, ++ .size = opts.size, ++ .link = 0, ++ .info = 0, ++ .addralign = @intCast(opts.addralign.toByteUnits()), ++ .entsize = opts.entsize, ++ }; ++ if (target_endian != native_endian) std.mem.byteSwapAllFields(@TypeOf(sh.*), sh); ++ }, ++ } ++ return si; ++} ++ ++fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void { ++ const strtab_entry = try elf.string(.strtab, name); ++ const shstrtab_entry = try elf.string(.shstrtab, name); ++ const target_endian = elf.endian(); ++ switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ sym.name = std.mem.nativeTo(@TypeOf(sym.name), strtab_entry, target_endian); ++ const shndx = std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian); ++ const sh = &shdr[shndx]; ++ sh.name = std.mem.nativeTo(@TypeOf(sh.name), shstrtab_entry, target_endian); ++ }, ++ } ++} ++ ++fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void { ++ const target_endian = elf.endian(); ++ switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ const shndx = std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian); ++ shdr[shndx].link = @field(elf.symPtr(link_si), @tagName(class)).shndx; ++ }, ++ } ++} ++ ++fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { ++ const target_endian = elf.endian(); ++ const name = Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[name: switch (elf.shdrSlice()) { ++ inline else => |shndx, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ const sh = &shndx[std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian)]; ++ break :name std.mem.toNative(@TypeOf(sh.name), sh.name, target_endian); ++ }, ++ }..]; ++ return name[0..std.mem.indexOfScalar(u8, name, 0).? :0]; ++} ++ ++fn string(elf: *Elf, comptime section: enum { shstrtab, strtab }, key: []const u8) !u32 { ++ if (key.len == 0) return 0; ++ return @field(elf, @tagName(section)).get( ++ elf.base.comp.gpa, ++ &elf.mf, ++ @field(Symbol.Index, @tagName(section)).node(elf), ++ key, ++ ); ++} ++ ++pub fn addReloc( ++ elf: *Elf, ++ loc_si: Symbol.Index, ++ offset: u64, ++ target_si: Symbol.Index, ++ addend: i64, ++ @"type": Reloc.Type, ++) !void { ++ const gpa = elf.base.comp.gpa; ++ const target = target_si.get(elf); ++ const ri: link.File.Elf2.Reloc.Index = @enumFromInt(elf.relocs.items.len); ++ (try elf.relocs.addOne(gpa)).* = .{ ++ .type = @"type", ++ .prev = .none, ++ .next = target.target_relocs, ++ .loc = loc_si, ++ .target = target_si, ++ .unused = 0, ++ .offset = offset, ++ .addend = addend, ++ }; ++ switch (target.target_relocs) { ++ .none => {}, ++ else => |target_ri| target_ri.get(elf).prev = ri, ++ } ++ target.target_relocs = ri; ++} ++ ++pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) void { ++ _ = elf; ++ _ = prog_node; ++} ++ ++pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { ++ elf.updateNavInner(pt, nav_index) catch |err| switch (err) { ++ error.OutOfMemory, ++ error.Overflow, ++ error.RelocationNotByteAligned, ++ => |e| return e, ++ else => |e| return elf.base.cgFail(nav_index, "linker failed to update variable: {t}", .{e}), ++ }; ++} ++fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { ++ const comp = elf.base.comp; ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ const ip = &zcu.intern_pool; ++ ++ const nav = ip.getNav(nav_index); ++ const nav_val = nav.status.fully_resolved.val; ++ const nav_init, const is_threadlocal = switch (ip.indexToKey(nav_val)) { ++ else => .{ nav_val, false }, ++ .variable => |variable| .{ variable.init, variable.is_threadlocal }, ++ .@"extern" => return, ++ .func => .{ .none, false }, ++ }; ++ if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return; ++ ++ const si = try elf.navSymbol(zcu, nav_index); ++ const ni = ni: { ++ const sym = si.get(elf); ++ switch (sym.ni) { ++ .none => { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const sec_si: Symbol.Index = ++ if (is_threadlocal and comp.config.any_non_single_threaded) .tdata else .data; ++ const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ ++ .alignment = pt.navAlignment(nav_index).toStdMem(), ++ .moved = true, ++ }); ++ elf.nodes.appendAssumeCapacity(.{ .nav = nav_index }); ++ sym.ni = ni; ++ switch (elf.symPtr(si)) { ++ inline else => |sym_ptr, class| sym_ptr.shndx = ++ @field(elf.symPtr(sec_si), @tagName(class)).shndx, ++ } ++ }, ++ else => si.deleteLocationRelocs(elf), ++ } ++ assert(sym.loc_relocs == .none); ++ sym.loc_relocs = @enumFromInt(elf.relocs.items.len); ++ break :ni sym.ni; ++ }; ++ ++ const size = size: { ++ var nw: MappedFile.Node.Writer = undefined; ++ ni.writer(&elf.mf, gpa, &nw); ++ defer nw.deinit(); ++ codegen.generateSymbol( ++ &elf.base, ++ pt, ++ zcu.navSrcLoc(nav_index), ++ .fromInterned(nav_init), ++ &nw.interface, ++ .{ .atom_index = @intFromEnum(si) }, ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ break :size nw.interface.end; ++ }; ++ ++ const target_endian = elf.endian(); ++ switch (elf.symPtr(si)) { ++ inline else => |sym| sym.size = ++ std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian), ++ } ++ si.applyLocationRelocs(elf); ++} ++ ++pub fn lowerUav( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ uav_val: InternPool.Index, ++ uav_align: InternPool.Alignment, ++ src_loc: Zcu.LazySrcLoc, ++) !codegen.SymbolResult { ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ ++ try elf.pending_uavs.ensureUnusedCapacity(gpa, 1); ++ const si = elf.uavSymbol(uav_val) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ else => |e| return .{ .fail = try Zcu.ErrorMsg.create( ++ gpa, ++ src_loc, ++ "linker failed to update constant: {s}", ++ .{@errorName(e)}, ++ ) }, ++ }; ++ if (switch (si.get(elf).ni) { ++ .none => true, ++ else => |ni| uav_align.toStdMem().order(ni.alignment(&elf.mf)).compare(.gt), ++ }) { ++ const gop = elf.pending_uavs.getOrPutAssumeCapacity(uav_val); ++ if (gop.found_existing) { ++ gop.value_ptr.alignment = gop.value_ptr.alignment.max(uav_align); ++ } else { ++ gop.value_ptr.* = .{ ++ .alignment = uav_align, ++ .src_loc = src_loc, ++ }; ++ elf.base.comp.link_uav_prog_node.increaseEstimatedTotalItems(1); ++ } ++ } ++ return .{ .sym_index = @intFromEnum(si) }; ++} ++ ++pub fn updateFunc( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ func_index: InternPool.Index, ++ mir: *const codegen.AnyMir, ++) !void { ++ elf.updateFuncInner(pt, func_index, mir) catch |err| switch (err) { ++ error.OutOfMemory, ++ error.Overflow, ++ error.RelocationNotByteAligned, ++ error.CodegenFail, ++ => |e| return e, ++ else => |e| return elf.base.cgFail( ++ pt.zcu.funcInfo(func_index).owner_nav, ++ "linker failed to update function: {s}", ++ .{@errorName(e)}, ++ ), ++ }; ++} ++fn updateFuncInner( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ func_index: InternPool.Index, ++ mir: *const codegen.AnyMir, ++) !void { ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ const ip = &zcu.intern_pool; ++ const func = zcu.funcInfo(func_index); ++ const nav = ip.getNav(func.owner_nav); ++ ++ const si = try elf.navSymbol(zcu, func.owner_nav); ++ log.debug("updateFunc({f}) = {d}", .{ nav.fqn.fmt(ip), si }); ++ const ni = ni: { ++ const sym = si.get(elf); ++ switch (sym.ni) { ++ .none => { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const mod = zcu.navFileScope(func.owner_nav).mod.?; ++ const target = &mod.resolved_target.result; ++ const ni = try elf.mf.addLastChildNode(gpa, Symbol.Index.text.node(elf), .{ ++ .alignment = switch (nav.status.fully_resolved.alignment) { ++ .none => switch (mod.optimize_mode) { ++ .Debug, ++ .ReleaseSafe, ++ .ReleaseFast, ++ => target_util.defaultFunctionAlignment(target), ++ .ReleaseSmall => target_util.minFunctionAlignment(target), ++ }, ++ else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), ++ }.toStdMem(), ++ .moved = true, ++ }); ++ elf.nodes.appendAssumeCapacity(.{ .nav = func.owner_nav }); ++ sym.ni = ni; ++ switch (elf.symPtr(si)) { ++ inline else => |sym_ptr, class| sym_ptr.shndx = ++ @field(elf.symPtr(.text), @tagName(class)).shndx, ++ } ++ }, ++ else => si.deleteLocationRelocs(elf), ++ } ++ assert(sym.loc_relocs == .none); ++ sym.loc_relocs = @enumFromInt(elf.relocs.items.len); ++ break :ni sym.ni; ++ }; ++ ++ const size = size: { ++ var nw: MappedFile.Node.Writer = undefined; ++ ni.writer(&elf.mf, gpa, &nw); ++ defer nw.deinit(); ++ codegen.emitFunction( ++ &elf.base, ++ pt, ++ zcu.navSrcLoc(func.owner_nav), ++ func_index, ++ @intFromEnum(si), ++ mir, ++ &nw.interface, ++ .none, ++ ) catch |err| switch (err) { ++ error.WriteFailed => return nw.err.?, ++ else => |e| return e, ++ }; ++ break :size nw.interface.end; ++ }; ++ ++ const target_endian = elf.endian(); ++ switch (elf.symPtr(si)) { ++ inline else => |sym| sym.size = ++ std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian), ++ } ++ si.applyLocationRelocs(elf); ++} ++ ++pub fn updateErrorData(elf: *Elf, pt: Zcu.PerThread) !void { ++ const si = elf.lazy.getPtr(.const_data).map.get(.anyerror_type) orelse return; ++ elf.flushLazy(pt, .{ .kind = .const_data, .ty = .anyerror_type }, si) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ error.CodegenFail => return error.LinkFailure, ++ else => |e| return elf.base.comp.link_diags.fail("updateErrorData failed {t}", .{e}), ++ }; ++} ++ ++pub fn flush( ++ elf: *Elf, ++ arena: std.mem.Allocator, ++ tid: Zcu.PerThread.Id, ++ prog_node: std.Progress.Node, ++) !void { ++ _ = arena; ++ _ = prog_node; ++ while (try elf.idle(tid)) {} ++} ++ ++pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool { ++ const comp = elf.base.comp; ++ task: { ++ while (elf.pending_uavs.pop()) |pending_uav| { ++ const sub_prog_node = ++ elf.idleProgNode( ++ tid, ++ comp.link_uav_prog_node, ++ .{ .uav = pending_uav.key }, ++ ); ++ defer sub_prog_node.end(); ++ break :task elf.flushUav( ++ .{ .zcu = elf.base.comp.zcu.?, .tid = tid }, ++ pending_uav.key, ++ pending_uav.value.alignment, ++ pending_uav.value.src_loc, ++ ) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ else => |e| return elf.base.comp.link_diags.fail( ++ "linker failed to lower constant: {t}", ++ .{e}, ++ ), ++ }; ++ } ++ var lazy_it = elf.lazy.iterator(); ++ while (lazy_it.next()) |lazy| for ( ++ lazy.value.map.keys()[lazy.value.pending_index..], ++ lazy.value.map.values()[lazy.value.pending_index..], ++ ) |ty, si| { ++ lazy.value.pending_index += 1; ++ const pt: Zcu.PerThread = .{ .zcu = elf.base.comp.zcu.?, .tid = tid }; ++ const kind = switch (lazy.key) { ++ .code => "code", ++ .const_data => "data", ++ }; ++ var name: [std.Progress.Node.max_name_len]u8 = undefined; ++ const sub_prog_node = comp.link_lazy_prog_node.start( ++ std.fmt.bufPrint(&name, "lazy {s} for {f}", .{ ++ kind, ++ Type.fromInterned(ty).fmt(pt), ++ }) catch &name, ++ 0, ++ ); ++ defer sub_prog_node.end(); ++ break :task elf.flushLazy(pt, .{ ++ .kind = lazy.key, ++ .ty = ty, ++ }, si) catch |err| switch (err) { ++ error.OutOfMemory => return error.OutOfMemory, ++ else => |e| return elf.base.comp.link_diags.fail( ++ "linker failed to lower lazy {s}: {t}", ++ .{ kind, e }, ++ ), ++ }; ++ }; ++ while (elf.mf.updates.pop()) |ni| { ++ const clean_moved = ni.cleanMoved(&elf.mf); ++ const clean_resized = ni.cleanResized(&elf.mf); ++ if (clean_moved or clean_resized) { ++ const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); ++ defer sub_prog_node.end(); ++ if (clean_moved) try elf.flushMoved(ni); ++ if (clean_resized) try elf.flushResized(ni); ++ break :task; ++ } else elf.mf.update_prog_node.completeOne(); ++ } ++ } ++ if (elf.pending_uavs.count() > 0) return true; ++ for (&elf.lazy.values) |lazy| if (lazy.map.count() > lazy.pending_index) return true; ++ if (elf.mf.updates.items.len > 0) return true; ++ return false; ++} ++ ++fn idleProgNode( ++ elf: *Elf, ++ tid: Zcu.PerThread.Id, ++ prog_node: std.Progress.Node, ++ node: Node, ++) std.Progress.Node { ++ var name: [std.Progress.Node.max_name_len]u8 = undefined; ++ return prog_node.start(name: switch (node) { ++ else => |tag| @tagName(tag), ++ .section => |si| elf.sectionName(si), ++ .nav => |nav| { ++ const ip = &elf.base.comp.zcu.?.intern_pool; ++ break :name ip.getNav(nav).fqn.toSlice(ip); ++ }, ++ .uav => |uav| std.fmt.bufPrint(&name, "{f}", .{ ++ Value.fromInterned(uav).fmtValue(.{ .zcu = elf.base.comp.zcu.?, .tid = tid }), ++ }) catch &name, ++ }, 0); ++} ++ ++fn flushUav( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ uav_val: InternPool.Index, ++ uav_align: InternPool.Alignment, ++ src_loc: Zcu.LazySrcLoc, ++) !void { ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ ++ const si = try elf.uavSymbol(uav_val); ++ const ni = ni: { ++ const sym = si.get(elf); ++ switch (sym.ni) { ++ .none => { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const ni = try elf.mf.addLastChildNode(gpa, Symbol.Index.data.node(elf), .{ ++ .alignment = uav_align.toStdMem(), ++ .moved = true, ++ }); ++ elf.nodes.appendAssumeCapacity(.{ .uav = uav_val }); ++ sym.ni = ni; ++ switch (elf.symPtr(si)) { ++ inline else => |sym_ptr, class| sym_ptr.shndx = ++ @field(elf.symPtr(.data), @tagName(class)).shndx, ++ } ++ }, ++ else => { ++ if (sym.ni.alignment(&elf.mf).order(uav_align.toStdMem()).compare(.gte)) return; ++ si.deleteLocationRelocs(elf); ++ }, ++ } ++ assert(sym.loc_relocs == .none); ++ sym.loc_relocs = @enumFromInt(elf.relocs.items.len); ++ break :ni sym.ni; ++ }; ++ ++ const size = size: { ++ var nw: MappedFile.Node.Writer = undefined; ++ ni.writer(&elf.mf, gpa, &nw); ++ defer nw.deinit(); ++ codegen.generateSymbol( ++ &elf.base, ++ pt, ++ src_loc, ++ .fromInterned(uav_val), ++ &nw.interface, ++ .{ .atom_index = @intFromEnum(si) }, ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ break :size nw.interface.end; ++ }; ++ ++ const target_endian = elf.endian(); ++ switch (elf.symPtr(si)) { ++ inline else => |sym| sym.size = ++ std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian), ++ } ++ si.applyLocationRelocs(elf); ++} ++ ++fn flushLazy(elf: *Elf, pt: Zcu.PerThread, lazy: link.File.LazySymbol, si: Symbol.Index) !void { ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ ++ const ni = ni: { ++ const sym = si.get(elf); ++ switch (sym.ni) { ++ .none => { ++ try elf.nodes.ensureUnusedCapacity(gpa, 1); ++ const sec_si: Symbol.Index = switch (lazy.kind) { ++ .code => .text, ++ .const_data => .rodata, ++ }; ++ const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ .moved = true }); ++ elf.nodes.appendAssumeCapacity(switch (lazy.kind) { ++ .code => .{ .lazy_code = lazy.ty }, ++ .const_data => .{ .lazy_const_data = lazy.ty }, ++ }); ++ sym.ni = ni; ++ switch (elf.symPtr(si)) { ++ inline else => |sym_ptr, class| sym_ptr.shndx = ++ @field(elf.symPtr(sec_si), @tagName(class)).shndx, ++ } ++ }, ++ else => si.deleteLocationRelocs(elf), ++ } ++ assert(sym.loc_relocs == .none); ++ sym.loc_relocs = @enumFromInt(elf.relocs.items.len); ++ break :ni sym.ni; ++ }; ++ ++ const size = size: { ++ var required_alignment: InternPool.Alignment = .none; ++ var nw: MappedFile.Node.Writer = undefined; ++ ni.writer(&elf.mf, gpa, &nw); ++ defer nw.deinit(); ++ try codegen.generateLazySymbol( ++ &elf.base, ++ pt, ++ Type.fromInterned(lazy.ty).srcLocOrNull(pt.zcu) orelse .unneeded, ++ lazy, ++ &required_alignment, ++ &nw.interface, ++ .none, ++ .{ .atom_index = @intFromEnum(si) }, ++ ); ++ break :size nw.interface.end; ++ }; ++ ++ const target_endian = elf.endian(); ++ switch (elf.symPtr(si)) { ++ inline else => |sym| sym.size = ++ std.mem.nativeTo(@TypeOf(sym.size), @intCast(size), target_endian), ++ } ++ si.applyLocationRelocs(elf); ++} ++ ++fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { ++ const target_endian = elf.endian(); ++ const file_offset = ni.fileLocation(&elf.mf, false).offset; ++ const node = elf.getNode(ni); ++ switch (node) { ++ else => |tag| @panic(@tagName(tag)), ++ .ehdr => assert(file_offset == 0), ++ .shdr => switch (elf.ehdrPtr()) { ++ inline else => |ehdr| ehdr.shoff = ++ std.mem.nativeTo(@TypeOf(ehdr.shoff), @intCast(file_offset), target_endian), ++ }, ++ .segment => |phndx| switch (elf.phdrSlice()) { ++ inline else => |phdr, class| { ++ const ph = &phdr[phndx]; ++ switch (std.mem.toNative(@TypeOf(ph.type), ph.type, target_endian)) { ++ else => unreachable, ++ std.elf.PT_NULL, std.elf.PT_LOAD, std.elf.PT_DYNAMIC, std.elf.PT_INTERP => {}, ++ std.elf.PT_PHDR => { ++ const ehdr = @field(elf.ehdrPtr(), @tagName(class)); ++ ehdr.phoff = ++ std.mem.nativeTo(@TypeOf(ehdr.phoff), @intCast(file_offset), target_endian); ++ }, ++ std.elf.PT_TLS => {}, ++ } ++ ph.offset = std.mem.nativeTo(@TypeOf(ph.offset), @intCast(file_offset), target_endian); ++ ph.vaddr = std.mem.nativeTo( ++ @TypeOf(ph.vaddr), ++ @intCast(elf.baseAddr() + file_offset), ++ target_endian, ++ ); ++ ph.paddr = ph.vaddr; ++ }, ++ }, ++ .section => |si| switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ const shndx = std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian); ++ const sh = &shdr[shndx]; ++ const flags: @TypeOf(sh.flags) = @bitCast(std.mem.toNative( ++ @typeInfo(@TypeOf(sh.flags)).@"struct".backing_integer.?, ++ @bitCast(sh.flags), ++ target_endian, ++ )); ++ if (flags.shf.ALLOC) { ++ sym.value = std.mem.nativeTo( ++ @TypeOf(sym.value), ++ @intCast(elf.baseAddr() + file_offset), ++ target_endian, ++ ); ++ sh.addr = sym.value; ++ } ++ sh.offset = std.mem.nativeTo(@TypeOf(sh.offset), @intCast(file_offset), target_endian); ++ }, ++ }, ++ .nav, .uav, .lazy_code, .lazy_const_data => { ++ const si = switch (node) { ++ else => unreachable, ++ .nav => |nav| elf.navs.get(nav), ++ .uav => |uav| elf.uavs.get(uav), ++ .lazy_code => |ty| elf.lazy.getPtr(.code).map.get(ty), ++ .lazy_const_data => |ty| elf.lazy.getPtr(.const_data).map.get(ty), ++ }.?; ++ switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ const sh = &shdr[std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian)]; ++ const flags: @TypeOf(sh.flags) = @bitCast(std.mem.toNative( ++ @typeInfo(@TypeOf(sh.flags)).@"struct".backing_integer.?, ++ @bitCast(sh.flags), ++ target_endian, ++ )); ++ const sh_addr = if (flags.shf.TLS) ++ 0 ++ else ++ std.mem.toNative(@TypeOf(sh.addr), sh.addr, target_endian); ++ const sh_offset = std.mem.toNative(@TypeOf(sh.offset), sh.offset, target_endian); ++ sym.value = std.mem.nativeTo( ++ @TypeOf(sym.value), ++ @intCast(file_offset - sh_offset + sh_addr), ++ target_endian, ++ ); ++ if (si == elf.entry_hack) @field(elf.ehdrPtr(), @tagName(class)).entry = sym.value; ++ }, ++ } ++ si.applyLocationRelocs(elf); ++ si.applyTargetRelocs(elf); ++ }, ++ } ++ try ni.childrenMoved(elf.base.comp.gpa, &elf.mf); ++} ++ ++fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { ++ const target_endian = elf.endian(); ++ _, const size = ni.location(&elf.mf).resolve(&elf.mf); ++ const node = elf.getNode(ni); ++ switch (node) { ++ else => |tag| @panic(@tagName(tag)), ++ .file, .shdr => {}, ++ .segment => |phndx| switch (elf.phdrSlice()) { ++ inline else => |phdr| { ++ const ph = &phdr[phndx]; ++ ph.filesz = std.mem.nativeTo(@TypeOf(ph.filesz), @intCast(size), target_endian); ++ ph.memsz = ph.filesz; ++ switch (std.mem.toNative(@TypeOf(ph.type), ph.type, target_endian)) { ++ else => unreachable, ++ std.elf.PT_NULL => { ++ if (size > 0) ph.type = std.mem.nativeTo( ++ @TypeOf(ph.type), ++ std.elf.PT_LOAD, ++ target_endian, ++ ); ++ }, ++ std.elf.PT_LOAD => { ++ if (size == 0) ph.type = std.mem.nativeTo( ++ @TypeOf(ph.type), ++ std.elf.PT_NULL, ++ target_endian, ++ ); ++ }, ++ std.elf.PT_DYNAMIC, std.elf.PT_INTERP, std.elf.PT_PHDR => {}, ++ std.elf.PT_TLS => try ni.childrenMoved(elf.base.comp.gpa, &elf.mf), ++ } ++ }, ++ }, ++ .section => |si| switch (elf.shdrSlice()) { ++ inline else => |shdr, class| { ++ const sym = @field(elf.symPtr(si), @tagName(class)); ++ const shndx = std.mem.toNative(@TypeOf(sym.shndx), sym.shndx, target_endian); ++ const sh = &shdr[shndx]; ++ switch (std.mem.toNative(@TypeOf(sh.type), sh.type, target_endian)) { ++ else => unreachable, ++ std.elf.SHT_NULL => { ++ if (size > 0) sh.type = std.mem.nativeTo( ++ @TypeOf(sh.type), ++ std.elf.SHT_PROGBITS, ++ target_endian, ++ ); ++ }, ++ std.elf.SHT_PROGBITS => { ++ if (size == 0) sh.type = std.mem.nativeTo( ++ @TypeOf(sh.type), ++ std.elf.SHT_NULL, ++ target_endian, ++ ); ++ }, ++ std.elf.SHT_SYMTAB => sh.info = std.mem.nativeTo( ++ @TypeOf(sh.info), ++ @intCast(@divExact( ++ size, ++ std.mem.toNative(@TypeOf(sh.entsize), sh.entsize, target_endian), ++ )), ++ target_endian, ++ ), ++ std.elf.SHT_STRTAB => {}, ++ } ++ sh.size = std.mem.nativeTo(@TypeOf(sh.size), @intCast(size), target_endian); ++ }, ++ }, ++ .nav, .uav, .lazy_code, .lazy_const_data => {}, ++ } ++} ++ ++pub fn updateExports( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ exported: Zcu.Exported, ++ export_indices: []const Zcu.Export.Index, ++) !void { ++ return elf.updateExportsInner(pt, exported, export_indices) catch |err| switch (err) { ++ error.OutOfMemory => error.OutOfMemory, ++ error.LinkFailure => error.AnalysisFail, ++ else => |e| switch (elf.base.comp.link_diags.fail( ++ "linker failed to update exports: {t}", ++ .{e}, ++ )) { ++ error.LinkFailure => return error.AnalysisFail, ++ }, ++ }; ++} ++fn updateExportsInner( ++ elf: *Elf, ++ pt: Zcu.PerThread, ++ exported: Zcu.Exported, ++ export_indices: []const Zcu.Export.Index, ++) !void { ++ const zcu = pt.zcu; ++ const gpa = zcu.gpa; ++ const ip = &zcu.intern_pool; ++ ++ switch (exported) { ++ .nav => |nav| log.debug("updateExports({f})", .{ip.getNav(nav).fqn.fmt(ip)}), ++ .uav => |uav| log.debug("updateExports(@as({f}, {f}))", .{ ++ Type.fromInterned(ip.typeOf(uav)).fmt(pt), ++ Value.fromInterned(uav).fmtValue(pt), ++ }), ++ } ++ try elf.symtab.ensureUnusedCapacity(gpa, export_indices.len); ++ const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) { ++ .nav => |nav| .{ ++ try elf.navSymbol(zcu, nav), ++ navType(ip, ip.getNav(nav).status, elf.base.comp.config.any_non_single_threaded), ++ }, ++ .uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav( ++ pt, ++ uav, ++ Type.fromInterned(ip.typeOf(uav)).abiAlignment(zcu), ++ export_indices[0].ptr(zcu).src, ++ )) { ++ .sym_index => |si| si, ++ .fail => |em| { ++ defer em.destroy(gpa); ++ return elf.base.comp.link_diags.fail("{s}", .{em.msg}); ++ }, ++ }), .OBJECT }, ++ }; ++ while (try elf.idle(pt.tid)) {} ++ const exported_ni = exported_si.node(elf); ++ const value, const size, const shndx = switch (elf.symPtr(exported_si)) { ++ inline else => |exported_sym| .{ exported_sym.value, exported_sym.size, exported_sym.shndx }, ++ }; ++ for (export_indices) |export_index| { ++ const @"export" = export_index.ptr(zcu); ++ const name = @"export".opts.name.toSlice(ip); ++ const export_si = try elf.globalSymbol(.{ ++ .name = name, ++ .type = @"type", ++ .bind = switch (@"export".opts.linkage) { ++ .internal => .LOCAL, ++ .strong => .GLOBAL, ++ .weak => .WEAK, ++ .link_once => return error.LinkOnceUnsupported, ++ }, ++ .visibility = switch (@"export".opts.visibility) { ++ .default => .DEFAULT, ++ .hidden => .HIDDEN, ++ .protected => .PROTECTED, ++ }, ++ }); ++ export_si.get(elf).ni = exported_ni; ++ switch (elf.symPtr(export_si)) { ++ inline else => |export_sym| { ++ export_sym.value = @intCast(value); ++ export_sym.size = @intCast(size); ++ export_sym.shndx = shndx; ++ }, ++ } ++ export_si.applyTargetRelocs(elf); ++ if (std.mem.eql(u8, name, "_start")) { ++ elf.entry_hack = exported_si; ++ switch (elf.ehdrPtr()) { ++ inline else => |ehdr| ehdr.entry = @intCast(value), ++ } ++ } ++ } ++} ++ ++pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerminatedString) void { ++ _ = elf; ++ _ = exported; ++ _ = name; ++} ++ ++pub fn dump(elf: *Elf, tid: Zcu.PerThread.Id) void { ++ const w = std.debug.lockStderrWriter(&.{}); ++ defer std.debug.unlockStderrWriter(); ++ elf.printNode(tid, w, .root, 0) catch {}; ++} ++ ++pub fn printNode( ++ elf: *Elf, ++ tid: Zcu.PerThread.Id, ++ w: *std.Io.Writer, ++ ni: MappedFile.Node.Index, ++ indent: usize, ++) !void { ++ const node = elf.getNode(ni); ++ const mf_node = &elf.mf.nodes.items[@intFromEnum(ni)]; ++ const off, const size = mf_node.location().resolve(&elf.mf); ++ try w.splatByteAll(' ', indent); ++ try w.writeAll(@tagName(node)); ++ switch (node) { ++ else => {}, ++ .section => |si| try w.print("({s})", .{elf.sectionName(si)}), ++ .nav => |nav_index| { ++ const zcu = elf.base.comp.zcu.?; ++ const ip = &zcu.intern_pool; ++ const nav = ip.getNav(nav_index); ++ try w.print("({f}, {f})", .{ ++ Type.fromInterned(nav.typeOf(ip)).fmt(.{ .zcu = zcu, .tid = tid }), ++ nav.fqn.fmt(ip), ++ }); ++ }, ++ .uav => |uav| { ++ const zcu = elf.base.comp.zcu.?; ++ const val: Value = .fromInterned(uav); ++ try w.print("({f}, {f})", .{ ++ val.typeOf(zcu).fmt(.{ .zcu = zcu, .tid = tid }), ++ val.fmtValue(.{ .zcu = zcu, .tid = tid }), ++ }); ++ }, ++ } ++ try w.print(" index={d} offset=0x{x} size=0x{x} align=0x{x}{s}{s}{s}{s}\n", .{ ++ @intFromEnum(ni), ++ off, ++ size, ++ mf_node.flags.alignment.toByteUnits(), ++ if (mf_node.flags.fixed) " fixed" else "", ++ if (mf_node.flags.moved) " moved" else "", ++ if (mf_node.flags.resized) " resized" else "", ++ if (mf_node.flags.has_content) " has_content" else "", ++ }); ++ var child_ni = mf_node.first; ++ switch (child_ni) { ++ .none => { ++ const file_loc = ni.fileLocation(&elf.mf, false); ++ if (file_loc.size == 0) return; ++ var address = file_loc.offset; ++ const line_len = 0x10; ++ var line_it = std.mem.window( ++ u8, ++ elf.mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)], ++ line_len, ++ line_len, ++ ); ++ while (line_it.next()) |line_bytes| : (address += line_len) { ++ try w.splatByteAll(' ', indent + 1); ++ try w.print("{x:0>8}", .{address}); ++ for (line_bytes) |byte| try w.print(" {x:0>2}", .{byte}); ++ try w.writeByte('\n'); ++ } ++ }, ++ else => while (child_ni != .none) { ++ try elf.printNode(tid, w, child_ni, indent + 1); ++ child_ni = elf.mf.nodes.items[@intFromEnum(child_ni)].next; ++ }, ++ } ++} ++ ++const assert = std.debug.assert; ++const builtin = @import("builtin"); ++const codegen = @import("../codegen.zig"); ++const Compilation = @import("../Compilation.zig"); ++const Elf = @This(); ++const InternPool = @import("../InternPool.zig"); ++const link = @import("../link.zig"); ++const log = std.log.scoped(.link); ++const MappedFile = @import("MappedFile.zig"); ++const native_endian = builtin.cpu.arch.endian(); ++const std = @import("std"); ++const target_util = @import("../target.zig"); ++const Type = @import("../Type.zig"); ++const Value = @import("../Value.zig"); ++const Zcu = @import("../Zcu.zig"); +diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig +index b1fc6528d5..5a0a71f380 100644 +--- a/src/link/MachO/ZigObject.zig ++++ b/src/link/MachO/ZigObject.zig +@@ -784,22 +784,26 @@ pub fn updateFunc( + const sym_index = try self.getOrCreateMetadataForNav(macho_file, func.owner_nav); + self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file); + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null; + defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit(); + +- try codegen.emitFunction( ++ codegen.emitFunction( + &macho_file.base, + pt, + zcu.navSrcLoc(func.owner_nav), + func_index, ++ sym_index, + mir, +- &code_buffer, ++ &aw.writer, + if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const sect_index = try self.getNavOutputSection(macho_file, zcu, func.owner_nav, code); + const old_rva, const old_alignment = blk: { +@@ -895,21 +899,24 @@ pub fn updateNav( + const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index); + self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file); + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(zcu.gpa); ++ var aw: std.Io.Writer.Allocating = .init(zcu.gpa); ++ defer aw.deinit(); + + var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, nav_index, sym_index) else null; + defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit(); + +- try codegen.generateSymbol( ++ codegen.generateSymbol( + &macho_file.base, + pt, + zcu.navSrcLoc(nav_index), + Value.fromInterned(nav_init), +- &code_buffer, ++ &aw.writer, + .{ .atom_index = sym_index }, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const sect_index = try self.getNavOutputSection(macho_file, zcu, nav_index, code); + if (isThreadlocal(macho_file, nav_index)) +@@ -1198,21 +1205,24 @@ fn lowerConst( + ) !codegen.SymbolResult { + const gpa = macho_file.base.comp.gpa; + +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const name_str = try self.addString(gpa, name); + const sym_index = try self.newSymbolWithAtom(gpa, name_str, macho_file); + +- try codegen.generateSymbol( ++ codegen.generateSymbol( + &macho_file.base, + pt, + src_loc, + val, +- &code_buffer, ++ &aw.writer, + .{ .atom_index = sym_index }, +- ); +- const code = code_buffer.items; ++ ) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ const code = aw.written(); + + const sym = &self.symbols.items[sym_index]; + sym.out_n_sect = output_section_index; +@@ -1349,8 +1359,8 @@ fn updateLazySymbol( + const gpa = zcu.gpa; + + var required_alignment: Atom.Alignment = .none; +- var code_buffer: std.ArrayListUnmanaged(u8) = .empty; +- defer code_buffer.deinit(gpa); ++ var aw: std.Io.Writer.Allocating = .init(gpa); ++ defer aw.deinit(); + + const name_str = blk: { + const name = try std.fmt.allocPrint(gpa, "__lazy_{s}_{f}", .{ +@@ -1368,11 +1378,11 @@ fn updateLazySymbol( + src, + lazy_sym, + &required_alignment, +- &code_buffer, ++ &aw.writer, + .none, + .{ .atom_index = symbol_index }, + ); +- const code = code_buffer.items; ++ const code = aw.written(); + + const output_section_index = switch (lazy_sym.kind) { + .code => macho_file.zig_text_sect_index.?, +diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig +new file mode 100644 +index 0000000000..d04a8d533a +--- /dev/null ++++ b/src/link/MappedFile.zig +@@ -0,0 +1,929 @@ ++file: std.fs.File, ++flags: packed struct { ++ block_size: std.mem.Alignment, ++ copy_file_range_unsupported: bool, ++ fallocate_punch_hole_unsupported: bool, ++ fallocate_insert_range_unsupported: bool, ++}, ++section: if (is_windows) windows.HANDLE else void, ++contents: []align(std.heap.page_size_min) u8, ++nodes: std.ArrayList(Node), ++free_ni: Node.Index, ++large: std.ArrayList(u64), ++updates: std.ArrayList(Node.Index), ++update_prog_node: std.Progress.Node, ++writers: std.SinglyLinkedList, ++ ++pub const Error = std.posix.MMapError || ++ std.posix.MRemapError || ++ std.fs.File.SetEndPosError || ++ std.fs.File.CopyRangeError || ++ error{NotFile}; ++ ++pub fn init(file: std.fs.File, gpa: std.mem.Allocator) !MappedFile { ++ var mf: MappedFile = .{ ++ .file = file, ++ .flags = undefined, ++ .section = if (is_windows) windows.INVALID_HANDLE_VALUE else {}, ++ .contents = &.{}, ++ .nodes = .empty, ++ .free_ni = .none, ++ .large = .empty, ++ .updates = .empty, ++ .update_prog_node = .none, ++ .writers = .{}, ++ }; ++ errdefer mf.deinit(gpa); ++ const size: u64, const blksize = if (is_windows) ++ .{ try windows.GetFileSizeEx(file.handle), 1 } ++ else stat: { ++ const stat = try std.posix.fstat(mf.file.handle); ++ if (!std.posix.S.ISREG(stat.mode)) return error.PathAlreadyExists; ++ break :stat .{ @bitCast(stat.size), stat.blksize }; ++ }; ++ mf.flags = .{ ++ .block_size = .fromByteUnits( ++ std.math.ceilPowerOfTwoAssert(usize, @max(std.heap.pageSize(), blksize)), ++ ), ++ .copy_file_range_unsupported = false, ++ .fallocate_insert_range_unsupported = false, ++ .fallocate_punch_hole_unsupported = false, ++ }; ++ try mf.nodes.ensureUnusedCapacity(gpa, 1); ++ assert(try mf.addNode(gpa, .{ ++ .add_node = .{ ++ .size = size, ++ .fixed = true, ++ }, ++ }) == Node.Index.root); ++ try mf.ensureTotalCapacity(@intCast(size)); ++ return mf; ++} ++ ++pub fn deinit(mf: *MappedFile, gpa: std.mem.Allocator) void { ++ mf.unmap(); ++ mf.nodes.deinit(gpa); ++ mf.large.deinit(gpa); ++ mf.updates.deinit(gpa); ++ mf.update_prog_node.end(); ++ assert(mf.writers.first == null); ++ mf.* = undefined; ++} ++ ++pub const Node = extern struct { ++ parent: Node.Index, ++ prev: Node.Index, ++ next: Node.Index, ++ first: Node.Index, ++ last: Node.Index, ++ flags: Flags, ++ location_payload: Location.Payload, ++ ++ pub const Flags = packed struct(u32) { ++ location_tag: Location.Tag, ++ alignment: std.mem.Alignment, ++ /// Whether this node can be moved. ++ fixed: bool, ++ /// Whether this node has been moved. ++ moved: bool, ++ /// Whether this node has been resized. ++ resized: bool, ++ /// Whether this node might contain non-zero bytes. ++ has_content: bool, ++ unused: @Type(.{ .int = .{ ++ .signedness = .unsigned, ++ .bits = 32 - @bitSizeOf(std.mem.Alignment) - 5, ++ } }) = 0, ++ }; ++ ++ pub const Location = union(enum(u1)) { ++ small: extern struct { ++ /// Relative to `parent`. ++ offset: u32, ++ size: u32, ++ }, ++ large: extern struct { ++ index: usize, ++ unused: @Type(.{ .int = .{ ++ .signedness = .unsigned, ++ .bits = 64 - @bitSizeOf(usize), ++ } }) = 0, ++ }, ++ ++ pub const Tag = @typeInfo(Location).@"union".tag_type.?; ++ pub const Payload = @Type(.{ .@"union" = .{ ++ .layout = .@"extern", ++ .tag_type = null, ++ .fields = @typeInfo(Location).@"union".fields, ++ .decls = &.{}, ++ } }); ++ ++ pub fn resolve(loc: Location, mf: *const MappedFile) [2]u64 { ++ return switch (loc) { ++ .small => |small| .{ small.offset, small.size }, ++ .large => |large| mf.large.items[large.index..][0..2].*, ++ }; ++ } ++ }; ++ ++ pub const Index = enum(u32) { ++ none, ++ _, ++ ++ pub const root: Node.Index = .none; ++ ++ fn get(ni: Node.Index, mf: *const MappedFile) *Node { ++ return &mf.nodes.items[@intFromEnum(ni)]; ++ } ++ ++ pub fn childrenMoved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void { ++ var child_ni = ni.get(mf).last; ++ while (child_ni != .none) { ++ try child_ni.moved(gpa, mf); ++ child_ni = child_ni.get(mf).prev; ++ } ++ } ++ ++ pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool { ++ var parent_ni = ni; ++ while (parent_ni != .none) { ++ const parent = parent_ni.get(mf); ++ if (parent.flags.moved) return true; ++ parent_ni = parent.parent; ++ } ++ return false; ++ } ++ pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void { ++ try mf.updates.ensureUnusedCapacity(gpa, 1); ++ ni.movedAssumeCapacity(mf); ++ } ++ pub fn cleanMoved(ni: Node.Index, mf: *const MappedFile) bool { ++ const node_moved = &ni.get(mf).flags.moved; ++ defer node_moved.* = false; ++ return node_moved.*; ++ } ++ fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { ++ var parent_ni = ni; ++ while (parent_ni != .none) { ++ const parent_node = parent_ni.get(mf); ++ if (parent_node.flags.moved) return; ++ parent_ni = parent_node.parent; ++ } ++ const node = ni.get(mf); ++ node.flags.moved = true; ++ if (node.flags.resized) return; ++ mf.updates.appendAssumeCapacity(ni); ++ mf.update_prog_node.increaseEstimatedTotalItems(1); ++ } ++ ++ pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool { ++ return ni.get(mf).flags.resized; ++ } ++ pub fn resized(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) !void { ++ try mf.updates.ensureUnusedCapacity(gpa, 1); ++ ni.resizedAssumeCapacity(mf); ++ } ++ pub fn cleanResized(ni: Node.Index, mf: *const MappedFile) bool { ++ const node_resized = &ni.get(mf).flags.resized; ++ defer node_resized.* = false; ++ return node_resized.*; ++ } ++ fn resizedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { ++ const node = ni.get(mf); ++ if (node.flags.resized) return; ++ node.flags.resized = true; ++ if (node.flags.moved) return; ++ mf.updates.appendAssumeCapacity(ni); ++ mf.update_prog_node.increaseEstimatedTotalItems(1); ++ } ++ ++ pub fn alignment(ni: Node.Index, mf: *const MappedFile) std.mem.Alignment { ++ return ni.get(mf).flags.alignment; ++ } ++ ++ fn setLocationAssumeCapacity(ni: Node.Index, mf: *MappedFile, offset: u64, size: u64) void { ++ const node = ni.get(mf); ++ if (size == 0) node.flags.has_content = false; ++ switch (node.location()) { ++ .small => |small| { ++ if (small.offset != offset) ni.movedAssumeCapacity(mf); ++ if (small.size != size) ni.resizedAssumeCapacity(mf); ++ if (std.math.cast(u32, offset)) |small_offset| { ++ if (std.math.cast(u32, size)) |small_size| { ++ node.location_payload.small = .{ ++ .offset = small_offset, ++ .size = small_size, ++ }; ++ return; ++ } ++ } ++ defer mf.large.appendSliceAssumeCapacity(&.{ offset, size }); ++ node.flags.location_tag = .large; ++ node.location_payload = .{ .large = .{ .index = mf.large.items.len } }; ++ }, ++ .large => |large| { ++ const large_items = mf.large.items[large.index..][0..2]; ++ if (large_items[0] != offset) ni.movedAssumeCapacity(mf); ++ if (large_items[1] != size) ni.resizedAssumeCapacity(mf); ++ large_items.* = .{ offset, size }; ++ }, ++ } ++ } ++ ++ pub fn location(ni: Node.Index, mf: *const MappedFile) Location { ++ return ni.get(mf).location(); ++ } ++ ++ pub fn fileLocation( ++ ni: Node.Index, ++ mf: *const MappedFile, ++ set_has_content: bool, ++ ) struct { offset: u64, size: u64 } { ++ var offset, const size = ni.location(mf).resolve(mf); ++ var parent_ni = ni; ++ while (true) { ++ const parent = parent_ni.get(mf); ++ if (set_has_content) parent.flags.has_content = true; ++ if (parent_ni == .none) break; ++ parent_ni = parent.parent; ++ offset += parent_ni.location(mf).resolve(mf)[0]; ++ } ++ return .{ .offset = offset, .size = size }; ++ } ++ ++ pub fn slice(ni: Node.Index, mf: *const MappedFile) []u8 { ++ const file_loc = ni.fileLocation(mf, true); ++ return mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; ++ } ++ ++ pub fn sliceConst(ni: Node.Index, mf: *const MappedFile) []const u8 { ++ const file_loc = ni.fileLocation(mf, false); ++ return mf.contents[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; ++ } ++ ++ pub fn resize(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, size: u64) !void { ++ try mf.resizeNode(gpa, ni, size); ++ var writers_it = mf.writers.first; ++ while (writers_it) |writer_node| : (writers_it = writer_node.next) { ++ const w: *Node.Writer = @fieldParentPtr("writer_node", writer_node); ++ w.interface.buffer = w.ni.slice(mf); ++ } ++ } ++ ++ pub fn writer(ni: Node.Index, mf: *MappedFile, gpa: std.mem.Allocator, w: *Writer) void { ++ w.* = .{ ++ .gpa = gpa, ++ .mf = mf, ++ .writer_node = .{}, ++ .ni = ni, ++ .interface = .{ ++ .buffer = ni.slice(mf), ++ .vtable = &Writer.vtable, ++ }, ++ .err = null, ++ }; ++ mf.writers.prepend(&w.writer_node); ++ } ++ }; ++ ++ pub fn location(node: *const Node) Location { ++ return switch (node.flags.location_tag) { ++ inline else => |tag| @unionInit( ++ Location, ++ @tagName(tag), ++ @field(node.location_payload, @tagName(tag)), ++ ), ++ }; ++ } ++ ++ pub const Writer = struct { ++ gpa: std.mem.Allocator, ++ mf: *MappedFile, ++ writer_node: std.SinglyLinkedList.Node, ++ ni: Node.Index, ++ interface: std.Io.Writer, ++ err: ?Error, ++ ++ pub fn deinit(w: *Writer) void { ++ assert(w.mf.writers.popFirst() == &w.writer_node); ++ w.* = undefined; ++ } ++ ++ const vtable: std.Io.Writer.VTable = .{ ++ .drain = drain, ++ .sendFile = sendFile, ++ .flush = std.Io.Writer.noopFlush, ++ .rebase = growingRebase, ++ }; ++ ++ fn drain( ++ interface: *std.Io.Writer, ++ data: []const []const u8, ++ splat: usize, ++ ) std.Io.Writer.Error!usize { ++ const pattern = data[data.len - 1]; ++ const splat_len = pattern.len * splat; ++ const start_len = interface.end; ++ assert(data.len != 0); ++ for (data) |bytes| { ++ try growingRebase(interface, interface.end, bytes.len + splat_len + 1); ++ @memcpy(interface.buffer[interface.end..][0..bytes.len], bytes); ++ interface.end += bytes.len; ++ } ++ if (splat == 0) { ++ interface.end -= pattern.len; ++ } else switch (pattern.len) { ++ 0 => {}, ++ 1 => { ++ @memset(interface.buffer[interface.end..][0 .. splat - 1], pattern[0]); ++ interface.end += splat - 1; ++ }, ++ else => for (0..splat - 1) |_| { ++ @memcpy(interface.buffer[interface.end..][0..pattern.len], pattern); ++ interface.end += pattern.len; ++ }, ++ } ++ return interface.end - start_len; ++ } ++ ++ fn sendFile( ++ interface: *std.Io.Writer, ++ file_reader: *std.fs.File.Reader, ++ limit: std.Io.Limit, ++ ) std.Io.Writer.FileError!usize { ++ if (limit == .nothing) return 0; ++ const pos = file_reader.logicalPos(); ++ const additional = if (file_reader.getSize()) |size| size - pos else |_| std.atomic.cache_line; ++ if (additional == 0) return error.EndOfStream; ++ try growingRebase(interface, interface.end, limit.minInt64(additional)); ++ switch (file_reader.mode) { ++ .positional => { ++ const fr_buf = file_reader.interface.buffered(); ++ const buf_copy_size = interface.write(fr_buf) catch unreachable; ++ file_reader.interface.toss(buf_copy_size); ++ if (buf_copy_size < fr_buf.len) return buf_copy_size; ++ assert(file_reader.logicalPos() == file_reader.pos); ++ ++ const w: *Writer = @fieldParentPtr("interface", interface); ++ const copy_size: usize = @intCast(w.mf.copyFileRange( ++ file_reader.file, ++ file_reader.pos, ++ w.ni.fileLocation(w.mf, true).offset + interface.end, ++ limit.minInt(interface.unusedCapacityLen()), ++ ) catch |err| { ++ w.err = err; ++ return error.WriteFailed; ++ }); ++ interface.end += copy_size; ++ return copy_size; ++ }, ++ .streaming, ++ .streaming_reading, ++ .positional_reading, ++ .failure, ++ => { ++ const dest = limit.slice(interface.unusedCapacitySlice()); ++ const n = try file_reader.read(dest); ++ interface.end += n; ++ return n; ++ }, ++ } ++ } ++ ++ fn growingRebase( ++ interface: *std.Io.Writer, ++ preserve: usize, ++ unused_capacity: usize, ++ ) std.Io.Writer.Error!void { ++ _ = preserve; ++ const total_capacity = interface.end + unused_capacity; ++ if (interface.buffer.len >= total_capacity) return; ++ const w: *Writer = @fieldParentPtr("interface", interface); ++ w.ni.resize(w.mf, w.gpa, total_capacity +| total_capacity / 2) catch |err| { ++ w.err = err; ++ return error.WriteFailed; ++ }; ++ } ++ }; ++ ++ comptime { ++ if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Node) == 32); ++ } ++}; ++ ++fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { ++ parent: Node.Index = .none, ++ prev: Node.Index = .none, ++ next: Node.Index = .none, ++ offset: u64 = 0, ++ add_node: AddNodeOptions, ++}) !Node.Index { ++ if (opts.add_node.moved or opts.add_node.resized) try mf.updates.ensureUnusedCapacity(gpa, 1); ++ const offset = opts.add_node.alignment.forward(@intCast(opts.offset)); ++ const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: { ++ if (std.math.cast(u32, offset)) |small_offset| break :location .{ .small, .{ ++ .small = .{ .offset = small_offset, .size = 0 }, ++ } }; ++ try mf.large.ensureUnusedCapacity(gpa, 2); ++ defer mf.large.appendSliceAssumeCapacity(&.{ offset, 0 }); ++ break :location .{ .large, .{ .large = .{ .index = mf.large.items.len } } }; ++ }; ++ const free_ni: Node.Index, const free_node = free: switch (mf.free_ni) { ++ .none => .{ @enumFromInt(mf.nodes.items.len), mf.nodes.addOneAssumeCapacity() }, ++ else => |free_ni| { ++ const free_node = free_ni.get(mf); ++ mf.free_ni = free_node.next; ++ break :free .{ free_ni, free_node }; ++ }, ++ }; ++ free_node.* = .{ ++ .parent = opts.parent, ++ .prev = opts.prev, ++ .next = opts.next, ++ .first = .none, ++ .last = .none, ++ .flags = .{ ++ .location_tag = location_tag, ++ .alignment = opts.add_node.alignment, ++ .fixed = opts.add_node.fixed, ++ .moved = true, ++ .resized = true, ++ .has_content = false, ++ }, ++ .location_payload = location_payload, ++ }; ++ { ++ defer { ++ free_node.flags.moved = false; ++ free_node.flags.resized = false; ++ } ++ if (offset > opts.parent.location(mf).resolve(mf)[1]) try opts.parent.resize(mf, gpa, offset); ++ try free_ni.resize(mf, gpa, opts.add_node.size); ++ } ++ if (opts.add_node.moved) free_ni.movedAssumeCapacity(mf); ++ if (opts.add_node.resized) free_ni.resizedAssumeCapacity(mf); ++ return free_ni; ++} ++ ++pub const AddNodeOptions = struct { ++ size: u64 = 0, ++ alignment: std.mem.Alignment = .@"1", ++ fixed: bool = false, ++ moved: bool = false, ++ resized: bool = false, ++}; ++ ++pub fn addOnlyChildNode( ++ mf: *MappedFile, ++ gpa: std.mem.Allocator, ++ parent_ni: Node.Index, ++ opts: AddNodeOptions, ++) !Node.Index { ++ try mf.nodes.ensureUnusedCapacity(gpa, 1); ++ const parent = parent_ni.get(mf); ++ assert(parent.first == .none and parent.last == .none); ++ const ni = try mf.addNode(gpa, .{ ++ .parent = parent_ni, ++ .add_node = opts, ++ }); ++ parent.first = ni; ++ parent.last = ni; ++ return ni; ++} ++ ++pub fn addLastChildNode( ++ mf: *MappedFile, ++ gpa: std.mem.Allocator, ++ parent_ni: Node.Index, ++ opts: AddNodeOptions, ++) !Node.Index { ++ try mf.nodes.ensureUnusedCapacity(gpa, 1); ++ const parent = parent_ni.get(mf); ++ const ni = try mf.addNode(gpa, .{ ++ .parent = parent_ni, ++ .prev = parent.last, ++ .offset = offset: switch (parent.last) { ++ .none => 0, ++ else => |last_ni| { ++ const last_offset, const last_size = last_ni.location(mf).resolve(mf); ++ break :offset last_offset + last_size; ++ }, ++ }, ++ .add_node = opts, ++ }); ++ switch (parent.last) { ++ .none => parent.first = ni, ++ else => |last_ni| last_ni.get(mf).next = ni, ++ } ++ parent.last = ni; ++ return ni; ++} ++ ++pub fn addNodeAfter( ++ mf: *MappedFile, ++ gpa: std.mem.Allocator, ++ prev_ni: Node.Index, ++ opts: AddNodeOptions, ++) !Node.Index { ++ assert(prev_ni != .none); ++ try mf.nodes.ensureUnusedCapacity(gpa, 1); ++ const prev = prev_ni.get(mf); ++ const prev_offset, const prev_size = prev.location().resolve(mf); ++ const ni = try mf.addNode(gpa, .{ ++ .parent = prev.parent, ++ .prev = prev_ni, ++ .next = prev.next, ++ .offset = prev_offset + prev_size, ++ .add_node = opts, ++ }); ++ switch (prev.next) { ++ .none => prev.parent.get(mf).last = ni, ++ else => |next_ni| next_ni.get(mf).prev = ni, ++ } ++ prev.next = ni; ++ return ni; ++} ++ ++fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void { ++ const node = ni.get(mf); ++ var old_offset, const old_size = node.location().resolve(mf); ++ const new_size = node.flags.alignment.forward(@intCast(requested_size)); ++ // Resize the entire file ++ if (ni == Node.Index.root) { ++ try mf.file.setEndPos(new_size); ++ try mf.ensureTotalCapacity(@intCast(new_size)); ++ try mf.ensureCapacityForSetLocation(gpa); ++ ni.setLocationAssumeCapacity(mf, old_offset, new_size); ++ return; ++ } ++ while (true) { ++ const parent = node.parent.get(mf); ++ _, const old_parent_size = parent.location().resolve(mf); ++ const trailing_end = switch (node.next) { ++ .none => parent.location().resolve(mf)[1], ++ else => |next_ni| next_ni.location(mf).resolve(mf)[0], ++ }; ++ assert(old_offset + old_size <= trailing_end); ++ // Expand the node into available trailing free space ++ if (old_offset + new_size <= trailing_end) { ++ try mf.ensureCapacityForSetLocation(gpa); ++ ni.setLocationAssumeCapacity(mf, old_offset, new_size); ++ return; ++ } ++ // Ask the filesystem driver to insert an extent into the file without copying any data ++ if (is_linux and !mf.flags.fallocate_insert_range_unsupported and ++ node.flags.alignment.order(mf.flags.block_size).compare(.gte)) ++ insert_range: { ++ const last_offset, const last_size = parent.last.location(mf).resolve(mf); ++ const last_end = last_offset + last_size; ++ assert(last_end <= old_parent_size); ++ const range_size = ++ node.flags.alignment.forward(@intCast(requested_size +| requested_size / 2)) - old_size; ++ const new_parent_size = last_end + range_size; ++ if (new_parent_size > old_parent_size) { ++ try mf.resizeNode(gpa, node.parent, new_parent_size +| new_parent_size / 2); ++ continue; ++ } ++ const range_file_offset = ni.fileLocation(mf, false).offset + old_size; ++ retry: while (true) { ++ switch (linux.E.init(linux.fallocate( ++ mf.file.handle, ++ linux.FALLOC.FL_INSERT_RANGE, ++ @intCast(range_file_offset), ++ @intCast(range_size), ++ ))) { ++ .SUCCESS => { ++ var enclosing_ni = ni; ++ while (enclosing_ni != .none) { ++ try mf.ensureCapacityForSetLocation(gpa); ++ const enclosing = enclosing_ni.get(mf); ++ const enclosing_offset, const enclosing_size = ++ enclosing.location().resolve(mf); ++ enclosing_ni.setLocationAssumeCapacity( ++ mf, ++ enclosing_offset, ++ enclosing_size + range_size, ++ ); ++ var after_ni = enclosing.next; ++ while (after_ni != .none) { ++ try mf.ensureCapacityForSetLocation(gpa); ++ const after = after_ni.get(mf); ++ const after_offset, const after_size = after.location().resolve(mf); ++ after_ni.setLocationAssumeCapacity( ++ mf, ++ range_size + after_offset, ++ after_size, ++ ); ++ after_ni = after.next; ++ } ++ enclosing_ni = enclosing.parent; ++ } ++ return; ++ }, ++ .INTR => continue :retry, ++ .BADF, .FBIG, .INVAL => unreachable, ++ .IO => return error.InputOutput, ++ .NODEV => return error.NotFile, ++ .NOSPC => return error.NoSpaceLeft, ++ .NOSYS, .OPNOTSUPP => { ++ mf.flags.fallocate_insert_range_unsupported = true; ++ break :insert_range; ++ }, ++ .PERM => return error.PermissionDenied, ++ .SPIPE => return error.Unseekable, ++ .TXTBSY => return error.FileBusy, ++ else => |e| return std.posix.unexpectedErrno(e), ++ } ++ } ++ } ++ switch (node.next) { ++ .none => { ++ // As this is the last node, we simply need more space in the parent ++ const new_parent_size = old_offset + new_size; ++ try mf.resizeNode(gpa, node.parent, new_parent_size +| new_parent_size / 2); ++ }, ++ else => |*next_ni_ptr| switch (node.flags.fixed) { ++ false => { ++ // Make space at the end of the parent for this floating node ++ const last = parent.last.get(mf); ++ const last_offset, const last_size = last.location().resolve(mf); ++ const new_offset = node.flags.alignment.forward(@intCast(last_offset + last_size)); ++ const new_parent_size = new_offset + new_size; ++ if (new_parent_size > old_parent_size) { ++ try mf.resizeNode( ++ gpa, ++ node.parent, ++ new_parent_size +| new_parent_size / 2, ++ ); ++ continue; ++ } ++ const next_ni = next_ni_ptr.*; ++ next_ni.get(mf).prev = node.prev; ++ switch (node.prev) { ++ .none => parent.first = next_ni, ++ else => |prev_ni| prev_ni.get(mf).next = next_ni, ++ } ++ last.next = ni; ++ node.prev = parent.last; ++ next_ni_ptr.* = .none; ++ parent.last = ni; ++ if (node.flags.has_content) { ++ const parent_file_offset = node.parent.fileLocation(mf, false).offset; ++ try mf.moveRange( ++ parent_file_offset + old_offset, ++ parent_file_offset + new_offset, ++ old_size, ++ ); ++ } ++ old_offset = new_offset; ++ }, ++ true => { ++ // Move the next floating node to make space for this fixed node ++ const next_ni = next_ni_ptr.*; ++ const next = next_ni.get(mf); ++ assert(!next.flags.fixed); ++ const next_offset, const next_size = next.location().resolve(mf); ++ const last = parent.last.get(mf); ++ const last_offset, const last_size = last.location().resolve(mf); ++ const new_offset = next.flags.alignment.forward(@intCast( ++ @max(old_offset + new_size, last_offset + last_size), ++ )); ++ const new_parent_size = new_offset + next_size; ++ if (new_parent_size > old_parent_size) { ++ try mf.resizeNode( ++ gpa, ++ node.parent, ++ new_parent_size +| new_parent_size / 2, ++ ); ++ continue; ++ } ++ try mf.ensureCapacityForSetLocation(gpa); ++ next.prev = parent.last; ++ parent.last = next_ni; ++ last.next = next_ni; ++ next_ni_ptr.* = next.next; ++ switch (next.next) { ++ .none => {}, ++ else => |next_next_ni| next_next_ni.get(mf).prev = ni, ++ } ++ next.next = .none; ++ if (node.flags.has_content) { ++ const parent_file_offset = node.parent.fileLocation(mf, false).offset; ++ try mf.moveRange( ++ parent_file_offset + next_offset, ++ parent_file_offset + new_offset, ++ next_size, ++ ); ++ } ++ next_ni.setLocationAssumeCapacity(mf, new_offset, next_size); ++ }, ++ }, ++ } ++ } ++} ++ ++fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void { ++ // make a copy of this node at the new location ++ try mf.copyRange(old_file_offset, new_file_offset, size); ++ // delete the copy of this node at the old location ++ if (is_linux and !mf.flags.fallocate_punch_hole_unsupported and ++ size >= mf.flags.block_size.toByteUnits() * 2 - 1) while (true) ++ { ++ switch (linux.E.init(linux.fallocate( ++ mf.file.handle, ++ linux.FALLOC.FL_PUNCH_HOLE | linux.FALLOC.FL_KEEP_SIZE, ++ @intCast(old_file_offset), ++ @intCast(size), ++ ))) { ++ .SUCCESS => return, ++ .INTR => continue, ++ .BADF, .FBIG, .INVAL => unreachable, ++ .IO => return error.InputOutput, ++ .NODEV => return error.NotFile, ++ .NOSPC => return error.NoSpaceLeft, ++ .NOSYS, .OPNOTSUPP => { ++ mf.flags.fallocate_punch_hole_unsupported = true; ++ break; ++ }, ++ .PERM => return error.PermissionDenied, ++ .SPIPE => return error.Unseekable, ++ .TXTBSY => return error.FileBusy, ++ else => |e| return std.posix.unexpectedErrno(e), ++ } ++ }; ++ @memset(mf.contents[@intCast(old_file_offset)..][0..@intCast(size)], 0); ++} ++ ++fn copyRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: u64) !void { ++ const copy_size = try mf.copyFileRange(mf.file, old_file_offset, new_file_offset, size); ++ if (copy_size < size) @memcpy( ++ mf.contents[@intCast(new_file_offset + copy_size)..][0..@intCast(size - copy_size)], ++ mf.contents[@intCast(old_file_offset + copy_size)..][0..@intCast(size - copy_size)], ++ ); ++} ++ ++fn copyFileRange( ++ mf: *MappedFile, ++ old_file: std.fs.File, ++ old_file_offset: u64, ++ new_file_offset: u64, ++ size: u64, ++) !u64 { ++ var remaining_size = size; ++ if (is_linux and !mf.flags.copy_file_range_unsupported) { ++ var old_file_offset_mut: i64 = @intCast(old_file_offset); ++ var new_file_offset_mut: i64 = @intCast(new_file_offset); ++ while (remaining_size >= mf.flags.block_size.toByteUnits() * 2 - 1) { ++ const copy_len = linux.copy_file_range( ++ old_file.handle, ++ &old_file_offset_mut, ++ mf.file.handle, ++ &new_file_offset_mut, ++ @intCast(remaining_size), ++ 0, ++ ); ++ switch (linux.E.init(copy_len)) { ++ .SUCCESS => { ++ if (copy_len == 0) break; ++ remaining_size -= copy_len; ++ if (remaining_size == 0) break; ++ }, ++ .INTR => continue, ++ .BADF, .FBIG, .INVAL, .OVERFLOW => unreachable, ++ .IO => return error.InputOutput, ++ .ISDIR => return error.IsDir, ++ .NOMEM => return error.SystemResources, ++ .NOSPC => return error.NoSpaceLeft, ++ .NOSYS, .OPNOTSUPP, .XDEV => { ++ mf.flags.copy_file_range_unsupported = true; ++ break; ++ }, ++ .PERM => return error.PermissionDenied, ++ .TXTBSY => return error.FileBusy, ++ else => |e| return std.posix.unexpectedErrno(e), ++ } ++ } ++ } ++ return size - remaining_size; ++} ++ ++fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) !void { ++ try mf.large.ensureUnusedCapacity(gpa, 2); ++ try mf.updates.ensureUnusedCapacity(gpa, 1); ++} ++ ++pub fn ensureTotalCapacity(mf: *MappedFile, new_capacity: usize) !void { ++ if (mf.contents.len >= new_capacity) return; ++ try mf.ensureTotalCapacityPrecise(new_capacity +| new_capacity / 2); ++} ++ ++pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void { ++ if (mf.contents.len >= new_capacity) return; ++ const aligned_capacity = mf.flags.block_size.forward(new_capacity); ++ if (!is_linux) mf.unmap() else if (mf.contents.len > 0) { ++ mf.contents = try std.posix.mremap( ++ mf.contents.ptr, ++ mf.contents.len, ++ aligned_capacity, ++ .{ .MAYMOVE = true }, ++ null, ++ ); ++ return; ++ } ++ if (is_windows) { ++ if (mf.section == windows.INVALID_HANDLE_VALUE) switch (windows.ntdll.NtCreateSection( ++ &mf.section, ++ windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | ++ windows.SECTION_MAP_WRITE | windows.SECTION_MAP_READ | windows.SECTION_EXTEND_SIZE, ++ null, ++ @constCast(&@as(i64, @intCast(aligned_capacity))), ++ windows.PAGE_READWRITE, ++ windows.SEC_COMMIT, ++ mf.file.handle, ++ )) { ++ .SUCCESS => {}, ++ else => return error.MemoryMappingNotSupported, ++ }; ++ var contents_ptr: ?[*]align(std.heap.page_size_min) u8 = null; ++ var contents_len = aligned_capacity; ++ switch (windows.ntdll.NtMapViewOfSection( ++ mf.section, ++ windows.GetCurrentProcess(), ++ @ptrCast(&contents_ptr), ++ null, ++ 0, ++ null, ++ &contents_len, ++ .ViewUnmap, ++ 0, ++ windows.PAGE_READWRITE, ++ )) { ++ .SUCCESS => mf.contents = contents_ptr.?[0..contents_len], ++ else => return error.MemoryMappingNotSupported, ++ } ++ } else mf.contents = try std.posix.mmap( ++ null, ++ aligned_capacity, ++ std.posix.PROT.READ | std.posix.PROT.WRITE, ++ .{ .TYPE = if (is_linux) .SHARED_VALIDATE else .SHARED }, ++ mf.file.handle, ++ 0, ++ ); ++} ++ ++pub fn unmap(mf: *MappedFile) void { ++ if (mf.contents.len == 0) return; ++ if (is_windows) ++ _ = windows.ntdll.NtUnmapViewOfSection(windows.GetCurrentProcess(), mf.contents.ptr) ++ else ++ std.posix.munmap(mf.contents); ++ mf.contents = &.{}; ++ if (is_windows and mf.section != windows.INVALID_HANDLE_VALUE) { ++ windows.CloseHandle(mf.section); ++ mf.section = windows.INVALID_HANDLE_VALUE; ++ } ++} ++ ++fn verify(mf: *MappedFile) void { ++ const root = Node.Index.root.get(mf); ++ assert(root.parent == .none); ++ assert(root.prev == .none); ++ assert(root.next == .none); ++ mf.verifyNode(Node.Index.root); ++} ++ ++fn verifyNode(mf: *MappedFile, parent_ni: Node.Index) void { ++ const parent = parent_ni.get(mf); ++ const parent_offset, const parent_size = parent.location().resolve(mf); ++ var prev_ni: Node.Index = .none; ++ var prev_end: u64 = 0; ++ var ni = parent.first; ++ while (true) { ++ if (ni == .none) { ++ assert(parent.last == prev_ni); ++ return; ++ } ++ const node = ni.get(mf); ++ assert(node.parent == parent_ni); ++ const offset, const size = node.location().resolve(mf); ++ assert(node.flags.alignment.check(@intCast(offset))); ++ assert(node.flags.alignment.check(@intCast(size))); ++ const end = offset + size; ++ assert(end <= parent_offset + parent_size); ++ assert(offset >= prev_end); ++ assert(node.prev == prev_ni); ++ mf.verifyNode(ni); ++ prev_ni = ni; ++ prev_end = end; ++ ni = node.next; ++ } ++} ++ ++const assert = std.debug.assert; ++const builtin = @import("builtin"); ++const is_linux = builtin.os.tag == .linux; ++const is_windows = builtin.os.tag == .windows; ++const linux = std.os.linux; ++const MappedFile = @This(); ++const std = @import("std"); ++const windows = std.os.windows; +diff --git a/src/link/Queue.zig b/src/link/Queue.zig +index 9f4535e1fe..742b4664f1 100644 +--- a/src/link/Queue.zig ++++ b/src/link/Queue.zig +@@ -22,17 +22,17 @@ prelink_wait_count: u32, + + /// Prelink tasks which have been enqueued and are not yet owned by the worker thread. + /// Allocated into `gpa`, guarded by `mutex`. +-queued_prelink: std.ArrayListUnmanaged(PrelinkTask), ++queued_prelink: std.ArrayList(PrelinkTask), + /// The worker thread moves items from `queued_prelink` into this array in order to process them. + /// Allocated into `gpa`, accessed only by the worker thread. +-wip_prelink: std.ArrayListUnmanaged(PrelinkTask), ++wip_prelink: std.ArrayList(PrelinkTask), + + /// Like `queued_prelink`, but for ZCU tasks. + /// Allocated into `gpa`, guarded by `mutex`. +-queued_zcu: std.ArrayListUnmanaged(ZcuTask), ++queued_zcu: std.ArrayList(ZcuTask), + /// Like `wip_prelink`, but for ZCU tasks. + /// Allocated into `gpa`, accessed only by the worker thread. +-wip_zcu: std.ArrayListUnmanaged(ZcuTask), ++wip_zcu: std.ArrayList(ZcuTask), + + /// When processing ZCU link tasks, we might have to block due to unpopulated MIR. When this + /// happens, some tasks in `wip_zcu` have been run, and some are still pending. This is the +@@ -213,32 +213,41 @@ pub fn enqueueZcu(q: *Queue, comp: *Compilation, task: ZcuTask) Allocator.Error! + + fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { + q.flush_safety.lock(); // every `return` site should unlock this before unlocking `q.mutex` +- + if (std.debug.runtime_safety) { + q.mutex.lock(); + defer q.mutex.unlock(); + assert(q.state == .running); + } ++ ++ var have_idle_tasks = true; + prelink: while (true) { + assert(q.wip_prelink.items.len == 0); +- { +- q.mutex.lock(); +- defer q.mutex.unlock(); +- std.mem.swap(std.ArrayListUnmanaged(PrelinkTask), &q.queued_prelink, &q.wip_prelink); +- if (q.wip_prelink.items.len == 0) { +- if (q.prelink_wait_count == 0) { +- break :prelink; // prelink is done +- } else { ++ swap_queues: while (true) { ++ { ++ q.mutex.lock(); ++ defer q.mutex.unlock(); ++ std.mem.swap(std.ArrayList(PrelinkTask), &q.queued_prelink, &q.wip_prelink); ++ if (q.wip_prelink.items.len > 0) break :swap_queues; ++ if (q.prelink_wait_count == 0) break :prelink; // prelink is done ++ if (!have_idle_tasks) { + // We're expecting more prelink tasks so can't move on to ZCU tasks. + q.state = .finished; + q.flush_safety.unlock(); + return; + } + } ++ have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { ++ error.OutOfMemory => have_idle_tasks: { ++ comp.link_diags.setAllocFailure(); ++ break :have_idle_tasks false; ++ }, ++ error.LinkFailure => false, ++ }; + } + for (q.wip_prelink.items) |task| { + link.doPrelinkTask(comp, task); + } ++ have_idle_tasks = true; + q.wip_prelink.clearRetainingCapacity(); + } + +@@ -256,17 +265,29 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { + + // Now we can run ZCU tasks. + while (true) { +- if (q.wip_zcu.items.len == q.wip_zcu_idx) { ++ if (q.wip_zcu.items.len == q.wip_zcu_idx) swap_queues: { + q.wip_zcu.clearRetainingCapacity(); + q.wip_zcu_idx = 0; +- q.mutex.lock(); +- defer q.mutex.unlock(); +- std.mem.swap(std.ArrayListUnmanaged(ZcuTask), &q.queued_zcu, &q.wip_zcu); +- if (q.wip_zcu.items.len == 0) { +- // We've exhausted all available tasks. +- q.state = .finished; +- q.flush_safety.unlock(); +- return; ++ while (true) { ++ { ++ q.mutex.lock(); ++ defer q.mutex.unlock(); ++ std.mem.swap(std.ArrayList(ZcuTask), &q.queued_zcu, &q.wip_zcu); ++ if (q.wip_zcu.items.len > 0) break :swap_queues; ++ if (!have_idle_tasks) { ++ // We've exhausted all available tasks. ++ q.state = .finished; ++ q.flush_safety.unlock(); ++ return; ++ } ++ } ++ have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { ++ error.OutOfMemory => have_idle_tasks: { ++ comp.link_diags.setAllocFailure(); ++ break :have_idle_tasks false; ++ }, ++ error.LinkFailure => false, ++ }; + } + } + const task = q.wip_zcu.items[q.wip_zcu_idx]; +@@ -274,8 +295,18 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { + pending: { + if (task != .link_func) break :pending; + const status_ptr = &task.link_func.mir.status; +- // First check without the mutex to optimize for the common case where MIR is ready. +- if (status_ptr.load(.acquire) != .pending) break :pending; ++ while (true) { ++ // First check without the mutex to optimize for the common case where MIR is ready. ++ if (status_ptr.load(.acquire) != .pending) break :pending; ++ if (have_idle_tasks) have_idle_tasks = link.doIdleTask(comp, tid) catch |err| switch (err) { ++ error.OutOfMemory => have_idle_tasks: { ++ comp.link_diags.setAllocFailure(); ++ break :have_idle_tasks false; ++ }, ++ error.LinkFailure => false, ++ }; ++ if (!have_idle_tasks) break; ++ } + q.mutex.lock(); + defer q.mutex.unlock(); + if (status_ptr.load(.acquire) != .pending) break :pending; +@@ -298,6 +329,7 @@ fn flushTaskQueue(tid: usize, q: *Queue, comp: *Compilation) void { + } + } + q.wip_zcu_idx += 1; ++ have_idle_tasks = true; + } + } + +diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig +index a125a70aae..d60b91c30f 100644 +--- a/src/link/Wasm.zig ++++ b/src/link/Wasm.zig +@@ -4257,7 +4257,14 @@ fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Zcu + const func_table_fixups_start: u32 = @intCast(wasm.func_table_fixups.items.len); + wasm.string_bytes_lock.lock(); + +- try codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &wasm.string_bytes, .none); ++ { ++ var aw: std.Io.Writer.Allocating = .fromArrayList(wasm.base.comp.gpa, &wasm.string_bytes); ++ defer wasm.string_bytes = aw.toArrayList(); ++ codegen.generateSymbol(&wasm.base, pt, .unneeded, .fromInterned(ip_index), &aw.writer, .none) catch |err| switch (err) { ++ error.WriteFailed => return error.OutOfMemory, ++ else => |e| return e, ++ }; ++ } + + const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start); + const relocs_len: u32 = @intCast(wasm.out_relocs.len - relocs_start); +diff --git a/src/main.zig b/src/main.zig +index 26d44c4463..9d43e47ea2 100644 +--- a/src/main.zig ++++ b/src/main.zig +@@ -904,7 +904,6 @@ fn buildOutputType( + var mingw_unicode_entry_point: bool = false; + var enable_link_snapshots: bool = false; + var debug_compiler_runtime_libs = false; +- var opt_incremental: ?bool = null; + var install_name: ?[]const u8 = null; + var hash_style: link.File.Lld.Elf.HashStyle = .both; + var entitlements: ?[]const u8 = null; +@@ -1374,9 +1373,9 @@ fn buildOutputType( + } + } else if (mem.eql(u8, arg, "-fincremental")) { + dev.check(.incremental); +- opt_incremental = true; ++ create_module.opts.incremental = true; + } else if (mem.eql(u8, arg, "-fno-incremental")) { +- opt_incremental = false; ++ create_module.opts.incremental = false; + } else if (mem.eql(u8, arg, "--entitlements")) { + entitlements = args_iter.nextOrFatal(); + } else if (mem.eql(u8, arg, "-fcompiler-rt")) { +@@ -1479,6 +1478,10 @@ fn buildOutputType( + create_module.opts.use_lld = true; + } else if (mem.eql(u8, arg, "-fno-lld")) { + create_module.opts.use_lld = false; ++ } else if (mem.eql(u8, arg, "-fnew-linker")) { ++ create_module.opts.use_new_linker = true; ++ } else if (mem.eql(u8, arg, "-fno-new-linker")) { ++ create_module.opts.use_new_linker = false; + } else if (mem.eql(u8, arg, "-fclang")) { + create_module.opts.use_clang = true; + } else if (mem.eql(u8, arg, "-fno-clang")) { +@@ -3371,7 +3374,7 @@ fn buildOutputType( + else => false, + }; + +- const incremental = opt_incremental orelse false; ++ const incremental = create_module.resolved_options.incremental; + if (debug_incremental and !incremental) { + fatal("--debug-incremental requires -fincremental", .{}); + } +@@ -3502,7 +3505,6 @@ fn buildOutputType( + .subsystem = subsystem, + .debug_compile_errors = debug_compile_errors, + .debug_incremental = debug_incremental, +- .incremental = incremental, + .enable_link_snapshots = enable_link_snapshots, + .install_name = install_name, + .entitlements = entitlements, +@@ -4016,6 +4018,8 @@ fn createModule( + error.LldUnavailable => fatal("zig was compiled without LLD libraries", .{}), + error.ClangUnavailable => fatal("zig was compiled without Clang libraries", .{}), + error.DllExportFnsRequiresWindows => fatal("only Windows OS targets support DLLs", .{}), ++ error.NewLinkerIncompatibleObjectFormat => fatal("using the new linker to link {s} files is unsupported", .{@tagName(target.ofmt)}), ++ error.NewLinkerIncompatibleWithLld => fatal("using the new linker is incompatible with using lld", .{}), + }; + } + +diff --git a/src/target.zig b/src/target.zig +index e999d2ae22..1cf5c9b082 100644 +--- a/src/target.zig ++++ b/src/target.zig +@@ -231,6 +231,13 @@ pub fn hasLldSupport(ofmt: std.Target.ObjectFormat) bool { + }; + } + ++pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat) bool { ++ return switch (ofmt) { ++ .elf => true, ++ else => false, ++ }; ++} ++ + /// The set of targets that our own self-hosted backends have robust support for. + /// Used to select between LLVM backend and self-hosted backend when compiling in + /// debug mode. A given target should only return true here if it is passing greater +diff --git a/test/incremental/change_exports b/test/incremental/change_exports +index 01605bdeeb..e492930031 100644 +--- a/test/incremental/change_exports ++++ b/test/incremental/change_exports +@@ -1,4 +1,4 @@ +-//#target=x86_64-linux-selfhosted ++#target=x86_64-linux-selfhosted + #target=x86_64-linux-cbe + #target=x86_64-windows-cbe + +diff --git a/test/incremental/change_panic_handler b/test/incremental/change_panic_handler +index 3e400b854e..699134100e 100644 +--- a/test/incremental/change_panic_handler ++++ b/test/incremental/change_panic_handler +@@ -1,3 +1,4 @@ ++#target=x86_64-linux-selfhosted + #target=x86_64-linux-cbe + #target=x86_64-windows-cbe + #update=initial version +diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit +index 9f7eb6c12f..2d068d593e 100644 +--- a/test/incremental/change_panic_handler_explicit ++++ b/test/incremental/change_panic_handler_explicit +@@ -1,3 +1,4 @@ ++#target=x86_64-linux-selfhosted + #target=x86_64-linux-cbe + #target=x86_64-windows-cbe + #update=initial version +diff --git a/test/incremental/change_struct_same_fields b/test/incremental/change_struct_same_fields +index 97049a1fc0..f3bfbbdd69 100644 +--- a/test/incremental/change_struct_same_fields ++++ b/test/incremental/change_struct_same_fields +@@ -1,4 +1,4 @@ +-//#target=x86_64-linux-selfhosted ++#target=x86_64-linux-selfhosted + #target=x86_64-linux-cbe + #target=x86_64-windows-cbe + #target=wasm32-wasi-selfhosted +diff --git a/test/incremental/type_becomes_comptime_only b/test/incremental/type_becomes_comptime_only +index 5c5d332975..3bcae1cd21 100644 +--- a/test/incremental/type_becomes_comptime_only ++++ b/test/incremental/type_becomes_comptime_only +@@ -1,3 +1,4 @@ ++#target=x86_64-linux-selfhosted + #target=x86_64-linux-cbe + #target=x86_64-windows-cbe + #target=wasm32-wasi-selfhosted