| author | |
| committer | |
| log | f9bd049c89e4d2b4d3f51a937ec2114c3cac9176 |
| tree | 81bf283c8ae2e06fd3a48d18e3b4196e194392d0 |
| parent | 3aeeb21b82915a3d03e75a88ded93049a5c1730c |
| parent | dad7af0b37f352c8c390438877ef1552a316ffde |
526 files changed, 9582 insertions(+), 4926 deletions(-)
build.zig+1-1| ... | @@ -38,7 +38,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -38,7 +38,7 @@ pub fn build(b: *Builder) !void { |
| 38 | const test_step = b.step("test", "Run all the tests"); | 38 | const test_step = b.step("test", "Run all the tests"); |
| 39 | 39 | ||
| 40 | var test_stage2 = b.addTest("src-self-hosted/test.zig"); | 40 | var test_stage2 = b.addTest("src-self-hosted/test.zig"); |
| 41 | test_stage2.setBuildMode(.Debug); // note this is only the mode of the test harness | 41 | test_stage2.setBuildMode(mode); |
| 42 | test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig"); | 42 | test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig"); |
| 43 | 43 | ||
| 44 | const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"}); | 44 | const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"}); |
lib/std/array_list.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 8 | const assert = debug.assert; |
lib/std/array_list_sentineled.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/ascii.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Does NOT look at the locale the way C89's toupper(3), isspace() et cetera does. | 6 | // Does NOT look at the locale the way C89's toupper(3), isspace() et cetera does. |
| 2 | // I could have taken only a u7 to make this clear, but it would be slower | 7 | // I could have taken only a u7 to make this clear, but it would be slower |
| 3 | // It is my opinion that encodings other than UTF-8 should not be supported. | 8 | // It is my opinion that encodings other than UTF-8 should not be supported. |
lib/std/atomic.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const Stack = @import("atomic/stack.zig").Stack; | 6 | pub const Stack = @import("atomic/stack.zig").Stack; |
| 2 | pub const Queue = @import("atomic/queue.zig").Queue; | 7 | pub const Queue = @import("atomic/queue.zig").Queue; |
| 3 | pub const Int = @import("atomic/int.zig").Int; | 8 | pub const Int = @import("atomic/int.zig").Int; |
lib/std/atomic/int.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Thread-safe, lock-free integer | 6 | /// Thread-safe, lock-free integer |
| 2 | pub fn Int(comptime T: type) type { | 7 | pub fn Int(comptime T: type) type { |
| 3 | return struct { | 8 | return struct { |
lib/std/atomic/queue.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/atomic/stack.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/base64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/bloom_filter.zig+6-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 7 | const std = @import("std.zig"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
| ... | @@ -153,7 +158,7 @@ pub fn BloomFilter( | ... | @@ -153,7 +158,7 @@ pub fn BloomFilter( |
| 153 | } | 158 | } |
| 154 | 159 | ||
| 155 | fn hashFunc(out: []u8, Ki: usize, in: []const u8) void { | 160 | fn hashFunc(out: []u8, Ki: usize, in: []const u8) void { |
| 156 | var st = std.crypto.gimli.Hash.init(); | 161 | var st = std.crypto.hash.Gimli.init(.{}); |
| 157 | st.update(std.mem.asBytes(&Ki)); | 162 | st.update(std.mem.asBytes(&Ki)); |
| 158 | st.update(in); | 163 | st.update(in); |
| 159 | st.final(out); | 164 | st.final(out); |
lib/std/buf_map.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const StringHashMap = std.StringHashMap; | 7 | const StringHashMap = std.StringHashMap; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/buf_set.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const StringHashMap = std.StringHashMap; | 7 | const StringHashMap = std.StringHashMap; |
| 3 | const mem = @import("mem.zig"); | 8 | const mem = @import("mem.zig"); |
lib/std/build.zig+32-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
| ... | @@ -449,7 +454,33 @@ pub const Builder = struct { | ... | @@ -449,7 +454,33 @@ pub const Builder = struct { |
| 449 | return null; | 454 | return null; |
| 450 | }, | 455 | }, |
| 451 | }, | 456 | }, |
| 452 | .Int => panic("TODO integer options to build script", .{}), | 457 | .Int => switch (entry.value.value) { |
| 458 | .Flag => { | ||
| 459 | warn("Expected -D{} to be an integer, but received a boolean.\n", .{name}); | ||
| 460 | self.markInvalidUserInput(); | ||
| 461 | return null; | ||
| 462 | }, | ||
| 463 | .Scalar => |s| { | ||
| 464 | const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) { | ||
| 465 | error.Overflow => { | ||
| 466 | warn("-D{} value {} cannot fit into type {}.\n", .{ name, s, @typeName(T) }); | ||
| 467 | self.markInvalidUserInput(); | ||
| 468 | return null; | ||
| 469 | }, | ||
| 470 | else => { | ||
| 471 | warn("Expected -D{} to be an integer of type {}.\n", .{ name, @typeName(T) }); | ||
| 472 | self.markInvalidUserInput(); | ||
| 473 | return null; | ||
| 474 | }, | ||
| 475 | }; | ||
| 476 | return n; | ||
| 477 | }, | ||
| 478 | .List => { | ||
| 479 | warn("Expected -D{} to be an integer, but received a list.\n", .{name}); | ||
| 480 | self.markInvalidUserInput(); | ||
| 481 | return null; | ||
| 482 | }, | ||
| 483 | }, | ||
| 453 | .Float => panic("TODO float options to build script", .{}), | 484 | .Float => panic("TODO float options to build script", .{}), |
| 454 | .Enum => switch (entry.value.value) { | 485 | .Enum => switch (entry.value.value) { |
| 455 | .Flag => { | 486 | .Flag => { |
lib/std/build/check_file.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const build = std.build; | 7 | const build = std.build; |
| 3 | const Step = build.Step; | 8 | const Step = build.Step; |
lib/std/build/emit_raw.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
lib/std/build/fmt.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const build = @import("../build.zig"); | 7 | const build = @import("../build.zig"); |
| 3 | const Step = build.Step; | 8 | const Step = build.Step; |
lib/std/build/run.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const build = std.build; | 8 | const build = std.build; |
lib/std/build/translate_c.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const build = std.build; | 7 | const build = std.build; |
| 3 | const Step = build.Step; | 8 | const Step = build.Step; |
lib/std/build/write_file.zig+6-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const build = @import("../build.zig"); | 7 | const build = @import("../build.zig"); |
| 3 | const Step = build.Step; | 8 | const Step = build.Step; |
| ... | @@ -53,7 +58,7 @@ pub const WriteFileStep = struct { | ... | @@ -53,7 +58,7 @@ pub const WriteFileStep = struct { |
| 53 | // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b | 58 | // TODO port the cache system from stage1 to zig std lib. Until then we use blake2b |
| 54 | // directly and construct the path, and no "cache hit" detection happens; the files | 59 | // directly and construct the path, and no "cache hit" detection happens; the files |
| 55 | // are always written. | 60 | // are always written. |
| 56 | var hash = std.crypto.Blake2b384.init(); | 61 | var hash = std.crypto.hash.blake2.Blake2b384.init(.{}); |
| 57 | 62 | ||
| 58 | // Random bytes to make WriteFileStep unique. Refresh this with | 63 | // Random bytes to make WriteFileStep unique. Refresh this with |
| 59 | // new random bytes when WriteFileStep implementation is modified | 64 | // new random bytes when WriteFileStep implementation is modified |
lib/std/builtin.zig+5-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub usingnamespace @import("builtin"); | 6 | pub usingnamespace @import("builtin"); |
| 2 | 7 | ||
| 3 | /// Deprecated: use `std.Target`. | 8 | /// Deprecated: use `std.Target`. |
| ... | @@ -254,7 +259,6 @@ pub const TypeInfo = union(enum) { | ... | @@ -254,7 +259,6 @@ pub const TypeInfo = union(enum) { |
| 254 | /// therefore must be kept in sync with the compiler implementation. | 259 | /// therefore must be kept in sync with the compiler implementation. |
| 255 | pub const StructField = struct { | 260 | pub const StructField = struct { |
| 256 | name: []const u8, | 261 | name: []const u8, |
| 257 | offset: ?comptime_int, | ||
| 258 | field_type: type, | 262 | field_type: type, |
| 259 | default_value: anytype, | 263 | default_value: anytype, |
| 260 | }; | 264 | }; |
lib/std/c.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const page_size = std.mem.page_size; | 8 | const page_size = std.mem.page_size; |
lib/std/c/ast.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const SegmentedList = std.SegmentedList; | 7 | const SegmentedList = std.SegmentedList; |
| 3 | const Token = std.c.Token; | 8 | const Token = std.c.Token; |
lib/std/c/darwin.zig+8-2| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| ... | @@ -41,10 +46,11 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header; | ... | @@ -41,10 +46,11 @@ const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header; |
| 41 | /// on this operating system. However when building object files or libraries, | 46 | /// on this operating system. However when building object files or libraries, |
| 42 | /// the system libc won't be linked until the final executable. So we | 47 | /// the system libc won't be linked until the final executable. So we |
| 43 | /// export a weak symbol here, to be overridden by the real one. | 48 | /// export a weak symbol here, to be overridden by the real one. |
| 44 | pub extern "c" var _mh_execute_header: mach_hdr = undefined; | 49 | var dummy_execute_header: mach_hdr = undefined; |
| 50 | pub extern var _mh_execute_header: mach_hdr; | ||
| 45 | comptime { | 51 | comptime { |
| 46 | if (std.Target.current.isDarwin()) { | 52 | if (std.Target.current.isDarwin()) { |
| 47 | @export(_mh_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak }); | 53 | @export(dummy_execute_header, .{ .name = "_mh_execute_header", .linkage = .Weak }); |
| 48 | } | 54 | } |
| 49 | } | 55 | } |
| 50 | 56 |
lib/std/c/dragonfly.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | usingnamespace std.c; | 7 | usingnamespace std.c; |
| 3 | extern "c" threadlocal var errno: c_int; | 8 | extern "c" threadlocal var errno: c_int; |
lib/std/c/emscripten.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(4) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | 7 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(4) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, |
| 3 | }; | 8 | }; |
lib/std/c/freebsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | usingnamespace std.c; | 7 | usingnamespace std.c; |
| 3 | 8 |
lib/std/c/fuchsia.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | 7 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, |
| 3 | }; | 8 | }; |
lib/std/c/haiku.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | flags: u32 = 0, | 7 | flags: u32 = 0, |
| 3 | lock: i32 = 0, | 8 | lock: i32 = 0, |
lib/std/c/hermit.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | inner: usize = ~@as(usize, 0), | 7 | inner: usize = ~@as(usize, 0), |
| 3 | }; | 8 | }; |
lib/std/c/linux.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/c/minix.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | pub const pthread_mutex_t = extern struct { | 7 | pub const pthread_mutex_t = extern struct { |
| 3 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | 8 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, |
lib/std/c/netbsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | 8 |
lib/std/c/openbsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | inner: ?*c_void = null, | 7 | inner: ?*c_void = null, |
| 3 | }; | 8 | }; |
lib/std/c/parse.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/c/solaris.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const pthread_mutex_t = extern struct { | 6 | pub const pthread_mutex_t = extern struct { |
| 2 | __pthread_mutex_flag1: u16 = 0, | 7 | __pthread_mutex_flag1: u16 = 0, |
| 3 | __pthread_mutex_flag2: u8 = 0, | 8 | __pthread_mutex_flag2: u8 = 0, |
lib/std/c/tokenizer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
lib/std/c/windows.zig+5| ... | @@ -1 +1,6 @@ | ... | @@ -1 +1,6 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub extern "c" fn _errno() *c_int; | 6 | pub extern "c" fn _errno() *c_int; |
lib/std/cache_hash.zig+11-6| ... | @@ -1,5 +1,10 @@ | ... | @@ -1,5 +1,10 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const Blake3 = std.crypto.Blake3; | 7 | const Blake3 = std.crypto.hash.Blake3; |
| 3 | const fs = std.fs; | 8 | const fs = std.fs; |
| 4 | const base64 = std.base64; | 9 | const base64 = std.base64; |
| 5 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| ... | @@ -51,7 +56,7 @@ pub const CacheHash = struct { | ... | @@ -51,7 +56,7 @@ pub const CacheHash = struct { |
| 51 | pub fn init(allocator: *Allocator, dir: fs.Dir, manifest_dir_path: []const u8) !CacheHash { | 56 | pub fn init(allocator: *Allocator, dir: fs.Dir, manifest_dir_path: []const u8) !CacheHash { |
| 52 | return CacheHash{ | 57 | return CacheHash{ |
| 53 | .allocator = allocator, | 58 | .allocator = allocator, |
| 54 | .blake3 = Blake3.init(), | 59 | .blake3 = Blake3.init(.{}), |
| 55 | .manifest_dir = try dir.makeOpenPath(manifest_dir_path, .{}), | 60 | .manifest_dir = try dir.makeOpenPath(manifest_dir_path, .{}), |
| 56 | .manifest_file = null, | 61 | .manifest_file = null, |
| 57 | .manifest_dirty = false, | 62 | .manifest_dirty = false, |
| ... | @@ -132,7 +137,7 @@ pub const CacheHash = struct { | ... | @@ -132,7 +137,7 @@ pub const CacheHash = struct { |
| 132 | 137 | ||
| 133 | base64_encoder.encode(self.b64_digest[0..], &bin_digest); | 138 | base64_encoder.encode(self.b64_digest[0..], &bin_digest); |
| 134 | 139 | ||
| 135 | self.blake3 = Blake3.init(); | 140 | self.blake3 = Blake3.init(.{}); |
| 136 | self.blake3.update(&bin_digest); | 141 | self.blake3.update(&bin_digest); |
| 137 | 142 | ||
| 138 | const manifest_file_path = try fmt.allocPrint(self.allocator, "{}.txt", .{self.b64_digest}); | 143 | const manifest_file_path = try fmt.allocPrint(self.allocator, "{}.txt", .{self.b64_digest}); |
| ... | @@ -251,7 +256,7 @@ pub const CacheHash = struct { | ... | @@ -251,7 +256,7 @@ pub const CacheHash = struct { |
| 251 | // cache miss | 256 | // cache miss |
| 252 | // keep the manifest file open | 257 | // keep the manifest file open |
| 253 | // reset the hash | 258 | // reset the hash |
| 254 | self.blake3 = Blake3.init(); | 259 | self.blake3 = Blake3.init(.{}); |
| 255 | self.blake3.update(&bin_digest); | 260 | self.blake3.update(&bin_digest); |
| 256 | 261 | ||
| 257 | // Remove files not in the initial hash | 262 | // Remove files not in the initial hash |
| ... | @@ -299,7 +304,7 @@ pub const CacheHash = struct { | ... | @@ -299,7 +304,7 @@ pub const CacheHash = struct { |
| 299 | 304 | ||
| 300 | // Hash while reading from disk, to keep the contents in the cpu cache while | 305 | // Hash while reading from disk, to keep the contents in the cpu cache while |
| 301 | // doing hashing. | 306 | // doing hashing. |
| 302 | var blake3 = Blake3.init(); | 307 | var blake3 = Blake3.init(.{}); |
| 303 | var off: usize = 0; | 308 | var off: usize = 0; |
| 304 | while (true) { | 309 | while (true) { |
| 305 | // give me everything you've got, captain | 310 | // give me everything you've got, captain |
| ... | @@ -429,7 +434,7 @@ pub const CacheHash = struct { | ... | @@ -429,7 +434,7 @@ pub const CacheHash = struct { |
| 429 | }; | 434 | }; |
| 430 | 435 | ||
| 431 | fn hashFile(file: fs.File, bin_digest: []u8) !void { | 436 | fn hashFile(file: fs.File, bin_digest: []u8) !void { |
| 432 | var blake3 = Blake3.init(); | 437 | var blake3 = Blake3.init(.{}); |
| 433 | var buf: [1024]u8 = undefined; | 438 | var buf: [1024]u8 = undefined; |
| 434 | 439 | ||
| 435 | while (true) { | 440 | while (true) { |
lib/std/child_process.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const cstr = std.cstr; | 7 | const cstr = std.cstr; |
| 3 | const unicode = std.unicode; | 8 | const unicode = std.unicode; |
lib/std/coff.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 7 | const std = @import("std.zig"); |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/comptime_string_map.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
lib/std/crypto.zig+74-56| ... | @@ -1,55 +1,68 @@ | ... | @@ -1,55 +1,68 @@ |
| 1 | pub const Md5 = @import("crypto/md5.zig").Md5; | 1 | // SPDX-License-Identifier: MIT |
| 2 | pub const Sha1 = @import("crypto/sha1.zig").Sha1; | 2 | // Copyright (c) 2015-2020 Zig Contributors |
| 3 | 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | const sha2 = @import("crypto/sha2.zig"); | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | pub const Sha224 = sha2.Sha224; | 5 | // and substantial portions of the software. |
| 6 | pub const Sha256 = sha2.Sha256; | 6 | |
| 7 | pub const Sha384 = sha2.Sha384; | 7 | /// Hash functions. |
| 8 | pub const Sha512 = sha2.Sha512; | 8 | pub const hash = struct { |
| 9 | 9 | pub const Md5 = @import("crypto/md5.zig").Md5; | |
| 10 | const sha3 = @import("crypto/sha3.zig"); | 10 | pub const Sha1 = @import("crypto/sha1.zig").Sha1; |
| 11 | pub const Sha3_224 = sha3.Sha3_224; | 11 | pub const sha2 = @import("crypto/sha2.zig"); |
| 12 | pub const Sha3_256 = sha3.Sha3_256; | 12 | pub const sha3 = @import("crypto/sha3.zig"); |
| 13 | pub const Sha3_384 = sha3.Sha3_384; | 13 | pub const blake2 = @import("crypto/blake2.zig"); |
| 14 | pub const Sha3_512 = sha3.Sha3_512; | 14 | pub const Blake3 = @import("crypto/blake3.zig").Blake3; |
| 15 | pub const Gimli = @import("crypto/gimli.zig").Hash; | ||
| 16 | }; | ||
| 15 | 17 | ||
| 16 | pub const gimli = @import("crypto/gimli.zig"); | 18 | /// Authentication (MAC) functions. |
| 19 | pub const auth = struct { | ||
| 20 | pub const hmac = @import("crypto/hmac.zig"); | ||
| 21 | }; | ||
| 17 | 22 | ||
| 18 | const blake2 = @import("crypto/blake2.zig"); | 23 | /// Authenticated Encryption with Associated Data |
| 19 | pub const Blake2s224 = blake2.Blake2s224; | 24 | pub const aead = struct { |
| 20 | pub const Blake2s256 = blake2.Blake2s256; | 25 | const chacha20 = @import("crypto/chacha20.zig"); |
| 21 | pub const Blake2b384 = blake2.Blake2b384; | ||
| 22 | pub const Blake2b512 = blake2.Blake2b512; | ||
| 23 | 26 | ||
| 24 | pub const Blake3 = @import("crypto/blake3.zig").Blake3; | 27 | pub const Gimli = @import("crypto/gimli.zig").Aead; |
| 28 | pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305; | ||
| 29 | pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305; | ||
| 30 | }; | ||
| 25 | 31 | ||
| 26 | const hmac = @import("crypto/hmac.zig"); | 32 | /// MAC functions requiring single-use secret keys. |
| 27 | pub const HmacMd5 = hmac.HmacMd5; | 33 | pub const onetimeauth = struct { |
| 28 | pub const HmacSha1 = hmac.HmacSha1; | 34 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 29 | pub const HmacSha256 = hmac.HmacSha256; | 35 | }; |
| 30 | pub const HmacBlake2s256 = hmac.HmacBlake2s256; | ||
| 31 | 36 | ||
| 32 | pub const chacha20 = @import("crypto/chacha20.zig"); | 37 | /// Core functions, that should rarely be used directly by applications. |
| 33 | pub const chaCha20IETF = chacha20.chaCha20IETF; | 38 | pub const core = struct { |
| 34 | pub const chaCha20With64BitNonce = chacha20.chaCha20With64BitNonce; | 39 | pub const aes = @import("crypto/aes.zig"); |
| 35 | pub const xChaCha20IETF = chacha20.xChaCha20IETF; | 40 | pub const Gimli = @import("crypto/gimli.zig").State; |
| 41 | }; | ||
| 36 | 42 | ||
| 37 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; | 43 | /// Elliptic-curve arithmetic. |
| 44 | pub const ecc = struct { | ||
| 45 | pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; | ||
| 46 | pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; | ||
| 47 | pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; | ||
| 48 | }; | ||
| 38 | 49 | ||
| 39 | const import_aes = @import("crypto/aes.zig"); | 50 | /// Diffie-Hellman key exchange functions. |
| 40 | pub const AES128 = import_aes.AES128; | 51 | pub const dh = struct { |
| 41 | pub const AES256 = import_aes.AES256; | 52 | pub const X25519 = @import("crypto/25519/x25519.zig").X25519; |
| 53 | }; | ||
| 42 | 54 | ||
| 43 | pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; | 55 | /// Digital signature functions. |
| 44 | pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; | 56 | pub const sign = struct { |
| 45 | pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; | 57 | pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; |
| 46 | pub const X25519 = @import("crypto/25519/x25519.zig").X25519; | 58 | }; |
| 47 | pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; | ||
| 48 | 59 | ||
| 49 | pub const aead = struct { | 60 | /// Stream ciphers. These do not provide any kind of authentication. |
| 50 | pub const Gimli = gimli.Aead; | 61 | /// Most applications should be using AEAD constructions instead of stream ciphers directly. |
| 51 | pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305; | 62 | pub const stream = struct { |
| 52 | pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305; | 63 | pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF; |
| 64 | pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF; | ||
| 65 | pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce; | ||
| 53 | }; | 66 | }; |
| 54 | 67 | ||
| 55 | const std = @import("std.zig"); | 68 | const std = @import("std.zig"); |
| ... | @@ -78,27 +91,32 @@ test "crypto" { | ... | @@ -78,27 +91,32 @@ test "crypto" { |
| 78 | 91 | ||
| 79 | test "issue #4532: no index out of bounds" { | 92 | test "issue #4532: no index out of bounds" { |
| 80 | const types = [_]type{ | 93 | const types = [_]type{ |
| 81 | Md5, | 94 | hash.Md5, |
| 82 | Sha1, | 95 | hash.Sha1, |
| 83 | Sha224, | 96 | hash.sha2.Sha224, |
| 84 | Sha256, | 97 | hash.sha2.Sha256, |
| 85 | Sha384, | 98 | hash.sha2.Sha384, |
| 86 | Sha512, | 99 | hash.sha2.Sha512, |
| 87 | Blake2s224, | 100 | hash.sha3.Sha3_224, |
| 88 | Blake2s256, | 101 | hash.sha3.Sha3_256, |
| 89 | Blake2b384, | 102 | hash.sha3.Sha3_384, |
| 90 | Blake2b512, | 103 | hash.sha3.Sha3_512, |
| 104 | hash.blake2.Blake2s224, | ||
| 105 | hash.blake2.Blake2s256, | ||
| 106 | hash.blake2.Blake2b384, | ||
| 107 | hash.blake2.Blake2b512, | ||
| 108 | hash.Gimli, | ||
| 91 | }; | 109 | }; |
| 92 | 110 | ||
| 93 | inline for (types) |Hasher| { | 111 | inline for (types) |Hasher| { |
| 94 | var block = [_]u8{'#'} ** Hasher.block_length; | 112 | var block = [_]u8{'#'} ** Hasher.block_length; |
| 95 | var out1: [Hasher.digest_length]u8 = undefined; | 113 | var out1: [Hasher.digest_length]u8 = undefined; |
| 96 | var out2: [Hasher.digest_length]u8 = undefined; | 114 | var out2: [Hasher.digest_length]u8 = undefined; |
| 97 | 115 | const h0 = Hasher.init(.{}); | |
| 98 | var h = Hasher.init(); | 116 | var h = h0; |
| 99 | h.update(block[0..]); | 117 | h.update(block[0..]); |
| 100 | h.final(out1[0..]); | 118 | h.final(out1[0..]); |
| 101 | h.reset(); | 119 | h = h0; |
| 102 | h.update(block[0..1]); | 120 | h.update(block[0..1]); |
| 103 | h.update(block[1..]); | 121 | h.update(block[1..]); |
| 104 | h.final(out2[0..]); | 122 | h.final(out2[0..]); |
lib/std/crypto/25519/curve25519.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | /// Group operations over Curve25519. | 8 | /// Group operations over Curve25519. |
lib/std/crypto/25519/ed25519.zig+11-6| ... | @@ -1,7 +1,12 @@ | ... | @@ -1,7 +1,12 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const fmt = std.fmt; | 7 | const fmt = std.fmt; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
| 4 | const Sha512 = std.crypto.Sha512; | 9 | const Sha512 = std.crypto.hash.sha2.Sha512; |
| 5 | 10 | ||
| 6 | /// Ed25519 (EdDSA) signatures. | 11 | /// Ed25519 (EdDSA) signatures. |
| 7 | pub const Ed25519 = struct { | 12 | pub const Ed25519 = struct { |
| ... | @@ -28,7 +33,7 @@ pub const Ed25519 = struct { | ... | @@ -28,7 +33,7 @@ pub const Ed25519 = struct { |
| 28 | /// from which the actual secret is derived. | 33 | /// from which the actual secret is derived. |
| 29 | pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 { | 34 | pub fn createKeyPair(seed: [seed_length]u8) ![keypair_length]u8 { |
| 30 | var az: [Sha512.digest_length]u8 = undefined; | 35 | var az: [Sha512.digest_length]u8 = undefined; |
| 31 | var h = Sha512.init(); | 36 | var h = Sha512.init(.{}); |
| 32 | h.update(&seed); | 37 | h.update(&seed); |
| 33 | h.final(&az); | 38 | h.final(&az); |
| 34 | const p = try Curve.basePoint.clampedMul(az[0..32].*); | 39 | const p = try Curve.basePoint.clampedMul(az[0..32].*); |
| ... | @@ -51,11 +56,11 @@ pub const Ed25519 = struct { | ... | @@ -51,11 +56,11 @@ pub const Ed25519 = struct { |
| 51 | pub fn sign(msg: []const u8, key_pair: [keypair_length]u8, noise: ?[noise_length]u8) ![signature_length]u8 { | 56 | pub fn sign(msg: []const u8, key_pair: [keypair_length]u8, noise: ?[noise_length]u8) ![signature_length]u8 { |
| 52 | const public_key = key_pair[32..]; | 57 | const public_key = key_pair[32..]; |
| 53 | var az: [Sha512.digest_length]u8 = undefined; | 58 | var az: [Sha512.digest_length]u8 = undefined; |
| 54 | var h = Sha512.init(); | 59 | var h = Sha512.init(.{}); |
| 55 | h.update(key_pair[0..seed_length]); | 60 | h.update(key_pair[0..seed_length]); |
| 56 | h.final(&az); | 61 | h.final(&az); |
| 57 | 62 | ||
| 58 | h = Sha512.init(); | 63 | h = Sha512.init(.{}); |
| 59 | if (noise) |*z| { | 64 | if (noise) |*z| { |
| 60 | h.update(z); | 65 | h.update(z); |
| 61 | } | 66 | } |
| ... | @@ -69,7 +74,7 @@ pub const Ed25519 = struct { | ... | @@ -69,7 +74,7 @@ pub const Ed25519 = struct { |
| 69 | var sig: [signature_length]u8 = undefined; | 74 | var sig: [signature_length]u8 = undefined; |
| 70 | mem.copy(u8, sig[0..32], &r.toBytes()); | 75 | mem.copy(u8, sig[0..32], &r.toBytes()); |
| 71 | mem.copy(u8, sig[32..], public_key); | 76 | mem.copy(u8, sig[32..], public_key); |
| 72 | h = Sha512.init(); | 77 | h = Sha512.init(.{}); |
| 73 | h.update(&sig); | 78 | h.update(&sig); |
| 74 | h.update(msg); | 79 | h.update(msg); |
| 75 | var hram64: [Sha512.digest_length]u8 = undefined; | 80 | var hram64: [Sha512.digest_length]u8 = undefined; |
| ... | @@ -93,7 +98,7 @@ pub const Ed25519 = struct { | ... | @@ -93,7 +98,7 @@ pub const Ed25519 = struct { |
| 93 | const a = try Curve.fromBytes(public_key); | 98 | const a = try Curve.fromBytes(public_key); |
| 94 | try a.rejectIdentity(); | 99 | try a.rejectIdentity(); |
| 95 | 100 | ||
| 96 | var h = Sha512.init(); | 101 | var h = Sha512.init(.{}); |
| 97 | h.update(r); | 102 | h.update(r); |
| 98 | h.update(&public_key); | 103 | h.update(&public_key); |
| 99 | h.update(msg); | 104 | h.update(msg); |
lib/std/crypto/25519/edwards25519.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const fmt = std.fmt; | 7 | const fmt = std.fmt; |
| 3 | 8 |
lib/std/crypto/25519/field.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const readIntLittle = std.mem.readIntLittle; | 7 | const readIntLittle = std.mem.readIntLittle; |
| 3 | const writeIntLittle = std.mem.writeIntLittle; | 8 | const writeIntLittle = std.mem.writeIntLittle; |
lib/std/crypto/25519/ristretto255.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const fmt = std.fmt; | 7 | const fmt = std.fmt; |
| 3 | 8 |
lib/std/crypto/25519/scalar.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
lib/std/crypto/25519/x25519.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const fmt = std.fmt; | 8 | const fmt = std.fmt; |
lib/std/crypto/aes.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Based on Go stdlib implementation | 6 | // Based on Go stdlib implementation |
| 2 | 7 | ||
| 3 | const std = @import("../std.zig"); | 8 | const std = @import("../std.zig"); |
lib/std/crypto/benchmark.zig+25-19| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // zig run benchmark.zig --release-fast --override-lib-dir .. | 6 | // zig run benchmark.zig --release-fast --override-lib-dir .. |
| 2 | 7 | ||
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| ... | @@ -17,20 +22,20 @@ const Crypto = struct { | ... | @@ -17,20 +22,20 @@ const Crypto = struct { |
| 17 | }; | 22 | }; |
| 18 | 23 | ||
| 19 | const hashes = [_]Crypto{ | 24 | const hashes = [_]Crypto{ |
| 20 | Crypto{ .ty = crypto.Md5, .name = "md5" }, | 25 | Crypto{ .ty = crypto.hash.Md5, .name = "md5" }, |
| 21 | Crypto{ .ty = crypto.Sha1, .name = "sha1" }, | 26 | Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" }, |
| 22 | Crypto{ .ty = crypto.Sha256, .name = "sha256" }, | 27 | Crypto{ .ty = crypto.hash.sha2.Sha256, .name = "sha256" }, |
| 23 | Crypto{ .ty = crypto.Sha512, .name = "sha512" }, | 28 | Crypto{ .ty = crypto.hash.sha2.Sha512, .name = "sha512" }, |
| 24 | Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" }, | 29 | Crypto{ .ty = crypto.hash.sha3.Sha3_256, .name = "sha3-256" }, |
| 25 | Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" }, | 30 | Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" }, |
| 26 | Crypto{ .ty = crypto.gimli.Hash, .name = "gimli-hash" }, | 31 | Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" }, |
| 27 | Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" }, | 32 | Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" }, |
| 28 | Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" }, | 33 | Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" }, |
| 29 | Crypto{ .ty = crypto.Blake3, .name = "blake3" }, | 34 | Crypto{ .ty = crypto.hash.Blake3, .name = "blake3" }, |
| 30 | }; | 35 | }; |
| 31 | 36 | ||
| 32 | pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 { | 37 | pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 { |
| 33 | var h = Hash.init(); | 38 | var h = Hash.init(.{}); |
| 34 | 39 | ||
| 35 | var block: [Hash.digest_length]u8 = undefined; | 40 | var block: [Hash.digest_length]u8 = undefined; |
| 36 | prng.random.bytes(block[0..]); | 41 | prng.random.bytes(block[0..]); |
| ... | @@ -50,19 +55,20 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 | ... | @@ -50,19 +55,20 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 |
| 50 | } | 55 | } |
| 51 | 56 | ||
| 52 | const macs = [_]Crypto{ | 57 | const macs = [_]Crypto{ |
| 53 | Crypto{ .ty = crypto.Poly1305, .name = "poly1305" }, | 58 | Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" }, |
| 54 | Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" }, | 59 | Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" }, |
| 55 | Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" }, | 60 | Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" }, |
| 56 | Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" }, | 61 | Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha256, .name = "hmac-sha256" }, |
| 62 | Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha512, .name = "hmac-sha512" }, | ||
| 57 | }; | 63 | }; |
| 58 | 64 | ||
| 59 | pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { | 65 | pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { |
| 60 | std.debug.assert(32 >= Mac.mac_length and 32 >= Mac.minimum_key_length); | 66 | std.debug.assert(64 >= Mac.mac_length and 32 >= Mac.minimum_key_length); |
| 61 | 67 | ||
| 62 | var in: [1 * MiB]u8 = undefined; | 68 | var in: [1 * MiB]u8 = undefined; |
| 63 | prng.random.bytes(in[0..]); | 69 | prng.random.bytes(in[0..]); |
| 64 | 70 | ||
| 65 | var key: [32]u8 = undefined; | 71 | var key: [64]u8 = undefined; |
| 66 | prng.random.bytes(key[0..]); | 72 | prng.random.bytes(key[0..]); |
| 67 | 73 | ||
| 68 | var offset: usize = 0; | 74 | var offset: usize = 0; |
| ... | @@ -79,7 +85,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { | ... | @@ -79,7 +85,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 { |
| 79 | return throughput; | 85 | return throughput; |
| 80 | } | 86 | } |
| 81 | 87 | ||
| 82 | const exchanges = [_]Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }}; | 88 | const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }}; |
| 83 | 89 | ||
| 84 | pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 { | 90 | pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 { |
| 85 | std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length); | 91 | std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length); |
| ... | @@ -106,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c | ... | @@ -106,7 +112,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c |
| 106 | return throughput; | 112 | return throughput; |
| 107 | } | 113 | } |
| 108 | 114 | ||
| 109 | const signatures = [_]Crypto{Crypto{ .ty = crypto.Ed25519, .name = "ed25519" }}; | 115 | const signatures = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }}; |
| 110 | 116 | ||
| 111 | pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { | 117 | pub fn benchmarkSignatures(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 { |
| 112 | var seed: [Signature.seed_length]u8 = undefined; | 118 | var seed: [Signature.seed_length]u8 = undefined; |
lib/std/crypto/blake2.zig+107-78| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const mem = @import("../mem.zig"); | 6 | const mem = @import("../mem.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const debug = @import("../debug.zig"); | 8 | const debug = @import("../debug.zig"); |
| ... | @@ -35,6 +40,7 @@ pub fn Blake2s(comptime out_len: usize) type { | ... | @@ -35,6 +40,7 @@ pub fn Blake2s(comptime out_len: usize) type { |
| 35 | const Self = @This(); | 40 | const Self = @This(); |
| 36 | pub const block_length = 64; | 41 | pub const block_length = 64; |
| 37 | pub const digest_length = out_len / 8; | 42 | pub const digest_length = out_len / 8; |
| 43 | pub const Options = struct { key: ?[]const u8 = null, salt: ?[8]u8 = null, context: ?[8]u8 = null }; | ||
| 38 | 44 | ||
| 39 | const iv = [8]u32{ | 45 | const iv = [8]u32{ |
| 40 | 0x6A09E667, | 46 | 0x6A09E667, |
| ... | @@ -66,42 +72,36 @@ pub fn Blake2s(comptime out_len: usize) type { | ... | @@ -66,42 +72,36 @@ pub fn Blake2s(comptime out_len: usize) type { |
| 66 | buf: [64]u8, | 72 | buf: [64]u8, |
| 67 | buf_len: u8, | 73 | buf_len: u8, |
| 68 | 74 | ||
| 69 | key: []const u8, | 75 | pub fn init(options: Options) Self { |
| 70 | |||
| 71 | pub fn init() Self { | ||
| 72 | return init_keyed(""); | ||
| 73 | } | ||
| 74 | |||
| 75 | pub fn init_keyed(key: []const u8) Self { | ||
| 76 | debug.assert(8 <= out_len and out_len <= 512); | 76 | debug.assert(8 <= out_len and out_len <= 512); |
| 77 | 77 | ||
| 78 | var s: Self = undefined; | 78 | var d: Self = undefined; |
| 79 | s.key = key; | ||
| 80 | s.reset(); | ||
| 81 | return s; | ||
| 82 | } | ||
| 83 | |||
| 84 | pub fn reset(d: *Self) void { | ||
| 85 | mem.copy(u32, d.h[0..], iv[0..]); | 79 | mem.copy(u32, d.h[0..], iv[0..]); |
| 86 | 80 | ||
| 81 | const key_len = if (options.key) |key| key.len else 0; | ||
| 87 | // default parameters | 82 | // default parameters |
| 88 | d.h[0] ^= 0x01010000 ^ @truncate(u32, d.key.len << 8) ^ @intCast(u32, out_len >> 3); | 83 | d.h[0] ^= 0x01010000 ^ @truncate(u32, key_len << 8) ^ @intCast(u32, out_len >> 3); |
| 89 | d.t = 0; | 84 | d.t = 0; |
| 90 | d.buf_len = 0; | 85 | d.buf_len = 0; |
| 91 | 86 | ||
| 92 | if (d.key.len > 0) { | 87 | if (options.salt) |salt| { |
| 93 | mem.set(u8, d.buf[d.key.len..], 0); | 88 | d.h[4] ^= mem.readIntLittle(u32, salt[0..4]); |
| 94 | d.update(d.key); | 89 | d.h[5] ^= mem.readIntLittle(u32, salt[4..8]); |
| 90 | } | ||
| 91 | if (options.context) |context| { | ||
| 92 | d.h[6] ^= mem.readIntLittle(u32, context[0..4]); | ||
| 93 | d.h[7] ^= mem.readIntLittle(u32, context[4..8]); | ||
| 94 | } | ||
| 95 | if (key_len > 0) { | ||
| 96 | mem.set(u8, d.buf[key_len..], 0); | ||
| 97 | d.update(options.key.?); | ||
| 95 | d.buf_len = 64; | 98 | d.buf_len = 64; |
| 96 | } | 99 | } |
| 100 | return d; | ||
| 97 | } | 101 | } |
| 98 | 102 | ||
| 99 | pub fn hash(b: []const u8, out: []u8) void { | 103 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 100 | Self.hash_keyed("", b, out); | 104 | var d = Self.init(options); |
| 101 | } | ||
| 102 | |||
| 103 | pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void { | ||
| 104 | var d = Self.init_keyed(key); | ||
| 105 | d.update(b); | 105 | d.update(b); |
| 106 | d.final(out); | 106 | d.final(out); |
| 107 | } | 107 | } |
| ... | @@ -210,7 +210,7 @@ test "blake2s224 single" { | ... | @@ -210,7 +210,7 @@ test "blake2s224 single" { |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | test "blake2s224 streaming" { | 212 | test "blake2s224 streaming" { |
| 213 | var h = Blake2s224.init(); | 213 | var h = Blake2s224.init(.{}); |
| 214 | var out: [28]u8 = undefined; | 214 | var out: [28]u8 = undefined; |
| 215 | 215 | ||
| 216 | const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; | 216 | const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; |
| ... | @@ -220,12 +220,12 @@ test "blake2s224 streaming" { | ... | @@ -220,12 +220,12 @@ test "blake2s224 streaming" { |
| 220 | 220 | ||
| 221 | const h2 = "0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55"; | 221 | const h2 = "0b033fc226df7abde29f67a05d3dc62cf271ef3dfea4d387407fbd55"; |
| 222 | 222 | ||
| 223 | h.reset(); | 223 | h = Blake2s224.init(.{}); |
| 224 | h.update("abc"); | 224 | h.update("abc"); |
| 225 | h.final(out[0..]); | 225 | h.final(out[0..]); |
| 226 | htest.assertEqual(h2, out[0..]); | 226 | htest.assertEqual(h2, out[0..]); |
| 227 | 227 | ||
| 228 | h.reset(); | 228 | h = Blake2s224.init(.{}); |
| 229 | h.update("a"); | 229 | h.update("a"); |
| 230 | h.update("b"); | 230 | h.update("b"); |
| 231 | h.update("c"); | 231 | h.update("c"); |
| ... | @@ -234,16 +234,29 @@ test "blake2s224 streaming" { | ... | @@ -234,16 +234,29 @@ test "blake2s224 streaming" { |
| 234 | 234 | ||
| 235 | const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01"; | 235 | const h3 = "557381a78facd2b298640f4e32113e58967d61420af1aa939d0cfe01"; |
| 236 | 236 | ||
| 237 | h.reset(); | 237 | h = Blake2s224.init(.{}); |
| 238 | h.update("a" ** 32); | 238 | h.update("a" ** 32); |
| 239 | h.update("b" ** 32); | 239 | h.update("b" ** 32); |
| 240 | h.final(out[0..]); | 240 | h.final(out[0..]); |
| 241 | htest.assertEqual(h3, out[0..]); | 241 | htest.assertEqual(h3, out[0..]); |
| 242 | 242 | ||
| 243 | h.reset(); | 243 | h = Blake2s224.init(.{}); |
| 244 | h.update("a" ** 32 ++ "b" ** 32); | 244 | h.update("a" ** 32 ++ "b" ** 32); |
| 245 | h.final(out[0..]); | 245 | h.final(out[0..]); |
| 246 | htest.assertEqual(h3, out[0..]); | 246 | htest.assertEqual(h3, out[0..]); |
| 247 | |||
| 248 | const h4 = "a4d6a9d253441b80e5dfd60a04db169ffab77aec56a2855c402828c3"; | ||
| 249 | |||
| 250 | h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 }); | ||
| 251 | h.update("a" ** 32); | ||
| 252 | h.update("b" ** 32); | ||
| 253 | h.final(out[0..]); | ||
| 254 | htest.assertEqual(h4, out[0..]); | ||
| 255 | |||
| 256 | h = Blake2s224.init(.{ .context = [_]u8{0x69} ** 8, .salt = [_]u8{0x42} ** 8 }); | ||
| 257 | h.update("a" ** 32 ++ "b" ** 32); | ||
| 258 | h.final(out[0..]); | ||
| 259 | htest.assertEqual(h4, out[0..]); | ||
| 247 | } | 260 | } |
| 248 | 261 | ||
| 249 | test "comptime blake2s224" { | 262 | test "comptime blake2s224" { |
| ... | @@ -256,7 +269,7 @@ test "comptime blake2s224" { | ... | @@ -256,7 +269,7 @@ test "comptime blake2s224" { |
| 256 | 269 | ||
| 257 | htest.assertEqualHash(Blake2s224, h1, block[0..]); | 270 | htest.assertEqualHash(Blake2s224, h1, block[0..]); |
| 258 | 271 | ||
| 259 | var h = Blake2s224.init(); | 272 | var h = Blake2s224.init(.{}); |
| 260 | h.update(&block); | 273 | h.update(&block); |
| 261 | h.final(out[0..]); | 274 | h.final(out[0..]); |
| 262 | 275 | ||
| ... | @@ -279,7 +292,7 @@ test "blake2s256 single" { | ... | @@ -279,7 +292,7 @@ test "blake2s256 single" { |
| 279 | } | 292 | } |
| 280 | 293 | ||
| 281 | test "blake2s256 streaming" { | 294 | test "blake2s256 streaming" { |
| 282 | var h = Blake2s256.init(); | 295 | var h = Blake2s256.init(.{}); |
| 283 | var out: [32]u8 = undefined; | 296 | var out: [32]u8 = undefined; |
| 284 | 297 | ||
| 285 | const h1 = "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"; | 298 | const h1 = "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"; |
| ... | @@ -289,12 +302,12 @@ test "blake2s256 streaming" { | ... | @@ -289,12 +302,12 @@ test "blake2s256 streaming" { |
| 289 | 302 | ||
| 290 | const h2 = "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"; | 303 | const h2 = "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"; |
| 291 | 304 | ||
| 292 | h.reset(); | 305 | h = Blake2s256.init(.{}); |
| 293 | h.update("abc"); | 306 | h.update("abc"); |
| 294 | h.final(out[0..]); | 307 | h.final(out[0..]); |
| 295 | htest.assertEqual(h2, out[0..]); | 308 | htest.assertEqual(h2, out[0..]); |
| 296 | 309 | ||
| 297 | h.reset(); | 310 | h = Blake2s256.init(.{}); |
| 298 | h.update("a"); | 311 | h.update("a"); |
| 299 | h.update("b"); | 312 | h.update("b"); |
| 300 | h.update("c"); | 313 | h.update("c"); |
| ... | @@ -303,13 +316,13 @@ test "blake2s256 streaming" { | ... | @@ -303,13 +316,13 @@ test "blake2s256 streaming" { |
| 303 | 316 | ||
| 304 | const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977"; | 317 | const h3 = "8d8711dade07a6b92b9a3ea1f40bee9b2c53ff3edd2a273dec170b0163568977"; |
| 305 | 318 | ||
| 306 | h.reset(); | 319 | h = Blake2s256.init(.{}); |
| 307 | h.update("a" ** 32); | 320 | h.update("a" ** 32); |
| 308 | h.update("b" ** 32); | 321 | h.update("b" ** 32); |
| 309 | h.final(out[0..]); | 322 | h.final(out[0..]); |
| 310 | htest.assertEqual(h3, out[0..]); | 323 | htest.assertEqual(h3, out[0..]); |
| 311 | 324 | ||
| 312 | h.reset(); | 325 | h = Blake2s256.init(.{}); |
| 313 | h.update("a" ** 32 ++ "b" ** 32); | 326 | h.update("a" ** 32 ++ "b" ** 32); |
| 314 | h.final(out[0..]); | 327 | h.final(out[0..]); |
| 315 | htest.assertEqual(h3, out[0..]); | 328 | htest.assertEqual(h3, out[0..]); |
| ... | @@ -321,16 +334,16 @@ test "blake2s256 keyed" { | ... | @@ -321,16 +334,16 @@ test "blake2s256 keyed" { |
| 321 | const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6"; | 334 | const h1 = "10f918da4d74fab3302e48a5d67d03804b1ec95372a62a0f33b7c9fa28ba1ae6"; |
| 322 | const key = "secret_key"; | 335 | const key = "secret_key"; |
| 323 | 336 | ||
| 324 | Blake2s256.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out); | 337 | Blake2s256.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key }); |
| 325 | htest.assertEqual(h1, out[0..]); | 338 | htest.assertEqual(h1, out[0..]); |
| 326 | 339 | ||
| 327 | var h = Blake2s256.init_keyed(key); | 340 | var h = Blake2s256.init(.{ .key = key }); |
| 328 | h.update("a" ** 64 ++ "b" ** 64); | 341 | h.update("a" ** 64 ++ "b" ** 64); |
| 329 | h.final(out[0..]); | 342 | h.final(out[0..]); |
| 330 | 343 | ||
| 331 | htest.assertEqual(h1, out[0..]); | 344 | htest.assertEqual(h1, out[0..]); |
| 332 | 345 | ||
| 333 | h.reset(); | 346 | h = Blake2s256.init(.{ .key = key }); |
| 334 | h.update("a" ** 64); | 347 | h.update("a" ** 64); |
| 335 | h.update("b" ** 64); | 348 | h.update("b" ** 64); |
| 336 | h.final(out[0..]); | 349 | h.final(out[0..]); |
| ... | @@ -348,7 +361,7 @@ test "comptime blake2s256" { | ... | @@ -348,7 +361,7 @@ test "comptime blake2s256" { |
| 348 | 361 | ||
| 349 | htest.assertEqualHash(Blake2s256, h1, block[0..]); | 362 | htest.assertEqualHash(Blake2s256, h1, block[0..]); |
| 350 | 363 | ||
| 351 | var h = Blake2s256.init(); | 364 | var h = Blake2s256.init(.{}); |
| 352 | h.update(&block); | 365 | h.update(&block); |
| 353 | h.final(out[0..]); | 366 | h.final(out[0..]); |
| 354 | 367 | ||
| ... | @@ -359,6 +372,7 @@ test "comptime blake2s256" { | ... | @@ -359,6 +372,7 @@ test "comptime blake2s256" { |
| 359 | ///////////////////// | 372 | ///////////////////// |
| 360 | // Blake2b | 373 | // Blake2b |
| 361 | 374 | ||
| 375 | pub const Blake2b256 = Blake2b(256); | ||
| 362 | pub const Blake2b384 = Blake2b(384); | 376 | pub const Blake2b384 = Blake2b(384); |
| 363 | pub const Blake2b512 = Blake2b(512); | 377 | pub const Blake2b512 = Blake2b(512); |
| 364 | 378 | ||
| ... | @@ -367,6 +381,7 @@ pub fn Blake2b(comptime out_len: usize) type { | ... | @@ -367,6 +381,7 @@ pub fn Blake2b(comptime out_len: usize) type { |
| 367 | const Self = @This(); | 381 | const Self = @This(); |
| 368 | pub const block_length = 128; | 382 | pub const block_length = 128; |
| 369 | pub const digest_length = out_len / 8; | 383 | pub const digest_length = out_len / 8; |
| 384 | pub const Options = struct { key: ?[]const u8 = null, salt: ?[16]u8 = null, context: ?[16]u8 = null }; | ||
| 370 | 385 | ||
| 371 | const iv = [8]u64{ | 386 | const iv = [8]u64{ |
| 372 | 0x6a09e667f3bcc908, | 387 | 0x6a09e667f3bcc908, |
| ... | @@ -400,42 +415,36 @@ pub fn Blake2b(comptime out_len: usize) type { | ... | @@ -400,42 +415,36 @@ pub fn Blake2b(comptime out_len: usize) type { |
| 400 | buf: [128]u8, | 415 | buf: [128]u8, |
| 401 | buf_len: u8, | 416 | buf_len: u8, |
| 402 | 417 | ||
| 403 | key: []const u8, | 418 | pub fn init(options: Options) Self { |
| 404 | |||
| 405 | pub fn init() Self { | ||
| 406 | return init_keyed(""); | ||
| 407 | } | ||
| 408 | |||
| 409 | pub fn init_keyed(key: []const u8) Self { | ||
| 410 | debug.assert(8 <= out_len and out_len <= 512); | 419 | debug.assert(8 <= out_len and out_len <= 512); |
| 411 | 420 | ||
| 412 | var s: Self = undefined; | 421 | var d: Self = undefined; |
| 413 | s.key = key; | ||
| 414 | s.reset(); | ||
| 415 | return s; | ||
| 416 | } | ||
| 417 | |||
| 418 | pub fn reset(d: *Self) void { | ||
| 419 | mem.copy(u64, d.h[0..], iv[0..]); | 422 | mem.copy(u64, d.h[0..], iv[0..]); |
| 420 | 423 | ||
| 424 | const key_len = if (options.key) |key| key.len else 0; | ||
| 421 | // default parameters | 425 | // default parameters |
| 422 | d.h[0] ^= 0x01010000 ^ (d.key.len << 8) ^ (out_len >> 3); | 426 | d.h[0] ^= 0x01010000 ^ (key_len << 8) ^ (out_len >> 3); |
| 423 | d.t = 0; | 427 | d.t = 0; |
| 424 | d.buf_len = 0; | 428 | d.buf_len = 0; |
| 425 | 429 | ||
| 426 | if (d.key.len > 0) { | 430 | if (options.salt) |salt| { |
| 427 | mem.set(u8, d.buf[d.key.len..], 0); | 431 | d.h[4] ^= mem.readIntLittle(u64, salt[0..8]); |
| 428 | d.update(d.key); | 432 | d.h[5] ^= mem.readIntLittle(u64, salt[8..16]); |
| 433 | } | ||
| 434 | if (options.context) |context| { | ||
| 435 | d.h[6] ^= mem.readIntLittle(u64, context[0..8]); | ||
| 436 | d.h[7] ^= mem.readIntLittle(u64, context[8..16]); | ||
| 437 | } | ||
| 438 | if (key_len > 0) { | ||
| 439 | mem.set(u8, d.buf[key_len..], 0); | ||
| 440 | d.update(options.key.?); | ||
| 429 | d.buf_len = 128; | 441 | d.buf_len = 128; |
| 430 | } | 442 | } |
| 443 | return d; | ||
| 431 | } | 444 | } |
| 432 | 445 | ||
| 433 | pub fn hash(b: []const u8, out: []u8) void { | 446 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 434 | Self.hash_keyed("", b, out); | 447 | var d = Self.init(options); |
| 435 | } | ||
| 436 | |||
| 437 | pub fn hash_keyed(key: []const u8, b: []const u8, out: []u8) void { | ||
| 438 | var d = Self.init_keyed(key); | ||
| 439 | d.update(b); | 448 | d.update(b); |
| 440 | d.final(out); | 449 | d.final(out); |
| 441 | } | 450 | } |
| ... | @@ -542,7 +551,7 @@ test "blake2b384 single" { | ... | @@ -542,7 +551,7 @@ test "blake2b384 single" { |
| 542 | } | 551 | } |
| 543 | 552 | ||
| 544 | test "blake2b384 streaming" { | 553 | test "blake2b384 streaming" { |
| 545 | var h = Blake2b384.init(); | 554 | var h = Blake2b384.init(.{}); |
| 546 | var out: [48]u8 = undefined; | 555 | var out: [48]u8 = undefined; |
| 547 | 556 | ||
| 548 | const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; | 557 | const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; |
| ... | @@ -552,12 +561,12 @@ test "blake2b384 streaming" { | ... | @@ -552,12 +561,12 @@ test "blake2b384 streaming" { |
| 552 | 561 | ||
| 553 | const h2 = "6f56a82c8e7ef526dfe182eb5212f7db9df1317e57815dbda46083fc30f54ee6c66ba83be64b302d7cba6ce15bb556f4"; | 562 | const h2 = "6f56a82c8e7ef526dfe182eb5212f7db9df1317e57815dbda46083fc30f54ee6c66ba83be64b302d7cba6ce15bb556f4"; |
| 554 | 563 | ||
| 555 | h.reset(); | 564 | h = Blake2b384.init(.{}); |
| 556 | h.update("abc"); | 565 | h.update("abc"); |
| 557 | h.final(out[0..]); | 566 | h.final(out[0..]); |
| 558 | htest.assertEqual(h2, out[0..]); | 567 | htest.assertEqual(h2, out[0..]); |
| 559 | 568 | ||
| 560 | h.reset(); | 569 | h = Blake2b384.init(.{}); |
| 561 | h.update("a"); | 570 | h.update("a"); |
| 562 | h.update("b"); | 571 | h.update("b"); |
| 563 | h.update("c"); | 572 | h.update("c"); |
| ... | @@ -566,16 +575,36 @@ test "blake2b384 streaming" { | ... | @@ -566,16 +575,36 @@ test "blake2b384 streaming" { |
| 566 | 575 | ||
| 567 | const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c"; | 576 | const h3 = "b7283f0172fecbbd7eca32ce10d8a6c06b453cb3cf675b33eb4246f0da2bb94a6c0bdd6eec0b5fd71ec4fd51be80bf4c"; |
| 568 | 577 | ||
| 569 | h.reset(); | 578 | h = Blake2b384.init(.{}); |
| 570 | h.update("a" ** 64 ++ "b" ** 64); | 579 | h.update("a" ** 64 ++ "b" ** 64); |
| 571 | h.final(out[0..]); | 580 | h.final(out[0..]); |
| 572 | htest.assertEqual(h3, out[0..]); | 581 | htest.assertEqual(h3, out[0..]); |
| 573 | 582 | ||
| 574 | h.reset(); | 583 | h = Blake2b384.init(.{}); |
| 584 | h.update("a" ** 64); | ||
| 585 | h.update("b" ** 64); | ||
| 586 | h.final(out[0..]); | ||
| 587 | htest.assertEqual(h3, out[0..]); | ||
| 588 | |||
| 589 | h = Blake2b384.init(.{}); | ||
| 575 | h.update("a" ** 64); | 590 | h.update("a" ** 64); |
| 576 | h.update("b" ** 64); | 591 | h.update("b" ** 64); |
| 577 | h.final(out[0..]); | 592 | h.final(out[0..]); |
| 578 | htest.assertEqual(h3, out[0..]); | 593 | htest.assertEqual(h3, out[0..]); |
| 594 | |||
| 595 | const h4 = "934c48fcb197031c71f583d92f98703510805e72142e0b46f5752d1e971bc86c355d556035613ff7a4154b4de09dac5c"; | ||
| 596 | |||
| 597 | h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 }); | ||
| 598 | h.update("a" ** 64); | ||
| 599 | h.update("b" ** 64); | ||
| 600 | h.final(out[0..]); | ||
| 601 | htest.assertEqual(h4, out[0..]); | ||
| 602 | |||
| 603 | h = Blake2b384.init(.{ .context = [_]u8{0x69} ** 16, .salt = [_]u8{0x42} ** 16 }); | ||
| 604 | h.update("a" ** 64); | ||
| 605 | h.update("b" ** 64); | ||
| 606 | h.final(out[0..]); | ||
| 607 | htest.assertEqual(h4, out[0..]); | ||
| 579 | } | 608 | } |
| 580 | 609 | ||
| 581 | test "comptime blake2b384" { | 610 | test "comptime blake2b384" { |
| ... | @@ -588,7 +617,7 @@ test "comptime blake2b384" { | ... | @@ -588,7 +617,7 @@ test "comptime blake2b384" { |
| 588 | 617 | ||
| 589 | htest.assertEqualHash(Blake2b384, h1, block[0..]); | 618 | htest.assertEqualHash(Blake2b384, h1, block[0..]); |
| 590 | 619 | ||
| 591 | var h = Blake2b384.init(); | 620 | var h = Blake2b384.init(.{}); |
| 592 | h.update(&block); | 621 | h.update(&block); |
| 593 | h.final(out[0..]); | 622 | h.final(out[0..]); |
| 594 | 623 | ||
| ... | @@ -611,7 +640,7 @@ test "blake2b512 single" { | ... | @@ -611,7 +640,7 @@ test "blake2b512 single" { |
| 611 | } | 640 | } |
| 612 | 641 | ||
| 613 | test "blake2b512 streaming" { | 642 | test "blake2b512 streaming" { |
| 614 | var h = Blake2b512.init(); | 643 | var h = Blake2b512.init(.{}); |
| 615 | var out: [64]u8 = undefined; | 644 | var out: [64]u8 = undefined; |
| 616 | 645 | ||
| 617 | const h1 = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"; | 646 | const h1 = "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"; |
| ... | @@ -621,12 +650,12 @@ test "blake2b512 streaming" { | ... | @@ -621,12 +650,12 @@ test "blake2b512 streaming" { |
| 621 | 650 | ||
| 622 | const h2 = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"; | 651 | const h2 = "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"; |
| 623 | 652 | ||
| 624 | h.reset(); | 653 | h = Blake2b512.init(.{}); |
| 625 | h.update("abc"); | 654 | h.update("abc"); |
| 626 | h.final(out[0..]); | 655 | h.final(out[0..]); |
| 627 | htest.assertEqual(h2, out[0..]); | 656 | htest.assertEqual(h2, out[0..]); |
| 628 | 657 | ||
| 629 | h.reset(); | 658 | h = Blake2b512.init(.{}); |
| 630 | h.update("a"); | 659 | h.update("a"); |
| 631 | h.update("b"); | 660 | h.update("b"); |
| 632 | h.update("c"); | 661 | h.update("c"); |
| ... | @@ -635,12 +664,12 @@ test "blake2b512 streaming" { | ... | @@ -635,12 +664,12 @@ test "blake2b512 streaming" { |
| 635 | 664 | ||
| 636 | const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920"; | 665 | const h3 = "049980af04d6a2cf16b4b49793c3ed7e40732073788806f2c989ebe9547bda0541d63abe298ec8955d08af48ae731f2e8a0bd6d201655a5473b4aa79d211b920"; |
| 637 | 666 | ||
| 638 | h.reset(); | 667 | h = Blake2b512.init(.{}); |
| 639 | h.update("a" ** 64 ++ "b" ** 64); | 668 | h.update("a" ** 64 ++ "b" ** 64); |
| 640 | h.final(out[0..]); | 669 | h.final(out[0..]); |
| 641 | htest.assertEqual(h3, out[0..]); | 670 | htest.assertEqual(h3, out[0..]); |
| 642 | 671 | ||
| 643 | h.reset(); | 672 | h = Blake2b512.init(.{}); |
| 644 | h.update("a" ** 64); | 673 | h.update("a" ** 64); |
| 645 | h.update("b" ** 64); | 674 | h.update("b" ** 64); |
| 646 | h.final(out[0..]); | 675 | h.final(out[0..]); |
| ... | @@ -653,16 +682,16 @@ test "blake2b512 keyed" { | ... | @@ -653,16 +682,16 @@ test "blake2b512 keyed" { |
| 653 | const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d"; | 682 | const h1 = "8a978060ccaf582f388f37454363071ac9a67e3a704585fd879fb8a419a447e389c7c6de790faa20a7a7dccf197de736bc5b40b98a930b36df5bee7555750c4d"; |
| 654 | const key = "secret_key"; | 683 | const key = "secret_key"; |
| 655 | 684 | ||
| 656 | Blake2b512.hash_keyed(key, "a" ** 64 ++ "b" ** 64, &out); | 685 | Blake2b512.hash("a" ** 64 ++ "b" ** 64, &out, .{ .key = key }); |
| 657 | htest.assertEqual(h1, out[0..]); | 686 | htest.assertEqual(h1, out[0..]); |
| 658 | 687 | ||
| 659 | var h = Blake2b512.init_keyed(key); | 688 | var h = Blake2b512.init(.{ .key = key }); |
| 660 | h.update("a" ** 64 ++ "b" ** 64); | 689 | h.update("a" ** 64 ++ "b" ** 64); |
| 661 | h.final(out[0..]); | 690 | h.final(out[0..]); |
| 662 | 691 | ||
| 663 | htest.assertEqual(h1, out[0..]); | 692 | htest.assertEqual(h1, out[0..]); |
| 664 | 693 | ||
| 665 | h.reset(); | 694 | h = Blake2b512.init(.{ .key = key }); |
| 666 | h.update("a" ** 64); | 695 | h.update("a" ** 64); |
| 667 | h.update("b" ** 64); | 696 | h.update("b" ** 64); |
| 668 | h.final(out[0..]); | 697 | h.final(out[0..]); |
| ... | @@ -680,7 +709,7 @@ test "comptime blake2b512" { | ... | @@ -680,7 +709,7 @@ test "comptime blake2b512" { |
| 680 | 709 | ||
| 681 | htest.assertEqualHash(Blake2b512, h1, block[0..]); | 710 | htest.assertEqualHash(Blake2b512, h1, block[0..]); |
| 682 | 711 | ||
| 683 | var h = Blake2b512.init(); | 712 | var h = Blake2b512.init(.{}); |
| 684 | h.update(&block); | 713 | h.update(&block); |
| 685 | h.final(out[0..]); | 714 | h.final(out[0..]); |
| 686 | 715 |
lib/std/crypto/blake3.zig+29-23| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Translated from BLAKE3 reference implementation. | 6 | // Translated from BLAKE3 reference implementation. |
| 2 | // Source: https://github.com/BLAKE3-team/BLAKE3 | 7 | // Source: https://github.com/BLAKE3-team/BLAKE3 |
| 3 | 8 | ||
| ... | @@ -274,6 +279,9 @@ fn parent_cv( | ... | @@ -274,6 +279,9 @@ fn parent_cv( |
| 274 | 279 | ||
| 275 | /// An incremental hasher that can accept any number of writes. | 280 | /// An incremental hasher that can accept any number of writes. |
| 276 | pub const Blake3 = struct { | 281 | pub const Blake3 = struct { |
| 282 | pub const Options = struct { key: ?[KEY_LEN]u8 = null }; | ||
| 283 | pub const KdfOptions = struct {}; | ||
| 284 | |||
| 277 | chunk_state: ChunkState, | 285 | chunk_state: ChunkState, |
| 278 | key: [8]u32, | 286 | key: [8]u32, |
| 279 | cv_stack: [54][8]u32 = undefined, // Space for 54 subtree chaining values: | 287 | cv_stack: [54][8]u32 = undefined, // Space for 54 subtree chaining values: |
| ... | @@ -291,21 +299,20 @@ pub const Blake3 = struct { | ... | @@ -291,21 +299,20 @@ pub const Blake3 = struct { |
| 291 | }; | 299 | }; |
| 292 | } | 300 | } |
| 293 | 301 | ||
| 294 | /// Construct a new `Blake3` for the regular hash function. | 302 | /// Construct a new `Blake3` for the hash function, with an optional key |
| 295 | pub fn init() Blake3 { | 303 | pub fn init(options: Options) Blake3 { |
| 296 | return Blake3.init_internal(IV, 0); | 304 | if (options.key) |key| { |
| 297 | } | 305 | var key_words: [8]u32 = undefined; |
| 298 | 306 | words_from_little_endian_bytes(key_words[0..], key[0..]); | |
| 299 | /// Construct a new `Blake3` for the keyed hash function. | 307 | return Blake3.init_internal(key_words, KEYED_HASH); |
| 300 | pub fn init_keyed(key: [KEY_LEN]u8) Blake3 { | 308 | } else { |
| 301 | var key_words: [8]u32 = undefined; | 309 | return Blake3.init_internal(IV, 0); |
| 302 | words_from_little_endian_bytes(key_words[0..], key[0..]); | 310 | } |
| 303 | return Blake3.init_internal(key_words, KEYED_HASH); | ||
| 304 | } | 311 | } |
| 305 | 312 | ||
| 306 | /// Construct a new `Blake3` for the key derivation function. The context | 313 | /// Construct a new `Blake3` for the key derivation function. The context |
| 307 | /// string should be hardcoded, globally unique, and application-specific. | 314 | /// string should be hardcoded, globally unique, and application-specific. |
| 308 | pub fn init_derive_key(context: []const u8) Blake3 { | 315 | pub fn initKdf(context: []const u8, options: KdfOptions) Blake3 { |
| 309 | var context_hasher = Blake3.init_internal(IV, DERIVE_KEY_CONTEXT); | 316 | var context_hasher = Blake3.init_internal(IV, DERIVE_KEY_CONTEXT); |
| 310 | context_hasher.update(context); | 317 | context_hasher.update(context); |
| 311 | var context_key: [KEY_LEN]u8 = undefined; | 318 | var context_key: [KEY_LEN]u8 = undefined; |
| ... | @@ -315,18 +322,12 @@ pub const Blake3 = struct { | ... | @@ -315,18 +322,12 @@ pub const Blake3 = struct { |
| 315 | return Blake3.init_internal(context_key_words, DERIVE_KEY_MATERIAL); | 322 | return Blake3.init_internal(context_key_words, DERIVE_KEY_MATERIAL); |
| 316 | } | 323 | } |
| 317 | 324 | ||
| 318 | pub fn hash(in: []const u8, out: []u8) void { | 325 | pub fn hash(in: []const u8, out: []u8, options: Options) void { |
| 319 | var hasher = Blake3.init(); | 326 | var hasher = Blake3.init(options); |
| 320 | hasher.update(in); | 327 | hasher.update(in); |
| 321 | hasher.final(out); | 328 | hasher.final(out); |
| 322 | } | 329 | } |
| 323 | 330 | ||
| 324 | /// Reset the `Blake3` to its initial state. | ||
| 325 | pub fn reset(self: *Blake3) void { | ||
| 326 | self.chunk_state = ChunkState.init(self.key, 0, self.flags); | ||
| 327 | self.cv_stack_len = 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | fn push_cv(self: *Blake3, cv: [8]u32) void { | 331 | fn push_cv(self: *Blake3, cv: [8]u32) void { |
| 331 | self.cv_stack[self.cv_stack_len] = cv; | 332 | self.cv_stack[self.cv_stack_len] = cv; |
| 332 | self.cv_stack_len += 1; | 333 | self.cv_stack_len += 1; |
| ... | @@ -561,6 +562,9 @@ const reference_test = ReferenceTest{ | ... | @@ -561,6 +562,9 @@ const reference_test = ReferenceTest{ |
| 561 | }; | 562 | }; |
| 562 | 563 | ||
| 563 | fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { | 564 | fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { |
| 565 | // Save initial state | ||
| 566 | const initial_state = hasher.*; | ||
| 567 | |||
| 564 | // Setup input pattern | 568 | // Setup input pattern |
| 565 | var input_pattern: [251]u8 = undefined; | 569 | var input_pattern: [251]u8 = undefined; |
| 566 | for (input_pattern) |*e, i| e.* = @truncate(u8, i); | 570 | for (input_pattern) |*e, i| e.* = @truncate(u8, i); |
| ... | @@ -576,18 +580,20 @@ fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { | ... | @@ -576,18 +580,20 @@ fn test_blake3(hasher: *Blake3, input_len: usize, expected_hex: [262]u8) void { |
| 576 | // Read final hash value | 580 | // Read final hash value |
| 577 | var actual_bytes: [expected_hex.len / 2]u8 = undefined; | 581 | var actual_bytes: [expected_hex.len / 2]u8 = undefined; |
| 578 | hasher.final(actual_bytes[0..]); | 582 | hasher.final(actual_bytes[0..]); |
| 579 | hasher.reset(); | ||
| 580 | 583 | ||
| 581 | // Compare to expected value | 584 | // Compare to expected value |
| 582 | var expected_bytes: [expected_hex.len / 2]u8 = undefined; | 585 | var expected_bytes: [expected_hex.len / 2]u8 = undefined; |
| 583 | fmt.hexToBytes(expected_bytes[0..], expected_hex[0..]) catch unreachable; | 586 | fmt.hexToBytes(expected_bytes[0..], expected_hex[0..]) catch unreachable; |
| 584 | testing.expectEqual(actual_bytes, expected_bytes); | 587 | testing.expectEqual(actual_bytes, expected_bytes); |
| 588 | |||
| 589 | // Restore initial state | ||
| 590 | hasher.* = initial_state; | ||
| 585 | } | 591 | } |
| 586 | 592 | ||
| 587 | test "BLAKE3 reference test cases" { | 593 | test "BLAKE3 reference test cases" { |
| 588 | var hash = &Blake3.init(); | 594 | var hash = &Blake3.init(.{}); |
| 589 | var keyed_hash = &Blake3.init_keyed(reference_test.key.*); | 595 | var keyed_hash = &Blake3.init(.{ .key = reference_test.key.* }); |
| 590 | var derive_key = &Blake3.init_derive_key(reference_test.context_string); | 596 | var derive_key = &Blake3.initKdf(reference_test.context_string, .{}); |
| 591 | 597 | ||
| 592 | for (reference_test.cases) |t| { | 598 | for (reference_test.cases) |t| { |
| 593 | test_blake3(hash, t.input_len, t.hash.*); | 599 | test_blake3(hash, t.input_len, t.hash.*); |
lib/std/crypto/chacha20.zig+79-68| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Based on public domain Supercop by Daniel J. Bernstein | 6 | // Based on public domain Supercop by Daniel J. Bernstein |
| 2 | 7 | ||
| 3 | const std = @import("../std.zig"); | 8 | const std = @import("../std.zig"); |
| ... | @@ -7,7 +12,7 @@ const assert = std.debug.assert; | ... | @@ -7,7 +12,7 @@ const assert = std.debug.assert; |
| 7 | const testing = std.testing; | 12 | const testing = std.testing; |
| 8 | const builtin = @import("builtin"); | 13 | const builtin = @import("builtin"); |
| 9 | const maxInt = std.math.maxInt; | 14 | const maxInt = std.math.maxInt; |
| 10 | const Poly1305 = std.crypto.Poly1305; | 15 | const Poly1305 = std.crypto.onetimeauth.Poly1305; |
| 11 | 16 | ||
| 12 | const QuarterRound = struct { | 17 | const QuarterRound = struct { |
| 13 | a: usize, | 18 | a: usize, |
| ... | @@ -132,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 { | ... | @@ -132,56 +137,60 @@ fn keyToWords(key: [32]u8) [8]u32 { |
| 132 | /// | 137 | /// |
| 133 | /// ChaCha20 is self-reversing. To decrypt just run the cipher with the same | 138 | /// ChaCha20 is self-reversing. To decrypt just run the cipher with the same |
| 134 | /// counter, nonce, and key. | 139 | /// counter, nonce, and key. |
| 135 | pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void { | 140 | pub const ChaCha20IETF = struct { |
| 136 | assert(in.len >= out.len); | 141 | pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void { |
| 137 | assert((in.len >> 6) + counter <= maxInt(u32)); | 142 | assert(in.len >= out.len); |
| 138 | 143 | assert((in.len >> 6) + counter <= maxInt(u32)); | |
| 139 | var c: [4]u32 = undefined; | 144 | |
| 140 | c[0] = counter; | 145 | var c: [4]u32 = undefined; |
| 141 | c[1] = mem.readIntLittle(u32, nonce[0..4]); | 146 | c[0] = counter; |
| 142 | c[2] = mem.readIntLittle(u32, nonce[4..8]); | 147 | c[1] = mem.readIntLittle(u32, nonce[0..4]); |
| 143 | c[3] = mem.readIntLittle(u32, nonce[8..12]); | 148 | c[2] = mem.readIntLittle(u32, nonce[4..8]); |
| 144 | chaCha20_internal(out, in, keyToWords(key), c); | 149 | c[3] = mem.readIntLittle(u32, nonce[8..12]); |
| 145 | } | 150 | chaCha20_internal(out, in, keyToWords(key), c); |
| 151 | } | ||
| 152 | }; | ||
| 146 | 153 | ||
| 147 | /// This is the original ChaCha20 before RFC 7539, which recommends using the | 154 | /// This is the original ChaCha20 before RFC 7539, which recommends using the |
| 148 | /// orgininal version on applications such as disk or file encryption that might | 155 | /// orgininal version on applications such as disk or file encryption that might |
| 149 | /// exceed the 256 GiB limit of the 96-bit nonce version. | 156 | /// exceed the 256 GiB limit of the 96-bit nonce version. |
| 150 | pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void { | 157 | pub const ChaCha20With64BitNonce = struct { |
| 151 | assert(in.len >= out.len); | 158 | pub fn xor(out: []u8, in: []const u8, counter: u64, key: [32]u8, nonce: [8]u8) void { |
| 152 | assert(counter +% (in.len >> 6) >= counter); | 159 | assert(in.len >= out.len); |
| 153 | 160 | assert(counter +% (in.len >> 6) >= counter); | |
| 154 | var cursor: usize = 0; | 161 | |
| 155 | const k = keyToWords(key); | 162 | var cursor: usize = 0; |
| 156 | var c: [4]u32 = undefined; | 163 | const k = keyToWords(key); |
| 157 | c[0] = @truncate(u32, counter); | 164 | var c: [4]u32 = undefined; |
| 158 | c[1] = @truncate(u32, counter >> 32); | 165 | c[0] = @truncate(u32, counter); |
| 159 | c[2] = mem.readIntLittle(u32, nonce[0..4]); | 166 | c[1] = @truncate(u32, counter >> 32); |
| 160 | c[3] = mem.readIntLittle(u32, nonce[4..8]); | 167 | c[2] = mem.readIntLittle(u32, nonce[0..4]); |
| 161 | 168 | c[3] = mem.readIntLittle(u32, nonce[4..8]); | |
| 162 | const block_size = (1 << 6); | 169 | |
| 163 | // The full block size is greater than the address space on a 32bit machine | 170 | const block_size = (1 << 6); |
| 164 | const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize); | 171 | // The full block size is greater than the address space on a 32bit machine |
| 165 | 172 | const big_block = if (@sizeOf(usize) > 4) (block_size << 32) else maxInt(usize); | |
| 166 | // first partial big block | 173 | |
| 167 | if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) { | 174 | // first partial big block |
| 168 | chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c); | 175 | if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) { |
| 169 | cursor = big_block - cursor; | 176 | chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c); |
| 170 | c[1] += 1; | 177 | cursor = big_block - cursor; |
| 171 | if (comptime @sizeOf(usize) > 4) { | 178 | c[1] += 1; |
| 172 | // A big block is giant: 256 GiB, but we can avoid this limitation | 179 | if (comptime @sizeOf(usize) > 4) { |
| 173 | var remaining_blocks: u32 = @intCast(u32, (in.len / big_block)); | 180 | // A big block is giant: 256 GiB, but we can avoid this limitation |
| 174 | var i: u32 = 0; | 181 | var remaining_blocks: u32 = @intCast(u32, (in.len / big_block)); |
| 175 | while (remaining_blocks > 0) : (remaining_blocks -= 1) { | 182 | var i: u32 = 0; |
| 176 | chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c); | 183 | while (remaining_blocks > 0) : (remaining_blocks -= 1) { |
| 177 | c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this. | 184 | chaCha20_internal(out[cursor .. cursor + big_block], in[cursor .. cursor + big_block], k, c); |
| 178 | cursor += big_block; | 185 | c[1] += 1; // upper 32-bit of counter, generic chaCha20_internal() doesn't know about this. |
| 186 | cursor += big_block; | ||
| 187 | } | ||
| 179 | } | 188 | } |
| 180 | } | 189 | } |
| 181 | } | ||
| 182 | 190 | ||
| 183 | chaCha20_internal(out[cursor..], in[cursor..], k, c); | 191 | chaCha20_internal(out[cursor..], in[cursor..], k, c); |
| 184 | } | 192 | } |
| 193 | }; | ||
| 185 | 194 | ||
| 186 | // https://tools.ietf.org/html/rfc7539#section-2.4.2 | 195 | // https://tools.ietf.org/html/rfc7539#section-2.4.2 |
| 187 | test "crypto.chacha20 test vector sunscreen" { | 196 | test "crypto.chacha20 test vector sunscreen" { |
| ... | @@ -216,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" { | ... | @@ -216,12 +225,12 @@ test "crypto.chacha20 test vector sunscreen" { |
| 216 | 0, 0, 0, 0, | 225 | 0, 0, 0, 0, |
| 217 | }; | 226 | }; |
| 218 | 227 | ||
| 219 | chaCha20IETF(result[0..], input[0..], 1, key, nonce); | 228 | ChaCha20IETF.xor(result[0..], input[0..], 1, key, nonce); |
| 220 | testing.expectEqualSlices(u8, &expected_result, &result); | 229 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 221 | 230 | ||
| 222 | // Chacha20 is self-reversing. | 231 | // Chacha20 is self-reversing. |
| 223 | var plaintext: [114]u8 = undefined; | 232 | var plaintext: [114]u8 = undefined; |
| 224 | chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce); | 233 | ChaCha20IETF.xor(plaintext[0..], result[0..], 1, key, nonce); |
| 225 | testing.expect(mem.order(u8, input, &plaintext) == .eq); | 234 | testing.expect(mem.order(u8, input, &plaintext) == .eq); |
| 226 | } | 235 | } |
| 227 | 236 | ||
| ... | @@ -256,7 +265,7 @@ test "crypto.chacha20 test vector 1" { | ... | @@ -256,7 +265,7 @@ test "crypto.chacha20 test vector 1" { |
| 256 | }; | 265 | }; |
| 257 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; | 266 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 258 | 267 | ||
| 259 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 268 | ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); |
| 260 | testing.expectEqualSlices(u8, &expected_result, &result); | 269 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 261 | } | 270 | } |
| 262 | 271 | ||
| ... | @@ -290,7 +299,7 @@ test "crypto.chacha20 test vector 2" { | ... | @@ -290,7 +299,7 @@ test "crypto.chacha20 test vector 2" { |
| 290 | }; | 299 | }; |
| 291 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; | 300 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 292 | 301 | ||
| 293 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 302 | ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); |
| 294 | testing.expectEqualSlices(u8, &expected_result, &result); | 303 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 295 | } | 304 | } |
| 296 | 305 | ||
| ... | @@ -324,7 +333,7 @@ test "crypto.chacha20 test vector 3" { | ... | @@ -324,7 +333,7 @@ test "crypto.chacha20 test vector 3" { |
| 324 | }; | 333 | }; |
| 325 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 }; | 334 | const nonce = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 1 }; |
| 326 | 335 | ||
| 327 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 336 | ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); |
| 328 | testing.expectEqualSlices(u8, &expected_result, &result); | 337 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 329 | } | 338 | } |
| 330 | 339 | ||
| ... | @@ -358,7 +367,7 @@ test "crypto.chacha20 test vector 4" { | ... | @@ -358,7 +367,7 @@ test "crypto.chacha20 test vector 4" { |
| 358 | }; | 367 | }; |
| 359 | const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 }; | 368 | const nonce = [_]u8{ 1, 0, 0, 0, 0, 0, 0, 0 }; |
| 360 | 369 | ||
| 361 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 370 | ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); |
| 362 | testing.expectEqualSlices(u8, &expected_result, &result); | 371 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 363 | } | 372 | } |
| 364 | 373 | ||
| ... | @@ -430,21 +439,21 @@ test "crypto.chacha20 test vector 5" { | ... | @@ -430,21 +439,21 @@ test "crypto.chacha20 test vector 5" { |
| 430 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | 439 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 431 | }; | 440 | }; |
| 432 | 441 | ||
| 433 | chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce); | 442 | ChaCha20With64BitNonce.xor(result[0..], input[0..], 0, key, nonce); |
| 434 | testing.expectEqualSlices(u8, &expected_result, &result); | 443 | testing.expectEqualSlices(u8, &expected_result, &result); |
| 435 | } | 444 | } |
| 436 | 445 | ||
| 437 | pub const chacha20poly1305_tag_size = 16; | 446 | pub const chacha20poly1305_tag_size = 16; |
| 438 | 447 | ||
| 439 | pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { | 448 | fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { |
| 440 | assert(ciphertext.len >= plaintext.len); | 449 | assert(ciphertext.len >= plaintext.len); |
| 441 | 450 | ||
| 442 | // derive poly1305 key | 451 | // derive poly1305 key |
| 443 | var polyKey = [_]u8{0} ** 32; | 452 | var polyKey = [_]u8{0} ** 32; |
| 444 | chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce); | 453 | ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce); |
| 445 | 454 | ||
| 446 | // encrypt plaintext | 455 | // encrypt plaintext |
| 447 | chaCha20IETF(ciphertext[0..plaintext.len], plaintext, 1, key, nonce); | 456 | ChaCha20IETF.xor(ciphertext[0..plaintext.len], plaintext, 1, key, nonce); |
| 448 | 457 | ||
| 449 | // construct mac | 458 | // construct mac |
| 450 | var mac = Poly1305.init(polyKey[0..]); | 459 | var mac = Poly1305.init(polyKey[0..]); |
| ... | @@ -467,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta | ... | @@ -467,18 +476,18 @@ pub fn chacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_ta |
| 467 | mac.final(tag); | 476 | mac.final(tag); |
| 468 | } | 477 | } |
| 469 | 478 | ||
| 470 | pub fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { | 479 | fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) void { |
| 471 | return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce); | 480 | return chacha20poly1305SealDetached(ciphertextAndTag[0..plaintext.len], ciphertextAndTag[plaintext.len..][0..chacha20poly1305_tag_size], plaintext, data, key, nonce); |
| 472 | } | 481 | } |
| 473 | 482 | ||
| 474 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. | 483 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. |
| 475 | pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { | 484 | fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { |
| 476 | // split ciphertext and tag | 485 | // split ciphertext and tag |
| 477 | assert(dst.len >= ciphertext.len); | 486 | assert(dst.len >= ciphertext.len); |
| 478 | 487 | ||
| 479 | // derive poly1305 key | 488 | // derive poly1305 key |
| 480 | var polyKey = [_]u8{0} ** 32; | 489 | var polyKey = [_]u8{0} ** 32; |
| 481 | chaCha20IETF(polyKey[0..], polyKey[0..], 0, key, nonce); | 490 | ChaCha20IETF.xor(polyKey[0..], polyKey[0..], 0, key, nonce); |
| 482 | 491 | ||
| 483 | // construct mac | 492 | // construct mac |
| 484 | var mac = Poly1305.init(polyKey[0..]); | 493 | var mac = Poly1305.init(polyKey[0..]); |
| ... | @@ -514,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con | ... | @@ -514,11 +523,11 @@ pub fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *con |
| 514 | } | 523 | } |
| 515 | 524 | ||
| 516 | // decrypt ciphertext | 525 | // decrypt ciphertext |
| 517 | chaCha20IETF(dst[0..ciphertext.len], ciphertext, 1, key, nonce); | 526 | ChaCha20IETF.xor(dst[0..ciphertext.len], ciphertext, 1, key, nonce); |
| 518 | } | 527 | } |
| 519 | 528 | ||
| 520 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. | 529 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. |
| 521 | pub fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { | 530 | fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { |
| 522 | if (ciphertextAndTag.len < chacha20poly1305_tag_size) { | 531 | if (ciphertextAndTag.len < chacha20poly1305_tag_size) { |
| 523 | return error.InvalidMessage; | 532 | return error.InvalidMessage; |
| 524 | } | 533 | } |
| ... | @@ -557,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } { | ... | @@ -557,31 +566,33 @@ fn extend(key: [32]u8, nonce: [24]u8) struct { key: [32]u8, nonce: [12]u8 } { |
| 557 | }; | 566 | }; |
| 558 | } | 567 | } |
| 559 | 568 | ||
| 560 | pub fn xChaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void { | 569 | pub const XChaCha20IETF = struct { |
| 561 | const extended = extend(key, nonce); | 570 | pub fn xor(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [24]u8) void { |
| 562 | chaCha20IETF(out, in, counter, extended.key, extended.nonce); | 571 | const extended = extend(key, nonce); |
| 563 | } | 572 | ChaCha20IETF.xor(out, in, counter, extended.key, extended.nonce); |
| 573 | } | ||
| 574 | }; | ||
| 564 | 575 | ||
| 565 | pub const xchacha20poly1305_tag_size = 16; | 576 | pub const xchacha20poly1305_tag_size = 16; |
| 566 | 577 | ||
| 567 | pub fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { | 578 | fn xchacha20poly1305SealDetached(ciphertext: []u8, tag: *[chacha20poly1305_tag_size]u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { |
| 568 | const extended = extend(key, nonce); | 579 | const extended = extend(key, nonce); |
| 569 | return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce); | 580 | return chacha20poly1305SealDetached(ciphertext, tag, plaintext, data, extended.key, extended.nonce); |
| 570 | } | 581 | } |
| 571 | 582 | ||
| 572 | pub fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { | 583 | fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) void { |
| 573 | const extended = extend(key, nonce); | 584 | const extended = extend(key, nonce); |
| 574 | return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce); | 585 | return chacha20poly1305Seal(ciphertextAndTag, plaintext, data, extended.key, extended.nonce); |
| 575 | } | 586 | } |
| 576 | 587 | ||
| 577 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. | 588 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. |
| 578 | pub fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { | 589 | fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_size]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { |
| 579 | const extended = extend(key, nonce); | 590 | const extended = extend(key, nonce); |
| 580 | return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); | 591 | return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); |
| 581 | } | 592 | } |
| 582 | 593 | ||
| 583 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. | 594 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. |
| 584 | pub fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { | 595 | fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { |
| 585 | const extended = extend(key, nonce); | 596 | const extended = extend(key, nonce); |
| 586 | return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); | 597 | return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); |
| 587 | } | 598 | } |
| ... | @@ -709,7 +720,7 @@ test "crypto.xchacha20" { | ... | @@ -709,7 +720,7 @@ test "crypto.xchacha20" { |
| 709 | const input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; | 720 | const input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; |
| 710 | { | 721 | { |
| 711 | var ciphertext: [input.len]u8 = undefined; | 722 | var ciphertext: [input.len]u8 = undefined; |
| 712 | xChaCha20IETF(ciphertext[0..], input[0..], 0, key, nonce); | 723 | XChaCha20IETF.xor(ciphertext[0..], input[0..], 0, key, nonce); |
| 713 | var buf: [2 * ciphertext.len]u8 = undefined; | 724 | var buf: [2 * ciphertext.len]u8 = undefined; |
| 714 | testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D"); | 725 | testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{X}", .{ciphertext}), "E0A1BCF939654AFDBDC1746EC49832647C19D891F0D1A81FC0C1703B4514BDEA584B512F6908C2C5E9DD18D5CBC1805DE5803FE3B9CA5F193FB8359E91FAB0C3BB40309A292EB1CF49685C65C4A3ADF4F11DB0CD2B6B67FBC174BC2E860E8F769FD3565BBFAD1C845E05A0FED9BE167C240D"); |
| 715 | } | 726 | } |
lib/std/crypto/gimli.zig+13-7| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Gimli is a 384-bit permutation designed to achieve high security with high | 6 | // Gimli is a 384-bit permutation designed to achieve high security with high |
| 2 | // performance across a broad range of platforms, including 64-bit Intel/AMD | 7 | // performance across a broad range of platforms, including 64-bit Intel/AMD |
| 3 | // server CPUs, 64-bit and 32-bit ARM smartphone CPUs, 32-bit ARM | 8 | // server CPUs, 64-bit and 32-bit ARM smartphone CPUs, 32-bit ARM |
| ... | @@ -104,13 +109,14 @@ pub const Hash = struct { | ... | @@ -104,13 +109,14 @@ pub const Hash = struct { |
| 104 | state: State, | 109 | state: State, |
| 105 | buf_off: usize, | 110 | buf_off: usize, |
| 106 | 111 | ||
| 112 | pub const block_length = State.RATE; | ||
| 113 | pub const Options = struct {}; | ||
| 114 | |||
| 107 | const Self = @This(); | 115 | const Self = @This(); |
| 108 | 116 | ||
| 109 | pub fn init() Self { | 117 | pub fn init(options: Options) Self { |
| 110 | return Self{ | 118 | return Self{ |
| 111 | .state = State{ | 119 | .state = State{ .data = [_]u32{0} ** (State.BLOCKBYTES / 4) }, |
| 112 | .data = [_]u32{0} ** (State.BLOCKBYTES / 4), | ||
| 113 | }, | ||
| 114 | .buf_off = 0, | 120 | .buf_off = 0, |
| 115 | }; | 121 | }; |
| 116 | } | 122 | } |
| ... | @@ -155,8 +161,8 @@ pub const Hash = struct { | ... | @@ -155,8 +161,8 @@ pub const Hash = struct { |
| 155 | } | 161 | } |
| 156 | }; | 162 | }; |
| 157 | 163 | ||
| 158 | pub fn hash(out: []u8, in: []const u8) void { | 164 | pub fn hash(out: []u8, in: []const u8, options: Hash.Options) void { |
| 159 | var st = Hash.init(); | 165 | var st = Hash.init(options); |
| 160 | st.update(in); | 166 | st.update(in); |
| 161 | st.final(out); | 167 | st.final(out); |
| 162 | } | 168 | } |
| ... | @@ -169,7 +175,7 @@ test "hash" { | ... | @@ -169,7 +175,7 @@ test "hash" { |
| 169 | var msg: [58 / 2]u8 = undefined; | 175 | var msg: [58 / 2]u8 = undefined; |
| 170 | try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C"); | 176 | try std.fmt.hexToBytes(&msg, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C"); |
| 171 | var md: [32]u8 = undefined; | 177 | var md: [32]u8 = undefined; |
| 172 | hash(&md, &msg); | 178 | hash(&md, &msg, .{}); |
| 173 | htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", &md); | 179 | htest.assertEqual("1C9A03DC6A5DDC5444CFC6F4B154CFF5CF081633B2CEA4D7D0AE7CCFED5AAA44", &md); |
| 174 | } | 180 | } |
| 175 | 181 |
lib/std/crypto/hmac.zig+27-13| ... | @@ -1,12 +1,26 @@ | ... | @@ -1,12 +1,26 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const crypto = std.crypto; | 7 | const crypto = std.crypto; |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
| 4 | const mem = std.mem; | 9 | const mem = std.mem; |
| 5 | 10 | ||
| 6 | pub const HmacMd5 = Hmac(crypto.Md5); | 11 | pub const HmacMd5 = Hmac(crypto.hash.Md5); |
| 7 | pub const HmacSha1 = Hmac(crypto.Sha1); | 12 | pub const HmacSha1 = Hmac(crypto.hash.Sha1); |
| 8 | pub const HmacSha256 = Hmac(crypto.Sha256); | 13 | |
| 9 | pub const HmacBlake2s256 = Hmac(crypto.Blake2s256); | 14 | pub const sha2 = struct { |
| 15 | pub const HmacSha224 = Hmac(crypto.hash.sha2.Sha224); | ||
| 16 | pub const HmacSha256 = Hmac(crypto.hash.sha2.Sha256); | ||
| 17 | pub const HmacSha384 = Hmac(crypto.hash.sha2.Sha384); | ||
| 18 | pub const HmacSha512 = Hmac(crypto.hash.sha2.Sha512); | ||
| 19 | }; | ||
| 20 | |||
| 21 | pub const blake2 = struct { | ||
| 22 | pub const HmacBlake2s256 = Hmac(crypto.hash.blake2.Blake2s256); | ||
| 23 | }; | ||
| 10 | 24 | ||
| 11 | pub fn Hmac(comptime Hash: type) type { | 25 | pub fn Hmac(comptime Hash: type) type { |
| 12 | return struct { | 26 | return struct { |
| ... | @@ -31,7 +45,7 @@ pub fn Hmac(comptime Hash: type) type { | ... | @@ -31,7 +45,7 @@ pub fn Hmac(comptime Hash: type) type { |
| 31 | 45 | ||
| 32 | // Normalize key length to block size of hash | 46 | // Normalize key length to block size of hash |
| 33 | if (key.len > Hash.block_length) { | 47 | if (key.len > Hash.block_length) { |
| 34 | Hash.hash(key, ctx.scratch[0..mac_length]); | 48 | Hash.hash(key, ctx.scratch[0..mac_length], .{}); |
| 35 | mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0); | 49 | mem.set(u8, ctx.scratch[mac_length..Hash.block_length], 0); |
| 36 | } else if (key.len < Hash.block_length) { | 50 | } else if (key.len < Hash.block_length) { |
| 37 | mem.copy(u8, ctx.scratch[0..key.len], key); | 51 | mem.copy(u8, ctx.scratch[0..key.len], key); |
| ... | @@ -48,7 +62,7 @@ pub fn Hmac(comptime Hash: type) type { | ... | @@ -48,7 +62,7 @@ pub fn Hmac(comptime Hash: type) type { |
| 48 | b.* = ctx.scratch[i] ^ 0x36; | 62 | b.* = ctx.scratch[i] ^ 0x36; |
| 49 | } | 63 | } |
| 50 | 64 | ||
| 51 | ctx.hash = Hash.init(); | 65 | ctx.hash = Hash.init(.{}); |
| 52 | ctx.hash.update(ctx.i_key_pad[0..]); | 66 | ctx.hash.update(ctx.i_key_pad[0..]); |
| 53 | return ctx; | 67 | return ctx; |
| 54 | } | 68 | } |
| ... | @@ -61,10 +75,10 @@ pub fn Hmac(comptime Hash: type) type { | ... | @@ -61,10 +75,10 @@ pub fn Hmac(comptime Hash: type) type { |
| 61 | debug.assert(Hash.block_length >= out.len and out.len >= mac_length); | 75 | debug.assert(Hash.block_length >= out.len and out.len >= mac_length); |
| 62 | 76 | ||
| 63 | ctx.hash.final(ctx.scratch[0..mac_length]); | 77 | ctx.hash.final(ctx.scratch[0..mac_length]); |
| 64 | ctx.hash.reset(); | 78 | var ohash = Hash.init(.{}); |
| 65 | ctx.hash.update(ctx.o_key_pad[0..]); | 79 | ohash.update(ctx.o_key_pad[0..]); |
| 66 | ctx.hash.update(ctx.scratch[0..mac_length]); | 80 | ohash.update(ctx.scratch[0..mac_length]); |
| 67 | ctx.hash.final(out[0..mac_length]); | 81 | ohash.final(out[0..mac_length]); |
| 68 | } | 82 | } |
| 69 | }; | 83 | }; |
| 70 | } | 84 | } |
| ... | @@ -90,10 +104,10 @@ test "hmac sha1" { | ... | @@ -90,10 +104,10 @@ test "hmac sha1" { |
| 90 | } | 104 | } |
| 91 | 105 | ||
| 92 | test "hmac sha256" { | 106 | test "hmac sha256" { |
| 93 | var out: [HmacSha256.mac_length]u8 = undefined; | 107 | var out: [sha2.HmacSha256.mac_length]u8 = undefined; |
| 94 | HmacSha256.create(out[0..], "", ""); | 108 | sha2.HmacSha256.create(out[0..], "", ""); |
| 95 | htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]); | 109 | htest.assertEqual("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", out[0..]); |
| 96 | 110 | ||
| 97 | HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key"); | 111 | sha2.HmacSha256.create(out[0..], "The quick brown fox jumps over the lazy dog", "key"); |
| 98 | htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]); | 112 | htest.assertEqual("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8", out[0..]); |
| 99 | } | 113 | } |
lib/std/crypto/md5.zig+27-19| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const mem = @import("../mem.zig"); | 6 | const mem = @import("../mem.zig"); |
| 2 | const math = @import("../math.zig"); | 7 | const math = @import("../math.zig"); |
| 3 | const endian = @import("../endian.zig"); | 8 | const endian = @import("../endian.zig"); |
| ... | @@ -27,10 +32,14 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar | ... | @@ -27,10 +32,14 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar |
| 27 | }; | 32 | }; |
| 28 | } | 33 | } |
| 29 | 34 | ||
| 35 | /// The MD5 function is now considered cryptographically broken. | ||
| 36 | /// Namely, it is trivial to find multiple inputs producing the same hash. | ||
| 37 | /// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3. | ||
| 30 | pub const Md5 = struct { | 38 | pub const Md5 = struct { |
| 31 | const Self = @This(); | 39 | const Self = @This(); |
| 32 | pub const block_length = 64; | 40 | pub const block_length = 64; |
| 33 | pub const digest_length = 16; | 41 | pub const digest_length = 16; |
| 42 | pub const Options = struct {}; | ||
| 34 | 43 | ||
| 35 | s: [4]u32, | 44 | s: [4]u32, |
| 36 | // Streaming Cache | 45 | // Streaming Cache |
| ... | @@ -38,23 +47,22 @@ pub const Md5 = struct { | ... | @@ -38,23 +47,22 @@ pub const Md5 = struct { |
| 38 | buf_len: u8, | 47 | buf_len: u8, |
| 39 | total_len: u64, | 48 | total_len: u64, |
| 40 | 49 | ||
| 41 | pub fn init() Self { | 50 | pub fn init(options: Options) Self { |
| 42 | var d: Self = undefined; | 51 | return Self{ |
| 43 | d.reset(); | 52 | .s = [_]u32{ |
| 44 | return d; | 53 | 0x67452301, |
| 45 | } | 54 | 0xEFCDAB89, |
| 46 | 55 | 0x98BADCFE, | |
| 47 | pub fn reset(d: *Self) void { | 56 | 0x10325476, |
| 48 | d.s[0] = 0x67452301; | 57 | }, |
| 49 | d.s[1] = 0xEFCDAB89; | 58 | .buf = undefined, |
| 50 | d.s[2] = 0x98BADCFE; | 59 | .buf_len = 0, |
| 51 | d.s[3] = 0x10325476; | 60 | .total_len = 0, |
| 52 | d.buf_len = 0; | 61 | }; |
| 53 | d.total_len = 0; | ||
| 54 | } | 62 | } |
| 55 | 63 | ||
| 56 | pub fn hash(b: []const u8, out: []u8) void { | 64 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 57 | var d = Md5.init(); | 65 | var d = Md5.init(options); |
| 58 | d.update(b); | 66 | d.update(b); |
| 59 | d.final(out); | 67 | d.final(out); |
| 60 | } | 68 | } |
| ... | @@ -250,18 +258,18 @@ test "md5 single" { | ... | @@ -250,18 +258,18 @@ test "md5 single" { |
| 250 | } | 258 | } |
| 251 | 259 | ||
| 252 | test "md5 streaming" { | 260 | test "md5 streaming" { |
| 253 | var h = Md5.init(); | 261 | var h = Md5.init(.{}); |
| 254 | var out: [16]u8 = undefined; | 262 | var out: [16]u8 = undefined; |
| 255 | 263 | ||
| 256 | h.final(out[0..]); | 264 | h.final(out[0..]); |
| 257 | htest.assertEqual("d41d8cd98f00b204e9800998ecf8427e", out[0..]); | 265 | htest.assertEqual("d41d8cd98f00b204e9800998ecf8427e", out[0..]); |
| 258 | 266 | ||
| 259 | h.reset(); | 267 | h = Md5.init(.{}); |
| 260 | h.update("abc"); | 268 | h.update("abc"); |
| 261 | h.final(out[0..]); | 269 | h.final(out[0..]); |
| 262 | htest.assertEqual("900150983cd24fb0d6963f7d28e17f72", out[0..]); | 270 | htest.assertEqual("900150983cd24fb0d6963f7d28e17f72", out[0..]); |
| 263 | 271 | ||
| 264 | h.reset(); | 272 | h = Md5.init(.{}); |
| 265 | h.update("a"); | 273 | h.update("a"); |
| 266 | h.update("b"); | 274 | h.update("b"); |
| 267 | h.update("c"); | 275 | h.update("c"); |
| ... | @@ -274,7 +282,7 @@ test "md5 aligned final" { | ... | @@ -274,7 +282,7 @@ test "md5 aligned final" { |
| 274 | var block = [_]u8{0} ** Md5.block_length; | 282 | var block = [_]u8{0} ** Md5.block_length; |
| 275 | var out: [Md5.digest_length]u8 = undefined; | 283 | var out: [Md5.digest_length]u8 = undefined; |
| 276 | 284 | ||
| 277 | var h = Md5.init(); | 285 | var h = Md5.init(.{}); |
| 278 | h.update(&block); | 286 | h.update(&block); |
| 279 | h.final(out[0..]); | 287 | h.final(out[0..]); |
| 280 | } | 288 | } |
lib/std/crypto/poly1305.zig+169-191| ... | @@ -1,221 +1,199 @@ | ... | @@ -1,221 +1,199 @@ |
| 1 | // Translated from monocypher which is licensed under CC-0/BSD-3. | 1 | // SPDX-License-Identifier: MIT |
| 2 | // | 2 | // Copyright (c) 2015-2020 Zig Contributors |
| 3 | // https://monocypher.org/ | 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. |
| 4 | 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | const std = @import("../std.zig"); | 5 | // and substantial portions of the software. |
| 6 | const builtin = std.builtin; | 6 | const std = @import("std"); |
| 7 | 7 | const mem = std.mem; | |
| 8 | const Endian = builtin.Endian; | ||
| 9 | const readIntLittle = std.mem.readIntLittle; | ||
| 10 | const writeIntLittle = std.mem.writeIntLittle; | ||
| 11 | 8 | ||
| 12 | pub const Poly1305 = struct { | 9 | pub const Poly1305 = struct { |
| 13 | const Self = @This(); | 10 | pub const block_size: usize = 16; |
| 14 | |||
| 15 | pub const mac_length = 16; | 11 | pub const mac_length = 16; |
| 16 | pub const minimum_key_length = 32; | 12 | pub const minimum_key_length = 32; |
| 17 | 13 | ||
| 18 | // constant multiplier (from the secret key) | 14 | // constant multiplier (from the secret key) |
| 19 | r: [4]u32, | 15 | r: [3]u64, |
| 20 | // accumulated hash | 16 | // accumulated hash |
| 21 | h: [5]u32, | 17 | h: [3]u64 = [_]u64{ 0, 0, 0 }, |
| 22 | // chunk of the message | ||
| 23 | c: [5]u32, | ||
| 24 | // random number added at the end (from the secret key) | 18 | // random number added at the end (from the secret key) |
| 25 | pad: [4]u32, | 19 | pad: [2]u64, |
| 26 | // How many bytes are there in the chunk. | 20 | // how many bytes are waiting to be processed in a partial block |
| 27 | c_idx: usize, | 21 | leftover: usize = 0, |
| 28 | 22 | // partial block buffer | |
| 29 | fn secureZero(self: *Self) void { | 23 | buf: [block_size]u8 align(16) = undefined, |
| 30 | std.mem.secureZero(u8, @ptrCast([*]u8, self)[0..@sizeOf(Poly1305)]); | ||
| 31 | } | ||
| 32 | 24 | ||
| 33 | pub fn create(out: []u8, msg: []const u8, key: []const u8) void { | 25 | pub fn init(key: []const u8) Poly1305 { |
| 34 | std.debug.assert(out.len >= mac_length); | ||
| 35 | std.debug.assert(key.len >= minimum_key_length); | 26 | std.debug.assert(key.len >= minimum_key_length); |
| 27 | const t0 = mem.readIntLittle(u64, key[0..8]); | ||
| 28 | const t1 = mem.readIntLittle(u64, key[8..16]); | ||
| 29 | return Poly1305{ | ||
| 30 | .r = [_]u64{ | ||
| 31 | t0 & 0xffc0fffffff, | ||
| 32 | ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff, | ||
| 33 | ((t1 >> 24)) & 0x00ffffffc0f, | ||
| 34 | }, | ||
| 35 | .pad = [_]u64{ | ||
| 36 | mem.readIntLittle(u64, key[16..24]), | ||
| 37 | mem.readIntLittle(u64, key[24..32]), | ||
| 38 | }, | ||
| 39 | }; | ||
| 40 | } | ||
| 36 | 41 | ||
| 37 | var ctx = Poly1305.init(key); | 42 | fn blocks(st: *Poly1305, m: []const u8, last: comptime bool) void { |
| 38 | ctx.update(msg); | 43 | const hibit: u64 = if (last) 0 else 1 << 40; |
| 39 | ctx.final(out); | 44 | const r0 = st.r[0]; |
| 45 | const r1 = st.r[1]; | ||
| 46 | const r2 = st.r[2]; | ||
| 47 | var h0 = st.h[0]; | ||
| 48 | var h1 = st.h[1]; | ||
| 49 | var h2 = st.h[2]; | ||
| 50 | const s1 = r1 * (5 << 2); | ||
| 51 | const s2 = r2 * (5 << 2); | ||
| 52 | var i: usize = 0; | ||
| 53 | while (i + block_size <= m.len) : (i += block_size) { | ||
| 54 | // h += m[i] | ||
| 55 | const t0 = mem.readIntLittle(u64, m[i..][0..8]); | ||
| 56 | const t1 = mem.readIntLittle(u64, m[i + 8 ..][0..8]); | ||
| 57 | h0 += @truncate(u44, t0); | ||
| 58 | h1 += @truncate(u44, (t0 >> 44) | (t1 << 20)); | ||
| 59 | h2 += @truncate(u42, t1 >> 24) | hibit; | ||
| 60 | |||
| 61 | // h *= r | ||
| 62 | const d0 = @as(u128, h0) * r0 + @as(u128, h1) * s2 + @as(u128, h2) * s1; | ||
| 63 | var d1 = @as(u128, h0) * r1 + @as(u128, h1) * r0 + @as(u128, h2) * s2; | ||
| 64 | var d2 = @as(u128, h0) * r2 + @as(u128, h1) * r1 + @as(u128, h2) * r0; | ||
| 65 | |||
| 66 | // partial reduction | ||
| 67 | var carry = @intCast(u64, d0 >> 44); | ||
| 68 | h0 = @truncate(u44, d0); | ||
| 69 | d1 += carry; | ||
| 70 | carry = @intCast(u64, d1 >> 44); | ||
| 71 | h1 = @truncate(u44, d1); | ||
| 72 | d2 += carry; | ||
| 73 | carry = @intCast(u64, d2 >> 42); | ||
| 74 | h2 = @truncate(u42, d2); | ||
| 75 | h0 += @truncate(u64, carry) * 5; | ||
| 76 | carry = h0 >> 44; | ||
| 77 | h0 = @truncate(u44, h0); | ||
| 78 | h1 += carry; | ||
| 79 | } | ||
| 80 | st.h = [_]u64{ h0, h1, h2 }; | ||
| 40 | } | 81 | } |
| 41 | 82 | ||
| 42 | // Initialize the MAC context. | 83 | pub fn update(st: *Poly1305, m: []const u8) void { |
| 43 | // - key.len is sufficient size. | 84 | var mb = m; |
| 44 | pub fn init(key: []const u8) Self { | ||
| 45 | var ctx: Poly1305 = undefined; | ||
| 46 | 85 | ||
| 47 | // Initial hash is zero | 86 | // handle leftover |
| 48 | { | 87 | if (st.leftover > 0) { |
| 49 | var i: usize = 0; | 88 | const want = std.math.min(block_size - st.leftover, mb.len); |
| 50 | while (i < 5) : (i += 1) { | 89 | const mc = mb[0..want]; |
| 51 | ctx.h[i] = 0; | 90 | for (mc) |x, i| { |
| 91 | st.buf[st.leftover + i] = x; | ||
| 52 | } | 92 | } |
| 53 | } | 93 | mb = mb[want..]; |
| 54 | // add 2^130 to every input block | 94 | st.leftover += want; |
| 55 | ctx.c[4] = 1; | 95 | if (st.leftover > block_size) { |
| 56 | polyClearC(&ctx); | 96 | return; |
| 57 | |||
| 58 | // load r and pad (r has some of its bits cleared) | ||
| 59 | { | ||
| 60 | var i: usize = 0; | ||
| 61 | while (i < 1) : (i += 1) { | ||
| 62 | ctx.r[0] = readIntLittle(u32, key[0..4]) & 0x0fffffff; | ||
| 63 | } | 97 | } |
| 98 | st.blocks(&st.buf, false); | ||
| 99 | st.leftover = 0; | ||
| 64 | } | 100 | } |
| 65 | { | ||
| 66 | var i: usize = 1; | ||
| 67 | while (i < 4) : (i += 1) { | ||
| 68 | ctx.r[i] = readIntLittle(u32, key[i * 4 ..][0..4]) & 0x0ffffffc; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | { | ||
| 72 | var i: usize = 0; | ||
| 73 | while (i < 4) : (i += 1) { | ||
| 74 | ctx.pad[i] = readIntLittle(u32, key[i * 4 + 16 ..][0..4]); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | return ctx; | ||
| 79 | } | ||
| 80 | |||
| 81 | // h = (h + c) * r | ||
| 82 | // preconditions: | ||
| 83 | // ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff | ||
| 84 | // ctx->c <= 1_ffffffff_ffffffff_ffffffff_ffffffff | ||
| 85 | // ctx->r <= 0ffffffc_0ffffffc_0ffffffc_0fffffff | ||
| 86 | // Postcondition: | ||
| 87 | // ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff | ||
| 88 | fn polyBlock(ctx: *Self) void { | ||
| 89 | // s = h + c, without carry propagation | ||
| 90 | const s0 = @as(u64, ctx.h[0]) + ctx.c[0]; // s0 <= 1_fffffffe | ||
| 91 | const s1 = @as(u64, ctx.h[1]) + ctx.c[1]; // s1 <= 1_fffffffe | ||
| 92 | const s2 = @as(u64, ctx.h[2]) + ctx.c[2]; // s2 <= 1_fffffffe | ||
| 93 | const s3 = @as(u64, ctx.h[3]) + ctx.c[3]; // s3 <= 1_fffffffe | ||
| 94 | const s4 = @as(u64, ctx.h[4]) + ctx.c[4]; // s4 <= 5 | ||
| 95 | |||
| 96 | // Local all the things! | ||
| 97 | const r0 = ctx.r[0]; // r0 <= 0fffffff | ||
| 98 | const r1 = ctx.r[1]; // r1 <= 0ffffffc | ||
| 99 | const r2 = ctx.r[2]; // r2 <= 0ffffffc | ||
| 100 | const r3 = ctx.r[3]; // r3 <= 0ffffffc | ||
| 101 | const rr0 = (r0 >> 2) * 5; // rr0 <= 13fffffb // lose 2 bits... | ||
| 102 | const rr1 = (r1 >> 2) + r1; // rr1 <= 13fffffb // rr1 == (r1 >> 2) * 5 | ||
| 103 | const rr2 = (r2 >> 2) + r2; // rr2 <= 13fffffb // rr1 == (r2 >> 2) * 5 | ||
| 104 | const rr3 = (r3 >> 2) + r3; // rr3 <= 13fffffb // rr1 == (r3 >> 2) * 5 | ||
| 105 | |||
| 106 | // (h + c) * r, without carry propagation | ||
| 107 | const x0 = s0 * r0 + s1 * rr3 + s2 * rr2 + s3 * rr1 + s4 * rr0; //<=97ffffe007fffff8 | ||
| 108 | const x1 = s0 * r1 + s1 * r0 + s2 * rr3 + s3 * rr2 + s4 * rr1; //<=8fffffe20ffffff6 | ||
| 109 | const x2 = s0 * r2 + s1 * r1 + s2 * r0 + s3 * rr3 + s4 * rr2; //<=87ffffe417fffff4 | ||
| 110 | const x3 = s0 * r3 + s1 * r2 + s2 * r1 + s3 * r0 + s4 * rr3; //<=7fffffe61ffffff2 | ||
| 111 | const x4 = s4 * (r0 & 3); // ...recover 2 bits //<= f | ||
| 112 | |||
| 113 | // partial reduction modulo 2^130 - 5 | ||
| 114 | const _u5 = @truncate(u32, x4 + (x3 >> 32)); // u5 <= 7ffffff5 | ||
| 115 | const _u0 = (_u5 >> 2) * 5 + (x0 & 0xffffffff); | ||
| 116 | const _u1 = (_u0 >> 32) + (x1 & 0xffffffff) + (x0 >> 32); | ||
| 117 | const _u2 = (_u1 >> 32) + (x2 & 0xffffffff) + (x1 >> 32); | ||
| 118 | const _u3 = (_u2 >> 32) + (x3 & 0xffffffff) + (x2 >> 32); | ||
| 119 | const _u4 = (_u3 >> 32) + (_u5 & 3); | ||
| 120 | |||
| 121 | // Update the hash | ||
| 122 | ctx.h[0] = @truncate(u32, _u0); // u0 <= 1_9ffffff0 | ||
| 123 | ctx.h[1] = @truncate(u32, _u1); // u1 <= 1_97ffffe0 | ||
| 124 | ctx.h[2] = @truncate(u32, _u2); // u2 <= 1_8fffffe2 | ||
| 125 | ctx.h[3] = @truncate(u32, _u3); // u3 <= 1_87ffffe4 | ||
| 126 | ctx.h[4] = @truncate(u32, _u4); // u4 <= 4 | ||
| 127 | } | ||
| 128 | |||
| 129 | // (re-)initializes the input counter and input buffer | ||
| 130 | fn polyClearC(ctx: *Self) void { | ||
| 131 | ctx.c[0] = 0; | ||
| 132 | ctx.c[1] = 0; | ||
| 133 | ctx.c[2] = 0; | ||
| 134 | ctx.c[3] = 0; | ||
| 135 | ctx.c_idx = 0; | ||
| 136 | } | ||
| 137 | 101 | ||
| 138 | fn polyTakeInput(ctx: *Self, input: u8) void { | 102 | // process full blocks |
| 139 | const word = ctx.c_idx >> 2; | 103 | if (mb.len >= block_size) { |
| 140 | const byte = ctx.c_idx & 3; | 104 | const want = mb.len & ~(block_size - 1); |
| 141 | ctx.c[word] |= std.math.shl(u32, input, byte * 8); | 105 | st.blocks(mb[0..want], false); |
| 142 | ctx.c_idx += 1; | 106 | mb = mb[want..]; |
| 143 | } | 107 | } |
| 144 | 108 | ||
| 145 | fn polyUpdate(ctx: *Self, msg: []const u8) void { | 109 | // store leftover |
| 146 | for (msg) |b| { | 110 | if (mb.len > 0) { |
| 147 | polyTakeInput(ctx, b); | 111 | for (mb) |x, i| { |
| 148 | if (ctx.c_idx == 16) { | 112 | st.buf[st.leftover + i] = x; |
| 149 | polyBlock(ctx); | ||
| 150 | polyClearC(ctx); | ||
| 151 | } | 113 | } |
| 114 | st.leftover += mb.len; | ||
| 152 | } | 115 | } |
| 153 | } | 116 | } |
| 154 | 117 | ||
| 155 | fn alignTo(x: usize, block_size: usize) usize { | 118 | pub fn final(st: *Poly1305, out: []u8) void { |
| 156 | return ((~x) +% 1) & (block_size - 1); | 119 | std.debug.assert(out.len >= mac_length); |
| 157 | } | 120 | if (st.leftover > 0) { |
| 158 | 121 | var i = st.leftover; | |
| 159 | // Feed data into the MAC context. | 122 | st.buf[i] = 1; |
| 160 | pub fn update(ctx: *Self, msg: []const u8) void { | 123 | i += 1; |
| 161 | // Align ourselves with block boundaries | 124 | while (i < block_size) : (i += 1) { |
| 162 | const alignm = std.math.min(alignTo(ctx.c_idx, 16), msg.len); | 125 | st.buf[i] = 0; |
| 163 | polyUpdate(ctx, msg[0..alignm]); | 126 | } |
| 164 | 127 | st.blocks(&st.buf, true); | |
| 165 | var nmsg = msg[alignm..]; | ||
| 166 | |||
| 167 | // Process the msg block by block | ||
| 168 | const nb_blocks = nmsg.len >> 4; | ||
| 169 | var i: usize = 0; | ||
| 170 | while (i < nb_blocks) : (i += 1) { | ||
| 171 | ctx.c[0] = readIntLittle(u32, nmsg[0..4]); | ||
| 172 | ctx.c[1] = readIntLittle(u32, nmsg[4..8]); | ||
| 173 | ctx.c[2] = readIntLittle(u32, nmsg[8..12]); | ||
| 174 | ctx.c[3] = readIntLittle(u32, nmsg[12..16]); | ||
| 175 | polyBlock(ctx); | ||
| 176 | nmsg = nmsg[16..]; | ||
| 177 | } | ||
| 178 | if (nb_blocks > 0) { | ||
| 179 | polyClearC(ctx); | ||
| 180 | } | 128 | } |
| 181 | 129 | // fully carry h | |
| 182 | // remaining bytes | 130 | var carry = st.h[1] >> 44; |
| 183 | polyUpdate(ctx, nmsg[0..]); | 131 | st.h[1] = @truncate(u44, st.h[1]); |
| 132 | st.h[2] += carry; | ||
| 133 | carry = st.h[2] >> 42; | ||
| 134 | st.h[2] = @truncate(u42, st.h[2]); | ||
| 135 | st.h[0] += carry * 5; | ||
| 136 | carry = st.h[0] >> 44; | ||
| 137 | st.h[0] = @truncate(u44, st.h[0]); | ||
| 138 | st.h[1] += carry; | ||
| 139 | carry = st.h[1] >> 44; | ||
| 140 | st.h[1] = @truncate(u44, st.h[1]); | ||
| 141 | st.h[2] += carry; | ||
| 142 | carry = st.h[2] >> 42; | ||
| 143 | st.h[2] = @truncate(u42, st.h[2]); | ||
| 144 | st.h[0] += carry * 5; | ||
| 145 | carry = st.h[0] >> 44; | ||
| 146 | st.h[0] = @truncate(u44, st.h[0]); | ||
| 147 | st.h[1] += carry; | ||
| 148 | |||
| 149 | // compute h + -p | ||
| 150 | var g0 = st.h[0] + 5; | ||
| 151 | carry = g0 >> 44; | ||
| 152 | g0 = @truncate(u44, g0); | ||
| 153 | var g1 = st.h[1] + carry; | ||
| 154 | carry = g1 >> 44; | ||
| 155 | g1 = @truncate(u44, g1); | ||
| 156 | var g2 = st.h[2] + carry -% (1 << 42); | ||
| 157 | |||
| 158 | // (hopefully) constant-time select h if h < p, or h + -p if h >= p | ||
| 159 | const mask = (g2 >> 63) -% 1; | ||
| 160 | g0 &= mask; | ||
| 161 | g1 &= mask; | ||
| 162 | g2 &= mask; | ||
| 163 | const nmask = ~mask; | ||
| 164 | st.h[0] = (st.h[0] & nmask) | g0; | ||
| 165 | st.h[1] = (st.h[1] & nmask) | g1; | ||
| 166 | st.h[2] = (st.h[2] & nmask) | g2; | ||
| 167 | |||
| 168 | // h = (h + pad) | ||
| 169 | const t0 = st.pad[0]; | ||
| 170 | const t1 = st.pad[1]; | ||
| 171 | st.h[0] += @truncate(u44, t0); | ||
| 172 | carry = st.h[0] >> 44; | ||
| 173 | st.h[0] = @truncate(u44, st.h[0]); | ||
| 174 | st.h[1] += @truncate(u44, (t0 >> 44) | (t1 << 20)) + carry; | ||
| 175 | carry = st.h[1] >> 44; | ||
| 176 | st.h[1] = @truncate(u44, st.h[1]); | ||
| 177 | st.h[2] += @truncate(u42, t1 >> 24) + carry; | ||
| 178 | st.h[2] = @truncate(u42, st.h[2]); | ||
| 179 | |||
| 180 | // mac = h % (2^128) | ||
| 181 | st.h[0] |= st.h[1] << 44; | ||
| 182 | st.h[1] = (st.h[1] >> 20) | (st.h[2] << 24); | ||
| 183 | |||
| 184 | mem.writeIntLittle(u64, out[0..8], st.h[0]); | ||
| 185 | mem.writeIntLittle(u64, out[8..16], st.h[1]); | ||
| 186 | |||
| 187 | std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]); | ||
| 184 | } | 188 | } |
| 185 | 189 | ||
| 186 | // Finalize the MAC and output into buffer provided by caller. | 190 | pub fn create(out: []u8, msg: []const u8, key: []const u8) void { |
| 187 | pub fn final(ctx: *Self, out: []u8) void { | 191 | std.debug.assert(out.len >= mac_length); |
| 188 | // Process the last block (if any) | 192 | std.debug.assert(key.len >= minimum_key_length); |
| 189 | if (ctx.c_idx != 0) { | ||
| 190 | // move the final 1 according to remaining input length | ||
| 191 | // (We may add less than 2^130 to the last input block) | ||
| 192 | ctx.c[4] = 0; | ||
| 193 | polyTakeInput(ctx, 1); | ||
| 194 | // one last hash update | ||
| 195 | polyBlock(ctx); | ||
| 196 | } | ||
| 197 | 193 | ||
| 198 | // check if we should subtract 2^130-5 by performing the | 194 | var st = Poly1305.init(key); |
| 199 | // corresponding carry propagation. | 195 | st.update(msg); |
| 200 | const _u0 = @as(u64, 5) + ctx.h[0]; // <= 1_00000004 | 196 | st.final(out); |
| 201 | const _u1 = (_u0 >> 32) + ctx.h[1]; // <= 1_00000000 | ||
| 202 | const _u2 = (_u1 >> 32) + ctx.h[2]; // <= 1_00000000 | ||
| 203 | const _u3 = (_u2 >> 32) + ctx.h[3]; // <= 1_00000000 | ||
| 204 | const _u4 = (_u3 >> 32) + ctx.h[4]; // <= 5 | ||
| 205 | // u4 indicates how many times we should subtract 2^130-5 (0 or 1) | ||
| 206 | |||
| 207 | // h + pad, minus 2^130-5 if u4 exceeds 3 | ||
| 208 | const uu0 = (_u4 >> 2) * 5 + ctx.h[0] + ctx.pad[0]; // <= 2_00000003 | ||
| 209 | const uu1 = (uu0 >> 32) + ctx.h[1] + ctx.pad[1]; // <= 2_00000000 | ||
| 210 | const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000 | ||
| 211 | const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000 | ||
| 212 | |||
| 213 | writeIntLittle(u32, out[0..4], @truncate(u32, uu0)); | ||
| 214 | writeIntLittle(u32, out[4..8], @truncate(u32, uu1)); | ||
| 215 | writeIntLittle(u32, out[8..12], @truncate(u32, uu2)); | ||
| 216 | writeIntLittle(u32, out[12..16], @truncate(u32, uu3)); | ||
| 217 | |||
| 218 | ctx.secureZero(); | ||
| 219 | } | 197 | } |
| 220 | }; | 198 | }; |
| 221 | 199 |
lib/std/crypto/sha1.zig+29-24| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const mem = @import("../mem.zig"); | 6 | const mem = @import("../mem.zig"); |
| 2 | const math = @import("../math.zig"); | 7 | const math = @import("../math.zig"); |
| 3 | const endian = @import("../endian.zig"); | 8 | const endian = @import("../endian.zig"); |
| ... | @@ -24,35 +29,35 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { | ... | @@ -24,35 +29,35 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { |
| 24 | }; | 29 | }; |
| 25 | } | 30 | } |
| 26 | 31 | ||
| 32 | /// The SHA-1 function is now considered cryptographically broken. | ||
| 33 | /// Namely, it is feasible to find multiple inputs producing the same hash. | ||
| 34 | /// For a fast-performing, cryptographically secure hash function, see SHA512/256, BLAKE2 or BLAKE3. | ||
| 27 | pub const Sha1 = struct { | 35 | pub const Sha1 = struct { |
| 28 | const Self = @This(); | 36 | const Self = @This(); |
| 29 | pub const block_length = 64; | 37 | pub const block_length = 64; |
| 30 | pub const digest_length = 20; | 38 | pub const digest_length = 20; |
| 39 | pub const Options = struct {}; | ||
| 31 | 40 | ||
| 32 | s: [5]u32, | 41 | s: [5]u32, |
| 33 | // Streaming Cache | 42 | // Streaming Cache |
| 34 | buf: [64]u8, | 43 | buf: [64]u8 = undefined, |
| 35 | buf_len: u8, | 44 | buf_len: u8 = 0, |
| 36 | total_len: u64, | 45 | total_len: u64 = 0, |
| 37 | 46 | ||
| 38 | pub fn init() Self { | 47 | pub fn init(options: Options) Self { |
| 39 | var d: Self = undefined; | 48 | return Self{ |
| 40 | d.reset(); | 49 | .s = [_]u32{ |
| 41 | return d; | 50 | 0x67452301, |
| 42 | } | 51 | 0xEFCDAB89, |
| 43 | 52 | 0x98BADCFE, | |
| 44 | pub fn reset(d: *Self) void { | 53 | 0x10325476, |
| 45 | d.s[0] = 0x67452301; | 54 | 0xC3D2E1F0, |
| 46 | d.s[1] = 0xEFCDAB89; | 55 | }, |
| 47 | d.s[2] = 0x98BADCFE; | 56 | }; |
| 48 | d.s[3] = 0x10325476; | ||
| 49 | d.s[4] = 0xC3D2E1F0; | ||
| 50 | d.buf_len = 0; | ||
| 51 | d.total_len = 0; | ||
| 52 | } | 57 | } |
| 53 | 58 | ||
| 54 | pub fn hash(b: []const u8, out: []u8) void { | 59 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 55 | var d = Sha1.init(); | 60 | var d = Sha1.init(options); |
| 56 | d.update(b); | 61 | d.update(b); |
| 57 | d.final(out); | 62 | d.final(out); |
| 58 | } | 63 | } |
| ... | @@ -272,18 +277,18 @@ test "sha1 single" { | ... | @@ -272,18 +277,18 @@ test "sha1 single" { |
| 272 | } | 277 | } |
| 273 | 278 | ||
| 274 | test "sha1 streaming" { | 279 | test "sha1 streaming" { |
| 275 | var h = Sha1.init(); | 280 | var h = Sha1.init(.{}); |
| 276 | var out: [20]u8 = undefined; | 281 | var out: [20]u8 = undefined; |
| 277 | 282 | ||
| 278 | h.final(out[0..]); | 283 | h.final(out[0..]); |
| 279 | htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]); | 284 | htest.assertEqual("da39a3ee5e6b4b0d3255bfef95601890afd80709", out[0..]); |
| 280 | 285 | ||
| 281 | h.reset(); | 286 | h = Sha1.init(.{}); |
| 282 | h.update("abc"); | 287 | h.update("abc"); |
| 283 | h.final(out[0..]); | 288 | h.final(out[0..]); |
| 284 | htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]); | 289 | htest.assertEqual("a9993e364706816aba3e25717850c26c9cd0d89d", out[0..]); |
| 285 | 290 | ||
| 286 | h.reset(); | 291 | h = Sha1.init(.{}); |
| 287 | h.update("a"); | 292 | h.update("a"); |
| 288 | h.update("b"); | 293 | h.update("b"); |
| 289 | h.update("c"); | 294 | h.update("c"); |
| ... | @@ -295,7 +300,7 @@ test "sha1 aligned final" { | ... | @@ -295,7 +300,7 @@ test "sha1 aligned final" { |
| 295 | var block = [_]u8{0} ** Sha1.block_length; | 300 | var block = [_]u8{0} ** Sha1.block_length; |
| 296 | var out: [Sha1.digest_length]u8 = undefined; | 301 | var out: [Sha1.digest_length]u8 = undefined; |
| 297 | 302 | ||
| 298 | var h = Sha1.init(); | 303 | var h = Sha1.init(.{}); |
| 299 | h.update(&block); | 304 | h.update(&block); |
| 300 | h.final(out[0..]); | 305 | h.final(out[0..]); |
| 301 | } | 306 | } |
lib/std/crypto/sha2.zig+95-60| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const mem = @import("../mem.zig"); | 6 | const mem = @import("../mem.zig"); |
| 2 | const math = @import("../math.zig"); | 7 | const math = @import("../math.zig"); |
| 3 | const endian = @import("../endian.zig"); | 8 | const endian = @import("../endian.zig"); |
| ... | @@ -72,7 +77,10 @@ const Sha256Params = Sha2Params32{ | ... | @@ -72,7 +77,10 @@ const Sha256Params = Sha2Params32{ |
| 72 | .out_len = 256, | 77 | .out_len = 256, |
| 73 | }; | 78 | }; |
| 74 | 79 | ||
| 80 | /// SHA-224 | ||
| 75 | pub const Sha224 = Sha2_32(Sha224Params); | 81 | pub const Sha224 = Sha2_32(Sha224Params); |
| 82 | |||
| 83 | /// SHA-256 | ||
| 76 | pub const Sha256 = Sha2_32(Sha256Params); | 84 | pub const Sha256 = Sha2_32(Sha256Params); |
| 77 | 85 | ||
| 78 | fn Sha2_32(comptime params: Sha2Params32) type { | 86 | fn Sha2_32(comptime params: Sha2Params32) type { |
| ... | @@ -80,34 +88,31 @@ fn Sha2_32(comptime params: Sha2Params32) type { | ... | @@ -80,34 +88,31 @@ fn Sha2_32(comptime params: Sha2Params32) type { |
| 80 | const Self = @This(); | 88 | const Self = @This(); |
| 81 | pub const block_length = 64; | 89 | pub const block_length = 64; |
| 82 | pub const digest_length = params.out_len / 8; | 90 | pub const digest_length = params.out_len / 8; |
| 91 | pub const Options = struct {}; | ||
| 83 | 92 | ||
| 84 | s: [8]u32, | 93 | s: [8]u32, |
| 85 | // Streaming Cache | 94 | // Streaming Cache |
| 86 | buf: [64]u8, | 95 | buf: [64]u8 = undefined, |
| 87 | buf_len: u8, | 96 | buf_len: u8 = 0, |
| 88 | total_len: u64, | 97 | total_len: u64 = 0, |
| 89 | 98 | ||
| 90 | pub fn init() Self { | 99 | pub fn init(options: Options) Self { |
| 91 | var d: Self = undefined; | 100 | return Self{ |
| 92 | d.reset(); | 101 | .s = [_]u32{ |
| 93 | return d; | 102 | params.iv0, |
| 94 | } | 103 | params.iv1, |
| 95 | 104 | params.iv2, | |
| 96 | pub fn reset(d: *Self) void { | 105 | params.iv3, |
| 97 | d.s[0] = params.iv0; | 106 | params.iv4, |
| 98 | d.s[1] = params.iv1; | 107 | params.iv5, |
| 99 | d.s[2] = params.iv2; | 108 | params.iv6, |
| 100 | d.s[3] = params.iv3; | 109 | params.iv7, |
| 101 | d.s[4] = params.iv4; | 110 | }, |
| 102 | d.s[5] = params.iv5; | 111 | }; |
| 103 | d.s[6] = params.iv6; | ||
| 104 | d.s[7] = params.iv7; | ||
| 105 | d.buf_len = 0; | ||
| 106 | d.total_len = 0; | ||
| 107 | } | 112 | } |
| 108 | 113 | ||
| 109 | pub fn hash(b: []const u8, out: []u8) void { | 114 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 110 | var d = Self.init(); | 115 | var d = Self.init(options); |
| 111 | d.update(b); | 116 | d.update(b); |
| 112 | d.final(out); | 117 | d.final(out); |
| 113 | } | 118 | } |
| ... | @@ -292,18 +297,18 @@ test "sha224 single" { | ... | @@ -292,18 +297,18 @@ test "sha224 single" { |
| 292 | } | 297 | } |
| 293 | 298 | ||
| 294 | test "sha224 streaming" { | 299 | test "sha224 streaming" { |
| 295 | var h = Sha224.init(); | 300 | var h = Sha224.init(.{}); |
| 296 | var out: [28]u8 = undefined; | 301 | var out: [28]u8 = undefined; |
| 297 | 302 | ||
| 298 | h.final(out[0..]); | 303 | h.final(out[0..]); |
| 299 | htest.assertEqual("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", out[0..]); | 304 | htest.assertEqual("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", out[0..]); |
| 300 | 305 | ||
| 301 | h.reset(); | 306 | h = Sha224.init(.{}); |
| 302 | h.update("abc"); | 307 | h.update("abc"); |
| 303 | h.final(out[0..]); | 308 | h.final(out[0..]); |
| 304 | htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]); | 309 | htest.assertEqual("23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", out[0..]); |
| 305 | 310 | ||
| 306 | h.reset(); | 311 | h = Sha224.init(.{}); |
| 307 | h.update("a"); | 312 | h.update("a"); |
| 308 | h.update("b"); | 313 | h.update("b"); |
| 309 | h.update("c"); | 314 | h.update("c"); |
| ... | @@ -318,18 +323,18 @@ test "sha256 single" { | ... | @@ -318,18 +323,18 @@ test "sha256 single" { |
| 318 | } | 323 | } |
| 319 | 324 | ||
| 320 | test "sha256 streaming" { | 325 | test "sha256 streaming" { |
| 321 | var h = Sha256.init(); | 326 | var h = Sha256.init(.{}); |
| 322 | var out: [32]u8 = undefined; | 327 | var out: [32]u8 = undefined; |
| 323 | 328 | ||
| 324 | h.final(out[0..]); | 329 | h.final(out[0..]); |
| 325 | htest.assertEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", out[0..]); | 330 | htest.assertEqual("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", out[0..]); |
| 326 | 331 | ||
| 327 | h.reset(); | 332 | h = Sha256.init(.{}); |
| 328 | h.update("abc"); | 333 | h.update("abc"); |
| 329 | h.final(out[0..]); | 334 | h.final(out[0..]); |
| 330 | htest.assertEqual("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", out[0..]); | 335 | htest.assertEqual("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", out[0..]); |
| 331 | 336 | ||
| 332 | h.reset(); | 337 | h = Sha256.init(.{}); |
| 333 | h.update("a"); | 338 | h.update("a"); |
| 334 | h.update("b"); | 339 | h.update("b"); |
| 335 | h.update("c"); | 340 | h.update("c"); |
| ... | @@ -341,7 +346,7 @@ test "sha256 aligned final" { | ... | @@ -341,7 +346,7 @@ test "sha256 aligned final" { |
| 341 | var block = [_]u8{0} ** Sha256.block_length; | 346 | var block = [_]u8{0} ** Sha256.block_length; |
| 342 | var out: [Sha256.digest_length]u8 = undefined; | 347 | var out: [Sha256.digest_length]u8 = undefined; |
| 343 | 348 | ||
| 344 | var h = Sha256.init(); | 349 | var h = Sha256.init(.{}); |
| 345 | h.update(&block); | 350 | h.update(&block); |
| 346 | h.final(out[0..]); | 351 | h.final(out[0..]); |
| 347 | } | 352 | } |
| ... | @@ -413,42 +418,72 @@ const Sha512Params = Sha2Params64{ | ... | @@ -413,42 +418,72 @@ const Sha512Params = Sha2Params64{ |
| 413 | .out_len = 512, | 418 | .out_len = 512, |
| 414 | }; | 419 | }; |
| 415 | 420 | ||
| 421 | const Sha512256Params = Sha2Params64{ | ||
| 422 | .iv0 = 0x22312194FC2BF72C, | ||
| 423 | .iv1 = 0x9F555FA3C84C64C2, | ||
| 424 | .iv2 = 0x2393B86B6F53B151, | ||
| 425 | .iv3 = 0x963877195940EABD, | ||
| 426 | .iv4 = 0x96283EE2A88EFFE3, | ||
| 427 | .iv5 = 0xBE5E1E2553863992, | ||
| 428 | .iv6 = 0x2B0199FC2C85B8AA, | ||
| 429 | .iv7 = 0x0EB72DDC81C52CA2, | ||
| 430 | .out_len = 256, | ||
| 431 | }; | ||
| 432 | |||
| 433 | const Sha512T256Params = Sha2Params64{ | ||
| 434 | .iv0 = 0x6A09E667F3BCC908, | ||
| 435 | .iv1 = 0xBB67AE8584CAA73B, | ||
| 436 | .iv2 = 0x3C6EF372FE94F82B, | ||
| 437 | .iv3 = 0xA54FF53A5F1D36F1, | ||
| 438 | .iv4 = 0x510E527FADE682D1, | ||
| 439 | .iv5 = 0x9B05688C2B3E6C1F, | ||
| 440 | .iv6 = 0x1F83D9ABFB41BD6B, | ||
| 441 | .iv7 = 0x5BE0CD19137E2179, | ||
| 442 | .out_len = 256, | ||
| 443 | }; | ||
| 444 | |||
| 445 | /// SHA-384 | ||
| 416 | pub const Sha384 = Sha2_64(Sha384Params); | 446 | pub const Sha384 = Sha2_64(Sha384Params); |
| 447 | |||
| 448 | /// SHA-512 | ||
| 417 | pub const Sha512 = Sha2_64(Sha512Params); | 449 | pub const Sha512 = Sha2_64(Sha512Params); |
| 418 | 450 | ||
| 451 | /// SHA-512/256 | ||
| 452 | pub const Sha512256 = Sha2_64(Sha512256Params); | ||
| 453 | |||
| 454 | /// Truncated SHA-512 | ||
| 455 | pub const Sha512T256 = Sha2_64(Sha512T256Params); | ||
| 456 | |||
| 419 | fn Sha2_64(comptime params: Sha2Params64) type { | 457 | fn Sha2_64(comptime params: Sha2Params64) type { |
| 420 | return struct { | 458 | return struct { |
| 421 | const Self = @This(); | 459 | const Self = @This(); |
| 422 | pub const block_length = 128; | 460 | pub const block_length = 128; |
| 423 | pub const digest_length = params.out_len / 8; | 461 | pub const digest_length = params.out_len / 8; |
| 462 | pub const Options = struct {}; | ||
| 424 | 463 | ||
| 425 | s: [8]u64, | 464 | s: [8]u64, |
| 426 | // Streaming Cache | 465 | // Streaming Cache |
| 427 | buf: [128]u8, | 466 | buf: [128]u8 = undefined, |
| 428 | buf_len: u8, | 467 | buf_len: u8 = 0, |
| 429 | total_len: u128, | 468 | total_len: u128 = 0, |
| 430 | 469 | ||
| 431 | pub fn init() Self { | 470 | pub fn init(options: Options) Self { |
| 432 | var d: Self = undefined; | 471 | return Self{ |
| 433 | d.reset(); | 472 | .s = [_]u64{ |
| 434 | return d; | 473 | params.iv0, |
| 435 | } | 474 | params.iv1, |
| 436 | 475 | params.iv2, | |
| 437 | pub fn reset(d: *Self) void { | 476 | params.iv3, |
| 438 | d.s[0] = params.iv0; | 477 | params.iv4, |
| 439 | d.s[1] = params.iv1; | 478 | params.iv5, |
| 440 | d.s[2] = params.iv2; | 479 | params.iv6, |
| 441 | d.s[3] = params.iv3; | 480 | params.iv7, |
| 442 | d.s[4] = params.iv4; | 481 | }, |
| 443 | d.s[5] = params.iv5; | 482 | }; |
| 444 | d.s[6] = params.iv6; | ||
| 445 | d.s[7] = params.iv7; | ||
| 446 | d.buf_len = 0; | ||
| 447 | d.total_len = 0; | ||
| 448 | } | 483 | } |
| 449 | 484 | ||
| 450 | pub fn hash(b: []const u8, out: []u8) void { | 485 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 451 | var d = Self.init(); | 486 | var d = Self.init(options); |
| 452 | d.update(b); | 487 | d.update(b); |
| 453 | d.final(out); | 488 | d.final(out); |
| 454 | } | 489 | } |
| ... | @@ -660,7 +695,7 @@ test "sha384 single" { | ... | @@ -660,7 +695,7 @@ test "sha384 single" { |
| 660 | } | 695 | } |
| 661 | 696 | ||
| 662 | test "sha384 streaming" { | 697 | test "sha384 streaming" { |
| 663 | var h = Sha384.init(); | 698 | var h = Sha384.init(.{}); |
| 664 | var out: [48]u8 = undefined; | 699 | var out: [48]u8 = undefined; |
| 665 | 700 | ||
| 666 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; | 701 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; |
| ... | @@ -669,12 +704,12 @@ test "sha384 streaming" { | ... | @@ -669,12 +704,12 @@ test "sha384 streaming" { |
| 669 | 704 | ||
| 670 | const h2 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"; | 705 | const h2 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"; |
| 671 | 706 | ||
| 672 | h.reset(); | 707 | h = Sha384.init(.{}); |
| 673 | h.update("abc"); | 708 | h.update("abc"); |
| 674 | h.final(out[0..]); | 709 | h.final(out[0..]); |
| 675 | htest.assertEqual(h2, out[0..]); | 710 | htest.assertEqual(h2, out[0..]); |
| 676 | 711 | ||
| 677 | h.reset(); | 712 | h = Sha384.init(.{}); |
| 678 | h.update("a"); | 713 | h.update("a"); |
| 679 | h.update("b"); | 714 | h.update("b"); |
| 680 | h.update("c"); | 715 | h.update("c"); |
| ... | @@ -694,7 +729,7 @@ test "sha512 single" { | ... | @@ -694,7 +729,7 @@ test "sha512 single" { |
| 694 | } | 729 | } |
| 695 | 730 | ||
| 696 | test "sha512 streaming" { | 731 | test "sha512 streaming" { |
| 697 | var h = Sha512.init(); | 732 | var h = Sha512.init(.{}); |
| 698 | var out: [64]u8 = undefined; | 733 | var out: [64]u8 = undefined; |
| 699 | 734 | ||
| 700 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; | 735 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; |
| ... | @@ -703,12 +738,12 @@ test "sha512 streaming" { | ... | @@ -703,12 +738,12 @@ test "sha512 streaming" { |
| 703 | 738 | ||
| 704 | const h2 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; | 739 | const h2 = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"; |
| 705 | 740 | ||
| 706 | h.reset(); | 741 | h = Sha512.init(.{}); |
| 707 | h.update("abc"); | 742 | h.update("abc"); |
| 708 | h.final(out[0..]); | 743 | h.final(out[0..]); |
| 709 | htest.assertEqual(h2, out[0..]); | 744 | htest.assertEqual(h2, out[0..]); |
| 710 | 745 | ||
| 711 | h.reset(); | 746 | h = Sha512.init(.{}); |
| 712 | h.update("a"); | 747 | h.update("a"); |
| 713 | h.update("b"); | 748 | h.update("b"); |
| 714 | h.update("c"); | 749 | h.update("c"); |
| ... | @@ -720,7 +755,7 @@ test "sha512 aligned final" { | ... | @@ -720,7 +755,7 @@ test "sha512 aligned final" { |
| 720 | var block = [_]u8{0} ** Sha512.block_length; | 755 | var block = [_]u8{0} ** Sha512.block_length; |
| 721 | var out: [Sha512.digest_length]u8 = undefined; | 756 | var out: [Sha512.digest_length]u8 = undefined; |
| 722 | 757 | ||
| 723 | var h = Sha512.init(); | 758 | var h = Sha512.init(.{}); |
| 724 | h.update(&block); | 759 | h.update(&block); |
| 725 | h.final(out[0..]); | 760 | h.final(out[0..]); |
| 726 | } | 761 | } |
lib/std/crypto/sha3.zig+24-26| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const mem = @import("../mem.zig"); | 6 | const mem = @import("../mem.zig"); |
| 2 | const math = @import("../math.zig"); | 7 | const math = @import("../math.zig"); |
| 3 | const endian = @import("../endian.zig"); | 8 | const endian = @import("../endian.zig"); |
| ... | @@ -15,25 +20,18 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type { | ... | @@ -15,25 +20,18 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type { |
| 15 | const Self = @This(); | 20 | const Self = @This(); |
| 16 | pub const block_length = 200; | 21 | pub const block_length = 200; |
| 17 | pub const digest_length = bits / 8; | 22 | pub const digest_length = bits / 8; |
| 23 | pub const Options = struct {}; | ||
| 18 | 24 | ||
| 19 | s: [200]u8, | 25 | s: [200]u8, |
| 20 | offset: usize, | 26 | offset: usize, |
| 21 | rate: usize, | 27 | rate: usize, |
| 22 | 28 | ||
| 23 | pub fn init() Self { | 29 | pub fn init(options: Options) Self { |
| 24 | var d: Self = undefined; | 30 | return Self{ .s = [_]u8{0} ** 200, .offset = 0, .rate = 200 - (bits / 4) }; |
| 25 | d.reset(); | ||
| 26 | return d; | ||
| 27 | } | 31 | } |
| 28 | 32 | ||
| 29 | pub fn reset(d: *Self) void { | 33 | pub fn hash(b: []const u8, out: []u8, options: Options) void { |
| 30 | mem.set(u8, d.s[0..], 0); | 34 | var d = Self.init(options); |
| 31 | d.offset = 0; | ||
| 32 | d.rate = 200 - (bits / 4); | ||
| 33 | } | ||
| 34 | |||
| 35 | pub fn hash(b: []const u8, out: []u8) void { | ||
| 36 | var d = Self.init(); | ||
| 37 | d.update(b); | 35 | d.update(b); |
| 38 | d.final(out); | 36 | d.final(out); |
| 39 | } | 37 | } |
| ... | @@ -178,18 +176,18 @@ test "sha3-224 single" { | ... | @@ -178,18 +176,18 @@ test "sha3-224 single" { |
| 178 | } | 176 | } |
| 179 | 177 | ||
| 180 | test "sha3-224 streaming" { | 178 | test "sha3-224 streaming" { |
| 181 | var h = Sha3_224.init(); | 179 | var h = Sha3_224.init(.{}); |
| 182 | var out: [28]u8 = undefined; | 180 | var out: [28]u8 = undefined; |
| 183 | 181 | ||
| 184 | h.final(out[0..]); | 182 | h.final(out[0..]); |
| 185 | htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]); | 183 | htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]); |
| 186 | 184 | ||
| 187 | h.reset(); | 185 | h = Sha3_224.init(.{}); |
| 188 | h.update("abc"); | 186 | h.update("abc"); |
| 189 | h.final(out[0..]); | 187 | h.final(out[0..]); |
| 190 | htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]); | 188 | htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]); |
| 191 | 189 | ||
| 192 | h.reset(); | 190 | h = Sha3_224.init(.{}); |
| 193 | h.update("a"); | 191 | h.update("a"); |
| 194 | h.update("b"); | 192 | h.update("b"); |
| 195 | h.update("c"); | 193 | h.update("c"); |
| ... | @@ -204,18 +202,18 @@ test "sha3-256 single" { | ... | @@ -204,18 +202,18 @@ test "sha3-256 single" { |
| 204 | } | 202 | } |
| 205 | 203 | ||
| 206 | test "sha3-256 streaming" { | 204 | test "sha3-256 streaming" { |
| 207 | var h = Sha3_256.init(); | 205 | var h = Sha3_256.init(.{}); |
| 208 | var out: [32]u8 = undefined; | 206 | var out: [32]u8 = undefined; |
| 209 | 207 | ||
| 210 | h.final(out[0..]); | 208 | h.final(out[0..]); |
| 211 | htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]); | 209 | htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]); |
| 212 | 210 | ||
| 213 | h.reset(); | 211 | h = Sha3_256.init(.{}); |
| 214 | h.update("abc"); | 212 | h.update("abc"); |
| 215 | h.final(out[0..]); | 213 | h.final(out[0..]); |
| 216 | htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]); | 214 | htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]); |
| 217 | 215 | ||
| 218 | h.reset(); | 216 | h = Sha3_256.init(.{}); |
| 219 | h.update("a"); | 217 | h.update("a"); |
| 220 | h.update("b"); | 218 | h.update("b"); |
| 221 | h.update("c"); | 219 | h.update("c"); |
| ... | @@ -227,7 +225,7 @@ test "sha3-256 aligned final" { | ... | @@ -227,7 +225,7 @@ test "sha3-256 aligned final" { |
| 227 | var block = [_]u8{0} ** Sha3_256.block_length; | 225 | var block = [_]u8{0} ** Sha3_256.block_length; |
| 228 | var out: [Sha3_256.digest_length]u8 = undefined; | 226 | var out: [Sha3_256.digest_length]u8 = undefined; |
| 229 | 227 | ||
| 230 | var h = Sha3_256.init(); | 228 | var h = Sha3_256.init(.{}); |
| 231 | h.update(&block); | 229 | h.update(&block); |
| 232 | h.final(out[0..]); | 230 | h.final(out[0..]); |
| 233 | } | 231 | } |
| ... | @@ -242,7 +240,7 @@ test "sha3-384 single" { | ... | @@ -242,7 +240,7 @@ test "sha3-384 single" { |
| 242 | } | 240 | } |
| 243 | 241 | ||
| 244 | test "sha3-384 streaming" { | 242 | test "sha3-384 streaming" { |
| 245 | var h = Sha3_384.init(); | 243 | var h = Sha3_384.init(.{}); |
| 246 | var out: [48]u8 = undefined; | 244 | var out: [48]u8 = undefined; |
| 247 | 245 | ||
| 248 | const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; | 246 | const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; |
| ... | @@ -250,12 +248,12 @@ test "sha3-384 streaming" { | ... | @@ -250,12 +248,12 @@ test "sha3-384 streaming" { |
| 250 | htest.assertEqual(h1, out[0..]); | 248 | htest.assertEqual(h1, out[0..]); |
| 251 | 249 | ||
| 252 | const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; | 250 | const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; |
| 253 | h.reset(); | 251 | h = Sha3_384.init(.{}); |
| 254 | h.update("abc"); | 252 | h.update("abc"); |
| 255 | h.final(out[0..]); | 253 | h.final(out[0..]); |
| 256 | htest.assertEqual(h2, out[0..]); | 254 | htest.assertEqual(h2, out[0..]); |
| 257 | 255 | ||
| 258 | h.reset(); | 256 | h = Sha3_384.init(.{}); |
| 259 | h.update("a"); | 257 | h.update("a"); |
| 260 | h.update("b"); | 258 | h.update("b"); |
| 261 | h.update("c"); | 259 | h.update("c"); |
| ... | @@ -273,7 +271,7 @@ test "sha3-512 single" { | ... | @@ -273,7 +271,7 @@ test "sha3-512 single" { |
| 273 | } | 271 | } |
| 274 | 272 | ||
| 275 | test "sha3-512 streaming" { | 273 | test "sha3-512 streaming" { |
| 276 | var h = Sha3_512.init(); | 274 | var h = Sha3_512.init(.{}); |
| 277 | var out: [64]u8 = undefined; | 275 | var out: [64]u8 = undefined; |
| 278 | 276 | ||
| 279 | const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; | 277 | const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; |
| ... | @@ -281,12 +279,12 @@ test "sha3-512 streaming" { | ... | @@ -281,12 +279,12 @@ test "sha3-512 streaming" { |
| 281 | htest.assertEqual(h1, out[0..]); | 279 | htest.assertEqual(h1, out[0..]); |
| 282 | 280 | ||
| 283 | const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; | 281 | const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; |
| 284 | h.reset(); | 282 | h = Sha3_512.init(.{}); |
| 285 | h.update("abc"); | 283 | h.update("abc"); |
| 286 | h.final(out[0..]); | 284 | h.final(out[0..]); |
| 287 | htest.assertEqual(h2, out[0..]); | 285 | htest.assertEqual(h2, out[0..]); |
| 288 | 286 | ||
| 289 | h.reset(); | 287 | h = Sha3_512.init(.{}); |
| 290 | h.update("a"); | 288 | h.update("a"); |
| 291 | h.update("b"); | 289 | h.update("b"); |
| 292 | h.update("c"); | 290 | h.update("c"); |
| ... | @@ -298,7 +296,7 @@ test "sha3-512 aligned final" { | ... | @@ -298,7 +296,7 @@ test "sha3-512 aligned final" { |
| 298 | var block = [_]u8{0} ** Sha3_512.block_length; | 296 | var block = [_]u8{0} ** Sha3_512.block_length; |
| 299 | var out: [Sha3_512.digest_length]u8 = undefined; | 297 | var out: [Sha3_512.digest_length]u8 = undefined; |
| 300 | 298 | ||
| 301 | var h = Sha3_512.init(); | 299 | var h = Sha3_512.init(.{}); |
| 302 | h.update(&block); | 300 | h.update(&block); |
| 303 | h.final(out[0..]); | 301 | h.final(out[0..]); |
| 304 | } | 302 | } |
lib/std/crypto/test.zig+6-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
| ... | @@ -6,7 +11,7 @@ const fmt = std.fmt; | ... | @@ -6,7 +11,7 @@ const fmt = std.fmt; |
| 6 | // Hash using the specified hasher `H` asserting `expected == H(input)`. | 11 | // Hash using the specified hasher `H` asserting `expected == H(input)`. |
| 7 | pub fn assertEqualHash(comptime Hasher: anytype, comptime expected: []const u8, input: []const u8) void { | 12 | pub fn assertEqualHash(comptime Hasher: anytype, comptime expected: []const u8, input: []const u8) void { |
| 8 | var h: [expected.len / 2]u8 = undefined; | 13 | var h: [expected.len / 2]u8 = undefined; |
| 9 | Hasher.hash(input, h[0..]); | 14 | Hasher.hash(input, h[0..], .{}); |
| 10 | 15 | ||
| 11 | assertEqual(expected, &h); | 16 | assertEqual(expected, &h); |
| 12 | } | 17 | } |
lib/std/cstr.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/debug.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/debug/leb128.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | 8 |
lib/std/dwarf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/dwarf_bits.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const TAG_padding = 0x00; | 6 | pub const TAG_padding = 0x00; |
| 2 | pub const TAG_array_type = 0x01; | 7 | pub const TAG_array_type = 0x01; |
| 3 | pub const TAG_class_type = 0x02; | 8 | pub const TAG_class_type = 0x02; |
lib/std/dynamic_library.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | const std = @import("std.zig"); | 8 | const std = @import("std.zig"); |
lib/std/elf.zig+6| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
| ... | @@ -558,6 +563,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void { | ... | @@ -558,6 +563,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void { |
| 558 | error.InputOutput => return error.FileSystem, | 563 | error.InputOutput => return error.FileSystem, |
| 559 | error.Unexpected => return error.Unexpected, | 564 | error.Unexpected => return error.Unexpected, |
| 560 | error.WouldBlock => return error.Unexpected, | 565 | error.WouldBlock => return error.Unexpected, |
| 566 | error.NotOpenForReading => return error.Unexpected, | ||
| 561 | error.AccessDenied => return error.Unexpected, | 567 | error.AccessDenied => return error.Unexpected, |
| 562 | }; | 568 | }; |
| 563 | if (len == 0) return error.UnexpectedEndOfFile; | 569 | if (len == 0) return error.UnexpectedEndOfFile; |
lib/std/event.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const Channel = @import("event/channel.zig").Channel; | 6 | pub const Channel = @import("event/channel.zig").Channel; |
| 2 | pub const Future = @import("event/future.zig").Future; | 7 | pub const Future = @import("event/future.zig").Future; |
| 3 | pub const Group = @import("event/group.zig").Group; | 8 | pub const Group = @import("event/group.zig").Group; |
lib/std/event/batch.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | 8 |
lib/std/event/channel.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/event/future.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/event/group.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const Lock = std.event.Lock; | 8 | const Lock = std.event.Lock; |
lib/std/event/lock.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/event/locked.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const Lock = std.event.Lock; | 7 | const Lock = std.event.Lock; |
| 3 | 8 |
lib/std/event/loop.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const root = @import("root"); | 8 | const root = @import("root"); |
lib/std/event/rwlock.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/event/rwlocked.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const RwLock = std.event.RwLock; | 7 | const RwLock = std.event.RwLock; |
| 3 | 8 |
lib/std/fifo.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // FIFO of fixed size items | 6 | // FIFO of fixed size items |
| 2 | // Usually used for e.g. byte buffers | 7 | // Usually used for e.g. byte buffers |
| 3 | 8 |
lib/std/fmt.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/fmt/errol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const enum3 = @import("errol/enum3.zig").enum3; | 7 | const enum3 = @import("errol/enum3.zig").enum3; |
| 3 | const enum3_data = @import("errol/enum3.zig").enum3_data; | 8 | const enum3_data = @import("errol/enum3.zig").enum3_data; |
lib/std/fmt/errol/enum3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const enum3 = [_]u64{ | 6 | pub const enum3 = [_]u64{ |
| 2 | 0x4e2e2785c3a2a20b, | 7 | 0x4e2e2785c3a2a20b, |
| 3 | 0x240a28877a09a4e1, | 8 | 0x240a28877a09a4e1, |
lib/std/fmt/errol/lookup.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const HP = struct { | 6 | pub const HP = struct { |
| 2 | val: f64, | 7 | val: f64, |
| 3 | off: f64, | 8 | off: f64, |
lib/std/fmt/parse_float.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Adapted from https://github.com/grzegorz-kraszewski/stringtofloat. | 6 | // Adapted from https://github.com/grzegorz-kraszewski/stringtofloat. |
| 2 | 7 | ||
| 3 | // MIT License | 8 | // MIT License |
lib/std/fs.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 7 | const std = @import("std.zig"); |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/fs/file.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/fs/get_app_data_dir.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const unicode = std.unicode; | 8 | const unicode = std.unicode; |
lib/std/fs/path.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/fs/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const builtin = std.builtin; | 8 | const builtin = std.builtin; |
lib/std/fs/wasi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const os = std.os; | 7 | const os = std.os; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/fs/watch.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const event = std.event; | 8 | const event = std.event; |
lib/std/hash.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const adler = @import("hash/adler.zig"); | 6 | const adler = @import("hash/adler.zig"); |
| 2 | pub const Adler32 = adler.Adler32; | 7 | pub const Adler32 = adler.Adler32; |
| 3 | 8 |
lib/std/hash/adler.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Adler32 checksum. | 6 | // Adler32 checksum. |
| 2 | // | 7 | // |
| 3 | // https://tools.ietf.org/html/rfc1950#section-9 | 8 | // https://tools.ietf.org/html/rfc1950#section-9 |
lib/std/hash/auto_hash.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/hash/benchmark.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // zig run benchmark.zig --release-fast --override-lib-dir .. | 6 | // zig run benchmark.zig --release-fast --override-lib-dir .. |
| 2 | 7 | ||
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
lib/std/hash/cityhash.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/hash/crc.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // There are two implementations of CRC32 implemented with the following key characteristics: | 6 | // There are two implementations of CRC32 implemented with the following key characteristics: |
| 2 | // | 7 | // |
| 3 | // - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method. | 8 | // - Crc32WithPoly uses 8Kb of tables but is ~10x faster than the small method. |
lib/std/hash/fnv.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // FNV1a - Fowler-Noll-Vo hash function | 6 | // FNV1a - Fowler-Noll-Vo hash function |
| 2 | // | 7 | // |
| 3 | // FNV1a is a fast, non-cryptographic hash function with fairly good distribution properties. | 8 | // FNV1a is a fast, non-cryptographic hash function with fairly good distribution properties. |
lib/std/hash/murmur.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/hash/siphash.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Siphash | 6 | // Siphash |
| 2 | // | 7 | // |
| 3 | // SipHash is a moderately fast, non-cryptographic keyed hash function designed for resistance | 8 | // SipHash is a moderately fast, non-cryptographic keyed hash function designed for resistance |
lib/std/hash/wyhash.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
lib/std/hash_map.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 8 | const assert = debug.assert; |
lib/std/heap.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const root = @import("root"); | 7 | const root = @import("root"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/heap/arena_allocator.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/heap/general_purpose_allocator.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | //! # General Purpose Allocator | 6 | //! # General Purpose Allocator |
| 2 | //! | 7 | //! |
| 3 | //! ## Design Priorities | 8 | //! ## Design Priorities |
lib/std/heap/logging_allocator.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const Allocator = std.mem.Allocator; | 7 | const Allocator = std.mem.Allocator; |
| 3 | 8 |
lib/std/http.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | test "std.http" { | 6 | test "std.http" { |
| 2 | _ = @import("http/headers.zig"); | 7 | _ = @import("http/headers.zig"); |
| 3 | } | 8 | } |
lib/std/http/headers.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // HTTP Header data structure/type | 6 | // HTTP Header data structure/type |
| 2 | // Based on lua-http's http.header module | 7 | // Based on lua-http's http.header module |
| 3 | // | 8 | // |
lib/std/io.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const root = @import("root"); | 8 | const root = @import("root"); |
lib/std/io/bit_in_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.bit_reader.BitReader` | 6 | /// Deprecated: use `std.io.bit_reader.BitReader` |
| 2 | pub const BitInStream = @import("./bit_reader.zig").BitReader; | 7 | pub const BitInStream = @import("./bit_reader.zig").BitReader; |
| 3 | 8 |
lib/std/io/bit_out_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.bit_writer.BitWriter` | 6 | /// Deprecated: use `std.io.bit_writer.BitWriter` |
| 2 | pub const BitOutStream = @import("./bit_writer.zig").BitWriter; | 7 | pub const BitOutStream = @import("./bit_writer.zig").BitWriter; |
| 3 | 8 |
lib/std/io/bit_reader.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/io/bit_writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/io/buffered_atomic_file.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const fs = std.fs; | 8 | const fs = std.fs; |
lib/std/io/buffered_in_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.buffered_reader.BufferedReader` | 6 | /// Deprecated: use `std.io.buffered_reader.BufferedReader` |
| 2 | pub const BufferedInStream = @import("./buffered_reader.zig").BufferedReader; | 7 | pub const BufferedInStream = @import("./buffered_reader.zig").BufferedReader; |
| 3 | 8 |
lib/std/io/buffered_out_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.buffered_writer.BufferedWriter` | 6 | /// Deprecated: use `std.io.buffered_writer.BufferedWriter` |
| 2 | pub const BufferedOutStream = @import("./buffered_writer.zig").BufferedWriter; | 7 | pub const BufferedOutStream = @import("./buffered_writer.zig").BufferedWriter; |
| 3 | 8 |
lib/std/io/buffered_reader.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/io/buffered_writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | 8 |
lib/std/io/c_out_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.c_writer.CWriter` | 6 | /// Deprecated: use `std.io.c_writer.CWriter` |
| 2 | pub const COutStream = @import("./c_writer.zig").CWriter; | 7 | pub const COutStream = @import("./c_writer.zig").CWriter; |
| 3 | 8 |
lib/std/io/c_writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/io/counting_out_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.counting_writer.CountingWriter` | 6 | /// Deprecated: use `std.io.counting_writer.CountingWriter` |
| 2 | pub const CountingOutStream = @import("./counting_writer.zig").CountingWriter; | 7 | pub const CountingOutStream = @import("./counting_writer.zig").CountingWriter; |
| 3 | 8 |
lib/std/io/counting_writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/io/fixed_buffer_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/io/in_stream.zig+5| ... | @@ -1,2 +1,7 @@ | ... | @@ -1,2 +1,7 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.reader.Reader` | 6 | /// Deprecated: use `std.io.reader.Reader` |
| 2 | pub const InStream = @import("./reader.zig").Reader; | 7 | pub const InStream = @import("./reader.zig").Reader; |
lib/std/io/multi_out_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.multi_writer.MultiWriter` | 6 | /// Deprecated: use `std.io.multi_writer.MultiWriter` |
| 2 | pub const MultiOutStream = @import("./multi_writer.zig").MultiWriter; | 7 | pub const MultiOutStream = @import("./multi_writer.zig").MultiWriter; |
| 3 | 8 |
lib/std/io/multi_writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/io/out_stream.zig+5| ... | @@ -1,2 +1,7 @@ | ... | @@ -1,2 +1,7 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Deprecated: use `std.io.writer.Writer` | 6 | /// Deprecated: use `std.io.writer.Writer` |
| 2 | pub const OutStream = @import("./writer.zig").Writer; | 7 | pub const OutStream = @import("./writer.zig").Writer; |
lib/std/io/peek_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/io/reader.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/io/seekable_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | 7 | ||
| 3 | pub fn SeekableStream( | 8 | pub fn SeekableStream( |
lib/std/io/serialization.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/io/stream_source.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/io/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/io/writer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/json.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // JSON parser conforming to RFC8259. | 6 | // JSON parser conforming to RFC8259. |
| 2 | // | 7 | // |
| 3 | // https://tools.ietf.org/html/rfc8259 | 8 | // https://tools.ietf.org/html/rfc8259 |
lib/std/json/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // RFC 8529 conformance tests. | 6 | // RFC 8529 conformance tests. |
| 2 | // | 7 | // |
| 3 | // Tests are taken from https://github.com/nst/JSONTestSuite | 8 | // Tests are taken from https://github.com/nst/JSONTestSuite |
lib/std/json/write_stream.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/linked_list.zig+38-91| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 8 | const assert = debug.assert; |
| ... | @@ -178,21 +183,9 @@ pub fn TailQueue(comptime T: type) type { | ... | @@ -178,21 +183,9 @@ pub fn TailQueue(comptime T: type) type { |
| 178 | } | 183 | } |
| 179 | }; | 184 | }; |
| 180 | 185 | ||
| 181 | first: ?*Node, | 186 | first: ?*Node = null, |
| 182 | last: ?*Node, | 187 | last: ?*Node = null, |
| 183 | len: usize, | 188 | len: usize = 0, |
| 184 | |||
| 185 | /// Initialize a linked list. | ||
| 186 | /// | ||
| 187 | /// Returns: | ||
| 188 | /// An empty linked list. | ||
| 189 | pub fn init() Self { | ||
| 190 | return Self{ | ||
| 191 | .first = null, | ||
| 192 | .last = null, | ||
| 193 | .len = 0, | ||
| 194 | }; | ||
| 195 | } | ||
| 196 | 189 | ||
| 197 | /// Insert a new node after an existing one. | 190 | /// Insert a new node after an existing one. |
| 198 | /// | 191 | /// |
| ... | @@ -335,65 +328,24 @@ pub fn TailQueue(comptime T: type) type { | ... | @@ -335,65 +328,24 @@ pub fn TailQueue(comptime T: type) type { |
| 335 | list.remove(first); | 328 | list.remove(first); |
| 336 | return first; | 329 | return first; |
| 337 | } | 330 | } |
| 338 | |||
| 339 | /// Allocate a new node. | ||
| 340 | /// | ||
| 341 | /// Arguments: | ||
| 342 | /// allocator: Dynamic memory allocator. | ||
| 343 | /// | ||
| 344 | /// Returns: | ||
| 345 | /// A pointer to the new node. | ||
| 346 | pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node { | ||
| 347 | return allocator.create(Node); | ||
| 348 | } | ||
| 349 | |||
| 350 | /// Deallocate a node. | ||
| 351 | /// | ||
| 352 | /// Arguments: | ||
| 353 | /// node: Pointer to the node to deallocate. | ||
| 354 | /// allocator: Dynamic memory allocator. | ||
| 355 | pub fn destroyNode(list: *Self, node: *Node, allocator: *Allocator) void { | ||
| 356 | allocator.destroy(node); | ||
| 357 | } | ||
| 358 | |||
| 359 | /// Allocate and initialize a node and its data. | ||
| 360 | /// | ||
| 361 | /// Arguments: | ||
| 362 | /// data: The data to put inside the node. | ||
| 363 | /// allocator: Dynamic memory allocator. | ||
| 364 | /// | ||
| 365 | /// Returns: | ||
| 366 | /// A pointer to the new node. | ||
| 367 | pub fn createNode(list: *Self, data: T, allocator: *Allocator) !*Node { | ||
| 368 | var node = try list.allocateNode(allocator); | ||
| 369 | node.* = Node.init(data); | ||
| 370 | return node; | ||
| 371 | } | ||
| 372 | }; | 331 | }; |
| 373 | } | 332 | } |
| 374 | 333 | ||
| 375 | test "basic TailQueue test" { | 334 | test "basic TailQueue test" { |
| 376 | const allocator = testing.allocator; | 335 | const L = TailQueue(u32); |
| 377 | var list = TailQueue(u32).init(); | 336 | var list = L{}; |
| 378 | 337 | ||
| 379 | var one = try list.createNode(1, allocator); | 338 | var one = L.Node{ .data = 1 }; |
| 380 | var two = try list.createNode(2, allocator); | 339 | var two = L.Node{ .data = 2 }; |
| 381 | var three = try list.createNode(3, allocator); | 340 | var three = L.Node{ .data = 3 }; |
| 382 | var four = try list.createNode(4, allocator); | 341 | var four = L.Node{ .data = 4 }; |
| 383 | var five = try list.createNode(5, allocator); | 342 | var five = L.Node{ .data = 5 }; |
| 384 | defer { | ||
| 385 | list.destroyNode(one, allocator); | ||
| 386 | list.destroyNode(two, allocator); | ||
| 387 | list.destroyNode(three, allocator); | ||
| 388 | list.destroyNode(four, allocator); | ||
| 389 | list.destroyNode(five, allocator); | ||
| 390 | } | ||
| 391 | 343 | ||
| 392 | list.append(two); // {2} | 344 | list.append(&two); // {2} |
| 393 | list.append(five); // {2, 5} | 345 | list.append(&five); // {2, 5} |
| 394 | list.prepend(one); // {1, 2, 5} | 346 | list.prepend(&one); // {1, 2, 5} |
| 395 | list.insertBefore(five, four); // {1, 2, 4, 5} | 347 | list.insertBefore(&five, &four); // {1, 2, 4, 5} |
| 396 | list.insertAfter(two, three); // {1, 2, 3, 4, 5} | 348 | list.insertAfter(&two, &three); // {1, 2, 3, 4, 5} |
| 397 | 349 | ||
| 398 | // Traverse forwards. | 350 | // Traverse forwards. |
| 399 | { | 351 | { |
| ... | @@ -417,7 +369,7 @@ test "basic TailQueue test" { | ... | @@ -417,7 +369,7 @@ test "basic TailQueue test" { |
| 417 | 369 | ||
| 418 | var first = list.popFirst(); // {2, 3, 4, 5} | 370 | var first = list.popFirst(); // {2, 3, 4, 5} |
| 419 | var last = list.pop(); // {2, 3, 4} | 371 | var last = list.pop(); // {2, 3, 4} |
| 420 | list.remove(three); // {2, 4} | 372 | list.remove(&three); // {2, 4} |
| 421 | 373 | ||
| 422 | testing.expect(list.first.?.data == 2); | 374 | testing.expect(list.first.?.data == 2); |
| 423 | testing.expect(list.last.?.data == 4); | 375 | testing.expect(list.last.?.data == 4); |
| ... | @@ -425,30 +377,25 @@ test "basic TailQueue test" { | ... | @@ -425,30 +377,25 @@ test "basic TailQueue test" { |
| 425 | } | 377 | } |
| 426 | 378 | ||
| 427 | test "TailQueue concatenation" { | 379 | test "TailQueue concatenation" { |
| 428 | const allocator = testing.allocator; | 380 | const L = TailQueue(u32); |
| 429 | var list1 = TailQueue(u32).init(); | 381 | var list1 = L{}; |
| 430 | var list2 = TailQueue(u32).init(); | 382 | var list2 = L{}; |
| 431 | 383 | ||
| 432 | var one = try list1.createNode(1, allocator); | 384 | var one = L.Node{ .data = 1 }; |
| 433 | defer list1.destroyNode(one, allocator); | 385 | var two = L.Node{ .data = 2 }; |
| 434 | var two = try list1.createNode(2, allocator); | 386 | var three = L.Node{ .data = 3 }; |
| 435 | defer list1.destroyNode(two, allocator); | 387 | var four = L.Node{ .data = 4 }; |
| 436 | var three = try list1.createNode(3, allocator); | 388 | var five = L.Node{ .data = 5 }; |
| 437 | defer list1.destroyNode(three, allocator); | 389 | |
| 438 | var four = try list1.createNode(4, allocator); | 390 | list1.append(&one); |
| 439 | defer list1.destroyNode(four, allocator); | 391 | list1.append(&two); |
| 440 | var five = try list1.createNode(5, allocator); | 392 | list2.append(&three); |
| 441 | defer list1.destroyNode(five, allocator); | 393 | list2.append(&four); |
| 442 | 394 | list2.append(&five); | |
| 443 | list1.append(one); | ||
| 444 | list1.append(two); | ||
| 445 | list2.append(three); | ||
| 446 | list2.append(four); | ||
| 447 | list2.append(five); | ||
| 448 | 395 | ||
| 449 | list1.concatByMoving(&list2); | 396 | list1.concatByMoving(&list2); |
| 450 | 397 | ||
| 451 | testing.expect(list1.last == five); | 398 | testing.expect(list1.last == &five); |
| 452 | testing.expect(list1.len == 5); | 399 | testing.expect(list1.len == 5); |
| 453 | testing.expect(list2.first == null); | 400 | testing.expect(list2.first == null); |
| 454 | testing.expect(list2.last == null); | 401 | testing.expect(list2.last == null); |
lib/std/log.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const root = @import("root"); | 8 | const root = @import("root"); |
lib/std/macho.zig+17| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const mach_header = extern struct { | 6 | pub const mach_header = extern struct { |
| 2 | magic: u32, | 7 | magic: u32, |
| 3 | cputype: cpu_type_t, | 8 | cputype: cpu_type_t, |
| ... | @@ -703,3 +708,15 @@ pub const cpu_type_t = integer_t; | ... | @@ -703,3 +708,15 @@ pub const cpu_type_t = integer_t; |
| 703 | pub const cpu_subtype_t = integer_t; | 708 | pub const cpu_subtype_t = integer_t; |
| 704 | pub const integer_t = c_int; | 709 | pub const integer_t = c_int; |
| 705 | pub const vm_prot_t = c_int; | 710 | pub const vm_prot_t = c_int; |
| 711 | |||
| 712 | /// CPU type targeting 64-bit Intel-based Macs | ||
| 713 | pub const CPU_TYPE_X86_64: cpu_type_t = 0x01000007; | ||
| 714 | |||
| 715 | /// CPU type targeting 64-bit ARM-based Macs | ||
| 716 | pub const CPU_TYPE_ARM64: cpu_type_t = 0x0100000C; | ||
| 717 | |||
| 718 | /// All Intel-based Macs | ||
| 719 | pub const CPU_SUBTYPE_X86_64_ALL: cpu_subtype_t = 0x3; | ||
| 720 | |||
| 721 | /// All ARM-based Macs | ||
| 722 | pub const CPU_SUBTYPE_ARM_ALL: cpu_subtype_t = 0x0; |
lib/std/math.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/math/acos.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/acosh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/asin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/asinh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/atan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/atan2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/atanh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/big.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | 8 |
lib/std/math/big/int.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const Limb = std.math.big.Limb; | 8 | const Limb = std.math.big.Limb; |
lib/std/math/big/int_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/math/big/rational.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/cbrt.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/ceil.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/abs.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/acos.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/acosh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/arg.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/asin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/asinh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/atan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/atanh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/conj.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/cos.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/cosh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/exp.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/ldexp.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/log.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/pow.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/proj.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/sin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/sinh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/sqrt.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/complex/tan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/math/complex/tanh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/copysign.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/cos.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from go, which is licensed under a BSD-3 license. | 6 | // Ported from go, which is licensed under a BSD-3 license. |
| 2 | // https://golang.org/LICENSE | 7 | // https://golang.org/LICENSE |
| 3 | // | 8 | // |
lib/std/math/cosh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/exp.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/exp2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/expm1.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/expo2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/fabs.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/floor.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/fma.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/frexp.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/hypot.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/ilogb.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/inf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | 8 |
lib/std/math/isfinite.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/isinf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/isnan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/isnormal.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/ln.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/log.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/log10.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/log1p.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/log2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/modf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/nan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const math = @import("../math.zig"); | 6 | const math = @import("../math.zig"); |
| 2 | 7 | ||
| 3 | /// Returns the nan representation for type T. | 8 | /// Returns the nan representation for type T. |
lib/std/math/pow.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from go, which is licensed under a BSD-3 license. | 6 | // Ported from go, which is licensed under a BSD-3 license. |
| 2 | // https://golang.org/LICENSE | 7 | // https://golang.org/LICENSE |
| 3 | // | 8 | // |
lib/std/math/powi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Based on Rust, which is licensed under the MIT license. | 6 | // Based on Rust, which is licensed under the MIT license. |
| 2 | // https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/LICENSE-MIT | 7 | // https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/LICENSE-MIT |
| 3 | // | 8 | // |
lib/std/math/round.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/scalbn.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/signbit.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/sin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from go, which is licensed under a BSD-3 license. | 6 | // Ported from go, which is licensed under a BSD-3 license. |
| 2 | // https://golang.org/LICENSE | 7 | // https://golang.org/LICENSE |
| 3 | // | 8 | // |
lib/std/math/sinh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/sqrt.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const expect = std.testing.expect; | 8 | const expect = std.testing.expect; |
lib/std/math/tan.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from go, which is licensed under a BSD-3 license. | 6 | // Ported from go, which is licensed under a BSD-3 license. |
| 2 | // https://golang.org/LICENSE | 7 | // https://golang.org/LICENSE |
| 3 | // | 8 | // |
lib/std/math/tanh.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/math/trunc.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from musl, which is licensed under the MIT license: | 6 | // Ported from musl, which is licensed under the MIT license: |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | 7 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT |
| 3 | // | 8 | // |
lib/std/mem.zig+24-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const debug = std.debug; | 7 | const debug = std.debug; |
| 3 | const assert = debug.assert; | 8 | const assert = debug.assert; |
| ... | @@ -221,9 +226,19 @@ pub fn zeroes(comptime T: type) T { | ... | @@ -221,9 +226,19 @@ pub fn zeroes(comptime T: type) T { |
| 221 | .Vector => |info| { | 226 | .Vector => |info| { |
| 222 | return @splat(info.len, zeroes(info.child)); | 227 | return @splat(info.len, zeroes(info.child)); |
| 223 | }, | 228 | }, |
| 229 | .Union => |info| { | ||
| 230 | if (comptime meta.containerLayout(T) == .Extern) { | ||
| 231 | // The C language specification states that (global) unions | ||
| 232 | // should be zero initialized to the first named member. | ||
| 233 | var item: T = undefined; | ||
| 234 | @field(item, info.fields[0].name) = zeroes(@TypeOf(@field(item, info.fields[0].name))); | ||
| 235 | return item; | ||
| 236 | } | ||
| 237 | |||
| 238 | @compileError("Can't set a " ++ @typeName(T) ++ " to zero."); | ||
| 239 | }, | ||
| 224 | .ErrorUnion, | 240 | .ErrorUnion, |
| 225 | .ErrorSet, | 241 | .ErrorSet, |
| 226 | .Union, | ||
| 227 | .Fn, | 242 | .Fn, |
| 228 | .BoundFn, | 243 | .BoundFn, |
| 229 | .Type, | 244 | .Type, |
| ... | @@ -312,6 +327,14 @@ test "mem.zeroes" { | ... | @@ -312,6 +327,14 @@ test "mem.zeroes" { |
| 312 | for (b.sentinel) |e| { | 327 | for (b.sentinel) |e| { |
| 313 | testing.expectEqual(@as(u8, 0), e); | 328 | testing.expectEqual(@as(u8, 0), e); |
| 314 | } | 329 | } |
| 330 | |||
| 331 | const C_union = extern union { | ||
| 332 | a: u8, | ||
| 333 | b: u32, | ||
| 334 | }; | ||
| 335 | |||
| 336 | var c = zeroes(C_union); | ||
| 337 | testing.expectEqual(@as(u8, 0), c.a); | ||
| 315 | } | 338 | } |
| 316 | 339 | ||
| 317 | /// Sets a slice to zeroes. | 340 | /// Sets a slice to zeroes. |
lib/std/mem/Allocator.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | //! The standard memory allocation interface. | 6 | //! The standard memory allocation interface. |
| 2 | 7 | ||
| 3 | const std = @import("../std.zig"); | 8 | const std = @import("../std.zig"); |
lib/std/meta.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/meta/trailer_flags.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const meta = std.meta; | 7 | const meta = std.meta; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/meta/trait.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/mutex.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/net.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/net/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const net = std.net; | 8 | const net = std.net; |
lib/std/once.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/os.zig+24-17| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // This file contains thin wrappers around OS-specific APIs, with these | 6 | // This file contains thin wrappers around OS-specific APIs, with these |
| 2 | // specific goals in mind: | 7 | // specific goals in mind: |
| 3 | // * Convert "errno"-style error codes into Zig errors. | 8 | // * Convert "errno"-style error codes into Zig errors. |
| ... | @@ -296,6 +301,7 @@ pub const ReadError = error{ | ... | @@ -296,6 +301,7 @@ pub const ReadError = error{ |
| 296 | BrokenPipe, | 301 | BrokenPipe, |
| 297 | ConnectionResetByPeer, | 302 | ConnectionResetByPeer, |
| 298 | ConnectionTimedOut, | 303 | ConnectionTimedOut, |
| 304 | NotOpenForReading, | ||
| 299 | 305 | ||
| 300 | /// This error occurs when no global event loop is configured, | 306 | /// This error occurs when no global event loop is configured, |
| 301 | /// and reading from the file descriptor would block. | 307 | /// and reading from the file descriptor would block. |
| ... | @@ -332,7 +338,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -332,7 +338,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 332 | wasi.EINVAL => unreachable, | 338 | wasi.EINVAL => unreachable, |
| 333 | wasi.EFAULT => unreachable, | 339 | wasi.EFAULT => unreachable, |
| 334 | wasi.EAGAIN => unreachable, | 340 | wasi.EAGAIN => unreachable, |
| 335 | wasi.EBADF => unreachable, // Always a race condition. | 341 | wasi.EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 336 | wasi.EIO => return error.InputOutput, | 342 | wasi.EIO => return error.InputOutput, |
| 337 | wasi.EISDIR => return error.IsDir, | 343 | wasi.EISDIR => return error.IsDir, |
| 338 | wasi.ENOBUFS => return error.SystemResources, | 344 | wasi.ENOBUFS => return error.SystemResources, |
| ... | @@ -364,7 +370,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -364,7 +370,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 364 | } else { | 370 | } else { |
| 365 | return error.WouldBlock; | 371 | return error.WouldBlock; |
| 366 | }, | 372 | }, |
| 367 | EBADF => unreachable, // Always a race condition. | 373 | EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 368 | EIO => return error.InputOutput, | 374 | EIO => return error.InputOutput, |
| 369 | EISDIR => return error.IsDir, | 375 | EISDIR => return error.IsDir, |
| 370 | ENOBUFS => return error.SystemResources, | 376 | ENOBUFS => return error.SystemResources, |
| ... | @@ -402,7 +408,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { | ... | @@ -402,7 +408,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { |
| 402 | wasi.EINVAL => unreachable, | 408 | wasi.EINVAL => unreachable, |
| 403 | wasi.EFAULT => unreachable, | 409 | wasi.EFAULT => unreachable, |
| 404 | wasi.EAGAIN => unreachable, // currently not support in WASI | 410 | wasi.EAGAIN => unreachable, // currently not support in WASI |
| 405 | wasi.EBADF => unreachable, // always a race condition | 411 | wasi.EBADF => return error.NotOpenForReading, // can be a race condition |
| 406 | wasi.EIO => return error.InputOutput, | 412 | wasi.EIO => return error.InputOutput, |
| 407 | wasi.EISDIR => return error.IsDir, | 413 | wasi.EISDIR => return error.IsDir, |
| 408 | wasi.ENOBUFS => return error.SystemResources, | 414 | wasi.ENOBUFS => return error.SystemResources, |
| ... | @@ -426,7 +432,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { | ... | @@ -426,7 +432,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { |
| 426 | } else { | 432 | } else { |
| 427 | return error.WouldBlock; | 433 | return error.WouldBlock; |
| 428 | }, | 434 | }, |
| 429 | EBADF => unreachable, // always a race condition | 435 | EBADF => return error.NotOpenForReading, // can be a race condition |
| 430 | EIO => return error.InputOutput, | 436 | EIO => return error.InputOutput, |
| 431 | EISDIR => return error.IsDir, | 437 | EISDIR => return error.IsDir, |
| 432 | ENOBUFS => return error.SystemResources, | 438 | ENOBUFS => return error.SystemResources, |
| ... | @@ -463,7 +469,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | ... | @@ -463,7 +469,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| 463 | wasi.EINVAL => unreachable, | 469 | wasi.EINVAL => unreachable, |
| 464 | wasi.EFAULT => unreachable, | 470 | wasi.EFAULT => unreachable, |
| 465 | wasi.EAGAIN => unreachable, | 471 | wasi.EAGAIN => unreachable, |
| 466 | wasi.EBADF => unreachable, // Always a race condition. | 472 | wasi.EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 467 | wasi.EIO => return error.InputOutput, | 473 | wasi.EIO => return error.InputOutput, |
| 468 | wasi.EISDIR => return error.IsDir, | 474 | wasi.EISDIR => return error.IsDir, |
| 469 | wasi.ENOBUFS => return error.SystemResources, | 475 | wasi.ENOBUFS => return error.SystemResources, |
| ... | @@ -490,7 +496,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | ... | @@ -490,7 +496,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| 490 | } else { | 496 | } else { |
| 491 | return error.WouldBlock; | 497 | return error.WouldBlock; |
| 492 | }, | 498 | }, |
| 493 | EBADF => unreachable, // Always a race condition. | 499 | EBADF => return error.NotOpenForReading, // Can be a race condition. |
| 494 | EIO => return error.InputOutput, | 500 | EIO => return error.InputOutput, |
| 495 | EISDIR => return error.IsDir, | 501 | EISDIR => return error.IsDir, |
| 496 | ENOBUFS => return error.SystemResources, | 502 | ENOBUFS => return error.SystemResources, |
| ... | @@ -607,7 +613,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { | ... | @@ -607,7 +613,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { |
| 607 | wasi.EINVAL => unreachable, | 613 | wasi.EINVAL => unreachable, |
| 608 | wasi.EFAULT => unreachable, | 614 | wasi.EFAULT => unreachable, |
| 609 | wasi.EAGAIN => unreachable, | 615 | wasi.EAGAIN => unreachable, |
| 610 | wasi.EBADF => unreachable, // always a race condition | 616 | wasi.EBADF => return error.NotOpenForReading, // can be a race condition |
| 611 | wasi.EIO => return error.InputOutput, | 617 | wasi.EIO => return error.InputOutput, |
| 612 | wasi.EISDIR => return error.IsDir, | 618 | wasi.EISDIR => return error.IsDir, |
| 613 | wasi.ENOBUFS => return error.SystemResources, | 619 | wasi.ENOBUFS => return error.SystemResources, |
| ... | @@ -635,7 +641,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { | ... | @@ -635,7 +641,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { |
| 635 | } else { | 641 | } else { |
| 636 | return error.WouldBlock; | 642 | return error.WouldBlock; |
| 637 | }, | 643 | }, |
| 638 | EBADF => unreachable, // always a race condition | 644 | EBADF => return error.NotOpenForReading, // can be a race condition |
| 639 | EIO => return error.InputOutput, | 645 | EIO => return error.InputOutput, |
| 640 | EISDIR => return error.IsDir, | 646 | EISDIR => return error.IsDir, |
| 641 | ENOBUFS => return error.SystemResources, | 647 | ENOBUFS => return error.SystemResources, |
| ... | @@ -660,6 +666,7 @@ pub const WriteError = error{ | ... | @@ -660,6 +666,7 @@ pub const WriteError = error{ |
| 660 | BrokenPipe, | 666 | BrokenPipe, |
| 661 | SystemResources, | 667 | SystemResources, |
| 662 | OperationAborted, | 668 | OperationAborted, |
| 669 | NotOpenForWriting, | ||
| 663 | 670 | ||
| 664 | /// This error occurs when no global event loop is configured, | 671 | /// This error occurs when no global event loop is configured, |
| 665 | /// and reading from the file descriptor would block. | 672 | /// and reading from the file descriptor would block. |
| ... | @@ -704,7 +711,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { | ... | @@ -704,7 +711,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 704 | wasi.EINVAL => unreachable, | 711 | wasi.EINVAL => unreachable, |
| 705 | wasi.EFAULT => unreachable, | 712 | wasi.EFAULT => unreachable, |
| 706 | wasi.EAGAIN => unreachable, | 713 | wasi.EAGAIN => unreachable, |
| 707 | wasi.EBADF => unreachable, // Always a race condition. | 714 | wasi.EBADF => return error.NotOpenForWriting, // can be a race condition. |
| 708 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. | 715 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. |
| 709 | wasi.EDQUOT => return error.DiskQuota, | 716 | wasi.EDQUOT => return error.DiskQuota, |
| 710 | wasi.EFBIG => return error.FileTooBig, | 717 | wasi.EFBIG => return error.FileTooBig, |
| ... | @@ -736,7 +743,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { | ... | @@ -736,7 +743,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 736 | } else { | 743 | } else { |
| 737 | return error.WouldBlock; | 744 | return error.WouldBlock; |
| 738 | }, | 745 | }, |
| 739 | EBADF => unreachable, // Always a race condition. | 746 | EBADF => return error.NotOpenForWriting, // can be a race condition. |
| 740 | EDESTADDRREQ => unreachable, // `connect` was never called. | 747 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 741 | EDQUOT => return error.DiskQuota, | 748 | EDQUOT => return error.DiskQuota, |
| 742 | EFBIG => return error.FileTooBig, | 749 | EFBIG => return error.FileTooBig, |
| ... | @@ -782,7 +789,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { | ... | @@ -782,7 +789,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 782 | wasi.EINVAL => unreachable, | 789 | wasi.EINVAL => unreachable, |
| 783 | wasi.EFAULT => unreachable, | 790 | wasi.EFAULT => unreachable, |
| 784 | wasi.EAGAIN => unreachable, | 791 | wasi.EAGAIN => unreachable, |
| 785 | wasi.EBADF => unreachable, // Always a race condition. | 792 | wasi.EBADF => return error.NotOpenForWriting, // can be a race condition. |
| 786 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. | 793 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. |
| 787 | wasi.EDQUOT => return error.DiskQuota, | 794 | wasi.EDQUOT => return error.DiskQuota, |
| 788 | wasi.EFBIG => return error.FileTooBig, | 795 | wasi.EFBIG => return error.FileTooBig, |
| ... | @@ -809,7 +816,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { | ... | @@ -809,7 +816,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 809 | } else { | 816 | } else { |
| 810 | return error.WouldBlock; | 817 | return error.WouldBlock; |
| 811 | }, | 818 | }, |
| 812 | EBADF => unreachable, // Always a race condition. | 819 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 813 | EDESTADDRREQ => unreachable, // `connect` was never called. | 820 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 814 | EDQUOT => return error.DiskQuota, | 821 | EDQUOT => return error.DiskQuota, |
| 815 | EFBIG => return error.FileTooBig, | 822 | EFBIG => return error.FileTooBig, |
| ... | @@ -862,7 +869,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { | ... | @@ -862,7 +869,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 862 | wasi.EINVAL => unreachable, | 869 | wasi.EINVAL => unreachable, |
| 863 | wasi.EFAULT => unreachable, | 870 | wasi.EFAULT => unreachable, |
| 864 | wasi.EAGAIN => unreachable, | 871 | wasi.EAGAIN => unreachable, |
| 865 | wasi.EBADF => unreachable, // Always a race condition. | 872 | wasi.EBADF => return error.NotOpenForWriting, // can be a race condition. |
| 866 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. | 873 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. |
| 867 | wasi.EDQUOT => return error.DiskQuota, | 874 | wasi.EDQUOT => return error.DiskQuota, |
| 868 | wasi.EFBIG => return error.FileTooBig, | 875 | wasi.EFBIG => return error.FileTooBig, |
| ... | @@ -898,7 +905,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { | ... | @@ -898,7 +905,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 898 | } else { | 905 | } else { |
| 899 | return error.WouldBlock; | 906 | return error.WouldBlock; |
| 900 | }, | 907 | }, |
| 901 | EBADF => unreachable, // Always a race condition. | 908 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 902 | EDESTADDRREQ => unreachable, // `connect` was never called. | 909 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 903 | EDQUOT => return error.DiskQuota, | 910 | EDQUOT => return error.DiskQuota, |
| 904 | EFBIG => return error.FileTooBig, | 911 | EFBIG => return error.FileTooBig, |
| ... | @@ -956,7 +963,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz | ... | @@ -956,7 +963,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 956 | wasi.EINVAL => unreachable, | 963 | wasi.EINVAL => unreachable, |
| 957 | wasi.EFAULT => unreachable, | 964 | wasi.EFAULT => unreachable, |
| 958 | wasi.EAGAIN => unreachable, | 965 | wasi.EAGAIN => unreachable, |
| 959 | wasi.EBADF => unreachable, // Always a race condition. | 966 | wasi.EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 960 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. | 967 | wasi.EDESTADDRREQ => unreachable, // `connect` was never called. |
| 961 | wasi.EDQUOT => return error.DiskQuota, | 968 | wasi.EDQUOT => return error.DiskQuota, |
| 962 | wasi.EFBIG => return error.FileTooBig, | 969 | wasi.EFBIG => return error.FileTooBig, |
| ... | @@ -986,7 +993,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz | ... | @@ -986,7 +993,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 986 | } else { | 993 | } else { |
| 987 | return error.WouldBlock; | 994 | return error.WouldBlock; |
| 988 | }, | 995 | }, |
| 989 | EBADF => unreachable, // Always a race condition. | 996 | EBADF => return error.NotOpenForWriting, // Can be a race condition. |
| 990 | EDESTADDRREQ => unreachable, // `connect` was never called. | 997 | EDESTADDRREQ => unreachable, // `connect` was never called. |
| 991 | EDQUOT => return error.DiskQuota, | 998 | EDQUOT => return error.DiskQuota, |
| 992 | EFBIG => return error.FileTooBig, | 999 | EFBIG => return error.FileTooBig, |
| ... | @@ -1251,7 +1258,7 @@ pub fn dup2(old_fd: fd_t, new_fd: fd_t) !void { | ... | @@ -1251,7 +1258,7 @@ pub fn dup2(old_fd: fd_t, new_fd: fd_t) !void { |
| 1251 | EBUSY, EINTR => continue, | 1258 | EBUSY, EINTR => continue, |
| 1252 | EMFILE => return error.ProcessFdQuotaExceeded, | 1259 | EMFILE => return error.ProcessFdQuotaExceeded, |
| 1253 | EINVAL => unreachable, // invalid parameters passed to dup2 | 1260 | EINVAL => unreachable, // invalid parameters passed to dup2 |
| 1254 | EBADF => unreachable, // always a race condition | 1261 | EBADF => unreachable, // invalid file descriptor |
| 1255 | else => |err| return unexpectedErrno(err), | 1262 | else => |err| return unexpectedErrno(err), |
| 1256 | } | 1263 | } |
| 1257 | } | 1264 | } |
lib/std/os/bits.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | //! Platform-dependent types and values that are used along with OS-specific APIs. | 6 | //! Platform-dependent types and values that are used along with OS-specific APIs. |
| 2 | //! These are imported into `std.c`, `std.os`, and `std.os.linux`. | 7 | //! These are imported into `std.c`, `std.os`, and `std.os.linux`. |
| 3 | //! Root source files can define `os.bits` and these will additionally be added | 8 | //! Root source files can define `os.bits` and these will additionally be added |
lib/std/os/bits/darwin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/os/bits/dragonfly.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 3 | 8 |
lib/std/os/bits/freebsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 3 | 8 |
lib/std/os/bits/linux.zig+9-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("../../std.zig"); | 7 | const std = @import("../../std.zig"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
| ... | @@ -19,7 +24,7 @@ pub usingnamespace switch (builtin.arch) { | ... | @@ -19,7 +24,7 @@ pub usingnamespace switch (builtin.arch) { |
| 19 | }; | 24 | }; |
| 20 | 25 | ||
| 21 | pub usingnamespace @import("linux/netlink.zig"); | 26 | pub usingnamespace @import("linux/netlink.zig"); |
| 22 | pub const bpf = @import("linux/bpf.zig"); | 27 | pub const BPF = @import("linux/bpf.zig"); |
| 23 | 28 | ||
| 24 | const is_mips = builtin.arch.isMIPS(); | 29 | const is_mips = builtin.arch.isMIPS(); |
| 25 | 30 | ||
| ... | @@ -770,6 +775,9 @@ pub fn S_ISSOCK(m: u32) bool { | ... | @@ -770,6 +775,9 @@ pub fn S_ISSOCK(m: u32) bool { |
| 770 | return m & S_IFMT == S_IFSOCK; | 775 | return m & S_IFMT == S_IFSOCK; |
| 771 | } | 776 | } |
| 772 | 777 | ||
| 778 | pub const UTIME_NOW = 0x3fffffff; | ||
| 779 | pub const UTIME_OMIT = 0x3ffffffe; | ||
| 780 | |||
| 773 | pub const TFD_NONBLOCK = O_NONBLOCK; | 781 | pub const TFD_NONBLOCK = O_NONBLOCK; |
| 774 | pub const TFD_CLOEXEC = O_CLOEXEC; | 782 | pub const TFD_CLOEXEC = O_CLOEXEC; |
| 775 | 783 |
lib/std/os/bits/linux/arm-eabi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // arm-eabi-specific declarations that are intended to be imported into the POSIX namespace. | 6 | // arm-eabi-specific declarations that are intended to be imported into the POSIX namespace. |
| 2 | const std = @import("../../../std.zig"); | 7 | const std = @import("../../../std.zig"); |
| 3 | const linux = std.os.linux; | 8 | const linux = std.os.linux; |
lib/std/os/bits/linux/arm64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // arm64-specific declarations that are intended to be imported into the POSIX namespace. | 6 | // arm64-specific declarations that are intended to be imported into the POSIX namespace. |
| 2 | // This does include Linux-only APIs. | 7 | // This does include Linux-only APIs. |
| 3 | 8 |
lib/std/os/bits/linux/bpf.zig+387-18| ... | @@ -1,5 +1,65 @@ | ... | @@ -1,5 +1,65 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace std.os; | 6 | usingnamespace std.os; |
| 2 | const std = @import("../../../std.zig"); | 7 | const std = @import("../../../std.zig"); |
| 8 | const expectEqual = std.testing.expectEqual; | ||
| 9 | const fd_t = std.os.fd_t; | ||
| 10 | const pid_t = std.os.pid_t; | ||
| 11 | |||
| 12 | // instruction classes | ||
| 13 | pub const LD = 0x00; | ||
| 14 | pub const LDX = 0x01; | ||
| 15 | pub const ST = 0x02; | ||
| 16 | pub const STX = 0x03; | ||
| 17 | pub const ALU = 0x04; | ||
| 18 | pub const JMP = 0x05; | ||
| 19 | pub const RET = 0x06; | ||
| 20 | pub const MISC = 0x07; | ||
| 21 | |||
| 22 | /// 32-bit | ||
| 23 | pub const W = 0x00; | ||
| 24 | /// 16-bit | ||
| 25 | pub const H = 0x08; | ||
| 26 | /// 8-bit | ||
| 27 | pub const B = 0x10; | ||
| 28 | /// 64-bit | ||
| 29 | pub const DW = 0x18; | ||
| 30 | |||
| 31 | pub const IMM = 0x00; | ||
| 32 | pub const ABS = 0x20; | ||
| 33 | pub const IND = 0x40; | ||
| 34 | pub const MEM = 0x60; | ||
| 35 | pub const LEN = 0x80; | ||
| 36 | pub const MSH = 0xa0; | ||
| 37 | |||
| 38 | // alu fields | ||
| 39 | pub const ADD = 0x00; | ||
| 40 | pub const SUB = 0x10; | ||
| 41 | pub const MUL = 0x20; | ||
| 42 | pub const DIV = 0x30; | ||
| 43 | pub const OR = 0x40; | ||
| 44 | pub const AND = 0x50; | ||
| 45 | pub const LSH = 0x60; | ||
| 46 | pub const RSH = 0x70; | ||
| 47 | pub const NEG = 0x80; | ||
| 48 | pub const MOD = 0x90; | ||
| 49 | pub const XOR = 0xa0; | ||
| 50 | |||
| 51 | // jmp fields | ||
| 52 | pub const JA = 0x00; | ||
| 53 | pub const JEQ = 0x10; | ||
| 54 | pub const JGT = 0x20; | ||
| 55 | pub const JGE = 0x30; | ||
| 56 | pub const JSET = 0x40; | ||
| 57 | |||
| 58 | //#define BPF_SRC(code) ((code) & 0x08) | ||
| 59 | pub const K = 0x00; | ||
| 60 | pub const X = 0x08; | ||
| 61 | |||
| 62 | pub const MAXINSNS = 4096; | ||
| 3 | 63 | ||
| 4 | // instruction classes | 64 | // instruction classes |
| 5 | /// jmp mode in word width | 65 | /// jmp mode in word width |
| ... | @@ -8,8 +68,6 @@ pub const JMP32 = 0x06; | ... | @@ -8,8 +68,6 @@ pub const JMP32 = 0x06; |
| 8 | pub const ALU64 = 0x07; | 68 | pub const ALU64 = 0x07; |
| 9 | 69 | ||
| 10 | // ld/ldx fields | 70 | // ld/ldx fields |
| 11 | /// double word (64-bit) | ||
| 12 | pub const DW = 0x18; | ||
| 13 | /// exclusive add | 71 | /// exclusive add |
| 14 | pub const XADD = 0xc0; | 72 | pub const XADD = 0xc0; |
| 15 | 73 | ||
| ... | @@ -148,6 +206,130 @@ pub const BPF_F_CLONE = 0x200; | ... | @@ -148,6 +206,130 @@ pub const BPF_F_CLONE = 0x200; |
| 148 | /// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map | 206 | /// flag for BPF_MAP_CREATE command. Enable memory-mapping BPF map |
| 149 | pub const BPF_F_MMAPABLE = 0x400; | 207 | pub const BPF_F_MMAPABLE = 0x400; |
| 150 | 208 | ||
| 209 | /// These values correspond to "syscalls" within the BPF program's environment | ||
| 210 | pub const Helper = enum(i32) { | ||
| 211 | unspec, | ||
| 212 | map_lookup_elem, | ||
| 213 | map_update_elem, | ||
| 214 | map_delete_elem, | ||
| 215 | probe_read, | ||
| 216 | ktime_get_ns, | ||
| 217 | trace_printk, | ||
| 218 | get_prandom_u32, | ||
| 219 | get_smp_processor_id, | ||
| 220 | skb_store_bytes, | ||
| 221 | l3_csum_replace, | ||
| 222 | l4_csum_replace, | ||
| 223 | tail_call, | ||
| 224 | clone_redirect, | ||
| 225 | get_current_pid_tgid, | ||
| 226 | get_current_uid_gid, | ||
| 227 | get_current_comm, | ||
| 228 | get_cgroup_classid, | ||
| 229 | skb_vlan_push, | ||
| 230 | skb_vlan_pop, | ||
| 231 | skb_get_tunnel_key, | ||
| 232 | skb_set_tunnel_key, | ||
| 233 | perf_event_read, | ||
| 234 | redirect, | ||
| 235 | get_route_realm, | ||
| 236 | perf_event_output, | ||
| 237 | skb_load_bytes, | ||
| 238 | get_stackid, | ||
| 239 | csum_diff, | ||
| 240 | skb_get_tunnel_opt, | ||
| 241 | skb_set_tunnel_opt, | ||
| 242 | skb_change_proto, | ||
| 243 | skb_change_type, | ||
| 244 | skb_under_cgroup, | ||
| 245 | get_hash_recalc, | ||
| 246 | get_current_task, | ||
| 247 | probe_write_user, | ||
| 248 | current_task_under_cgroup, | ||
| 249 | skb_change_tail, | ||
| 250 | skb_pull_data, | ||
| 251 | csum_update, | ||
| 252 | set_hash_invalid, | ||
| 253 | get_numa_node_id, | ||
| 254 | skb_change_head, | ||
| 255 | xdp_adjust_head, | ||
| 256 | probe_read_str, | ||
| 257 | get_socket_cookie, | ||
| 258 | get_socket_uid, | ||
| 259 | set_hash, | ||
| 260 | setsockopt, | ||
| 261 | skb_adjust_room, | ||
| 262 | redirect_map, | ||
| 263 | sk_redirect_map, | ||
| 264 | sock_map_update, | ||
| 265 | xdp_adjust_meta, | ||
| 266 | perf_event_read_value, | ||
| 267 | perf_prog_read_value, | ||
| 268 | getsockopt, | ||
| 269 | override_return, | ||
| 270 | sock_ops_cb_flags_set, | ||
| 271 | msg_redirect_map, | ||
| 272 | msg_apply_bytes, | ||
| 273 | msg_cork_bytes, | ||
| 274 | msg_pull_data, | ||
| 275 | bind, | ||
| 276 | xdp_adjust_tail, | ||
| 277 | skb_get_xfrm_state, | ||
| 278 | get_stack, | ||
| 279 | skb_load_bytes_relative, | ||
| 280 | fib_lookup, | ||
| 281 | sock_hash_update, | ||
| 282 | msg_redirect_hash, | ||
| 283 | sk_redirect_hash, | ||
| 284 | lwt_push_encap, | ||
| 285 | lwt_seg6_store_bytes, | ||
| 286 | lwt_seg6_adjust_srh, | ||
| 287 | lwt_seg6_action, | ||
| 288 | rc_repeat, | ||
| 289 | rc_keydown, | ||
| 290 | skb_cgroup_id, | ||
| 291 | get_current_cgroup_id, | ||
| 292 | get_local_storage, | ||
| 293 | sk_select_reuseport, | ||
| 294 | skb_ancestor_cgroup_id, | ||
| 295 | sk_lookup_tcp, | ||
| 296 | sk_lookup_udp, | ||
| 297 | sk_release, | ||
| 298 | map_push_elem, | ||
| 299 | map_pop_elem, | ||
| 300 | map_peek_elem, | ||
| 301 | msg_push_data, | ||
| 302 | msg_pop_data, | ||
| 303 | rc_pointer_rel, | ||
| 304 | spin_lock, | ||
| 305 | spin_unlock, | ||
| 306 | sk_fullsock, | ||
| 307 | tcp_sock, | ||
| 308 | skb_ecn_set_ce, | ||
| 309 | get_listener_sock, | ||
| 310 | skc_lookup_tcp, | ||
| 311 | tcp_check_syncookie, | ||
| 312 | sysctl_get_name, | ||
| 313 | sysctl_get_current_value, | ||
| 314 | sysctl_get_new_value, | ||
| 315 | sysctl_set_new_value, | ||
| 316 | strtol, | ||
| 317 | strtoul, | ||
| 318 | sk_storage_get, | ||
| 319 | sk_storage_delete, | ||
| 320 | send_signal, | ||
| 321 | tcp_gen_syncookie, | ||
| 322 | skb_output, | ||
| 323 | probe_read_user, | ||
| 324 | probe_read_kernel, | ||
| 325 | probe_read_user_str, | ||
| 326 | probe_read_kernel_str, | ||
| 327 | tcp_send_ack, | ||
| 328 | send_signal_thread, | ||
| 329 | jiffies64, | ||
| 330 | _, | ||
| 331 | }; | ||
| 332 | |||
| 151 | /// a single BPF instruction | 333 | /// a single BPF instruction |
| 152 | pub const Insn = packed struct { | 334 | pub const Insn = packed struct { |
| 153 | code: u8, | 335 | code: u8, |
| ... | @@ -158,32 +340,168 @@ pub const Insn = packed struct { | ... | @@ -158,32 +340,168 @@ pub const Insn = packed struct { |
| 158 | 340 | ||
| 159 | /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack | 341 | /// r0 - r9 are general purpose 64-bit registers, r10 points to the stack |
| 160 | /// frame | 342 | /// frame |
| 161 | pub const Reg = enum(u4) { | 343 | pub const Reg = packed enum(u4) { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 }; |
| 162 | r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 | 344 | const Source = packed enum(u1) { reg, imm }; |
| 345 | const AluOp = packed enum(u8) { | ||
| 346 | add = ADD, | ||
| 347 | sub = SUB, | ||
| 348 | mul = MUL, | ||
| 349 | div = DIV, | ||
| 350 | op_or = OR, | ||
| 351 | op_and = AND, | ||
| 352 | lsh = LSH, | ||
| 353 | rsh = RSH, | ||
| 354 | neg = NEG, | ||
| 355 | mod = MOD, | ||
| 356 | xor = XOR, | ||
| 357 | mov = MOV, | ||
| 163 | }; | 358 | }; |
| 164 | 359 | ||
| 165 | const alu = 0x04; | 360 | pub const Size = packed enum(u8) { |
| 166 | const jmp = 0x05; | 361 | byte = B, |
| 167 | const mov = 0xb0; | 362 | half_word = H, |
| 168 | const k = 0; | 363 | word = W, |
| 169 | const exit_code = 0x90; | 364 | double_word = DW, |
| 365 | }; | ||
| 366 | |||
| 367 | const JmpOp = packed enum(u8) { | ||
| 368 | ja = JA, | ||
| 369 | jeq = JEQ, | ||
| 370 | jgt = JGT, | ||
| 371 | jge = JGE, | ||
| 372 | jset = JSET, | ||
| 373 | }; | ||
| 374 | |||
| 375 | const ImmOrReg = union(Source) { | ||
| 376 | imm: i32, | ||
| 377 | reg: Reg, | ||
| 378 | }; | ||
| 379 | |||
| 380 | fn imm_reg(code: u8, dst: Reg, src: anytype, off: i16) Insn { | ||
| 381 | const imm_or_reg = if (@typeInfo(@TypeOf(src)) == .EnumLiteral) | ||
| 382 | ImmOrReg{ .reg = @as(Reg, src) } | ||
| 383 | else | ||
| 384 | ImmOrReg{ .imm = src }; | ||
| 385 | |||
| 386 | const src_type = switch (imm_or_reg) { | ||
| 387 | .imm => K, | ||
| 388 | .reg => X, | ||
| 389 | }; | ||
| 390 | |||
| 391 | return Insn{ | ||
| 392 | .code = code | src_type, | ||
| 393 | .dst = @enumToInt(dst), | ||
| 394 | .src = switch (imm_or_reg) { | ||
| 395 | .imm => 0, | ||
| 396 | .reg => |r| @enumToInt(r), | ||
| 397 | }, | ||
| 398 | .off = off, | ||
| 399 | .imm = switch (imm_or_reg) { | ||
| 400 | .imm => |i| i, | ||
| 401 | .reg => 0, | ||
| 402 | }, | ||
| 403 | }; | ||
| 404 | } | ||
| 405 | |||
| 406 | fn alu(comptime width: comptime_int, op: AluOp, dst: Reg, src: anytype) Insn { | ||
| 407 | const width_bitfield = switch (width) { | ||
| 408 | 32 => ALU, | ||
| 409 | 64 => ALU64, | ||
| 410 | else => @compileError("width must be 32 or 64"), | ||
| 411 | }; | ||
| 412 | |||
| 413 | return imm_reg(width_bitfield | @enumToInt(op), dst, src, 0); | ||
| 414 | } | ||
| 170 | 415 | ||
| 171 | // TODO: implement more factory functions for the other instructions | 416 | pub fn mov(dst: Reg, src: anytype) Insn { |
| 172 | /// load immediate value into a register | 417 | return alu(64, .mov, dst, src); |
| 173 | pub fn load_imm(dst: Reg, imm: i32) Insn { | 418 | } |
| 419 | |||
| 420 | pub fn add(dst: Reg, src: anytype) Insn { | ||
| 421 | return alu(64, .add, dst, src); | ||
| 422 | } | ||
| 423 | |||
| 424 | fn jmp(op: JmpOp, dst: Reg, src: anytype, off: i16) Insn { | ||
| 425 | return imm_reg(JMP | @enumToInt(op), dst, src, off); | ||
| 426 | } | ||
| 427 | |||
| 428 | pub fn jeq(dst: Reg, src: anytype, off: i16) Insn { | ||
| 429 | return jmp(.jeq, dst, src, off); | ||
| 430 | } | ||
| 431 | |||
| 432 | pub fn stx_mem(size: Size, dst: Reg, src: Reg, off: i16) Insn { | ||
| 174 | return Insn{ | 433 | return Insn{ |
| 175 | .code = alu | mov | k, | 434 | .code = STX | @enumToInt(size) | MEM, |
| 176 | .dst = @enumToInt(dst), | 435 | .dst = @enumToInt(dst), |
| 436 | .src = @enumToInt(src), | ||
| 437 | .off = off, | ||
| 438 | .imm = 0, | ||
| 439 | }; | ||
| 440 | } | ||
| 441 | |||
| 442 | pub fn xadd(dst: Reg, src: Reg) Insn { | ||
| 443 | return Insn{ | ||
| 444 | .code = STX | XADD | DW, | ||
| 445 | .dst = @enumToInt(dst), | ||
| 446 | .src = @enumToInt(src), | ||
| 447 | .off = 0, | ||
| 448 | .imm = 0, | ||
| 449 | }; | ||
| 450 | } | ||
| 451 | |||
| 452 | /// direct packet access, R0 = *(uint *)(skb->data + imm32) | ||
| 453 | pub fn ld_abs(size: Size, imm: i32) Insn { | ||
| 454 | return Insn{ | ||
| 455 | .code = LD | @enumToInt(size) | ABS, | ||
| 456 | .dst = 0, | ||
| 177 | .src = 0, | 457 | .src = 0, |
| 178 | .off = 0, | 458 | .off = 0, |
| 179 | .imm = imm, | 459 | .imm = imm, |
| 180 | }; | 460 | }; |
| 181 | } | 461 | } |
| 182 | 462 | ||
| 463 | fn ld_imm_impl1(dst: Reg, src: Reg, imm: u64) Insn { | ||
| 464 | return Insn{ | ||
| 465 | .code = LD | DW | IMM, | ||
| 466 | .dst = @enumToInt(dst), | ||
| 467 | .src = @enumToInt(src), | ||
| 468 | .off = 0, | ||
| 469 | .imm = @intCast(i32, @truncate(u32, imm)), | ||
| 470 | }; | ||
| 471 | } | ||
| 472 | |||
| 473 | fn ld_imm_impl2(imm: u64) Insn { | ||
| 474 | return Insn{ | ||
| 475 | .code = 0, | ||
| 476 | .dst = 0, | ||
| 477 | .src = 0, | ||
| 478 | .off = 0, | ||
| 479 | .imm = @intCast(i32, @truncate(u32, imm >> 32)), | ||
| 480 | }; | ||
| 481 | } | ||
| 482 | |||
| 483 | pub fn ld_map_fd1(dst: Reg, map_fd: fd_t) Insn { | ||
| 484 | return ld_imm_impl1(dst, @intToEnum(Reg, PSEUDO_MAP_FD), @intCast(u64, map_fd)); | ||
| 485 | } | ||
| 486 | |||
| 487 | pub fn ld_map_fd2(map_fd: fd_t) Insn { | ||
| 488 | return ld_imm_impl2(@intCast(u64, map_fd)); | ||
| 489 | } | ||
| 490 | |||
| 491 | pub fn call(helper: Helper) Insn { | ||
| 492 | return Insn{ | ||
| 493 | .code = JMP | CALL, | ||
| 494 | .dst = 0, | ||
| 495 | .src = 0, | ||
| 496 | .off = 0, | ||
| 497 | .imm = @enumToInt(helper), | ||
| 498 | }; | ||
| 499 | } | ||
| 500 | |||
| 183 | /// exit BPF program | 501 | /// exit BPF program |
| 184 | pub fn exit() Insn { | 502 | pub fn exit() Insn { |
| 185 | return Insn{ | 503 | return Insn{ |
| 186 | .code = jmp | exit_code, | 504 | .code = JMP | EXIT, |
| 187 | .dst = 0, | 505 | .dst = 0, |
| 188 | .src = 0, | 506 | .src = 0, |
| 189 | .off = 0, | 507 | .off = 0, |
| ... | @@ -192,6 +510,61 @@ pub const Insn = packed struct { | ... | @@ -192,6 +510,61 @@ pub const Insn = packed struct { |
| 192 | } | 510 | } |
| 193 | }; | 511 | }; |
| 194 | 512 | ||
| 513 | fn expect_insn(insn: Insn, val: u64) void { | ||
| 514 | expectEqual(@bitCast(u64, insn), val); | ||
| 515 | } | ||
| 516 | |||
| 517 | test "insn bitsize" { | ||
| 518 | expectEqual(@bitSizeOf(Insn), 64); | ||
| 519 | } | ||
| 520 | |||
| 521 | // mov instructions | ||
| 522 | test "mov imm" { | ||
| 523 | expect_insn(Insn.mov(.r1, 1), 0x00000001000001b7); | ||
| 524 | } | ||
| 525 | |||
| 526 | test "mov reg" { | ||
| 527 | expect_insn(Insn.mov(.r6, .r1), 0x00000000000016bf); | ||
| 528 | } | ||
| 529 | |||
| 530 | // alu instructions | ||
| 531 | test "add imm" { | ||
| 532 | expect_insn(Insn.add(.r2, -4), 0xfffffffc00000207); | ||
| 533 | } | ||
| 534 | |||
| 535 | // ld instructions | ||
| 536 | test "ld_abs" { | ||
| 537 | expect_insn(Insn.ld_abs(.byte, 42), 0x0000002a00000030); | ||
| 538 | } | ||
| 539 | |||
| 540 | test "ld_map_fd" { | ||
| 541 | expect_insn(Insn.ld_map_fd1(.r1, 42), 0x0000002a00001118); | ||
| 542 | expect_insn(Insn.ld_map_fd2(42), 0x0000000000000000); | ||
| 543 | } | ||
| 544 | |||
| 545 | // st instructions | ||
| 546 | test "stx_mem" { | ||
| 547 | expect_insn(Insn.stx_mem(.word, .r10, .r0, -4), 0x00000000fffc0a63); | ||
| 548 | } | ||
| 549 | |||
| 550 | test "xadd" { | ||
| 551 | expect_insn(Insn.xadd(.r0, .r1), 0x00000000000010db); | ||
| 552 | } | ||
| 553 | |||
| 554 | // jmp instructions | ||
| 555 | test "jeq imm" { | ||
| 556 | expect_insn(Insn.jeq(.r0, 0, 2), 0x0000000000020015); | ||
| 557 | } | ||
| 558 | |||
| 559 | // other instructions | ||
| 560 | test "call" { | ||
| 561 | expect_insn(Insn.call(.map_lookup_elem), 0x0000000100000085); | ||
| 562 | } | ||
| 563 | |||
| 564 | test "exit" { | ||
| 565 | expect_insn(Insn.exit(), 0x0000000000000095); | ||
| 566 | } | ||
| 567 | |||
| 195 | pub const Cmd = extern enum(usize) { | 568 | pub const Cmd = extern enum(usize) { |
| 196 | map_create, | 569 | map_create, |
| 197 | map_lookup_elem, | 570 | map_lookup_elem, |
| ... | @@ -600,7 +973,3 @@ pub const Attr = extern union { | ... | @@ -600,7 +973,3 @@ pub const Attr = extern union { |
| 600 | enable_stats: EnableStatsAttr, | 973 | enable_stats: EnableStatsAttr, |
| 601 | iter_create: IterCreateAttr, | 974 | iter_create: IterCreateAttr, |
| 602 | }; | 975 | }; |
| 603 | |||
| 604 | pub fn bpf(cmd: Cmd, attr: *Attr, size: u32) usize { | ||
| 605 | return syscall3(.bpf, @enumToInt(cmd), @ptrToInt(attr), size); | ||
| 606 | } |
lib/std/os/bits/linux/errno-generic.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// Operation not permitted | 6 | /// Operation not permitted |
| 2 | pub const EPERM = 1; | 7 | pub const EPERM = 1; |
| 3 | 8 |
lib/std/os/bits/linux/errno-mips.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const EPERM = 1; | 6 | pub const EPERM = 1; |
| 2 | pub const ENOENT = 2; | 7 | pub const ENOENT = 2; |
| 3 | pub const ESRCH = 3; | 8 | pub const ESRCH = 3; |
lib/std/os/bits/linux/i386.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // i386-specific declarations that are intended to be imported into the POSIX namespace. | 6 | // i386-specific declarations that are intended to be imported into the POSIX namespace. |
| 2 | // This does include Linux-only APIs. | 7 | // This does include Linux-only APIs. |
| 3 | 8 |
lib/std/os/bits/linux/mips.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../../std.zig"); | 6 | const std = @import("../../../std.zig"); |
| 2 | const linux = std.os.linux; | 7 | const linux = std.os.linux; |
| 3 | const socklen_t = linux.socklen_t; | 8 | const socklen_t = linux.socklen_t; |
lib/std/os/bits/linux/netlink.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../linux.zig"); | 6 | usingnamespace @import("../linux.zig"); |
| 2 | 7 | ||
| 3 | /// Routing/device hook | 8 | /// Routing/device hook |
lib/std/os/bits/linux/riscv64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // riscv64-specific declarations that are intended to be imported into the POSIX namespace. | 6 | // riscv64-specific declarations that are intended to be imported into the POSIX namespace. |
| 2 | const std = @import("../../../std.zig"); | 7 | const std = @import("../../../std.zig"); |
| 3 | const uid_t = std.os.linux.uid_t; | 8 | const uid_t = std.os.linux.uid_t; |
lib/std/os/bits/linux/x86_64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // x86-64-specific declarations that are intended to be imported into the POSIX namespace. | 6 | // x86-64-specific declarations that are intended to be imported into the POSIX namespace. |
| 2 | const std = @import("../../../std.zig"); | 7 | const std = @import("../../../std.zig"); |
| 3 | const pid_t = linux.pid_t; | 8 | const pid_t = linux.pid_t; |
lib/std/os/bits/netbsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/os/bits/wasi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Convenience types and consts used by std.os module | 6 | // Convenience types and consts used by std.os module |
| 2 | pub const STDIN_FILENO = 0; | 7 | pub const STDIN_FILENO = 0; |
| 3 | pub const STDOUT_FILENO = 1; | 8 | pub const STDOUT_FILENO = 1; |
lib/std/os/bits/windows.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // The reference for these types and values is Microsoft Windows's ucrt (Universal C RunTime). | 6 | // The reference for these types and values is Microsoft Windows's ucrt (Universal C RunTime). |
| 2 | 7 | ||
| 3 | usingnamespace @import("../windows/bits.zig"); | 8 | usingnamespace @import("../windows/bits.zig"); |
lib/std/os/darwin.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 3 | pub usingnamespace std.c; | 8 | pub usingnamespace std.c; |
lib/std/os/dragonfly.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | pub usingnamespace std.c; | 7 | pub usingnamespace std.c; |
| 3 | pub usingnamespace @import("bits.zig"); | 8 | pub usingnamespace @import("bits.zig"); |
lib/std/os/freebsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | pub usingnamespace std.c; | 7 | pub usingnamespace std.c; |
| 3 | pub usingnamespace @import("bits.zig"); | 8 | pub usingnamespace @import("bits.zig"); |
lib/std/os/linux.zig+9| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // This file provides the system interface functions for Linux matching those | 6 | // This file provides the system interface functions for Linux matching those |
| 2 | // that are provided by libc, whether or not libc is linked. The following | 7 | // that are provided by libc, whether or not libc is linked. The following |
| 3 | // abstractions are made: | 8 | // abstractions are made: |
| ... | @@ -1216,6 +1221,10 @@ pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, | ... | @@ -1216,6 +1221,10 @@ pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, |
| 1216 | ); | 1221 | ); |
| 1217 | } | 1222 | } |
| 1218 | 1223 | ||
| 1224 | pub fn bpf(cmd: BPF.Cmd, attr: *BPF.Attr, size: u32) usize { | ||
| 1225 | return syscall3(.bpf, @enumToInt(cmd), @ptrToInt(attr), size); | ||
| 1226 | } | ||
| 1227 | |||
| 1219 | test "" { | 1228 | test "" { |
| 1220 | if (builtin.os.tag == .linux) { | 1229 | if (builtin.os.tag == .linux) { |
| 1221 | _ = @import("linux/test.zig"); | 1230 | _ = @import("linux/test.zig"); |
lib/std/os/linux/arm-eabi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/linux/arm64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/linux/i386.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/linux/mips.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/linux/riscv64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/linux/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const linux = std.os.linux; | 8 | const linux = std.os.linux; |
lib/std/os/linux/tls.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/os/linux/vdso.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 2 | const elf = std.elf; | 7 | const elf = std.elf; |
| 3 | const linux = std.os.linux; | 8 | const linux = std.os.linux; |
lib/std/os/linux/x86_64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("../bits.zig"); | 6 | usingnamespace @import("../bits.zig"); |
| 2 | 7 | ||
| 3 | pub fn syscall0(number: SYS) usize { | 8 | pub fn syscall0(number: SYS) usize { |
lib/std/os/netbsd.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | pub usingnamespace std.c; | 7 | pub usingnamespace std.c; |
| 3 | pub usingnamespace @import("bits.zig"); | 8 | pub usingnamespace @import("bits.zig"); |
lib/std/os/test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const os = std.os; | 7 | const os = std.os; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/os/uefi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | /// A protocol is an interface identified by a GUID. | 6 | /// A protocol is an interface identified by a GUID. |
| 2 | pub const protocols = @import("uefi/protocols.zig"); | 7 | pub const protocols = @import("uefi/protocols.zig"); |
| 3 | 8 |
lib/std/os/uefi/protocols.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").LoadedImageProtocol; | 6 | pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").LoadedImageProtocol; |
| 2 | pub const loaded_image_device_path_protocol_guid = @import("protocols/loaded_image_protocol.zig").loaded_image_device_path_protocol_guid; | 7 | pub const loaded_image_device_path_protocol_guid = @import("protocols/loaded_image_protocol.zig").loaded_image_device_path_protocol_guid; |
| 3 | 8 |
lib/std/os/uefi/protocols/absolute_pointer_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/device_path_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | 8 |
lib/std/os/uefi/protocols/edid_active_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | 8 |
lib/std/os/uefi/protocols/edid_discovered_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | 8 |
lib/std/os/uefi/protocols/edid_override_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Handle = uefi.Handle; | 8 | const Handle = uefi.Handle; |
lib/std/os/uefi/protocols/file_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Time = uefi.Time; | 8 | const Time = uefi.Time; |
lib/std/os/uefi/protocols/graphics_output_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Status = uefi.Status; | 8 | const Status = uefi.Status; |
lib/std/os/uefi/protocols/hii.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | 8 |
lib/std/os/uefi/protocols/hii_database_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Status = uefi.Status; | 8 | const Status = uefi.Status; |
lib/std/os/uefi/protocols/hii_popup_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Status = uefi.Status; | 8 | const Status = uefi.Status; |
lib/std/os/uefi/protocols/ip6_config_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Event = uefi.Event; | 8 | const Event = uefi.Event; |
lib/std/os/uefi/protocols/ip6_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Event = uefi.Event; | 8 | const Event = uefi.Event; |
lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Handle = uefi.Handle; | 7 | const Handle = uefi.Handle; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/loaded_image_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Handle = uefi.Handle; | 8 | const Handle = uefi.Handle; |
lib/std/os/uefi/protocols/managed_network_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Event = uefi.Event; | 8 | const Event = uefi.Event; |
lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Handle = uefi.Handle; | 7 | const Handle = uefi.Handle; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/rng_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Status = uefi.Status; | 8 | const Status = uefi.Status; |
lib/std/os/uefi/protocols/shell_parameters_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const FileHandle = uefi.FileHandle; | 8 | const FileHandle = uefi.FileHandle; |
lib/std/os/uefi/protocols/simple_file_system_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const FileProtocol = uefi.protocols.FileProtocol; | 8 | const FileProtocol = uefi.protocols.FileProtocol; |
lib/std/os/uefi/protocols/simple_network_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/simple_pointer_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/simple_text_input_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/protocols/simple_text_output_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Status = uefi.Status; | 8 | const Status = uefi.Status; |
lib/std/os/uefi/protocols/udp6_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const Event = uefi.Event; | 8 | const Event = uefi.Event; |
lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Handle = uefi.Handle; | 7 | const Handle = uefi.Handle; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/status.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const high_bit = 1 << @typeInfo(usize).Int.bits - 1; | 6 | const high_bit = 1 << @typeInfo(usize).Int.bits - 1; |
| 2 | 7 | ||
| 3 | pub const Status = extern enum(usize) { | 8 | pub const Status = extern enum(usize) { |
lib/std/os/uefi/tables.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const AllocateType = @import("tables/boot_services.zig").AllocateType; | 6 | pub const AllocateType = @import("tables/boot_services.zig").AllocateType; |
| 2 | pub const BootServices = @import("tables/boot_services.zig").BootServices; | 7 | pub const BootServices = @import("tables/boot_services.zig").BootServices; |
| 3 | pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; | 8 | pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; |
lib/std/os/uefi/tables/boot_services.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Event = uefi.Event; | 7 | const Event = uefi.Event; |
| 3 | const Guid = uefi.Guid; | 8 | const Guid = uefi.Guid; |
lib/std/os/uefi/tables/configuration_table.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | 8 |
lib/std/os/uefi/tables/runtime_services.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const Guid = uefi.Guid; | 7 | const Guid = uefi.Guid; |
| 3 | const TableHeader = uefi.tables.TableHeader; | 8 | const TableHeader = uefi.tables.TableHeader; |
lib/std/os/uefi/tables/system_table.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const uefi = @import("std").os.uefi; | 6 | const uefi = @import("std").os.uefi; |
| 2 | const BootServices = uefi.tables.BootServices; | 7 | const BootServices = uefi.tables.BootServices; |
| 3 | const ConfigurationTable = uefi.tables.ConfigurationTable; | 8 | const ConfigurationTable = uefi.tables.ConfigurationTable; |
lib/std/os/uefi/tables/table_header.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const TableHeader = extern struct { | 6 | pub const TableHeader = extern struct { |
| 2 | signature: u64, | 7 | signature: u64, |
| 3 | revision: u32, | 8 | revision: u32, |
lib/std/os/wasi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // wasi_snapshot_preview1 spec available (in witx format) here: | 6 | // wasi_snapshot_preview1 spec available (in witx format) here: |
| 2 | // * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx | 7 | // * typenames -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx |
| 3 | // * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx | 8 | // * module -- https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/wasi_snapshot_preview1.witx |
lib/std/os/windows.zig+7| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // This file contains thin wrappers around Windows-specific APIs, with these | 6 | // This file contains thin wrappers around Windows-specific APIs, with these |
| 2 | // specific goals in mind: | 7 | // specific goals in mind: |
| 3 | // * Convert "errno"-style error codes into Zig errors. | 8 | // * Convert "errno"-style error codes into Zig errors. |
| ... | @@ -469,6 +474,7 @@ pub const WriteFileError = error{ | ... | @@ -469,6 +474,7 @@ pub const WriteFileError = error{ |
| 469 | SystemResources, | 474 | SystemResources, |
| 470 | OperationAborted, | 475 | OperationAborted, |
| 471 | BrokenPipe, | 476 | BrokenPipe, |
| 477 | NotOpenForWriting, | ||
| 472 | Unexpected, | 478 | Unexpected, |
| 473 | }; | 479 | }; |
| 474 | 480 | ||
| ... | @@ -542,6 +548,7 @@ pub fn WriteFile( | ... | @@ -542,6 +548,7 @@ pub fn WriteFile( |
| 542 | .NOT_ENOUGH_QUOTA => return error.SystemResources, | 548 | .NOT_ENOUGH_QUOTA => return error.SystemResources, |
| 543 | .IO_PENDING => unreachable, | 549 | .IO_PENDING => unreachable, |
| 544 | .BROKEN_PIPE => return error.BrokenPipe, | 550 | .BROKEN_PIPE => return error.BrokenPipe, |
| 551 | .INVALID_HANDLE => return error.NotOpenForWriting, | ||
| 545 | else => |err| return unexpectedError(err), | 552 | else => |err| return unexpectedError(err), |
| 546 | } | 553 | } |
| 547 | } | 554 | } |
lib/std/os/windows/advapi32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "advapi32" fn RegOpenKeyExW( | 8 | pub extern "advapi32" fn RegOpenKeyExW( |
lib/std/os/windows/bits.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Platform-dependent types and values that are used along with OS-specific APIs. | 6 | // Platform-dependent types and values that are used along with OS-specific APIs. |
| 2 | 7 | ||
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
lib/std/os/windows/gdi32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub const PIXELFORMATDESCRIPTOR = extern struct { | 8 | pub const PIXELFORMATDESCRIPTOR = extern struct { |
lib/std/os/windows/kernel32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(.Stdcall) ?*c_void; | 8 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(.Stdcall) ?*c_void; |
lib/std/os/windows/lang.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const NEUTRAL = 0x00; | 6 | pub const NEUTRAL = 0x00; |
| 2 | pub const INVARIANT = 0x7f; | 7 | pub const INVARIANT = 0x7f; |
| 3 | pub const AFRIKAANS = 0x36; | 8 | pub const AFRIKAANS = 0x36; |
lib/std/os/windows/ntdll.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "NtDll" fn RtlGetVersion( | 8 | pub extern "NtDll" fn RtlGetVersion( |
lib/std/os/windows/ntstatus.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // NTSTATUS codes from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55? | 6 | // NTSTATUS codes from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55? |
| 2 | pub const NTSTATUS = extern enum(u32) { | 7 | pub const NTSTATUS = extern enum(u32) { |
| 3 | /// The operation completed successfully. | 8 | /// The operation completed successfully. |
lib/std/os/windows/ole32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "ole32" fn CoTaskMemFree(pv: LPVOID) callconv(.Stdcall) void; | 8 | pub extern "ole32" fn CoTaskMemFree(pv: LPVOID) callconv(.Stdcall) void; |
lib/std/os/windows/psapi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "psapi" fn EmptyWorkingSet(hProcess: HANDLE) callconv(.Stdcall) BOOL; | 8 | pub extern "psapi" fn EmptyWorkingSet(hProcess: HANDLE) callconv(.Stdcall) BOOL; |
lib/std/os/windows/shell32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub extern "shell32" fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*:0]WCHAR) callconv(.Stdcall) HRESULT; | 8 | pub extern "shell32" fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*:0]WCHAR) callconv(.Stdcall) HRESULT; |
lib/std/os/windows/sublang.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const NEUTRAL = 0x00; | 6 | pub const NEUTRAL = 0x00; |
| 2 | pub const DEFAULT = 0x01; | 7 | pub const DEFAULT = 0x01; |
| 3 | pub const SYS_DEFAULT = 0x02; | 8 | pub const SYS_DEFAULT = 0x02; |
lib/std/os/windows/user32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | // PM | 8 | // PM |
lib/std/os/windows/win32error.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Codes are from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d | 6 | // Codes are from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d |
| 2 | pub const Win32Error = extern enum(u16) { | 7 | pub const Win32Error = extern enum(u16) { |
| 3 | /// The operation completed successfully. | 8 | /// The operation completed successfully. |
lib/std/os/windows/ws2_32.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | usingnamespace @import("bits.zig"); | 6 | usingnamespace @import("bits.zig"); |
| 2 | 7 | ||
| 3 | pub const SOCKET = *@Type(.Opaque); | 8 | pub const SOCKET = *@Type(.Opaque); |
lib/std/packed_int_array.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const debug = std.debug; | 8 | const debug = std.debug; |
lib/std/pdb.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 7 | const std = @import("std.zig"); |
| 3 | const io = std.io; | 8 | const io = std.io; |
lib/std/priority_queue.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const Allocator = std.mem.Allocator; | 7 | const Allocator = std.mem.Allocator; |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/process.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/progress.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const windows = std.os.windows; | 7 | const windows = std.os.windows; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/rand.zig+7-2| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // The engines provided here should be initialized from an external source. For now, randomBytes | 6 | // The engines provided here should be initialized from an external source. For now, randomBytes |
| 2 | // from the crypto package is the most suitable. Be sure to use a CSPRNG when required, otherwise using | 7 | // from the crypto package is the most suitable. Be sure to use a CSPRNG when required, otherwise using |
| 3 | // a normal PRNG will be faster and use substantially less stack space. | 8 | // a normal PRNG will be faster and use substantially less stack space. |
| ... | @@ -732,12 +737,12 @@ test "xoroshiro sequence" { | ... | @@ -732,12 +737,12 @@ test "xoroshiro sequence" { |
| 732 | // CSPRNG | 737 | // CSPRNG |
| 733 | pub const Gimli = struct { | 738 | pub const Gimli = struct { |
| 734 | random: Random, | 739 | random: Random, |
| 735 | state: std.crypto.gimli.State, | 740 | state: std.crypto.core.Gimli, |
| 736 | 741 | ||
| 737 | pub fn init(init_s: u64) Gimli { | 742 | pub fn init(init_s: u64) Gimli { |
| 738 | var self = Gimli{ | 743 | var self = Gimli{ |
| 739 | .random = Random{ .fillFn = fill }, | 744 | .random = Random{ .fillFn = fill }, |
| 740 | .state = std.crypto.gimli.State{ | 745 | .state = std.crypto.core.Gimli{ |
| 741 | .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4), | 746 | .data = [_]u32{0} ** (std.crypto.gimli.State.BLOCKBYTES / 4), |
| 742 | }, | 747 | }, |
| 743 | }; | 748 | }; |
lib/std/rand/ziggurat.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Implements ZIGNOR [1]. | 6 | // Implements ZIGNOR [1]. |
| 2 | // | 7 | // |
| 3 | // [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to Generate Normal Random Samples*] | 8 | // [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to Generate Normal Random Samples*] |
lib/std/rb.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/reset_event.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/segmented_list.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/sort.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/special/build_runner.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const root = @import("@build"); | 6 | const root = @import("@build"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
lib/std/special/c.zig+6-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // This is Zig's multi-target implementation of libc. | 6 | // This is Zig's multi-target implementation of libc. |
| 2 | // When builtin.link_libc is true, we need to export all the functions and | 7 | // When builtin.link_libc is true, we need to export all the functions and |
| 3 | // provide an entire C API. | 8 | // provide an entire C API. |
| ... | @@ -35,7 +40,7 @@ comptime { | ... | @@ -35,7 +40,7 @@ comptime { |
| 35 | } | 40 | } |
| 36 | } | 41 | } |
| 37 | 42 | ||
| 38 | extern var _fltused: c_int = 1; | 43 | var _fltused: c_int = 1; |
| 39 | 44 | ||
| 40 | extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int; | 45 | extern fn main(argc: c_int, argv: [*:null]?[*:0]u8) c_int; |
| 41 | fn wasm_start() callconv(.C) void { | 46 | fn wasm_start() callconv(.C) void { |
lib/std/special/compiler_rt.zig+6-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const is_test = builtin.is_test; | 8 | const is_test = builtin.is_test; |
| ... | @@ -335,7 +340,7 @@ fn __stack_chk_fail() callconv(.C) noreturn { | ... | @@ -335,7 +340,7 @@ fn __stack_chk_fail() callconv(.C) noreturn { |
| 335 | @panic("stack smashing detected"); | 340 | @panic("stack smashing detected"); |
| 336 | } | 341 | } |
| 337 | 342 | ||
| 338 | extern var __stack_chk_guard: usize = blk: { | 343 | var __stack_chk_guard: usize = blk: { |
| 339 | var buf = [1]u8{0} ** @sizeOf(usize); | 344 | var buf = [1]u8{0} ** @sizeOf(usize); |
| 340 | buf[@sizeOf(usize) - 1] = 255; | 345 | buf[@sizeOf(usize) - 1] = 255; |
| 341 | buf[@sizeOf(usize) - 2] = '\n'; | 346 | buf[@sizeOf(usize) - 2] = '\n'; |
lib/std/special/compiler_rt/addXf3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc | 8 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc |
lib/std/special/compiler_rt/addXf3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c | 8 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c |
lib/std/special/compiler_rt/arm.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // ARM specific builtins | 6 | // ARM specific builtins |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/ashldi3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __ashldi3 = @import("shift.zig").__ashldi3; | 6 | const __ashldi3 = @import("shift.zig").__ashldi3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/ashlti3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __ashlti3 = @import("shift.zig").__ashlti3; | 6 | const __ashlti3 = @import("shift.zig").__ashlti3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/ashrdi3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __ashrdi3 = @import("shift.zig").__ashrdi3; | 6 | const __ashrdi3 = @import("shift.zig").__ashrdi3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/ashrti3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __ashrti3 = @import("shift.zig").__ashrti3; | 6 | const __ashrti3 = @import("shift.zig").__ashrti3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/atomics.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | 8 |
lib/std/special/compiler_rt/aulldiv.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 { | 8 | pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 { |
lib/std/special/compiler_rt/aullrem.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 { | 8 | pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 { |
lib/std/special/compiler_rt/clear_cache.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const arch = std.builtin.cpu.arch; | 7 | const arch = std.builtin.cpu.arch; |
| 3 | const os = std.builtin.os.tag; | 8 | const os = std.builtin.os.tag; |
lib/std/special/compiler_rt/clzsi2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | fn __clzsi2_generic(a: i32) callconv(.C) i32 { | 8 | fn __clzsi2_generic(a: i32) callconv(.C) i32 { |
lib/std/special/compiler_rt/clzsi2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const clzsi2 = @import("clzsi2.zig"); | 6 | const clzsi2 = @import("clzsi2.zig"); |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/compareXf2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c |
lib/std/special/compiler_rt/comparedf2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparedf2_test.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparedf2_test.c |
lib/std/special/compiler_rt/comparesf2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparesf2_test.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/comparesf2_test.c |
lib/std/special/compiler_rt/divdf3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c |
lib/std/special/compiler_rt/divdf3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divdf3_test.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divdf3_test.c |
lib/std/special/compiler_rt/divsf3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c |
lib/std/special/compiler_rt/divsf3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divsf3_test.c | 8 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/test/builtins/Unit/divsf3_test.c |
lib/std/special/compiler_rt/divtf3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/divtf3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const math = std.math; | 7 | const math = std.math; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/special/compiler_rt/divti3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const udivmod = @import("udivmod.zig").udivmod; | 6 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/divti3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __divti3 = @import("divti3.zig").__divti3; | 6 | const __divti3 = @import("divti3.zig").__divti3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/extendXfYf2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | 8 | const is_test = builtin.is_test; |
lib/std/special/compiler_rt/extendXfYf2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; | 7 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; |
| 3 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; | 8 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; |
lib/std/special/compiler_rt/fixdfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixdfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; | 6 | const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixdfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixdfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; | 6 | const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixdfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixdfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixdfti = @import("fixdfti.zig").__fixdfti; | 6 | const __fixdfti = @import("fixdfti.zig").__fixdfti; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixint.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const is_test = @import("builtin").is_test; | 6 | const is_test = @import("builtin").is_test; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixint_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const is_test = @import("builtin").is_test; | 6 | const is_test = @import("builtin").is_test; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixsfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixsfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; | 6 | const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixsfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixsfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; | 6 | const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixsfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixsfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixsfti = @import("fixsfti.zig").__fixsfti; | 6 | const __fixsfti = @import("fixsfti.zig").__fixsfti; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixtfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixtfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; | 6 | const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixtfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixtfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; | 6 | const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixtfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixint = @import("fixint.zig").fixint; | 6 | const fixint = @import("fixint.zig").fixint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixtfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixtfti = @import("fixtfti.zig").__fixtfti; | 6 | const __fixtfti = @import("fixtfti.zig").__fixtfti; |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/special/compiler_rt/fixuint.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const is_test = @import("builtin").is_test; | 6 | const is_test = @import("builtin").is_test; |
| 2 | const Log2Int = @import("std").math.Log2Int; | 7 | const Log2Int = @import("std").math.Log2Int; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; | 6 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; | 6 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunsdfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; | 6 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; | 6 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; | 6 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunssfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; | 6 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfdi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfdi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; | 6 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfsi.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfsi_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; | 6 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfti.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const fixuint = @import("fixuint.zig").fixuint; | 6 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/fixunstfti_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; | 6 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatdidf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | 8 |
lib/std/special/compiler_rt/floatdidf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatdidf = @import("floatdidf.zig").__floatdidf; | 6 | const __floatdidf = @import("floatdidf.zig").__floatdidf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatditf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatditf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatditf = @import("floatditf.zig").__floatditf; | 6 | const __floatditf = @import("floatditf.zig").__floatditf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatsiXf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/special/compiler_rt/floattidf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floattidf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floattidf = @import("floattidf.zig").__floattidf; | 6 | const __floattidf = @import("floattidf.zig").__floattidf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floattisf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floattisf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floattisf = @import("floattisf.zig").__floattisf; | 6 | const __floattisf = @import("floattisf.zig").__floattisf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floattitf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floattitf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floattitf = @import("floattitf.zig").__floattitf; | 6 | const __floattitf = @import("floattitf.zig").__floattitf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatundidf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | 8 |
lib/std/special/compiler_rt/floatundidf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatundidf = @import("floatundidf.zig").__floatundidf; | 6 | const __floatundidf = @import("floatundidf.zig").__floatundidf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatundisf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/special/compiler_rt/floatunditf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatunditf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatunditf = @import("floatunditf.zig").__floatunditf; | 6 | const __floatunditf = @import("floatunditf.zig").__floatunditf; |
| 2 | 7 | ||
| 3 | fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) void { | 8 | fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) void { |
lib/std/special/compiler_rt/floatunsidf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/special/compiler_rt/floatunsisf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/special/compiler_rt/floatunsitf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatunsitf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; | 6 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; |
| 2 | 7 | ||
| 3 | fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void { | 8 | fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void { |
lib/std/special/compiler_rt/floatuntidf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatuntidf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; | 6 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatuntisf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatuntisf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; | 6 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/floatuntitf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | const std = @import("std"); | 8 | const std = @import("std"); |
lib/std/special/compiler_rt/floatuntitf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; | 6 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/int.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Builtin functions that operate on integer types | 6 | // Builtin functions that operate on integer types |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const testing = @import("std").testing; | 8 | const testing = @import("std").testing; |
lib/std/special/compiler_rt/lshrdi3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __lshrdi3 = @import("shift.zig").__lshrdi3; | 6 | const __lshrdi3 = @import("shift.zig").__lshrdi3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/lshrti3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __lshrti3 = @import("shift.zig").__lshrti3; | 6 | const __lshrti3 = @import("shift.zig").__lshrti3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/modti3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/modti3.c | 8 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/modti3.c |
lib/std/special/compiler_rt/modti3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __modti3 = @import("modti3.zig").__modti3; | 6 | const __modti3 = @import("modti3.zig").__modti3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/mulXf3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc | 8 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc |
lib/std/special/compiler_rt/mulXf3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Ported from: | 6 | // Ported from: |
| 2 | // | 7 | // |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/test/builtins/Unit/multf3_test.c | 8 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/test/builtins/Unit/multf3_test.c |
lib/std/special/compiler_rt/muldi3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | // Ported from | 8 | // Ported from |
lib/std/special/compiler_rt/muldi3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __muldi3 = @import("muldi3.zig").__muldi3; | 6 | const __muldi3 = @import("muldi3.zig").__muldi3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/mulodi4.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 3 | const maxInt = std.math.maxInt; | 8 | const maxInt = std.math.maxInt; |
lib/std/special/compiler_rt/mulodi4_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __mulodi4 = @import("mulodi4.zig").__mulodi4; | 6 | const __mulodi4 = @import("mulodi4.zig").__mulodi4; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/muloti4.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 3 | 8 |
lib/std/special/compiler_rt/muloti4_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __muloti4 = @import("muloti4.zig").__muloti4; | 6 | const __muloti4 = @import("muloti4.zig").__muloti4; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/multi3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 3 | 8 |
lib/std/special/compiler_rt/multi3_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __multi3 = @import("multi3.zig").__multi3; | 6 | const __multi3 = @import("multi3.zig").__multi3; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/negXf2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | pub fn __negsf2(a: f32) callconv(.C) f32 { | 8 | pub fn __negsf2(a: f32) callconv(.C) f32 { |
lib/std/special/compiler_rt/popcountdi2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 3 | 8 |
lib/std/special/compiler_rt/popcountdi2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __popcountdi2 = @import("popcountdi2.zig").__popcountdi2; | 6 | const __popcountdi2 = @import("popcountdi2.zig").__popcountdi2; |
| 2 | const testing = @import("std").testing; | 7 | const testing = @import("std").testing; |
| 3 | 8 |
lib/std/special/compiler_rt/shift.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const Log2Int = std.math.Log2Int; | 8 | const Log2Int = std.math.Log2Int; |
lib/std/special/compiler_rt/stack_probe.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | 7 | ||
| 3 | // Zig's own stack-probe routine (available only on x86 and x86_64) | 8 | // Zig's own stack-probe routine (available only on x86 and x86_64) |
lib/std/special/compiler_rt/truncXfYf2.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | pub fn __truncsfhf2(a: f32) callconv(.C) u16 { | 8 | pub fn __truncsfhf2(a: f32) callconv(.C) u16 { |
lib/std/special/compiler_rt/truncXfYf2_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; | 6 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; |
| 2 | 7 | ||
| 3 | fn test__truncsfhf2(a: u32, expected: u16) void { | 8 | fn test__truncsfhf2(a: u32, expected: u16) void { |
lib/std/special/compiler_rt/udivmod.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 3 | 8 |
lib/std/special/compiler_rt/udivmoddi4_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Disable formatting to avoid unnecessary source repository bloat. | 6 | // Disable formatting to avoid unnecessary source repository bloat. |
| 2 | // zig fmt: off | 7 | // zig fmt: off |
| 3 | const __udivmoddi4 = @import("int.zig").__udivmoddi4; | 8 | const __udivmoddi4 = @import("int.zig").__udivmoddi4; |
lib/std/special/compiler_rt/udivmodti4.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const udivmod = @import("udivmod.zig").udivmod; | 6 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | 8 | const compiler_rt = @import("../compiler_rt.zig"); |
lib/std/special/compiler_rt/udivmodti4_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // Disable formatting to avoid unnecessary source repository bloat. | 6 | // Disable formatting to avoid unnecessary source repository bloat. |
| 2 | // zig fmt: off | 7 | // zig fmt: off |
| 3 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; | 8 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
lib/std/special/compiler_rt/udivti3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const udivmodti4 = @import("udivmodti4.zig"); | 6 | const udivmodti4 = @import("udivmodti4.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/special/compiler_rt/umodti3.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const udivmodti4 = @import("udivmodti4.zig"); | 6 | const udivmodti4 = @import("udivmodti4.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | 8 | const compiler_rt = @import("../compiler_rt.zig"); |
lib/std/special/init-exe/build.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const Builder = @import("std").build.Builder; | 6 | const Builder = @import("std").build.Builder; |
| 2 | 7 | ||
| 3 | pub fn build(b: *Builder) void { | 8 | pub fn build(b: *Builder) void { |
lib/std/special/init-exe/src/main.zig+6-1| ... | @@ -1,5 +1,10 @@ | ... | @@ -1,5 +1,10 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | pub fn main() anyerror!void { | 8 | pub fn main() anyerror!void { |
| 4 | std.debug.warn("All your codebase are belong to us.\n", .{}); | 9 | std.log.info("All your codebase are belong to us.", .{}); |
| 5 | } | 10 | } |
lib/std/special/init-lib/build.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const Builder = @import("std").build.Builder; | 6 | const Builder = @import("std").build.Builder; |
| 2 | 7 | ||
| 3 | pub fn build(b: *Builder) void { | 8 | pub fn build(b: *Builder) void { |
lib/std/special/init-lib/src/main.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | 8 |
lib/std/special/test_runner.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const io = std.io; | 7 | const io = std.io; |
| 3 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
lib/std/spinlock.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | 8 |
lib/std/start.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | // This file is included in the compilation unit when exporting an executable. | 6 | // This file is included in the compilation unit when exporting an executable. |
| 2 | 7 | ||
| 3 | const root = @import("root"); | 8 | const root = @import("root"); |
lib/std/start_windows_tls.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | 8 |
lib/std/std.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | pub const ArrayList = @import("array_list.zig").ArrayList; | 6 | pub const ArrayList = @import("array_list.zig").ArrayList; |
| 2 | pub const ArrayListAligned = @import("array_list.zig").ArrayListAligned; | 7 | pub const ArrayListAligned = @import("array_list.zig").ArrayListAligned; |
| 3 | pub const ArrayListAlignedUnmanaged = @import("array_list.zig").ArrayListAlignedUnmanaged; | 8 | pub const ArrayListAlignedUnmanaged = @import("array_list.zig").ArrayListAlignedUnmanaged; |
lib/std/target.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const builtin = std.builtin; | 8 | const builtin = std.builtin; |
lib/std/target/aarch64.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/amdgpu.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/arm.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/avr.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/bpf.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/hexagon.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/mips.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/msp430.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/nvptx.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/powerpc.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/riscv.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/sparc.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/systemz.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/wasm.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/target/x86.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const CpuFeature = std.Target.Cpu.Feature; | 7 | const CpuFeature = std.Target.Cpu.Feature; |
| 3 | const CpuModel = std.Target.Cpu.Model; | 8 | const CpuModel = std.Target.Cpu.Model; |
lib/std/testing.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const print = std.debug.print; | 7 | const print = std.debug.print; |
| 3 | 8 |
lib/std/testing/failing_allocator.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
lib/std/thread.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const os = std.os; | 8 | const os = std.os; |
lib/std/time.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const builtin = std.builtin; | 7 | const builtin = std.builtin; |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/time/epoch.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | //! Epoch reference times in terms of their difference from | 6 | //! Epoch reference times in terms of their difference from |
| 2 | //! UTC 1970-01-01 in seconds. | 7 | //! UTC 1970-01-01 in seconds. |
| 3 | 8 |
lib/std/unicode.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("./std.zig"); | 6 | const std = @import("./std.zig"); |
| 2 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
lib/std/unicode/throughput_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 7 | const std = @import("std"); |
| 3 | 8 |
lib/std/valgrind.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 2 | const std = @import("std.zig"); | 7 | const std = @import("std.zig"); |
| 3 | const math = std.math; | 8 | const math = std.math; |
lib/std/valgrind/callgrind.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const valgrind = std.valgrind; | 7 | const valgrind = std.valgrind; |
| 3 | 8 |
lib/std/valgrind/memcheck.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const testing = std.testing; | 7 | const testing = std.testing; |
| 3 | const valgrind = std.valgrind; | 8 | const valgrind = std.valgrind; |
lib/std/zig.zig+115-1| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std.zig"); | 6 | const std = @import("std.zig"); |
| 2 | const tokenizer = @import("zig/tokenizer.zig"); | 7 | const tokenizer = @import("zig/tokenizer.zig"); |
| 3 | 8 | ||
| ... | @@ -21,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash { | ... | @@ -21,7 +26,7 @@ pub fn hashSrc(src: []const u8) SrcHash { |
| 21 | std.mem.copy(u8, &out, src); | 26 | std.mem.copy(u8, &out, src); |
| 22 | std.mem.set(u8, out[src.len..], 0); | 27 | std.mem.set(u8, out[src.len..], 0); |
| 23 | } else { | 28 | } else { |
| 24 | std.crypto.Blake3.hash(src, &out); | 29 | std.crypto.hash.Blake3.hash(src, &out, .{}); |
| 25 | } | 30 | } |
| 26 | return out; | 31 | return out; |
| 27 | } | 32 | } |
| ... | @@ -80,6 +85,115 @@ pub fn binNameAlloc( | ... | @@ -80,6 +85,115 @@ pub fn binNameAlloc( |
| 80 | } | 85 | } |
| 81 | } | 86 | } |
| 82 | 87 | ||
| 88 | /// Only validates escape sequence characters. | ||
| 89 | /// Slice must be valid utf8 starting and ending with "'" and exactly one codepoint in between. | ||
| 90 | pub fn parseCharLiteral( | ||
| 91 | slice: []const u8, | ||
| 92 | bad_index: *usize, // populated if error.InvalidCharacter is returned | ||
| 93 | ) error{InvalidCharacter}!u32 { | ||
| 94 | std.debug.assert(slice.len >= 3 and slice[0] == '\'' and slice[slice.len - 1] == '\''); | ||
| 95 | |||
| 96 | if (slice[1] == '\\') { | ||
| 97 | switch (slice[2]) { | ||
| 98 | 'n' => return '\n', | ||
| 99 | 'r' => return '\r', | ||
| 100 | '\\' => return '\\', | ||
| 101 | 't' => return '\t', | ||
| 102 | '\'' => return '\'', | ||
| 103 | '"' => return '"', | ||
| 104 | 'x' => { | ||
| 105 | if (slice.len != 6) { | ||
| 106 | bad_index.* = slice.len - 2; | ||
| 107 | return error.InvalidCharacter; | ||
| 108 | } | ||
| 109 | var value: u32 = 0; | ||
| 110 | for (slice[3..5]) |c, i| { | ||
| 111 | switch (c) { | ||
| 112 | '0'...'9' => { | ||
| 113 | value *= 16; | ||
| 114 | value += c - '0'; | ||
| 115 | }, | ||
| 116 | 'a'...'f' => { | ||
| 117 | value *= 16; | ||
| 118 | value += c - 'a' + 10; | ||
| 119 | }, | ||
| 120 | 'A'...'F' => { | ||
| 121 | value *= 16; | ||
| 122 | value += c - 'A' + 10; | ||
| 123 | }, | ||
| 124 | else => { | ||
| 125 | bad_index.* = 3 + i; | ||
| 126 | return error.InvalidCharacter; | ||
| 127 | }, | ||
| 128 | } | ||
| 129 | } | ||
| 130 | return value; | ||
| 131 | }, | ||
| 132 | 'u' => { | ||
| 133 | if (slice.len < "'\\u{0}'".len or slice[3] != '{' or slice[slice.len - 2] != '}') { | ||
| 134 | bad_index.* = 2; | ||
| 135 | return error.InvalidCharacter; | ||
| 136 | } | ||
| 137 | var value: u32 = 0; | ||
| 138 | for (slice[4 .. slice.len - 2]) |c, i| { | ||
| 139 | switch (c) { | ||
| 140 | '0'...'9' => { | ||
| 141 | value *= 16; | ||
| 142 | value += c - '0'; | ||
| 143 | }, | ||
| 144 | 'a'...'f' => { | ||
| 145 | value *= 16; | ||
| 146 | value += c - 'a' + 10; | ||
| 147 | }, | ||
| 148 | 'A'...'F' => { | ||
| 149 | value *= 16; | ||
| 150 | value += c - 'A' + 10; | ||
| 151 | }, | ||
| 152 | else => { | ||
| 153 | bad_index.* = 4 + i; | ||
| 154 | return error.InvalidCharacter; | ||
| 155 | }, | ||
| 156 | } | ||
| 157 | if (value > 0x10ffff) { | ||
| 158 | bad_index.* = 4 + i; | ||
| 159 | return error.InvalidCharacter; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | return value; | ||
| 163 | }, | ||
| 164 | else => { | ||
| 165 | bad_index.* = 2; | ||
| 166 | return error.InvalidCharacter; | ||
| 167 | }, | ||
| 168 | } | ||
| 169 | } | ||
| 170 | return std.unicode.utf8Decode(slice[1 .. slice.len - 1]) catch unreachable; | ||
| 171 | } | ||
| 172 | |||
| 173 | test "parseCharLiteral" { | ||
| 174 | var bad_index: usize = undefined; | ||
| 175 | std.testing.expectEqual(try parseCharLiteral("'a'", &bad_index), 'a'); | ||
| 176 | std.testing.expectEqual(try parseCharLiteral("'ä'", &bad_index), 'ä'); | ||
| 177 | std.testing.expectEqual(try parseCharLiteral("'\\x00'", &bad_index), 0); | ||
| 178 | std.testing.expectEqual(try parseCharLiteral("'\\x4f'", &bad_index), 0x4f); | ||
| 179 | std.testing.expectEqual(try parseCharLiteral("'\\x4F'", &bad_index), 0x4f); | ||
| 180 | std.testing.expectEqual(try parseCharLiteral("'ぁ'", &bad_index), 0x3041); | ||
| 181 | std.testing.expectEqual(try parseCharLiteral("'\\u{0}'", &bad_index), 0); | ||
| 182 | std.testing.expectEqual(try parseCharLiteral("'\\u{3041}'", &bad_index), 0x3041); | ||
| 183 | std.testing.expectEqual(try parseCharLiteral("'\\u{7f}'", &bad_index), 0x7f); | ||
| 184 | std.testing.expectEqual(try parseCharLiteral("'\\u{7FFF}'", &bad_index), 0x7FFF); | ||
| 185 | |||
| 186 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x0'", &bad_index)); | ||
| 187 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\x000'", &bad_index)); | ||
| 188 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\y'", &bad_index)); | ||
| 189 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u'", &bad_index)); | ||
| 190 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\uFFFF'", &bad_index)); | ||
| 191 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{}'", &bad_index)); | ||
| 192 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFFFF}'", &bad_index)); | ||
| 193 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFF'", &bad_index)); | ||
| 194 | std.testing.expectError(error.InvalidCharacter, parseCharLiteral("'\\u{FFFF}x'", &bad_index)); | ||
| 195 | } | ||
| 196 | |||
| 83 | test "" { | 197 | test "" { |
| 84 | @import("std").meta.refAllDecls(@This()); | 198 | @import("std").meta.refAllDecls(@This()); |
| 85 | } | 199 | } |
lib/std/zig/ast.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const testing = std.testing; | 8 | const testing = std.testing; |
lib/std/zig/cross_target.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const Target = std.Target; | 8 | const Target = std.Target; |
lib/std/zig/parse.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
lib/std/zig/parser_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | test "zig fmt: convert var to anytype" { | 6 | test "zig fmt: convert var to anytype" { |
| 2 | // TODO remove in next release cycle | 7 | // TODO remove in next release cycle |
| 3 | try testTransform( | 8 | try testTransform( |
lib/std/zig/perf_test.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | const warn = std.debug.warn; | 8 | const warn = std.debug.warn; |
lib/std/zig/render.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
lib/std/zig/string_literal.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 3 | 8 |
lib/std/zig/system.zig+6| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const elf = std.elf; | 7 | const elf = std.elf; |
| 3 | const mem = std.mem; | 8 | const mem = std.mem; |
| ... | @@ -857,6 +862,7 @@ pub const NativeTargetInfo = struct { | ... | @@ -857,6 +862,7 @@ pub const NativeTargetInfo = struct { |
| 857 | const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) { | 862 | const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) { |
| 858 | error.OperationAborted => unreachable, // Windows-only | 863 | error.OperationAborted => unreachable, // Windows-only |
| 859 | error.WouldBlock => unreachable, // Did not request blocking mode | 864 | error.WouldBlock => unreachable, // Did not request blocking mode |
| 865 | error.NotOpenForReading => unreachable, | ||
| 860 | error.SystemResources => return error.SystemResources, | 866 | error.SystemResources => return error.SystemResources, |
| 861 | error.IsDir => return error.UnableToReadElfFile, | 867 | error.IsDir => return error.UnableToReadElfFile, |
| 862 | error.BrokenPipe => return error.UnableToReadElfFile, | 868 | error.BrokenPipe => return error.UnableToReadElfFile, |
lib/std/zig/system/macos.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | 7 | ||
| 3 | pub fn version_from_build(build: []const u8) !std.builtin.Version { | 8 | pub fn version_from_build(build: []const u8) !std.builtin.Version { |
lib/std/zig/system/x86.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("std"); | 6 | const std = @import("std"); |
| 2 | const Target = std.Target; | 7 | const Target = std.Target; |
| 3 | const CrossTarget = std.zig.CrossTarget; | 8 | const CrossTarget = std.zig.CrossTarget; |
lib/std/zig/tokenizer.zig+5| ... | @@ -1,3 +1,8 @@ | ... | @@ -1,3 +1,8 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2020 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 1 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 2 | const mem = std.mem; | 7 | const mem = std.mem; |
| 3 | 8 |
src-self-hosted/Module.zig+412-14| ... | @@ -170,6 +170,9 @@ pub const Decl = struct { | ... | @@ -170,6 +170,9 @@ pub const Decl = struct { |
| 170 | /// This flag is set when this Decl is added to a check_for_deletion set, and cleared | 170 | /// This flag is set when this Decl is added to a check_for_deletion set, and cleared |
| 171 | /// when removed. | 171 | /// when removed. |
| 172 | deletion_flag: bool, | 172 | deletion_flag: bool, |
| 173 | /// Whether the corresponding AST decl has a `pub` keyword. | ||
| 174 | is_pub: bool, | ||
| 175 | |||
| 173 | /// An integer that can be checked against the corresponding incrementing | 176 | /// An integer that can be checked against the corresponding incrementing |
| 174 | /// generation field of Module. This is used to determine whether `complete` status | 177 | /// generation field of Module. This is used to determine whether `complete` status |
| 175 | /// represents pre- or post- re-analysis. | 178 | /// represents pre- or post- re-analysis. |
| ... | @@ -320,6 +323,16 @@ pub const Fn = struct { | ... | @@ -320,6 +323,16 @@ pub const Fn = struct { |
| 320 | } | 323 | } |
| 321 | }; | 324 | }; |
| 322 | 325 | ||
| 326 | pub const Var = struct { | ||
| 327 | /// if is_extern == true this is undefined | ||
| 328 | init: Value, | ||
| 329 | owner_decl: *Decl, | ||
| 330 | |||
| 331 | is_extern: bool, | ||
| 332 | is_mutable: bool, | ||
| 333 | is_threadlocal: bool, | ||
| 334 | }; | ||
| 335 | |||
| 323 | pub const Scope = struct { | 336 | pub const Scope = struct { |
| 324 | tag: Tag, | 337 | tag: Tag, |
| 325 | 338 | ||
| ... | @@ -1235,6 +1248,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1235,6 +1248,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1235 | }; | 1248 | }; |
| 1236 | defer fn_type_scope.instructions.deinit(self.gpa); | 1249 | defer fn_type_scope.instructions.deinit(self.gpa); |
| 1237 | 1250 | ||
| 1251 | decl.is_pub = fn_proto.getTrailer("visib_token") != null; | ||
| 1238 | const body_node = fn_proto.getTrailer("body_node") orelse | 1252 | const body_node = fn_proto.getTrailer("body_node") orelse |
| 1239 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); | 1253 | return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{}); |
| 1240 | 1254 | ||
| ... | @@ -1419,8 +1433,213 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1419,8 +1433,213 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1419 | } | 1433 | } |
| 1420 | return type_changed; | 1434 | return type_changed; |
| 1421 | }, | 1435 | }, |
| 1422 | .VarDecl => @panic("TODO var decl"), | 1436 | .VarDecl => { |
| 1423 | .Comptime => @panic("TODO comptime decl"), | 1437 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", ast_node); |
| 1438 | |||
| 1439 | decl.analysis = .in_progress; | ||
| 1440 | |||
| 1441 | // We need the memory for the Type to go into the arena for the Decl | ||
| 1442 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1443 | errdefer decl_arena.deinit(); | ||
| 1444 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | ||
| 1445 | |||
| 1446 | var block_scope: Scope.Block = .{ | ||
| 1447 | .parent = null, | ||
| 1448 | .func = null, | ||
| 1449 | .decl = decl, | ||
| 1450 | .instructions = .{}, | ||
| 1451 | .arena = &decl_arena.allocator, | ||
| 1452 | }; | ||
| 1453 | defer block_scope.instructions.deinit(self.gpa); | ||
| 1454 | |||
| 1455 | decl.is_pub = var_decl.getTrailer("visib_token") != null; | ||
| 1456 | const is_extern = blk: { | ||
| 1457 | const maybe_extern_token = var_decl.getTrailer("extern_export_token") orelse | ||
| 1458 | break :blk false; | ||
| 1459 | if (tree.token_ids[maybe_extern_token] != .Keyword_extern) break :blk false; | ||
| 1460 | if (var_decl.getTrailer("init_node")) |some| { | ||
| 1461 | return self.failNode(&block_scope.base, some, "extern variables have no initializers", .{}); | ||
| 1462 | } | ||
| 1463 | break :blk true; | ||
| 1464 | }; | ||
| 1465 | if (var_decl.getTrailer("lib_name")) |lib_name| { | ||
| 1466 | assert(is_extern); | ||
| 1467 | return self.failNode(&block_scope.base, lib_name, "TODO implement function library name", .{}); | ||
| 1468 | } | ||
| 1469 | const is_mutable = tree.token_ids[var_decl.mut_token] == .Keyword_var; | ||
| 1470 | const is_threadlocal = if (var_decl.getTrailer("thread_local_token")) |some| blk: { | ||
| 1471 | if (!is_mutable) { | ||
| 1472 | return self.failTok(&block_scope.base, some, "threadlocal variable cannot be constant", .{}); | ||
| 1473 | } | ||
| 1474 | break :blk true; | ||
| 1475 | } else false; | ||
| 1476 | assert(var_decl.getTrailer("comptime_token") == null); | ||
| 1477 | if (var_decl.getTrailer("align_node")) |align_expr| { | ||
| 1478 | return self.failNode(&block_scope.base, align_expr, "TODO implement function align expression", .{}); | ||
| 1479 | } | ||
| 1480 | if (var_decl.getTrailer("section_node")) |sect_expr| { | ||
| 1481 | return self.failNode(&block_scope.base, sect_expr, "TODO implement function section expression", .{}); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | const explicit_type = blk: { | ||
| 1485 | const type_node = var_decl.getTrailer("type_node") orelse | ||
| 1486 | break :blk null; | ||
| 1487 | |||
| 1488 | // Temporary arena for the zir instructions. | ||
| 1489 | var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1490 | defer type_scope_arena.deinit(); | ||
| 1491 | var type_scope: Scope.GenZIR = .{ | ||
| 1492 | .decl = decl, | ||
| 1493 | .arena = &type_scope_arena.allocator, | ||
| 1494 | .parent = decl.scope, | ||
| 1495 | }; | ||
| 1496 | defer type_scope.instructions.deinit(self.gpa); | ||
| 1497 | |||
| 1498 | const src = tree.token_locs[type_node.firstToken()].start; | ||
| 1499 | const type_type = try astgen.addZIRInstConst(self, &type_scope.base, src, .{ | ||
| 1500 | .ty = Type.initTag(.type), | ||
| 1501 | .val = Value.initTag(.type_type), | ||
| 1502 | }); | ||
| 1503 | const var_type = try astgen.expr(self, &type_scope.base, .{ .ty = type_type }, type_node); | ||
| 1504 | _ = try astgen.addZIRUnOp(self, &type_scope.base, src, .@"return", var_type); | ||
| 1505 | |||
| 1506 | break :blk try zir_sema.analyzeBodyValueAsType(self, &block_scope, .{ | ||
| 1507 | .instructions = type_scope.instructions.items, | ||
| 1508 | }); | ||
| 1509 | }; | ||
| 1510 | |||
| 1511 | var var_type: Type = undefined; | ||
| 1512 | const value: ?Value = if (var_decl.getTrailer("init_node")) |init_node| blk: { | ||
| 1513 | var gen_scope_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1514 | defer gen_scope_arena.deinit(); | ||
| 1515 | var gen_scope: Scope.GenZIR = .{ | ||
| 1516 | .decl = decl, | ||
| 1517 | .arena = &gen_scope_arena.allocator, | ||
| 1518 | .parent = decl.scope, | ||
| 1519 | }; | ||
| 1520 | defer gen_scope.instructions.deinit(self.gpa); | ||
| 1521 | const src = tree.token_locs[init_node.firstToken()].start; | ||
| 1522 | |||
| 1523 | // TODO comptime scope here | ||
| 1524 | const init_inst = try astgen.expr(self, &gen_scope.base, .none, init_node); | ||
| 1525 | _ = try astgen.addZIRUnOp(self, &gen_scope.base, src, .@"return", init_inst); | ||
| 1526 | |||
| 1527 | var inner_block: Scope.Block = .{ | ||
| 1528 | .parent = null, | ||
| 1529 | .func = null, | ||
| 1530 | .decl = decl, | ||
| 1531 | .instructions = .{}, | ||
| 1532 | .arena = &gen_scope_arena.allocator, | ||
| 1533 | }; | ||
| 1534 | defer inner_block.instructions.deinit(self.gpa); | ||
| 1535 | try zir_sema.analyzeBody(self, &inner_block.base, .{ .instructions = gen_scope.instructions.items }); | ||
| 1536 | |||
| 1537 | for (inner_block.instructions.items) |inst| { | ||
| 1538 | if (inst.castTag(.ret)) |ret| { | ||
| 1539 | const coerced = if (explicit_type) |some| | ||
| 1540 | try self.coerce(&inner_block.base, some, ret.operand) | ||
| 1541 | else | ||
| 1542 | ret.operand; | ||
| 1543 | const val = coerced.value() orelse | ||
| 1544 | return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{}); | ||
| 1545 | |||
| 1546 | var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena); | ||
| 1547 | break :blk try val.copy(block_scope.arena); | ||
| 1548 | } else { | ||
| 1549 | return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{}); | ||
| 1550 | } | ||
| 1551 | } | ||
| 1552 | unreachable; | ||
| 1553 | } else if (!is_extern) { | ||
| 1554 | return self.failTok(&block_scope.base, var_decl.firstToken(), "variables must be initialized", .{}); | ||
| 1555 | } else if (explicit_type) |some| blk: { | ||
| 1556 | var_type = some; | ||
| 1557 | break :blk null; | ||
| 1558 | } else { | ||
| 1559 | return self.failTok(&block_scope.base, var_decl.firstToken(), "unable to infer variable type", .{}); | ||
| 1560 | }; | ||
| 1561 | |||
| 1562 | if (is_mutable and !var_type.isValidVarType(is_extern)) { | ||
| 1563 | return self.failTok(&block_scope.base, var_decl.firstToken(), "variable of type '{}' must be const", .{var_type}); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | var type_changed = true; | ||
| 1567 | if (decl.typedValueManaged()) |tvm| { | ||
| 1568 | type_changed = !tvm.typed_value.ty.eql(var_type); | ||
| 1569 | |||
| 1570 | tvm.deinit(self.gpa); | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | const new_variable = try decl_arena.allocator.create(Var); | ||
| 1574 | const var_payload = try decl_arena.allocator.create(Value.Payload.Variable); | ||
| 1575 | new_variable.* = .{ | ||
| 1576 | .owner_decl = decl, | ||
| 1577 | .init = value orelse undefined, | ||
| 1578 | .is_extern = is_extern, | ||
| 1579 | .is_mutable = is_mutable, | ||
| 1580 | .is_threadlocal = is_threadlocal, | ||
| 1581 | }; | ||
| 1582 | var_payload.* = .{ .variable = new_variable }; | ||
| 1583 | |||
| 1584 | decl_arena_state.* = decl_arena.state; | ||
| 1585 | decl.typed_value = .{ | ||
| 1586 | .most_recent = .{ | ||
| 1587 | .typed_value = .{ | ||
| 1588 | .ty = var_type, | ||
| 1589 | .val = Value.initPayload(&var_payload.base), | ||
| 1590 | }, | ||
| 1591 | .arena = decl_arena_state, | ||
| 1592 | }, | ||
| 1593 | }; | ||
| 1594 | decl.analysis = .complete; | ||
| 1595 | decl.generation = self.generation; | ||
| 1596 | |||
| 1597 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | ||
| 1598 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | ||
| 1599 | const export_src = tree.token_locs[maybe_export_token].start; | ||
| 1600 | const name_loc = tree.token_locs[var_decl.name_token]; | ||
| 1601 | const name = tree.tokenSliceLoc(name_loc); | ||
| 1602 | // The scope needs to have the decl in it. | ||
| 1603 | try self.analyzeExport(&block_scope.base, export_src, name, decl); | ||
| 1604 | } | ||
| 1605 | } | ||
| 1606 | return type_changed; | ||
| 1607 | }, | ||
| 1608 | .Comptime => { | ||
| 1609 | const comptime_decl = @fieldParentPtr(ast.Node.Comptime, "base", ast_node); | ||
| 1610 | |||
| 1611 | decl.analysis = .in_progress; | ||
| 1612 | |||
| 1613 | // A comptime decl does not store any value so we can just deinit this arena after analysis is done. | ||
| 1614 | var analysis_arena = std.heap.ArenaAllocator.init(self.gpa); | ||
| 1615 | defer analysis_arena.deinit(); | ||
| 1616 | var gen_scope: Scope.GenZIR = .{ | ||
| 1617 | .decl = decl, | ||
| 1618 | .arena = &analysis_arena.allocator, | ||
| 1619 | .parent = decl.scope, | ||
| 1620 | }; | ||
| 1621 | defer gen_scope.instructions.deinit(self.gpa); | ||
| 1622 | |||
| 1623 | // TODO comptime scope here | ||
| 1624 | _ = try astgen.expr(self, &gen_scope.base, .none, comptime_decl.expr); | ||
| 1625 | |||
| 1626 | var block_scope: Scope.Block = .{ | ||
| 1627 | .parent = null, | ||
| 1628 | .func = null, | ||
| 1629 | .decl = decl, | ||
| 1630 | .instructions = .{}, | ||
| 1631 | .arena = &analysis_arena.allocator, | ||
| 1632 | }; | ||
| 1633 | defer block_scope.instructions.deinit(self.gpa); | ||
| 1634 | |||
| 1635 | _ = try zir_sema.analyzeBody(self, &block_scope.base, .{ | ||
| 1636 | .instructions = gen_scope.instructions.items, | ||
| 1637 | }); | ||
| 1638 | |||
| 1639 | decl.analysis = .complete; | ||
| 1640 | decl.generation = self.generation; | ||
| 1641 | return true; | ||
| 1642 | }, | ||
| 1424 | .Use => @panic("TODO usingnamespace decl"), | 1643 | .Use => @panic("TODO usingnamespace decl"), |
| 1425 | else => unreachable, | 1644 | else => unreachable, |
| 1426 | } | 1645 | } |
| ... | @@ -1583,11 +1802,53 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { | ... | @@ -1583,11 +1802,53 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { |
| 1583 | } | 1802 | } |
| 1584 | } | 1803 | } |
| 1585 | } | 1804 | } |
| 1805 | } else if (src_decl.castTag(.VarDecl)) |var_decl| { | ||
| 1806 | const name_loc = tree.token_locs[var_decl.name_token]; | ||
| 1807 | const name = tree.tokenSliceLoc(name_loc); | ||
| 1808 | const name_hash = root_scope.fullyQualifiedNameHash(name); | ||
| 1809 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl)); | ||
| 1810 | if (self.decl_table.get(name_hash)) |decl| { | ||
| 1811 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | ||
| 1812 | // have been re-ordered. | ||
| 1813 | decl.src_index = decl_i; | ||
| 1814 | if (deleted_decls.remove(decl) == null) { | ||
| 1815 | decl.analysis = .sema_failure; | ||
| 1816 | const err_msg = try ErrorMsg.create(self.gpa, name_loc.start, "redefinition of '{}'", .{decl.name}); | ||
| 1817 | errdefer err_msg.destroy(self.gpa); | ||
| 1818 | try self.failed_decls.putNoClobber(self.gpa, decl, err_msg); | ||
| 1819 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { | ||
| 1820 | try self.markOutdatedDecl(decl); | ||
| 1821 | decl.contents_hash = contents_hash; | ||
| 1822 | } | ||
| 1823 | } else { | ||
| 1824 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); | ||
| 1825 | root_scope.decls.appendAssumeCapacity(new_decl); | ||
| 1826 | if (var_decl.getTrailer("extern_export_token")) |maybe_export_token| { | ||
| 1827 | if (tree.token_ids[maybe_export_token] == .Keyword_export) { | ||
| 1828 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | ||
| 1829 | } | ||
| 1830 | } | ||
| 1831 | } | ||
| 1832 | } else if (src_decl.castTag(.Comptime)) |comptime_node| { | ||
| 1833 | const name_index = self.getNextAnonNameIndex(); | ||
| 1834 | const name = try std.fmt.allocPrint(self.gpa, "__comptime_{}", .{name_index}); | ||
| 1835 | defer self.gpa.free(name); | ||
| 1836 | |||
| 1837 | const name_hash = root_scope.fullyQualifiedNameHash(name); | ||
| 1838 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl)); | ||
| 1839 | |||
| 1840 | const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); | ||
| 1841 | root_scope.decls.appendAssumeCapacity(new_decl); | ||
| 1842 | self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | ||
| 1843 | } else if (src_decl.castTag(.ContainerField)) |container_field| { | ||
| 1844 | log.err("TODO: analyze container field", .{}); | ||
| 1845 | } else if (src_decl.castTag(.TestDecl)) |test_decl| { | ||
| 1846 | log.err("TODO: analyze test decl", .{}); | ||
| 1847 | } else if (src_decl.castTag(.Use)) |use_decl| { | ||
| 1848 | log.err("TODO: analyze usingnamespace decl", .{}); | ||
| 1586 | } else { | 1849 | } else { |
| 1587 | std.debug.panic("TODO: analyzeRootSrcFile {}", .{src_decl.tag}); | 1850 | unreachable; |
| 1588 | } | 1851 | } |
| 1589 | // TODO also look for global variable declarations | ||
| 1590 | // TODO also look for comptime blocks and exported globals | ||
| 1591 | } | 1852 | } |
| 1592 | // Handle explicitly deleted decls from the source code. Not to be confused | 1853 | // Handle explicitly deleted decls from the source code. Not to be confused |
| 1593 | // with when we delete decls because they are no longer referenced. | 1854 | // with when we delete decls because they are no longer referenced. |
| ... | @@ -1790,6 +2051,7 @@ fn allocateNewDecl( | ... | @@ -1790,6 +2051,7 @@ fn allocateNewDecl( |
| 1790 | .wasm => .{ .wasm = null }, | 2051 | .wasm => .{ .wasm = null }, |
| 1791 | }, | 2052 | }, |
| 1792 | .generation = 0, | 2053 | .generation = 0, |
| 2054 | .is_pub = false, | ||
| 1793 | }; | 2055 | }; |
| 1794 | return new_decl; | 2056 | return new_decl; |
| 1795 | } | 2057 | } |
| ... | @@ -2209,20 +2471,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn | ... | @@ -2209,20 +2471,46 @@ pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) Inn |
| 2209 | }; | 2471 | }; |
| 2210 | 2472 | ||
| 2211 | const decl_tv = try decl.typedValue(); | 2473 | const decl_tv = try decl.typedValue(); |
| 2212 | const ty_payload = try scope.arena().create(Type.Payload.Pointer); | 2474 | if (decl_tv.val.tag() == .variable) { |
| 2213 | ty_payload.* = .{ | 2475 | return self.analyzeVarRef(scope, src, decl_tv); |
| 2214 | .base = .{ .tag = .single_const_pointer }, | 2476 | } |
| 2215 | .pointee_type = decl_tv.ty, | 2477 | const ty = try self.simplePtrType(scope, src, decl_tv.ty, false, .One); |
| 2216 | }; | ||
| 2217 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); | 2478 | const val_payload = try scope.arena().create(Value.Payload.DeclRef); |
| 2218 | val_payload.* = .{ .decl = decl }; | 2479 | val_payload.* = .{ .decl = decl }; |
| 2219 | 2480 | ||
| 2220 | return self.constInst(scope, src, .{ | 2481 | return self.constInst(scope, src, .{ |
| 2221 | .ty = Type.initPayload(&ty_payload.base), | 2482 | .ty = ty, |
| 2222 | .val = Value.initPayload(&val_payload.base), | 2483 | .val = Value.initPayload(&val_payload.base), |
| 2223 | }); | 2484 | }); |
| 2224 | } | 2485 | } |
| 2225 | 2486 | ||
| 2487 | fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) InnerError!*Inst { | ||
| 2488 | const variable = tv.val.cast(Value.Payload.Variable).?.variable; | ||
| 2489 | |||
| 2490 | const ty = try self.simplePtrType(scope, src, tv.ty, variable.is_mutable, .One); | ||
| 2491 | if (!variable.is_mutable and !variable.is_extern) { | ||
| 2492 | const val_payload = try scope.arena().create(Value.Payload.RefVal); | ||
| 2493 | val_payload.* = .{ .val = variable.init }; | ||
| 2494 | return self.constInst(scope, src, .{ | ||
| 2495 | .ty = ty, | ||
| 2496 | .val = Value.initPayload(&val_payload.base), | ||
| 2497 | }); | ||
| 2498 | } | ||
| 2499 | |||
| 2500 | const b = try self.requireRuntimeBlock(scope, src); | ||
| 2501 | const inst = try b.arena.create(Inst.VarPtr); | ||
| 2502 | inst.* = .{ | ||
| 2503 | .base = .{ | ||
| 2504 | .tag = .varptr, | ||
| 2505 | .ty = ty, | ||
| 2506 | .src = src, | ||
| 2507 | }, | ||
| 2508 | .variable = variable, | ||
| 2509 | }; | ||
| 2510 | try b.instructions.append(self.gpa, &inst.base); | ||
| 2511 | return &inst.base; | ||
| 2512 | } | ||
| 2513 | |||
| 2226 | pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst { | 2514 | pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst { |
| 2227 | const elem_ty = switch (ptr.ty.zigTypeTag()) { | 2515 | const elem_ty = switch (ptr.ty.zigTypeTag()) { |
| 2228 | .Pointer => ptr.ty.elemType(), | 2516 | .Pointer => ptr.ty.elemType(), |
| ... | @@ -2523,7 +2811,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst | ... | @@ -2523,7 +2811,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst |
| 2523 | 2811 | ||
| 2524 | // T to ?T | 2812 | // T to ?T |
| 2525 | if (dest_type.zigTypeTag() == .Optional) { | 2813 | if (dest_type.zigTypeTag() == .Optional) { |
| 2526 | var buf: Type.Payload.Pointer = undefined; | 2814 | var buf: Type.Payload.PointerSimple = undefined; |
| 2527 | const child_type = dest_type.optionalChild(&buf); | 2815 | const child_type = dest_type.optionalChild(&buf); |
| 2528 | if (child_type.eql(inst.ty)) { | 2816 | if (child_type.eql(inst.ty)) { |
| 2529 | return self.wrapOptional(scope, dest_type, inst); | 2817 | return self.wrapOptional(scope, dest_type, inst); |
| ... | @@ -2902,15 +3190,125 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: | ... | @@ -2902,15 +3190,125 @@ pub fn floatSub(self: *Module, scope: *Scope, float_type: Type, src: usize, lhs: |
| 2902 | return Value.initPayload(val_payload); | 3190 | return Value.initPayload(val_payload); |
| 2903 | } | 3191 | } |
| 2904 | 3192 | ||
| 2905 | pub fn singlePtrType(self: *Module, scope: *Scope, src: usize, mutable: bool, elem_ty: Type) error{OutOfMemory}!Type { | 3193 | pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type { |
| 3194 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { | ||
| 3195 | return Type.initTag(.const_slice_u8); | ||
| 3196 | } | ||
| 3197 | // TODO stage1 type inference bug | ||
| 3198 | const T = Type.Tag; | ||
| 3199 | |||
| 3200 | const type_payload = try scope.arena().create(Type.Payload.PointerSimple); | ||
| 3201 | type_payload.* = .{ | ||
| 3202 | .base = .{ | ||
| 3203 | .tag = switch (size) { | ||
| 3204 | .One => if (mutable) T.single_mut_pointer else T.single_const_pointer, | ||
| 3205 | .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer, | ||
| 3206 | .C => if (mutable) T.c_mut_pointer else T.c_const_pointer, | ||
| 3207 | .Slice => if (mutable) T.mut_slice else T.const_slice, | ||
| 3208 | }, | ||
| 3209 | }, | ||
| 3210 | .pointee_type = elem_ty, | ||
| 3211 | }; | ||
| 3212 | return Type.initPayload(&type_payload.base); | ||
| 3213 | } | ||
| 3214 | |||
| 3215 | pub fn ptrType( | ||
| 3216 | self: *Module, | ||
| 3217 | scope: *Scope, | ||
| 3218 | src: usize, | ||
| 3219 | elem_ty: Type, | ||
| 3220 | sentinel: ?Value, | ||
| 3221 | @"align": u32, | ||
| 3222 | bit_offset: u16, | ||
| 3223 | host_size: u16, | ||
| 3224 | mutable: bool, | ||
| 3225 | @"allowzero": bool, | ||
| 3226 | @"volatile": bool, | ||
| 3227 | size: std.builtin.TypeInfo.Pointer.Size, | ||
| 3228 | ) Allocator.Error!Type { | ||
| 3229 | assert(host_size == 0 or bit_offset < host_size * 8); | ||
| 3230 | |||
| 3231 | // TODO check if type can be represented by simplePtrType | ||
| 2906 | const type_payload = try scope.arena().create(Type.Payload.Pointer); | 3232 | const type_payload = try scope.arena().create(Type.Payload.Pointer); |
| 2907 | type_payload.* = .{ | 3233 | type_payload.* = .{ |
| 2908 | .base = .{ .tag = if (mutable) .single_mut_pointer else .single_const_pointer }, | ||
| 2909 | .pointee_type = elem_ty, | 3234 | .pointee_type = elem_ty, |
| 3235 | .sentinel = sentinel, | ||
| 3236 | .@"align" = @"align", | ||
| 3237 | .bit_offset = bit_offset, | ||
| 3238 | .host_size = host_size, | ||
| 3239 | .@"allowzero" = @"allowzero", | ||
| 3240 | .mutable = mutable, | ||
| 3241 | .@"volatile" = @"volatile", | ||
| 3242 | .size = size, | ||
| 2910 | }; | 3243 | }; |
| 2911 | return Type.initPayload(&type_payload.base); | 3244 | return Type.initPayload(&type_payload.base); |
| 2912 | } | 3245 | } |
| 2913 | 3246 | ||
| 3247 | pub fn optionalType(self: *Module, scope: *Scope, child_type: Type) Allocator.Error!Type { | ||
| 3248 | return Type.initPayload(switch (child_type.tag()) { | ||
| 3249 | .single_const_pointer => blk: { | ||
| 3250 | const payload = try scope.arena().create(Type.Payload.PointerSimple); | ||
| 3251 | payload.* = .{ | ||
| 3252 | .base = .{ .tag = .optional_single_const_pointer }, | ||
| 3253 | .pointee_type = child_type.elemType(), | ||
| 3254 | }; | ||
| 3255 | break :blk &payload.base; | ||
| 3256 | }, | ||
| 3257 | .single_mut_pointer => blk: { | ||
| 3258 | const payload = try scope.arena().create(Type.Payload.PointerSimple); | ||
| 3259 | payload.* = .{ | ||
| 3260 | .base = .{ .tag = .optional_single_mut_pointer }, | ||
| 3261 | .pointee_type = child_type.elemType(), | ||
| 3262 | }; | ||
| 3263 | break :blk &payload.base; | ||
| 3264 | }, | ||
| 3265 | else => blk: { | ||
| 3266 | const payload = try scope.arena().create(Type.Payload.Optional); | ||
| 3267 | payload.* = .{ | ||
| 3268 | .child_type = child_type, | ||
| 3269 | }; | ||
| 3270 | break :blk &payload.base; | ||
| 3271 | }, | ||
| 3272 | }); | ||
| 3273 | } | ||
| 3274 | |||
| 3275 | pub fn arrayType(self: *Module, scope: *Scope, len: u64, sentinel: ?Value, elem_type: Type) Allocator.Error!Type { | ||
| 3276 | if (elem_type.eql(Type.initTag(.u8))) { | ||
| 3277 | if (sentinel) |some| { | ||
| 3278 | if (some.eql(Value.initTag(.zero))) { | ||
| 3279 | const payload = try scope.arena().create(Type.Payload.Array_u8_Sentinel0); | ||
| 3280 | payload.* = .{ | ||
| 3281 | .len = len, | ||
| 3282 | }; | ||
| 3283 | return Type.initPayload(&payload.base); | ||
| 3284 | } | ||
| 3285 | } else { | ||
| 3286 | const payload = try scope.arena().create(Type.Payload.Array_u8); | ||
| 3287 | payload.* = .{ | ||
| 3288 | .len = len, | ||
| 3289 | }; | ||
| 3290 | return Type.initPayload(&payload.base); | ||
| 3291 | } | ||
| 3292 | } | ||
| 3293 | |||
| 3294 | if (sentinel) |some| { | ||
| 3295 | const payload = try scope.arena().create(Type.Payload.ArraySentinel); | ||
| 3296 | payload.* = .{ | ||
| 3297 | .len = len, | ||
| 3298 | .sentinel = some, | ||
| 3299 | .elem_type = elem_type, | ||
| 3300 | }; | ||
| 3301 | return Type.initPayload(&payload.base); | ||
| 3302 | } | ||
| 3303 | |||
| 3304 | const payload = try scope.arena().create(Type.Payload.Array); | ||
| 3305 | payload.* = .{ | ||
| 3306 | .len = len, | ||
| 3307 | .elem_type = elem_type, | ||
| 3308 | }; | ||
| 3309 | return Type.initPayload(&payload.base); | ||
| 3310 | } | ||
| 3311 | |||
| 2914 | pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void { | 3312 | pub fn dumpInst(self: *Module, scope: *Scope, inst: *Inst) void { |
| 2915 | const zir_module = scope.namespace(); | 3313 | const zir_module = scope.namespace(); |
| 2916 | const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source"); | 3314 | const source = zir_module.getSource(self) catch @panic("dumpInst failed to get source"); |
src-self-hosted/astgen.zig+384-42| ... | @@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) { | ... | @@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) { |
| 20 | /// The expression must generate a pointer rather than a value. For example, the left hand side | 20 | /// The expression must generate a pointer rather than a value. For example, the left hand side |
| 21 | /// of an assignment uses an "LValue" result location. | 21 | /// of an assignment uses an "LValue" result location. |
| 22 | lvalue, | 22 | lvalue, |
| 23 | /// The expression must generate a pointer | ||
| 24 | ref, | ||
| 23 | /// The expression will be type coerced into this type, but it will be evaluated as an rvalue. | 25 | /// The expression will be type coerced into this type, but it will be evaluated as an rvalue. |
| 24 | ty: *zir.Inst, | 26 | ty: *zir.Inst, |
| 25 | /// The expression must store its result into this typed pointer. | 27 | /// The expression must store its result into this typed pointer. |
| ... | @@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z | ... | @@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z |
| 46 | 48 | ||
| 47 | /// Turn Zig AST into untyped ZIR istructions. | 49 | /// Turn Zig AST into untyped ZIR istructions. |
| 48 | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst { | 50 | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst { |
| 51 | if (rl == .lvalue) { | ||
| 52 | switch (node.tag) { | ||
| 53 | .Root => unreachable, | ||
| 54 | .Use => unreachable, | ||
| 55 | .TestDecl => unreachable, | ||
| 56 | .DocComment => unreachable, | ||
| 57 | .VarDecl => unreachable, | ||
| 58 | .SwitchCase => unreachable, | ||
| 59 | .SwitchElse => unreachable, | ||
| 60 | .Else => unreachable, | ||
| 61 | .Payload => unreachable, | ||
| 62 | .PointerPayload => unreachable, | ||
| 63 | .PointerIndexPayload => unreachable, | ||
| 64 | .ErrorTag => unreachable, | ||
| 65 | .FieldInitializer => unreachable, | ||
| 66 | .ContainerField => unreachable, | ||
| 67 | |||
| 68 | .Assign, | ||
| 69 | .AssignBitAnd, | ||
| 70 | .AssignBitOr, | ||
| 71 | .AssignBitShiftLeft, | ||
| 72 | .AssignBitShiftRight, | ||
| 73 | .AssignBitXor, | ||
| 74 | .AssignDiv, | ||
| 75 | .AssignSub, | ||
| 76 | .AssignSubWrap, | ||
| 77 | .AssignMod, | ||
| 78 | .AssignAdd, | ||
| 79 | .AssignAddWrap, | ||
| 80 | .AssignMul, | ||
| 81 | .AssignMulWrap, | ||
| 82 | .Add, | ||
| 83 | .AddWrap, | ||
| 84 | .Sub, | ||
| 85 | .SubWrap, | ||
| 86 | .Mul, | ||
| 87 | .MulWrap, | ||
| 88 | .Div, | ||
| 89 | .Mod, | ||
| 90 | .BitAnd, | ||
| 91 | .BitOr, | ||
| 92 | .BitShiftLeft, | ||
| 93 | .BitShiftRight, | ||
| 94 | .BitXor, | ||
| 95 | .BangEqual, | ||
| 96 | .EqualEqual, | ||
| 97 | .GreaterThan, | ||
| 98 | .GreaterOrEqual, | ||
| 99 | .LessThan, | ||
| 100 | .LessOrEqual, | ||
| 101 | .ArrayCat, | ||
| 102 | .ArrayMult, | ||
| 103 | .BoolAnd, | ||
| 104 | .BoolOr, | ||
| 105 | .Asm, | ||
| 106 | .StringLiteral, | ||
| 107 | .IntegerLiteral, | ||
| 108 | .Call, | ||
| 109 | .Unreachable, | ||
| 110 | .Return, | ||
| 111 | .If, | ||
| 112 | .While, | ||
| 113 | .BoolNot, | ||
| 114 | .AddressOf, | ||
| 115 | .FloatLiteral, | ||
| 116 | .UndefinedLiteral, | ||
| 117 | .BoolLiteral, | ||
| 118 | .NullLiteral, | ||
| 119 | .OptionalType, | ||
| 120 | .Block, | ||
| 121 | .LabeledBlock, | ||
| 122 | .Break, | ||
| 123 | .PtrType, | ||
| 124 | .GroupedExpression, | ||
| 125 | .ArrayType, | ||
| 126 | .ArrayTypeSentinel, | ||
| 127 | .EnumLiteral, | ||
| 128 | .MultilineStringLiteral, | ||
| 129 | .CharLiteral, | ||
| 130 | .Defer, | ||
| 131 | .Catch, | ||
| 132 | .ErrorUnion, | ||
| 133 | .MergeErrorSets, | ||
| 134 | .Range, | ||
| 135 | .OrElse, | ||
| 136 | .Await, | ||
| 137 | .BitNot, | ||
| 138 | .Negation, | ||
| 139 | .NegationWrap, | ||
| 140 | .Resume, | ||
| 141 | .Try, | ||
| 142 | .SliceType, | ||
| 143 | .Slice, | ||
| 144 | .ArrayInitializer, | ||
| 145 | .ArrayInitializerDot, | ||
| 146 | .StructInitializer, | ||
| 147 | .StructInitializerDot, | ||
| 148 | .Switch, | ||
| 149 | .For, | ||
| 150 | .Suspend, | ||
| 151 | .Continue, | ||
| 152 | .AnyType, | ||
| 153 | .ErrorType, | ||
| 154 | .FnProto, | ||
| 155 | .AnyFrameType, | ||
| 156 | .ErrorSetDecl, | ||
| 157 | .ContainerDecl, | ||
| 158 | .Comptime, | ||
| 159 | .Nosuspend, | ||
| 160 | => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}), | ||
| 161 | |||
| 162 | // @field can be assigned to | ||
| 163 | .BuiltinCall => { | ||
| 164 | const call = node.castTag(.BuiltinCall).?; | ||
| 165 | const tree = scope.tree(); | ||
| 166 | const builtin_name = tree.tokenSlice(call.builtin_token); | ||
| 167 | |||
| 168 | if (!mem.eql(u8, builtin_name, "@field")) { | ||
| 169 | return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}); | ||
| 170 | } | ||
| 171 | }, | ||
| 172 | |||
| 173 | // can be assigned to | ||
| 174 | .UnwrapOptional, .Deref, .Period, .ArrayAccess, .Identifier => {}, | ||
| 175 | } | ||
| 176 | } | ||
| 49 | switch (node.tag) { | 177 | switch (node.tag) { |
| 50 | .Root => unreachable, // Top-level declaration. | 178 | .Root => unreachable, // Top-level declaration. |
| 51 | .Use => unreachable, // Top-level declaration. | 179 | .Use => unreachable, // Top-level declaration. |
| ... | @@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 60 | .PointerIndexPayload => unreachable, // Handled explicitly. | 188 | .PointerIndexPayload => unreachable, // Handled explicitly. |
| 61 | .ErrorTag => unreachable, // Handled explicitly. | 189 | .ErrorTag => unreachable, // Handled explicitly. |
| 62 | .FieldInitializer => unreachable, // Handled explicitly. | 190 | .FieldInitializer => unreachable, // Handled explicitly. |
| 191 | .ContainerField => unreachable, // Handled explicitly. | ||
| 63 | 192 | ||
| 64 | .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)), | 193 | .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)), |
| 65 | .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)), | 194 | .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)), |
| ... | @@ -100,6 +229,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -100,6 +229,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 100 | .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat), | 229 | .ArrayCat => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayCat).?, .array_cat), |
| 101 | .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul), | 230 | .ArrayMult => return simpleBinOp(mod, scope, rl, node.castTag(.ArrayMult).?, .array_mul), |
| 102 | 231 | ||
| 232 | .BoolAnd => return boolBinOp(mod, scope, rl, node.castTag(.BoolAnd).?), | ||
| 233 | .BoolOr => return boolBinOp(mod, scope, rl, node.castTag(.BoolOr).?), | ||
| 234 | |||
| 103 | .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?), | 235 | .Identifier => return try identifier(mod, scope, rl, node.castTag(.Identifier).?), |
| 104 | .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)), | 236 | .Asm => return rlWrap(mod, scope, rl, try assembly(mod, scope, node.castTag(.Asm).?)), |
| 105 | .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)), | 237 | .StringLiteral => return rlWrap(mod, scope, rl, try stringLiteral(mod, scope, node.castTag(.StringLiteral).?)), |
| ... | @@ -124,11 +256,16 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -124,11 +256,16 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 124 | .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?), | 256 | .LabeledBlock => return labeledBlockExpr(mod, scope, rl, node.castTag(.LabeledBlock).?), |
| 125 | .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)), | 257 | .Break => return rlWrap(mod, scope, rl, try breakExpr(mod, scope, node.castTag(.Break).?)), |
| 126 | .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)), | 258 | .PtrType => return rlWrap(mod, scope, rl, try ptrType(mod, scope, node.castTag(.PtrType).?)), |
| 259 | .GroupedExpression => return expr(mod, scope, rl, node.castTag(.GroupedExpression).?.expr), | ||
| 260 | .ArrayType => return rlWrap(mod, scope, rl, try arrayType(mod, scope, node.castTag(.ArrayType).?)), | ||
| 261 | .ArrayTypeSentinel => return rlWrap(mod, scope, rl, try arrayTypeSentinel(mod, scope, node.castTag(.ArrayTypeSentinel).?)), | ||
| 262 | .EnumLiteral => return rlWrap(mod, scope, rl, try enumLiteral(mod, scope, node.castTag(.EnumLiteral).?)), | ||
| 263 | .MultilineStringLiteral => return rlWrap(mod, scope, rl, try multilineStrLiteral(mod, scope, node.castTag(.MultilineStringLiteral).?)), | ||
| 264 | .CharLiteral => return rlWrap(mod, scope, rl, try charLiteral(mod, scope, node.castTag(.CharLiteral).?)), | ||
| 265 | .SliceType => return rlWrap(mod, scope, rl, try sliceType(mod, scope, node.castTag(.SliceType).?)), | ||
| 127 | 266 | ||
| 128 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), | 267 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), |
| 129 | .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}), | 268 | .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}), |
| 130 | .BoolAnd => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolAnd", .{}), | ||
| 131 | .BoolOr => return mod.failNode(scope, node, "TODO implement astgen.expr for .BoolOr", .{}), | ||
| 132 | .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}), | 269 | .ErrorUnion => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorUnion", .{}), |
| 133 | .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}), | 270 | .MergeErrorSets => return mod.failNode(scope, node, "TODO implement astgen.expr for .MergeErrorSets", .{}), |
| 134 | .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), | 271 | .Range => return mod.failNode(scope, node, "TODO implement astgen.expr for .Range", .{}), |
| ... | @@ -139,9 +276,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -139,9 +276,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 139 | .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}), | 276 | .NegationWrap => return mod.failNode(scope, node, "TODO implement astgen.expr for .NegationWrap", .{}), |
| 140 | .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), | 277 | .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}), |
| 141 | .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), | 278 | .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| 142 | .ArrayType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayType", .{}), | ||
| 143 | .ArrayTypeSentinel => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayTypeSentinel", .{}), | ||
| 144 | .SliceType => return mod.failNode(scope, node, "TODO implement astgen.expr for .SliceType", .{}), | ||
| 145 | .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}), | 279 | .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}), |
| 146 | .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}), | 280 | .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}), |
| 147 | .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}), | 281 | .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}), |
| ... | @@ -156,15 +290,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -156,15 +290,10 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 156 | .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}), | 290 | .ErrorType => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorType", .{}), |
| 157 | .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}), | 291 | .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}), |
| 158 | .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}), | 292 | .AnyFrameType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyFrameType", .{}), |
| 159 | .EnumLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .EnumLiteral", .{}), | ||
| 160 | .MultilineStringLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .MultilineStringLiteral", .{}), | ||
| 161 | .CharLiteral => return mod.failNode(scope, node, "TODO implement astgen.expr for .CharLiteral", .{}), | ||
| 162 | .GroupedExpression => return mod.failNode(scope, node, "TODO implement astgen.expr for .GroupedExpression", .{}), | ||
| 163 | .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}), | 293 | .ErrorSetDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ErrorSetDecl", .{}), |
| 164 | .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}), | 294 | .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}), |
| 165 | .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}), | 295 | .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}), |
| 166 | .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}), | 296 | .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}), |
| 167 | .ContainerField => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerField", .{}), | ||
| 168 | } | 297 | } |
| 169 | } | 298 | } |
| 170 | 299 | ||
| ... | @@ -187,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr | ... | @@ -187,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr |
| 187 | // proper type inference requires peer type resolution on the block's | 316 | // proper type inference requires peer type resolution on the block's |
| 188 | // break operand expressions. | 317 | // break operand expressions. |
| 189 | const branch_rl: ResultLoc = switch (label.result_loc) { | 318 | const branch_rl: ResultLoc = switch (label.result_loc) { |
| 190 | .discard, .none, .ty, .ptr, .lvalue => label.result_loc, | 319 | .discard, .none, .ty, .ptr, .lvalue, .ref => label.result_loc, |
| 191 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst }, | 320 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst }, |
| 192 | }; | 321 | }; |
| 193 | const operand = try expr(mod, parent_scope, branch_rl, rhs); | 322 | const operand = try expr(mod, parent_scope, branch_rl, rhs); |
| ... | @@ -426,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr | ... | @@ -426,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr |
| 426 | } | 555 | } |
| 427 | 556 | ||
| 428 | fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { | 557 | fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { |
| 429 | return expr(mod, scope, .lvalue, node.rhs); | 558 | return expr(mod, scope, .ref, node.rhs); |
| 430 | } | 559 | } |
| 431 | 560 | ||
| 432 | fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { | 561 | fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { |
| ... | @@ -440,43 +569,67 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn | ... | @@ -440,43 +569,67 @@ fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) Inn |
| 440 | return addZIRUnOp(mod, scope, src, .optional_type, operand); | 569 | return addZIRUnOp(mod, scope, src, .optional_type, operand); |
| 441 | } | 570 | } |
| 442 | 571 | ||
| 572 | fn sliceType(mod: *Module, scope: *Scope, node: *ast.Node.SliceType) InnerError!*zir.Inst { | ||
| 573 | const tree = scope.tree(); | ||
| 574 | const src = tree.token_locs[node.op_token].start; | ||
| 575 | return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, .Slice); | ||
| 576 | } | ||
| 577 | |||
| 443 | fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { | 578 | fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir.Inst { |
| 444 | const tree = scope.tree(); | 579 | const tree = scope.tree(); |
| 445 | const src = tree.token_locs[node.op_token].start; | 580 | const src = tree.token_locs[node.op_token].start; |
| 581 | return ptrSliceType(mod, scope, src, &node.ptr_info, node.rhs, switch (tree.token_ids[node.op_token]) { | ||
| 582 | .Asterisk, .AsteriskAsterisk => .One, | ||
| 583 | // TODO stage1 type inference bug | ||
| 584 | .LBracket => @as(std.builtin.TypeInfo.Pointer.Size, switch (tree.token_ids[node.op_token + 2]) { | ||
| 585 | .Identifier => .C, | ||
| 586 | else => .Many, | ||
| 587 | }), | ||
| 588 | else => unreachable, | ||
| 589 | }); | ||
| 590 | } | ||
| 591 | |||
| 592 | fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst { | ||
| 446 | const meta_type = try addZIRInstConst(mod, scope, src, .{ | 593 | const meta_type = try addZIRInstConst(mod, scope, src, .{ |
| 447 | .ty = Type.initTag(.type), | 594 | .ty = Type.initTag(.type), |
| 448 | .val = Value.initTag(.type_type), | 595 | .val = Value.initTag(.type_type), |
| 449 | }); | 596 | }); |
| 450 | 597 | ||
| 451 | const simple = node.ptr_info.allowzero_token == null and | 598 | const simple = ptr_info.allowzero_token == null and |
| 452 | node.ptr_info.align_info == null and | 599 | ptr_info.align_info == null and |
| 453 | node.ptr_info.volatile_token == null and | 600 | ptr_info.volatile_token == null and |
| 454 | node.ptr_info.sentinel == null; | 601 | ptr_info.sentinel == null; |
| 455 | 602 | ||
| 456 | if (simple) { | 603 | if (simple) { |
| 457 | const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); | 604 | const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs); |
| 458 | return addZIRUnOp(mod, scope, src, if (node.ptr_info.const_token == null) | 605 | const mutable = ptr_info.const_token == null; |
| 459 | .single_mut_ptr_type | 606 | // TODO stage1 type inference bug |
| 460 | else | 607 | const T = zir.Inst.Tag; |
| 461 | .single_const_ptr_type, child_type); | 608 | return addZIRUnOp(mod, scope, src, switch (size) { |
| 609 | .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type, | ||
| 610 | .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type, | ||
| 611 | .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type, | ||
| 612 | .Slice => if (mutable) T.mut_slice_type else T.mut_slice_type, | ||
| 613 | }, child_type); | ||
| 462 | } | 614 | } |
| 463 | 615 | ||
| 464 | var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{}; | 616 | var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{}; |
| 465 | kw_args.@"allowzero" = node.ptr_info.allowzero_token != null; | 617 | kw_args.size = size; |
| 466 | if (node.ptr_info.align_info) |some| { | 618 | kw_args.@"allowzero" = ptr_info.allowzero_token != null; |
| 619 | if (ptr_info.align_info) |some| { | ||
| 467 | kw_args.@"align" = try expr(mod, scope, .none, some.node); | 620 | kw_args.@"align" = try expr(mod, scope, .none, some.node); |
| 468 | if (some.bit_range) |bit_range| { | 621 | if (some.bit_range) |bit_range| { |
| 469 | kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start); | 622 | kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start); |
| 470 | kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end); | 623 | kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end); |
| 471 | } | 624 | } |
| 472 | } | 625 | } |
| 473 | kw_args.@"const" = node.ptr_info.const_token != null; | 626 | kw_args.mutable = ptr_info.const_token == null; |
| 474 | kw_args.@"volatile" = node.ptr_info.volatile_token != null; | 627 | kw_args.@"volatile" = ptr_info.volatile_token != null; |
| 475 | if (node.ptr_info.sentinel) |some| { | 628 | if (ptr_info.sentinel) |some| { |
| 476 | kw_args.sentinel = try expr(mod, scope, .none, some); | 629 | kw_args.sentinel = try expr(mod, scope, .none, some); |
| 477 | } | 630 | } |
| 478 | 631 | ||
| 479 | const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); | 632 | const child_type = try expr(mod, scope, .{ .ty = meta_type }, rhs); |
| 480 | if (kw_args.sentinel) |some| { | 633 | if (kw_args.sentinel) |some| { |
| 481 | kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some); | 634 | kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some); |
| 482 | } | 635 | } |
| ... | @@ -484,13 +637,65 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir | ... | @@ -484,13 +637,65 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir |
| 484 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); | 637 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); |
| 485 | } | 638 | } |
| 486 | 639 | ||
| 640 | fn arrayType(mod: *Module, scope: *Scope, node: *ast.Node.ArrayType) !*zir.Inst { | ||
| 641 | const tree = scope.tree(); | ||
| 642 | const src = tree.token_locs[node.op_token].start; | ||
| 643 | const meta_type = try addZIRInstConst(mod, scope, src, .{ | ||
| 644 | .ty = Type.initTag(.type), | ||
| 645 | .val = Value.initTag(.type_type), | ||
| 646 | }); | ||
| 647 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | ||
| 648 | .ty = Type.initTag(.type), | ||
| 649 | .val = Value.initTag(.usize_type), | ||
| 650 | }); | ||
| 651 | |||
| 652 | // TODO check for [_]T | ||
| 653 | const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr); | ||
| 654 | const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); | ||
| 655 | |||
| 656 | return addZIRBinOp(mod, scope, src, .array_type, len, child_type); | ||
| 657 | } | ||
| 658 | |||
| 659 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, node: *ast.Node.ArrayTypeSentinel) !*zir.Inst { | ||
| 660 | const tree = scope.tree(); | ||
| 661 | const src = tree.token_locs[node.op_token].start; | ||
| 662 | const meta_type = try addZIRInstConst(mod, scope, src, .{ | ||
| 663 | .ty = Type.initTag(.type), | ||
| 664 | .val = Value.initTag(.type_type), | ||
| 665 | }); | ||
| 666 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | ||
| 667 | .ty = Type.initTag(.type), | ||
| 668 | .val = Value.initTag(.usize_type), | ||
| 669 | }); | ||
| 670 | |||
| 671 | // TODO check for [_]T | ||
| 672 | const len = try expr(mod, scope, .{ .ty = usize_type }, node.len_expr); | ||
| 673 | const sentinel_uncasted = try expr(mod, scope, .none, node.sentinel); | ||
| 674 | const elem_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); | ||
| 675 | const sentinel = try addZIRBinOp(mod, scope, src, .as, elem_type, sentinel_uncasted); | ||
| 676 | |||
| 677 | return addZIRInst(mod, scope, src, zir.Inst.ArrayTypeSentinel, .{ | ||
| 678 | .len = len, | ||
| 679 | .sentinel = sentinel, | ||
| 680 | .elem_type = elem_type, | ||
| 681 | }, .{}); | ||
| 682 | } | ||
| 683 | |||
| 684 | fn enumLiteral(mod: *Module, scope: *Scope, node: *ast.Node.EnumLiteral) !*zir.Inst { | ||
| 685 | const tree = scope.tree(); | ||
| 686 | const src = tree.token_locs[node.name].start; | ||
| 687 | const name = try identifierTokenString(mod, scope, node.name); | ||
| 688 | |||
| 689 | return addZIRInst(mod, scope, src, zir.Inst.EnumLiteral, .{ .name = name }, .{}); | ||
| 690 | } | ||
| 691 | |||
| 487 | fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { | 692 | fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { |
| 488 | const tree = scope.tree(); | 693 | const tree = scope.tree(); |
| 489 | const src = tree.token_locs[node.rtoken].start; | 694 | const src = tree.token_locs[node.rtoken].start; |
| 490 | 695 | ||
| 491 | const operand = try expr(mod, scope, .lvalue, node.lhs); | 696 | const operand = try expr(mod, scope, .ref, node.lhs); |
| 492 | const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand); | 697 | const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand); |
| 493 | if (rl == .lvalue) return unwrapped_ptr; | 698 | if (rl == .lvalue or rl == .ref) return unwrapped_ptr; |
| 494 | 699 | ||
| 495 | return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr)); | 700 | return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr)); |
| 496 | } | 701 | } |
| ... | @@ -568,6 +773,88 @@ fn simpleBinOp( | ... | @@ -568,6 +773,88 @@ fn simpleBinOp( |
| 568 | return rlWrap(mod, scope, rl, result); | 773 | return rlWrap(mod, scope, rl, result); |
| 569 | } | 774 | } |
| 570 | 775 | ||
| 776 | fn boolBinOp( | ||
| 777 | mod: *Module, | ||
| 778 | scope: *Scope, | ||
| 779 | rl: ResultLoc, | ||
| 780 | infix_node: *ast.Node.SimpleInfixOp, | ||
| 781 | ) InnerError!*zir.Inst { | ||
| 782 | const tree = scope.tree(); | ||
| 783 | const src = tree.token_locs[infix_node.op_token].start; | ||
| 784 | const bool_type = try addZIRInstConst(mod, scope, src, .{ | ||
| 785 | .ty = Type.initTag(.type), | ||
| 786 | .val = Value.initTag(.bool_type), | ||
| 787 | }); | ||
| 788 | |||
| 789 | var block_scope: Scope.GenZIR = .{ | ||
| 790 | .parent = scope, | ||
| 791 | .decl = scope.decl().?, | ||
| 792 | .arena = scope.arena(), | ||
| 793 | .instructions = .{}, | ||
| 794 | }; | ||
| 795 | defer block_scope.instructions.deinit(mod.gpa); | ||
| 796 | |||
| 797 | const lhs = try expr(mod, scope, .{ .ty = bool_type }, infix_node.lhs); | ||
| 798 | const condbr = try addZIRInstSpecial(mod, &block_scope.base, src, zir.Inst.CondBr, .{ | ||
| 799 | .condition = lhs, | ||
| 800 | .then_body = undefined, // populated below | ||
| 801 | .else_body = undefined, // populated below | ||
| 802 | }, .{}); | ||
| 803 | |||
| 804 | const block = try addZIRInstBlock(mod, scope, src, .{ | ||
| 805 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), | ||
| 806 | }); | ||
| 807 | |||
| 808 | var rhs_scope: Scope.GenZIR = .{ | ||
| 809 | .parent = scope, | ||
| 810 | .decl = block_scope.decl, | ||
| 811 | .arena = block_scope.arena, | ||
| 812 | .instructions = .{}, | ||
| 813 | }; | ||
| 814 | defer rhs_scope.instructions.deinit(mod.gpa); | ||
| 815 | |||
| 816 | const rhs = try expr(mod, &rhs_scope.base, .{ .ty = bool_type }, infix_node.rhs); | ||
| 817 | _ = try addZIRInst(mod, &rhs_scope.base, src, zir.Inst.Break, .{ | ||
| 818 | .block = block, | ||
| 819 | .operand = rhs, | ||
| 820 | }, .{}); | ||
| 821 | |||
| 822 | var const_scope: Scope.GenZIR = .{ | ||
| 823 | .parent = scope, | ||
| 824 | .decl = block_scope.decl, | ||
| 825 | .arena = block_scope.arena, | ||
| 826 | .instructions = .{}, | ||
| 827 | }; | ||
| 828 | defer const_scope.instructions.deinit(mod.gpa); | ||
| 829 | |||
| 830 | const is_bool_and = infix_node.base.tag == .BoolAnd; | ||
| 831 | _ = try addZIRInst(mod, &const_scope.base, src, zir.Inst.Break, .{ | ||
| 832 | .block = block, | ||
| 833 | .operand = try addZIRInstConst(mod, &const_scope.base, src, .{ | ||
| 834 | .ty = Type.initTag(.bool), | ||
| 835 | .val = if (is_bool_and) Value.initTag(.bool_false) else Value.initTag(.bool_true), | ||
| 836 | }), | ||
| 837 | }, .{}); | ||
| 838 | |||
| 839 | if (is_bool_and) { | ||
| 840 | // if lhs // AND | ||
| 841 | // break rhs | ||
| 842 | // else | ||
| 843 | // break false | ||
| 844 | condbr.positionals.then_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) }; | ||
| 845 | condbr.positionals.else_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) }; | ||
| 846 | } else { | ||
| 847 | // if lhs // OR | ||
| 848 | // break true | ||
| 849 | // else | ||
| 850 | // break rhs | ||
| 851 | condbr.positionals.then_body = .{ .instructions = try const_scope.arena.dupe(*zir.Inst, const_scope.instructions.items) }; | ||
| 852 | condbr.positionals.else_body = .{ .instructions = try rhs_scope.arena.dupe(*zir.Inst, rhs_scope.instructions.items) }; | ||
| 853 | } | ||
| 854 | |||
| 855 | return rlWrap(mod, scope, rl, &block.base); | ||
| 856 | } | ||
| 857 | |||
| 571 | const CondKind = union(enum) { | 858 | const CondKind = union(enum) { |
| 572 | bool, | 859 | bool, |
| 573 | optional: ?*zir.Inst, | 860 | optional: ?*zir.Inst, |
| ... | @@ -583,13 +870,13 @@ const CondKind = union(enum) { | ... | @@ -583,13 +870,13 @@ const CondKind = union(enum) { |
| 583 | return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node); | 870 | return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node); |
| 584 | }, | 871 | }, |
| 585 | .optional => { | 872 | .optional => { |
| 586 | const cond_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node); | 873 | const cond_ptr = try expr(mod, &block_scope.base, .ref, cond_node); |
| 587 | self.* = .{ .optional = cond_ptr }; | 874 | self.* = .{ .optional = cond_ptr }; |
| 588 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr); | 875 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr); |
| 589 | return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result); | 876 | return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result); |
| 590 | }, | 877 | }, |
| 591 | .err_union => { | 878 | .err_union => { |
| 592 | const err_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node); | 879 | const err_ptr = try expr(mod, &block_scope.base, .ref, cond_node); |
| 593 | self.* = .{ .err_union = err_ptr }; | 880 | self.* = .{ .err_union = err_ptr }; |
| 594 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr); | 881 | const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr); |
| 595 | return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result); | 882 | return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result); |
| ... | @@ -600,7 +887,11 @@ const CondKind = union(enum) { | ... | @@ -600,7 +887,11 @@ const CondKind = union(enum) { |
| 600 | fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope { | 887 | fn thenSubScope(self: CondKind, mod: *Module, then_scope: *Scope.GenZIR, src: usize, payload_node: ?*ast.Node) !*Scope { |
| 601 | if (self == .bool) return &then_scope.base; | 888 | if (self == .bool) return &then_scope.base; |
| 602 | 889 | ||
| 603 | const payload = payload_node.?.castTag(.PointerPayload).?; | 890 | const payload = payload_node.?.castTag(.PointerPayload) orelse { |
| 891 | // condition is error union and payload is not explicitly ignored | ||
| 892 | _ = try addZIRUnOp(mod, &then_scope.base, src, .ensure_err_payload_void, self.err_union.?); | ||
| 893 | return &then_scope.base; | ||
| 894 | }; | ||
| 604 | const is_ptr = payload.ptr_token != null; | 895 | const is_ptr = payload.ptr_token != null; |
| 605 | const ident_node = payload.value_symbol.castTag(.Identifier).?; | 896 | const ident_node = payload.value_symbol.castTag(.Identifier).?; |
| 606 | 897 | ||
| ... | @@ -680,7 +971,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -680,7 +971,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 680 | // proper type inference requires peer type resolution on the if's | 971 | // proper type inference requires peer type resolution on the if's |
| 681 | // branches. | 972 | // branches. |
| 682 | const branch_rl: ResultLoc = switch (rl) { | 973 | const branch_rl: ResultLoc = switch (rl) { |
| 683 | .discard, .none, .ty, .ptr, .lvalue => rl, | 974 | .discard, .none, .ty, .ptr, .lvalue, .ref => rl, |
| 684 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block }, | 975 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block }, |
| 685 | }; | 976 | }; |
| 686 | 977 | ||
| ... | @@ -810,7 +1101,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W | ... | @@ -810,7 +1101,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W |
| 810 | // proper type inference requires peer type resolution on the while's | 1101 | // proper type inference requires peer type resolution on the while's |
| 811 | // branches. | 1102 | // branches. |
| 812 | const branch_rl: ResultLoc = switch (rl) { | 1103 | const branch_rl: ResultLoc = switch (rl) { |
| 813 | .discard, .none, .ty, .ptr, .lvalue => rl, | 1104 | .discard, .none, .ty, .ptr, .lvalue, .ref => rl, |
| 814 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block }, | 1105 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block }, |
| 815 | }; | 1106 | }; |
| 816 | 1107 | ||
| ... | @@ -941,7 +1232,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo | ... | @@ -941,7 +1232,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo |
| 941 | .local_ptr => { | 1232 | .local_ptr => { |
| 942 | const local_ptr = s.cast(Scope.LocalPtr).?; | 1233 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 943 | if (mem.eql(u8, local_ptr.name, ident_name)) { | 1234 | if (mem.eql(u8, local_ptr.name, ident_name)) { |
| 944 | if (rl == .lvalue) { | 1235 | if (rl == .lvalue or rl == .ref) { |
| 945 | return local_ptr.ptr; | 1236 | return local_ptr.ptr; |
| 946 | } else { | 1237 | } else { |
| 947 | const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr); | 1238 | const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr); |
| ... | @@ -956,9 +1247,10 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo | ... | @@ -956,9 +1247,10 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo |
| 956 | } | 1247 | } |
| 957 | 1248 | ||
| 958 | if (mod.lookupDeclName(scope, ident_name)) |decl| { | 1249 | if (mod.lookupDeclName(scope, ident_name)) |decl| { |
| 959 | // TODO handle lvalues | ||
| 960 | const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}); | 1250 | const result = try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}); |
| 961 | return rlWrap(mod, scope, rl, result); | 1251 | if (rl == .lvalue or rl == .ref) |
| 1252 | return result; | ||
| 1253 | return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, result)); | ||
| 962 | } | 1254 | } |
| 963 | 1255 | ||
| 964 | return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name}); | 1256 | return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name}); |
| ... | @@ -983,6 +1275,54 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner | ... | @@ -983,6 +1275,54 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner |
| 983 | return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{}); | 1275 | return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{}); |
| 984 | } | 1276 | } |
| 985 | 1277 | ||
| 1278 | fn multilineStrLiteral(mod: *Module, scope: *Scope, node: *ast.Node.MultilineStringLiteral) !*zir.Inst { | ||
| 1279 | const tree = scope.tree(); | ||
| 1280 | const lines = node.linesConst(); | ||
| 1281 | const src = tree.token_locs[lines[0]].start; | ||
| 1282 | |||
| 1283 | // line lengths and new lines | ||
| 1284 | var len = lines.len - 1; | ||
| 1285 | for (lines) |line| { | ||
| 1286 | // 2 for the '//' + 1 for '\n' | ||
| 1287 | len += tree.tokenSlice(line).len - 3; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | const bytes = try scope.arena().alloc(u8, len); | ||
| 1291 | var i: usize = 0; | ||
| 1292 | for (lines) |line, line_i| { | ||
| 1293 | if (line_i != 0) { | ||
| 1294 | bytes[i] = '\n'; | ||
| 1295 | i += 1; | ||
| 1296 | } | ||
| 1297 | const slice = tree.tokenSlice(line); | ||
| 1298 | mem.copy(u8, bytes[i..], slice[2 .. slice.len - 1]); | ||
| 1299 | i += slice.len - 3; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{}); | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | fn charLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) !*zir.Inst { | ||
| 1306 | const tree = scope.tree(); | ||
| 1307 | const src = tree.token_locs[node.token].start; | ||
| 1308 | const slice = tree.tokenSlice(node.token); | ||
| 1309 | |||
| 1310 | var bad_index: usize = undefined; | ||
| 1311 | const value = std.zig.parseCharLiteral(slice, &bad_index) catch |err| switch (err) { | ||
| 1312 | error.InvalidCharacter => { | ||
| 1313 | const bad_byte = slice[bad_index]; | ||
| 1314 | return mod.fail(scope, src + bad_index, "invalid character: '{c}'\n", .{bad_byte}); | ||
| 1315 | }, | ||
| 1316 | }; | ||
| 1317 | |||
| 1318 | const int_payload = try scope.arena().create(Value.Payload.Int_u64); | ||
| 1319 | int_payload.* = .{ .int = value }; | ||
| 1320 | return addZIRInstConst(mod, scope, src, .{ | ||
| 1321 | .ty = Type.initTag(.comptime_int), | ||
| 1322 | .val = Value.initPayload(&int_payload.base), | ||
| 1323 | }); | ||
| 1324 | } | ||
| 1325 | |||
| 986 | fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst { | 1326 | fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst { |
| 987 | const arena = scope.arena(); | 1327 | const arena = scope.arena(); |
| 988 | const tree = scope.tree(); | 1328 | const tree = scope.tree(); |
| ... | @@ -1158,7 +1498,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I | ... | @@ -1158,7 +1498,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I |
| 1158 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); | 1498 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); |
| 1159 | return result; | 1499 | return result; |
| 1160 | }, | 1500 | }, |
| 1161 | .lvalue => { | 1501 | .lvalue => unreachable, |
| 1502 | .ref => { | ||
| 1162 | const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]); | 1503 | const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]); |
| 1163 | return addZIRUnOp(mod, scope, result.src, .ref, result); | 1504 | return addZIRUnOp(mod, scope, result.src, .ref, result); |
| 1164 | }, | 1505 | }, |
| ... | @@ -1209,9 +1550,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa | ... | @@ -1209,9 +1550,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa |
| 1209 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); | 1550 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); |
| 1210 | return result; | 1551 | return result; |
| 1211 | }, | 1552 | }, |
| 1212 | .lvalue => { | 1553 | .lvalue => unreachable, |
| 1213 | const operand = try expr(mod, scope, .lvalue, params[1]); | 1554 | .ref => { |
| 1214 | const result = try addZIRBinOp(mod, scope, src, .bitcast_lvalue, dest_type, operand); | 1555 | const operand = try expr(mod, scope, .ref, params[1]); |
| 1556 | const result = try addZIRBinOp(mod, scope, src, .bitcast_ref, dest_type, operand); | ||
| 1215 | return result; | 1557 | return result; |
| 1216 | }, | 1558 | }, |
| 1217 | .ty => |result_ty| { | 1559 | .ty => |result_ty| { |
| ... | @@ -1476,7 +1818,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr | ... | @@ -1476,7 +1818,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr |
| 1476 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); | 1818 | _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result); |
| 1477 | return result; | 1819 | return result; |
| 1478 | }, | 1820 | }, |
| 1479 | .lvalue => { | 1821 | .lvalue, .ref => { |
| 1480 | // We need a pointer but we have a value. | 1822 | // We need a pointer but we have a value. |
| 1481 | return addZIRUnOp(mod, scope, result.src, .ref, result); | 1823 | return addZIRUnOp(mod, scope, result.src, .ref, result); |
| 1482 | }, | 1824 | }, |
src-self-hosted/cbe.h deleted-15| ... | @@ -1,15 +0,0 @@ | ||
| 1 | #if __STDC_VERSION__ >= 201112L | ||
| 2 | #define zig_noreturn _Noreturn | ||
| 3 | #elif __GNUC__ | ||
| 4 | #define zig_noreturn __attribute__ ((noreturn)) | ||
| 5 | #elif _MSC_VER | ||
| 6 | #define zig_noreturn __declspec(noreturn) | ||
| 7 | #else | ||
| 8 | #define zig_noreturn | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #if __GNUC__ | ||
| 12 | #define zig_unreachable() __builtin_unreachable() | ||
| 13 | #else | ||
| 14 | #define zig_unreachable() | ||
| 15 | #endif | ||
src-self-hosted/codegen.zig+131-100| ... | @@ -59,20 +59,20 @@ pub const GenerateSymbolError = error{ | ... | @@ -59,20 +59,20 @@ pub const GenerateSymbolError = error{ |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | pub fn generateSymbol( | 61 | pub fn generateSymbol( |
| 62 | bin_file: *link.File.Elf, | 62 | bin_file: *link.File, |
| 63 | src: usize, | 63 | src: usize, |
| 64 | typed_value: TypedValue, | 64 | typed_value: TypedValue, |
| 65 | code: *std.ArrayList(u8), | 65 | code: *std.ArrayList(u8), |
| 66 | dbg_line: *std.ArrayList(u8), | 66 | dbg_line: *std.ArrayList(u8), |
| 67 | dbg_info: *std.ArrayList(u8), | 67 | dbg_info: *std.ArrayList(u8), |
| 68 | dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable, | 68 | dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable, |
| 69 | ) GenerateSymbolError!Result { | 69 | ) GenerateSymbolError!Result { |
| 70 | const tracy = trace(@src()); | 70 | const tracy = trace(@src()); |
| 71 | defer tracy.end(); | 71 | defer tracy.end(); |
| 72 | 72 | ||
| 73 | switch (typed_value.ty.zigTypeTag()) { | 73 | switch (typed_value.ty.zigTypeTag()) { |
| 74 | .Fn => { | 74 | .Fn => { |
| 75 | switch (bin_file.base.options.target.cpu.arch) { | 75 | switch (bin_file.options.target.cpu.arch) { |
| 76 | .wasm32 => unreachable, // has its own code path | 76 | .wasm32 => unreachable, // has its own code path |
| 77 | .wasm64 => unreachable, // has its own code path | 77 | .wasm64 => unreachable, // has its own code path |
| 78 | //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), | 78 | //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), |
| ... | @@ -151,7 +151,7 @@ pub fn generateSymbol( | ... | @@ -151,7 +151,7 @@ pub fn generateSymbol( |
| 151 | } | 151 | } |
| 152 | return Result{ | 152 | return Result{ |
| 153 | .fail = try ErrorMsg.create( | 153 | .fail = try ErrorMsg.create( |
| 154 | bin_file.base.allocator, | 154 | bin_file.allocator, |
| 155 | src, | 155 | src, |
| 156 | "TODO implement generateSymbol for more kinds of arrays", | 156 | "TODO implement generateSymbol for more kinds of arrays", |
| 157 | .{}, | 157 | .{}, |
| ... | @@ -164,12 +164,11 @@ pub fn generateSymbol( | ... | @@ -164,12 +164,11 @@ pub fn generateSymbol( |
| 164 | if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| { | 164 | if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| { |
| 165 | const decl = payload.decl; | 165 | const decl = payload.decl; |
| 166 | if (decl.analysis != .complete) return error.AnalysisFail; | 166 | if (decl.analysis != .complete) return error.AnalysisFail; |
| 167 | assert(decl.link.elf.local_sym_index != 0); | ||
| 168 | // TODO handle the dependency of this symbol on the decl's vaddr. | 167 | // TODO handle the dependency of this symbol on the decl's vaddr. |
| 169 | // If the decl changes vaddr, then this symbol needs to get regenerated. | 168 | // If the decl changes vaddr, then this symbol needs to get regenerated. |
| 170 | const vaddr = bin_file.local_symbols.items[decl.link.elf.local_sym_index].st_value; | 169 | const vaddr = bin_file.getDeclVAddr(decl); |
| 171 | const endian = bin_file.base.options.target.cpu.arch.endian(); | 170 | const endian = bin_file.options.target.cpu.arch.endian(); |
| 172 | switch (bin_file.base.options.target.cpu.arch.ptrBitWidth()) { | 171 | switch (bin_file.options.target.cpu.arch.ptrBitWidth()) { |
| 173 | 16 => { | 172 | 16 => { |
| 174 | try code.resize(2); | 173 | try code.resize(2); |
| 175 | mem.writeInt(u16, code.items[0..2], @intCast(u16, vaddr), endian); | 174 | mem.writeInt(u16, code.items[0..2], @intCast(u16, vaddr), endian); |
| ... | @@ -188,7 +187,7 @@ pub fn generateSymbol( | ... | @@ -188,7 +187,7 @@ pub fn generateSymbol( |
| 188 | } | 187 | } |
| 189 | return Result{ | 188 | return Result{ |
| 190 | .fail = try ErrorMsg.create( | 189 | .fail = try ErrorMsg.create( |
| 191 | bin_file.base.allocator, | 190 | bin_file.allocator, |
| 192 | src, | 191 | src, |
| 193 | "TODO implement generateSymbol for pointer {}", | 192 | "TODO implement generateSymbol for pointer {}", |
| 194 | .{typed_value.val}, | 193 | .{typed_value.val}, |
| ... | @@ -198,7 +197,7 @@ pub fn generateSymbol( | ... | @@ -198,7 +197,7 @@ pub fn generateSymbol( |
| 198 | .Int => { | 197 | .Int => { |
| 199 | // TODO populate .debug_info for the integer | 198 | // TODO populate .debug_info for the integer |
| 200 | 199 | ||
| 201 | const info = typed_value.ty.intInfo(bin_file.base.options.target); | 200 | const info = typed_value.ty.intInfo(bin_file.options.target); |
| 202 | if (info.bits == 8 and !info.signed) { | 201 | if (info.bits == 8 and !info.signed) { |
| 203 | const x = typed_value.val.toUnsignedInt(); | 202 | const x = typed_value.val.toUnsignedInt(); |
| 204 | try code.append(@intCast(u8, x)); | 203 | try code.append(@intCast(u8, x)); |
| ... | @@ -206,7 +205,7 @@ pub fn generateSymbol( | ... | @@ -206,7 +205,7 @@ pub fn generateSymbol( |
| 206 | } | 205 | } |
| 207 | return Result{ | 206 | return Result{ |
| 208 | .fail = try ErrorMsg.create( | 207 | .fail = try ErrorMsg.create( |
| 209 | bin_file.base.allocator, | 208 | bin_file.allocator, |
| 210 | src, | 209 | src, |
| 211 | "TODO implement generateSymbol for int type '{}'", | 210 | "TODO implement generateSymbol for int type '{}'", |
| 212 | .{typed_value.ty}, | 211 | .{typed_value.ty}, |
| ... | @@ -216,7 +215,7 @@ pub fn generateSymbol( | ... | @@ -216,7 +215,7 @@ pub fn generateSymbol( |
| 216 | else => |t| { | 215 | else => |t| { |
| 217 | return Result{ | 216 | return Result{ |
| 218 | .fail = try ErrorMsg.create( | 217 | .fail = try ErrorMsg.create( |
| 219 | bin_file.base.allocator, | 218 | bin_file.allocator, |
| 220 | src, | 219 | src, |
| 221 | "TODO implement generateSymbol for type '{}'", | 220 | "TODO implement generateSymbol for type '{}'", |
| 222 | .{@tagName(t)}, | 221 | .{@tagName(t)}, |
| ... | @@ -234,13 +233,13 @@ const InnerError = error{ | ... | @@ -234,13 +233,13 @@ const InnerError = error{ |
| 234 | fn Function(comptime arch: std.Target.Cpu.Arch) type { | 233 | fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 235 | return struct { | 234 | return struct { |
| 236 | gpa: *Allocator, | 235 | gpa: *Allocator, |
| 237 | bin_file: *link.File.Elf, | 236 | bin_file: *link.File, |
| 238 | target: *const std.Target, | 237 | target: *const std.Target, |
| 239 | mod_fn: *const Module.Fn, | 238 | mod_fn: *const Module.Fn, |
| 240 | code: *std.ArrayList(u8), | 239 | code: *std.ArrayList(u8), |
| 241 | dbg_line: *std.ArrayList(u8), | 240 | dbg_line: *std.ArrayList(u8), |
| 242 | dbg_info: *std.ArrayList(u8), | 241 | dbg_info: *std.ArrayList(u8), |
| 243 | dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable, | 242 | dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable, |
| 244 | err_msg: ?*ErrorMsg, | 243 | err_msg: ?*ErrorMsg, |
| 245 | args: []MCValue, | 244 | args: []MCValue, |
| 246 | ret_mcv: MCValue, | 245 | ret_mcv: MCValue, |
| ... | @@ -405,22 +404,22 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -405,22 +404,22 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 405 | const Self = @This(); | 404 | const Self = @This(); |
| 406 | 405 | ||
| 407 | fn generateSymbol( | 406 | fn generateSymbol( |
| 408 | bin_file: *link.File.Elf, | 407 | bin_file: *link.File, |
| 409 | src: usize, | 408 | src: usize, |
| 410 | typed_value: TypedValue, | 409 | typed_value: TypedValue, |
| 411 | code: *std.ArrayList(u8), | 410 | code: *std.ArrayList(u8), |
| 412 | dbg_line: *std.ArrayList(u8), | 411 | dbg_line: *std.ArrayList(u8), |
| 413 | dbg_info: *std.ArrayList(u8), | 412 | dbg_info: *std.ArrayList(u8), |
| 414 | dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable, | 413 | dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable, |
| 415 | ) GenerateSymbolError!Result { | 414 | ) GenerateSymbolError!Result { |
| 416 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; | 415 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; |
| 417 | 416 | ||
| 418 | const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty; | 417 | const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty; |
| 419 | 418 | ||
| 420 | var branch_stack = std.ArrayList(Branch).init(bin_file.base.allocator); | 419 | var branch_stack = std.ArrayList(Branch).init(bin_file.allocator); |
| 421 | defer { | 420 | defer { |
| 422 | assert(branch_stack.items.len == 1); | 421 | assert(branch_stack.items.len == 1); |
| 423 | branch_stack.items[0].deinit(bin_file.base.allocator); | 422 | branch_stack.items[0].deinit(bin_file.allocator); |
| 424 | branch_stack.deinit(); | 423 | branch_stack.deinit(); |
| 425 | } | 424 | } |
| 426 | const branch = try branch_stack.addOne(); | 425 | const branch = try branch_stack.addOne(); |
| ... | @@ -443,8 +442,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -443,8 +442,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 443 | }; | 442 | }; |
| 444 | 443 | ||
| 445 | var function = Self{ | 444 | var function = Self{ |
| 446 | .gpa = bin_file.base.allocator, | 445 | .gpa = bin_file.allocator, |
| 447 | .target = &bin_file.base.options.target, | 446 | .target = &bin_file.options.target, |
| 448 | .bin_file = bin_file, | 447 | .bin_file = bin_file, |
| 449 | .mod_fn = module_fn, | 448 | .mod_fn = module_fn, |
| 450 | .code = code, | 449 | .code = code, |
| ... | @@ -464,7 +463,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -464,7 +463,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 464 | .rbrace_src = src_data.rbrace_src, | 463 | .rbrace_src = src_data.rbrace_src, |
| 465 | .source = src_data.source, | 464 | .source = src_data.source, |
| 466 | }; | 465 | }; |
| 467 | defer function.exitlude_jump_relocs.deinit(bin_file.base.allocator); | 466 | defer function.exitlude_jump_relocs.deinit(bin_file.allocator); |
| 468 | 467 | ||
| 469 | var call_info = function.resolveCallingConventionValues(src, fn_type) catch |err| switch (err) { | 468 | var call_info = function.resolveCallingConventionValues(src, fn_type) catch |err| switch (err) { |
| 470 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, | 469 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, |
| ... | @@ -684,6 +683,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -684,6 +683,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 684 | .unreach => return MCValue{ .unreach = {} }, | 683 | .unreach => return MCValue{ .unreach = {} }, |
| 685 | .unwrap_optional => return self.genUnwrapOptional(inst.castTag(.unwrap_optional).?), | 684 | .unwrap_optional => return self.genUnwrapOptional(inst.castTag(.unwrap_optional).?), |
| 686 | .wrap_optional => return self.genWrapOptional(inst.castTag(.wrap_optional).?), | 685 | .wrap_optional => return self.genWrapOptional(inst.castTag(.wrap_optional).?), |
| 686 | .varptr => return self.genVarPtr(inst.castTag(.varptr).?), | ||
| 687 | } | 687 | } |
| 688 | } | 688 | } |
| 689 | 689 | ||
| ... | @@ -858,6 +858,26 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -858,6 +858,26 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 858 | } | 858 | } |
| 859 | } | 859 | } |
| 860 | 860 | ||
| 861 | fn genVarPtr(self: *Self, inst: *ir.Inst.VarPtr) !MCValue { | ||
| 862 | // No side effects, so if it's unreferenced, do nothing. | ||
| 863 | if (inst.base.isUnused()) | ||
| 864 | return MCValue.dead; | ||
| 865 | |||
| 866 | switch (arch) { | ||
| 867 | else => return self.fail(inst.base.src, "TODO implement varptr for {}", .{self.target.cpu.arch}), | ||
| 868 | } | ||
| 869 | } | ||
| 870 | |||
| 871 | fn reuseOperand(inst: *ir.Inst, op_index: ir.Inst.DeathsBitIndex, mcv: MCValue) bool { | ||
| 872 | if (!inst.operandDies(op_index) or !mcv.isMutable()) | ||
| 873 | return false; | ||
| 874 | |||
| 875 | // OK we're going to do it, but we need to clear the operand death bit so that | ||
| 876 | // it stays allocated. | ||
| 877 | inst.clearOperandDeath(op_index); | ||
| 878 | return true; | ||
| 879 | } | ||
| 880 | |||
| 861 | fn genLoad(self: *Self, inst: *ir.Inst.UnOp) !MCValue { | 881 | fn genLoad(self: *Self, inst: *ir.Inst.UnOp) !MCValue { |
| 862 | const elem_ty = inst.base.ty; | 882 | const elem_ty = inst.base.ty; |
| 863 | if (!elem_ty.hasCodeGenBits()) | 883 | if (!elem_ty.hasCodeGenBits()) |
| ... | @@ -867,9 +887,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -867,9 +887,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 867 | if (inst.base.isUnused() and !is_volatile) | 887 | if (inst.base.isUnused() and !is_volatile) |
| 868 | return MCValue.dead; | 888 | return MCValue.dead; |
| 869 | const dst_mcv: MCValue = blk: { | 889 | const dst_mcv: MCValue = blk: { |
| 870 | if (inst.base.operandDies(0) and ptr.isMutable()) { | 890 | if (reuseOperand(&inst.base, 0, ptr)) { |
| 871 | // The MCValue that holds the pointer can be re-used as the value. | 891 | // The MCValue that holds the pointer can be re-used as the value. |
| 872 | // TODO track this in the register/stack allocation metadata. | ||
| 873 | break :blk ptr; | 892 | break :blk ptr; |
| 874 | } else { | 893 | } else { |
| 875 | break :blk try self.allocRegOrMem(&inst.base); | 894 | break :blk try self.allocRegOrMem(&inst.base); |
| ... | @@ -966,7 +985,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -966,7 +985,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 966 | var dst_mcv: MCValue = undefined; | 985 | var dst_mcv: MCValue = undefined; |
| 967 | var src_mcv: MCValue = undefined; | 986 | var src_mcv: MCValue = undefined; |
| 968 | var src_inst: *ir.Inst = undefined; | 987 | var src_inst: *ir.Inst = undefined; |
| 969 | if (inst.operandDies(0) and lhs.isMutable()) { | 988 | if (reuseOperand(inst, 0, lhs)) { |
| 970 | // LHS dies; use it as the destination. | 989 | // LHS dies; use it as the destination. |
| 971 | // Both operands cannot be memory. | 990 | // Both operands cannot be memory. |
| 972 | src_inst = op_rhs; | 991 | src_inst = op_rhs; |
| ... | @@ -977,7 +996,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -977,7 +996,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 977 | dst_mcv = lhs; | 996 | dst_mcv = lhs; |
| 978 | src_mcv = rhs; | 997 | src_mcv = rhs; |
| 979 | } | 998 | } |
| 980 | } else if (inst.operandDies(1) and rhs.isMutable()) { | 999 | } else if (reuseOperand(inst, 1, rhs)) { |
| 981 | // RHS dies; use it as the destination. | 1000 | // RHS dies; use it as the destination. |
| 982 | // Both operands cannot be memory. | 1001 | // Both operands cannot be memory. |
| 983 | src_inst = op_lhs; | 1002 | src_inst = op_lhs; |
| ... | @@ -1124,80 +1143,88 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1124,80 +1143,88 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1124 | var info = try self.resolveCallingConventionValues(inst.base.src, inst.func.ty); | 1143 | var info = try self.resolveCallingConventionValues(inst.base.src, inst.func.ty); |
| 1125 | defer info.deinit(self); | 1144 | defer info.deinit(self); |
| 1126 | 1145 | ||
| 1127 | switch (arch) { | 1146 | // Due to incremental compilation, how function calls are generated depends |
| 1128 | .x86_64 => { | 1147 | // on linking. |
| 1129 | for (info.args) |mc_arg, arg_i| { | 1148 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 1130 | const arg = inst.args[arg_i]; | 1149 | switch (arch) { |
| 1131 | const arg_mcv = try self.resolveInst(inst.args[arg_i]); | 1150 | .x86_64 => { |
| 1132 | // Here we do not use setRegOrMem even though the logic is similar, because | 1151 | for (info.args) |mc_arg, arg_i| { |
| 1133 | // the function call will move the stack pointer, so the offsets are different. | 1152 | const arg = inst.args[arg_i]; |
| 1134 | switch (mc_arg) { | 1153 | const arg_mcv = try self.resolveInst(inst.args[arg_i]); |
| 1135 | .none => continue, | 1154 | // Here we do not use setRegOrMem even though the logic is similar, because |
| 1136 | .register => |reg| { | 1155 | // the function call will move the stack pointer, so the offsets are different. |
| 1137 | try self.genSetReg(arg.src, reg, arg_mcv); | 1156 | switch (mc_arg) { |
| 1138 | // TODO interact with the register allocator to mark the instruction as moved. | 1157 | .none => continue, |
| 1139 | }, | 1158 | .register => |reg| { |
| 1140 | .stack_offset => { | 1159 | try self.genSetReg(arg.src, reg, arg_mcv); |
| 1141 | // Here we need to emit instructions like this: | 1160 | // TODO interact with the register allocator to mark the instruction as moved. |
| 1142 | // mov qword ptr [rsp + stack_offset], x | 1161 | }, |
| 1143 | return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{}); | 1162 | .stack_offset => { |
| 1144 | }, | 1163 | // Here we need to emit instructions like this: |
| 1145 | .ptr_stack_offset => { | 1164 | // mov qword ptr [rsp + stack_offset], x |
| 1146 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{}); | 1165 | return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{}); |
| 1147 | }, | 1166 | }, |
| 1148 | .ptr_embedded_in_code => { | 1167 | .ptr_stack_offset => { |
| 1149 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); | 1168 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 1150 | }, | 1169 | }, |
| 1151 | .undef => unreachable, | 1170 | .ptr_embedded_in_code => { |
| 1152 | .immediate => unreachable, | 1171 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 1153 | .unreach => unreachable, | 1172 | }, |
| 1154 | .dead => unreachable, | 1173 | .undef => unreachable, |
| 1155 | .embedded_in_code => unreachable, | 1174 | .immediate => unreachable, |
| 1156 | .memory => unreachable, | 1175 | .unreach => unreachable, |
| 1157 | .compare_flags_signed => unreachable, | 1176 | .dead => unreachable, |
| 1158 | .compare_flags_unsigned => unreachable, | 1177 | .embedded_in_code => unreachable, |
| 1178 | .memory => unreachable, | ||
| 1179 | .compare_flags_signed => unreachable, | ||
| 1180 | .compare_flags_unsigned => unreachable, | ||
| 1181 | } | ||
| 1159 | } | 1182 | } |
| 1160 | } | ||
| 1161 | 1183 | ||
| 1162 | if (inst.func.cast(ir.Inst.Constant)) |func_inst| { | 1184 | if (inst.func.cast(ir.Inst.Constant)) |func_inst| { |
| 1163 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | 1185 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { |
| 1164 | const func = func_val.func; | 1186 | const func = func_val.func; |
| 1165 | const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?]; | 1187 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 1166 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 1188 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1167 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 1189 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1168 | const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | 1190 | const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); |
| 1169 | // ff 14 25 xx xx xx xx call [addr] | 1191 | // ff 14 25 xx xx xx xx call [addr] |
| 1170 | try self.code.ensureCapacity(self.code.items.len + 7); | 1192 | try self.code.ensureCapacity(self.code.items.len + 7); |
| 1171 | self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 }); | 1193 | self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 }); |
| 1172 | mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr); | 1194 | mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr); |
| 1195 | } else { | ||
| 1196 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); | ||
| 1197 | } | ||
| 1173 | } else { | 1198 | } else { |
| 1174 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); | 1199 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 1175 | } | 1200 | } |
| 1176 | } else { | 1201 | }, |
| 1177 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); | 1202 | .riscv64 => { |
| 1178 | } | 1203 | if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch}); |
| 1179 | }, | 1204 | |
| 1180 | .riscv64 => { | 1205 | if (inst.func.cast(ir.Inst.Constant)) |func_inst| { |
| 1181 | if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch}); | 1206 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { |
| 1182 | 1207 | const func = func_val.func; | |
| 1183 | if (inst.func.cast(ir.Inst.Constant)) |func_inst| { | 1208 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 1184 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | 1209 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1185 | const func = func_val.func; | 1210 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1186 | const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?]; | 1211 | const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); |
| 1187 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 1212 | |
| 1188 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 1213 | try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr }); |
| 1189 | const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes); | 1214 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32()); |
| 1190 | 1215 | } else { | |
| 1191 | try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr }); | 1216 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1192 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32()); | 1217 | } |
| 1193 | } else { | 1218 | } else { |
| 1194 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); | 1219 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 1195 | } | 1220 | } |
| 1196 | } else { | 1221 | }, |
| 1197 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); | 1222 | else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), |
| 1198 | } | 1223 | } |
| 1199 | }, | 1224 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 1200 | else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), | 1225 | return self.fail(inst.base.src, "TODO implement codegen for call when linking with MachO", .{}); |
| 1226 | } else { | ||
| 1227 | unreachable; | ||
| 1201 | } | 1228 | } |
| 1202 | 1229 | ||
| 1203 | return info.return_value; | 1230 | return info.return_value; |
| ... | @@ -2016,10 +2043,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2016,10 +2043,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2016 | switch (typed_value.ty.zigTypeTag()) { | 2043 | switch (typed_value.ty.zigTypeTag()) { |
| 2017 | .Pointer => { | 2044 | .Pointer => { |
| 2018 | if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| { | 2045 | if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| { |
| 2019 | const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?]; | 2046 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 2020 | const decl = payload.decl; | 2047 | const decl = payload.decl; |
| 2021 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; | 2048 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 2022 | return MCValue{ .memory = got_addr }; | 2049 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
| 2050 | return MCValue{ .memory = got_addr }; | ||
| 2051 | } else { | ||
| 2052 | return self.fail(src, "TODO codegen non-ELF const Decl pointer", .{}); | ||
| 2053 | } | ||
| 2023 | } | 2054 | } |
| 2024 | return self.fail(src, "TODO codegen more kinds of const pointers", .{}); | 2055 | return self.fail(src, "TODO codegen more kinds of const pointers", .{}); |
| 2025 | }, | 2056 | }, |
| ... | @@ -2040,7 +2071,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2040,7 +2071,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2040 | if (typed_value.val.isNull()) | 2071 | if (typed_value.val.isNull()) |
| 2041 | return MCValue{ .immediate = 0 }; | 2072 | return MCValue{ .immediate = 0 }; |
| 2042 | 2073 | ||
| 2043 | var buf: Type.Payload.Pointer = undefined; | 2074 | var buf: Type.Payload.PointerSimple = undefined; |
| 2044 | return self.genTypedValue(src, .{ | 2075 | return self.genTypedValue(src, .{ |
| 2045 | .ty = typed_value.ty.optionalChild(&buf), | 2076 | .ty = typed_value.ty.optionalChild(&buf), |
| 2046 | .val = typed_value.val, | 2077 | .val = typed_value.val, |
| ... | @@ -2147,7 +2178,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2147,7 +2178,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2147 | 2178 | ||
| 2148 | /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. | 2179 | /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. |
| 2149 | fn wantSafety(self: *Self) bool { | 2180 | fn wantSafety(self: *Self) bool { |
| 2150 | return switch (self.bin_file.base.options.optimize_mode) { | 2181 | return switch (self.bin_file.options.optimize_mode) { |
| 2151 | .Debug => true, | 2182 | .Debug => true, |
| 2152 | .ReleaseSafe => true, | 2183 | .ReleaseSafe => true, |
| 2153 | .ReleaseFast => false, | 2184 | .ReleaseFast => false, |
| ... | @@ -2158,7 +2189,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2158,7 +2189,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2158 | fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) InnerError { | 2189 | fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) InnerError { |
| 2159 | @setCold(true); | 2190 | @setCold(true); |
| 2160 | assert(self.err_msg == null); | 2191 | assert(self.err_msg == null); |
| 2161 | self.err_msg = try ErrorMsg.create(self.bin_file.base.allocator, src, format, args); | 2192 | self.err_msg = try ErrorMsg.create(self.bin_file.allocator, src, format, args); |
| 2162 | return error.CodegenFail; | 2193 | return error.CodegenFail; |
| 2163 | } | 2194 | } |
| 2164 | 2195 |
src-self-hosted/codegen/wasm.zig+59-37| ... | @@ -62,58 +62,80 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void { | ... | @@ -62,58 +62,80 @@ pub fn genCode(buf: *ArrayList(u8), decl: *Decl) !void { |
| 62 | // TODO: check for and handle death of instructions | 62 | // TODO: check for and handle death of instructions |
| 63 | const tv = decl.typed_value.most_recent.typed_value; | 63 | const tv = decl.typed_value.most_recent.typed_value; |
| 64 | const mod_fn = tv.val.cast(Value.Payload.Function).?.func; | 64 | const mod_fn = tv.val.cast(Value.Payload.Function).?.func; |
| 65 | for (mod_fn.analysis.success.instructions) |inst| try genInst(writer, inst); | 65 | for (mod_fn.analysis.success.instructions) |inst| try genInst(buf, decl, inst); |
| 66 | 66 | ||
| 67 | // Write 'end' opcode | 67 | // Write 'end' opcode |
| 68 | try writer.writeByte(0x0B); | 68 | try writer.writeByte(0x0B); |
| 69 | 69 | ||
| 70 | // Fill in the size of the generated code to the reserved space at the | 70 | // Fill in the size of the generated code to the reserved space at the |
| 71 | // beginning of the buffer. | 71 | // beginning of the buffer. |
| 72 | leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, buf.items.len - 5)); | 72 | const size = buf.items.len - 5 + decl.fn_link.wasm.?.idx_refs.items.len * 5; |
| 73 | leb.writeUnsignedFixed(5, buf.items[0..5], @intCast(u32, size)); | ||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | fn genInst(writer: ArrayList(u8).Writer, inst: *Inst) !void { | 76 | fn genInst(buf: *ArrayList(u8), decl: *Decl, inst: *Inst) !void { |
| 76 | return switch (inst.tag) { | 77 | return switch (inst.tag) { |
| 78 | .call => genCall(buf, decl, inst.castTag(.call).?), | ||
| 79 | .constant => genConstant(buf, decl, inst.castTag(.constant).?), | ||
| 77 | .dbg_stmt => {}, | 80 | .dbg_stmt => {}, |
| 78 | .ret => genRet(writer, inst.castTag(.ret).?), | 81 | .ret => genRet(buf, decl, inst.castTag(.ret).?), |
| 82 | .retvoid => {}, | ||
| 79 | else => error.TODOImplementMoreWasmCodegen, | 83 | else => error.TODOImplementMoreWasmCodegen, |
| 80 | }; | 84 | }; |
| 81 | } | 85 | } |
| 82 | 86 | ||
| 83 | fn genRet(writer: ArrayList(u8).Writer, inst: *Inst.UnOp) !void { | 87 | fn genConstant(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Constant) !void { |
| 84 | switch (inst.operand.tag) { | 88 | const writer = buf.writer(); |
| 85 | .constant => { | 89 | switch (inst.base.ty.tag()) { |
| 86 | const constant = inst.operand.castTag(.constant).?; | 90 | .u32 => { |
| 87 | switch (inst.operand.ty.tag()) { | 91 | try writer.writeByte(0x41); // i32.const |
| 88 | .u32 => { | 92 | try leb.writeILEB128(writer, inst.val.toUnsignedInt()); |
| 89 | try writer.writeByte(0x41); // i32.const | 93 | }, |
| 90 | try leb.writeILEB128(writer, constant.val.toUnsignedInt()); | 94 | .i32 => { |
| 91 | }, | 95 | try writer.writeByte(0x41); // i32.const |
| 92 | .i32 => { | 96 | try leb.writeILEB128(writer, inst.val.toSignedInt()); |
| 93 | try writer.writeByte(0x41); // i32.const | 97 | }, |
| 94 | try leb.writeILEB128(writer, constant.val.toSignedInt()); | 98 | .u64 => { |
| 95 | }, | 99 | try writer.writeByte(0x42); // i64.const |
| 96 | .u64 => { | 100 | try leb.writeILEB128(writer, inst.val.toUnsignedInt()); |
| 97 | try writer.writeByte(0x42); // i64.const | 101 | }, |
| 98 | try leb.writeILEB128(writer, constant.val.toUnsignedInt()); | 102 | .i64 => { |
| 99 | }, | 103 | try writer.writeByte(0x42); // i64.const |
| 100 | .i64 => { | 104 | try leb.writeILEB128(writer, inst.val.toSignedInt()); |
| 101 | try writer.writeByte(0x42); // i64.const | ||
| 102 | try leb.writeILEB128(writer, constant.val.toSignedInt()); | ||
| 103 | }, | ||
| 104 | .f32 => { | ||
| 105 | try writer.writeByte(0x43); // f32.const | ||
| 106 | // TODO: enforce LE byte order | ||
| 107 | try writer.writeAll(mem.asBytes(&constant.val.toFloat(f32))); | ||
| 108 | }, | ||
| 109 | .f64 => { | ||
| 110 | try writer.writeByte(0x44); // f64.const | ||
| 111 | // TODO: enforce LE byte order | ||
| 112 | try writer.writeAll(mem.asBytes(&constant.val.toFloat(f64))); | ||
| 113 | }, | ||
| 114 | else => return error.TODOImplementMoreWasmCodegen, | ||
| 115 | } | ||
| 116 | }, | 105 | }, |
| 106 | .f32 => { | ||
| 107 | try writer.writeByte(0x43); // f32.const | ||
| 108 | // TODO: enforce LE byte order | ||
| 109 | try writer.writeAll(mem.asBytes(&inst.val.toFloat(f32))); | ||
| 110 | }, | ||
| 111 | .f64 => { | ||
| 112 | try writer.writeByte(0x44); // f64.const | ||
| 113 | // TODO: enforce LE byte order | ||
| 114 | try writer.writeAll(mem.asBytes(&inst.val.toFloat(f64))); | ||
| 115 | }, | ||
| 116 | .void => {}, | ||
| 117 | else => return error.TODOImplementMoreWasmCodegen, | 117 | else => return error.TODOImplementMoreWasmCodegen, |
| 118 | } | 118 | } |
| 119 | } | 119 | } |
| 120 | |||
| 121 | fn genRet(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.UnOp) !void { | ||
| 122 | try genInst(buf, decl, inst.operand); | ||
| 123 | } | ||
| 124 | |||
| 125 | fn genCall(buf: *ArrayList(u8), decl: *Decl, inst: *Inst.Call) !void { | ||
| 126 | const func_inst = inst.func.castTag(.constant).?; | ||
| 127 | const func_val = func_inst.val.cast(Value.Payload.Function).?; | ||
| 128 | const target = func_val.func.owner_decl; | ||
| 129 | const target_ty = target.typed_value.most_recent.typed_value.ty; | ||
| 130 | |||
| 131 | if (inst.args.len != 0) return error.TODOImplementMoreWasmCodegen; | ||
| 132 | |||
| 133 | try buf.append(0x10); // call | ||
| 134 | |||
| 135 | // The function index immediate argument will be filled in using this data | ||
| 136 | // in link.Wasm.flush(). | ||
| 137 | try decl.fn_link.wasm.?.idx_refs.append(buf.allocator, .{ | ||
| 138 | .offset = @intCast(u32, buf.items.len), | ||
| 139 | .decl = target, | ||
| 140 | }); | ||
| 141 | } |
src-self-hosted/introspect.zig+8-5| ... | @@ -87,6 +87,13 @@ pub fn resolveGlobalCacheDir(allocator: *mem.Allocator) ![]u8 { | ... | @@ -87,6 +87,13 @@ pub fn resolveGlobalCacheDir(allocator: *mem.Allocator) ![]u8 { |
| 87 | return fs.getAppDataDir(allocator, appname); | 87 | return fs.getAppDataDir(allocator, appname); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | pub fn openGlobalCacheDir() !fs.Dir { | ||
| 91 | var buf: [fs.MAX_PATH_BYTES]u8 = undefined; | ||
| 92 | var fba = std.heap.FixedBufferAllocator.init(&buf); | ||
| 93 | const path_name = try resolveGlobalCacheDir(&fba.allocator); | ||
| 94 | return fs.cwd().makeOpenPath(path_name, .{}); | ||
| 95 | } | ||
| 96 | |||
| 90 | var compiler_id_mutex = std.Mutex{}; | 97 | var compiler_id_mutex = std.Mutex{}; |
| 91 | var compiler_id: [16]u8 = undefined; | 98 | var compiler_id: [16]u8 = undefined; |
| 92 | var compiler_id_computed = false; | 99 | var compiler_id_computed = false; |
| ... | @@ -99,11 +106,7 @@ pub fn resolveCompilerId(gpa: *mem.Allocator) ![16]u8 { | ... | @@ -99,11 +106,7 @@ pub fn resolveCompilerId(gpa: *mem.Allocator) ![16]u8 { |
| 99 | return compiler_id; | 106 | return compiler_id; |
| 100 | compiler_id_computed = true; | 107 | compiler_id_computed = true; |
| 101 | 108 | ||
| 102 | const global_cache_dir = try resolveGlobalCacheDir(gpa); | 109 | var cache_dir = try openGlobalCacheDir(); |
| 103 | defer gpa.free(global_cache_dir); | ||
| 104 | |||
| 105 | // TODO Introduce openGlobalCacheDir which returns a dir handle rather than a string. | ||
| 106 | var cache_dir = try fs.cwd().openDir(global_cache_dir, .{}); | ||
| 107 | defer cache_dir.close(); | 110 | defer cache_dir.close(); |
| 108 | 111 | ||
| 109 | var ch = try CacheHash.init(gpa, cache_dir, "exe"); | 112 | var ch = try CacheHash.init(gpa, cache_dir, "exe"); |
src-self-hosted/ir.zig+21| ... | @@ -42,6 +42,11 @@ pub const Inst = struct { | ... | @@ -42,6 +42,11 @@ pub const Inst = struct { |
| 42 | return @truncate(u1, self.deaths >> index) != 0; | 42 | return @truncate(u1, self.deaths >> index) != 0; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | pub fn clearOperandDeath(self: *Inst, index: DeathsBitIndex) void { | ||
| 46 | assert(index < deaths_bits); | ||
| 47 | self.deaths &= ~(@as(DeathsInt, 1) << index); | ||
| 48 | } | ||
| 49 | |||
| 45 | pub fn specialOperandDeaths(self: Inst) bool { | 50 | pub fn specialOperandDeaths(self: Inst) bool { |
| 46 | return (self.deaths & (1 << deaths_bits)) != 0; | 51 | return (self.deaths & (1 << deaths_bits)) != 0; |
| 47 | } | 52 | } |
| ... | @@ -76,6 +81,7 @@ pub const Inst = struct { | ... | @@ -76,6 +81,7 @@ pub const Inst = struct { |
| 76 | ref, | 81 | ref, |
| 77 | ret, | 82 | ret, |
| 78 | retvoid, | 83 | retvoid, |
| 84 | varptr, | ||
| 79 | /// Write a value to a pointer. LHS is pointer, RHS is value. | 85 | /// Write a value to a pointer. LHS is pointer, RHS is value. |
| 80 | store, | 86 | store, |
| 81 | sub, | 87 | sub, |
| ... | @@ -130,6 +136,7 @@ pub const Inst = struct { | ... | @@ -130,6 +136,7 @@ pub const Inst = struct { |
| 130 | .condbr => CondBr, | 136 | .condbr => CondBr, |
| 131 | .constant => Constant, | 137 | .constant => Constant, |
| 132 | .loop => Loop, | 138 | .loop => Loop, |
| 139 | .varptr => VarPtr, | ||
| 133 | }; | 140 | }; |
| 134 | } | 141 | } |
| 135 | 142 | ||
| ... | @@ -429,6 +436,20 @@ pub const Inst = struct { | ... | @@ -429,6 +436,20 @@ pub const Inst = struct { |
| 429 | return null; | 436 | return null; |
| 430 | } | 437 | } |
| 431 | }; | 438 | }; |
| 439 | |||
| 440 | pub const VarPtr = struct { | ||
| 441 | pub const base_tag = Tag.varptr; | ||
| 442 | |||
| 443 | base: Inst, | ||
| 444 | variable: *Module.Var, | ||
| 445 | |||
| 446 | pub fn operandCount(self: *const VarPtr) usize { | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | pub fn getOperand(self: *const VarPtr, index: usize) ?*Inst { | ||
| 450 | return null; | ||
| 451 | } | ||
| 452 | }; | ||
| 432 | }; | 453 | }; |
| 433 | 454 | ||
| 434 | pub const Body = struct { | 455 | pub const Body = struct { |
src-self-hosted/link.zig+36-2686| ... | @@ -1,28 +1,10 @@ | ... | @@ -1,28 +1,10 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const mem = std.mem; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const Allocator = std.mem.Allocator; | 2 | const Allocator = std.mem.Allocator; |
| 5 | const ir = @import("ir.zig"); | ||
| 6 | const Module = @import("Module.zig"); | 3 | const Module = @import("Module.zig"); |
| 7 | const fs = std.fs; | 4 | const fs = std.fs; |
| 8 | const elf = std.elf; | ||
| 9 | const codegen = @import("codegen.zig"); | ||
| 10 | const c_codegen = @import("codegen/c.zig"); | ||
| 11 | const log = std.log.scoped(.link); | ||
| 12 | const DW = std.dwarf; | ||
| 13 | const trace = @import("tracy.zig").trace; | 5 | const trace = @import("tracy.zig").trace; |
| 14 | const leb128 = std.debug.leb; | ||
| 15 | const Package = @import("Package.zig"); | 6 | const Package = @import("Package.zig"); |
| 16 | const Value = @import("value.zig").Value; | ||
| 17 | const Type = @import("type.zig").Type; | 7 | const Type = @import("type.zig").Type; |
| 18 | const build_options = @import("build_options"); | ||
| 19 | |||
| 20 | const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; | ||
| 21 | |||
| 22 | // TODO Turn back on zig fmt when https://github.com/ziglang/zig/issues/5948 is implemented. | ||
| 23 | // zig fmt: off | ||
| 24 | |||
| 25 | const default_entry_addr = 0x8000000; | ||
| 26 | 8 | ||
| 27 | pub const Options = struct { | 9 | pub const Options = struct { |
| 28 | target: std.Target, | 10 | target: std.Target, |
| ... | @@ -40,8 +22,12 @@ pub const Options = struct { | ... | @@ -40,8 +22,12 @@ pub const Options = struct { |
| 40 | program_code_size_hint: u64 = 256 * 1024, | 22 | program_code_size_hint: u64 = 256 * 1024, |
| 41 | }; | 23 | }; |
| 42 | 24 | ||
| 43 | |||
| 44 | pub const File = struct { | 25 | pub const File = struct { |
| 26 | tag: Tag, | ||
| 27 | options: Options, | ||
| 28 | file: ?fs.File, | ||
| 29 | allocator: *Allocator, | ||
| 30 | |||
| 45 | pub const LinkBlock = union { | 31 | pub const LinkBlock = union { |
| 46 | elf: Elf.TextBlock, | 32 | elf: Elf.TextBlock, |
| 47 | macho: MachO.TextBlock, | 33 | macho: MachO.TextBlock, |
| ... | @@ -56,16 +42,24 @@ pub const File = struct { | ... | @@ -56,16 +42,24 @@ pub const File = struct { |
| 56 | wasm: ?Wasm.FnData, | 42 | wasm: ?Wasm.FnData, |
| 57 | }; | 43 | }; |
| 58 | 44 | ||
| 59 | tag: Tag, | 45 | /// For DWARF .debug_info. |
| 60 | options: Options, | 46 | pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.hash, Type.eql, true); |
| 61 | file: ?fs.File, | 47 | |
| 62 | allocator: *Allocator, | 48 | /// For DWARF .debug_info. |
| 49 | pub const DbgInfoTypeReloc = struct { | ||
| 50 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | ||
| 51 | /// This is where the .debug_info tag for the type is. | ||
| 52 | off: u32, | ||
| 53 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | ||
| 54 | /// List of DW.AT_type / DW.FORM_ref4 that points to the type. | ||
| 55 | relocs: std.ArrayListUnmanaged(u32), | ||
| 56 | }; | ||
| 63 | 57 | ||
| 64 | /// Attempts incremental linking, if the file already exists. If | 58 | /// Attempts incremental linking, if the file already exists. If |
| 65 | /// incremental linking fails, falls back to truncating the file and | 59 | /// incremental linking fails, falls back to truncating the file and |
| 66 | /// rewriting it. A malicious file is detected as incremental link failure | 60 | /// rewriting it. A malicious file is detected as incremental link failure |
| 67 | /// and does not cause Illegal Behavior. This operation is not atomic. | 61 | /// and does not cause Illegal Behavior. This operation is not atomic. |
| 68 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File { | 62 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File { |
| 69 | switch (options.object_format) { | 63 | switch (options.object_format) { |
| 70 | .unknown => unreachable, | 64 | .unknown => unreachable, |
| 71 | .coff => return error.TODOImplementCoff, | 65 | .coff => return error.TODOImplementCoff, |
| ... | @@ -110,6 +104,8 @@ pub const File = struct { | ... | @@ -110,6 +104,8 @@ pub const File = struct { |
| 110 | } | 104 | } |
| 111 | } | 105 | } |
| 112 | 106 | ||
| 107 | /// May be called before or after updateDeclExports but must be called | ||
| 108 | /// after allocateDeclIndexes for any given Decl. | ||
| 113 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { | 109 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { |
| 114 | switch (base.tag) { | 110 | switch (base.tag) { |
| 115 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), | 111 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| ... | @@ -127,6 +123,8 @@ pub const File = struct { | ... | @@ -127,6 +123,8 @@ pub const File = struct { |
| 127 | } | 123 | } |
| 128 | } | 124 | } |
| 129 | 125 | ||
| 126 | /// Must be called before any call to updateDecl or updateDeclExports for | ||
| 127 | /// any given Decl. | ||
| 130 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { | 128 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { |
| 131 | switch (base.tag) { | 129 | switch (base.tag) { |
| 132 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), | 130 | .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| ... | @@ -200,7 +198,8 @@ pub const File = struct { | ... | @@ -200,7 +198,8 @@ pub const File = struct { |
| 200 | }; | 198 | }; |
| 201 | } | 199 | } |
| 202 | 200 | ||
| 203 | /// Must be called only after a successful call to `updateDecl`. | 201 | /// May be called before or after updateDecl, but must be called after |
| 202 | /// allocateDeclIndexes for any given Decl. | ||
| 204 | pub fn updateDeclExports( | 203 | pub fn updateDeclExports( |
| 205 | base: *File, | 204 | base: *File, |
| 206 | module: *Module, | 205 | module: *Module, |
| ... | @@ -215,6 +214,15 @@ pub const File = struct { | ... | @@ -215,6 +214,15 @@ pub const File = struct { |
| 215 | } | 214 | } |
| 216 | } | 215 | } |
| 217 | 216 | ||
| 217 | pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 { | ||
| 218 | switch (base.tag) { | ||
| 219 | .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl), | ||
| 220 | .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl), | ||
| 221 | .c => unreachable, | ||
| 222 | .wasm => unreachable, | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 218 | pub const Tag = enum { | 226 | pub const Tag = enum { |
| 219 | elf, | 227 | elf, |
| 220 | macho, | 228 | macho, |
| ... | @@ -226,2670 +234,12 @@ pub const File = struct { | ... | @@ -226,2670 +234,12 @@ pub const File = struct { |
| 226 | no_entry_point_found: bool = false, | 234 | no_entry_point_found: bool = false, |
| 227 | }; | 235 | }; |
| 228 | 236 | ||
| 229 | pub const C = struct { | 237 | pub const C = @import("link/C.zig"); |
| 230 | pub const base_tag: Tag = .c; | 238 | pub const Elf = @import("link/Elf.zig"); |
| 231 | |||
| 232 | base: File, | ||
| 233 | |||
| 234 | header: std.ArrayList(u8), | ||
| 235 | constants: std.ArrayList(u8), | ||
| 236 | main: std.ArrayList(u8), | ||
| 237 | |||
| 238 | called: std.StringHashMap(void), | ||
| 239 | need_stddef: bool = false, | ||
| 240 | need_stdint: bool = false, | ||
| 241 | error_msg: *Module.ErrorMsg = undefined, | ||
| 242 | |||
| 243 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File { | ||
| 244 | assert(options.object_format == .c); | ||
| 245 | |||
| 246 | const file = try dir.createFile(sub_path, .{ .truncate = true, .read = true, .mode = determineMode(options) }); | ||
| 247 | errdefer file.close(); | ||
| 248 | |||
| 249 | var c_file = try allocator.create(C); | ||
| 250 | errdefer allocator.destroy(c_file); | ||
| 251 | |||
| 252 | c_file.* = File.C{ | ||
| 253 | .base = .{ | ||
| 254 | .tag = .c, | ||
| 255 | .options = options, | ||
| 256 | .file = file, | ||
| 257 | .allocator = allocator, | ||
| 258 | }, | ||
| 259 | .main = std.ArrayList(u8).init(allocator), | ||
| 260 | .header = std.ArrayList(u8).init(allocator), | ||
| 261 | .constants = std.ArrayList(u8).init(allocator), | ||
| 262 | .called = std.StringHashMap(void).init(allocator), | ||
| 263 | }; | ||
| 264 | |||
| 265 | return &c_file.base; | ||
| 266 | } | ||
| 267 | |||
| 268 | pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) error{AnalysisFail, OutOfMemory} { | ||
| 269 | self.error_msg = try Module.ErrorMsg.create(self.base.allocator, src, format, args); | ||
| 270 | return error.AnalysisFail; | ||
| 271 | } | ||
| 272 | |||
| 273 | pub fn deinit(self: *File.C) void { | ||
| 274 | self.main.deinit(); | ||
| 275 | self.header.deinit(); | ||
| 276 | self.constants.deinit(); | ||
| 277 | self.called.deinit(); | ||
| 278 | } | ||
| 279 | |||
| 280 | pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { | ||
| 281 | c_codegen.generate(self, decl) catch |err| { | ||
| 282 | if (err == error.AnalysisFail) { | ||
| 283 | try module.failed_decls.put(module.gpa, decl, self.error_msg); | ||
| 284 | } | ||
| 285 | return err; | ||
| 286 | }; | ||
| 287 | } | ||
| 288 | |||
| 289 | pub fn flush(self: *File.C, module: *Module) !void { | ||
| 290 | const writer = self.base.file.?.writer(); | ||
| 291 | try writer.writeAll(@embedFile("cbe.h")); | ||
| 292 | var includes = false; | ||
| 293 | if (self.need_stddef) { | ||
| 294 | try writer.writeAll("#include <stddef.h>\n"); | ||
| 295 | includes = true; | ||
| 296 | } | ||
| 297 | if (self.need_stdint) { | ||
| 298 | try writer.writeAll("#include <stdint.h>\n"); | ||
| 299 | includes = true; | ||
| 300 | } | ||
| 301 | if (includes) { | ||
| 302 | try writer.writeByte('\n'); | ||
| 303 | } | ||
| 304 | if (self.header.items.len > 0) { | ||
| 305 | try writer.print("{}\n", .{self.header.items}); | ||
| 306 | } | ||
| 307 | if (self.constants.items.len > 0) { | ||
| 308 | try writer.print("{}\n", .{self.constants.items}); | ||
| 309 | } | ||
| 310 | if (self.main.items.len > 1) { | ||
| 311 | const last_two = self.main.items[self.main.items.len - 2 ..]; | ||
| 312 | if (std.mem.eql(u8, last_two, "\n\n")) { | ||
| 313 | self.main.items.len -= 1; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | try writer.writeAll(self.main.items); | ||
| 317 | self.base.file.?.close(); | ||
| 318 | self.base.file = null; | ||
| 319 | } | ||
| 320 | }; | ||
| 321 | |||
| 322 | pub const Elf = struct { | ||
| 323 | pub const base_tag: Tag = .elf; | ||
| 324 | |||
| 325 | base: File, | ||
| 326 | |||
| 327 | ptr_width: enum { p32, p64 }, | ||
| 328 | |||
| 329 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 330 | /// Same order as in the file. | ||
| 331 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, | ||
| 332 | shdr_table_offset: ?u64 = null, | ||
| 333 | |||
| 334 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 335 | /// Same order as in the file. | ||
| 336 | program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = std.ArrayListUnmanaged(elf.Elf64_Phdr){}, | ||
| 337 | phdr_table_offset: ?u64 = null, | ||
| 338 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | ||
| 339 | phdr_load_re_index: ?u16 = null, | ||
| 340 | /// The index into the program headers of the global offset table. | ||
| 341 | /// It needs PT_LOAD and Read flags. | ||
| 342 | phdr_got_index: ?u16 = null, | ||
| 343 | entry_addr: ?u64 = null, | ||
| 344 | |||
| 345 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | ||
| 346 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | ||
| 347 | shstrtab_index: ?u16 = null, | ||
| 348 | |||
| 349 | text_section_index: ?u16 = null, | ||
| 350 | symtab_section_index: ?u16 = null, | ||
| 351 | got_section_index: ?u16 = null, | ||
| 352 | debug_info_section_index: ?u16 = null, | ||
| 353 | debug_abbrev_section_index: ?u16 = null, | ||
| 354 | debug_str_section_index: ?u16 = null, | ||
| 355 | debug_aranges_section_index: ?u16 = null, | ||
| 356 | debug_line_section_index: ?u16 = null, | ||
| 357 | |||
| 358 | debug_abbrev_table_offset: ?u64 = null, | ||
| 359 | |||
| 360 | /// The same order as in the file. ELF requires global symbols to all be after the | ||
| 361 | /// local symbols, they cannot be mixed. So we must buffer all the global symbols and | ||
| 362 | /// write them at the end. These are only the local symbols. The length of this array | ||
| 363 | /// is the value used for sh_info in the .symtab section. | ||
| 364 | local_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | ||
| 365 | global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | ||
| 366 | |||
| 367 | local_symbol_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 368 | global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 369 | offset_table_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 370 | |||
| 371 | /// Same order as in the file. The value is the absolute vaddr value. | ||
| 372 | /// If the vaddr of the executable program header changes, the entire | ||
| 373 | /// offset table needs to be rewritten. | ||
| 374 | offset_table: std.ArrayListUnmanaged(u64) = .{}, | ||
| 375 | |||
| 376 | phdr_table_dirty: bool = false, | ||
| 377 | shdr_table_dirty: bool = false, | ||
| 378 | shstrtab_dirty: bool = false, | ||
| 379 | debug_strtab_dirty: bool = false, | ||
| 380 | offset_table_count_dirty: bool = false, | ||
| 381 | debug_abbrev_section_dirty: bool = false, | ||
| 382 | debug_aranges_section_dirty: bool = false, | ||
| 383 | |||
| 384 | debug_info_header_dirty: bool = false, | ||
| 385 | debug_line_header_dirty: bool = false, | ||
| 386 | |||
| 387 | error_flags: ErrorFlags = ErrorFlags{}, | ||
| 388 | |||
| 389 | /// A list of text blocks that have surplus capacity. This list can have false | ||
| 390 | /// positives, as functions grow and shrink over time, only sometimes being added | ||
| 391 | /// or removed from the freelist. | ||
| 392 | /// | ||
| 393 | /// A text block has surplus capacity when its overcapacity value is greater than | ||
| 394 | /// minimum_text_block_size * alloc_num / alloc_den. That is, when it has so | ||
| 395 | /// much extra capacity, that we could fit a small new symbol in it, itself with | ||
| 396 | /// ideal_capacity or more. | ||
| 397 | /// | ||
| 398 | /// Ideal capacity is defined by size * alloc_num / alloc_den. | ||
| 399 | /// | ||
| 400 | /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that | ||
| 401 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | ||
| 402 | /// allocate a fresh text block, which will have ideal capacity, and then grow it | ||
| 403 | /// by 1 byte. It will then have -1 overcapacity. | ||
| 404 | text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, | ||
| 405 | last_text_block: ?*TextBlock = null, | ||
| 406 | |||
| 407 | /// A list of `SrcFn` whose Line Number Programs have surplus capacity. | ||
| 408 | /// This is the same concept as `text_block_free_list`; see those doc comments. | ||
| 409 | dbg_line_fn_free_list: std.AutoHashMapUnmanaged(*SrcFn, void) = .{}, | ||
| 410 | dbg_line_fn_first: ?*SrcFn = null, | ||
| 411 | dbg_line_fn_last: ?*SrcFn = null, | ||
| 412 | |||
| 413 | /// A list of `TextBlock` whose corresponding .debug_info tags have surplus capacity. | ||
| 414 | /// This is the same concept as `text_block_free_list`; see those doc comments. | ||
| 415 | dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{}, | ||
| 416 | dbg_info_decl_first: ?*TextBlock = null, | ||
| 417 | dbg_info_decl_last: ?*TextBlock = null, | ||
| 418 | |||
| 419 | /// `alloc_num / alloc_den` is the factor of padding when allocating. | ||
| 420 | const alloc_num = 4; | ||
| 421 | const alloc_den = 3; | ||
| 422 | |||
| 423 | /// In order for a slice of bytes to be considered eligible to keep metadata pointing at | ||
| 424 | /// it as a possible place to put new symbols, it must have enough room for this many bytes | ||
| 425 | /// (plus extra for reserved capacity). | ||
| 426 | const minimum_text_block_size = 64; | ||
| 427 | const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den; | ||
| 428 | |||
| 429 | pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.hash, Type.eql, true); | ||
| 430 | |||
| 431 | const DbgInfoTypeReloc = struct { | ||
| 432 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | ||
| 433 | /// This is where the .debug_info tag for the type is. | ||
| 434 | off: u32, | ||
| 435 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). | ||
| 436 | /// List of DW.AT_type / DW.FORM_ref4 that points to the type. | ||
| 437 | relocs: std.ArrayListUnmanaged(u32), | ||
| 438 | }; | ||
| 439 | |||
| 440 | pub const TextBlock = struct { | ||
| 441 | /// Each decl always gets a local symbol with the fully qualified name. | ||
| 442 | /// The vaddr and size are found here directly. | ||
| 443 | /// The file offset is found by computing the vaddr offset from the section vaddr | ||
| 444 | /// the symbol references, and adding that to the file offset of the section. | ||
| 445 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | ||
| 446 | /// offset table entry. | ||
| 447 | local_sym_index: u32, | ||
| 448 | /// This field is undefined for symbols with size = 0. | ||
| 449 | offset_table_index: u32, | ||
| 450 | /// Points to the previous and next neighbors, based on the `text_offset`. | ||
| 451 | /// This can be used to find, for example, the capacity of this `TextBlock`. | ||
| 452 | prev: ?*TextBlock, | ||
| 453 | next: ?*TextBlock, | ||
| 454 | |||
| 455 | /// Previous/next linked list pointers. This value is `next ^ prev`. | ||
| 456 | /// This is the linked list node for this Decl's corresponding .debug_info tag. | ||
| 457 | dbg_info_prev: ?*TextBlock, | ||
| 458 | dbg_info_next: ?*TextBlock, | ||
| 459 | /// Offset into .debug_info pointing to the tag for this Decl. | ||
| 460 | dbg_info_off: u32, | ||
| 461 | /// Size of the .debug_info tag for this Decl, not including padding. | ||
| 462 | dbg_info_len: u32, | ||
| 463 | |||
| 464 | pub const empty = TextBlock{ | ||
| 465 | .local_sym_index = 0, | ||
| 466 | .offset_table_index = undefined, | ||
| 467 | .prev = null, | ||
| 468 | .next = null, | ||
| 469 | .dbg_info_prev = null, | ||
| 470 | .dbg_info_next = null, | ||
| 471 | .dbg_info_off = undefined, | ||
| 472 | .dbg_info_len = undefined, | ||
| 473 | }; | ||
| 474 | |||
| 475 | /// Returns how much room there is to grow in virtual address space. | ||
| 476 | /// File offset relocation happens transparently, so it is not included in | ||
| 477 | /// this calculation. | ||
| 478 | fn capacity(self: TextBlock, elf_file: Elf) u64 { | ||
| 479 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | ||
| 480 | if (self.next) |next| { | ||
| 481 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | ||
| 482 | return next_sym.st_value - self_sym.st_value; | ||
| 483 | } else { | ||
| 484 | // We are the last block. The capacity is limited only by virtual address space. | ||
| 485 | return std.math.maxInt(u32) - self_sym.st_value; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | fn freeListEligible(self: TextBlock, elf_file: Elf) bool { | ||
| 490 | // No need to keep a free list node for the last block. | ||
| 491 | const next = self.next orelse return false; | ||
| 492 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | ||
| 493 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | ||
| 494 | const cap = next_sym.st_value - self_sym.st_value; | ||
| 495 | const ideal_cap = self_sym.st_size * alloc_num / alloc_den; | ||
| 496 | if (cap <= ideal_cap) return false; | ||
| 497 | const surplus = cap - ideal_cap; | ||
| 498 | return surplus >= min_text_capacity; | ||
| 499 | } | ||
| 500 | }; | ||
| 501 | |||
| 502 | pub const Export = struct { | ||
| 503 | sym_index: ?u32 = null, | ||
| 504 | }; | ||
| 505 | |||
| 506 | pub const SrcFn = struct { | ||
| 507 | /// Offset from the beginning of the Debug Line Program header that contains this function. | ||
| 508 | off: u32, | ||
| 509 | /// Size of the line number program component belonging to this function, not | ||
| 510 | /// including padding. | ||
| 511 | len: u32, | ||
| 512 | |||
| 513 | /// Points to the previous and next neighbors, based on the offset from .debug_line. | ||
| 514 | /// This can be used to find, for example, the capacity of this `SrcFn`. | ||
| 515 | prev: ?*SrcFn, | ||
| 516 | next: ?*SrcFn, | ||
| 517 | |||
| 518 | pub const empty: SrcFn = .{ | ||
| 519 | .off = 0, | ||
| 520 | .len = 0, | ||
| 521 | .prev = null, | ||
| 522 | .next = null, | ||
| 523 | }; | ||
| 524 | }; | ||
| 525 | |||
| 526 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File { | ||
| 527 | assert(options.object_format == .elf); | ||
| 528 | |||
| 529 | const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = determineMode(options) }); | ||
| 530 | errdefer file.close(); | ||
| 531 | |||
| 532 | var elf_file = try allocator.create(Elf); | ||
| 533 | errdefer allocator.destroy(elf_file); | ||
| 534 | |||
| 535 | elf_file.* = openFile(allocator, file, options) catch |err| switch (err) { | ||
| 536 | error.IncrFailed => try createFile(allocator, file, options), | ||
| 537 | else => |e| return e, | ||
| 538 | }; | ||
| 539 | |||
| 540 | return &elf_file.base; | ||
| 541 | } | ||
| 542 | |||
| 543 | /// Returns error.IncrFailed if incremental update could not be performed. | ||
| 544 | fn openFile(allocator: *Allocator, file: fs.File, options: Options) !Elf { | ||
| 545 | switch (options.output_mode) { | ||
| 546 | .Exe => {}, | ||
| 547 | .Obj => {}, | ||
| 548 | .Lib => return error.IncrFailed, | ||
| 549 | } | ||
| 550 | var self: Elf = .{ | ||
| 551 | .base = .{ | ||
| 552 | .file = file, | ||
| 553 | .tag = .elf, | ||
| 554 | .options = options, | ||
| 555 | .allocator = allocator, | ||
| 556 | }, | ||
| 557 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 558 | 32 => .p32, | ||
| 559 | 64 => .p64, | ||
| 560 | else => return error.UnsupportedELFArchitecture, | ||
| 561 | }, | ||
| 562 | }; | ||
| 563 | errdefer self.deinit(); | ||
| 564 | |||
| 565 | // TODO implement reading the elf file | ||
| 566 | return error.IncrFailed; | ||
| 567 | //try self.populateMissingMetadata(); | ||
| 568 | //return self; | ||
| 569 | } | ||
| 570 | |||
| 571 | /// Truncates the existing file contents and overwrites the contents. | ||
| 572 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | ||
| 573 | fn createFile(allocator: *Allocator, file: fs.File, options: Options) !Elf { | ||
| 574 | switch (options.output_mode) { | ||
| 575 | .Exe => {}, | ||
| 576 | .Obj => {}, | ||
| 577 | .Lib => return error.TODOImplementWritingLibFiles, | ||
| 578 | } | ||
| 579 | var self: Elf = .{ | ||
| 580 | .base = .{ | ||
| 581 | .tag = .elf, | ||
| 582 | .options = options, | ||
| 583 | .allocator = allocator, | ||
| 584 | .file = file, | ||
| 585 | }, | ||
| 586 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 587 | 32 => .p32, | ||
| 588 | 64 => .p64, | ||
| 589 | else => return error.UnsupportedELFArchitecture, | ||
| 590 | }, | ||
| 591 | .shdr_table_dirty = true, | ||
| 592 | }; | ||
| 593 | errdefer self.deinit(); | ||
| 594 | |||
| 595 | // Index 0 is always a null symbol. | ||
| 596 | try self.local_symbols.append(allocator, .{ | ||
| 597 | .st_name = 0, | ||
| 598 | .st_info = 0, | ||
| 599 | .st_other = 0, | ||
| 600 | .st_shndx = 0, | ||
| 601 | .st_value = 0, | ||
| 602 | .st_size = 0, | ||
| 603 | }); | ||
| 604 | |||
| 605 | // There must always be a null section in index 0 | ||
| 606 | try self.sections.append(allocator, .{ | ||
| 607 | .sh_name = 0, | ||
| 608 | .sh_type = elf.SHT_NULL, | ||
| 609 | .sh_flags = 0, | ||
| 610 | .sh_addr = 0, | ||
| 611 | .sh_offset = 0, | ||
| 612 | .sh_size = 0, | ||
| 613 | .sh_link = 0, | ||
| 614 | .sh_info = 0, | ||
| 615 | .sh_addralign = 0, | ||
| 616 | .sh_entsize = 0, | ||
| 617 | }); | ||
| 618 | |||
| 619 | try self.populateMissingMetadata(); | ||
| 620 | |||
| 621 | return self; | ||
| 622 | } | ||
| 623 | |||
| 624 | pub fn deinit(self: *Elf) void { | ||
| 625 | self.sections.deinit(self.base.allocator); | ||
| 626 | self.program_headers.deinit(self.base.allocator); | ||
| 627 | self.shstrtab.deinit(self.base.allocator); | ||
| 628 | self.debug_strtab.deinit(self.base.allocator); | ||
| 629 | self.local_symbols.deinit(self.base.allocator); | ||
| 630 | self.global_symbols.deinit(self.base.allocator); | ||
| 631 | self.global_symbol_free_list.deinit(self.base.allocator); | ||
| 632 | self.local_symbol_free_list.deinit(self.base.allocator); | ||
| 633 | self.offset_table_free_list.deinit(self.base.allocator); | ||
| 634 | self.text_block_free_list.deinit(self.base.allocator); | ||
| 635 | self.dbg_line_fn_free_list.deinit(self.base.allocator); | ||
| 636 | self.dbg_info_decl_free_list.deinit(self.base.allocator); | ||
| 637 | self.offset_table.deinit(self.base.allocator); | ||
| 638 | } | ||
| 639 | |||
| 640 | fn getDebugLineProgramOff(self: Elf) u32 { | ||
| 641 | return self.dbg_line_fn_first.?.off; | ||
| 642 | } | ||
| 643 | |||
| 644 | fn getDebugLineProgramEnd(self: Elf) u32 { | ||
| 645 | return self.dbg_line_fn_last.?.off + self.dbg_line_fn_last.?.len; | ||
| 646 | } | ||
| 647 | |||
| 648 | /// Returns end pos of collision, if any. | ||
| 649 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { | ||
| 650 | const small_ptr = self.base.options.target.cpu.arch.ptrBitWidth() == 32; | ||
| 651 | const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); | ||
| 652 | if (start < ehdr_size) | ||
| 653 | return ehdr_size; | ||
| 654 | |||
| 655 | const end = start + satMul(size, alloc_num) / alloc_den; | ||
| 656 | |||
| 657 | if (self.shdr_table_offset) |off| { | ||
| 658 | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); | ||
| 659 | const tight_size = self.sections.items.len * shdr_size; | ||
| 660 | const increased_size = satMul(tight_size, alloc_num) / alloc_den; | ||
| 661 | const test_end = off + increased_size; | ||
| 662 | if (end > off and start < test_end) { | ||
| 663 | return test_end; | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | if (self.phdr_table_offset) |off| { | ||
| 668 | const phdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Phdr) else @sizeOf(elf.Elf64_Phdr); | ||
| 669 | const tight_size = self.sections.items.len * phdr_size; | ||
| 670 | const increased_size = satMul(tight_size, alloc_num) / alloc_den; | ||
| 671 | const test_end = off + increased_size; | ||
| 672 | if (end > off and start < test_end) { | ||
| 673 | return test_end; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | for (self.sections.items) |section| { | ||
| 678 | const increased_size = satMul(section.sh_size, alloc_num) / alloc_den; | ||
| 679 | const test_end = section.sh_offset + increased_size; | ||
| 680 | if (end > section.sh_offset and start < test_end) { | ||
| 681 | return test_end; | ||
| 682 | } | ||
| 683 | } | ||
| 684 | for (self.program_headers.items) |program_header| { | ||
| 685 | const increased_size = satMul(program_header.p_filesz, alloc_num) / alloc_den; | ||
| 686 | const test_end = program_header.p_offset + increased_size; | ||
| 687 | if (end > program_header.p_offset and start < test_end) { | ||
| 688 | return test_end; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | return null; | ||
| 692 | } | ||
| 693 | |||
| 694 | fn allocatedSize(self: *Elf, start: u64) u64 { | ||
| 695 | if (start == 0) | ||
| 696 | return 0; | ||
| 697 | var min_pos: u64 = std.math.maxInt(u64); | ||
| 698 | if (self.shdr_table_offset) |off| { | ||
| 699 | if (off > start and off < min_pos) min_pos = off; | ||
| 700 | } | ||
| 701 | if (self.phdr_table_offset) |off| { | ||
| 702 | if (off > start and off < min_pos) min_pos = off; | ||
| 703 | } | ||
| 704 | for (self.sections.items) |section| { | ||
| 705 | if (section.sh_offset <= start) continue; | ||
| 706 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; | ||
| 707 | } | ||
| 708 | for (self.program_headers.items) |program_header| { | ||
| 709 | if (program_header.p_offset <= start) continue; | ||
| 710 | if (program_header.p_offset < min_pos) min_pos = program_header.p_offset; | ||
| 711 | } | ||
| 712 | return min_pos - start; | ||
| 713 | } | ||
| 714 | |||
| 715 | fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u16) u64 { | ||
| 716 | var start: u64 = 0; | ||
| 717 | while (self.detectAllocCollision(start, object_size)) |item_end| { | ||
| 718 | start = mem.alignForwardGeneric(u64, item_end, min_alignment); | ||
| 719 | } | ||
| 720 | return start; | ||
| 721 | } | ||
| 722 | |||
| 723 | /// TODO Improve this to use a table. | ||
| 724 | fn makeString(self: *Elf, bytes: []const u8) !u32 { | ||
| 725 | try self.shstrtab.ensureCapacity(self.base.allocator, self.shstrtab.items.len + bytes.len + 1); | ||
| 726 | const result = self.shstrtab.items.len; | ||
| 727 | self.shstrtab.appendSliceAssumeCapacity(bytes); | ||
| 728 | self.shstrtab.appendAssumeCapacity(0); | ||
| 729 | return @intCast(u32, result); | ||
| 730 | } | ||
| 731 | |||
| 732 | /// TODO Improve this to use a table. | ||
| 733 | fn makeDebugString(self: *Elf, bytes: []const u8) !u32 { | ||
| 734 | try self.debug_strtab.ensureCapacity(self.base.allocator, self.debug_strtab.items.len + bytes.len + 1); | ||
| 735 | const result = self.debug_strtab.items.len; | ||
| 736 | self.debug_strtab.appendSliceAssumeCapacity(bytes); | ||
| 737 | self.debug_strtab.appendAssumeCapacity(0); | ||
| 738 | return @intCast(u32, result); | ||
| 739 | } | ||
| 740 | |||
| 741 | fn getString(self: *Elf, str_off: u32) []const u8 { | ||
| 742 | assert(str_off < self.shstrtab.items.len); | ||
| 743 | return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off)); | ||
| 744 | } | ||
| 745 | |||
| 746 | fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { | ||
| 747 | const existing_name = self.getString(old_str_off); | ||
| 748 | if (mem.eql(u8, existing_name, new_name)) { | ||
| 749 | return old_str_off; | ||
| 750 | } | ||
| 751 | return self.makeString(new_name); | ||
| 752 | } | ||
| 753 | |||
| 754 | pub fn populateMissingMetadata(self: *Elf) !void { | ||
| 755 | const small_ptr = switch (self.ptr_width) { | ||
| 756 | .p32 => true, | ||
| 757 | .p64 => false, | ||
| 758 | }; | ||
| 759 | const ptr_size: u8 = self.ptrWidthBytes(); | ||
| 760 | if (self.phdr_load_re_index == null) { | ||
| 761 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); | ||
| 762 | const file_size = self.base.options.program_code_size_hint; | ||
| 763 | const p_align = 0x1000; | ||
| 764 | const off = self.findFreeSpace(file_size, p_align); | ||
| 765 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 766 | try self.program_headers.append(self.base.allocator, .{ | ||
| 767 | .p_type = elf.PT_LOAD, | ||
| 768 | .p_offset = off, | ||
| 769 | .p_filesz = file_size, | ||
| 770 | .p_vaddr = default_entry_addr, | ||
| 771 | .p_paddr = default_entry_addr, | ||
| 772 | .p_memsz = file_size, | ||
| 773 | .p_align = p_align, | ||
| 774 | .p_flags = elf.PF_X | elf.PF_R, | ||
| 775 | }); | ||
| 776 | self.entry_addr = null; | ||
| 777 | self.phdr_table_dirty = true; | ||
| 778 | } | ||
| 779 | if (self.phdr_got_index == null) { | ||
| 780 | self.phdr_got_index = @intCast(u16, self.program_headers.items.len); | ||
| 781 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; | ||
| 782 | // We really only need ptr alignment but since we are using PROGBITS, linux requires | ||
| 783 | // page align. | ||
| 784 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | ||
| 785 | const off = self.findFreeSpace(file_size, p_align); | ||
| 786 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 787 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. | ||
| 788 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something | ||
| 789 | // else in virtual memory. | ||
| 790 | const default_got_addr = if (ptr_size == 2) @as(u32, 0x8000) else 0x4000000; | ||
| 791 | try self.program_headers.append(self.base.allocator, .{ | ||
| 792 | .p_type = elf.PT_LOAD, | ||
| 793 | .p_offset = off, | ||
| 794 | .p_filesz = file_size, | ||
| 795 | .p_vaddr = default_got_addr, | ||
| 796 | .p_paddr = default_got_addr, | ||
| 797 | .p_memsz = file_size, | ||
| 798 | .p_align = p_align, | ||
| 799 | .p_flags = elf.PF_R, | ||
| 800 | }); | ||
| 801 | self.phdr_table_dirty = true; | ||
| 802 | } | ||
| 803 | if (self.shstrtab_index == null) { | ||
| 804 | self.shstrtab_index = @intCast(u16, self.sections.items.len); | ||
| 805 | assert(self.shstrtab.items.len == 0); | ||
| 806 | try self.shstrtab.append(self.base.allocator, 0); // need a 0 at position 0 | ||
| 807 | const off = self.findFreeSpace(self.shstrtab.items.len, 1); | ||
| 808 | log.debug("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len }); | ||
| 809 | try self.sections.append(self.base.allocator, .{ | ||
| 810 | .sh_name = try self.makeString(".shstrtab"), | ||
| 811 | .sh_type = elf.SHT_STRTAB, | ||
| 812 | .sh_flags = 0, | ||
| 813 | .sh_addr = 0, | ||
| 814 | .sh_offset = off, | ||
| 815 | .sh_size = self.shstrtab.items.len, | ||
| 816 | .sh_link = 0, | ||
| 817 | .sh_info = 0, | ||
| 818 | .sh_addralign = 1, | ||
| 819 | .sh_entsize = 0, | ||
| 820 | }); | ||
| 821 | self.shstrtab_dirty = true; | ||
| 822 | self.shdr_table_dirty = true; | ||
| 823 | } | ||
| 824 | if (self.text_section_index == null) { | ||
| 825 | self.text_section_index = @intCast(u16, self.sections.items.len); | ||
| 826 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 827 | |||
| 828 | try self.sections.append(self.base.allocator, .{ | ||
| 829 | .sh_name = try self.makeString(".text"), | ||
| 830 | .sh_type = elf.SHT_PROGBITS, | ||
| 831 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 832 | .sh_addr = phdr.p_vaddr, | ||
| 833 | .sh_offset = phdr.p_offset, | ||
| 834 | .sh_size = phdr.p_filesz, | ||
| 835 | .sh_link = 0, | ||
| 836 | .sh_info = 0, | ||
| 837 | .sh_addralign = phdr.p_align, | ||
| 838 | .sh_entsize = 0, | ||
| 839 | }); | ||
| 840 | self.shdr_table_dirty = true; | ||
| 841 | } | ||
| 842 | if (self.got_section_index == null) { | ||
| 843 | self.got_section_index = @intCast(u16, self.sections.items.len); | ||
| 844 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | ||
| 845 | |||
| 846 | try self.sections.append(self.base.allocator, .{ | ||
| 847 | .sh_name = try self.makeString(".got"), | ||
| 848 | .sh_type = elf.SHT_PROGBITS, | ||
| 849 | .sh_flags = elf.SHF_ALLOC, | ||
| 850 | .sh_addr = phdr.p_vaddr, | ||
| 851 | .sh_offset = phdr.p_offset, | ||
| 852 | .sh_size = phdr.p_filesz, | ||
| 853 | .sh_link = 0, | ||
| 854 | .sh_info = 0, | ||
| 855 | .sh_addralign = phdr.p_align, | ||
| 856 | .sh_entsize = 0, | ||
| 857 | }); | ||
| 858 | self.shdr_table_dirty = true; | ||
| 859 | } | ||
| 860 | if (self.symtab_section_index == null) { | ||
| 861 | self.symtab_section_index = @intCast(u16, self.sections.items.len); | ||
| 862 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); | ||
| 863 | const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym); | ||
| 864 | const file_size = self.base.options.symbol_count_hint * each_size; | ||
| 865 | const off = self.findFreeSpace(file_size, min_align); | ||
| 866 | log.debug("found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 867 | |||
| 868 | try self.sections.append(self.base.allocator, .{ | ||
| 869 | .sh_name = try self.makeString(".symtab"), | ||
| 870 | .sh_type = elf.SHT_SYMTAB, | ||
| 871 | .sh_flags = 0, | ||
| 872 | .sh_addr = 0, | ||
| 873 | .sh_offset = off, | ||
| 874 | .sh_size = file_size, | ||
| 875 | // The section header index of the associated string table. | ||
| 876 | .sh_link = self.shstrtab_index.?, | ||
| 877 | .sh_info = @intCast(u32, self.local_symbols.items.len), | ||
| 878 | .sh_addralign = min_align, | ||
| 879 | .sh_entsize = each_size, | ||
| 880 | }); | ||
| 881 | self.shdr_table_dirty = true; | ||
| 882 | try self.writeSymbol(0); | ||
| 883 | } | ||
| 884 | if (self.debug_str_section_index == null) { | ||
| 885 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); | ||
| 886 | assert(self.debug_strtab.items.len == 0); | ||
| 887 | try self.sections.append(self.base.allocator, .{ | ||
| 888 | .sh_name = try self.makeString(".debug_str"), | ||
| 889 | .sh_type = elf.SHT_PROGBITS, | ||
| 890 | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 891 | .sh_addr = 0, | ||
| 892 | .sh_offset = 0, | ||
| 893 | .sh_size = self.debug_strtab.items.len, | ||
| 894 | .sh_link = 0, | ||
| 895 | .sh_info = 0, | ||
| 896 | .sh_addralign = 1, | ||
| 897 | .sh_entsize = 1, | ||
| 898 | }); | ||
| 899 | self.debug_strtab_dirty = true; | ||
| 900 | self.shdr_table_dirty = true; | ||
| 901 | } | ||
| 902 | if (self.debug_info_section_index == null) { | ||
| 903 | self.debug_info_section_index = @intCast(u16, self.sections.items.len); | ||
| 904 | |||
| 905 | const file_size_hint = 200; | ||
| 906 | const p_align = 1; | ||
| 907 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 908 | log.debug("found .debug_info free space 0x{x} to 0x{x}\n", .{ | ||
| 909 | off, | ||
| 910 | off + file_size_hint, | ||
| 911 | }); | ||
| 912 | try self.sections.append(self.base.allocator, .{ | ||
| 913 | .sh_name = try self.makeString(".debug_info"), | ||
| 914 | .sh_type = elf.SHT_PROGBITS, | ||
| 915 | .sh_flags = 0, | ||
| 916 | .sh_addr = 0, | ||
| 917 | .sh_offset = off, | ||
| 918 | .sh_size = file_size_hint, | ||
| 919 | .sh_link = 0, | ||
| 920 | .sh_info = 0, | ||
| 921 | .sh_addralign = p_align, | ||
| 922 | .sh_entsize = 0, | ||
| 923 | }); | ||
| 924 | self.shdr_table_dirty = true; | ||
| 925 | self.debug_info_header_dirty = true; | ||
| 926 | } | ||
| 927 | if (self.debug_abbrev_section_index == null) { | ||
| 928 | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); | ||
| 929 | |||
| 930 | const file_size_hint = 128; | ||
| 931 | const p_align = 1; | ||
| 932 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 933 | log.debug("found .debug_abbrev free space 0x{x} to 0x{x}\n", .{ | ||
| 934 | off, | ||
| 935 | off + file_size_hint, | ||
| 936 | }); | ||
| 937 | try self.sections.append(self.base.allocator, .{ | ||
| 938 | .sh_name = try self.makeString(".debug_abbrev"), | ||
| 939 | .sh_type = elf.SHT_PROGBITS, | ||
| 940 | .sh_flags = 0, | ||
| 941 | .sh_addr = 0, | ||
| 942 | .sh_offset = off, | ||
| 943 | .sh_size = file_size_hint, | ||
| 944 | .sh_link = 0, | ||
| 945 | .sh_info = 0, | ||
| 946 | .sh_addralign = p_align, | ||
| 947 | .sh_entsize = 0, | ||
| 948 | }); | ||
| 949 | self.shdr_table_dirty = true; | ||
| 950 | self.debug_abbrev_section_dirty = true; | ||
| 951 | } | ||
| 952 | if (self.debug_aranges_section_index == null) { | ||
| 953 | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); | ||
| 954 | |||
| 955 | const file_size_hint = 160; | ||
| 956 | const p_align = 16; | ||
| 957 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 958 | log.debug("found .debug_aranges free space 0x{x} to 0x{x}\n", .{ | ||
| 959 | off, | ||
| 960 | off + file_size_hint, | ||
| 961 | }); | ||
| 962 | try self.sections.append(self.base.allocator, .{ | ||
| 963 | .sh_name = try self.makeString(".debug_aranges"), | ||
| 964 | .sh_type = elf.SHT_PROGBITS, | ||
| 965 | .sh_flags = 0, | ||
| 966 | .sh_addr = 0, | ||
| 967 | .sh_offset = off, | ||
| 968 | .sh_size = file_size_hint, | ||
| 969 | .sh_link = 0, | ||
| 970 | .sh_info = 0, | ||
| 971 | .sh_addralign = p_align, | ||
| 972 | .sh_entsize = 0, | ||
| 973 | }); | ||
| 974 | self.shdr_table_dirty = true; | ||
| 975 | self.debug_aranges_section_dirty = true; | ||
| 976 | } | ||
| 977 | if (self.debug_line_section_index == null) { | ||
| 978 | self.debug_line_section_index = @intCast(u16, self.sections.items.len); | ||
| 979 | |||
| 980 | const file_size_hint = 250; | ||
| 981 | const p_align = 1; | ||
| 982 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 983 | log.debug("found .debug_line free space 0x{x} to 0x{x}\n", .{ | ||
| 984 | off, | ||
| 985 | off + file_size_hint, | ||
| 986 | }); | ||
| 987 | try self.sections.append(self.base.allocator, .{ | ||
| 988 | .sh_name = try self.makeString(".debug_line"), | ||
| 989 | .sh_type = elf.SHT_PROGBITS, | ||
| 990 | .sh_flags = 0, | ||
| 991 | .sh_addr = 0, | ||
| 992 | .sh_offset = off, | ||
| 993 | .sh_size = file_size_hint, | ||
| 994 | .sh_link = 0, | ||
| 995 | .sh_info = 0, | ||
| 996 | .sh_addralign = p_align, | ||
| 997 | .sh_entsize = 0, | ||
| 998 | }); | ||
| 999 | self.shdr_table_dirty = true; | ||
| 1000 | self.debug_line_header_dirty = true; | ||
| 1001 | } | ||
| 1002 | const shsize: u64 = switch (self.ptr_width) { | ||
| 1003 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 1004 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 1005 | }; | ||
| 1006 | const shalign: u16 = switch (self.ptr_width) { | ||
| 1007 | .p32 => @alignOf(elf.Elf32_Shdr), | ||
| 1008 | .p64 => @alignOf(elf.Elf64_Shdr), | ||
| 1009 | }; | ||
| 1010 | if (self.shdr_table_offset == null) { | ||
| 1011 | self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign); | ||
| 1012 | self.shdr_table_dirty = true; | ||
| 1013 | } | ||
| 1014 | const phsize: u64 = switch (self.ptr_width) { | ||
| 1015 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 1016 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 1017 | }; | ||
| 1018 | const phalign: u16 = switch (self.ptr_width) { | ||
| 1019 | .p32 => @alignOf(elf.Elf32_Phdr), | ||
| 1020 | .p64 => @alignOf(elf.Elf64_Phdr), | ||
| 1021 | }; | ||
| 1022 | if (self.phdr_table_offset == null) { | ||
| 1023 | self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign); | ||
| 1024 | self.phdr_table_dirty = true; | ||
| 1025 | } | ||
| 1026 | { | ||
| 1027 | // Iterate over symbols, populating free_list and last_text_block. | ||
| 1028 | if (self.local_symbols.items.len != 1) { | ||
| 1029 | @panic("TODO implement setting up free_list and last_text_block from existing ELF file"); | ||
| 1030 | } | ||
| 1031 | // We are starting with an empty file. The default values are correct, null and empty list. | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | pub const abbrev_compile_unit = 1; | ||
| 1036 | pub const abbrev_subprogram = 2; | ||
| 1037 | pub const abbrev_subprogram_retvoid = 3; | ||
| 1038 | pub const abbrev_base_type = 4; | ||
| 1039 | pub const abbrev_pad1 = 5; | ||
| 1040 | pub const abbrev_parameter = 6; | ||
| 1041 | |||
| 1042 | /// Commit pending changes and write headers. | ||
| 1043 | pub fn flush(self: *Elf, module: *Module) !void { | ||
| 1044 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 1045 | const foreign_endian = target_endian != std.Target.current.cpu.arch.endian(); | ||
| 1046 | const ptr_width_bytes: u8 = self.ptrWidthBytes(); | ||
| 1047 | const init_len_size: usize = switch (self.ptr_width) { | ||
| 1048 | .p32 => 4, | ||
| 1049 | .p64 => 12, | ||
| 1050 | }; | ||
| 1051 | |||
| 1052 | // Unfortunately these have to be buffered and done at the end because ELF does not allow | ||
| 1053 | // mixing local and global symbols within a symbol table. | ||
| 1054 | try self.writeAllGlobalSymbols(); | ||
| 1055 | |||
| 1056 | if (self.debug_abbrev_section_dirty) { | ||
| 1057 | const debug_abbrev_sect = &self.sections.items[self.debug_abbrev_section_index.?]; | ||
| 1058 | |||
| 1059 | // These are LEB encoded but since the values are all less than 127 | ||
| 1060 | // we can simply append these bytes. | ||
| 1061 | const abbrev_buf = [_]u8{ | ||
| 1062 | abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header | ||
| 1063 | DW.AT_stmt_list, DW.FORM_sec_offset, | ||
| 1064 | DW.AT_low_pc , DW.FORM_addr, | ||
| 1065 | DW.AT_high_pc , DW.FORM_addr, | ||
| 1066 | DW.AT_name , DW.FORM_strp, | ||
| 1067 | DW.AT_comp_dir , DW.FORM_strp, | ||
| 1068 | DW.AT_producer , DW.FORM_strp, | ||
| 1069 | DW.AT_language , DW.FORM_data2, | ||
| 1070 | 0, 0, // table sentinel | ||
| 1071 | |||
| 1072 | abbrev_subprogram, DW.TAG_subprogram, DW.CHILDREN_yes, // header | ||
| 1073 | DW.AT_low_pc , DW.FORM_addr, | ||
| 1074 | DW.AT_high_pc , DW.FORM_data4, | ||
| 1075 | DW.AT_type , DW.FORM_ref4, | ||
| 1076 | DW.AT_name , DW.FORM_string, | ||
| 1077 | 0, 0, // table sentinel | ||
| 1078 | |||
| 1079 | abbrev_subprogram_retvoid, DW.TAG_subprogram, DW.CHILDREN_yes, // header | ||
| 1080 | DW.AT_low_pc , DW.FORM_addr, | ||
| 1081 | DW.AT_high_pc , DW.FORM_data4, | ||
| 1082 | DW.AT_name , DW.FORM_string, | ||
| 1083 | 0, 0, // table sentinel | ||
| 1084 | |||
| 1085 | abbrev_base_type, DW.TAG_base_type, DW.CHILDREN_no, // header | ||
| 1086 | DW.AT_encoding , DW.FORM_data1, | ||
| 1087 | DW.AT_byte_size, DW.FORM_data1, | ||
| 1088 | DW.AT_name , DW.FORM_string, | ||
| 1089 | 0, 0, // table sentinel | ||
| 1090 | |||
| 1091 | abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header | ||
| 1092 | 0, 0, // table sentinel | ||
| 1093 | |||
| 1094 | abbrev_parameter, DW.TAG_formal_parameter, DW.CHILDREN_no, // header | ||
| 1095 | DW.AT_location , DW.FORM_exprloc, | ||
| 1096 | DW.AT_type , DW.FORM_ref4, | ||
| 1097 | DW.AT_name , DW.FORM_string, | ||
| 1098 | 0, 0, // table sentinel | ||
| 1099 | |||
| 1100 | 0, 0, 0, // section sentinel | ||
| 1101 | }; | ||
| 1102 | |||
| 1103 | const needed_size = abbrev_buf.len; | ||
| 1104 | const allocated_size = self.allocatedSize(debug_abbrev_sect.sh_offset); | ||
| 1105 | if (needed_size > allocated_size) { | ||
| 1106 | debug_abbrev_sect.sh_size = 0; // free the space | ||
| 1107 | debug_abbrev_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 1108 | } | ||
| 1109 | debug_abbrev_sect.sh_size = needed_size; | ||
| 1110 | log.debug(".debug_abbrev start=0x{x} end=0x{x}\n", .{ | ||
| 1111 | debug_abbrev_sect.sh_offset, | ||
| 1112 | debug_abbrev_sect.sh_offset + needed_size, | ||
| 1113 | }); | ||
| 1114 | |||
| 1115 | const abbrev_offset = 0; | ||
| 1116 | self.debug_abbrev_table_offset = abbrev_offset; | ||
| 1117 | try self.base.file.?.pwriteAll(&abbrev_buf, debug_abbrev_sect.sh_offset + abbrev_offset); | ||
| 1118 | if (!self.shdr_table_dirty) { | ||
| 1119 | // Then it won't get written with the others and we need to do it. | ||
| 1120 | try self.writeSectHeader(self.debug_abbrev_section_index.?); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | self.debug_abbrev_section_dirty = false; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (self.debug_info_header_dirty) debug_info: { | ||
| 1127 | // If this value is null it means there is an error in the module; | ||
| 1128 | // leave debug_info_header_dirty=true. | ||
| 1129 | const first_dbg_info_decl = self.dbg_info_decl_first orelse break :debug_info; | ||
| 1130 | const last_dbg_info_decl = self.dbg_info_decl_last.?; | ||
| 1131 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 1132 | |||
| 1133 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 1134 | defer di_buf.deinit(); | ||
| 1135 | |||
| 1136 | // We have a function to compute the upper bound size, because it's needed | ||
| 1137 | // for determining where to put the offset of the first `LinkBlock`. | ||
| 1138 | try di_buf.ensureCapacity(self.dbgInfoNeededHeaderBytes()); | ||
| 1139 | |||
| 1140 | // initial length - length of the .debug_info contribution for this compilation unit, | ||
| 1141 | // not including the initial length itself. | ||
| 1142 | // We have to come back and write it later after we know the size. | ||
| 1143 | const after_init_len = di_buf.items.len + init_len_size; | ||
| 1144 | // +1 for the final 0 that ends the compilation unit children. | ||
| 1145 | const dbg_info_end = last_dbg_info_decl.dbg_info_off + last_dbg_info_decl.dbg_info_len + 1; | ||
| 1146 | const init_len = dbg_info_end - after_init_len; | ||
| 1147 | switch (self.ptr_width) { | ||
| 1148 | .p32 => { | ||
| 1149 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len), target_endian); | ||
| 1150 | }, | ||
| 1151 | .p64 => { | ||
| 1152 | di_buf.appendNTimesAssumeCapacity(0xff, 4); | ||
| 1153 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian); | ||
| 1154 | }, | ||
| 1155 | } | ||
| 1156 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version | ||
| 1157 | const abbrev_offset = self.debug_abbrev_table_offset.?; | ||
| 1158 | switch (self.ptr_width) { | ||
| 1159 | .p32 => { | ||
| 1160 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, abbrev_offset), target_endian); | ||
| 1161 | di_buf.appendAssumeCapacity(4); // address size | ||
| 1162 | }, | ||
| 1163 | .p64 => { | ||
| 1164 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), abbrev_offset, target_endian); | ||
| 1165 | di_buf.appendAssumeCapacity(8); // address size | ||
| 1166 | }, | ||
| 1167 | } | ||
| 1168 | // Write the form for the compile unit, which must match the abbrev table above. | ||
| 1169 | const name_strp = try self.makeDebugString(self.base.options.root_pkg.root_src_path); | ||
| 1170 | const comp_dir_strp = try self.makeDebugString(self.base.options.root_pkg.root_src_dir_path); | ||
| 1171 | const producer_strp = try self.makeDebugString(producer_string); | ||
| 1172 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 1173 | // identical to the main program header virtual address and memory size. | ||
| 1174 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1175 | const low_pc = text_phdr.p_vaddr; | ||
| 1176 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; | ||
| 1177 | |||
| 1178 | di_buf.appendAssumeCapacity(abbrev_compile_unit); | ||
| 1179 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT_stmt_list, DW.FORM_sec_offset | ||
| 1180 | self.writeDwarfAddrAssumeCapacity(&di_buf, low_pc); | ||
| 1181 | self.writeDwarfAddrAssumeCapacity(&di_buf, high_pc); | ||
| 1182 | self.writeDwarfAddrAssumeCapacity(&di_buf, name_strp); | ||
| 1183 | self.writeDwarfAddrAssumeCapacity(&di_buf, comp_dir_strp); | ||
| 1184 | self.writeDwarfAddrAssumeCapacity(&di_buf, producer_strp); | ||
| 1185 | // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: | ||
| 1186 | // http://dwarfstd.org/ShowIssue.php?issue=171115.1 | ||
| 1187 | // Until then we say it is C99. | ||
| 1188 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99, target_endian); | ||
| 1189 | |||
| 1190 | if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { | ||
| 1191 | // Move the first N decls to the end to make more padding for the header. | ||
| 1192 | @panic("TODO: handle .debug_info header exceeding its padding"); | ||
| 1193 | } | ||
| 1194 | const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len; | ||
| 1195 | try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, false, debug_info_sect.sh_offset); | ||
| 1196 | self.debug_info_header_dirty = false; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | if (self.debug_aranges_section_dirty) { | ||
| 1200 | const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?]; | ||
| 1201 | |||
| 1202 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 1203 | defer di_buf.deinit(); | ||
| 1204 | |||
| 1205 | // Enough for all the data without resizing. When support for more compilation units | ||
| 1206 | // is added, the size of this section will become more variable. | ||
| 1207 | try di_buf.ensureCapacity(100); | ||
| 1208 | |||
| 1209 | // initial length - length of the .debug_aranges contribution for this compilation unit, | ||
| 1210 | // not including the initial length itself. | ||
| 1211 | // We have to come back and write it later after we know the size. | ||
| 1212 | const init_len_index = di_buf.items.len; | ||
| 1213 | di_buf.items.len += init_len_size; | ||
| 1214 | const after_init_len = di_buf.items.len; | ||
| 1215 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version | ||
| 1216 | // When more than one compilation unit is supported, this will be the offset to it. | ||
| 1217 | // For now it is always at offset 0 in .debug_info. | ||
| 1218 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // .debug_info offset | ||
| 1219 | di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size | ||
| 1220 | di_buf.appendAssumeCapacity(0); // segment_selector_size | ||
| 1221 | |||
| 1222 | const end_header_offset = di_buf.items.len; | ||
| 1223 | const begin_entries_offset = mem.alignForward(end_header_offset, ptr_width_bytes * 2); | ||
| 1224 | di_buf.appendNTimesAssumeCapacity(0, begin_entries_offset - end_header_offset); | ||
| 1225 | |||
| 1226 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 1227 | // identical to the main program header virtual address and memory size. | ||
| 1228 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1229 | self.writeDwarfAddrAssumeCapacity(&di_buf, text_phdr.p_vaddr); | ||
| 1230 | self.writeDwarfAddrAssumeCapacity(&di_buf, text_phdr.p_memsz); | ||
| 1231 | |||
| 1232 | // Sentinel. | ||
| 1233 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); | ||
| 1234 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); | ||
| 1235 | |||
| 1236 | // Go back and populate the initial length. | ||
| 1237 | const init_len = di_buf.items.len - after_init_len; | ||
| 1238 | switch (self.ptr_width) { | ||
| 1239 | .p32 => { | ||
| 1240 | mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @intCast(u32, init_len), target_endian); | ||
| 1241 | }, | ||
| 1242 | .p64 => { | ||
| 1243 | // initial length - length of the .debug_aranges contribution for this compilation unit, | ||
| 1244 | // not including the initial length itself. | ||
| 1245 | di_buf.items[init_len_index..][0..4].* = [_]u8{ 0xff, 0xff, 0xff, 0xff }; | ||
| 1246 | mem.writeInt(u64, di_buf.items[init_len_index + 4..][0..8], init_len, target_endian); | ||
| 1247 | }, | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | const needed_size = di_buf.items.len; | ||
| 1251 | const allocated_size = self.allocatedSize(debug_aranges_sect.sh_offset); | ||
| 1252 | if (needed_size > allocated_size) { | ||
| 1253 | debug_aranges_sect.sh_size = 0; // free the space | ||
| 1254 | debug_aranges_sect.sh_offset = self.findFreeSpace(needed_size, 16); | ||
| 1255 | } | ||
| 1256 | debug_aranges_sect.sh_size = needed_size; | ||
| 1257 | log.debug(".debug_aranges start=0x{x} end=0x{x}\n", .{ | ||
| 1258 | debug_aranges_sect.sh_offset, | ||
| 1259 | debug_aranges_sect.sh_offset + needed_size, | ||
| 1260 | }); | ||
| 1261 | |||
| 1262 | try self.base.file.?.pwriteAll(di_buf.items, debug_aranges_sect.sh_offset); | ||
| 1263 | if (!self.shdr_table_dirty) { | ||
| 1264 | // Then it won't get written with the others and we need to do it. | ||
| 1265 | try self.writeSectHeader(self.debug_aranges_section_index.?); | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | self.debug_aranges_section_dirty = false; | ||
| 1269 | } | ||
| 1270 | if (self.debug_line_header_dirty) debug_line: { | ||
| 1271 | if (self.dbg_line_fn_first == null) { | ||
| 1272 | break :debug_line; // Error in module; leave debug_line_header_dirty=true. | ||
| 1273 | } | ||
| 1274 | const dbg_line_prg_off = self.getDebugLineProgramOff(); | ||
| 1275 | const dbg_line_prg_end = self.getDebugLineProgramEnd(); | ||
| 1276 | assert(dbg_line_prg_end != 0); | ||
| 1277 | |||
| 1278 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | ||
| 1279 | |||
| 1280 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 1281 | defer di_buf.deinit(); | ||
| 1282 | |||
| 1283 | // The size of this header is variable, depending on the number of directories, | ||
| 1284 | // files, and padding. We have a function to compute the upper bound size, however, | ||
| 1285 | // because it's needed for determining where to put the offset of the first `SrcFn`. | ||
| 1286 | try di_buf.ensureCapacity(self.dbgLineNeededHeaderBytes()); | ||
| 1287 | |||
| 1288 | // initial length - length of the .debug_line contribution for this compilation unit, | ||
| 1289 | // not including the initial length itself. | ||
| 1290 | const after_init_len = di_buf.items.len + init_len_size; | ||
| 1291 | const init_len = dbg_line_prg_end - after_init_len; | ||
| 1292 | switch (self.ptr_width) { | ||
| 1293 | .p32 => { | ||
| 1294 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len), target_endian); | ||
| 1295 | }, | ||
| 1296 | .p64 => { | ||
| 1297 | di_buf.appendNTimesAssumeCapacity(0xff, 4); | ||
| 1298 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian); | ||
| 1299 | }, | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version | ||
| 1303 | |||
| 1304 | // Empirically, debug info consumers do not respect this field, or otherwise | ||
| 1305 | // consider it to be an error when it does not point exactly to the end of the header. | ||
| 1306 | // Therefore we rely on the NOP jump at the beginning of the Line Number Program for | ||
| 1307 | // padding rather than this field. | ||
| 1308 | const before_header_len = di_buf.items.len; | ||
| 1309 | di_buf.items.len += ptr_width_bytes; // We will come back and write this. | ||
| 1310 | const after_header_len = di_buf.items.len; | ||
| 1311 | |||
| 1312 | const opcode_base = DW.LNS_set_isa + 1; | ||
| 1313 | di_buf.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1314 | 1, // minimum_instruction_length | ||
| 1315 | 1, // maximum_operations_per_instruction | ||
| 1316 | 1, // default_is_stmt | ||
| 1317 | 1, // line_base (signed) | ||
| 1318 | 1, // line_range | ||
| 1319 | opcode_base, | ||
| 1320 | |||
| 1321 | // Standard opcode lengths. The number of items here is based on `opcode_base`. | ||
| 1322 | // The value is the number of LEB128 operands the instruction takes. | ||
| 1323 | 0, // `DW.LNS_copy` | ||
| 1324 | 1, // `DW.LNS_advance_pc` | ||
| 1325 | 1, // `DW.LNS_advance_line` | ||
| 1326 | 1, // `DW.LNS_set_file` | ||
| 1327 | 1, // `DW.LNS_set_column` | ||
| 1328 | 0, // `DW.LNS_negate_stmt` | ||
| 1329 | 0, // `DW.LNS_set_basic_block` | ||
| 1330 | 0, // `DW.LNS_const_add_pc` | ||
| 1331 | 1, // `DW.LNS_fixed_advance_pc` | ||
| 1332 | 0, // `DW.LNS_set_prologue_end` | ||
| 1333 | 0, // `DW.LNS_set_epilogue_begin` | ||
| 1334 | 1, // `DW.LNS_set_isa` | ||
| 1335 | |||
| 1336 | 0, // include_directories (none except the compilation unit cwd) | ||
| 1337 | }); | ||
| 1338 | // file_names[0] | ||
| 1339 | di_buf.appendSliceAssumeCapacity(self.base.options.root_pkg.root_src_path); // relative path name | ||
| 1340 | di_buf.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1341 | 0, // null byte for the relative path name | ||
| 1342 | 0, // directory_index | ||
| 1343 | 0, // mtime (TODO supply this) | ||
| 1344 | 0, // file size bytes (TODO supply this) | ||
| 1345 | 0, // file_names sentinel | ||
| 1346 | }); | ||
| 1347 | |||
| 1348 | const header_len = di_buf.items.len - after_header_len; | ||
| 1349 | switch (self.ptr_width) { | ||
| 1350 | .p32 => { | ||
| 1351 | mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @intCast(u32, header_len), target_endian); | ||
| 1352 | }, | ||
| 1353 | .p64 => { | ||
| 1354 | mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian); | ||
| 1355 | }, | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | // We use NOPs because consumers empirically do not respect the header length field. | ||
| 1359 | if (di_buf.items.len > dbg_line_prg_off) { | ||
| 1360 | // Move the first N files to the end to make more padding for the header. | ||
| 1361 | @panic("TODO: handle .debug_line header exceeding its padding"); | ||
| 1362 | } | ||
| 1363 | const jmp_amt = dbg_line_prg_off - di_buf.items.len; | ||
| 1364 | try self.pwriteDbgLineNops(0, di_buf.items, jmp_amt, debug_line_sect.sh_offset); | ||
| 1365 | self.debug_line_header_dirty = false; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | if (self.phdr_table_dirty) { | ||
| 1369 | const phsize: u64 = switch (self.ptr_width) { | ||
| 1370 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 1371 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 1372 | }; | ||
| 1373 | const phalign: u16 = switch (self.ptr_width) { | ||
| 1374 | .p32 => @alignOf(elf.Elf32_Phdr), | ||
| 1375 | .p64 => @alignOf(elf.Elf64_Phdr), | ||
| 1376 | }; | ||
| 1377 | const allocated_size = self.allocatedSize(self.phdr_table_offset.?); | ||
| 1378 | const needed_size = self.program_headers.items.len * phsize; | ||
| 1379 | |||
| 1380 | if (needed_size > allocated_size) { | ||
| 1381 | self.phdr_table_offset = null; // free the space | ||
| 1382 | self.phdr_table_offset = self.findFreeSpace(needed_size, phalign); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | switch (self.ptr_width) { | ||
| 1386 | .p32 => { | ||
| 1387 | const buf = try self.base.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len); | ||
| 1388 | defer self.base.allocator.free(buf); | ||
| 1389 | |||
| 1390 | for (buf) |*phdr, i| { | ||
| 1391 | phdr.* = progHeaderTo32(self.program_headers.items[i]); | ||
| 1392 | if (foreign_endian) { | ||
| 1393 | bswapAllFields(elf.Elf32_Phdr, phdr); | ||
| 1394 | } | ||
| 1395 | } | ||
| 1396 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | ||
| 1397 | }, | ||
| 1398 | .p64 => { | ||
| 1399 | const buf = try self.base.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); | ||
| 1400 | defer self.base.allocator.free(buf); | ||
| 1401 | |||
| 1402 | for (buf) |*phdr, i| { | ||
| 1403 | phdr.* = self.program_headers.items[i]; | ||
| 1404 | if (foreign_endian) { | ||
| 1405 | bswapAllFields(elf.Elf64_Phdr, phdr); | ||
| 1406 | } | ||
| 1407 | } | ||
| 1408 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | ||
| 1409 | }, | ||
| 1410 | } | ||
| 1411 | self.phdr_table_dirty = false; | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | { | ||
| 1415 | const shstrtab_sect = &self.sections.items[self.shstrtab_index.?]; | ||
| 1416 | if (self.shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) { | ||
| 1417 | const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset); | ||
| 1418 | const needed_size = self.shstrtab.items.len; | ||
| 1419 | |||
| 1420 | if (needed_size > allocated_size) { | ||
| 1421 | shstrtab_sect.sh_size = 0; // free the space | ||
| 1422 | shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 1423 | } | ||
| 1424 | shstrtab_sect.sh_size = needed_size; | ||
| 1425 | log.debug("writing shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); | ||
| 1426 | |||
| 1427 | try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); | ||
| 1428 | if (!self.shdr_table_dirty) { | ||
| 1429 | // Then it won't get written with the others and we need to do it. | ||
| 1430 | try self.writeSectHeader(self.shstrtab_index.?); | ||
| 1431 | } | ||
| 1432 | self.shstrtab_dirty = false; | ||
| 1433 | } | ||
| 1434 | } | ||
| 1435 | { | ||
| 1436 | const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?]; | ||
| 1437 | if (self.debug_strtab_dirty or self.debug_strtab.items.len != debug_strtab_sect.sh_size) { | ||
| 1438 | const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset); | ||
| 1439 | const needed_size = self.debug_strtab.items.len; | ||
| 1440 | |||
| 1441 | if (needed_size > allocated_size) { | ||
| 1442 | debug_strtab_sect.sh_size = 0; // free the space | ||
| 1443 | debug_strtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 1444 | } | ||
| 1445 | debug_strtab_sect.sh_size = needed_size; | ||
| 1446 | log.debug("debug_strtab start=0x{x} end=0x{x}\n", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); | ||
| 1447 | |||
| 1448 | try self.base.file.?.pwriteAll(self.debug_strtab.items, debug_strtab_sect.sh_offset); | ||
| 1449 | if (!self.shdr_table_dirty) { | ||
| 1450 | // Then it won't get written with the others and we need to do it. | ||
| 1451 | try self.writeSectHeader(self.debug_str_section_index.?); | ||
| 1452 | } | ||
| 1453 | self.debug_strtab_dirty = false; | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | if (self.shdr_table_dirty) { | ||
| 1457 | const shsize: u64 = switch (self.ptr_width) { | ||
| 1458 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 1459 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 1460 | }; | ||
| 1461 | const shalign: u16 = switch (self.ptr_width) { | ||
| 1462 | .p32 => @alignOf(elf.Elf32_Shdr), | ||
| 1463 | .p64 => @alignOf(elf.Elf64_Shdr), | ||
| 1464 | }; | ||
| 1465 | const allocated_size = self.allocatedSize(self.shdr_table_offset.?); | ||
| 1466 | const needed_size = self.sections.items.len * shsize; | ||
| 1467 | |||
| 1468 | if (needed_size > allocated_size) { | ||
| 1469 | self.shdr_table_offset = null; // free the space | ||
| 1470 | self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | switch (self.ptr_width) { | ||
| 1474 | .p32 => { | ||
| 1475 | const buf = try self.base.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); | ||
| 1476 | defer self.base.allocator.free(buf); | ||
| 1477 | |||
| 1478 | for (buf) |*shdr, i| { | ||
| 1479 | shdr.* = sectHeaderTo32(self.sections.items[i]); | ||
| 1480 | log.debug("writing section {}\n", .{shdr.*}); | ||
| 1481 | if (foreign_endian) { | ||
| 1482 | bswapAllFields(elf.Elf32_Shdr, shdr); | ||
| 1483 | } | ||
| 1484 | } | ||
| 1485 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | ||
| 1486 | }, | ||
| 1487 | .p64 => { | ||
| 1488 | const buf = try self.base.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); | ||
| 1489 | defer self.base.allocator.free(buf); | ||
| 1490 | |||
| 1491 | for (buf) |*shdr, i| { | ||
| 1492 | shdr.* = self.sections.items[i]; | ||
| 1493 | log.debug("writing section {}\n", .{shdr.*}); | ||
| 1494 | if (foreign_endian) { | ||
| 1495 | bswapAllFields(elf.Elf64_Shdr, shdr); | ||
| 1496 | } | ||
| 1497 | } | ||
| 1498 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | ||
| 1499 | }, | ||
| 1500 | } | ||
| 1501 | self.shdr_table_dirty = false; | ||
| 1502 | } | ||
| 1503 | if (self.entry_addr == null and self.base.options.output_mode == .Exe) { | ||
| 1504 | log.debug("flushing. no_entry_point_found = true\n", .{}); | ||
| 1505 | self.error_flags.no_entry_point_found = true; | ||
| 1506 | } else { | ||
| 1507 | log.debug("flushing. no_entry_point_found = false\n", .{}); | ||
| 1508 | self.error_flags.no_entry_point_found = false; | ||
| 1509 | try self.writeElfHeader(); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | // The point of flush() is to commit changes, so in theory, nothing should | ||
| 1513 | // be dirty after this. However, it is possible for some things to remain | ||
| 1514 | // dirty because they fail to be written in the event of compile errors, | ||
| 1515 | // such as debug_line_header_dirty and debug_info_header_dirty. | ||
| 1516 | assert(!self.debug_abbrev_section_dirty); | ||
| 1517 | assert(!self.debug_aranges_section_dirty); | ||
| 1518 | assert(!self.phdr_table_dirty); | ||
| 1519 | assert(!self.shdr_table_dirty); | ||
| 1520 | assert(!self.shstrtab_dirty); | ||
| 1521 | assert(!self.debug_strtab_dirty); | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void { | ||
| 1525 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 1526 | switch (self.ptr_width) { | ||
| 1527 | .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, addr), target_endian), | ||
| 1528 | .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian), | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | fn writeElfHeader(self: *Elf) !void { | ||
| 1533 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | ||
| 1534 | |||
| 1535 | var index: usize = 0; | ||
| 1536 | hdr_buf[0..4].* = "\x7fELF".*; | ||
| 1537 | index += 4; | ||
| 1538 | |||
| 1539 | hdr_buf[index] = switch (self.ptr_width) { | ||
| 1540 | .p32 => elf.ELFCLASS32, | ||
| 1541 | .p64 => elf.ELFCLASS64, | ||
| 1542 | }; | ||
| 1543 | index += 1; | ||
| 1544 | |||
| 1545 | const endian = self.base.options.target.cpu.arch.endian(); | ||
| 1546 | hdr_buf[index] = switch (endian) { | ||
| 1547 | .Little => elf.ELFDATA2LSB, | ||
| 1548 | .Big => elf.ELFDATA2MSB, | ||
| 1549 | }; | ||
| 1550 | index += 1; | ||
| 1551 | |||
| 1552 | hdr_buf[index] = 1; // ELF version | ||
| 1553 | index += 1; | ||
| 1554 | |||
| 1555 | // OS ABI, often set to 0 regardless of target platform | ||
| 1556 | // ABI Version, possibly used by glibc but not by static executables | ||
| 1557 | // padding | ||
| 1558 | mem.set(u8, hdr_buf[index..][0..9], 0); | ||
| 1559 | index += 9; | ||
| 1560 | |||
| 1561 | assert(index == 16); | ||
| 1562 | |||
| 1563 | const elf_type = switch (self.base.options.output_mode) { | ||
| 1564 | .Exe => elf.ET.EXEC, | ||
| 1565 | .Obj => elf.ET.REL, | ||
| 1566 | .Lib => switch (self.base.options.link_mode) { | ||
| 1567 | .Static => elf.ET.REL, | ||
| 1568 | .Dynamic => elf.ET.DYN, | ||
| 1569 | }, | ||
| 1570 | }; | ||
| 1571 | mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(elf_type), endian); | ||
| 1572 | index += 2; | ||
| 1573 | |||
| 1574 | const machine = self.base.options.target.cpu.arch.toElfMachine(); | ||
| 1575 | mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(machine), endian); | ||
| 1576 | index += 2; | ||
| 1577 | |||
| 1578 | // ELF Version, again | ||
| 1579 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); | ||
| 1580 | index += 4; | ||
| 1581 | |||
| 1582 | const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?; | ||
| 1583 | |||
| 1584 | switch (self.ptr_width) { | ||
| 1585 | .p32 => { | ||
| 1586 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, e_entry), endian); | ||
| 1587 | index += 4; | ||
| 1588 | |||
| 1589 | // e_phoff | ||
| 1590 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.phdr_table_offset.?), endian); | ||
| 1591 | index += 4; | ||
| 1592 | |||
| 1593 | // e_shoff | ||
| 1594 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.shdr_table_offset.?), endian); | ||
| 1595 | index += 4; | ||
| 1596 | }, | ||
| 1597 | .p64 => { | ||
| 1598 | // e_entry | ||
| 1599 | mem.writeInt(u64, hdr_buf[index..][0..8], e_entry, endian); | ||
| 1600 | index += 8; | ||
| 1601 | |||
| 1602 | // e_phoff | ||
| 1603 | mem.writeInt(u64, hdr_buf[index..][0..8], self.phdr_table_offset.?, endian); | ||
| 1604 | index += 8; | ||
| 1605 | |||
| 1606 | // e_shoff | ||
| 1607 | mem.writeInt(u64, hdr_buf[index..][0..8], self.shdr_table_offset.?, endian); | ||
| 1608 | index += 8; | ||
| 1609 | }, | ||
| 1610 | } | ||
| 1611 | |||
| 1612 | const e_flags = 0; | ||
| 1613 | mem.writeInt(u32, hdr_buf[index..][0..4], e_flags, endian); | ||
| 1614 | index += 4; | ||
| 1615 | |||
| 1616 | const e_ehsize: u16 = switch (self.ptr_width) { | ||
| 1617 | .p32 => @sizeOf(elf.Elf32_Ehdr), | ||
| 1618 | .p64 => @sizeOf(elf.Elf64_Ehdr), | ||
| 1619 | }; | ||
| 1620 | mem.writeInt(u16, hdr_buf[index..][0..2], e_ehsize, endian); | ||
| 1621 | index += 2; | ||
| 1622 | |||
| 1623 | const e_phentsize: u16 = switch (self.ptr_width) { | ||
| 1624 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 1625 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 1626 | }; | ||
| 1627 | mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian); | ||
| 1628 | index += 2; | ||
| 1629 | |||
| 1630 | const e_phnum = @intCast(u16, self.program_headers.items.len); | ||
| 1631 | mem.writeInt(u16, hdr_buf[index..][0..2], e_phnum, endian); | ||
| 1632 | index += 2; | ||
| 1633 | |||
| 1634 | const e_shentsize: u16 = switch (self.ptr_width) { | ||
| 1635 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 1636 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 1637 | }; | ||
| 1638 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); | ||
| 1639 | index += 2; | ||
| 1640 | |||
| 1641 | const e_shnum = @intCast(u16, self.sections.items.len); | ||
| 1642 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); | ||
| 1643 | index += 2; | ||
| 1644 | |||
| 1645 | mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_index.?, endian); | ||
| 1646 | index += 2; | ||
| 1647 | |||
| 1648 | assert(index == e_ehsize); | ||
| 1649 | |||
| 1650 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | fn freeTextBlock(self: *Elf, text_block: *TextBlock) void { | ||
| 1654 | var already_have_free_list_node = false; | ||
| 1655 | { | ||
| 1656 | var i: usize = 0; | ||
| 1657 | while (i < self.text_block_free_list.items.len) { | ||
| 1658 | if (self.text_block_free_list.items[i] == text_block) { | ||
| 1659 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1660 | continue; | ||
| 1661 | } | ||
| 1662 | if (self.text_block_free_list.items[i] == text_block.prev) { | ||
| 1663 | already_have_free_list_node = true; | ||
| 1664 | } | ||
| 1665 | i += 1; | ||
| 1666 | } | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | if (self.last_text_block == text_block) { | ||
| 1670 | // TODO shrink the .text section size here | ||
| 1671 | self.last_text_block = text_block.prev; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | if (text_block.prev) |prev| { | ||
| 1675 | prev.next = text_block.next; | ||
| 1676 | |||
| 1677 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | ||
| 1678 | // The free list is heuristics, it doesn't have to be perfect, so we can | ||
| 1679 | // ignore the OOM here. | ||
| 1680 | self.text_block_free_list.append(self.base.allocator, prev) catch {}; | ||
| 1681 | } | ||
| 1682 | } else { | ||
| 1683 | text_block.prev = null; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | if (text_block.next) |next| { | ||
| 1687 | next.prev = text_block.prev; | ||
| 1688 | } else { | ||
| 1689 | text_block.next = null; | ||
| 1690 | } | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void { | ||
| 1694 | // TODO check the new capacity, and if it crosses the size threshold into a big enough | ||
| 1695 | // capacity, insert a free list node for it. | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | ||
| 1699 | const sym = self.local_symbols.items[text_block.local_sym_index]; | ||
| 1700 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; | ||
| 1701 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); | ||
| 1702 | if (!need_realloc) return sym.st_value; | ||
| 1703 | return self.allocateTextBlock(text_block, new_block_size, alignment); | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | ||
| 1707 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1708 | const shdr = &self.sections.items[self.text_section_index.?]; | ||
| 1709 | const new_block_ideal_capacity = new_block_size * alloc_num / alloc_den; | ||
| 1710 | |||
| 1711 | // We use these to indicate our intention to update metadata, placing the new block, | ||
| 1712 | // and possibly removing a free list node. | ||
| 1713 | // It would be simpler to do it inside the for loop below, but that would cause a | ||
| 1714 | // problem if an error was returned later in the function. So this action | ||
| 1715 | // is actually carried out at the end of the function, when errors are no longer possible. | ||
| 1716 | var block_placement: ?*TextBlock = null; | ||
| 1717 | var free_list_removal: ?usize = null; | ||
| 1718 | |||
| 1719 | // First we look for an appropriately sized free list node. | ||
| 1720 | // The list is unordered. We'll just take the first thing that works. | ||
| 1721 | const vaddr = blk: { | ||
| 1722 | var i: usize = 0; | ||
| 1723 | while (i < self.text_block_free_list.items.len) { | ||
| 1724 | const big_block = self.text_block_free_list.items[i]; | ||
| 1725 | // We now have a pointer to a live text block that has too much capacity. | ||
| 1726 | // Is it enough that we could fit this new text block? | ||
| 1727 | const sym = self.local_symbols.items[big_block.local_sym_index]; | ||
| 1728 | const capacity = big_block.capacity(self.*); | ||
| 1729 | const ideal_capacity = capacity * alloc_num / alloc_den; | ||
| 1730 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; | ||
| 1731 | const capacity_end_vaddr = sym.st_value + capacity; | ||
| 1732 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_block_ideal_capacity; | ||
| 1733 | const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment); | ||
| 1734 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | ||
| 1735 | // Additional bookkeeping here to notice if this free list node | ||
| 1736 | // should be deleted because the block that it points to has grown to take up | ||
| 1737 | // more of the extra capacity. | ||
| 1738 | if (!big_block.freeListEligible(self.*)) { | ||
| 1739 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1740 | } else { | ||
| 1741 | i += 1; | ||
| 1742 | } | ||
| 1743 | continue; | ||
| 1744 | } | ||
| 1745 | // At this point we know that we will place the new block here. But the | ||
| 1746 | // remaining question is whether there is still yet enough capacity left | ||
| 1747 | // over for there to still be a free list node. | ||
| 1748 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; | ||
| 1749 | const keep_free_list_node = remaining_capacity >= min_text_capacity; | ||
| 1750 | |||
| 1751 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 1752 | block_placement = big_block; | ||
| 1753 | if (!keep_free_list_node) { | ||
| 1754 | free_list_removal = i; | ||
| 1755 | } | ||
| 1756 | break :blk new_start_vaddr; | ||
| 1757 | } else if (self.last_text_block) |last| { | ||
| 1758 | const sym = self.local_symbols.items[last.local_sym_index]; | ||
| 1759 | const ideal_capacity = sym.st_size * alloc_num / alloc_den; | ||
| 1760 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; | ||
| 1761 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); | ||
| 1762 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 1763 | block_placement = last; | ||
| 1764 | break :blk new_start_vaddr; | ||
| 1765 | } else { | ||
| 1766 | break :blk phdr.p_vaddr; | ||
| 1767 | } | ||
| 1768 | }; | ||
| 1769 | |||
| 1770 | const expand_text_section = block_placement == null or block_placement.?.next == null; | ||
| 1771 | if (expand_text_section) { | ||
| 1772 | const text_capacity = self.allocatedSize(shdr.sh_offset); | ||
| 1773 | const needed_size = (vaddr + new_block_size) - phdr.p_vaddr; | ||
| 1774 | if (needed_size > text_capacity) { | ||
| 1775 | // Must move the entire text section. | ||
| 1776 | const new_offset = self.findFreeSpace(needed_size, 0x1000); | ||
| 1777 | const text_size = if (self.last_text_block) |last| blk: { | ||
| 1778 | const sym = self.local_symbols.items[last.local_sym_index]; | ||
| 1779 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; | ||
| 1780 | } else 0; | ||
| 1781 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size); | ||
| 1782 | if (amt != text_size) return error.InputOutput; | ||
| 1783 | shdr.sh_offset = new_offset; | ||
| 1784 | phdr.p_offset = new_offset; | ||
| 1785 | } | ||
| 1786 | self.last_text_block = text_block; | ||
| 1787 | |||
| 1788 | shdr.sh_size = needed_size; | ||
| 1789 | phdr.p_memsz = needed_size; | ||
| 1790 | phdr.p_filesz = needed_size; | ||
| 1791 | |||
| 1792 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address | ||
| 1793 | // range of the compilation unit. When we expand the text section, this range changes, | ||
| 1794 | // so the DW_TAG_compile_unit tag of the .debug_info section becomes dirty. | ||
| 1795 | self.debug_info_header_dirty = true; | ||
| 1796 | // This becomes dirty for the same reason. We could potentially make this more | ||
| 1797 | // fine-grained with the addition of support for more compilation units. It is planned to | ||
| 1798 | // model each package as a different compilation unit. | ||
| 1799 | self.debug_aranges_section_dirty = true; | ||
| 1800 | |||
| 1801 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty | ||
| 1802 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 1803 | } | ||
| 1804 | |||
| 1805 | // This function can also reallocate a text block. | ||
| 1806 | // In this case we need to "unplug" it from its previous location before | ||
| 1807 | // plugging it in to its new location. | ||
| 1808 | if (text_block.prev) |prev| { | ||
| 1809 | prev.next = text_block.next; | ||
| 1810 | } | ||
| 1811 | if (text_block.next) |next| { | ||
| 1812 | next.prev = text_block.prev; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | if (block_placement) |big_block| { | ||
| 1816 | text_block.prev = big_block; | ||
| 1817 | text_block.next = big_block.next; | ||
| 1818 | big_block.next = text_block; | ||
| 1819 | } else { | ||
| 1820 | text_block.prev = null; | ||
| 1821 | text_block.next = null; | ||
| 1822 | } | ||
| 1823 | if (free_list_removal) |i| { | ||
| 1824 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1825 | } | ||
| 1826 | return vaddr; | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ||
| 1830 | if (decl.link.elf.local_sym_index != 0) return; | ||
| 1831 | |||
| 1832 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); | ||
| 1833 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); | ||
| 1834 | |||
| 1835 | if (self.local_symbol_free_list.popOrNull()) |i| { | ||
| 1836 | log.debug("reusing symbol index {} for {}\n", .{ i, decl.name }); | ||
| 1837 | decl.link.elf.local_sym_index = i; | ||
| 1838 | } else { | ||
| 1839 | log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name }); | ||
| 1840 | decl.link.elf.local_sym_index = @intCast(u32, self.local_symbols.items.len); | ||
| 1841 | _ = self.local_symbols.addOneAssumeCapacity(); | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | if (self.offset_table_free_list.popOrNull()) |i| { | ||
| 1845 | decl.link.elf.offset_table_index = i; | ||
| 1846 | } else { | ||
| 1847 | decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len); | ||
| 1848 | _ = self.offset_table.addOneAssumeCapacity(); | ||
| 1849 | self.offset_table_count_dirty = true; | ||
| 1850 | } | ||
| 1851 | |||
| 1852 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1853 | |||
| 1854 | self.local_symbols.items[decl.link.elf.local_sym_index] = .{ | ||
| 1855 | .st_name = 0, | ||
| 1856 | .st_info = 0, | ||
| 1857 | .st_other = 0, | ||
| 1858 | .st_shndx = 0, | ||
| 1859 | .st_value = phdr.p_vaddr, | ||
| 1860 | .st_size = 0, | ||
| 1861 | }; | ||
| 1862 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | ||
| 1866 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | ||
| 1867 | self.freeTextBlock(&decl.link.elf); | ||
| 1868 | if (decl.link.elf.local_sym_index != 0) { | ||
| 1869 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; | ||
| 1870 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; | ||
| 1871 | |||
| 1872 | self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; | ||
| 1873 | |||
| 1874 | decl.link.elf.local_sym_index = 0; | ||
| 1875 | } | ||
| 1876 | // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing | ||
| 1877 | // is desired for both. | ||
| 1878 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link.elf); | ||
| 1879 | if (decl.fn_link.elf.prev) |prev| { | ||
| 1880 | _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 1881 | prev.next = decl.fn_link.elf.next; | ||
| 1882 | if (decl.fn_link.elf.next) |next| { | ||
| 1883 | next.prev = prev; | ||
| 1884 | } else { | ||
| 1885 | self.dbg_line_fn_last = prev; | ||
| 1886 | } | ||
| 1887 | } else if (decl.fn_link.elf.next) |next| { | ||
| 1888 | self.dbg_line_fn_first = next; | ||
| 1889 | next.prev = null; | ||
| 1890 | } | ||
| 1891 | if (self.dbg_line_fn_first == &decl.fn_link.elf) { | ||
| 1892 | self.dbg_line_fn_first = null; | ||
| 1893 | } | ||
| 1894 | if (self.dbg_line_fn_last == &decl.fn_link.elf) { | ||
| 1895 | self.dbg_line_fn_last = null; | ||
| 1896 | } | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ||
| 1900 | const tracy = trace(@src()); | ||
| 1901 | defer tracy.end(); | ||
| 1902 | |||
| 1903 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1904 | defer code_buffer.deinit(); | ||
| 1905 | |||
| 1906 | var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1907 | defer dbg_line_buffer.deinit(); | ||
| 1908 | |||
| 1909 | var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1910 | defer dbg_info_buffer.deinit(); | ||
| 1911 | |||
| 1912 | var dbg_info_type_relocs: DbgInfoTypeRelocsTable = .{}; | ||
| 1913 | defer { | ||
| 1914 | for (dbg_info_type_relocs.items()) |*entry| { | ||
| 1915 | entry.value.relocs.deinit(self.base.allocator); | ||
| 1916 | } | ||
| 1917 | dbg_info_type_relocs.deinit(self.base.allocator); | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 1921 | const is_fn: bool = switch (typed_value.ty.zigTypeTag()) { | ||
| 1922 | .Fn => true, | ||
| 1923 | else => false, | ||
| 1924 | }; | ||
| 1925 | if (is_fn) { | ||
| 1926 | //if (mem.eql(u8, mem.spanZ(decl.name), "add")) { | ||
| 1927 | // typed_value.val.cast(Value.Payload.Function).?.func.dump(module.*); | ||
| 1928 | //} | ||
| 1929 | |||
| 1930 | // For functions we need to add a prologue to the debug line program. | ||
| 1931 | try dbg_line_buffer.ensureCapacity(26); | ||
| 1932 | |||
| 1933 | const line_off: u28 = blk: { | ||
| 1934 | if (decl.scope.cast(Module.Scope.File)) |scope_file| { | ||
| 1935 | const tree = scope_file.contents.tree; | ||
| 1936 | const file_ast_decls = tree.root_node.decls(); | ||
| 1937 | // TODO Look into improving the performance here by adding a token-index-to-line | ||
| 1938 | // lookup table. Currently this involves scanning over the source code for newlines. | ||
| 1939 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; | ||
| 1940 | const block = fn_proto.body().?.castTag(.Block).?; | ||
| 1941 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); | ||
| 1942 | break :blk @intCast(u28, line_delta); | ||
| 1943 | } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { | ||
| 1944 | const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src; | ||
| 1945 | const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off); | ||
| 1946 | break :blk @intCast(u28, line_delta); | ||
| 1947 | } else { | ||
| 1948 | unreachable; | ||
| 1949 | } | ||
| 1950 | }; | ||
| 1951 | |||
| 1952 | const ptr_width_bytes = self.ptrWidthBytes(); | ||
| 1953 | dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1954 | DW.LNS_extended_op, | ||
| 1955 | ptr_width_bytes + 1, | ||
| 1956 | DW.LNE_set_address, | ||
| 1957 | }); | ||
| 1958 | // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. | ||
| 1959 | assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); | ||
| 1960 | dbg_line_buffer.items.len += ptr_width_bytes; | ||
| 1961 | |||
| 1962 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); | ||
| 1963 | // This is the "relocatable" relative line offset from the previous function's end curly | ||
| 1964 | // to this function's begin curly. | ||
| 1965 | assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len); | ||
| 1966 | // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. | ||
| 1967 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); | ||
| 1968 | |||
| 1969 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); | ||
| 1970 | assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); | ||
| 1971 | // Once we support more than one source file, this will have the ability to be more | ||
| 1972 | // than one possible value. | ||
| 1973 | const file_index = 1; | ||
| 1974 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index); | ||
| 1975 | |||
| 1976 | // Emit a line for the begin curly with prologue_end=false. The codegen will | ||
| 1977 | // do the work of setting prologue_end=true and epilogue_begin=true. | ||
| 1978 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); | ||
| 1979 | |||
| 1980 | // .debug_info subprogram | ||
| 1981 | const decl_name_with_null = decl.name[0..mem.lenZ(decl.name) + 1]; | ||
| 1982 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len); | ||
| 1983 | |||
| 1984 | const fn_ret_type = typed_value.ty.fnReturnType(); | ||
| 1985 | const fn_ret_has_bits = fn_ret_type.hasCodeGenBits(); | ||
| 1986 | if (fn_ret_has_bits) { | ||
| 1987 | dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram); | ||
| 1988 | } else { | ||
| 1989 | dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram_retvoid); | ||
| 1990 | } | ||
| 1991 | // These get overwritten after generating the machine code. These values are | ||
| 1992 | // "relocations" and have to be in this fixed place so that functions can be | ||
| 1993 | // moved in virtual address space. | ||
| 1994 | assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); | ||
| 1995 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT_low_pc, DW.FORM_addr | ||
| 1996 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); | ||
| 1997 | dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 | ||
| 1998 | if (fn_ret_has_bits) { | ||
| 1999 | const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, fn_ret_type); | ||
| 2000 | if (!gop.found_existing) { | ||
| 2001 | gop.entry.value = .{ | ||
| 2002 | .off = undefined, | ||
| 2003 | .relocs = .{}, | ||
| 2004 | }; | ||
| 2005 | } | ||
| 2006 | try gop.entry.value.relocs.append(self.base.allocator, @intCast(u32, dbg_info_buffer.items.len)); | ||
| 2007 | dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 | ||
| 2008 | } | ||
| 2009 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string | ||
| 2010 | } else { | ||
| 2011 | // TODO implement .debug_info for global variables | ||
| 2012 | } | ||
| 2013 | const res = try codegen.generateSymbol(self, decl.src(), typed_value, &code_buffer, &dbg_line_buffer, &dbg_info_buffer, &dbg_info_type_relocs); | ||
| 2014 | const code = switch (res) { | ||
| 2015 | .externally_managed => |x| x, | ||
| 2016 | .appended => code_buffer.items, | ||
| 2017 | .fail => |em| { | ||
| 2018 | decl.analysis = .codegen_failure; | ||
| 2019 | try module.failed_decls.put(module.gpa, decl, em); | ||
| 2020 | return; | ||
| 2021 | }, | ||
| 2022 | }; | ||
| 2023 | |||
| 2024 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); | ||
| 2025 | |||
| 2026 | const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT; | ||
| 2027 | |||
| 2028 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() | ||
| 2029 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; | ||
| 2030 | if (local_sym.st_size != 0) { | ||
| 2031 | const capacity = decl.link.elf.capacity(self.*); | ||
| 2032 | const need_realloc = code.len > capacity or | ||
| 2033 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); | ||
| 2034 | if (need_realloc) { | ||
| 2035 | const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment); | ||
| 2036 | log.debug("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr }); | ||
| 2037 | if (vaddr != local_sym.st_value) { | ||
| 2038 | local_sym.st_value = vaddr; | ||
| 2039 | |||
| 2040 | log.debug(" (writing new offset table entry)\n", .{}); | ||
| 2041 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; | ||
| 2042 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | ||
| 2043 | } | ||
| 2044 | } else if (code.len < local_sym.st_size) { | ||
| 2045 | self.shrinkTextBlock(&decl.link.elf, code.len); | ||
| 2046 | } | ||
| 2047 | local_sym.st_size = code.len; | ||
| 2048 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name)); | ||
| 2049 | local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; | ||
| 2050 | local_sym.st_other = 0; | ||
| 2051 | local_sym.st_shndx = self.text_section_index.?; | ||
| 2052 | // TODO this write could be avoided if no fields of the symbol were changed. | ||
| 2053 | try self.writeSymbol(decl.link.elf.local_sym_index); | ||
| 2054 | } else { | ||
| 2055 | const decl_name = mem.spanZ(decl.name); | ||
| 2056 | const name_str_index = try self.makeString(decl_name); | ||
| 2057 | const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment); | ||
| 2058 | log.debug("allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr }); | ||
| 2059 | errdefer self.freeTextBlock(&decl.link.elf); | ||
| 2060 | |||
| 2061 | local_sym.* = .{ | ||
| 2062 | .st_name = name_str_index, | ||
| 2063 | .st_info = (elf.STB_LOCAL << 4) | stt_bits, | ||
| 2064 | .st_other = 0, | ||
| 2065 | .st_shndx = self.text_section_index.?, | ||
| 2066 | .st_value = vaddr, | ||
| 2067 | .st_size = code.len, | ||
| 2068 | }; | ||
| 2069 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; | ||
| 2070 | |||
| 2071 | try self.writeSymbol(decl.link.elf.local_sym_index); | ||
| 2072 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | ||
| 2073 | } | ||
| 2074 | |||
| 2075 | const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr; | ||
| 2076 | const file_offset = self.sections.items[self.text_section_index.?].sh_offset + section_offset; | ||
| 2077 | try self.base.file.?.pwriteAll(code, file_offset); | ||
| 2078 | |||
| 2079 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 2080 | |||
| 2081 | const text_block = &decl.link.elf; | ||
| 2082 | |||
| 2083 | // If the Decl is a function, we need to update the .debug_line program. | ||
| 2084 | if (is_fn) { | ||
| 2085 | // Perform the relocations based on vaddr. | ||
| 2086 | switch (self.ptr_width) { | ||
| 2087 | .p32 => { | ||
| 2088 | { | ||
| 2089 | const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..4]; | ||
| 2090 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_value), target_endian); | ||
| 2091 | } | ||
| 2092 | { | ||
| 2093 | const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..4]; | ||
| 2094 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_value), target_endian); | ||
| 2095 | } | ||
| 2096 | }, | ||
| 2097 | .p64 => { | ||
| 2098 | { | ||
| 2099 | const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..8]; | ||
| 2100 | mem.writeInt(u64, ptr, local_sym.st_value, target_endian); | ||
| 2101 | } | ||
| 2102 | { | ||
| 2103 | const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..8]; | ||
| 2104 | mem.writeInt(u64, ptr, local_sym.st_value, target_endian); | ||
| 2105 | } | ||
| 2106 | }, | ||
| 2107 | } | ||
| 2108 | { | ||
| 2109 | const ptr = dbg_info_buffer.items[self.getRelocDbgInfoSubprogramHighPC()..][0..4]; | ||
| 2110 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_size), target_endian); | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); | ||
| 2114 | |||
| 2115 | // Now we have the full contents and may allocate a region to store it. | ||
| 2116 | |||
| 2117 | // This logic is nearly identical to the logic below in `updateDeclDebugInfo` for | ||
| 2118 | // `TextBlock` and the .debug_info. If you are editing this logic, you | ||
| 2119 | // probably need to edit that logic too. | ||
| 2120 | |||
| 2121 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | ||
| 2122 | const src_fn = &decl.fn_link.elf; | ||
| 2123 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); | ||
| 2124 | if (self.dbg_line_fn_last) |last| { | ||
| 2125 | if (src_fn.next) |next| { | ||
| 2126 | // Update existing function - non-last item. | ||
| 2127 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { | ||
| 2128 | // It grew too big, so we move it to a new location. | ||
| 2129 | if (src_fn.prev) |prev| { | ||
| 2130 | _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 2131 | prev.next = src_fn.next; | ||
| 2132 | } | ||
| 2133 | next.prev = src_fn.prev; | ||
| 2134 | src_fn.next = null; | ||
| 2135 | // Populate where it used to be with NOPs. | ||
| 2136 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | ||
| 2137 | try self.pwriteDbgLineNops(0, &[0]u8{}, src_fn.len, file_pos); | ||
| 2138 | // TODO Look at the free list before appending at the end. | ||
| 2139 | src_fn.prev = last; | ||
| 2140 | last.next = src_fn; | ||
| 2141 | self.dbg_line_fn_last = src_fn; | ||
| 2142 | |||
| 2143 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); | ||
| 2144 | } | ||
| 2145 | } else if (src_fn.prev == null) { | ||
| 2146 | // Append new function. | ||
| 2147 | // TODO Look at the free list before appending at the end. | ||
| 2148 | src_fn.prev = last; | ||
| 2149 | last.next = src_fn; | ||
| 2150 | self.dbg_line_fn_last = src_fn; | ||
| 2151 | |||
| 2152 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); | ||
| 2153 | } | ||
| 2154 | } else { | ||
| 2155 | // This is the first function of the Line Number Program. | ||
| 2156 | self.dbg_line_fn_first = src_fn; | ||
| 2157 | self.dbg_line_fn_last = src_fn; | ||
| 2158 | |||
| 2159 | src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den; | ||
| 2160 | } | ||
| 2161 | |||
| 2162 | const last_src_fn = self.dbg_line_fn_last.?; | ||
| 2163 | const needed_size = last_src_fn.off + last_src_fn.len; | ||
| 2164 | if (needed_size != debug_line_sect.sh_size) { | ||
| 2165 | if (needed_size > self.allocatedSize(debug_line_sect.sh_offset)) { | ||
| 2166 | const new_offset = self.findFreeSpace(needed_size, 1); | ||
| 2167 | const existing_size = last_src_fn.off; | ||
| 2168 | log.debug("moving .debug_line section: {} bytes from 0x{x} to 0x{x}\n", .{ | ||
| 2169 | existing_size, | ||
| 2170 | debug_line_sect.sh_offset, | ||
| 2171 | new_offset, | ||
| 2172 | }); | ||
| 2173 | const amt = try self.base.file.?.copyRangeAll(debug_line_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 2174 | if (amt != existing_size) return error.InputOutput; | ||
| 2175 | debug_line_sect.sh_offset = new_offset; | ||
| 2176 | } | ||
| 2177 | debug_line_sect.sh_size = needed_size; | ||
| 2178 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 2179 | self.debug_line_header_dirty = true; | ||
| 2180 | } | ||
| 2181 | const prev_padding_size: u32 = if (src_fn.prev) |prev| src_fn.off - (prev.off + prev.len) else 0; | ||
| 2182 | const next_padding_size: u32 = if (src_fn.next) |next| next.off - (src_fn.off + src_fn.len) else 0; | ||
| 2183 | |||
| 2184 | // We only have support for one compilation unit so far, so the offsets are directly | ||
| 2185 | // from the .debug_line section. | ||
| 2186 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | ||
| 2187 | try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); | ||
| 2188 | |||
| 2189 | // .debug_info - End the TAG_subprogram children. | ||
| 2190 | try dbg_info_buffer.append(0); | ||
| 2191 | } | ||
| 2192 | |||
| 2193 | // Now we emit the .debug_info types of the Decl. These will count towards the size of | ||
| 2194 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual | ||
| 2195 | // relocations yet. | ||
| 2196 | for (dbg_info_type_relocs.items()) |*entry| { | ||
| 2197 | entry.value.off = @intCast(u32, dbg_info_buffer.items.len); | ||
| 2198 | try self.addDbgInfoType(entry.key, &dbg_info_buffer); | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | try self.updateDeclDebugInfoAllocation(text_block, @intCast(u32, dbg_info_buffer.items.len)); | ||
| 2202 | |||
| 2203 | // Now that we have the offset assigned we can finally perform type relocations. | ||
| 2204 | for (dbg_info_type_relocs.items()) |entry| { | ||
| 2205 | for (entry.value.relocs.items) |off| { | ||
| 2206 | mem.writeInt( | ||
| 2207 | u32, | ||
| 2208 | dbg_info_buffer.items[off..][0..4], | ||
| 2209 | text_block.dbg_info_off + entry.value.off, | ||
| 2210 | target_endian, | ||
| 2211 | ); | ||
| 2212 | } | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | try self.writeDeclDebugInfo(text_block, dbg_info_buffer.items); | ||
| 2216 | |||
| 2217 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | ||
| 2218 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | ||
| 2219 | return self.updateDeclExports(module, decl, decl_exports); | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | /// Asserts the type has codegen bits. | ||
| 2223 | fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void { | ||
| 2224 | switch (ty.zigTypeTag()) { | ||
| 2225 | .Void => unreachable, | ||
| 2226 | .NoReturn => unreachable, | ||
| 2227 | .Bool => { | ||
| 2228 | try dbg_info_buffer.appendSlice(&[_]u8{ | ||
| 2229 | abbrev_base_type, | ||
| 2230 | DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 | ||
| 2231 | 1, // DW.AT_byte_size, DW.FORM_data1 | ||
| 2232 | 'b', 'o', 'o', 'l', 0, // DW.AT_name, DW.FORM_string | ||
| 2233 | }); | ||
| 2234 | }, | ||
| 2235 | .Int => { | ||
| 2236 | const info = ty.intInfo(self.base.options.target); | ||
| 2237 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); | ||
| 2238 | dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); | ||
| 2239 | // DW.AT_encoding, DW.FORM_data1 | ||
| 2240 | dbg_info_buffer.appendAssumeCapacity(if (info.signed) DW.ATE_signed else DW.ATE_unsigned); | ||
| 2241 | // DW.AT_byte_size, DW.FORM_data1 | ||
| 2242 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); | ||
| 2243 | // DW.AT_name, DW.FORM_string | ||
| 2244 | try dbg_info_buffer.writer().print("{}\x00", .{ty}); | ||
| 2245 | }, | ||
| 2246 | else => { | ||
| 2247 | std.log.scoped(.compiler).err("TODO implement .debug_info for type '{}'", .{ty}); | ||
| 2248 | try dbg_info_buffer.append(abbrev_pad1); | ||
| 2249 | }, | ||
| 2250 | } | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | fn updateDeclDebugInfoAllocation(self: *Elf, text_block: *TextBlock, len: u32) !void { | ||
| 2254 | const tracy = trace(@src()); | ||
| 2255 | defer tracy.end(); | ||
| 2256 | |||
| 2257 | // This logic is nearly identical to the logic above in `updateDecl` for | ||
| 2258 | // `SrcFn` and the line number programs. If you are editing this logic, you | ||
| 2259 | // probably need to edit that logic too. | ||
| 2260 | |||
| 2261 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 2262 | text_block.dbg_info_len = len; | ||
| 2263 | if (self.dbg_info_decl_last) |last| { | ||
| 2264 | if (text_block.dbg_info_next) |next| { | ||
| 2265 | // Update existing Decl - non-last item. | ||
| 2266 | if (text_block.dbg_info_off + text_block.dbg_info_len + min_nop_size > next.dbg_info_off) { | ||
| 2267 | // It grew too big, so we move it to a new location. | ||
| 2268 | if (text_block.dbg_info_prev) |prev| { | ||
| 2269 | _ = self.dbg_info_decl_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 2270 | prev.dbg_info_next = text_block.dbg_info_next; | ||
| 2271 | } | ||
| 2272 | next.dbg_info_prev = text_block.dbg_info_prev; | ||
| 2273 | text_block.dbg_info_next = null; | ||
| 2274 | // Populate where it used to be with NOPs. | ||
| 2275 | const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off; | ||
| 2276 | try self.pwriteDbgInfoNops(0, &[0]u8{}, text_block.dbg_info_len, false, file_pos); | ||
| 2277 | // TODO Look at the free list before appending at the end. | ||
| 2278 | text_block.dbg_info_prev = last; | ||
| 2279 | last.dbg_info_next = text_block; | ||
| 2280 | self.dbg_info_decl_last = text_block; | ||
| 2281 | |||
| 2282 | text_block.dbg_info_off = last.dbg_info_off + (last.dbg_info_len * alloc_num / alloc_den); | ||
| 2283 | } | ||
| 2284 | } else if (text_block.dbg_info_prev == null) { | ||
| 2285 | // Append new Decl. | ||
| 2286 | // TODO Look at the free list before appending at the end. | ||
| 2287 | text_block.dbg_info_prev = last; | ||
| 2288 | last.dbg_info_next = text_block; | ||
| 2289 | self.dbg_info_decl_last = text_block; | ||
| 2290 | |||
| 2291 | text_block.dbg_info_off = last.dbg_info_off + (last.dbg_info_len * alloc_num / alloc_den); | ||
| 2292 | } | ||
| 2293 | } else { | ||
| 2294 | // This is the first Decl of the .debug_info | ||
| 2295 | self.dbg_info_decl_first = text_block; | ||
| 2296 | self.dbg_info_decl_last = text_block; | ||
| 2297 | |||
| 2298 | text_block.dbg_info_off = self.dbgInfoNeededHeaderBytes() * alloc_num / alloc_den; | ||
| 2299 | } | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | fn writeDeclDebugInfo(self: *Elf, text_block: *TextBlock, dbg_info_buf: []const u8) !void { | ||
| 2303 | const tracy = trace(@src()); | ||
| 2304 | defer tracy.end(); | ||
| 2305 | |||
| 2306 | // This logic is nearly identical to the logic above in `updateDecl` for | ||
| 2307 | // `SrcFn` and the line number programs. If you are editing this logic, you | ||
| 2308 | // probably need to edit that logic too. | ||
| 2309 | |||
| 2310 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 2311 | |||
| 2312 | const last_decl = self.dbg_info_decl_last.?; | ||
| 2313 | // +1 for a trailing zero to end the children of the decl tag. | ||
| 2314 | const needed_size = last_decl.dbg_info_off + last_decl.dbg_info_len + 1; | ||
| 2315 | if (needed_size != debug_info_sect.sh_size) { | ||
| 2316 | if (needed_size > self.allocatedSize(debug_info_sect.sh_offset)) { | ||
| 2317 | const new_offset = self.findFreeSpace(needed_size, 1); | ||
| 2318 | const existing_size = last_decl.dbg_info_off; | ||
| 2319 | log.debug("moving .debug_info section: {} bytes from 0x{x} to 0x{x}\n", .{ | ||
| 2320 | existing_size, | ||
| 2321 | debug_info_sect.sh_offset, | ||
| 2322 | new_offset, | ||
| 2323 | }); | ||
| 2324 | const amt = try self.base.file.?.copyRangeAll(debug_info_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 2325 | if (amt != existing_size) return error.InputOutput; | ||
| 2326 | debug_info_sect.sh_offset = new_offset; | ||
| 2327 | } | ||
| 2328 | debug_info_sect.sh_size = needed_size; | ||
| 2329 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 2330 | self.debug_info_header_dirty = true; | ||
| 2331 | } | ||
| 2332 | const prev_padding_size: u32 = if (text_block.dbg_info_prev) |prev| | ||
| 2333 | text_block.dbg_info_off - (prev.dbg_info_off + prev.dbg_info_len) | ||
| 2334 | else | ||
| 2335 | 0; | ||
| 2336 | const next_padding_size: u32 = if (text_block.dbg_info_next) |next| | ||
| 2337 | next.dbg_info_off - (text_block.dbg_info_off + text_block.dbg_info_len) | ||
| 2338 | else | ||
| 2339 | 0; | ||
| 2340 | |||
| 2341 | // To end the children of the decl tag. | ||
| 2342 | const trailing_zero = text_block.dbg_info_next == null; | ||
| 2343 | |||
| 2344 | // We only have support for one compilation unit so far, so the offsets are directly | ||
| 2345 | // from the .debug_info section. | ||
| 2346 | const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off; | ||
| 2347 | try self.pwriteDbgInfoNops(prev_padding_size, dbg_info_buf, next_padding_size, trailing_zero, file_pos); | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | pub fn updateDeclExports( | ||
| 2351 | self: *Elf, | ||
| 2352 | module: *Module, | ||
| 2353 | decl: *const Module.Decl, | ||
| 2354 | exports: []const *Module.Export, | ||
| 2355 | ) !void { | ||
| 2356 | const tracy = trace(@src()); | ||
| 2357 | defer tracy.end(); | ||
| 2358 | |||
| 2359 | try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len); | ||
| 2360 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 2361 | if (decl.link.elf.local_sym_index == 0) return; | ||
| 2362 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; | ||
| 2363 | |||
| 2364 | for (exports) |exp| { | ||
| 2365 | if (exp.options.section) |section_name| { | ||
| 2366 | if (!mem.eql(u8, section_name, ".text")) { | ||
| 2367 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | ||
| 2368 | module.failed_exports.putAssumeCapacityNoClobber( | ||
| 2369 | exp, | ||
| 2370 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}), | ||
| 2371 | ); | ||
| 2372 | continue; | ||
| 2373 | } | ||
| 2374 | } | ||
| 2375 | const stb_bits: u8 = switch (exp.options.linkage) { | ||
| 2376 | .Internal => elf.STB_LOCAL, | ||
| 2377 | .Strong => blk: { | ||
| 2378 | if (mem.eql(u8, exp.options.name, "_start")) { | ||
| 2379 | self.entry_addr = decl_sym.st_value; | ||
| 2380 | } | ||
| 2381 | break :blk elf.STB_GLOBAL; | ||
| 2382 | }, | ||
| 2383 | .Weak => elf.STB_WEAK, | ||
| 2384 | .LinkOnce => { | ||
| 2385 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | ||
| 2386 | module.failed_exports.putAssumeCapacityNoClobber( | ||
| 2387 | exp, | ||
| 2388 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), | ||
| 2389 | ); | ||
| 2390 | continue; | ||
| 2391 | }, | ||
| 2392 | }; | ||
| 2393 | const stt_bits: u8 = @truncate(u4, decl_sym.st_info); | ||
| 2394 | if (exp.link.sym_index) |i| { | ||
| 2395 | const sym = &self.global_symbols.items[i]; | ||
| 2396 | sym.* = .{ | ||
| 2397 | .st_name = try self.updateString(sym.st_name, exp.options.name), | ||
| 2398 | .st_info = (stb_bits << 4) | stt_bits, | ||
| 2399 | .st_other = 0, | ||
| 2400 | .st_shndx = self.text_section_index.?, | ||
| 2401 | .st_value = decl_sym.st_value, | ||
| 2402 | .st_size = decl_sym.st_size, | ||
| 2403 | }; | ||
| 2404 | } else { | ||
| 2405 | const name = try self.makeString(exp.options.name); | ||
| 2406 | const i = if (self.global_symbol_free_list.popOrNull()) |i| i else blk: { | ||
| 2407 | _ = self.global_symbols.addOneAssumeCapacity(); | ||
| 2408 | break :blk self.global_symbols.items.len - 1; | ||
| 2409 | }; | ||
| 2410 | self.global_symbols.items[i] = .{ | ||
| 2411 | .st_name = name, | ||
| 2412 | .st_info = (stb_bits << 4) | stt_bits, | ||
| 2413 | .st_other = 0, | ||
| 2414 | .st_shndx = self.text_section_index.?, | ||
| 2415 | .st_value = decl_sym.st_value, | ||
| 2416 | .st_size = decl_sym.st_size, | ||
| 2417 | }; | ||
| 2418 | |||
| 2419 | exp.link.sym_index = @intCast(u32, i); | ||
| 2420 | } | ||
| 2421 | } | ||
| 2422 | } | ||
| 2423 | |||
| 2424 | /// Must be called only after a successful call to `updateDecl`. | ||
| 2425 | pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Decl) !void { | ||
| 2426 | const tracy = trace(@src()); | ||
| 2427 | defer tracy.end(); | ||
| 2428 | |||
| 2429 | const scope_file = decl.scope.cast(Module.Scope.File).?; | ||
| 2430 | const tree = scope_file.contents.tree; | ||
| 2431 | const file_ast_decls = tree.root_node.decls(); | ||
| 2432 | // TODO Look into improving the performance here by adding a token-index-to-line | ||
| 2433 | // lookup table. Currently this involves scanning over the source code for newlines. | ||
| 2434 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; | ||
| 2435 | const block = fn_proto.body().?.castTag(.Block).?; | ||
| 2436 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); | ||
| 2437 | const casted_line_off = @intCast(u28, line_delta); | ||
| 2438 | |||
| 2439 | const shdr = &self.sections.items[self.debug_line_section_index.?]; | ||
| 2440 | const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff(); | ||
| 2441 | var data: [4]u8 = undefined; | ||
| 2442 | leb128.writeUnsignedFixed(4, &data, casted_line_off); | ||
| 2443 | try self.base.file.?.pwriteAll(&data, file_pos); | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | pub fn deleteExport(self: *Elf, exp: Export) void { | ||
| 2447 | const sym_index = exp.sym_index orelse return; | ||
| 2448 | self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {}; | ||
| 2449 | self.global_symbols.items[sym_index].st_info = 0; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | fn writeProgHeader(self: *Elf, index: usize) !void { | ||
| 2453 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2454 | const offset = self.program_headers.items[index].p_offset; | ||
| 2455 | switch (self.base.options.target.cpu.arch.ptrBitWidth()) { | ||
| 2456 | 32 => { | ||
| 2457 | var phdr = [1]elf.Elf32_Phdr{progHeaderTo32(self.program_headers.items[index])}; | ||
| 2458 | if (foreign_endian) { | ||
| 2459 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); | ||
| 2460 | } | ||
| 2461 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | ||
| 2462 | }, | ||
| 2463 | 64 => { | ||
| 2464 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; | ||
| 2465 | if (foreign_endian) { | ||
| 2466 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); | ||
| 2467 | } | ||
| 2468 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | ||
| 2469 | }, | ||
| 2470 | else => return error.UnsupportedArchitecture, | ||
| 2471 | } | ||
| 2472 | } | ||
| 2473 | |||
| 2474 | fn writeSectHeader(self: *Elf, index: usize) !void { | ||
| 2475 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2476 | switch (self.base.options.target.cpu.arch.ptrBitWidth()) { | ||
| 2477 | 32 => { | ||
| 2478 | var shdr: [1]elf.Elf32_Shdr = undefined; | ||
| 2479 | shdr[0] = sectHeaderTo32(self.sections.items[index]); | ||
| 2480 | if (foreign_endian) { | ||
| 2481 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); | ||
| 2482 | } | ||
| 2483 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr); | ||
| 2484 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); | ||
| 2485 | }, | ||
| 2486 | 64 => { | ||
| 2487 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; | ||
| 2488 | if (foreign_endian) { | ||
| 2489 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); | ||
| 2490 | } | ||
| 2491 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr); | ||
| 2492 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); | ||
| 2493 | }, | ||
| 2494 | else => return error.UnsupportedArchitecture, | ||
| 2495 | } | ||
| 2496 | } | ||
| 2497 | |||
| 2498 | fn writeOffsetTableEntry(self: *Elf, index: usize) !void { | ||
| 2499 | const shdr = &self.sections.items[self.got_section_index.?]; | ||
| 2500 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | ||
| 2501 | const entry_size: u16 = self.ptrWidthBytes(); | ||
| 2502 | if (self.offset_table_count_dirty) { | ||
| 2503 | // TODO Also detect virtual address collisions. | ||
| 2504 | const allocated_size = self.allocatedSize(shdr.sh_offset); | ||
| 2505 | const needed_size = self.local_symbols.items.len * entry_size; | ||
| 2506 | if (needed_size > allocated_size) { | ||
| 2507 | // Must move the entire got section. | ||
| 2508 | const new_offset = self.findFreeSpace(needed_size, entry_size); | ||
| 2509 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size); | ||
| 2510 | if (amt != shdr.sh_size) return error.InputOutput; | ||
| 2511 | shdr.sh_offset = new_offset; | ||
| 2512 | phdr.p_offset = new_offset; | ||
| 2513 | } | ||
| 2514 | shdr.sh_size = needed_size; | ||
| 2515 | phdr.p_memsz = needed_size; | ||
| 2516 | phdr.p_filesz = needed_size; | ||
| 2517 | |||
| 2518 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 2519 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty | ||
| 2520 | |||
| 2521 | self.offset_table_count_dirty = false; | ||
| 2522 | } | ||
| 2523 | const endian = self.base.options.target.cpu.arch.endian(); | ||
| 2524 | const off = shdr.sh_offset + @as(u64, entry_size) * index; | ||
| 2525 | switch (self.ptr_width) { | ||
| 2526 | .p32 => { | ||
| 2527 | var buf: [4]u8 = undefined; | ||
| 2528 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); | ||
| 2529 | try self.base.file.?.pwriteAll(&buf, off); | ||
| 2530 | }, | ||
| 2531 | .p64 => { | ||
| 2532 | var buf: [8]u8 = undefined; | ||
| 2533 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); | ||
| 2534 | try self.base.file.?.pwriteAll(&buf, off); | ||
| 2535 | }, | ||
| 2536 | } | ||
| 2537 | } | ||
| 2538 | |||
| 2539 | fn writeSymbol(self: *Elf, index: usize) !void { | ||
| 2540 | const tracy = trace(@src()); | ||
| 2541 | defer tracy.end(); | ||
| 2542 | |||
| 2543 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; | ||
| 2544 | // Make sure we are not pointlessly writing symbol data that will have to get relocated | ||
| 2545 | // due to running out of space. | ||
| 2546 | if (self.local_symbols.items.len != syms_sect.sh_info) { | ||
| 2547 | const sym_size: u64 = switch (self.ptr_width) { | ||
| 2548 | .p32 => @sizeOf(elf.Elf32_Sym), | ||
| 2549 | .p64 => @sizeOf(elf.Elf64_Sym), | ||
| 2550 | }; | ||
| 2551 | const sym_align: u16 = switch (self.ptr_width) { | ||
| 2552 | .p32 => @alignOf(elf.Elf32_Sym), | ||
| 2553 | .p64 => @alignOf(elf.Elf64_Sym), | ||
| 2554 | }; | ||
| 2555 | const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; | ||
| 2556 | if (needed_size > self.allocatedSize(syms_sect.sh_offset)) { | ||
| 2557 | // Move all the symbols to a new file location. | ||
| 2558 | const new_offset = self.findFreeSpace(needed_size, sym_align); | ||
| 2559 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; | ||
| 2560 | const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 2561 | if (amt != existing_size) return error.InputOutput; | ||
| 2562 | syms_sect.sh_offset = new_offset; | ||
| 2563 | } | ||
| 2564 | syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len); | ||
| 2565 | syms_sect.sh_size = needed_size; // anticipating adding the global symbols later | ||
| 2566 | self.shdr_table_dirty = true; // TODO look into only writing one section | ||
| 2567 | } | ||
| 2568 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2569 | switch (self.ptr_width) { | ||
| 2570 | .p32 => { | ||
| 2571 | var sym = [1]elf.Elf32_Sym{ | ||
| 2572 | .{ | ||
| 2573 | .st_name = self.local_symbols.items[index].st_name, | ||
| 2574 | .st_value = @intCast(u32, self.local_symbols.items[index].st_value), | ||
| 2575 | .st_size = @intCast(u32, self.local_symbols.items[index].st_size), | ||
| 2576 | .st_info = self.local_symbols.items[index].st_info, | ||
| 2577 | .st_other = self.local_symbols.items[index].st_other, | ||
| 2578 | .st_shndx = self.local_symbols.items[index].st_shndx, | ||
| 2579 | }, | ||
| 2580 | }; | ||
| 2581 | if (foreign_endian) { | ||
| 2582 | bswapAllFields(elf.Elf32_Sym, &sym[0]); | ||
| 2583 | } | ||
| 2584 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index; | ||
| 2585 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | ||
| 2586 | }, | ||
| 2587 | .p64 => { | ||
| 2588 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; | ||
| 2589 | if (foreign_endian) { | ||
| 2590 | bswapAllFields(elf.Elf64_Sym, &sym[0]); | ||
| 2591 | } | ||
| 2592 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index; | ||
| 2593 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | ||
| 2594 | }, | ||
| 2595 | } | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | fn writeAllGlobalSymbols(self: *Elf) !void { | ||
| 2599 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; | ||
| 2600 | const sym_size: u64 = switch (self.ptr_width) { | ||
| 2601 | .p32 => @sizeOf(elf.Elf32_Sym), | ||
| 2602 | .p64 => @sizeOf(elf.Elf64_Sym), | ||
| 2603 | }; | ||
| 2604 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2605 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; | ||
| 2606 | switch (self.ptr_width) { | ||
| 2607 | .p32 => { | ||
| 2608 | const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len); | ||
| 2609 | defer self.base.allocator.free(buf); | ||
| 2610 | |||
| 2611 | for (buf) |*sym, i| { | ||
| 2612 | sym.* = .{ | ||
| 2613 | .st_name = self.global_symbols.items[i].st_name, | ||
| 2614 | .st_value = @intCast(u32, self.global_symbols.items[i].st_value), | ||
| 2615 | .st_size = @intCast(u32, self.global_symbols.items[i].st_size), | ||
| 2616 | .st_info = self.global_symbols.items[i].st_info, | ||
| 2617 | .st_other = self.global_symbols.items[i].st_other, | ||
| 2618 | .st_shndx = self.global_symbols.items[i].st_shndx, | ||
| 2619 | }; | ||
| 2620 | if (foreign_endian) { | ||
| 2621 | bswapAllFields(elf.Elf32_Sym, sym); | ||
| 2622 | } | ||
| 2623 | } | ||
| 2624 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | ||
| 2625 | }, | ||
| 2626 | .p64 => { | ||
| 2627 | const buf = try self.base.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); | ||
| 2628 | defer self.base.allocator.free(buf); | ||
| 2629 | |||
| 2630 | for (buf) |*sym, i| { | ||
| 2631 | sym.* = .{ | ||
| 2632 | .st_name = self.global_symbols.items[i].st_name, | ||
| 2633 | .st_value = self.global_symbols.items[i].st_value, | ||
| 2634 | .st_size = self.global_symbols.items[i].st_size, | ||
| 2635 | .st_info = self.global_symbols.items[i].st_info, | ||
| 2636 | .st_other = self.global_symbols.items[i].st_other, | ||
| 2637 | .st_shndx = self.global_symbols.items[i].st_shndx, | ||
| 2638 | }; | ||
| 2639 | if (foreign_endian) { | ||
| 2640 | bswapAllFields(elf.Elf64_Sym, sym); | ||
| 2641 | } | ||
| 2642 | } | ||
| 2643 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | ||
| 2644 | }, | ||
| 2645 | } | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | fn ptrWidthBytes(self: Elf) u8 { | ||
| 2649 | return switch (self.ptr_width) { | ||
| 2650 | .p32 => 4, | ||
| 2651 | .p64 => 8, | ||
| 2652 | }; | ||
| 2653 | } | ||
| 2654 | |||
| 2655 | /// The reloc offset for the virtual address of a function in its Line Number Program. | ||
| 2656 | /// Size is a virtual address integer. | ||
| 2657 | const dbg_line_vaddr_reloc_index = 3; | ||
| 2658 | /// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. | ||
| 2659 | /// Size is a virtual address integer. | ||
| 2660 | const dbg_info_low_pc_reloc_index = 1; | ||
| 2661 | |||
| 2662 | /// The reloc offset for the line offset of a function from the previous function's line. | ||
| 2663 | /// It's a fixed-size 4-byte ULEB128. | ||
| 2664 | fn getRelocDbgLineOff(self: Elf) usize { | ||
| 2665 | return dbg_line_vaddr_reloc_index + self.ptrWidthBytes() + 1; | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | fn getRelocDbgFileIndex(self: Elf) usize { | ||
| 2669 | return self.getRelocDbgLineOff() + 5; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | fn getRelocDbgInfoSubprogramHighPC(self: Elf) u32 { | ||
| 2673 | return dbg_info_low_pc_reloc_index + self.ptrWidthBytes(); | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | fn dbgLineNeededHeaderBytes(self: Elf) u32 { | ||
| 2677 | const directory_entry_format_count = 1; | ||
| 2678 | const file_name_entry_format_count = 1; | ||
| 2679 | const directory_count = 1; | ||
| 2680 | const file_name_count = 1; | ||
| 2681 | return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + | ||
| 2682 | directory_count * 8 + file_name_count * 8 + | ||
| 2683 | // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like | ||
| 2684 | // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. | ||
| 2685 | self.base.options.root_pkg.root_src_dir_path.len + | ||
| 2686 | self.base.options.root_pkg.root_src_path.len); | ||
| 2687 | |||
| 2688 | } | ||
| 2689 | |||
| 2690 | fn dbgInfoNeededHeaderBytes(self: Elf) u32 { | ||
| 2691 | return 120; | ||
| 2692 | } | ||
| 2693 | |||
| 2694 | const min_nop_size = 2; | ||
| 2695 | |||
| 2696 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of | ||
| 2697 | /// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes | ||
| 2698 | /// are less than 126,976 bytes (if this limit is ever reached, this function can be | ||
| 2699 | /// improved to make more than one pwritev call, or the limit can be raised by a fixed | ||
| 2700 | /// amount by increasing the length of `vecs`). | ||
| 2701 | fn pwriteDbgLineNops( | ||
| 2702 | self: *Elf, | ||
| 2703 | prev_padding_size: usize, | ||
| 2704 | buf: []const u8, | ||
| 2705 | next_padding_size: usize, | ||
| 2706 | offset: usize, | ||
| 2707 | ) !void { | ||
| 2708 | const tracy = trace(@src()); | ||
| 2709 | defer tracy.end(); | ||
| 2710 | |||
| 2711 | const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; | ||
| 2712 | const three_byte_nop = [3]u8{DW.LNS_advance_pc, 0b1000_0000, 0}; | ||
| 2713 | var vecs: [32]std.os.iovec_const = undefined; | ||
| 2714 | var vec_index: usize = 0; | ||
| 2715 | { | ||
| 2716 | var padding_left = prev_padding_size; | ||
| 2717 | if (padding_left % 2 != 0) { | ||
| 2718 | vecs[vec_index] = .{ | ||
| 2719 | .iov_base = &three_byte_nop, | ||
| 2720 | .iov_len = three_byte_nop.len, | ||
| 2721 | }; | ||
| 2722 | vec_index += 1; | ||
| 2723 | padding_left -= three_byte_nop.len; | ||
| 2724 | } | ||
| 2725 | while (padding_left > page_of_nops.len) { | ||
| 2726 | vecs[vec_index] = .{ | ||
| 2727 | .iov_base = &page_of_nops, | ||
| 2728 | .iov_len = page_of_nops.len, | ||
| 2729 | }; | ||
| 2730 | vec_index += 1; | ||
| 2731 | padding_left -= page_of_nops.len; | ||
| 2732 | } | ||
| 2733 | if (padding_left > 0) { | ||
| 2734 | vecs[vec_index] = .{ | ||
| 2735 | .iov_base = &page_of_nops, | ||
| 2736 | .iov_len = padding_left, | ||
| 2737 | }; | ||
| 2738 | vec_index += 1; | ||
| 2739 | } | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | vecs[vec_index] = .{ | ||
| 2743 | .iov_base = buf.ptr, | ||
| 2744 | .iov_len = buf.len, | ||
| 2745 | }; | ||
| 2746 | vec_index += 1; | ||
| 2747 | |||
| 2748 | { | ||
| 2749 | var padding_left = next_padding_size; | ||
| 2750 | if (padding_left % 2 != 0) { | ||
| 2751 | vecs[vec_index] = .{ | ||
| 2752 | .iov_base = &three_byte_nop, | ||
| 2753 | .iov_len = three_byte_nop.len, | ||
| 2754 | }; | ||
| 2755 | vec_index += 1; | ||
| 2756 | padding_left -= three_byte_nop.len; | ||
| 2757 | } | ||
| 2758 | while (padding_left > page_of_nops.len) { | ||
| 2759 | vecs[vec_index] = .{ | ||
| 2760 | .iov_base = &page_of_nops, | ||
| 2761 | .iov_len = page_of_nops.len, | ||
| 2762 | }; | ||
| 2763 | vec_index += 1; | ||
| 2764 | padding_left -= page_of_nops.len; | ||
| 2765 | } | ||
| 2766 | if (padding_left > 0) { | ||
| 2767 | vecs[vec_index] = .{ | ||
| 2768 | .iov_base = &page_of_nops, | ||
| 2769 | .iov_len = padding_left, | ||
| 2770 | }; | ||
| 2771 | vec_index += 1; | ||
| 2772 | } | ||
| 2773 | } | ||
| 2774 | try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); | ||
| 2775 | } | ||
| 2776 | |||
| 2777 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of | ||
| 2778 | /// bytes of padding. | ||
| 2779 | fn pwriteDbgInfoNops( | ||
| 2780 | self: *Elf, | ||
| 2781 | prev_padding_size: usize, | ||
| 2782 | buf: []const u8, | ||
| 2783 | next_padding_size: usize, | ||
| 2784 | trailing_zero: bool, | ||
| 2785 | offset: usize, | ||
| 2786 | ) !void { | ||
| 2787 | const tracy = trace(@src()); | ||
| 2788 | defer tracy.end(); | ||
| 2789 | |||
| 2790 | const page_of_nops = [1]u8{abbrev_pad1} ** 4096; | ||
| 2791 | var vecs: [32]std.os.iovec_const = undefined; | ||
| 2792 | var vec_index: usize = 0; | ||
| 2793 | { | ||
| 2794 | var padding_left = prev_padding_size; | ||
| 2795 | while (padding_left > page_of_nops.len) { | ||
| 2796 | vecs[vec_index] = .{ | ||
| 2797 | .iov_base = &page_of_nops, | ||
| 2798 | .iov_len = page_of_nops.len, | ||
| 2799 | }; | ||
| 2800 | vec_index += 1; | ||
| 2801 | padding_left -= page_of_nops.len; | ||
| 2802 | } | ||
| 2803 | if (padding_left > 0) { | ||
| 2804 | vecs[vec_index] = .{ | ||
| 2805 | .iov_base = &page_of_nops, | ||
| 2806 | .iov_len = padding_left, | ||
| 2807 | }; | ||
| 2808 | vec_index += 1; | ||
| 2809 | } | ||
| 2810 | } | ||
| 2811 | |||
| 2812 | vecs[vec_index] = .{ | ||
| 2813 | .iov_base = buf.ptr, | ||
| 2814 | .iov_len = buf.len, | ||
| 2815 | }; | ||
| 2816 | vec_index += 1; | ||
| 2817 | |||
| 2818 | { | ||
| 2819 | var padding_left = next_padding_size; | ||
| 2820 | while (padding_left > page_of_nops.len) { | ||
| 2821 | vecs[vec_index] = .{ | ||
| 2822 | .iov_base = &page_of_nops, | ||
| 2823 | .iov_len = page_of_nops.len, | ||
| 2824 | }; | ||
| 2825 | vec_index += 1; | ||
| 2826 | padding_left -= page_of_nops.len; | ||
| 2827 | } | ||
| 2828 | if (padding_left > 0) { | ||
| 2829 | vecs[vec_index] = .{ | ||
| 2830 | .iov_base = &page_of_nops, | ||
| 2831 | .iov_len = padding_left, | ||
| 2832 | }; | ||
| 2833 | vec_index += 1; | ||
| 2834 | } | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | if (trailing_zero) { | ||
| 2838 | var zbuf = [1]u8{0}; | ||
| 2839 | vecs[vec_index] = .{ | ||
| 2840 | .iov_base = &zbuf, | ||
| 2841 | .iov_len = zbuf.len, | ||
| 2842 | }; | ||
| 2843 | vec_index += 1; | ||
| 2844 | } | ||
| 2845 | |||
| 2846 | try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); | ||
| 2847 | } | ||
| 2848 | |||
| 2849 | }; | ||
| 2850 | |||
| 2851 | pub const MachO = @import("link/MachO.zig"); | 239 | pub const MachO = @import("link/MachO.zig"); |
| 2852 | const Wasm = @import("link/Wasm.zig"); | 240 | pub const Wasm = @import("link/Wasm.zig"); |
| 2853 | }; | 241 | }; |
| 2854 | 242 | ||
| 2855 | /// Saturating multiplication | ||
| 2856 | fn satMul(a: anytype, b: anytype) @TypeOf(a, b) { | ||
| 2857 | const T = @TypeOf(a, b); | ||
| 2858 | return std.math.mul(T, a, b) catch std.math.maxInt(T); | ||
| 2859 | } | ||
| 2860 | |||
| 2861 | fn bswapAllFields(comptime S: type, ptr: *S) void { | ||
| 2862 | @panic("TODO implement bswapAllFields"); | ||
| 2863 | } | ||
| 2864 | |||
| 2865 | fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { | ||
| 2866 | return .{ | ||
| 2867 | .p_type = phdr.p_type, | ||
| 2868 | .p_flags = phdr.p_flags, | ||
| 2869 | .p_offset = @intCast(u32, phdr.p_offset), | ||
| 2870 | .p_vaddr = @intCast(u32, phdr.p_vaddr), | ||
| 2871 | .p_paddr = @intCast(u32, phdr.p_paddr), | ||
| 2872 | .p_filesz = @intCast(u32, phdr.p_filesz), | ||
| 2873 | .p_memsz = @intCast(u32, phdr.p_memsz), | ||
| 2874 | .p_align = @intCast(u32, phdr.p_align), | ||
| 2875 | }; | ||
| 2876 | } | ||
| 2877 | |||
| 2878 | fn sectHeaderTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { | ||
| 2879 | return .{ | ||
| 2880 | .sh_name = shdr.sh_name, | ||
| 2881 | .sh_type = shdr.sh_type, | ||
| 2882 | .sh_flags = @intCast(u32, shdr.sh_flags), | ||
| 2883 | .sh_addr = @intCast(u32, shdr.sh_addr), | ||
| 2884 | .sh_offset = @intCast(u32, shdr.sh_offset), | ||
| 2885 | .sh_size = @intCast(u32, shdr.sh_size), | ||
| 2886 | .sh_link = shdr.sh_link, | ||
| 2887 | .sh_info = shdr.sh_info, | ||
| 2888 | .sh_addralign = @intCast(u32, shdr.sh_addralign), | ||
| 2889 | .sh_entsize = @intCast(u32, shdr.sh_entsize), | ||
| 2890 | }; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | pub fn determineMode(options: Options) fs.File.Mode { | 243 | pub fn determineMode(options: Options) fs.File.Mode { |
| 2894 | // On common systems with a 0o022 umask, 0o777 will still result in a file created | 244 | // On common systems with a 0o022 umask, 0o777 will still result in a file created |
| 2895 | // with 0o755 permissions, but it works appropriately if the system is configured | 245 | // with 0o755 permissions, but it works appropriately if the system is configured |
src-self-hosted/link/C.zig created+101| ... | @@ -0,0 +1,101 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const Allocator = std.mem.Allocator; | ||
| 5 | const Module = @import("../Module.zig"); | ||
| 6 | const fs = std.fs; | ||
| 7 | const codegen = @import("../codegen/c.zig"); | ||
| 8 | const link = @import("../link.zig"); | ||
| 9 | const File = link.File; | ||
| 10 | const C = @This(); | ||
| 11 | |||
| 12 | pub const base_tag: File.Tag = .c; | ||
| 13 | |||
| 14 | base: File, | ||
| 15 | |||
| 16 | header: std.ArrayList(u8), | ||
| 17 | constants: std.ArrayList(u8), | ||
| 18 | main: std.ArrayList(u8), | ||
| 19 | |||
| 20 | called: std.StringHashMap(void), | ||
| 21 | need_stddef: bool = false, | ||
| 22 | need_stdint: bool = false, | ||
| 23 | error_msg: *Module.ErrorMsg = undefined, | ||
| 24 | |||
| 25 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File { | ||
| 26 | assert(options.object_format == .c); | ||
| 27 | |||
| 28 | const file = try dir.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); | ||
| 29 | errdefer file.close(); | ||
| 30 | |||
| 31 | var c_file = try allocator.create(C); | ||
| 32 | errdefer allocator.destroy(c_file); | ||
| 33 | |||
| 34 | c_file.* = C{ | ||
| 35 | .base = .{ | ||
| 36 | .tag = .c, | ||
| 37 | .options = options, | ||
| 38 | .file = file, | ||
| 39 | .allocator = allocator, | ||
| 40 | }, | ||
| 41 | .main = std.ArrayList(u8).init(allocator), | ||
| 42 | .header = std.ArrayList(u8).init(allocator), | ||
| 43 | .constants = std.ArrayList(u8).init(allocator), | ||
| 44 | .called = std.StringHashMap(void).init(allocator), | ||
| 45 | }; | ||
| 46 | |||
| 47 | return &c_file.base; | ||
| 48 | } | ||
| 49 | |||
| 50 | pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | ||
| 51 | self.error_msg = try Module.ErrorMsg.create(self.base.allocator, src, format, args); | ||
| 52 | return error.AnalysisFail; | ||
| 53 | } | ||
| 54 | |||
| 55 | pub fn deinit(self: *C) void { | ||
| 56 | self.main.deinit(); | ||
| 57 | self.header.deinit(); | ||
| 58 | self.constants.deinit(); | ||
| 59 | self.called.deinit(); | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | ||
| 63 | codegen.generate(self, decl) catch |err| { | ||
| 64 | if (err == error.AnalysisFail) { | ||
| 65 | try module.failed_decls.put(module.gpa, decl, self.error_msg); | ||
| 66 | } | ||
| 67 | return err; | ||
| 68 | }; | ||
| 69 | } | ||
| 70 | |||
| 71 | pub fn flush(self: *C, module: *Module) !void { | ||
| 72 | const writer = self.base.file.?.writer(); | ||
| 73 | try writer.writeAll(@embedFile("cbe.h")); | ||
| 74 | var includes = false; | ||
| 75 | if (self.need_stddef) { | ||
| 76 | try writer.writeAll("#include <stddef.h>\n"); | ||
| 77 | includes = true; | ||
| 78 | } | ||
| 79 | if (self.need_stdint) { | ||
| 80 | try writer.writeAll("#include <stdint.h>\n"); | ||
| 81 | includes = true; | ||
| 82 | } | ||
| 83 | if (includes) { | ||
| 84 | try writer.writeByte('\n'); | ||
| 85 | } | ||
| 86 | if (self.header.items.len > 0) { | ||
| 87 | try writer.print("{}\n", .{self.header.items}); | ||
| 88 | } | ||
| 89 | if (self.constants.items.len > 0) { | ||
| 90 | try writer.print("{}\n", .{self.constants.items}); | ||
| 91 | } | ||
| 92 | if (self.main.items.len > 1) { | ||
| 93 | const last_two = self.main.items[self.main.items.len - 2 ..]; | ||
| 94 | if (std.mem.eql(u8, last_two, "\n\n")) { | ||
| 95 | self.main.items.len -= 1; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | try writer.writeAll(self.main.items); | ||
| 99 | self.base.file.?.close(); | ||
| 100 | self.base.file = null; | ||
| 101 | } | ||
src-self-hosted/link/Elf.zig created+2583| ... | @@ -0,0 +1,2583 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const assert = std.debug.assert; | ||
| 4 | const Allocator = std.mem.Allocator; | ||
| 5 | const ir = @import("../ir.zig"); | ||
| 6 | const Module = @import("../Module.zig"); | ||
| 7 | const fs = std.fs; | ||
| 8 | const elf = std.elf; | ||
| 9 | const codegen = @import("../codegen.zig"); | ||
| 10 | const log = std.log.scoped(.link); | ||
| 11 | const DW = std.dwarf; | ||
| 12 | const trace = @import("../tracy.zig").trace; | ||
| 13 | const leb128 = std.debug.leb; | ||
| 14 | const Package = @import("../Package.zig"); | ||
| 15 | const Value = @import("../value.zig").Value; | ||
| 16 | const Type = @import("../type.zig").Type; | ||
| 17 | const build_options = @import("build_options"); | ||
| 18 | const link = @import("../link.zig"); | ||
| 19 | const File = link.File; | ||
| 20 | const Elf = @This(); | ||
| 21 | |||
| 22 | const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version; | ||
| 23 | const default_entry_addr = 0x8000000; | ||
| 24 | |||
| 25 | // TODO Turn back on zig fmt when https://github.com/ziglang/zig/issues/5948 is implemented. | ||
| 26 | // zig fmt: off | ||
| 27 | |||
| 28 | pub const base_tag: File.Tag = .elf; | ||
| 29 | |||
| 30 | base: File, | ||
| 31 | |||
| 32 | ptr_width: enum { p32, p64 }, | ||
| 33 | |||
| 34 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 35 | /// Same order as in the file. | ||
| 36 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, | ||
| 37 | shdr_table_offset: ?u64 = null, | ||
| 38 | |||
| 39 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 40 | /// Same order as in the file. | ||
| 41 | program_headers: std.ArrayListUnmanaged(elf.Elf64_Phdr) = std.ArrayListUnmanaged(elf.Elf64_Phdr){}, | ||
| 42 | phdr_table_offset: ?u64 = null, | ||
| 43 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | ||
| 44 | phdr_load_re_index: ?u16 = null, | ||
| 45 | /// The index into the program headers of the global offset table. | ||
| 46 | /// It needs PT_LOAD and Read flags. | ||
| 47 | phdr_got_index: ?u16 = null, | ||
| 48 | entry_addr: ?u64 = null, | ||
| 49 | |||
| 50 | debug_strtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | ||
| 51 | shstrtab: std.ArrayListUnmanaged(u8) = std.ArrayListUnmanaged(u8){}, | ||
| 52 | shstrtab_index: ?u16 = null, | ||
| 53 | |||
| 54 | text_section_index: ?u16 = null, | ||
| 55 | symtab_section_index: ?u16 = null, | ||
| 56 | got_section_index: ?u16 = null, | ||
| 57 | debug_info_section_index: ?u16 = null, | ||
| 58 | debug_abbrev_section_index: ?u16 = null, | ||
| 59 | debug_str_section_index: ?u16 = null, | ||
| 60 | debug_aranges_section_index: ?u16 = null, | ||
| 61 | debug_line_section_index: ?u16 = null, | ||
| 62 | |||
| 63 | debug_abbrev_table_offset: ?u64 = null, | ||
| 64 | |||
| 65 | /// The same order as in the file. ELF requires global symbols to all be after the | ||
| 66 | /// local symbols, they cannot be mixed. So we must buffer all the global symbols and | ||
| 67 | /// write them at the end. These are only the local symbols. The length of this array | ||
| 68 | /// is the value used for sh_info in the .symtab section. | ||
| 69 | local_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | ||
| 70 | global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | ||
| 71 | |||
| 72 | local_symbol_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 73 | global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 74 | offset_table_free_list: std.ArrayListUnmanaged(u32) = .{}, | ||
| 75 | |||
| 76 | /// Same order as in the file. The value is the absolute vaddr value. | ||
| 77 | /// If the vaddr of the executable program header changes, the entire | ||
| 78 | /// offset table needs to be rewritten. | ||
| 79 | offset_table: std.ArrayListUnmanaged(u64) = .{}, | ||
| 80 | |||
| 81 | phdr_table_dirty: bool = false, | ||
| 82 | shdr_table_dirty: bool = false, | ||
| 83 | shstrtab_dirty: bool = false, | ||
| 84 | debug_strtab_dirty: bool = false, | ||
| 85 | offset_table_count_dirty: bool = false, | ||
| 86 | debug_abbrev_section_dirty: bool = false, | ||
| 87 | debug_aranges_section_dirty: bool = false, | ||
| 88 | |||
| 89 | debug_info_header_dirty: bool = false, | ||
| 90 | debug_line_header_dirty: bool = false, | ||
| 91 | |||
| 92 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | ||
| 93 | |||
| 94 | /// A list of text blocks that have surplus capacity. This list can have false | ||
| 95 | /// positives, as functions grow and shrink over time, only sometimes being added | ||
| 96 | /// or removed from the freelist. | ||
| 97 | /// | ||
| 98 | /// A text block has surplus capacity when its overcapacity value is greater than | ||
| 99 | /// minimum_text_block_size * alloc_num / alloc_den. That is, when it has so | ||
| 100 | /// much extra capacity, that we could fit a small new symbol in it, itself with | ||
| 101 | /// ideal_capacity or more. | ||
| 102 | /// | ||
| 103 | /// Ideal capacity is defined by size * alloc_num / alloc_den. | ||
| 104 | /// | ||
| 105 | /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that | ||
| 106 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | ||
| 107 | /// allocate a fresh text block, which will have ideal capacity, and then grow it | ||
| 108 | /// by 1 byte. It will then have -1 overcapacity. | ||
| 109 | text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, | ||
| 110 | last_text_block: ?*TextBlock = null, | ||
| 111 | |||
| 112 | /// A list of `SrcFn` whose Line Number Programs have surplus capacity. | ||
| 113 | /// This is the same concept as `text_block_free_list`; see those doc comments. | ||
| 114 | dbg_line_fn_free_list: std.AutoHashMapUnmanaged(*SrcFn, void) = .{}, | ||
| 115 | dbg_line_fn_first: ?*SrcFn = null, | ||
| 116 | dbg_line_fn_last: ?*SrcFn = null, | ||
| 117 | |||
| 118 | /// A list of `TextBlock` whose corresponding .debug_info tags have surplus capacity. | ||
| 119 | /// This is the same concept as `text_block_free_list`; see those doc comments. | ||
| 120 | dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{}, | ||
| 121 | dbg_info_decl_first: ?*TextBlock = null, | ||
| 122 | dbg_info_decl_last: ?*TextBlock = null, | ||
| 123 | |||
| 124 | /// `alloc_num / alloc_den` is the factor of padding when allocating. | ||
| 125 | const alloc_num = 4; | ||
| 126 | const alloc_den = 3; | ||
| 127 | |||
| 128 | /// In order for a slice of bytes to be considered eligible to keep metadata pointing at | ||
| 129 | /// it as a possible place to put new symbols, it must have enough room for this many bytes | ||
| 130 | /// (plus extra for reserved capacity). | ||
| 131 | const minimum_text_block_size = 64; | ||
| 132 | const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den; | ||
| 133 | |||
| 134 | pub const TextBlock = struct { | ||
| 135 | /// Each decl always gets a local symbol with the fully qualified name. | ||
| 136 | /// The vaddr and size are found here directly. | ||
| 137 | /// The file offset is found by computing the vaddr offset from the section vaddr | ||
| 138 | /// the symbol references, and adding that to the file offset of the section. | ||
| 139 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | ||
| 140 | /// offset table entry. | ||
| 141 | local_sym_index: u32, | ||
| 142 | /// This field is undefined for symbols with size = 0. | ||
| 143 | offset_table_index: u32, | ||
| 144 | /// Points to the previous and next neighbors, based on the `text_offset`. | ||
| 145 | /// This can be used to find, for example, the capacity of this `TextBlock`. | ||
| 146 | prev: ?*TextBlock, | ||
| 147 | next: ?*TextBlock, | ||
| 148 | |||
| 149 | /// Previous/next linked list pointers. This value is `next ^ prev`. | ||
| 150 | /// This is the linked list node for this Decl's corresponding .debug_info tag. | ||
| 151 | dbg_info_prev: ?*TextBlock, | ||
| 152 | dbg_info_next: ?*TextBlock, | ||
| 153 | /// Offset into .debug_info pointing to the tag for this Decl. | ||
| 154 | dbg_info_off: u32, | ||
| 155 | /// Size of the .debug_info tag for this Decl, not including padding. | ||
| 156 | dbg_info_len: u32, | ||
| 157 | |||
| 158 | pub const empty = TextBlock{ | ||
| 159 | .local_sym_index = 0, | ||
| 160 | .offset_table_index = undefined, | ||
| 161 | .prev = null, | ||
| 162 | .next = null, | ||
| 163 | .dbg_info_prev = null, | ||
| 164 | .dbg_info_next = null, | ||
| 165 | .dbg_info_off = undefined, | ||
| 166 | .dbg_info_len = undefined, | ||
| 167 | }; | ||
| 168 | |||
| 169 | /// Returns how much room there is to grow in virtual address space. | ||
| 170 | /// File offset relocation happens transparently, so it is not included in | ||
| 171 | /// this calculation. | ||
| 172 | fn capacity(self: TextBlock, elf_file: Elf) u64 { | ||
| 173 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | ||
| 174 | if (self.next) |next| { | ||
| 175 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | ||
| 176 | return next_sym.st_value - self_sym.st_value; | ||
| 177 | } else { | ||
| 178 | // We are the last block. The capacity is limited only by virtual address space. | ||
| 179 | return std.math.maxInt(u32) - self_sym.st_value; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | fn freeListEligible(self: TextBlock, elf_file: Elf) bool { | ||
| 184 | // No need to keep a free list node for the last block. | ||
| 185 | const next = self.next orelse return false; | ||
| 186 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; | ||
| 187 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; | ||
| 188 | const cap = next_sym.st_value - self_sym.st_value; | ||
| 189 | const ideal_cap = self_sym.st_size * alloc_num / alloc_den; | ||
| 190 | if (cap <= ideal_cap) return false; | ||
| 191 | const surplus = cap - ideal_cap; | ||
| 192 | return surplus >= min_text_capacity; | ||
| 193 | } | ||
| 194 | }; | ||
| 195 | |||
| 196 | pub const Export = struct { | ||
| 197 | sym_index: ?u32 = null, | ||
| 198 | }; | ||
| 199 | |||
| 200 | pub const SrcFn = struct { | ||
| 201 | /// Offset from the beginning of the Debug Line Program header that contains this function. | ||
| 202 | off: u32, | ||
| 203 | /// Size of the line number program component belonging to this function, not | ||
| 204 | /// including padding. | ||
| 205 | len: u32, | ||
| 206 | |||
| 207 | /// Points to the previous and next neighbors, based on the offset from .debug_line. | ||
| 208 | /// This can be used to find, for example, the capacity of this `SrcFn`. | ||
| 209 | prev: ?*SrcFn, | ||
| 210 | next: ?*SrcFn, | ||
| 211 | |||
| 212 | pub const empty: SrcFn = .{ | ||
| 213 | .off = 0, | ||
| 214 | .len = 0, | ||
| 215 | .prev = null, | ||
| 216 | .next = null, | ||
| 217 | }; | ||
| 218 | }; | ||
| 219 | |||
| 220 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File { | ||
| 221 | assert(options.object_format == .elf); | ||
| 222 | |||
| 223 | const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) }); | ||
| 224 | errdefer file.close(); | ||
| 225 | |||
| 226 | var elf_file = try allocator.create(Elf); | ||
| 227 | errdefer allocator.destroy(elf_file); | ||
| 228 | |||
| 229 | elf_file.* = openFile(allocator, file, options) catch |err| switch (err) { | ||
| 230 | error.IncrFailed => try createFile(allocator, file, options), | ||
| 231 | else => |e| return e, | ||
| 232 | }; | ||
| 233 | |||
| 234 | return &elf_file.base; | ||
| 235 | } | ||
| 236 | |||
| 237 | /// Returns error.IncrFailed if incremental update could not be performed. | ||
| 238 | fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { | ||
| 239 | switch (options.output_mode) { | ||
| 240 | .Exe => {}, | ||
| 241 | .Obj => {}, | ||
| 242 | .Lib => return error.IncrFailed, | ||
| 243 | } | ||
| 244 | var self: Elf = .{ | ||
| 245 | .base = .{ | ||
| 246 | .file = file, | ||
| 247 | .tag = .elf, | ||
| 248 | .options = options, | ||
| 249 | .allocator = allocator, | ||
| 250 | }, | ||
| 251 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 252 | 32 => .p32, | ||
| 253 | 64 => .p64, | ||
| 254 | else => return error.UnsupportedELFArchitecture, | ||
| 255 | }, | ||
| 256 | }; | ||
| 257 | errdefer self.deinit(); | ||
| 258 | |||
| 259 | // TODO implement reading the elf file | ||
| 260 | return error.IncrFailed; | ||
| 261 | //try self.populateMissingMetadata(); | ||
| 262 | //return self; | ||
| 263 | } | ||
| 264 | |||
| 265 | /// Truncates the existing file contents and overwrites the contents. | ||
| 266 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | ||
| 267 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Elf { | ||
| 268 | switch (options.output_mode) { | ||
| 269 | .Exe => {}, | ||
| 270 | .Obj => {}, | ||
| 271 | .Lib => return error.TODOImplementWritingLibFiles, | ||
| 272 | } | ||
| 273 | var self: Elf = .{ | ||
| 274 | .base = .{ | ||
| 275 | .tag = .elf, | ||
| 276 | .options = options, | ||
| 277 | .allocator = allocator, | ||
| 278 | .file = file, | ||
| 279 | }, | ||
| 280 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | ||
| 281 | 32 => .p32, | ||
| 282 | 64 => .p64, | ||
| 283 | else => return error.UnsupportedELFArchitecture, | ||
| 284 | }, | ||
| 285 | .shdr_table_dirty = true, | ||
| 286 | }; | ||
| 287 | errdefer self.deinit(); | ||
| 288 | |||
| 289 | // Index 0 is always a null symbol. | ||
| 290 | try self.local_symbols.append(allocator, .{ | ||
| 291 | .st_name = 0, | ||
| 292 | .st_info = 0, | ||
| 293 | .st_other = 0, | ||
| 294 | .st_shndx = 0, | ||
| 295 | .st_value = 0, | ||
| 296 | .st_size = 0, | ||
| 297 | }); | ||
| 298 | |||
| 299 | // There must always be a null section in index 0 | ||
| 300 | try self.sections.append(allocator, .{ | ||
| 301 | .sh_name = 0, | ||
| 302 | .sh_type = elf.SHT_NULL, | ||
| 303 | .sh_flags = 0, | ||
| 304 | .sh_addr = 0, | ||
| 305 | .sh_offset = 0, | ||
| 306 | .sh_size = 0, | ||
| 307 | .sh_link = 0, | ||
| 308 | .sh_info = 0, | ||
| 309 | .sh_addralign = 0, | ||
| 310 | .sh_entsize = 0, | ||
| 311 | }); | ||
| 312 | |||
| 313 | try self.populateMissingMetadata(); | ||
| 314 | |||
| 315 | return self; | ||
| 316 | } | ||
| 317 | |||
| 318 | pub fn deinit(self: *Elf) void { | ||
| 319 | self.sections.deinit(self.base.allocator); | ||
| 320 | self.program_headers.deinit(self.base.allocator); | ||
| 321 | self.shstrtab.deinit(self.base.allocator); | ||
| 322 | self.debug_strtab.deinit(self.base.allocator); | ||
| 323 | self.local_symbols.deinit(self.base.allocator); | ||
| 324 | self.global_symbols.deinit(self.base.allocator); | ||
| 325 | self.global_symbol_free_list.deinit(self.base.allocator); | ||
| 326 | self.local_symbol_free_list.deinit(self.base.allocator); | ||
| 327 | self.offset_table_free_list.deinit(self.base.allocator); | ||
| 328 | self.text_block_free_list.deinit(self.base.allocator); | ||
| 329 | self.dbg_line_fn_free_list.deinit(self.base.allocator); | ||
| 330 | self.dbg_info_decl_free_list.deinit(self.base.allocator); | ||
| 331 | self.offset_table.deinit(self.base.allocator); | ||
| 332 | } | ||
| 333 | |||
| 334 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { | ||
| 335 | assert(decl.link.elf.local_sym_index != 0); | ||
| 336 | return self.local_symbols.items[decl.link.elf.local_sym_index].st_value; | ||
| 337 | } | ||
| 338 | |||
| 339 | fn getDebugLineProgramOff(self: Elf) u32 { | ||
| 340 | return self.dbg_line_fn_first.?.off; | ||
| 341 | } | ||
| 342 | |||
| 343 | fn getDebugLineProgramEnd(self: Elf) u32 { | ||
| 344 | return self.dbg_line_fn_last.?.off + self.dbg_line_fn_last.?.len; | ||
| 345 | } | ||
| 346 | |||
| 347 | /// Returns end pos of collision, if any. | ||
| 348 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { | ||
| 349 | const small_ptr = self.base.options.target.cpu.arch.ptrBitWidth() == 32; | ||
| 350 | const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); | ||
| 351 | if (start < ehdr_size) | ||
| 352 | return ehdr_size; | ||
| 353 | |||
| 354 | const end = start + satMul(size, alloc_num) / alloc_den; | ||
| 355 | |||
| 356 | if (self.shdr_table_offset) |off| { | ||
| 357 | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); | ||
| 358 | const tight_size = self.sections.items.len * shdr_size; | ||
| 359 | const increased_size = satMul(tight_size, alloc_num) / alloc_den; | ||
| 360 | const test_end = off + increased_size; | ||
| 361 | if (end > off and start < test_end) { | ||
| 362 | return test_end; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | if (self.phdr_table_offset) |off| { | ||
| 367 | const phdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Phdr) else @sizeOf(elf.Elf64_Phdr); | ||
| 368 | const tight_size = self.sections.items.len * phdr_size; | ||
| 369 | const increased_size = satMul(tight_size, alloc_num) / alloc_den; | ||
| 370 | const test_end = off + increased_size; | ||
| 371 | if (end > off and start < test_end) { | ||
| 372 | return test_end; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | for (self.sections.items) |section| { | ||
| 377 | const increased_size = satMul(section.sh_size, alloc_num) / alloc_den; | ||
| 378 | const test_end = section.sh_offset + increased_size; | ||
| 379 | if (end > section.sh_offset and start < test_end) { | ||
| 380 | return test_end; | ||
| 381 | } | ||
| 382 | } | ||
| 383 | for (self.program_headers.items) |program_header| { | ||
| 384 | const increased_size = satMul(program_header.p_filesz, alloc_num) / alloc_den; | ||
| 385 | const test_end = program_header.p_offset + increased_size; | ||
| 386 | if (end > program_header.p_offset and start < test_end) { | ||
| 387 | return test_end; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | return null; | ||
| 391 | } | ||
| 392 | |||
| 393 | fn allocatedSize(self: *Elf, start: u64) u64 { | ||
| 394 | if (start == 0) | ||
| 395 | return 0; | ||
| 396 | var min_pos: u64 = std.math.maxInt(u64); | ||
| 397 | if (self.shdr_table_offset) |off| { | ||
| 398 | if (off > start and off < min_pos) min_pos = off; | ||
| 399 | } | ||
| 400 | if (self.phdr_table_offset) |off| { | ||
| 401 | if (off > start and off < min_pos) min_pos = off; | ||
| 402 | } | ||
| 403 | for (self.sections.items) |section| { | ||
| 404 | if (section.sh_offset <= start) continue; | ||
| 405 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; | ||
| 406 | } | ||
| 407 | for (self.program_headers.items) |program_header| { | ||
| 408 | if (program_header.p_offset <= start) continue; | ||
| 409 | if (program_header.p_offset < min_pos) min_pos = program_header.p_offset; | ||
| 410 | } | ||
| 411 | return min_pos - start; | ||
| 412 | } | ||
| 413 | |||
| 414 | fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u16) u64 { | ||
| 415 | var start: u64 = 0; | ||
| 416 | while (self.detectAllocCollision(start, object_size)) |item_end| { | ||
| 417 | start = mem.alignForwardGeneric(u64, item_end, min_alignment); | ||
| 418 | } | ||
| 419 | return start; | ||
| 420 | } | ||
| 421 | |||
| 422 | /// TODO Improve this to use a table. | ||
| 423 | fn makeString(self: *Elf, bytes: []const u8) !u32 { | ||
| 424 | try self.shstrtab.ensureCapacity(self.base.allocator, self.shstrtab.items.len + bytes.len + 1); | ||
| 425 | const result = self.shstrtab.items.len; | ||
| 426 | self.shstrtab.appendSliceAssumeCapacity(bytes); | ||
| 427 | self.shstrtab.appendAssumeCapacity(0); | ||
| 428 | return @intCast(u32, result); | ||
| 429 | } | ||
| 430 | |||
| 431 | /// TODO Improve this to use a table. | ||
| 432 | fn makeDebugString(self: *Elf, bytes: []const u8) !u32 { | ||
| 433 | try self.debug_strtab.ensureCapacity(self.base.allocator, self.debug_strtab.items.len + bytes.len + 1); | ||
| 434 | const result = self.debug_strtab.items.len; | ||
| 435 | self.debug_strtab.appendSliceAssumeCapacity(bytes); | ||
| 436 | self.debug_strtab.appendAssumeCapacity(0); | ||
| 437 | return @intCast(u32, result); | ||
| 438 | } | ||
| 439 | |||
| 440 | fn getString(self: *Elf, str_off: u32) []const u8 { | ||
| 441 | assert(str_off < self.shstrtab.items.len); | ||
| 442 | return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off)); | ||
| 443 | } | ||
| 444 | |||
| 445 | fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { | ||
| 446 | const existing_name = self.getString(old_str_off); | ||
| 447 | if (mem.eql(u8, existing_name, new_name)) { | ||
| 448 | return old_str_off; | ||
| 449 | } | ||
| 450 | return self.makeString(new_name); | ||
| 451 | } | ||
| 452 | |||
| 453 | pub fn populateMissingMetadata(self: *Elf) !void { | ||
| 454 | const small_ptr = switch (self.ptr_width) { | ||
| 455 | .p32 => true, | ||
| 456 | .p64 => false, | ||
| 457 | }; | ||
| 458 | const ptr_size: u8 = self.ptrWidthBytes(); | ||
| 459 | if (self.phdr_load_re_index == null) { | ||
| 460 | self.phdr_load_re_index = @intCast(u16, self.program_headers.items.len); | ||
| 461 | const file_size = self.base.options.program_code_size_hint; | ||
| 462 | const p_align = 0x1000; | ||
| 463 | const off = self.findFreeSpace(file_size, p_align); | ||
| 464 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 465 | try self.program_headers.append(self.base.allocator, .{ | ||
| 466 | .p_type = elf.PT_LOAD, | ||
| 467 | .p_offset = off, | ||
| 468 | .p_filesz = file_size, | ||
| 469 | .p_vaddr = default_entry_addr, | ||
| 470 | .p_paddr = default_entry_addr, | ||
| 471 | .p_memsz = file_size, | ||
| 472 | .p_align = p_align, | ||
| 473 | .p_flags = elf.PF_X | elf.PF_R, | ||
| 474 | }); | ||
| 475 | self.entry_addr = null; | ||
| 476 | self.phdr_table_dirty = true; | ||
| 477 | } | ||
| 478 | if (self.phdr_got_index == null) { | ||
| 479 | self.phdr_got_index = @intCast(u16, self.program_headers.items.len); | ||
| 480 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; | ||
| 481 | // We really only need ptr alignment but since we are using PROGBITS, linux requires | ||
| 482 | // page align. | ||
| 483 | const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size); | ||
| 484 | const off = self.findFreeSpace(file_size, p_align); | ||
| 485 | log.debug("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 486 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. | ||
| 487 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something | ||
| 488 | // else in virtual memory. | ||
| 489 | const default_got_addr = if (ptr_size == 2) @as(u32, 0x8000) else 0x4000000; | ||
| 490 | try self.program_headers.append(self.base.allocator, .{ | ||
| 491 | .p_type = elf.PT_LOAD, | ||
| 492 | .p_offset = off, | ||
| 493 | .p_filesz = file_size, | ||
| 494 | .p_vaddr = default_got_addr, | ||
| 495 | .p_paddr = default_got_addr, | ||
| 496 | .p_memsz = file_size, | ||
| 497 | .p_align = p_align, | ||
| 498 | .p_flags = elf.PF_R, | ||
| 499 | }); | ||
| 500 | self.phdr_table_dirty = true; | ||
| 501 | } | ||
| 502 | if (self.shstrtab_index == null) { | ||
| 503 | self.shstrtab_index = @intCast(u16, self.sections.items.len); | ||
| 504 | assert(self.shstrtab.items.len == 0); | ||
| 505 | try self.shstrtab.append(self.base.allocator, 0); // need a 0 at position 0 | ||
| 506 | const off = self.findFreeSpace(self.shstrtab.items.len, 1); | ||
| 507 | log.debug("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len }); | ||
| 508 | try self.sections.append(self.base.allocator, .{ | ||
| 509 | .sh_name = try self.makeString(".shstrtab"), | ||
| 510 | .sh_type = elf.SHT_STRTAB, | ||
| 511 | .sh_flags = 0, | ||
| 512 | .sh_addr = 0, | ||
| 513 | .sh_offset = off, | ||
| 514 | .sh_size = self.shstrtab.items.len, | ||
| 515 | .sh_link = 0, | ||
| 516 | .sh_info = 0, | ||
| 517 | .sh_addralign = 1, | ||
| 518 | .sh_entsize = 0, | ||
| 519 | }); | ||
| 520 | self.shstrtab_dirty = true; | ||
| 521 | self.shdr_table_dirty = true; | ||
| 522 | } | ||
| 523 | if (self.text_section_index == null) { | ||
| 524 | self.text_section_index = @intCast(u16, self.sections.items.len); | ||
| 525 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 526 | |||
| 527 | try self.sections.append(self.base.allocator, .{ | ||
| 528 | .sh_name = try self.makeString(".text"), | ||
| 529 | .sh_type = elf.SHT_PROGBITS, | ||
| 530 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 531 | .sh_addr = phdr.p_vaddr, | ||
| 532 | .sh_offset = phdr.p_offset, | ||
| 533 | .sh_size = phdr.p_filesz, | ||
| 534 | .sh_link = 0, | ||
| 535 | .sh_info = 0, | ||
| 536 | .sh_addralign = phdr.p_align, | ||
| 537 | .sh_entsize = 0, | ||
| 538 | }); | ||
| 539 | self.shdr_table_dirty = true; | ||
| 540 | } | ||
| 541 | if (self.got_section_index == null) { | ||
| 542 | self.got_section_index = @intCast(u16, self.sections.items.len); | ||
| 543 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | ||
| 544 | |||
| 545 | try self.sections.append(self.base.allocator, .{ | ||
| 546 | .sh_name = try self.makeString(".got"), | ||
| 547 | .sh_type = elf.SHT_PROGBITS, | ||
| 548 | .sh_flags = elf.SHF_ALLOC, | ||
| 549 | .sh_addr = phdr.p_vaddr, | ||
| 550 | .sh_offset = phdr.p_offset, | ||
| 551 | .sh_size = phdr.p_filesz, | ||
| 552 | .sh_link = 0, | ||
| 553 | .sh_info = 0, | ||
| 554 | .sh_addralign = phdr.p_align, | ||
| 555 | .sh_entsize = 0, | ||
| 556 | }); | ||
| 557 | self.shdr_table_dirty = true; | ||
| 558 | } | ||
| 559 | if (self.symtab_section_index == null) { | ||
| 560 | self.symtab_section_index = @intCast(u16, self.sections.items.len); | ||
| 561 | const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym); | ||
| 562 | const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym); | ||
| 563 | const file_size = self.base.options.symbol_count_hint * each_size; | ||
| 564 | const off = self.findFreeSpace(file_size, min_align); | ||
| 565 | log.debug("found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | ||
| 566 | |||
| 567 | try self.sections.append(self.base.allocator, .{ | ||
| 568 | .sh_name = try self.makeString(".symtab"), | ||
| 569 | .sh_type = elf.SHT_SYMTAB, | ||
| 570 | .sh_flags = 0, | ||
| 571 | .sh_addr = 0, | ||
| 572 | .sh_offset = off, | ||
| 573 | .sh_size = file_size, | ||
| 574 | // The section header index of the associated string table. | ||
| 575 | .sh_link = self.shstrtab_index.?, | ||
| 576 | .sh_info = @intCast(u32, self.local_symbols.items.len), | ||
| 577 | .sh_addralign = min_align, | ||
| 578 | .sh_entsize = each_size, | ||
| 579 | }); | ||
| 580 | self.shdr_table_dirty = true; | ||
| 581 | try self.writeSymbol(0); | ||
| 582 | } | ||
| 583 | if (self.debug_str_section_index == null) { | ||
| 584 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); | ||
| 585 | assert(self.debug_strtab.items.len == 0); | ||
| 586 | try self.sections.append(self.base.allocator, .{ | ||
| 587 | .sh_name = try self.makeString(".debug_str"), | ||
| 588 | .sh_type = elf.SHT_PROGBITS, | ||
| 589 | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 590 | .sh_addr = 0, | ||
| 591 | .sh_offset = 0, | ||
| 592 | .sh_size = self.debug_strtab.items.len, | ||
| 593 | .sh_link = 0, | ||
| 594 | .sh_info = 0, | ||
| 595 | .sh_addralign = 1, | ||
| 596 | .sh_entsize = 1, | ||
| 597 | }); | ||
| 598 | self.debug_strtab_dirty = true; | ||
| 599 | self.shdr_table_dirty = true; | ||
| 600 | } | ||
| 601 | if (self.debug_info_section_index == null) { | ||
| 602 | self.debug_info_section_index = @intCast(u16, self.sections.items.len); | ||
| 603 | |||
| 604 | const file_size_hint = 200; | ||
| 605 | const p_align = 1; | ||
| 606 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 607 | log.debug("found .debug_info free space 0x{x} to 0x{x}\n", .{ | ||
| 608 | off, | ||
| 609 | off + file_size_hint, | ||
| 610 | }); | ||
| 611 | try self.sections.append(self.base.allocator, .{ | ||
| 612 | .sh_name = try self.makeString(".debug_info"), | ||
| 613 | .sh_type = elf.SHT_PROGBITS, | ||
| 614 | .sh_flags = 0, | ||
| 615 | .sh_addr = 0, | ||
| 616 | .sh_offset = off, | ||
| 617 | .sh_size = file_size_hint, | ||
| 618 | .sh_link = 0, | ||
| 619 | .sh_info = 0, | ||
| 620 | .sh_addralign = p_align, | ||
| 621 | .sh_entsize = 0, | ||
| 622 | }); | ||
| 623 | self.shdr_table_dirty = true; | ||
| 624 | self.debug_info_header_dirty = true; | ||
| 625 | } | ||
| 626 | if (self.debug_abbrev_section_index == null) { | ||
| 627 | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); | ||
| 628 | |||
| 629 | const file_size_hint = 128; | ||
| 630 | const p_align = 1; | ||
| 631 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 632 | log.debug("found .debug_abbrev free space 0x{x} to 0x{x}\n", .{ | ||
| 633 | off, | ||
| 634 | off + file_size_hint, | ||
| 635 | }); | ||
| 636 | try self.sections.append(self.base.allocator, .{ | ||
| 637 | .sh_name = try self.makeString(".debug_abbrev"), | ||
| 638 | .sh_type = elf.SHT_PROGBITS, | ||
| 639 | .sh_flags = 0, | ||
| 640 | .sh_addr = 0, | ||
| 641 | .sh_offset = off, | ||
| 642 | .sh_size = file_size_hint, | ||
| 643 | .sh_link = 0, | ||
| 644 | .sh_info = 0, | ||
| 645 | .sh_addralign = p_align, | ||
| 646 | .sh_entsize = 0, | ||
| 647 | }); | ||
| 648 | self.shdr_table_dirty = true; | ||
| 649 | self.debug_abbrev_section_dirty = true; | ||
| 650 | } | ||
| 651 | if (self.debug_aranges_section_index == null) { | ||
| 652 | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); | ||
| 653 | |||
| 654 | const file_size_hint = 160; | ||
| 655 | const p_align = 16; | ||
| 656 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 657 | log.debug("found .debug_aranges free space 0x{x} to 0x{x}\n", .{ | ||
| 658 | off, | ||
| 659 | off + file_size_hint, | ||
| 660 | }); | ||
| 661 | try self.sections.append(self.base.allocator, .{ | ||
| 662 | .sh_name = try self.makeString(".debug_aranges"), | ||
| 663 | .sh_type = elf.SHT_PROGBITS, | ||
| 664 | .sh_flags = 0, | ||
| 665 | .sh_addr = 0, | ||
| 666 | .sh_offset = off, | ||
| 667 | .sh_size = file_size_hint, | ||
| 668 | .sh_link = 0, | ||
| 669 | .sh_info = 0, | ||
| 670 | .sh_addralign = p_align, | ||
| 671 | .sh_entsize = 0, | ||
| 672 | }); | ||
| 673 | self.shdr_table_dirty = true; | ||
| 674 | self.debug_aranges_section_dirty = true; | ||
| 675 | } | ||
| 676 | if (self.debug_line_section_index == null) { | ||
| 677 | self.debug_line_section_index = @intCast(u16, self.sections.items.len); | ||
| 678 | |||
| 679 | const file_size_hint = 250; | ||
| 680 | const p_align = 1; | ||
| 681 | const off = self.findFreeSpace(file_size_hint, p_align); | ||
| 682 | log.debug("found .debug_line free space 0x{x} to 0x{x}\n", .{ | ||
| 683 | off, | ||
| 684 | off + file_size_hint, | ||
| 685 | }); | ||
| 686 | try self.sections.append(self.base.allocator, .{ | ||
| 687 | .sh_name = try self.makeString(".debug_line"), | ||
| 688 | .sh_type = elf.SHT_PROGBITS, | ||
| 689 | .sh_flags = 0, | ||
| 690 | .sh_addr = 0, | ||
| 691 | .sh_offset = off, | ||
| 692 | .sh_size = file_size_hint, | ||
| 693 | .sh_link = 0, | ||
| 694 | .sh_info = 0, | ||
| 695 | .sh_addralign = p_align, | ||
| 696 | .sh_entsize = 0, | ||
| 697 | }); | ||
| 698 | self.shdr_table_dirty = true; | ||
| 699 | self.debug_line_header_dirty = true; | ||
| 700 | } | ||
| 701 | const shsize: u64 = switch (self.ptr_width) { | ||
| 702 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 703 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 704 | }; | ||
| 705 | const shalign: u16 = switch (self.ptr_width) { | ||
| 706 | .p32 => @alignOf(elf.Elf32_Shdr), | ||
| 707 | .p64 => @alignOf(elf.Elf64_Shdr), | ||
| 708 | }; | ||
| 709 | if (self.shdr_table_offset == null) { | ||
| 710 | self.shdr_table_offset = self.findFreeSpace(self.sections.items.len * shsize, shalign); | ||
| 711 | self.shdr_table_dirty = true; | ||
| 712 | } | ||
| 713 | const phsize: u64 = switch (self.ptr_width) { | ||
| 714 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 715 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 716 | }; | ||
| 717 | const phalign: u16 = switch (self.ptr_width) { | ||
| 718 | .p32 => @alignOf(elf.Elf32_Phdr), | ||
| 719 | .p64 => @alignOf(elf.Elf64_Phdr), | ||
| 720 | }; | ||
| 721 | if (self.phdr_table_offset == null) { | ||
| 722 | self.phdr_table_offset = self.findFreeSpace(self.program_headers.items.len * phsize, phalign); | ||
| 723 | self.phdr_table_dirty = true; | ||
| 724 | } | ||
| 725 | { | ||
| 726 | // Iterate over symbols, populating free_list and last_text_block. | ||
| 727 | if (self.local_symbols.items.len != 1) { | ||
| 728 | @panic("TODO implement setting up free_list and last_text_block from existing ELF file"); | ||
| 729 | } | ||
| 730 | // We are starting with an empty file. The default values are correct, null and empty list. | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | pub const abbrev_compile_unit = 1; | ||
| 735 | pub const abbrev_subprogram = 2; | ||
| 736 | pub const abbrev_subprogram_retvoid = 3; | ||
| 737 | pub const abbrev_base_type = 4; | ||
| 738 | pub const abbrev_pad1 = 5; | ||
| 739 | pub const abbrev_parameter = 6; | ||
| 740 | |||
| 741 | /// Commit pending changes and write headers. | ||
| 742 | pub fn flush(self: *Elf, module: *Module) !void { | ||
| 743 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 744 | const foreign_endian = target_endian != std.Target.current.cpu.arch.endian(); | ||
| 745 | const ptr_width_bytes: u8 = self.ptrWidthBytes(); | ||
| 746 | const init_len_size: usize = switch (self.ptr_width) { | ||
| 747 | .p32 => 4, | ||
| 748 | .p64 => 12, | ||
| 749 | }; | ||
| 750 | |||
| 751 | // Unfortunately these have to be buffered and done at the end because ELF does not allow | ||
| 752 | // mixing local and global symbols within a symbol table. | ||
| 753 | try self.writeAllGlobalSymbols(); | ||
| 754 | |||
| 755 | if (self.debug_abbrev_section_dirty) { | ||
| 756 | const debug_abbrev_sect = &self.sections.items[self.debug_abbrev_section_index.?]; | ||
| 757 | |||
| 758 | // These are LEB encoded but since the values are all less than 127 | ||
| 759 | // we can simply append these bytes. | ||
| 760 | const abbrev_buf = [_]u8{ | ||
| 761 | abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header | ||
| 762 | DW.AT_stmt_list, DW.FORM_sec_offset, DW.AT_low_pc, | ||
| 763 | DW.FORM_addr, DW.AT_high_pc, DW.FORM_addr, | ||
| 764 | DW.AT_name, DW.FORM_strp, DW.AT_comp_dir, | ||
| 765 | DW.FORM_strp, DW.AT_producer, DW.FORM_strp, | ||
| 766 | DW.AT_language, DW.FORM_data2, 0, | ||
| 767 | 0, // table sentinel | ||
| 768 | abbrev_subprogram, DW.TAG_subprogram, | ||
| 769 | DW.CHILDREN_yes, // header | ||
| 770 | DW.AT_low_pc, DW.FORM_addr, | ||
| 771 | DW.AT_high_pc, DW.FORM_data4, DW.AT_type, | ||
| 772 | DW.FORM_ref4, DW.AT_name, DW.FORM_string, | ||
| 773 | 0, 0, // table sentinel | ||
| 774 | abbrev_subprogram_retvoid, | ||
| 775 | DW.TAG_subprogram, DW.CHILDREN_yes, // header | ||
| 776 | DW.AT_low_pc, | ||
| 777 | DW.FORM_addr, DW.AT_high_pc, DW.FORM_data4, | ||
| 778 | DW.AT_name, DW.FORM_string, 0, | ||
| 779 | 0, // table sentinel | ||
| 780 | abbrev_base_type, DW.TAG_base_type, | ||
| 781 | DW.CHILDREN_no, // header | ||
| 782 | DW.AT_encoding, DW.FORM_data1, | ||
| 783 | DW.AT_byte_size, DW.FORM_data1, DW.AT_name, | ||
| 784 | DW.FORM_string, 0, 0, // table sentinel | ||
| 785 | |||
| 786 | abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header | ||
| 787 | 0, 0, // table sentinel | ||
| 788 | abbrev_parameter, | ||
| 789 | DW.TAG_formal_parameter, DW.CHILDREN_no, // header | ||
| 790 | DW.AT_location, | ||
| 791 | DW.FORM_exprloc, DW.AT_type, DW.FORM_ref4, | ||
| 792 | DW.AT_name, DW.FORM_string, 0, | ||
| 793 | 0, // table sentinel | ||
| 794 | 0, 0, | ||
| 795 | 0, // section sentinel | ||
| 796 | }; | ||
| 797 | |||
| 798 | const needed_size = abbrev_buf.len; | ||
| 799 | const allocated_size = self.allocatedSize(debug_abbrev_sect.sh_offset); | ||
| 800 | if (needed_size > allocated_size) { | ||
| 801 | debug_abbrev_sect.sh_size = 0; // free the space | ||
| 802 | debug_abbrev_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 803 | } | ||
| 804 | debug_abbrev_sect.sh_size = needed_size; | ||
| 805 | log.debug(".debug_abbrev start=0x{x} end=0x{x}\n", .{ | ||
| 806 | debug_abbrev_sect.sh_offset, | ||
| 807 | debug_abbrev_sect.sh_offset + needed_size, | ||
| 808 | }); | ||
| 809 | |||
| 810 | const abbrev_offset = 0; | ||
| 811 | self.debug_abbrev_table_offset = abbrev_offset; | ||
| 812 | try self.base.file.?.pwriteAll(&abbrev_buf, debug_abbrev_sect.sh_offset + abbrev_offset); | ||
| 813 | if (!self.shdr_table_dirty) { | ||
| 814 | // Then it won't get written with the others and we need to do it. | ||
| 815 | try self.writeSectHeader(self.debug_abbrev_section_index.?); | ||
| 816 | } | ||
| 817 | |||
| 818 | self.debug_abbrev_section_dirty = false; | ||
| 819 | } | ||
| 820 | |||
| 821 | if (self.debug_info_header_dirty) debug_info: { | ||
| 822 | // If this value is null it means there is an error in the module; | ||
| 823 | // leave debug_info_header_dirty=true. | ||
| 824 | const first_dbg_info_decl = self.dbg_info_decl_first orelse break :debug_info; | ||
| 825 | const last_dbg_info_decl = self.dbg_info_decl_last.?; | ||
| 826 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 827 | |||
| 828 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 829 | defer di_buf.deinit(); | ||
| 830 | |||
| 831 | // We have a function to compute the upper bound size, because it's needed | ||
| 832 | // for determining where to put the offset of the first `LinkBlock`. | ||
| 833 | try di_buf.ensureCapacity(self.dbgInfoNeededHeaderBytes()); | ||
| 834 | |||
| 835 | // initial length - length of the .debug_info contribution for this compilation unit, | ||
| 836 | // not including the initial length itself. | ||
| 837 | // We have to come back and write it later after we know the size. | ||
| 838 | const after_init_len = di_buf.items.len + init_len_size; | ||
| 839 | // +1 for the final 0 that ends the compilation unit children. | ||
| 840 | const dbg_info_end = last_dbg_info_decl.dbg_info_off + last_dbg_info_decl.dbg_info_len + 1; | ||
| 841 | const init_len = dbg_info_end - after_init_len; | ||
| 842 | switch (self.ptr_width) { | ||
| 843 | .p32 => { | ||
| 844 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len), target_endian); | ||
| 845 | }, | ||
| 846 | .p64 => { | ||
| 847 | di_buf.appendNTimesAssumeCapacity(0xff, 4); | ||
| 848 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian); | ||
| 849 | }, | ||
| 850 | } | ||
| 851 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version | ||
| 852 | const abbrev_offset = self.debug_abbrev_table_offset.?; | ||
| 853 | switch (self.ptr_width) { | ||
| 854 | .p32 => { | ||
| 855 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, abbrev_offset), target_endian); | ||
| 856 | di_buf.appendAssumeCapacity(4); // address size | ||
| 857 | }, | ||
| 858 | .p64 => { | ||
| 859 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), abbrev_offset, target_endian); | ||
| 860 | di_buf.appendAssumeCapacity(8); // address size | ||
| 861 | }, | ||
| 862 | } | ||
| 863 | // Write the form for the compile unit, which must match the abbrev table above. | ||
| 864 | const name_strp = try self.makeDebugString(self.base.options.root_pkg.root_src_path); | ||
| 865 | const comp_dir_strp = try self.makeDebugString(self.base.options.root_pkg.root_src_dir_path); | ||
| 866 | const producer_strp = try self.makeDebugString(producer_string); | ||
| 867 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 868 | // identical to the main program header virtual address and memory size. | ||
| 869 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 870 | const low_pc = text_phdr.p_vaddr; | ||
| 871 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; | ||
| 872 | |||
| 873 | di_buf.appendAssumeCapacity(abbrev_compile_unit); | ||
| 874 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT_stmt_list, DW.FORM_sec_offset | ||
| 875 | self.writeDwarfAddrAssumeCapacity(&di_buf, low_pc); | ||
| 876 | self.writeDwarfAddrAssumeCapacity(&di_buf, high_pc); | ||
| 877 | self.writeDwarfAddrAssumeCapacity(&di_buf, name_strp); | ||
| 878 | self.writeDwarfAddrAssumeCapacity(&di_buf, comp_dir_strp); | ||
| 879 | self.writeDwarfAddrAssumeCapacity(&di_buf, producer_strp); | ||
| 880 | // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: | ||
| 881 | // http://dwarfstd.org/ShowIssue.php?issue=171115.1 | ||
| 882 | // Until then we say it is C99. | ||
| 883 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99, target_endian); | ||
| 884 | |||
| 885 | if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { | ||
| 886 | // Move the first N decls to the end to make more padding for the header. | ||
| 887 | @panic("TODO: handle .debug_info header exceeding its padding"); | ||
| 888 | } | ||
| 889 | const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len; | ||
| 890 | try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, false, debug_info_sect.sh_offset); | ||
| 891 | self.debug_info_header_dirty = false; | ||
| 892 | } | ||
| 893 | |||
| 894 | if (self.debug_aranges_section_dirty) { | ||
| 895 | const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?]; | ||
| 896 | |||
| 897 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 898 | defer di_buf.deinit(); | ||
| 899 | |||
| 900 | // Enough for all the data without resizing. When support for more compilation units | ||
| 901 | // is added, the size of this section will become more variable. | ||
| 902 | try di_buf.ensureCapacity(100); | ||
| 903 | |||
| 904 | // initial length - length of the .debug_aranges contribution for this compilation unit, | ||
| 905 | // not including the initial length itself. | ||
| 906 | // We have to come back and write it later after we know the size. | ||
| 907 | const init_len_index = di_buf.items.len; | ||
| 908 | di_buf.items.len += init_len_size; | ||
| 909 | const after_init_len = di_buf.items.len; | ||
| 910 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version | ||
| 911 | // When more than one compilation unit is supported, this will be the offset to it. | ||
| 912 | // For now it is always at offset 0 in .debug_info. | ||
| 913 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // .debug_info offset | ||
| 914 | di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size | ||
| 915 | di_buf.appendAssumeCapacity(0); // segment_selector_size | ||
| 916 | |||
| 917 | const end_header_offset = di_buf.items.len; | ||
| 918 | const begin_entries_offset = mem.alignForward(end_header_offset, ptr_width_bytes * 2); | ||
| 919 | di_buf.appendNTimesAssumeCapacity(0, begin_entries_offset - end_header_offset); | ||
| 920 | |||
| 921 | // Currently only one compilation unit is supported, so the address range is simply | ||
| 922 | // identical to the main program header virtual address and memory size. | ||
| 923 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 924 | self.writeDwarfAddrAssumeCapacity(&di_buf, text_phdr.p_vaddr); | ||
| 925 | self.writeDwarfAddrAssumeCapacity(&di_buf, text_phdr.p_memsz); | ||
| 926 | |||
| 927 | // Sentinel. | ||
| 928 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); | ||
| 929 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); | ||
| 930 | |||
| 931 | // Go back and populate the initial length. | ||
| 932 | const init_len = di_buf.items.len - after_init_len; | ||
| 933 | switch (self.ptr_width) { | ||
| 934 | .p32 => { | ||
| 935 | mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @intCast(u32, init_len), target_endian); | ||
| 936 | }, | ||
| 937 | .p64 => { | ||
| 938 | // initial length - length of the .debug_aranges contribution for this compilation unit, | ||
| 939 | // not including the initial length itself. | ||
| 940 | di_buf.items[init_len_index..][0..4].* = [_]u8{ 0xff, 0xff, 0xff, 0xff }; | ||
| 941 | mem.writeInt(u64, di_buf.items[init_len_index + 4 ..][0..8], init_len, target_endian); | ||
| 942 | }, | ||
| 943 | } | ||
| 944 | |||
| 945 | const needed_size = di_buf.items.len; | ||
| 946 | const allocated_size = self.allocatedSize(debug_aranges_sect.sh_offset); | ||
| 947 | if (needed_size > allocated_size) { | ||
| 948 | debug_aranges_sect.sh_size = 0; // free the space | ||
| 949 | debug_aranges_sect.sh_offset = self.findFreeSpace(needed_size, 16); | ||
| 950 | } | ||
| 951 | debug_aranges_sect.sh_size = needed_size; | ||
| 952 | log.debug(".debug_aranges start=0x{x} end=0x{x}\n", .{ | ||
| 953 | debug_aranges_sect.sh_offset, | ||
| 954 | debug_aranges_sect.sh_offset + needed_size, | ||
| 955 | }); | ||
| 956 | |||
| 957 | try self.base.file.?.pwriteAll(di_buf.items, debug_aranges_sect.sh_offset); | ||
| 958 | if (!self.shdr_table_dirty) { | ||
| 959 | // Then it won't get written with the others and we need to do it. | ||
| 960 | try self.writeSectHeader(self.debug_aranges_section_index.?); | ||
| 961 | } | ||
| 962 | |||
| 963 | self.debug_aranges_section_dirty = false; | ||
| 964 | } | ||
| 965 | if (self.debug_line_header_dirty) debug_line: { | ||
| 966 | if (self.dbg_line_fn_first == null) { | ||
| 967 | break :debug_line; // Error in module; leave debug_line_header_dirty=true. | ||
| 968 | } | ||
| 969 | const dbg_line_prg_off = self.getDebugLineProgramOff(); | ||
| 970 | const dbg_line_prg_end = self.getDebugLineProgramEnd(); | ||
| 971 | assert(dbg_line_prg_end != 0); | ||
| 972 | |||
| 973 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | ||
| 974 | |||
| 975 | var di_buf = std.ArrayList(u8).init(self.base.allocator); | ||
| 976 | defer di_buf.deinit(); | ||
| 977 | |||
| 978 | // The size of this header is variable, depending on the number of directories, | ||
| 979 | // files, and padding. We have a function to compute the upper bound size, however, | ||
| 980 | // because it's needed for determining where to put the offset of the first `SrcFn`. | ||
| 981 | try di_buf.ensureCapacity(self.dbgLineNeededHeaderBytes()); | ||
| 982 | |||
| 983 | // initial length - length of the .debug_line contribution for this compilation unit, | ||
| 984 | // not including the initial length itself. | ||
| 985 | const after_init_len = di_buf.items.len + init_len_size; | ||
| 986 | const init_len = dbg_line_prg_end - after_init_len; | ||
| 987 | switch (self.ptr_width) { | ||
| 988 | .p32 => { | ||
| 989 | mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len), target_endian); | ||
| 990 | }, | ||
| 991 | .p64 => { | ||
| 992 | di_buf.appendNTimesAssumeCapacity(0xff, 4); | ||
| 993 | mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian); | ||
| 994 | }, | ||
| 995 | } | ||
| 996 | |||
| 997 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version | ||
| 998 | |||
| 999 | // Empirically, debug info consumers do not respect this field, or otherwise | ||
| 1000 | // consider it to be an error when it does not point exactly to the end of the header. | ||
| 1001 | // Therefore we rely on the NOP jump at the beginning of the Line Number Program for | ||
| 1002 | // padding rather than this field. | ||
| 1003 | const before_header_len = di_buf.items.len; | ||
| 1004 | di_buf.items.len += ptr_width_bytes; // We will come back and write this. | ||
| 1005 | const after_header_len = di_buf.items.len; | ||
| 1006 | |||
| 1007 | const opcode_base = DW.LNS_set_isa + 1; | ||
| 1008 | di_buf.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1009 | 1, // minimum_instruction_length | ||
| 1010 | 1, // maximum_operations_per_instruction | ||
| 1011 | 1, // default_is_stmt | ||
| 1012 | 1, // line_base (signed) | ||
| 1013 | 1, // line_range | ||
| 1014 | opcode_base, | ||
| 1015 | |||
| 1016 | // Standard opcode lengths. The number of items here is based on `opcode_base`. | ||
| 1017 | // The value is the number of LEB128 operands the instruction takes. | ||
| 1018 | 0, // `DW.LNS_copy` | ||
| 1019 | 1, // `DW.LNS_advance_pc` | ||
| 1020 | 1, // `DW.LNS_advance_line` | ||
| 1021 | 1, // `DW.LNS_set_file` | ||
| 1022 | 1, // `DW.LNS_set_column` | ||
| 1023 | 0, // `DW.LNS_negate_stmt` | ||
| 1024 | 0, // `DW.LNS_set_basic_block` | ||
| 1025 | 0, // `DW.LNS_const_add_pc` | ||
| 1026 | 1, // `DW.LNS_fixed_advance_pc` | ||
| 1027 | 0, // `DW.LNS_set_prologue_end` | ||
| 1028 | 0, // `DW.LNS_set_epilogue_begin` | ||
| 1029 | 1, // `DW.LNS_set_isa` | ||
| 1030 | |||
| 1031 | 0, // include_directories (none except the compilation unit cwd) | ||
| 1032 | }); | ||
| 1033 | // file_names[0] | ||
| 1034 | di_buf.appendSliceAssumeCapacity(self.base.options.root_pkg.root_src_path); // relative path name | ||
| 1035 | di_buf.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1036 | 0, // null byte for the relative path name | ||
| 1037 | 0, // directory_index | ||
| 1038 | 0, // mtime (TODO supply this) | ||
| 1039 | 0, // file size bytes (TODO supply this) | ||
| 1040 | 0, // file_names sentinel | ||
| 1041 | }); | ||
| 1042 | |||
| 1043 | const header_len = di_buf.items.len - after_header_len; | ||
| 1044 | switch (self.ptr_width) { | ||
| 1045 | .p32 => { | ||
| 1046 | mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @intCast(u32, header_len), target_endian); | ||
| 1047 | }, | ||
| 1048 | .p64 => { | ||
| 1049 | mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian); | ||
| 1050 | }, | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | // We use NOPs because consumers empirically do not respect the header length field. | ||
| 1054 | if (di_buf.items.len > dbg_line_prg_off) { | ||
| 1055 | // Move the first N files to the end to make more padding for the header. | ||
| 1056 | @panic("TODO: handle .debug_line header exceeding its padding"); | ||
| 1057 | } | ||
| 1058 | const jmp_amt = dbg_line_prg_off - di_buf.items.len; | ||
| 1059 | try self.pwriteDbgLineNops(0, di_buf.items, jmp_amt, debug_line_sect.sh_offset); | ||
| 1060 | self.debug_line_header_dirty = false; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | if (self.phdr_table_dirty) { | ||
| 1064 | const phsize: u64 = switch (self.ptr_width) { | ||
| 1065 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 1066 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 1067 | }; | ||
| 1068 | const phalign: u16 = switch (self.ptr_width) { | ||
| 1069 | .p32 => @alignOf(elf.Elf32_Phdr), | ||
| 1070 | .p64 => @alignOf(elf.Elf64_Phdr), | ||
| 1071 | }; | ||
| 1072 | const allocated_size = self.allocatedSize(self.phdr_table_offset.?); | ||
| 1073 | const needed_size = self.program_headers.items.len * phsize; | ||
| 1074 | |||
| 1075 | if (needed_size > allocated_size) { | ||
| 1076 | self.phdr_table_offset = null; // free the space | ||
| 1077 | self.phdr_table_offset = self.findFreeSpace(needed_size, phalign); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | switch (self.ptr_width) { | ||
| 1081 | .p32 => { | ||
| 1082 | const buf = try self.base.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len); | ||
| 1083 | defer self.base.allocator.free(buf); | ||
| 1084 | |||
| 1085 | for (buf) |*phdr, i| { | ||
| 1086 | phdr.* = progHeaderTo32(self.program_headers.items[i]); | ||
| 1087 | if (foreign_endian) { | ||
| 1088 | bswapAllFields(elf.Elf32_Phdr, phdr); | ||
| 1089 | } | ||
| 1090 | } | ||
| 1091 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | ||
| 1092 | }, | ||
| 1093 | .p64 => { | ||
| 1094 | const buf = try self.base.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); | ||
| 1095 | defer self.base.allocator.free(buf); | ||
| 1096 | |||
| 1097 | for (buf) |*phdr, i| { | ||
| 1098 | phdr.* = self.program_headers.items[i]; | ||
| 1099 | if (foreign_endian) { | ||
| 1100 | bswapAllFields(elf.Elf64_Phdr, phdr); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | ||
| 1104 | }, | ||
| 1105 | } | ||
| 1106 | self.phdr_table_dirty = false; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | { | ||
| 1110 | const shstrtab_sect = &self.sections.items[self.shstrtab_index.?]; | ||
| 1111 | if (self.shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) { | ||
| 1112 | const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset); | ||
| 1113 | const needed_size = self.shstrtab.items.len; | ||
| 1114 | |||
| 1115 | if (needed_size > allocated_size) { | ||
| 1116 | shstrtab_sect.sh_size = 0; // free the space | ||
| 1117 | shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 1118 | } | ||
| 1119 | shstrtab_sect.sh_size = needed_size; | ||
| 1120 | log.debug("writing shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); | ||
| 1121 | |||
| 1122 | try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); | ||
| 1123 | if (!self.shdr_table_dirty) { | ||
| 1124 | // Then it won't get written with the others and we need to do it. | ||
| 1125 | try self.writeSectHeader(self.shstrtab_index.?); | ||
| 1126 | } | ||
| 1127 | self.shstrtab_dirty = false; | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | { | ||
| 1131 | const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?]; | ||
| 1132 | if (self.debug_strtab_dirty or self.debug_strtab.items.len != debug_strtab_sect.sh_size) { | ||
| 1133 | const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset); | ||
| 1134 | const needed_size = self.debug_strtab.items.len; | ||
| 1135 | |||
| 1136 | if (needed_size > allocated_size) { | ||
| 1137 | debug_strtab_sect.sh_size = 0; // free the space | ||
| 1138 | debug_strtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); | ||
| 1139 | } | ||
| 1140 | debug_strtab_sect.sh_size = needed_size; | ||
| 1141 | log.debug("debug_strtab start=0x{x} end=0x{x}\n", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); | ||
| 1142 | |||
| 1143 | try self.base.file.?.pwriteAll(self.debug_strtab.items, debug_strtab_sect.sh_offset); | ||
| 1144 | if (!self.shdr_table_dirty) { | ||
| 1145 | // Then it won't get written with the others and we need to do it. | ||
| 1146 | try self.writeSectHeader(self.debug_str_section_index.?); | ||
| 1147 | } | ||
| 1148 | self.debug_strtab_dirty = false; | ||
| 1149 | } | ||
| 1150 | } | ||
| 1151 | if (self.shdr_table_dirty) { | ||
| 1152 | const shsize: u64 = switch (self.ptr_width) { | ||
| 1153 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 1154 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 1155 | }; | ||
| 1156 | const shalign: u16 = switch (self.ptr_width) { | ||
| 1157 | .p32 => @alignOf(elf.Elf32_Shdr), | ||
| 1158 | .p64 => @alignOf(elf.Elf64_Shdr), | ||
| 1159 | }; | ||
| 1160 | const allocated_size = self.allocatedSize(self.shdr_table_offset.?); | ||
| 1161 | const needed_size = self.sections.items.len * shsize; | ||
| 1162 | |||
| 1163 | if (needed_size > allocated_size) { | ||
| 1164 | self.shdr_table_offset = null; // free the space | ||
| 1165 | self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | switch (self.ptr_width) { | ||
| 1169 | .p32 => { | ||
| 1170 | const buf = try self.base.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); | ||
| 1171 | defer self.base.allocator.free(buf); | ||
| 1172 | |||
| 1173 | for (buf) |*shdr, i| { | ||
| 1174 | shdr.* = sectHeaderTo32(self.sections.items[i]); | ||
| 1175 | log.debug("writing section {}\n", .{shdr.*}); | ||
| 1176 | if (foreign_endian) { | ||
| 1177 | bswapAllFields(elf.Elf32_Shdr, shdr); | ||
| 1178 | } | ||
| 1179 | } | ||
| 1180 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | ||
| 1181 | }, | ||
| 1182 | .p64 => { | ||
| 1183 | const buf = try self.base.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); | ||
| 1184 | defer self.base.allocator.free(buf); | ||
| 1185 | |||
| 1186 | for (buf) |*shdr, i| { | ||
| 1187 | shdr.* = self.sections.items[i]; | ||
| 1188 | log.debug("writing section {}\n", .{shdr.*}); | ||
| 1189 | if (foreign_endian) { | ||
| 1190 | bswapAllFields(elf.Elf64_Shdr, shdr); | ||
| 1191 | } | ||
| 1192 | } | ||
| 1193 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | ||
| 1194 | }, | ||
| 1195 | } | ||
| 1196 | self.shdr_table_dirty = false; | ||
| 1197 | } | ||
| 1198 | if (self.entry_addr == null and self.base.options.output_mode == .Exe) { | ||
| 1199 | log.debug("flushing. no_entry_point_found = true\n", .{}); | ||
| 1200 | self.error_flags.no_entry_point_found = true; | ||
| 1201 | } else { | ||
| 1202 | log.debug("flushing. no_entry_point_found = false\n", .{}); | ||
| 1203 | self.error_flags.no_entry_point_found = false; | ||
| 1204 | try self.writeElfHeader(); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | // The point of flush() is to commit changes, so in theory, nothing should | ||
| 1208 | // be dirty after this. However, it is possible for some things to remain | ||
| 1209 | // dirty because they fail to be written in the event of compile errors, | ||
| 1210 | // such as debug_line_header_dirty and debug_info_header_dirty. | ||
| 1211 | assert(!self.debug_abbrev_section_dirty); | ||
| 1212 | assert(!self.debug_aranges_section_dirty); | ||
| 1213 | assert(!self.phdr_table_dirty); | ||
| 1214 | assert(!self.shdr_table_dirty); | ||
| 1215 | assert(!self.shstrtab_dirty); | ||
| 1216 | assert(!self.debug_strtab_dirty); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void { | ||
| 1220 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 1221 | switch (self.ptr_width) { | ||
| 1222 | .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, addr), target_endian), | ||
| 1223 | .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian), | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | fn writeElfHeader(self: *Elf) !void { | ||
| 1228 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | ||
| 1229 | |||
| 1230 | var index: usize = 0; | ||
| 1231 | hdr_buf[0..4].* = "\x7fELF".*; | ||
| 1232 | index += 4; | ||
| 1233 | |||
| 1234 | hdr_buf[index] = switch (self.ptr_width) { | ||
| 1235 | .p32 => elf.ELFCLASS32, | ||
| 1236 | .p64 => elf.ELFCLASS64, | ||
| 1237 | }; | ||
| 1238 | index += 1; | ||
| 1239 | |||
| 1240 | const endian = self.base.options.target.cpu.arch.endian(); | ||
| 1241 | hdr_buf[index] = switch (endian) { | ||
| 1242 | .Little => elf.ELFDATA2LSB, | ||
| 1243 | .Big => elf.ELFDATA2MSB, | ||
| 1244 | }; | ||
| 1245 | index += 1; | ||
| 1246 | |||
| 1247 | hdr_buf[index] = 1; // ELF version | ||
| 1248 | index += 1; | ||
| 1249 | |||
| 1250 | // OS ABI, often set to 0 regardless of target platform | ||
| 1251 | // ABI Version, possibly used by glibc but not by static executables | ||
| 1252 | // padding | ||
| 1253 | mem.set(u8, hdr_buf[index..][0..9], 0); | ||
| 1254 | index += 9; | ||
| 1255 | |||
| 1256 | assert(index == 16); | ||
| 1257 | |||
| 1258 | const elf_type = switch (self.base.options.output_mode) { | ||
| 1259 | .Exe => elf.ET.EXEC, | ||
| 1260 | .Obj => elf.ET.REL, | ||
| 1261 | .Lib => switch (self.base.options.link_mode) { | ||
| 1262 | .Static => elf.ET.REL, | ||
| 1263 | .Dynamic => elf.ET.DYN, | ||
| 1264 | }, | ||
| 1265 | }; | ||
| 1266 | mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(elf_type), endian); | ||
| 1267 | index += 2; | ||
| 1268 | |||
| 1269 | const machine = self.base.options.target.cpu.arch.toElfMachine(); | ||
| 1270 | mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(machine), endian); | ||
| 1271 | index += 2; | ||
| 1272 | |||
| 1273 | // ELF Version, again | ||
| 1274 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); | ||
| 1275 | index += 4; | ||
| 1276 | |||
| 1277 | const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?; | ||
| 1278 | |||
| 1279 | switch (self.ptr_width) { | ||
| 1280 | .p32 => { | ||
| 1281 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, e_entry), endian); | ||
| 1282 | index += 4; | ||
| 1283 | |||
| 1284 | // e_phoff | ||
| 1285 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.phdr_table_offset.?), endian); | ||
| 1286 | index += 4; | ||
| 1287 | |||
| 1288 | // e_shoff | ||
| 1289 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.shdr_table_offset.?), endian); | ||
| 1290 | index += 4; | ||
| 1291 | }, | ||
| 1292 | .p64 => { | ||
| 1293 | // e_entry | ||
| 1294 | mem.writeInt(u64, hdr_buf[index..][0..8], e_entry, endian); | ||
| 1295 | index += 8; | ||
| 1296 | |||
| 1297 | // e_phoff | ||
| 1298 | mem.writeInt(u64, hdr_buf[index..][0..8], self.phdr_table_offset.?, endian); | ||
| 1299 | index += 8; | ||
| 1300 | |||
| 1301 | // e_shoff | ||
| 1302 | mem.writeInt(u64, hdr_buf[index..][0..8], self.shdr_table_offset.?, endian); | ||
| 1303 | index += 8; | ||
| 1304 | }, | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | const e_flags = 0; | ||
| 1308 | mem.writeInt(u32, hdr_buf[index..][0..4], e_flags, endian); | ||
| 1309 | index += 4; | ||
| 1310 | |||
| 1311 | const e_ehsize: u16 = switch (self.ptr_width) { | ||
| 1312 | .p32 => @sizeOf(elf.Elf32_Ehdr), | ||
| 1313 | .p64 => @sizeOf(elf.Elf64_Ehdr), | ||
| 1314 | }; | ||
| 1315 | mem.writeInt(u16, hdr_buf[index..][0..2], e_ehsize, endian); | ||
| 1316 | index += 2; | ||
| 1317 | |||
| 1318 | const e_phentsize: u16 = switch (self.ptr_width) { | ||
| 1319 | .p32 => @sizeOf(elf.Elf32_Phdr), | ||
| 1320 | .p64 => @sizeOf(elf.Elf64_Phdr), | ||
| 1321 | }; | ||
| 1322 | mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian); | ||
| 1323 | index += 2; | ||
| 1324 | |||
| 1325 | const e_phnum = @intCast(u16, self.program_headers.items.len); | ||
| 1326 | mem.writeInt(u16, hdr_buf[index..][0..2], e_phnum, endian); | ||
| 1327 | index += 2; | ||
| 1328 | |||
| 1329 | const e_shentsize: u16 = switch (self.ptr_width) { | ||
| 1330 | .p32 => @sizeOf(elf.Elf32_Shdr), | ||
| 1331 | .p64 => @sizeOf(elf.Elf64_Shdr), | ||
| 1332 | }; | ||
| 1333 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); | ||
| 1334 | index += 2; | ||
| 1335 | |||
| 1336 | const e_shnum = @intCast(u16, self.sections.items.len); | ||
| 1337 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); | ||
| 1338 | index += 2; | ||
| 1339 | |||
| 1340 | mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_index.?, endian); | ||
| 1341 | index += 2; | ||
| 1342 | |||
| 1343 | assert(index == e_ehsize); | ||
| 1344 | |||
| 1345 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | fn freeTextBlock(self: *Elf, text_block: *TextBlock) void { | ||
| 1349 | var already_have_free_list_node = false; | ||
| 1350 | { | ||
| 1351 | var i: usize = 0; | ||
| 1352 | while (i < self.text_block_free_list.items.len) { | ||
| 1353 | if (self.text_block_free_list.items[i] == text_block) { | ||
| 1354 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1355 | continue; | ||
| 1356 | } | ||
| 1357 | if (self.text_block_free_list.items[i] == text_block.prev) { | ||
| 1358 | already_have_free_list_node = true; | ||
| 1359 | } | ||
| 1360 | i += 1; | ||
| 1361 | } | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | if (self.last_text_block == text_block) { | ||
| 1365 | // TODO shrink the .text section size here | ||
| 1366 | self.last_text_block = text_block.prev; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | if (text_block.prev) |prev| { | ||
| 1370 | prev.next = text_block.next; | ||
| 1371 | |||
| 1372 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | ||
| 1373 | // The free list is heuristics, it doesn't have to be perfect, so we can | ||
| 1374 | // ignore the OOM here. | ||
| 1375 | self.text_block_free_list.append(self.base.allocator, prev) catch {}; | ||
| 1376 | } | ||
| 1377 | } else { | ||
| 1378 | text_block.prev = null; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | if (text_block.next) |next| { | ||
| 1382 | next.prev = text_block.prev; | ||
| 1383 | } else { | ||
| 1384 | text_block.next = null; | ||
| 1385 | } | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void { | ||
| 1389 | // TODO check the new capacity, and if it crosses the size threshold into a big enough | ||
| 1390 | // capacity, insert a free list node for it. | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | ||
| 1394 | const sym = self.local_symbols.items[text_block.local_sym_index]; | ||
| 1395 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; | ||
| 1396 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); | ||
| 1397 | if (!need_realloc) return sym.st_value; | ||
| 1398 | return self.allocateTextBlock(text_block, new_block_size, alignment); | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | ||
| 1402 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1403 | const shdr = &self.sections.items[self.text_section_index.?]; | ||
| 1404 | const new_block_ideal_capacity = new_block_size * alloc_num / alloc_den; | ||
| 1405 | |||
| 1406 | // We use these to indicate our intention to update metadata, placing the new block, | ||
| 1407 | // and possibly removing a free list node. | ||
| 1408 | // It would be simpler to do it inside the for loop below, but that would cause a | ||
| 1409 | // problem if an error was returned later in the function. So this action | ||
| 1410 | // is actually carried out at the end of the function, when errors are no longer possible. | ||
| 1411 | var block_placement: ?*TextBlock = null; | ||
| 1412 | var free_list_removal: ?usize = null; | ||
| 1413 | |||
| 1414 | // First we look for an appropriately sized free list node. | ||
| 1415 | // The list is unordered. We'll just take the first thing that works. | ||
| 1416 | const vaddr = blk: { | ||
| 1417 | var i: usize = 0; | ||
| 1418 | while (i < self.text_block_free_list.items.len) { | ||
| 1419 | const big_block = self.text_block_free_list.items[i]; | ||
| 1420 | // We now have a pointer to a live text block that has too much capacity. | ||
| 1421 | // Is it enough that we could fit this new text block? | ||
| 1422 | const sym = self.local_symbols.items[big_block.local_sym_index]; | ||
| 1423 | const capacity = big_block.capacity(self.*); | ||
| 1424 | const ideal_capacity = capacity * alloc_num / alloc_den; | ||
| 1425 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; | ||
| 1426 | const capacity_end_vaddr = sym.st_value + capacity; | ||
| 1427 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_block_ideal_capacity; | ||
| 1428 | const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment); | ||
| 1429 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | ||
| 1430 | // Additional bookkeeping here to notice if this free list node | ||
| 1431 | // should be deleted because the block that it points to has grown to take up | ||
| 1432 | // more of the extra capacity. | ||
| 1433 | if (!big_block.freeListEligible(self.*)) { | ||
| 1434 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1435 | } else { | ||
| 1436 | i += 1; | ||
| 1437 | } | ||
| 1438 | continue; | ||
| 1439 | } | ||
| 1440 | // At this point we know that we will place the new block here. But the | ||
| 1441 | // remaining question is whether there is still yet enough capacity left | ||
| 1442 | // over for there to still be a free list node. | ||
| 1443 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; | ||
| 1444 | const keep_free_list_node = remaining_capacity >= min_text_capacity; | ||
| 1445 | |||
| 1446 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 1447 | block_placement = big_block; | ||
| 1448 | if (!keep_free_list_node) { | ||
| 1449 | free_list_removal = i; | ||
| 1450 | } | ||
| 1451 | break :blk new_start_vaddr; | ||
| 1452 | } else if (self.last_text_block) |last| { | ||
| 1453 | const sym = self.local_symbols.items[last.local_sym_index]; | ||
| 1454 | const ideal_capacity = sym.st_size * alloc_num / alloc_den; | ||
| 1455 | const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; | ||
| 1456 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); | ||
| 1457 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 1458 | block_placement = last; | ||
| 1459 | break :blk new_start_vaddr; | ||
| 1460 | } else { | ||
| 1461 | break :blk phdr.p_vaddr; | ||
| 1462 | } | ||
| 1463 | }; | ||
| 1464 | |||
| 1465 | const expand_text_section = block_placement == null or block_placement.?.next == null; | ||
| 1466 | if (expand_text_section) { | ||
| 1467 | const text_capacity = self.allocatedSize(shdr.sh_offset); | ||
| 1468 | const needed_size = (vaddr + new_block_size) - phdr.p_vaddr; | ||
| 1469 | if (needed_size > text_capacity) { | ||
| 1470 | // Must move the entire text section. | ||
| 1471 | const new_offset = self.findFreeSpace(needed_size, 0x1000); | ||
| 1472 | const text_size = if (self.last_text_block) |last| blk: { | ||
| 1473 | const sym = self.local_symbols.items[last.local_sym_index]; | ||
| 1474 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; | ||
| 1475 | } else 0; | ||
| 1476 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size); | ||
| 1477 | if (amt != text_size) return error.InputOutput; | ||
| 1478 | shdr.sh_offset = new_offset; | ||
| 1479 | phdr.p_offset = new_offset; | ||
| 1480 | } | ||
| 1481 | self.last_text_block = text_block; | ||
| 1482 | |||
| 1483 | shdr.sh_size = needed_size; | ||
| 1484 | phdr.p_memsz = needed_size; | ||
| 1485 | phdr.p_filesz = needed_size; | ||
| 1486 | |||
| 1487 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address | ||
| 1488 | // range of the compilation unit. When we expand the text section, this range changes, | ||
| 1489 | // so the DW_TAG_compile_unit tag of the .debug_info section becomes dirty. | ||
| 1490 | self.debug_info_header_dirty = true; | ||
| 1491 | // This becomes dirty for the same reason. We could potentially make this more | ||
| 1492 | // fine-grained with the addition of support for more compilation units. It is planned to | ||
| 1493 | // model each package as a different compilation unit. | ||
| 1494 | self.debug_aranges_section_dirty = true; | ||
| 1495 | |||
| 1496 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty | ||
| 1497 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | // This function can also reallocate a text block. | ||
| 1501 | // In this case we need to "unplug" it from its previous location before | ||
| 1502 | // plugging it in to its new location. | ||
| 1503 | if (text_block.prev) |prev| { | ||
| 1504 | prev.next = text_block.next; | ||
| 1505 | } | ||
| 1506 | if (text_block.next) |next| { | ||
| 1507 | next.prev = text_block.prev; | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | if (block_placement) |big_block| { | ||
| 1511 | text_block.prev = big_block; | ||
| 1512 | text_block.next = big_block.next; | ||
| 1513 | big_block.next = text_block; | ||
| 1514 | } else { | ||
| 1515 | text_block.prev = null; | ||
| 1516 | text_block.next = null; | ||
| 1517 | } | ||
| 1518 | if (free_list_removal) |i| { | ||
| 1519 | _ = self.text_block_free_list.swapRemove(i); | ||
| 1520 | } | ||
| 1521 | return vaddr; | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ||
| 1525 | if (decl.link.elf.local_sym_index != 0) return; | ||
| 1526 | |||
| 1527 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); | ||
| 1528 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); | ||
| 1529 | |||
| 1530 | if (self.local_symbol_free_list.popOrNull()) |i| { | ||
| 1531 | log.debug("reusing symbol index {} for {}\n", .{ i, decl.name }); | ||
| 1532 | decl.link.elf.local_sym_index = i; | ||
| 1533 | } else { | ||
| 1534 | log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name }); | ||
| 1535 | decl.link.elf.local_sym_index = @intCast(u32, self.local_symbols.items.len); | ||
| 1536 | _ = self.local_symbols.addOneAssumeCapacity(); | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | if (self.offset_table_free_list.popOrNull()) |i| { | ||
| 1540 | decl.link.elf.offset_table_index = i; | ||
| 1541 | } else { | ||
| 1542 | decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len); | ||
| 1543 | _ = self.offset_table.addOneAssumeCapacity(); | ||
| 1544 | self.offset_table_count_dirty = true; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | ||
| 1548 | |||
| 1549 | self.local_symbols.items[decl.link.elf.local_sym_index] = .{ | ||
| 1550 | .st_name = 0, | ||
| 1551 | .st_info = 0, | ||
| 1552 | .st_other = 0, | ||
| 1553 | .st_shndx = 0, | ||
| 1554 | .st_value = phdr.p_vaddr, | ||
| 1555 | .st_size = 0, | ||
| 1556 | }; | ||
| 1557 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | ||
| 1561 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | ||
| 1562 | self.freeTextBlock(&decl.link.elf); | ||
| 1563 | if (decl.link.elf.local_sym_index != 0) { | ||
| 1564 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; | ||
| 1565 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; | ||
| 1566 | |||
| 1567 | self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; | ||
| 1568 | |||
| 1569 | decl.link.elf.local_sym_index = 0; | ||
| 1570 | } | ||
| 1571 | // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing | ||
| 1572 | // is desired for both. | ||
| 1573 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link.elf); | ||
| 1574 | if (decl.fn_link.elf.prev) |prev| { | ||
| 1575 | _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 1576 | prev.next = decl.fn_link.elf.next; | ||
| 1577 | if (decl.fn_link.elf.next) |next| { | ||
| 1578 | next.prev = prev; | ||
| 1579 | } else { | ||
| 1580 | self.dbg_line_fn_last = prev; | ||
| 1581 | } | ||
| 1582 | } else if (decl.fn_link.elf.next) |next| { | ||
| 1583 | self.dbg_line_fn_first = next; | ||
| 1584 | next.prev = null; | ||
| 1585 | } | ||
| 1586 | if (self.dbg_line_fn_first == &decl.fn_link.elf) { | ||
| 1587 | self.dbg_line_fn_first = null; | ||
| 1588 | } | ||
| 1589 | if (self.dbg_line_fn_last == &decl.fn_link.elf) { | ||
| 1590 | self.dbg_line_fn_last = null; | ||
| 1591 | } | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ||
| 1595 | const tracy = trace(@src()); | ||
| 1596 | defer tracy.end(); | ||
| 1597 | |||
| 1598 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1599 | defer code_buffer.deinit(); | ||
| 1600 | |||
| 1601 | var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1602 | defer dbg_line_buffer.deinit(); | ||
| 1603 | |||
| 1604 | var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator); | ||
| 1605 | defer dbg_info_buffer.deinit(); | ||
| 1606 | |||
| 1607 | var dbg_info_type_relocs: File.DbgInfoTypeRelocsTable = .{}; | ||
| 1608 | defer { | ||
| 1609 | for (dbg_info_type_relocs.items()) |*entry| { | ||
| 1610 | entry.value.relocs.deinit(self.base.allocator); | ||
| 1611 | } | ||
| 1612 | dbg_info_type_relocs.deinit(self.base.allocator); | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 1616 | const is_fn: bool = switch (typed_value.ty.zigTypeTag()) { | ||
| 1617 | .Fn => true, | ||
| 1618 | else => false, | ||
| 1619 | }; | ||
| 1620 | if (is_fn) { | ||
| 1621 | //if (mem.eql(u8, mem.spanZ(decl.name), "add")) { | ||
| 1622 | // typed_value.val.cast(Value.Payload.Function).?.func.dump(module.*); | ||
| 1623 | //} | ||
| 1624 | |||
| 1625 | // For functions we need to add a prologue to the debug line program. | ||
| 1626 | try dbg_line_buffer.ensureCapacity(26); | ||
| 1627 | |||
| 1628 | const line_off: u28 = blk: { | ||
| 1629 | if (decl.scope.cast(Module.Scope.File)) |scope_file| { | ||
| 1630 | const tree = scope_file.contents.tree; | ||
| 1631 | const file_ast_decls = tree.root_node.decls(); | ||
| 1632 | // TODO Look into improving the performance here by adding a token-index-to-line | ||
| 1633 | // lookup table. Currently this involves scanning over the source code for newlines. | ||
| 1634 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; | ||
| 1635 | const block = fn_proto.body().?.castTag(.Block).?; | ||
| 1636 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); | ||
| 1637 | break :blk @intCast(u28, line_delta); | ||
| 1638 | } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { | ||
| 1639 | const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src; | ||
| 1640 | const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off); | ||
| 1641 | break :blk @intCast(u28, line_delta); | ||
| 1642 | } else { | ||
| 1643 | unreachable; | ||
| 1644 | } | ||
| 1645 | }; | ||
| 1646 | |||
| 1647 | const ptr_width_bytes = self.ptrWidthBytes(); | ||
| 1648 | dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ | ||
| 1649 | DW.LNS_extended_op, | ||
| 1650 | ptr_width_bytes + 1, | ||
| 1651 | DW.LNE_set_address, | ||
| 1652 | }); | ||
| 1653 | // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. | ||
| 1654 | assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); | ||
| 1655 | dbg_line_buffer.items.len += ptr_width_bytes; | ||
| 1656 | |||
| 1657 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); | ||
| 1658 | // This is the "relocatable" relative line offset from the previous function's end curly | ||
| 1659 | // to this function's begin curly. | ||
| 1660 | assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len); | ||
| 1661 | // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. | ||
| 1662 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); | ||
| 1663 | |||
| 1664 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); | ||
| 1665 | assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); | ||
| 1666 | // Once we support more than one source file, this will have the ability to be more | ||
| 1667 | // than one possible value. | ||
| 1668 | const file_index = 1; | ||
| 1669 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), file_index); | ||
| 1670 | |||
| 1671 | // Emit a line for the begin curly with prologue_end=false. The codegen will | ||
| 1672 | // do the work of setting prologue_end=true and epilogue_begin=true. | ||
| 1673 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); | ||
| 1674 | |||
| 1675 | // .debug_info subprogram | ||
| 1676 | const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1]; | ||
| 1677 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len); | ||
| 1678 | |||
| 1679 | const fn_ret_type = typed_value.ty.fnReturnType(); | ||
| 1680 | const fn_ret_has_bits = fn_ret_type.hasCodeGenBits(); | ||
| 1681 | if (fn_ret_has_bits) { | ||
| 1682 | dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram); | ||
| 1683 | } else { | ||
| 1684 | dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram_retvoid); | ||
| 1685 | } | ||
| 1686 | // These get overwritten after generating the machine code. These values are | ||
| 1687 | // "relocations" and have to be in this fixed place so that functions can be | ||
| 1688 | // moved in virtual address space. | ||
| 1689 | assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); | ||
| 1690 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT_low_pc, DW.FORM_addr | ||
| 1691 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); | ||
| 1692 | dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 | ||
| 1693 | if (fn_ret_has_bits) { | ||
| 1694 | const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, fn_ret_type); | ||
| 1695 | if (!gop.found_existing) { | ||
| 1696 | gop.entry.value = .{ | ||
| 1697 | .off = undefined, | ||
| 1698 | .relocs = .{}, | ||
| 1699 | }; | ||
| 1700 | } | ||
| 1701 | try gop.entry.value.relocs.append(self.base.allocator, @intCast(u32, dbg_info_buffer.items.len)); | ||
| 1702 | dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 | ||
| 1703 | } | ||
| 1704 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string | ||
| 1705 | } else { | ||
| 1706 | // TODO implement .debug_info for global variables | ||
| 1707 | } | ||
| 1708 | const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, &dbg_line_buffer, &dbg_info_buffer, &dbg_info_type_relocs); | ||
| 1709 | const code = switch (res) { | ||
| 1710 | .externally_managed => |x| x, | ||
| 1711 | .appended => code_buffer.items, | ||
| 1712 | .fail => |em| { | ||
| 1713 | decl.analysis = .codegen_failure; | ||
| 1714 | try module.failed_decls.put(module.gpa, decl, em); | ||
| 1715 | return; | ||
| 1716 | }, | ||
| 1717 | }; | ||
| 1718 | |||
| 1719 | const required_alignment = typed_value.ty.abiAlignment(self.base.options.target); | ||
| 1720 | |||
| 1721 | const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT; | ||
| 1722 | |||
| 1723 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() | ||
| 1724 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; | ||
| 1725 | if (local_sym.st_size != 0) { | ||
| 1726 | const capacity = decl.link.elf.capacity(self.*); | ||
| 1727 | const need_realloc = code.len > capacity or | ||
| 1728 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); | ||
| 1729 | if (need_realloc) { | ||
| 1730 | const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment); | ||
| 1731 | log.debug("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr }); | ||
| 1732 | if (vaddr != local_sym.st_value) { | ||
| 1733 | local_sym.st_value = vaddr; | ||
| 1734 | |||
| 1735 | log.debug(" (writing new offset table entry)\n", .{}); | ||
| 1736 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; | ||
| 1737 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | ||
| 1738 | } | ||
| 1739 | } else if (code.len < local_sym.st_size) { | ||
| 1740 | self.shrinkTextBlock(&decl.link.elf, code.len); | ||
| 1741 | } | ||
| 1742 | local_sym.st_size = code.len; | ||
| 1743 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name)); | ||
| 1744 | local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; | ||
| 1745 | local_sym.st_other = 0; | ||
| 1746 | local_sym.st_shndx = self.text_section_index.?; | ||
| 1747 | // TODO this write could be avoided if no fields of the symbol were changed. | ||
| 1748 | try self.writeSymbol(decl.link.elf.local_sym_index); | ||
| 1749 | } else { | ||
| 1750 | const decl_name = mem.spanZ(decl.name); | ||
| 1751 | const name_str_index = try self.makeString(decl_name); | ||
| 1752 | const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment); | ||
| 1753 | log.debug("allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr }); | ||
| 1754 | errdefer self.freeTextBlock(&decl.link.elf); | ||
| 1755 | |||
| 1756 | local_sym.* = .{ | ||
| 1757 | .st_name = name_str_index, | ||
| 1758 | .st_info = (elf.STB_LOCAL << 4) | stt_bits, | ||
| 1759 | .st_other = 0, | ||
| 1760 | .st_shndx = self.text_section_index.?, | ||
| 1761 | .st_value = vaddr, | ||
| 1762 | .st_size = code.len, | ||
| 1763 | }; | ||
| 1764 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; | ||
| 1765 | |||
| 1766 | try self.writeSymbol(decl.link.elf.local_sym_index); | ||
| 1767 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr; | ||
| 1771 | const file_offset = self.sections.items[self.text_section_index.?].sh_offset + section_offset; | ||
| 1772 | try self.base.file.?.pwriteAll(code, file_offset); | ||
| 1773 | |||
| 1774 | const target_endian = self.base.options.target.cpu.arch.endian(); | ||
| 1775 | |||
| 1776 | const text_block = &decl.link.elf; | ||
| 1777 | |||
| 1778 | // If the Decl is a function, we need to update the .debug_line program. | ||
| 1779 | if (is_fn) { | ||
| 1780 | // Perform the relocations based on vaddr. | ||
| 1781 | switch (self.ptr_width) { | ||
| 1782 | .p32 => { | ||
| 1783 | { | ||
| 1784 | const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..4]; | ||
| 1785 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_value), target_endian); | ||
| 1786 | } | ||
| 1787 | { | ||
| 1788 | const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..4]; | ||
| 1789 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_value), target_endian); | ||
| 1790 | } | ||
| 1791 | }, | ||
| 1792 | .p64 => { | ||
| 1793 | { | ||
| 1794 | const ptr = dbg_line_buffer.items[dbg_line_vaddr_reloc_index..][0..8]; | ||
| 1795 | mem.writeInt(u64, ptr, local_sym.st_value, target_endian); | ||
| 1796 | } | ||
| 1797 | { | ||
| 1798 | const ptr = dbg_info_buffer.items[dbg_info_low_pc_reloc_index..][0..8]; | ||
| 1799 | mem.writeInt(u64, ptr, local_sym.st_value, target_endian); | ||
| 1800 | } | ||
| 1801 | }, | ||
| 1802 | } | ||
| 1803 | { | ||
| 1804 | const ptr = dbg_info_buffer.items[self.getRelocDbgInfoSubprogramHighPC()..][0..4]; | ||
| 1805 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_size), target_endian); | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); | ||
| 1809 | |||
| 1810 | // Now we have the full contents and may allocate a region to store it. | ||
| 1811 | |||
| 1812 | // This logic is nearly identical to the logic below in `updateDeclDebugInfo` for | ||
| 1813 | // `TextBlock` and the .debug_info. If you are editing this logic, you | ||
| 1814 | // probably need to edit that logic too. | ||
| 1815 | |||
| 1816 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | ||
| 1817 | const src_fn = &decl.fn_link.elf; | ||
| 1818 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); | ||
| 1819 | if (self.dbg_line_fn_last) |last| { | ||
| 1820 | if (src_fn.next) |next| { | ||
| 1821 | // Update existing function - non-last item. | ||
| 1822 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { | ||
| 1823 | // It grew too big, so we move it to a new location. | ||
| 1824 | if (src_fn.prev) |prev| { | ||
| 1825 | _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 1826 | prev.next = src_fn.next; | ||
| 1827 | } | ||
| 1828 | next.prev = src_fn.prev; | ||
| 1829 | src_fn.next = null; | ||
| 1830 | // Populate where it used to be with NOPs. | ||
| 1831 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | ||
| 1832 | try self.pwriteDbgLineNops(0, &[0]u8{}, src_fn.len, file_pos); | ||
| 1833 | // TODO Look at the free list before appending at the end. | ||
| 1834 | src_fn.prev = last; | ||
| 1835 | last.next = src_fn; | ||
| 1836 | self.dbg_line_fn_last = src_fn; | ||
| 1837 | |||
| 1838 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); | ||
| 1839 | } | ||
| 1840 | } else if (src_fn.prev == null) { | ||
| 1841 | // Append new function. | ||
| 1842 | // TODO Look at the free list before appending at the end. | ||
| 1843 | src_fn.prev = last; | ||
| 1844 | last.next = src_fn; | ||
| 1845 | self.dbg_line_fn_last = src_fn; | ||
| 1846 | |||
| 1847 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); | ||
| 1848 | } | ||
| 1849 | } else { | ||
| 1850 | // This is the first function of the Line Number Program. | ||
| 1851 | self.dbg_line_fn_first = src_fn; | ||
| 1852 | self.dbg_line_fn_last = src_fn; | ||
| 1853 | |||
| 1854 | src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | const last_src_fn = self.dbg_line_fn_last.?; | ||
| 1858 | const needed_size = last_src_fn.off + last_src_fn.len; | ||
| 1859 | if (needed_size != debug_line_sect.sh_size) { | ||
| 1860 | if (needed_size > self.allocatedSize(debug_line_sect.sh_offset)) { | ||
| 1861 | const new_offset = self.findFreeSpace(needed_size, 1); | ||
| 1862 | const existing_size = last_src_fn.off; | ||
| 1863 | log.debug("moving .debug_line section: {} bytes from 0x{x} to 0x{x}\n", .{ | ||
| 1864 | existing_size, | ||
| 1865 | debug_line_sect.sh_offset, | ||
| 1866 | new_offset, | ||
| 1867 | }); | ||
| 1868 | const amt = try self.base.file.?.copyRangeAll(debug_line_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 1869 | if (amt != existing_size) return error.InputOutput; | ||
| 1870 | debug_line_sect.sh_offset = new_offset; | ||
| 1871 | } | ||
| 1872 | debug_line_sect.sh_size = needed_size; | ||
| 1873 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 1874 | self.debug_line_header_dirty = true; | ||
| 1875 | } | ||
| 1876 | const prev_padding_size: u32 = if (src_fn.prev) |prev| src_fn.off - (prev.off + prev.len) else 0; | ||
| 1877 | const next_padding_size: u32 = if (src_fn.next) |next| next.off - (src_fn.off + src_fn.len) else 0; | ||
| 1878 | |||
| 1879 | // We only have support for one compilation unit so far, so the offsets are directly | ||
| 1880 | // from the .debug_line section. | ||
| 1881 | const file_pos = debug_line_sect.sh_offset + src_fn.off; | ||
| 1882 | try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); | ||
| 1883 | |||
| 1884 | // .debug_info - End the TAG_subprogram children. | ||
| 1885 | try dbg_info_buffer.append(0); | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | // Now we emit the .debug_info types of the Decl. These will count towards the size of | ||
| 1889 | // the buffer, so we have to do it before computing the offset, and we can't perform the actual | ||
| 1890 | // relocations yet. | ||
| 1891 | for (dbg_info_type_relocs.items()) |*entry| { | ||
| 1892 | entry.value.off = @intCast(u32, dbg_info_buffer.items.len); | ||
| 1893 | try self.addDbgInfoType(entry.key, &dbg_info_buffer); | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | try self.updateDeclDebugInfoAllocation(text_block, @intCast(u32, dbg_info_buffer.items.len)); | ||
| 1897 | |||
| 1898 | // Now that we have the offset assigned we can finally perform type relocations. | ||
| 1899 | for (dbg_info_type_relocs.items()) |entry| { | ||
| 1900 | for (entry.value.relocs.items) |off| { | ||
| 1901 | mem.writeInt( | ||
| 1902 | u32, | ||
| 1903 | dbg_info_buffer.items[off..][0..4], | ||
| 1904 | text_block.dbg_info_off + entry.value.off, | ||
| 1905 | target_endian, | ||
| 1906 | ); | ||
| 1907 | } | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | try self.writeDeclDebugInfo(text_block, dbg_info_buffer.items); | ||
| 1911 | |||
| 1912 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | ||
| 1913 | const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{}; | ||
| 1914 | return self.updateDeclExports(module, decl, decl_exports); | ||
| 1915 | } | ||
| 1916 | |||
| 1917 | /// Asserts the type has codegen bits. | ||
| 1918 | fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void { | ||
| 1919 | switch (ty.zigTypeTag()) { | ||
| 1920 | .Void => unreachable, | ||
| 1921 | .NoReturn => unreachable, | ||
| 1922 | .Bool => { | ||
| 1923 | try dbg_info_buffer.appendSlice(&[_]u8{ | ||
| 1924 | abbrev_base_type, | ||
| 1925 | DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 | ||
| 1926 | 1, // DW.AT_byte_size, DW.FORM_data1 | ||
| 1927 | 'b', | ||
| 1928 | 'o', | ||
| 1929 | 'o', | ||
| 1930 | 'l', | ||
| 1931 | 0, // DW.AT_name, DW.FORM_string | ||
| 1932 | }); | ||
| 1933 | }, | ||
| 1934 | .Int => { | ||
| 1935 | const info = ty.intInfo(self.base.options.target); | ||
| 1936 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); | ||
| 1937 | dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); | ||
| 1938 | // DW.AT_encoding, DW.FORM_data1 | ||
| 1939 | dbg_info_buffer.appendAssumeCapacity(if (info.signed) DW.ATE_signed else DW.ATE_unsigned); | ||
| 1940 | // DW.AT_byte_size, DW.FORM_data1 | ||
| 1941 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); | ||
| 1942 | // DW.AT_name, DW.FORM_string | ||
| 1943 | try dbg_info_buffer.writer().print("{}\x00", .{ty}); | ||
| 1944 | }, | ||
| 1945 | else => { | ||
| 1946 | std.log.scoped(.compiler).err("TODO implement .debug_info for type '{}'", .{ty}); | ||
| 1947 | try dbg_info_buffer.append(abbrev_pad1); | ||
| 1948 | }, | ||
| 1949 | } | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | fn updateDeclDebugInfoAllocation(self: *Elf, text_block: *TextBlock, len: u32) !void { | ||
| 1953 | const tracy = trace(@src()); | ||
| 1954 | defer tracy.end(); | ||
| 1955 | |||
| 1956 | // This logic is nearly identical to the logic above in `updateDecl` for | ||
| 1957 | // `SrcFn` and the line number programs. If you are editing this logic, you | ||
| 1958 | // probably need to edit that logic too. | ||
| 1959 | |||
| 1960 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 1961 | text_block.dbg_info_len = len; | ||
| 1962 | if (self.dbg_info_decl_last) |last| { | ||
| 1963 | if (text_block.dbg_info_next) |next| { | ||
| 1964 | // Update existing Decl - non-last item. | ||
| 1965 | if (text_block.dbg_info_off + text_block.dbg_info_len + min_nop_size > next.dbg_info_off) { | ||
| 1966 | // It grew too big, so we move it to a new location. | ||
| 1967 | if (text_block.dbg_info_prev) |prev| { | ||
| 1968 | _ = self.dbg_info_decl_free_list.put(self.base.allocator, prev, {}) catch {}; | ||
| 1969 | prev.dbg_info_next = text_block.dbg_info_next; | ||
| 1970 | } | ||
| 1971 | next.dbg_info_prev = text_block.dbg_info_prev; | ||
| 1972 | text_block.dbg_info_next = null; | ||
| 1973 | // Populate where it used to be with NOPs. | ||
| 1974 | const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off; | ||
| 1975 | try self.pwriteDbgInfoNops(0, &[0]u8{}, text_block.dbg_info_len, false, file_pos); | ||
| 1976 | // TODO Look at the free list before appending at the end. | ||
| 1977 | text_block.dbg_info_prev = last; | ||
| 1978 | last.dbg_info_next = text_block; | ||
| 1979 | self.dbg_info_decl_last = text_block; | ||
| 1980 | |||
| 1981 | text_block.dbg_info_off = last.dbg_info_off + (last.dbg_info_len * alloc_num / alloc_den); | ||
| 1982 | } | ||
| 1983 | } else if (text_block.dbg_info_prev == null) { | ||
| 1984 | // Append new Decl. | ||
| 1985 | // TODO Look at the free list before appending at the end. | ||
| 1986 | text_block.dbg_info_prev = last; | ||
| 1987 | last.dbg_info_next = text_block; | ||
| 1988 | self.dbg_info_decl_last = text_block; | ||
| 1989 | |||
| 1990 | text_block.dbg_info_off = last.dbg_info_off + (last.dbg_info_len * alloc_num / alloc_den); | ||
| 1991 | } | ||
| 1992 | } else { | ||
| 1993 | // This is the first Decl of the .debug_info | ||
| 1994 | self.dbg_info_decl_first = text_block; | ||
| 1995 | self.dbg_info_decl_last = text_block; | ||
| 1996 | |||
| 1997 | text_block.dbg_info_off = self.dbgInfoNeededHeaderBytes() * alloc_num / alloc_den; | ||
| 1998 | } | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | fn writeDeclDebugInfo(self: *Elf, text_block: *TextBlock, dbg_info_buf: []const u8) !void { | ||
| 2002 | const tracy = trace(@src()); | ||
| 2003 | defer tracy.end(); | ||
| 2004 | |||
| 2005 | // This logic is nearly identical to the logic above in `updateDecl` for | ||
| 2006 | // `SrcFn` and the line number programs. If you are editing this logic, you | ||
| 2007 | // probably need to edit that logic too. | ||
| 2008 | |||
| 2009 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | ||
| 2010 | |||
| 2011 | const last_decl = self.dbg_info_decl_last.?; | ||
| 2012 | // +1 for a trailing zero to end the children of the decl tag. | ||
| 2013 | const needed_size = last_decl.dbg_info_off + last_decl.dbg_info_len + 1; | ||
| 2014 | if (needed_size != debug_info_sect.sh_size) { | ||
| 2015 | if (needed_size > self.allocatedSize(debug_info_sect.sh_offset)) { | ||
| 2016 | const new_offset = self.findFreeSpace(needed_size, 1); | ||
| 2017 | const existing_size = last_decl.dbg_info_off; | ||
| 2018 | log.debug("moving .debug_info section: {} bytes from 0x{x} to 0x{x}\n", .{ | ||
| 2019 | existing_size, | ||
| 2020 | debug_info_sect.sh_offset, | ||
| 2021 | new_offset, | ||
| 2022 | }); | ||
| 2023 | const amt = try self.base.file.?.copyRangeAll(debug_info_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 2024 | if (amt != existing_size) return error.InputOutput; | ||
| 2025 | debug_info_sect.sh_offset = new_offset; | ||
| 2026 | } | ||
| 2027 | debug_info_sect.sh_size = needed_size; | ||
| 2028 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 2029 | self.debug_info_header_dirty = true; | ||
| 2030 | } | ||
| 2031 | const prev_padding_size: u32 = if (text_block.dbg_info_prev) |prev| | ||
| 2032 | text_block.dbg_info_off - (prev.dbg_info_off + prev.dbg_info_len) | ||
| 2033 | else | ||
| 2034 | 0; | ||
| 2035 | const next_padding_size: u32 = if (text_block.dbg_info_next) |next| | ||
| 2036 | next.dbg_info_off - (text_block.dbg_info_off + text_block.dbg_info_len) | ||
| 2037 | else | ||
| 2038 | 0; | ||
| 2039 | |||
| 2040 | // To end the children of the decl tag. | ||
| 2041 | const trailing_zero = text_block.dbg_info_next == null; | ||
| 2042 | |||
| 2043 | // We only have support for one compilation unit so far, so the offsets are directly | ||
| 2044 | // from the .debug_info section. | ||
| 2045 | const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off; | ||
| 2046 | try self.pwriteDbgInfoNops(prev_padding_size, dbg_info_buf, next_padding_size, trailing_zero, file_pos); | ||
| 2047 | } | ||
| 2048 | |||
| 2049 | pub fn updateDeclExports( | ||
| 2050 | self: *Elf, | ||
| 2051 | module: *Module, | ||
| 2052 | decl: *const Module.Decl, | ||
| 2053 | exports: []const *Module.Export, | ||
| 2054 | ) !void { | ||
| 2055 | const tracy = trace(@src()); | ||
| 2056 | defer tracy.end(); | ||
| 2057 | |||
| 2058 | try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len); | ||
| 2059 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 2060 | if (decl.link.elf.local_sym_index == 0) return; | ||
| 2061 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; | ||
| 2062 | |||
| 2063 | for (exports) |exp| { | ||
| 2064 | if (exp.options.section) |section_name| { | ||
| 2065 | if (!mem.eql(u8, section_name, ".text")) { | ||
| 2066 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | ||
| 2067 | module.failed_exports.putAssumeCapacityNoClobber( | ||
| 2068 | exp, | ||
| 2069 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}), | ||
| 2070 | ); | ||
| 2071 | continue; | ||
| 2072 | } | ||
| 2073 | } | ||
| 2074 | const stb_bits: u8 = switch (exp.options.linkage) { | ||
| 2075 | .Internal => elf.STB_LOCAL, | ||
| 2076 | .Strong => blk: { | ||
| 2077 | if (mem.eql(u8, exp.options.name, "_start")) { | ||
| 2078 | self.entry_addr = decl_sym.st_value; | ||
| 2079 | } | ||
| 2080 | break :blk elf.STB_GLOBAL; | ||
| 2081 | }, | ||
| 2082 | .Weak => elf.STB_WEAK, | ||
| 2083 | .LinkOnce => { | ||
| 2084 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | ||
| 2085 | module.failed_exports.putAssumeCapacityNoClobber( | ||
| 2086 | exp, | ||
| 2087 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), | ||
| 2088 | ); | ||
| 2089 | continue; | ||
| 2090 | }, | ||
| 2091 | }; | ||
| 2092 | const stt_bits: u8 = @truncate(u4, decl_sym.st_info); | ||
| 2093 | if (exp.link.sym_index) |i| { | ||
| 2094 | const sym = &self.global_symbols.items[i]; | ||
| 2095 | sym.* = .{ | ||
| 2096 | .st_name = try self.updateString(sym.st_name, exp.options.name), | ||
| 2097 | .st_info = (stb_bits << 4) | stt_bits, | ||
| 2098 | .st_other = 0, | ||
| 2099 | .st_shndx = self.text_section_index.?, | ||
| 2100 | .st_value = decl_sym.st_value, | ||
| 2101 | .st_size = decl_sym.st_size, | ||
| 2102 | }; | ||
| 2103 | } else { | ||
| 2104 | const name = try self.makeString(exp.options.name); | ||
| 2105 | const i = if (self.global_symbol_free_list.popOrNull()) |i| i else blk: { | ||
| 2106 | _ = self.global_symbols.addOneAssumeCapacity(); | ||
| 2107 | break :blk self.global_symbols.items.len - 1; | ||
| 2108 | }; | ||
| 2109 | self.global_symbols.items[i] = .{ | ||
| 2110 | .st_name = name, | ||
| 2111 | .st_info = (stb_bits << 4) | stt_bits, | ||
| 2112 | .st_other = 0, | ||
| 2113 | .st_shndx = self.text_section_index.?, | ||
| 2114 | .st_value = decl_sym.st_value, | ||
| 2115 | .st_size = decl_sym.st_size, | ||
| 2116 | }; | ||
| 2117 | |||
| 2118 | exp.link.sym_index = @intCast(u32, i); | ||
| 2119 | } | ||
| 2120 | } | ||
| 2121 | } | ||
| 2122 | |||
| 2123 | /// Must be called only after a successful call to `updateDecl`. | ||
| 2124 | pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Decl) !void { | ||
| 2125 | const tracy = trace(@src()); | ||
| 2126 | defer tracy.end(); | ||
| 2127 | |||
| 2128 | const scope_file = decl.scope.cast(Module.Scope.File).?; | ||
| 2129 | const tree = scope_file.contents.tree; | ||
| 2130 | const file_ast_decls = tree.root_node.decls(); | ||
| 2131 | // TODO Look into improving the performance here by adding a token-index-to-line | ||
| 2132 | // lookup table. Currently this involves scanning over the source code for newlines. | ||
| 2133 | const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; | ||
| 2134 | const block = fn_proto.body().?.castTag(.Block).?; | ||
| 2135 | const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); | ||
| 2136 | const casted_line_off = @intCast(u28, line_delta); | ||
| 2137 | |||
| 2138 | const shdr = &self.sections.items[self.debug_line_section_index.?]; | ||
| 2139 | const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff(); | ||
| 2140 | var data: [4]u8 = undefined; | ||
| 2141 | leb128.writeUnsignedFixed(4, &data, casted_line_off); | ||
| 2142 | try self.base.file.?.pwriteAll(&data, file_pos); | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | pub fn deleteExport(self: *Elf, exp: Export) void { | ||
| 2146 | const sym_index = exp.sym_index orelse return; | ||
| 2147 | self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {}; | ||
| 2148 | self.global_symbols.items[sym_index].st_info = 0; | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | fn writeProgHeader(self: *Elf, index: usize) !void { | ||
| 2152 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2153 | const offset = self.program_headers.items[index].p_offset; | ||
| 2154 | switch (self.base.options.target.cpu.arch.ptrBitWidth()) { | ||
| 2155 | 32 => { | ||
| 2156 | var phdr = [1]elf.Elf32_Phdr{progHeaderTo32(self.program_headers.items[index])}; | ||
| 2157 | if (foreign_endian) { | ||
| 2158 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); | ||
| 2159 | } | ||
| 2160 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | ||
| 2161 | }, | ||
| 2162 | 64 => { | ||
| 2163 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; | ||
| 2164 | if (foreign_endian) { | ||
| 2165 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); | ||
| 2166 | } | ||
| 2167 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | ||
| 2168 | }, | ||
| 2169 | else => return error.UnsupportedArchitecture, | ||
| 2170 | } | ||
| 2171 | } | ||
| 2172 | |||
| 2173 | fn writeSectHeader(self: *Elf, index: usize) !void { | ||
| 2174 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2175 | switch (self.base.options.target.cpu.arch.ptrBitWidth()) { | ||
| 2176 | 32 => { | ||
| 2177 | var shdr: [1]elf.Elf32_Shdr = undefined; | ||
| 2178 | shdr[0] = sectHeaderTo32(self.sections.items[index]); | ||
| 2179 | if (foreign_endian) { | ||
| 2180 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); | ||
| 2181 | } | ||
| 2182 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr); | ||
| 2183 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); | ||
| 2184 | }, | ||
| 2185 | 64 => { | ||
| 2186 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; | ||
| 2187 | if (foreign_endian) { | ||
| 2188 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); | ||
| 2189 | } | ||
| 2190 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr); | ||
| 2191 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); | ||
| 2192 | }, | ||
| 2193 | else => return error.UnsupportedArchitecture, | ||
| 2194 | } | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | fn writeOffsetTableEntry(self: *Elf, index: usize) !void { | ||
| 2198 | const shdr = &self.sections.items[self.got_section_index.?]; | ||
| 2199 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | ||
| 2200 | const entry_size: u16 = self.ptrWidthBytes(); | ||
| 2201 | if (self.offset_table_count_dirty) { | ||
| 2202 | // TODO Also detect virtual address collisions. | ||
| 2203 | const allocated_size = self.allocatedSize(shdr.sh_offset); | ||
| 2204 | const needed_size = self.local_symbols.items.len * entry_size; | ||
| 2205 | if (needed_size > allocated_size) { | ||
| 2206 | // Must move the entire got section. | ||
| 2207 | const new_offset = self.findFreeSpace(needed_size, entry_size); | ||
| 2208 | const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size); | ||
| 2209 | if (amt != shdr.sh_size) return error.InputOutput; | ||
| 2210 | shdr.sh_offset = new_offset; | ||
| 2211 | phdr.p_offset = new_offset; | ||
| 2212 | } | ||
| 2213 | shdr.sh_size = needed_size; | ||
| 2214 | phdr.p_memsz = needed_size; | ||
| 2215 | phdr.p_filesz = needed_size; | ||
| 2216 | |||
| 2217 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty | ||
| 2218 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty | ||
| 2219 | |||
| 2220 | self.offset_table_count_dirty = false; | ||
| 2221 | } | ||
| 2222 | const endian = self.base.options.target.cpu.arch.endian(); | ||
| 2223 | const off = shdr.sh_offset + @as(u64, entry_size) * index; | ||
| 2224 | switch (self.ptr_width) { | ||
| 2225 | .p32 => { | ||
| 2226 | var buf: [4]u8 = undefined; | ||
| 2227 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); | ||
| 2228 | try self.base.file.?.pwriteAll(&buf, off); | ||
| 2229 | }, | ||
| 2230 | .p64 => { | ||
| 2231 | var buf: [8]u8 = undefined; | ||
| 2232 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); | ||
| 2233 | try self.base.file.?.pwriteAll(&buf, off); | ||
| 2234 | }, | ||
| 2235 | } | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | fn writeSymbol(self: *Elf, index: usize) !void { | ||
| 2239 | const tracy = trace(@src()); | ||
| 2240 | defer tracy.end(); | ||
| 2241 | |||
| 2242 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; | ||
| 2243 | // Make sure we are not pointlessly writing symbol data that will have to get relocated | ||
| 2244 | // due to running out of space. | ||
| 2245 | if (self.local_symbols.items.len != syms_sect.sh_info) { | ||
| 2246 | const sym_size: u64 = switch (self.ptr_width) { | ||
| 2247 | .p32 => @sizeOf(elf.Elf32_Sym), | ||
| 2248 | .p64 => @sizeOf(elf.Elf64_Sym), | ||
| 2249 | }; | ||
| 2250 | const sym_align: u16 = switch (self.ptr_width) { | ||
| 2251 | .p32 => @alignOf(elf.Elf32_Sym), | ||
| 2252 | .p64 => @alignOf(elf.Elf64_Sym), | ||
| 2253 | }; | ||
| 2254 | const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; | ||
| 2255 | if (needed_size > self.allocatedSize(syms_sect.sh_offset)) { | ||
| 2256 | // Move all the symbols to a new file location. | ||
| 2257 | const new_offset = self.findFreeSpace(needed_size, sym_align); | ||
| 2258 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; | ||
| 2259 | const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size); | ||
| 2260 | if (amt != existing_size) return error.InputOutput; | ||
| 2261 | syms_sect.sh_offset = new_offset; | ||
| 2262 | } | ||
| 2263 | syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len); | ||
| 2264 | syms_sect.sh_size = needed_size; // anticipating adding the global symbols later | ||
| 2265 | self.shdr_table_dirty = true; // TODO look into only writing one section | ||
| 2266 | } | ||
| 2267 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2268 | switch (self.ptr_width) { | ||
| 2269 | .p32 => { | ||
| 2270 | var sym = [1]elf.Elf32_Sym{ | ||
| 2271 | .{ | ||
| 2272 | .st_name = self.local_symbols.items[index].st_name, | ||
| 2273 | .st_value = @intCast(u32, self.local_symbols.items[index].st_value), | ||
| 2274 | .st_size = @intCast(u32, self.local_symbols.items[index].st_size), | ||
| 2275 | .st_info = self.local_symbols.items[index].st_info, | ||
| 2276 | .st_other = self.local_symbols.items[index].st_other, | ||
| 2277 | .st_shndx = self.local_symbols.items[index].st_shndx, | ||
| 2278 | }, | ||
| 2279 | }; | ||
| 2280 | if (foreign_endian) { | ||
| 2281 | bswapAllFields(elf.Elf32_Sym, &sym[0]); | ||
| 2282 | } | ||
| 2283 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index; | ||
| 2284 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | ||
| 2285 | }, | ||
| 2286 | .p64 => { | ||
| 2287 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; | ||
| 2288 | if (foreign_endian) { | ||
| 2289 | bswapAllFields(elf.Elf64_Sym, &sym[0]); | ||
| 2290 | } | ||
| 2291 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index; | ||
| 2292 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | ||
| 2293 | }, | ||
| 2294 | } | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | fn writeAllGlobalSymbols(self: *Elf) !void { | ||
| 2298 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; | ||
| 2299 | const sym_size: u64 = switch (self.ptr_width) { | ||
| 2300 | .p32 => @sizeOf(elf.Elf32_Sym), | ||
| 2301 | .p64 => @sizeOf(elf.Elf64_Sym), | ||
| 2302 | }; | ||
| 2303 | const foreign_endian = self.base.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); | ||
| 2304 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; | ||
| 2305 | switch (self.ptr_width) { | ||
| 2306 | .p32 => { | ||
| 2307 | const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len); | ||
| 2308 | defer self.base.allocator.free(buf); | ||
| 2309 | |||
| 2310 | for (buf) |*sym, i| { | ||
| 2311 | sym.* = .{ | ||
| 2312 | .st_name = self.global_symbols.items[i].st_name, | ||
| 2313 | .st_value = @intCast(u32, self.global_symbols.items[i].st_value), | ||
| 2314 | .st_size = @intCast(u32, self.global_symbols.items[i].st_size), | ||
| 2315 | .st_info = self.global_symbols.items[i].st_info, | ||
| 2316 | .st_other = self.global_symbols.items[i].st_other, | ||
| 2317 | .st_shndx = self.global_symbols.items[i].st_shndx, | ||
| 2318 | }; | ||
| 2319 | if (foreign_endian) { | ||
| 2320 | bswapAllFields(elf.Elf32_Sym, sym); | ||
| 2321 | } | ||
| 2322 | } | ||
| 2323 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | ||
| 2324 | }, | ||
| 2325 | .p64 => { | ||
| 2326 | const buf = try self.base.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); | ||
| 2327 | defer self.base.allocator.free(buf); | ||
| 2328 | |||
| 2329 | for (buf) |*sym, i| { | ||
| 2330 | sym.* = .{ | ||
| 2331 | .st_name = self.global_symbols.items[i].st_name, | ||
| 2332 | .st_value = self.global_symbols.items[i].st_value, | ||
| 2333 | .st_size = self.global_symbols.items[i].st_size, | ||
| 2334 | .st_info = self.global_symbols.items[i].st_info, | ||
| 2335 | .st_other = self.global_symbols.items[i].st_other, | ||
| 2336 | .st_shndx = self.global_symbols.items[i].st_shndx, | ||
| 2337 | }; | ||
| 2338 | if (foreign_endian) { | ||
| 2339 | bswapAllFields(elf.Elf64_Sym, sym); | ||
| 2340 | } | ||
| 2341 | } | ||
| 2342 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | ||
| 2343 | }, | ||
| 2344 | } | ||
| 2345 | } | ||
| 2346 | |||
| 2347 | fn ptrWidthBytes(self: Elf) u8 { | ||
| 2348 | return switch (self.ptr_width) { | ||
| 2349 | .p32 => 4, | ||
| 2350 | .p64 => 8, | ||
| 2351 | }; | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | /// The reloc offset for the virtual address of a function in its Line Number Program. | ||
| 2355 | /// Size is a virtual address integer. | ||
| 2356 | const dbg_line_vaddr_reloc_index = 3; | ||
| 2357 | /// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. | ||
| 2358 | /// Size is a virtual address integer. | ||
| 2359 | const dbg_info_low_pc_reloc_index = 1; | ||
| 2360 | |||
| 2361 | /// The reloc offset for the line offset of a function from the previous function's line. | ||
| 2362 | /// It's a fixed-size 4-byte ULEB128. | ||
| 2363 | fn getRelocDbgLineOff(self: Elf) usize { | ||
| 2364 | return dbg_line_vaddr_reloc_index + self.ptrWidthBytes() + 1; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | fn getRelocDbgFileIndex(self: Elf) usize { | ||
| 2368 | return self.getRelocDbgLineOff() + 5; | ||
| 2369 | } | ||
| 2370 | |||
| 2371 | fn getRelocDbgInfoSubprogramHighPC(self: Elf) u32 { | ||
| 2372 | return dbg_info_low_pc_reloc_index + self.ptrWidthBytes(); | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | fn dbgLineNeededHeaderBytes(self: Elf) u32 { | ||
| 2376 | const directory_entry_format_count = 1; | ||
| 2377 | const file_name_entry_format_count = 1; | ||
| 2378 | const directory_count = 1; | ||
| 2379 | const file_name_count = 1; | ||
| 2380 | return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + | ||
| 2381 | directory_count * 8 + file_name_count * 8 + | ||
| 2382 | // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like | ||
| 2383 | // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. | ||
| 2384 | self.base.options.root_pkg.root_src_dir_path.len + | ||
| 2385 | self.base.options.root_pkg.root_src_path.len); | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | fn dbgInfoNeededHeaderBytes(self: Elf) u32 { | ||
| 2389 | return 120; | ||
| 2390 | } | ||
| 2391 | |||
| 2392 | const min_nop_size = 2; | ||
| 2393 | |||
| 2394 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of | ||
| 2395 | /// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes | ||
| 2396 | /// are less than 126,976 bytes (if this limit is ever reached, this function can be | ||
| 2397 | /// improved to make more than one pwritev call, or the limit can be raised by a fixed | ||
| 2398 | /// amount by increasing the length of `vecs`). | ||
| 2399 | fn pwriteDbgLineNops( | ||
| 2400 | self: *Elf, | ||
| 2401 | prev_padding_size: usize, | ||
| 2402 | buf: []const u8, | ||
| 2403 | next_padding_size: usize, | ||
| 2404 | offset: usize, | ||
| 2405 | ) !void { | ||
| 2406 | const tracy = trace(@src()); | ||
| 2407 | defer tracy.end(); | ||
| 2408 | |||
| 2409 | const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; | ||
| 2410 | const three_byte_nop = [3]u8{ DW.LNS_advance_pc, 0b1000_0000, 0 }; | ||
| 2411 | var vecs: [32]std.os.iovec_const = undefined; | ||
| 2412 | var vec_index: usize = 0; | ||
| 2413 | { | ||
| 2414 | var padding_left = prev_padding_size; | ||
| 2415 | if (padding_left % 2 != 0) { | ||
| 2416 | vecs[vec_index] = .{ | ||
| 2417 | .iov_base = &three_byte_nop, | ||
| 2418 | .iov_len = three_byte_nop.len, | ||
| 2419 | }; | ||
| 2420 | vec_index += 1; | ||
| 2421 | padding_left -= three_byte_nop.len; | ||
| 2422 | } | ||
| 2423 | while (padding_left > page_of_nops.len) { | ||
| 2424 | vecs[vec_index] = .{ | ||
| 2425 | .iov_base = &page_of_nops, | ||
| 2426 | .iov_len = page_of_nops.len, | ||
| 2427 | }; | ||
| 2428 | vec_index += 1; | ||
| 2429 | padding_left -= page_of_nops.len; | ||
| 2430 | } | ||
| 2431 | if (padding_left > 0) { | ||
| 2432 | vecs[vec_index] = .{ | ||
| 2433 | .iov_base = &page_of_nops, | ||
| 2434 | .iov_len = padding_left, | ||
| 2435 | }; | ||
| 2436 | vec_index += 1; | ||
| 2437 | } | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | vecs[vec_index] = .{ | ||
| 2441 | .iov_base = buf.ptr, | ||
| 2442 | .iov_len = buf.len, | ||
| 2443 | }; | ||
| 2444 | vec_index += 1; | ||
| 2445 | |||
| 2446 | { | ||
| 2447 | var padding_left = next_padding_size; | ||
| 2448 | if (padding_left % 2 != 0) { | ||
| 2449 | vecs[vec_index] = .{ | ||
| 2450 | .iov_base = &three_byte_nop, | ||
| 2451 | .iov_len = three_byte_nop.len, | ||
| 2452 | }; | ||
| 2453 | vec_index += 1; | ||
| 2454 | padding_left -= three_byte_nop.len; | ||
| 2455 | } | ||
| 2456 | while (padding_left > page_of_nops.len) { | ||
| 2457 | vecs[vec_index] = .{ | ||
| 2458 | .iov_base = &page_of_nops, | ||
| 2459 | .iov_len = page_of_nops.len, | ||
| 2460 | }; | ||
| 2461 | vec_index += 1; | ||
| 2462 | padding_left -= page_of_nops.len; | ||
| 2463 | } | ||
| 2464 | if (padding_left > 0) { | ||
| 2465 | vecs[vec_index] = .{ | ||
| 2466 | .iov_base = &page_of_nops, | ||
| 2467 | .iov_len = padding_left, | ||
| 2468 | }; | ||
| 2469 | vec_index += 1; | ||
| 2470 | } | ||
| 2471 | } | ||
| 2472 | try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of | ||
| 2476 | /// bytes of padding. | ||
| 2477 | fn pwriteDbgInfoNops( | ||
| 2478 | self: *Elf, | ||
| 2479 | prev_padding_size: usize, | ||
| 2480 | buf: []const u8, | ||
| 2481 | next_padding_size: usize, | ||
| 2482 | trailing_zero: bool, | ||
| 2483 | offset: usize, | ||
| 2484 | ) !void { | ||
| 2485 | const tracy = trace(@src()); | ||
| 2486 | defer tracy.end(); | ||
| 2487 | |||
| 2488 | const page_of_nops = [1]u8{abbrev_pad1} ** 4096; | ||
| 2489 | var vecs: [32]std.os.iovec_const = undefined; | ||
| 2490 | var vec_index: usize = 0; | ||
| 2491 | { | ||
| 2492 | var padding_left = prev_padding_size; | ||
| 2493 | while (padding_left > page_of_nops.len) { | ||
| 2494 | vecs[vec_index] = .{ | ||
| 2495 | .iov_base = &page_of_nops, | ||
| 2496 | .iov_len = page_of_nops.len, | ||
| 2497 | }; | ||
| 2498 | vec_index += 1; | ||
| 2499 | padding_left -= page_of_nops.len; | ||
| 2500 | } | ||
| 2501 | if (padding_left > 0) { | ||
| 2502 | vecs[vec_index] = .{ | ||
| 2503 | .iov_base = &page_of_nops, | ||
| 2504 | .iov_len = padding_left, | ||
| 2505 | }; | ||
| 2506 | vec_index += 1; | ||
| 2507 | } | ||
| 2508 | } | ||
| 2509 | |||
| 2510 | vecs[vec_index] = .{ | ||
| 2511 | .iov_base = buf.ptr, | ||
| 2512 | .iov_len = buf.len, | ||
| 2513 | }; | ||
| 2514 | vec_index += 1; | ||
| 2515 | |||
| 2516 | { | ||
| 2517 | var padding_left = next_padding_size; | ||
| 2518 | while (padding_left > page_of_nops.len) { | ||
| 2519 | vecs[vec_index] = .{ | ||
| 2520 | .iov_base = &page_of_nops, | ||
| 2521 | .iov_len = page_of_nops.len, | ||
| 2522 | }; | ||
| 2523 | vec_index += 1; | ||
| 2524 | padding_left -= page_of_nops.len; | ||
| 2525 | } | ||
| 2526 | if (padding_left > 0) { | ||
| 2527 | vecs[vec_index] = .{ | ||
| 2528 | .iov_base = &page_of_nops, | ||
| 2529 | .iov_len = padding_left, | ||
| 2530 | }; | ||
| 2531 | vec_index += 1; | ||
| 2532 | } | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | if (trailing_zero) { | ||
| 2536 | var zbuf = [1]u8{0}; | ||
| 2537 | vecs[vec_index] = .{ | ||
| 2538 | .iov_base = &zbuf, | ||
| 2539 | .iov_len = zbuf.len, | ||
| 2540 | }; | ||
| 2541 | vec_index += 1; | ||
| 2542 | } | ||
| 2543 | |||
| 2544 | try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); | ||
| 2545 | } | ||
| 2546 | |||
| 2547 | /// Saturating multiplication | ||
| 2548 | fn satMul(a: anytype, b: anytype) @TypeOf(a, b) { | ||
| 2549 | const T = @TypeOf(a, b); | ||
| 2550 | return std.math.mul(T, a, b) catch std.math.maxInt(T); | ||
| 2551 | } | ||
| 2552 | |||
| 2553 | fn bswapAllFields(comptime S: type, ptr: *S) void { | ||
| 2554 | @panic("TODO implement bswapAllFields"); | ||
| 2555 | } | ||
| 2556 | |||
| 2557 | fn progHeaderTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { | ||
| 2558 | return .{ | ||
| 2559 | .p_type = phdr.p_type, | ||
| 2560 | .p_flags = phdr.p_flags, | ||
| 2561 | .p_offset = @intCast(u32, phdr.p_offset), | ||
| 2562 | .p_vaddr = @intCast(u32, phdr.p_vaddr), | ||
| 2563 | .p_paddr = @intCast(u32, phdr.p_paddr), | ||
| 2564 | .p_filesz = @intCast(u32, phdr.p_filesz), | ||
| 2565 | .p_memsz = @intCast(u32, phdr.p_memsz), | ||
| 2566 | .p_align = @intCast(u32, phdr.p_align), | ||
| 2567 | }; | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | fn sectHeaderTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { | ||
| 2571 | return .{ | ||
| 2572 | .sh_name = shdr.sh_name, | ||
| 2573 | .sh_type = shdr.sh_type, | ||
| 2574 | .sh_flags = @intCast(u32, shdr.sh_flags), | ||
| 2575 | .sh_addr = @intCast(u32, shdr.sh_addr), | ||
| 2576 | .sh_offset = @intCast(u32, shdr.sh_offset), | ||
| 2577 | .sh_size = @intCast(u32, shdr.sh_size), | ||
| 2578 | .sh_link = shdr.sh_link, | ||
| 2579 | .sh_info = shdr.sh_info, | ||
| 2580 | .sh_addralign = @intCast(u32, shdr.sh_addralign), | ||
| 2581 | .sh_entsize = @intCast(u32, shdr.sh_entsize), | ||
| 2582 | }; | ||
| 2583 | } | ||
src-self-hosted/link/MachO.zig+128-5| ... | @@ -4,15 +4,29 @@ const std = @import("std"); | ... | @@ -4,15 +4,29 @@ const std = @import("std"); |
| 4 | const Allocator = std.mem.Allocator; | 4 | const Allocator = std.mem.Allocator; |
| 5 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 6 | const fs = std.fs; | 6 | const fs = std.fs; |
| 7 | const log = std.log.scoped(.link); | ||
| 8 | const macho = std.macho; | ||
| 9 | const math = std.math; | ||
| 10 | const mem = std.mem; | ||
| 7 | 11 | ||
| 8 | const Module = @import("../Module.zig"); | 12 | const Module = @import("../Module.zig"); |
| 9 | const link = @import("../link.zig"); | 13 | const link = @import("../link.zig"); |
| 10 | const File = link.File; | 14 | const File = link.File; |
| 11 | 15 | ||
| 12 | pub const base_tag: Tag = File.Tag.macho; | 16 | pub const base_tag: File.Tag = File.Tag.macho; |
| 13 | 17 | ||
| 14 | base: File, | 18 | base: File, |
| 15 | 19 | ||
| 20 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 21 | /// Same order as in the file. | ||
| 22 | segment_cmds: std.ArrayListUnmanaged(macho.segment_command_64) = std.ArrayListUnmanaged(macho.segment_command_64){}, | ||
| 23 | |||
| 24 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | ||
| 25 | /// Same order as in the file. | ||
| 26 | sections: std.ArrayListUnmanaged(macho.section_64) = std.ArrayListUnmanaged(macho.section_64){}, | ||
| 27 | |||
| 28 | entry_addr: ?u64 = null, | ||
| 29 | |||
| 16 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 30 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 17 | 31 | ||
| 18 | pub const TextBlock = struct { | 32 | pub const TextBlock = struct { |
| ... | @@ -67,15 +81,120 @@ fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO | ... | @@ -67,15 +81,120 @@ fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO |
| 67 | /// Returns an error if `file` is not already open with +read +write +seek abilities. | 81 | /// Returns an error if `file` is not already open with +read +write +seek abilities. |
| 68 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO { | 82 | fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO { |
| 69 | switch (options.output_mode) { | 83 | switch (options.output_mode) { |
| 70 | .Exe => return error.TODOImplementWritingMachOExeFiles, | 84 | .Exe => {}, |
| 71 | .Obj => return error.TODOImplementWritingMachOObjFiles, | 85 | .Obj => {}, |
| 72 | .Lib => return error.TODOImplementWritingLibFiles, | 86 | .Lib => return error.TODOImplementWritingLibFiles, |
| 73 | } | 87 | } |
| 88 | |||
| 89 | var self: MachO = .{ | ||
| 90 | .base = .{ | ||
| 91 | .file = file, | ||
| 92 | .tag = .macho, | ||
| 93 | .options = options, | ||
| 94 | .allocator = allocator, | ||
| 95 | }, | ||
| 96 | }; | ||
| 97 | errdefer self.deinit(); | ||
| 98 | |||
| 99 | if (options.output_mode == .Exe) { | ||
| 100 | // The first segment command for executables is always a __PAGEZERO segment. | ||
| 101 | try self.segment_cmds.append(allocator, .{ | ||
| 102 | .cmd = macho.LC_SEGMENT_64, | ||
| 103 | .cmdsize = @sizeOf(macho.segment_command_64), | ||
| 104 | .segname = self.makeString("__PAGEZERO"), | ||
| 105 | .vmaddr = 0, | ||
| 106 | .vmsize = 0, | ||
| 107 | .fileoff = 0, | ||
| 108 | .filesize = 0, | ||
| 109 | .maxprot = 0, | ||
| 110 | .initprot = 0, | ||
| 111 | .nsects = 0, | ||
| 112 | .flags = 0, | ||
| 113 | }); | ||
| 114 | } | ||
| 115 | |||
| 116 | return self; | ||
| 117 | } | ||
| 118 | |||
| 119 | fn makeString(self: *MachO, comptime bytes: []const u8) [16]u8 { | ||
| 120 | var buf: [16]u8 = undefined; | ||
| 121 | if (bytes.len > buf.len) @compileError("MachO segment/section name too long"); | ||
| 122 | mem.copy(u8, buf[0..], bytes); | ||
| 123 | return buf; | ||
| 124 | } | ||
| 125 | |||
| 126 | fn writeMachOHeader(self: *MachO) !void { | ||
| 127 | var hdr: macho.mach_header_64 = undefined; | ||
| 128 | hdr.magic = macho.MH_MAGIC_64; | ||
| 129 | |||
| 130 | const CpuInfo = struct { | ||
| 131 | cpu_type: macho.cpu_type_t, | ||
| 132 | cpu_subtype: macho.cpu_subtype_t, | ||
| 133 | }; | ||
| 134 | |||
| 135 | const cpu_info: CpuInfo = switch (self.base.options.target.cpu.arch) { | ||
| 136 | .aarch64 => .{ | ||
| 137 | .cpu_type = macho.CPU_TYPE_ARM64, | ||
| 138 | .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL, | ||
| 139 | }, | ||
| 140 | .x86_64 => .{ | ||
| 141 | .cpu_type = macho.CPU_TYPE_X86_64, | ||
| 142 | .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL, | ||
| 143 | }, | ||
| 144 | else => return error.UnsupportedMachOArchitecture, | ||
| 145 | }; | ||
| 146 | hdr.cputype = cpu_info.cpu_type; | ||
| 147 | hdr.cpusubtype = cpu_info.cpu_subtype; | ||
| 148 | |||
| 149 | const filetype: u32 = switch (self.base.options.output_mode) { | ||
| 150 | .Exe => macho.MH_EXECUTE, | ||
| 151 | .Obj => macho.MH_OBJECT, | ||
| 152 | .Lib => switch (self.base.options.link_mode) { | ||
| 153 | .Static => return error.TODOStaticLibMachOType, | ||
| 154 | .Dynamic => macho.MH_DYLIB, | ||
| 155 | }, | ||
| 156 | }; | ||
| 157 | hdr.filetype = filetype; | ||
| 158 | |||
| 159 | // TODO consider other commands | ||
| 160 | const ncmds = try math.cast(u32, self.segment_cmds.items.len); | ||
| 161 | hdr.ncmds = ncmds; | ||
| 162 | hdr.sizeofcmds = ncmds * @sizeOf(macho.segment_command_64); | ||
| 163 | |||
| 164 | // TODO should these be set to something else? | ||
| 165 | hdr.flags = 0; | ||
| 166 | hdr.reserved = 0; | ||
| 167 | |||
| 168 | try self.base.file.?.pwriteAll(@ptrCast([*]const u8, &hdr)[0..@sizeOf(macho.mach_header_64)], 0); | ||
| 74 | } | 169 | } |
| 75 | 170 | ||
| 76 | pub fn flush(self: *MachO, module: *Module) !void {} | 171 | pub fn flush(self: *MachO, module: *Module) !void { |
| 172 | // TODO implement flush | ||
| 173 | { | ||
| 174 | const buf = try self.base.allocator.alloc(macho.segment_command_64, self.segment_cmds.items.len); | ||
| 175 | defer self.base.allocator.free(buf); | ||
| 176 | |||
| 177 | for (buf) |*seg, i| { | ||
| 178 | seg.* = self.segment_cmds.items[i]; | ||
| 179 | } | ||
| 180 | |||
| 181 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), @sizeOf(macho.mach_header_64)); | ||
| 182 | } | ||
| 183 | |||
| 184 | if (self.entry_addr == null and self.base.options.output_mode == .Exe) { | ||
| 185 | log.debug("flushing. no_entry_point_found = true\n", .{}); | ||
| 186 | self.error_flags.no_entry_point_found = true; | ||
| 187 | } else { | ||
| 188 | log.debug("flushing. no_entry_point_found = false\n", .{}); | ||
| 189 | self.error_flags.no_entry_point_found = false; | ||
| 190 | try self.writeMachOHeader(); | ||
| 191 | } | ||
| 192 | } | ||
| 77 | 193 | ||
| 78 | pub fn deinit(self: *MachO) void {} | 194 | pub fn deinit(self: *MachO) void { |
| 195 | self.segment_cmds.deinit(self.base.allocator); | ||
| 196 | self.sections.deinit(self.base.allocator); | ||
| 197 | } | ||
| 79 | 198 | ||
| 80 | pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {} | 199 | pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {} |
| 81 | 200 | ||
| ... | @@ -91,3 +210,7 @@ pub fn updateDeclExports( | ... | @@ -91,3 +210,7 @@ pub fn updateDeclExports( |
| 91 | ) !void {} | 210 | ) !void {} |
| 92 | 211 | ||
| 93 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {} | 212 | pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {} |
| 213 | |||
| 214 | pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { | ||
| 215 | @panic("TODO implement getDeclVAddr for MachO"); | ||
| 216 | } |
src-self-hosted/link/Wasm.zig+158-360| ... | @@ -32,19 +32,22 @@ const spec = struct { | ... | @@ -32,19 +32,22 @@ const spec = struct { |
| 32 | pub const base_tag = link.File.Tag.wasm; | 32 | pub const base_tag = link.File.Tag.wasm; |
| 33 | 33 | ||
| 34 | pub const FnData = struct { | 34 | pub const FnData = struct { |
| 35 | funcidx: u32, | 35 | /// Generated code for the type of the function |
| 36 | functype: std.ArrayListUnmanaged(u8) = .{}, | ||
| 37 | /// Generated code for the body of the function | ||
| 38 | code: std.ArrayListUnmanaged(u8) = .{}, | ||
| 39 | /// Locations in the generated code where function indexes must be filled in. | ||
| 40 | /// This must be kept ordered by offset. | ||
| 41 | idx_refs: std.ArrayListUnmanaged(struct { offset: u32, decl: *Module.Decl }) = .{}, | ||
| 36 | }; | 42 | }; |
| 37 | 43 | ||
| 38 | base: link.File, | 44 | base: link.File, |
| 39 | 45 | ||
| 40 | types: Types, | 46 | /// List of all function Decls to be written to the output file. The index of |
| 41 | funcs: Funcs, | 47 | /// each Decl in this list at the time of writing the binary is used as the |
| 42 | exports: Exports, | 48 | /// function index. |
| 43 | 49 | /// TODO: can/should we access some data structure in Module directly? | |
| 44 | /// Array over the section structs used in the various sections above to | 50 | funcs: std.ArrayListUnmanaged(*Module.Decl) = .{}, |
| 45 | /// allow iteration when shifting sections to make space. | ||
| 46 | /// TODO: this should eventually be size 11 when we use all the sections. | ||
| 47 | sections: [4]*Section, | ||
| 48 | 51 | ||
| 49 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*link.File { | 52 | pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*link.File { |
| 50 | assert(options.object_format == .wasm); | 53 | assert(options.object_format == .wasm); |
| ... | @@ -58,10 +61,6 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option | ... | @@ -58,10 +61,6 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option |
| 58 | 61 | ||
| 59 | try file.writeAll(&(spec.magic ++ spec.version)); | 62 | try file.writeAll(&(spec.magic ++ spec.version)); |
| 60 | 63 | ||
| 61 | // TODO: this should vary depending on the section and be less arbitrary | ||
| 62 | const size = 1024; | ||
| 63 | const offset = @sizeOf(@TypeOf(spec.magic ++ spec.version)); | ||
| 64 | |||
| 65 | wasm.* = .{ | 64 | wasm.* = .{ |
| 66 | .base = .{ | 65 | .base = .{ |
| 67 | .tag = .wasm, | 66 | .tag = .wasm, |
| ... | @@ -69,52 +68,42 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option | ... | @@ -69,52 +68,42 @@ pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, option |
| 69 | .file = file, | 68 | .file = file, |
| 70 | .allocator = allocator, | 69 | .allocator = allocator, |
| 71 | }, | 70 | }, |
| 72 | |||
| 73 | .types = try Types.init(file, offset, size), | ||
| 74 | .funcs = try Funcs.init(file, offset + size, size, offset + 3 * size, size), | ||
| 75 | .exports = try Exports.init(file, offset + 2 * size, size), | ||
| 76 | |||
| 77 | // These must be ordered as they will appear in the output file | ||
| 78 | .sections = [_]*Section{ | ||
| 79 | &wasm.types.typesec.section, | ||
| 80 | &wasm.funcs.funcsec, | ||
| 81 | &wasm.exports.exportsec, | ||
| 82 | &wasm.funcs.codesec.section, | ||
| 83 | }, | ||
| 84 | }; | 71 | }; |
| 85 | 72 | ||
| 86 | try file.setEndPos(offset + 4 * size); | ||
| 87 | |||
| 88 | return &wasm.base; | 73 | return &wasm.base; |
| 89 | } | 74 | } |
| 90 | 75 | ||
| 91 | pub fn deinit(self: *Wasm) void { | 76 | pub fn deinit(self: *Wasm) void { |
| 92 | self.types.deinit(); | 77 | for (self.funcs.items) |decl| { |
| 93 | self.funcs.deinit(); | 78 | decl.fn_link.wasm.?.functype.deinit(self.base.allocator); |
| 79 | decl.fn_link.wasm.?.code.deinit(self.base.allocator); | ||
| 80 | decl.fn_link.wasm.?.idx_refs.deinit(self.base.allocator); | ||
| 81 | } | ||
| 82 | self.funcs.deinit(self.base.allocator); | ||
| 94 | } | 83 | } |
| 95 | 84 | ||
| 85 | // Generate code for the Decl, storing it in memory to be later written to | ||
| 86 | // the file on flush(). | ||
| 96 | pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { | 87 | pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 97 | if (decl.typed_value.most_recent.typed_value.ty.zigTypeTag() != .Fn) | 88 | if (decl.typed_value.most_recent.typed_value.ty.zigTypeTag() != .Fn) |
| 98 | return error.TODOImplementNonFnDeclsForWasm; | 89 | return error.TODOImplementNonFnDeclsForWasm; |
| 99 | 90 | ||
| 100 | if (decl.fn_link.wasm) |fn_data| { | 91 | if (decl.fn_link.wasm) |*fn_data| { |
| 101 | self.funcs.free(fn_data.funcidx); | 92 | fn_data.functype.items.len = 0; |
| 102 | } | 93 | fn_data.code.items.len = 0; |
| 103 | 94 | fn_data.idx_refs.items.len = 0; | |
| 104 | var buf = std.ArrayList(u8).init(self.base.allocator); | 95 | } else { |
| 105 | defer buf.deinit(); | 96 | decl.fn_link.wasm = .{}; |
| 106 | 97 | try self.funcs.append(self.base.allocator, decl); | |
| 107 | try codegen.genFunctype(&buf, decl); | 98 | } |
| 108 | const typeidx = try self.types.new(buf.items); | 99 | const fn_data = &decl.fn_link.wasm.?; |
| 109 | buf.items.len = 0; | 100 | |
| 110 | 101 | var managed_functype = fn_data.functype.toManaged(self.base.allocator); | |
| 111 | try codegen.genCode(&buf, decl); | 102 | var managed_code = fn_data.code.toManaged(self.base.allocator); |
| 112 | const funcidx = try self.funcs.new(typeidx, buf.items); | 103 | try codegen.genFunctype(&managed_functype, decl); |
| 113 | 104 | try codegen.genCode(&managed_code, decl); | |
| 114 | decl.fn_link.wasm = .{ .funcidx = funcidx }; | 105 | fn_data.functype = managed_functype.toUnmanaged(); |
| 115 | 106 | fn_data.code = managed_code.toUnmanaged(); | |
| 116 | // TODO: we should be more smart and set this only when needed | ||
| 117 | self.exports.dirty = true; | ||
| 118 | } | 107 | } |
| 119 | 108 | ||
| 120 | pub fn updateDeclExports( | 109 | pub fn updateDeclExports( |
| ... | @@ -122,332 +111,141 @@ pub fn updateDeclExports( | ... | @@ -122,332 +111,141 @@ pub fn updateDeclExports( |
| 122 | module: *Module, | 111 | module: *Module, |
| 123 | decl: *const Module.Decl, | 112 | decl: *const Module.Decl, |
| 124 | exports: []const *Module.Export, | 113 | exports: []const *Module.Export, |
| 125 | ) !void { | 114 | ) !void {} |
| 126 | self.exports.dirty = true; | ||
| 127 | } | ||
| 128 | 115 | ||
| 129 | pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { | 116 | pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { |
| 130 | // TODO: remove this assert when non-function Decls are implemented | 117 | // TODO: remove this assert when non-function Decls are implemented |
| 131 | assert(decl.typed_value.most_recent.typed_value.ty.zigTypeTag() == .Fn); | 118 | assert(decl.typed_value.most_recent.typed_value.ty.zigTypeTag() == .Fn); |
| 132 | if (decl.fn_link.wasm) |fn_data| { | 119 | _ = self.funcs.swapRemove(self.getFuncidx(decl).?); |
| 133 | self.funcs.free(fn_data.funcidx); | 120 | decl.fn_link.wasm.?.functype.deinit(self.base.allocator); |
| 134 | decl.fn_link.wasm = null; | 121 | decl.fn_link.wasm.?.code.deinit(self.base.allocator); |
| 135 | } | 122 | decl.fn_link.wasm.?.idx_refs.deinit(self.base.allocator); |
| 123 | decl.fn_link.wasm = null; | ||
| 136 | } | 124 | } |
| 137 | 125 | ||
| 138 | pub fn flush(self: *Wasm, module: *Module) !void { | 126 | pub fn flush(self: *Wasm, module: *Module) !void { |
| 139 | if (self.exports.dirty) try self.exports.writeAll(module); | 127 | const file = self.base.file.?; |
| 140 | } | 128 | const header_size = 5 + 1; |
| 141 | 129 | ||
| 142 | /// This struct describes the location of a named section + custom section | 130 | // No need to rewrite the magic/version header |
| 143 | /// padding in the output file. This is all the data we need to allow for | 131 | try file.setEndPos(@sizeOf(@TypeOf(spec.magic ++ spec.version))); |
| 144 | /// shifting sections around when padding runs out. | 132 | try file.seekTo(@sizeOf(@TypeOf(spec.magic ++ spec.version))); |
| 145 | const Section = struct { | 133 | |
| 146 | /// The size of a section header: 1 byte section id + 5 bytes | 134 | // Type section |
| 147 | /// for the fixed-width ULEB128 encoded contents size. | 135 | { |
| 148 | const header_size = 1 + 5; | 136 | const header_offset = try reserveVecSectionHeader(file); |
| 149 | /// Offset of the section id byte from the start of the file. | 137 | for (self.funcs.items) |decl| { |
| 150 | offset: u64, | 138 | try file.writeAll(decl.fn_link.wasm.?.functype.items); |
| 151 | /// Size of the section, including the header and directly | ||
| 152 | /// following custom section used for padding if any. | ||
| 153 | size: u64, | ||
| 154 | |||
| 155 | /// Resize the usable part of the section, handling the following custom | ||
| 156 | /// section used for padding. If there is not enough padding left, shift | ||
| 157 | /// all following sections to make space. Takes the current and target | ||
| 158 | /// contents sizes of the section as arguments. | ||
| 159 | fn resize(self: *Section, file: fs.File, current: u32, target: u32) !void { | ||
| 160 | // Section header + target contents size + custom section header | ||
| 161 | // + custom section name + empty custom section > owned chunk of the file | ||
| 162 | if (header_size + target + header_size + 1 + 0 > self.size) | ||
| 163 | return error.TODOImplementSectionShifting; | ||
| 164 | |||
| 165 | const new_custom_start = self.offset + header_size + target; | ||
| 166 | const new_custom_contents_size = self.size - target - 2 * header_size; | ||
| 167 | assert(new_custom_contents_size >= 1); | ||
| 168 | // +1 for the name of the custom section, which we set to an empty string | ||
| 169 | var custom_header: [header_size + 1]u8 = undefined; | ||
| 170 | custom_header[0] = spec.custom_id; | ||
| 171 | leb.writeUnsignedFixed(5, custom_header[1..header_size], @intCast(u32, new_custom_contents_size)); | ||
| 172 | custom_header[header_size] = 0; | ||
| 173 | try file.pwriteAll(&custom_header, new_custom_start); | ||
| 174 | } | ||
| 175 | }; | ||
| 176 | |||
| 177 | /// This can be used to manage the contents of any section which uses a vector | ||
| 178 | /// of contents. This interface maintains index stability while allowing for | ||
| 179 | /// reuse of "dead" indexes. | ||
| 180 | const VecSection = struct { | ||
| 181 | /// Represents a single entry in the vector (e.g. a type in the type section) | ||
| 182 | const Entry = struct { | ||
| 183 | /// Offset from the start of the section contents in bytes | ||
| 184 | offset: u32, | ||
| 185 | /// Size in bytes of the entry | ||
| 186 | size: u32, | ||
| 187 | }; | ||
| 188 | section: Section, | ||
| 189 | /// Size in bytes of the contents of the section. Does not include | ||
| 190 | /// the "header" containing the section id and this value. | ||
| 191 | contents_size: u32, | ||
| 192 | /// List of all entries in the contents of the section. | ||
| 193 | entries: std.ArrayListUnmanaged(Entry) = std.ArrayListUnmanaged(Entry){}, | ||
| 194 | /// List of indexes of unreferenced entries which may be | ||
| 195 | /// overwritten and reused. | ||
| 196 | dead_list: std.ArrayListUnmanaged(u32) = std.ArrayListUnmanaged(u32){}, | ||
| 197 | |||
| 198 | /// Write the headers of the section and custom padding section | ||
| 199 | fn init(comptime section_id: u8, file: fs.File, offset: u64, initial_size: u64) !VecSection { | ||
| 200 | // section id, section size, empty vector, custom section id, | ||
| 201 | // custom section size, empty custom section name | ||
| 202 | var initial_data: [1 + 5 + 5 + 1 + 5 + 1]u8 = undefined; | ||
| 203 | |||
| 204 | assert(initial_size >= initial_data.len); | ||
| 205 | |||
| 206 | comptime var i = 0; | ||
| 207 | initial_data[i] = section_id; | ||
| 208 | i += 1; | ||
| 209 | leb.writeUnsignedFixed(5, initial_data[i..(i + 5)], 5); | ||
| 210 | i += 5; | ||
| 211 | leb.writeUnsignedFixed(5, initial_data[i..(i + 5)], 0); | ||
| 212 | i += 5; | ||
| 213 | initial_data[i] = spec.custom_id; | ||
| 214 | i += 1; | ||
| 215 | leb.writeUnsignedFixed(5, initial_data[i..(i + 5)], @intCast(u32, initial_size - @sizeOf(@TypeOf(initial_data)))); | ||
| 216 | i += 5; | ||
| 217 | initial_data[i] = 0; | ||
| 218 | |||
| 219 | try file.pwriteAll(&initial_data, offset); | ||
| 220 | |||
| 221 | return VecSection{ | ||
| 222 | .section = .{ | ||
| 223 | .offset = offset, | ||
| 224 | .size = initial_size, | ||
| 225 | }, | ||
| 226 | .contents_size = 5, | ||
| 227 | }; | ||
| 228 | } | ||
| 229 | |||
| 230 | fn deinit(self: *VecSection, allocator: *Allocator) void { | ||
| 231 | self.entries.deinit(allocator); | ||
| 232 | self.dead_list.deinit(allocator); | ||
| 233 | } | ||
| 234 | |||
| 235 | /// Write a new entry into the file, returning the index used. | ||
| 236 | fn addEntry(self: *VecSection, file: fs.File, allocator: *Allocator, data: []const u8) !u32 { | ||
| 237 | // First look for a dead entry we can reuse | ||
| 238 | for (self.dead_list.items) |dead_idx, i| { | ||
| 239 | const dead_entry = &self.entries.items[dead_idx]; | ||
| 240 | if (dead_entry.size == data.len) { | ||
| 241 | // Found a dead entry of the right length, overwrite it | ||
| 242 | try file.pwriteAll(data, self.section.offset + Section.header_size + dead_entry.offset); | ||
| 243 | _ = self.dead_list.swapRemove(i); | ||
| 244 | return dead_idx; | ||
| 245 | } | ||
| 246 | } | 139 | } |
| 247 | 140 | try writeVecSectionHeader( | |
| 248 | // TODO: We can be more efficient if we special-case one or | 141 | file, |
| 249 | // more consecutive dead entries at the end of the vector. | 142 | header_offset, |
| 250 | 143 | spec.types_id, | |
| 251 | // We failed to find a dead entry to reuse, so write the new | 144 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 252 | // entry to the end of the section. | 145 | @intCast(u32, self.funcs.items.len), |
| 253 | try self.section.resize(file, self.contents_size, self.contents_size + @intCast(u32, data.len)); | 146 | ); |
| 254 | try file.pwriteAll(data, self.section.offset + Section.header_size + self.contents_size); | 147 | } |
| 255 | try self.entries.append(allocator, .{ | 148 | |
| 256 | .offset = self.contents_size, | 149 | // Function section |
| 257 | .size = @intCast(u32, data.len), | 150 | { |
| 258 | }); | 151 | const header_offset = try reserveVecSectionHeader(file); |
| 259 | self.contents_size += @intCast(u32, data.len); | 152 | const writer = file.writer(); |
| 260 | // Make sure the dead list always has enough space to store all free'd | 153 | for (self.funcs.items) |_, typeidx| try leb.writeULEB128(writer, @intCast(u32, typeidx)); |
| 261 | // entries. This makes it so that delEntry() cannot fail. | 154 | try writeVecSectionHeader( |
| 262 | // TODO: figure out a better way that doesn't waste as much memory | 155 | file, |
| 263 | try self.dead_list.ensureCapacity(allocator, self.entries.items.len); | 156 | header_offset, |
| 264 | 157 | spec.funcs_id, | |
| 265 | // Update the size in the section header and the item count of | 158 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 266 | // the contents vector. | 159 | @intCast(u32, self.funcs.items.len), |
| 267 | var size_and_count: [10]u8 = undefined; | 160 | ); |
| 268 | leb.writeUnsignedFixed(5, size_and_count[0..5], self.contents_size); | 161 | } |
| 269 | leb.writeUnsignedFixed(5, size_and_count[5..], @intCast(u32, self.entries.items.len)); | 162 | |
| 270 | try file.pwriteAll(&size_and_count, self.section.offset + 1); | 163 | // Export section |
| 271 | 164 | { | |
| 272 | return @intCast(u32, self.entries.items.len - 1); | 165 | const header_offset = try reserveVecSectionHeader(file); |
| 273 | } | 166 | const writer = file.writer(); |
| 274 | 167 | var count: u32 = 0; | |
| 275 | /// Mark the type referenced by the given index as dead. | ||
| 276 | fn delEntry(self: *VecSection, index: u32) void { | ||
| 277 | self.dead_list.appendAssumeCapacity(index); | ||
| 278 | } | ||
| 279 | }; | ||
| 280 | |||
| 281 | const Types = struct { | ||
| 282 | typesec: VecSection, | ||
| 283 | |||
| 284 | fn init(file: fs.File, offset: u64, initial_size: u64) !Types { | ||
| 285 | return Types{ .typesec = try VecSection.init(spec.types_id, file, offset, initial_size) }; | ||
| 286 | } | ||
| 287 | |||
| 288 | fn deinit(self: *Types) void { | ||
| 289 | const wasm = @fieldParentPtr(Wasm, "types", self); | ||
| 290 | self.typesec.deinit(wasm.base.allocator); | ||
| 291 | } | ||
| 292 | |||
| 293 | fn new(self: *Types, data: []const u8) !u32 { | ||
| 294 | const wasm = @fieldParentPtr(Wasm, "types", self); | ||
| 295 | return self.typesec.addEntry(wasm.base.file.?, wasm.base.allocator, data); | ||
| 296 | } | ||
| 297 | |||
| 298 | fn free(self: *Types, typeidx: u32) void { | ||
| 299 | self.typesec.delEntry(typeidx); | ||
| 300 | } | ||
| 301 | }; | ||
| 302 | |||
| 303 | const Funcs = struct { | ||
| 304 | /// This section needs special handling to keep the indexes matching with | ||
| 305 | /// the codesec, so we cant just use a VecSection. | ||
| 306 | funcsec: Section, | ||
| 307 | /// The typeidx stored for each function, indexed by funcidx. | ||
| 308 | func_types: std.ArrayListUnmanaged(u32) = std.ArrayListUnmanaged(u32){}, | ||
| 309 | codesec: VecSection, | ||
| 310 | |||
| 311 | fn init(file: fs.File, funcs_offset: u64, funcs_size: u64, code_offset: u64, code_size: u64) !Funcs { | ||
| 312 | return Funcs{ | ||
| 313 | .funcsec = (try VecSection.init(spec.funcs_id, file, funcs_offset, funcs_size)).section, | ||
| 314 | .codesec = try VecSection.init(spec.code_id, file, code_offset, code_size), | ||
| 315 | }; | ||
| 316 | } | ||
| 317 | |||
| 318 | fn deinit(self: *Funcs) void { | ||
| 319 | const wasm = @fieldParentPtr(Wasm, "funcs", self); | ||
| 320 | self.func_types.deinit(wasm.base.allocator); | ||
| 321 | self.codesec.deinit(wasm.base.allocator); | ||
| 322 | } | ||
| 323 | |||
| 324 | /// Add a new function to the binary, first finding space for and writing | ||
| 325 | /// the code then writing the typeidx to the corresponding index in the | ||
| 326 | /// funcsec. Returns the function index used. | ||
| 327 | fn new(self: *Funcs, typeidx: u32, code: []const u8) !u32 { | ||
| 328 | const wasm = @fieldParentPtr(Wasm, "funcs", self); | ||
| 329 | const file = wasm.base.file.?; | ||
| 330 | const allocator = wasm.base.allocator; | ||
| 331 | |||
| 332 | assert(self.func_types.items.len == self.codesec.entries.items.len); | ||
| 333 | |||
| 334 | // TODO: consider nop-padding the code if there is a close but not perfect fit | ||
| 335 | const funcidx = try self.codesec.addEntry(file, allocator, code); | ||
| 336 | |||
| 337 | if (self.func_types.items.len < self.codesec.entries.items.len) { | ||
| 338 | // u32 vector length + funcs_count u32s in the vector | ||
| 339 | const current = 5 + @intCast(u32, self.func_types.items.len) * 5; | ||
| 340 | try self.funcsec.resize(file, current, current + 5); | ||
| 341 | try self.func_types.append(allocator, typeidx); | ||
| 342 | |||
| 343 | // Update the size in the section header and the item count of | ||
| 344 | // the contents vector. | ||
| 345 | const count = @intCast(u32, self.func_types.items.len); | ||
| 346 | var size_and_count: [10]u8 = undefined; | ||
| 347 | leb.writeUnsignedFixed(5, size_and_count[0..5], 5 + count * 5); | ||
| 348 | leb.writeUnsignedFixed(5, size_and_count[5..], count); | ||
| 349 | try file.pwriteAll(&size_and_count, self.funcsec.offset + 1); | ||
| 350 | } else { | ||
| 351 | // We are overwriting a dead function and may now free the type | ||
| 352 | wasm.types.free(self.func_types.items[funcidx]); | ||
| 353 | } | ||
| 354 | |||
| 355 | assert(self.func_types.items.len == self.codesec.entries.items.len); | ||
| 356 | |||
| 357 | var typeidx_leb: [5]u8 = undefined; | ||
| 358 | leb.writeUnsignedFixed(5, &typeidx_leb, typeidx); | ||
| 359 | try file.pwriteAll(&typeidx_leb, self.funcsec.offset + Section.header_size + 5 + funcidx * 5); | ||
| 360 | |||
| 361 | return funcidx; | ||
| 362 | } | ||
| 363 | |||
| 364 | fn free(self: *Funcs, funcidx: u32) void { | ||
| 365 | self.codesec.delEntry(funcidx); | ||
| 366 | } | ||
| 367 | }; | ||
| 368 | |||
| 369 | /// Exports are tricky. We can't leave dead entries in the binary as they | ||
| 370 | /// would obviously be visible from the execution environment. The simplest | ||
| 371 | /// way to work around this is to re-emit the export section whenever | ||
| 372 | /// something changes. This also makes it easier to ensure exported function | ||
| 373 | /// and global indexes are updated as they change. | ||
| 374 | const Exports = struct { | ||
| 375 | exportsec: Section, | ||
| 376 | /// Size in bytes of the contents of the section. Does not include | ||
| 377 | /// the "header" containing the section id and this value. | ||
| 378 | contents_size: u32, | ||
| 379 | /// If this is true, then exports will be rewritten on flush() | ||
| 380 | dirty: bool, | ||
| 381 | |||
| 382 | fn init(file: fs.File, offset: u64, initial_size: u64) !Exports { | ||
| 383 | return Exports{ | ||
| 384 | .exportsec = (try VecSection.init(spec.exports_id, file, offset, initial_size)).section, | ||
| 385 | .contents_size = 5, | ||
| 386 | .dirty = false, | ||
| 387 | }; | ||
| 388 | } | ||
| 389 | |||
| 390 | fn writeAll(self: *Exports, module: *Module) !void { | ||
| 391 | const wasm = @fieldParentPtr(Wasm, "exports", self); | ||
| 392 | const file = wasm.base.file.?; | ||
| 393 | var buf: [5]u8 = undefined; | ||
| 394 | |||
| 395 | // First ensure the section is the right size | ||
| 396 | var export_count: u32 = 0; | ||
| 397 | var new_contents_size: u32 = 5; | ||
| 398 | for (module.decl_exports.entries.items) |entry| { | 168 | for (module.decl_exports.entries.items) |entry| { |
| 399 | for (entry.value) |e| { | 169 | for (entry.value) |exprt| { |
| 400 | export_count += 1; | 170 | // Export name length + name |
| 401 | new_contents_size += calcSize(e); | 171 | try leb.writeULEB128(writer, @intCast(u32, exprt.options.name.len)); |
| 172 | try writer.writeAll(exprt.options.name); | ||
| 173 | |||
| 174 | switch (exprt.exported_decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { | ||
| 175 | .Fn => { | ||
| 176 | // Type of the export | ||
| 177 | try writer.writeByte(0x00); | ||
| 178 | // Exported function index | ||
| 179 | try leb.writeULEB128(writer, self.getFuncidx(exprt.exported_decl).?); | ||
| 180 | }, | ||
| 181 | else => return error.TODOImplementNonFnDeclsForWasm, | ||
| 182 | } | ||
| 183 | |||
| 184 | count += 1; | ||
| 402 | } | 185 | } |
| 403 | } | 186 | } |
| 404 | if (new_contents_size != self.contents_size) { | 187 | try writeVecSectionHeader( |
| 405 | try self.exportsec.resize(file, self.contents_size, new_contents_size); | 188 | file, |
| 406 | leb.writeUnsignedFixed(5, &buf, new_contents_size); | 189 | header_offset, |
| 407 | try file.pwriteAll(&buf, self.exportsec.offset + 1); | 190 | spec.exports_id, |
| 408 | } | 191 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 409 | 192 | count, | |
| 410 | try file.seekTo(self.exportsec.offset + Section.header_size); | 193 | ); |
| 194 | } | ||
| 195 | |||
| 196 | // Code section | ||
| 197 | { | ||
| 198 | const header_offset = try reserveVecSectionHeader(file); | ||
| 411 | const writer = file.writer(); | 199 | const writer = file.writer(); |
| 200 | for (self.funcs.items) |decl| { | ||
| 201 | const fn_data = &decl.fn_link.wasm.?; | ||
| 202 | |||
| 203 | // Write the already generated code to the file, inserting | ||
| 204 | // function indexes where required. | ||
| 205 | var current: u32 = 0; | ||
| 206 | for (fn_data.idx_refs.items) |idx_ref| { | ||
| 207 | try writer.writeAll(fn_data.code.items[current..idx_ref.offset]); | ||
| 208 | current = idx_ref.offset; | ||
| 209 | // Use a fixed width here to make calculating the code size | ||
| 210 | // in codegen.wasm.genCode() simpler. | ||
| 211 | var buf: [5]u8 = undefined; | ||
| 212 | leb.writeUnsignedFixed(5, &buf, self.getFuncidx(idx_ref.decl).?); | ||
| 213 | try writer.writeAll(&buf); | ||
| 214 | } | ||
| 412 | 215 | ||
| 413 | // Length of the exports vec | 216 | try writer.writeAll(fn_data.code.items[current..]); |
| 414 | leb.writeUnsignedFixed(5, &buf, export_count); | 217 | } |
| 415 | try writer.writeAll(&buf); | 218 | try writeVecSectionHeader( |
| 416 | 219 | file, | |
| 417 | for (module.decl_exports.entries.items) |entry| | 220 | header_offset, |
| 418 | for (entry.value) |e| try writeExport(writer, e); | 221 | spec.code_id, |
| 419 | 222 | @intCast(u32, (try file.getPos()) - header_offset - header_size), | |
| 420 | self.dirty = false; | 223 | @intCast(u32, self.funcs.items.len), |
| 224 | ); | ||
| 421 | } | 225 | } |
| 226 | } | ||
| 422 | 227 | ||
| 423 | /// Return the total number of bytes an export will take. | 228 | /// Get the current index of a given Decl in the function list |
| 424 | /// TODO: fixed-width LEB128 is currently used for simplicity, but should | 229 | /// TODO: we could maintain a hash map to potentially make this |
| 425 | /// be replaced with proper variable-length LEB128 as it is inefficient. | 230 | fn getFuncidx(self: Wasm, decl: *Module.Decl) ?u32 { |
| 426 | fn calcSize(e: *Module.Export) u32 { | 231 | return for (self.funcs.items) |func, idx| { |
| 427 | // LEB128 name length + name bytes + export type + LEB128 index | 232 | if (func == decl) break @intCast(u32, idx); |
| 428 | return 5 + @intCast(u32, e.options.name.len) + 1 + 5; | 233 | } else null; |
| 429 | } | 234 | } |
| 430 | 235 | ||
| 431 | /// Write the data for a single export to the given file at a given offset. | 236 | fn reserveVecSectionHeader(file: fs.File) !u64 { |
| 432 | /// TODO: fixed-width LEB128 is currently used for simplicity, but should | 237 | // section id + fixed leb contents size + fixed leb vector length |
| 433 | /// be replaced with proper variable-length LEB128 as it is inefficient. | 238 | const header_size = 1 + 5 + 5; |
| 434 | fn writeExport(writer: anytype, e: *Module.Export) !void { | 239 | // TODO: this should be a single lseek(2) call, but fs.File does not |
| 435 | var buf: [5]u8 = undefined; | 240 | // currently provide a way to do this. |
| 436 | 241 | try file.seekBy(header_size); | |
| 437 | // Export name length + name | 242 | return (try file.getPos()) - header_size; |
| 438 | leb.writeUnsignedFixed(5, &buf, @intCast(u32, e.options.name.len)); | 243 | } |
| 439 | try writer.writeAll(&buf); | 244 | |
| 440 | try writer.writeAll(e.options.name); | 245 | fn writeVecSectionHeader(file: fs.File, offset: u64, section: u8, size: u32, items: u32) !void { |
| 441 | 246 | var buf: [1 + 5 + 5]u8 = undefined; | |
| 442 | switch (e.exported_decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { | 247 | buf[0] = section; |
| 443 | .Fn => { | 248 | leb.writeUnsignedFixed(5, buf[1..6], size); |
| 444 | // Type of the export | 249 | leb.writeUnsignedFixed(5, buf[6..], items); |
| 445 | try writer.writeByte(0x00); | 250 | try file.pwriteAll(&buf, offset); |
| 446 | // Exported function index | 251 | } |
| 447 | leb.writeUnsignedFixed(5, &buf, e.exported_decl.fn_link.wasm.?.funcidx); | ||
| 448 | try writer.writeAll(&buf); | ||
| 449 | }, | ||
| 450 | else => return error.TODOImplementNonFnDeclsForWasm, | ||
| 451 | } | ||
| 452 | } | ||
| 453 | }; |
src-self-hosted/link/cbe.h created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | #if __STDC_VERSION__ >= 201112L | ||
| 2 | #define zig_noreturn _Noreturn | ||
| 3 | #elif __GNUC__ | ||
| 4 | #define zig_noreturn __attribute__ ((noreturn)) | ||
| 5 | #elif _MSC_VER | ||
| 6 | #define zig_noreturn __declspec(noreturn) | ||
| 7 | #else | ||
| 8 | #define zig_noreturn | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #if __GNUC__ | ||
| 12 | #define zig_unreachable() __builtin_unreachable() | ||
| 13 | #else | ||
| 14 | #define zig_unreachable() | ||
| 15 | #endif | ||
src-self-hosted/main.zig+2| ... | @@ -742,6 +742,7 @@ const FmtError = error{ | ... | @@ -742,6 +742,7 @@ const FmtError = error{ |
| 742 | LinkQuotaExceeded, | 742 | LinkQuotaExceeded, |
| 743 | FileBusy, | 743 | FileBusy, |
| 744 | EndOfStream, | 744 | EndOfStream, |
| 745 | NotOpenForWriting, | ||
| 745 | } || fs.File.OpenError; | 746 | } || fs.File.OpenError; |
| 746 | 747 | ||
| 747 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { | 748 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { |
| ... | @@ -807,6 +808,7 @@ fn fmtPathFile( | ... | @@ -807,6 +808,7 @@ fn fmtPathFile( |
| 807 | const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) { | 808 | const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) { |
| 808 | error.ConnectionResetByPeer => unreachable, | 809 | error.ConnectionResetByPeer => unreachable, |
| 809 | error.ConnectionTimedOut => unreachable, | 810 | error.ConnectionTimedOut => unreachable, |
| 811 | error.NotOpenForReading => unreachable, | ||
| 810 | else => |e| return e, | 812 | else => |e| return e, |
| 811 | }; | 813 | }; |
| 812 | source_file.close(); | 814 | source_file.close(); |
src-self-hosted/stage2.zig+4| ... | @@ -153,6 +153,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { | ... | @@ -153,6 +153,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { |
| 153 | const c_out_stream = std.io.cOutStream(output_file); | 153 | const c_out_stream = std.io.cOutStream(output_file); |
| 154 | _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { | 154 | _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { |
| 155 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | 155 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode |
| 156 | error.NotOpenForWriting => unreachable, | ||
| 156 | error.SystemResources => return .SystemResources, | 157 | error.SystemResources => return .SystemResources, |
| 157 | error.OperationAborted => return .OperationAborted, | 158 | error.OperationAborted => return .OperationAborted, |
| 158 | error.BrokenPipe => return .BrokenPipe, | 159 | error.BrokenPipe => return .BrokenPipe, |
| ... | @@ -611,6 +612,8 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [ | ... | @@ -611,6 +612,8 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [ |
| 611 | error.SystemResources => return .SystemResources, | 612 | error.SystemResources => return .SystemResources, |
| 612 | error.OperationAborted => return .OperationAborted, | 613 | error.OperationAborted => return .OperationAborted, |
| 613 | error.WouldBlock => unreachable, | 614 | error.WouldBlock => unreachable, |
| 615 | error.NotOpenForWriting => unreachable, | ||
| 616 | error.NotOpenForReading => unreachable, | ||
| 614 | error.Unexpected => return .Unexpected, | 617 | error.Unexpected => return .Unexpected, |
| 615 | error.EndOfStream => return .EndOfFile, | 618 | error.EndOfStream => return .EndOfFile, |
| 616 | error.IsDir => return .IsDir, | 619 | error.IsDir => return .IsDir, |
| ... | @@ -666,6 +669,7 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: | ... | @@ -666,6 +669,7 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: |
| 666 | const c_out_stream = std.io.cOutStream(output_file); | 669 | const c_out_stream = std.io.cOutStream(output_file); |
| 667 | libc.render(c_out_stream) catch |err| switch (err) { | 670 | libc.render(c_out_stream) catch |err| switch (err) { |
| 668 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | 671 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode |
| 672 | error.NotOpenForWriting => unreachable, | ||
| 669 | error.SystemResources => return .SystemResources, | 673 | error.SystemResources => return .SystemResources, |
| 670 | error.OperationAborted => return .OperationAborted, | 674 | error.OperationAborted => return .OperationAborted, |
| 671 | error.BrokenPipe => return .BrokenPipe, | 675 | error.BrokenPipe => return .BrokenPipe, |
src-self-hosted/test.zig+1-1| ... | @@ -10,7 +10,7 @@ const enable_wine: bool = build_options.enable_wine; | ... | @@ -10,7 +10,7 @@ const enable_wine: bool = build_options.enable_wine; |
| 10 | const enable_wasmtime: bool = build_options.enable_wasmtime; | 10 | const enable_wasmtime: bool = build_options.enable_wasmtime; |
| 11 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; | 11 | const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; |
| 12 | 12 | ||
| 13 | const cheader = @embedFile("cbe.h"); | 13 | const cheader = @embedFile("link/cbe.h"); |
| 14 | 14 | ||
| 15 | test "self-hosted" { | 15 | test "self-hosted" { |
| 16 | var ctx = TestContext.init(); | 16 | var ctx = TestContext.init(); |
src-self-hosted/translate_c.zig+41-13| ... | @@ -498,7 +498,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { | ... | @@ -498,7 +498,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void { |
| 498 | _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl)); | 498 | _ = try transRecordDecl(c, @ptrCast(*const ZigClangRecordDecl, decl)); |
| 499 | }, | 499 | }, |
| 500 | .Var => { | 500 | .Var => { |
| 501 | return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl)); | 501 | return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl), null); |
| 502 | }, | 502 | }, |
| 503 | .Empty => { | 503 | .Empty => { |
| 504 | // Do nothing | 504 | // Do nothing |
| ... | @@ -679,12 +679,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -679,12 +679,13 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 679 | return addTopLevelDecl(c, fn_name, &proto_node.base); | 679 | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | 682 | /// if mangled_name is not null, this var decl was declared in a block scope. |
| 683 | const var_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl))); | 683 | fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl, mangled_name: ?[]const u8) Error!void { |
| 684 | const var_name = mangled_name orelse try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, var_decl))); | ||
| 684 | if (c.global_scope.sym_table.contains(var_name)) | 685 | if (c.global_scope.sym_table.contains(var_name)) |
| 685 | return; // Avoid processing this decl twice | 686 | return; // Avoid processing this decl twice |
| 686 | const rp = makeRestorePoint(c); | 687 | const rp = makeRestorePoint(c); |
| 687 | const visib_tok = try appendToken(c, .Keyword_pub, "pub"); | 688 | const visib_tok = if (mangled_name) |_| null else try appendToken(c, .Keyword_pub, "pub"); |
| 688 | 689 | ||
| 689 | const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) | 690 | const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) |
| 690 | null | 691 | null |
| ... | @@ -701,8 +702,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -701,8 +702,14 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 701 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); | 702 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); |
| 702 | const storage_class = ZigClangVarDecl_getStorageClass(var_decl); | 703 | const storage_class = ZigClangVarDecl_getStorageClass(var_decl); |
| 703 | const is_const = ZigClangQualType_isConstQualified(qual_type); | 704 | const is_const = ZigClangQualType_isConstQualified(qual_type); |
| 704 | 705 | const has_init = ZigClangVarDecl_hasInit(var_decl); | |
| 705 | const extern_tok = if (storage_class == .Extern) | 706 | |
| 707 | // In C extern variables with initializers behave like Zig exports. | ||
| 708 | // extern int foo = 2; | ||
| 709 | // does the same as: | ||
| 710 | // extern int foo; | ||
| 711 | // int foo = 2; | ||
| 712 | const extern_tok = if (storage_class == .Extern and !has_init) | ||
| 706 | try appendToken(c, .Keyword_extern, "extern") | 713 | try appendToken(c, .Keyword_extern, "extern") |
| 707 | else if (storage_class != .Static) | 714 | else if (storage_class != .Static) |
| 708 | try appendToken(c, .Keyword_export, "export") | 715 | try appendToken(c, .Keyword_export, "export") |
| ... | @@ -730,7 +737,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -730,7 +737,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 730 | // If the initialization expression is not present, initialize with undefined. | 737 | // If the initialization expression is not present, initialize with undefined. |
| 731 | // If it is an integer literal, we can skip the @as since it will be redundant | 738 | // If it is an integer literal, we can skip the @as since it will be redundant |
| 732 | // with the variable type. | 739 | // with the variable type. |
| 733 | if (ZigClangVarDecl_hasInit(var_decl)) { | 740 | if (has_init) { |
| 734 | eq_tok = try appendToken(c, .Equal, "="); | 741 | eq_tok = try appendToken(c, .Equal, "="); |
| 735 | init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| | 742 | init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| |
| 736 | transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) { | 743 | transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) { |
| ... | @@ -745,7 +752,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { | ... | @@ -745,7 +752,22 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { |
| 745 | try transCreateNodeUndefinedLiteral(c); | 752 | try transCreateNodeUndefinedLiteral(c); |
| 746 | } else if (storage_class != .Extern) { | 753 | } else if (storage_class != .Extern) { |
| 747 | eq_tok = try appendToken(c, .Equal, "="); | 754 | eq_tok = try appendToken(c, .Equal, "="); |
| 748 | init_node = try transCreateNodeIdentifierUnchecked(c, "undefined"); | 755 | // The C language specification states that variables with static or threadlocal |
| 756 | // storage without an initializer are initialized to a zero value. | ||
| 757 | |||
| 758 | // @import("std").mem.zeroes(T) | ||
| 759 | const import_fn_call = try c.createBuiltinCall("@import", 1); | ||
| 760 | const std_node = try transCreateNodeStringLiteral(c, "\"std\""); | ||
| 761 | import_fn_call.params()[0] = std_node; | ||
| 762 | import_fn_call.rparen_token = try appendToken(c, .RParen, ")"); | ||
| 763 | const inner_field_access = try transCreateNodeFieldAccess(c, &import_fn_call.base, "mem"); | ||
| 764 | const outer_field_access = try transCreateNodeFieldAccess(c, inner_field_access, "zeroes"); | ||
| 765 | |||
| 766 | const zero_init_call = try c.createCall(outer_field_access, 1); | ||
| 767 | zero_init_call.params()[0] = type_node; | ||
| 768 | zero_init_call.rtoken = try appendToken(c, .RParen, ")"); | ||
| 769 | |||
| 770 | init_node = &zero_init_call.base; | ||
| 749 | } | 771 | } |
| 750 | 772 | ||
| 751 | const linksection_expr = blk: { | 773 | const linksection_expr = blk: { |
| ... | @@ -1561,15 +1583,22 @@ fn transDeclStmtOne( | ... | @@ -1561,15 +1583,22 @@ fn transDeclStmtOne( |
| 1561 | .Var => { | 1583 | .Var => { |
| 1562 | const var_decl = @ptrCast(*const ZigClangVarDecl, decl); | 1584 | const var_decl = @ptrCast(*const ZigClangVarDecl, decl); |
| 1563 | 1585 | ||
| 1564 | const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None) | ||
| 1565 | null | ||
| 1566 | else | ||
| 1567 | try appendToken(c, .Keyword_threadlocal, "threadlocal"); | ||
| 1568 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); | 1586 | const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); |
| 1569 | const name = try c.str(ZigClangNamedDecl_getName_bytes_begin( | 1587 | const name = try c.str(ZigClangNamedDecl_getName_bytes_begin( |
| 1570 | @ptrCast(*const ZigClangNamedDecl, var_decl), | 1588 | @ptrCast(*const ZigClangNamedDecl, var_decl), |
| 1571 | )); | 1589 | )); |
| 1572 | const mangled_name = try block_scope.makeMangledName(c, name); | 1590 | const mangled_name = try block_scope.makeMangledName(c, name); |
| 1591 | |||
| 1592 | switch (ZigClangVarDecl_getStorageClass(var_decl)) { | ||
| 1593 | .Extern, .Static => { | ||
| 1594 | // This is actually a global variable, put it in the global scope and reference it. | ||
| 1595 | // `_ = mangled_name;` | ||
| 1596 | try visitVarDecl(rp.c, var_decl, mangled_name); | ||
| 1597 | return try maybeSuppressResult(rp, scope, .unused, try transCreateNodeIdentifier(rp.c, mangled_name)); | ||
| 1598 | }, | ||
| 1599 | else => {}, | ||
| 1600 | } | ||
| 1601 | |||
| 1573 | const mut_tok = if (ZigClangQualType_isConstQualified(qual_type)) | 1602 | const mut_tok = if (ZigClangQualType_isConstQualified(qual_type)) |
| 1574 | try appendToken(c, .Keyword_const, "const") | 1603 | try appendToken(c, .Keyword_const, "const") |
| 1575 | else | 1604 | else |
| ... | @@ -1597,7 +1626,6 @@ fn transDeclStmtOne( | ... | @@ -1597,7 +1626,6 @@ fn transDeclStmtOne( |
| 1597 | .mut_token = mut_tok, | 1626 | .mut_token = mut_tok, |
| 1598 | .semicolon_token = semicolon_token, | 1627 | .semicolon_token = semicolon_token, |
| 1599 | }, .{ | 1628 | }, .{ |
| 1600 | .thread_local_token = thread_local_token, | ||
| 1601 | .eq_token = eq_token, | 1629 | .eq_token = eq_token, |
| 1602 | .type_node = type_node, | 1630 | .type_node = type_node, |
| 1603 | .init_node = init_node, | 1631 | .init_node = init_node, |
src-self-hosted/type.zig+516-55| ... | @@ -65,16 +65,25 @@ pub const Type = extern union { | ... | @@ -65,16 +65,25 @@ pub const Type = extern union { |
| 65 | .fn_ccc_void_no_args => return .Fn, | 65 | .fn_ccc_void_no_args => return .Fn, |
| 66 | .function => return .Fn, | 66 | .function => return .Fn, |
| 67 | 67 | ||
| 68 | .array, .array_u8_sentinel_0 => return .Array, | 68 | .array, .array_u8_sentinel_0, .array_u8, .array_sentinel => return .Array, |
| 69 | .single_const_pointer => return .Pointer, | 69 | .single_const_pointer_to_comptime_int, |
| 70 | .single_mut_pointer => return .Pointer, | 70 | .const_slice_u8, |
| 71 | .single_const_pointer_to_comptime_int => return .Pointer, | 71 | .single_const_pointer, |
| 72 | .const_slice_u8 => return .Pointer, | 72 | .single_mut_pointer, |
| 73 | .many_const_pointer, | ||
| 74 | .many_mut_pointer, | ||
| 75 | .c_const_pointer, | ||
| 76 | .c_mut_pointer, | ||
| 77 | .const_slice, | ||
| 78 | .mut_slice, | ||
| 79 | .pointer, | ||
| 80 | => return .Pointer, | ||
| 73 | 81 | ||
| 74 | .optional, | 82 | .optional, |
| 75 | .optional_single_const_pointer, | 83 | .optional_single_const_pointer, |
| 76 | .optional_single_mut_pointer, | 84 | .optional_single_mut_pointer, |
| 77 | => return .Optional, | 85 | => return .Optional, |
| 86 | .enum_literal => return .EnumLiteral, | ||
| 78 | } | 87 | } |
| 79 | } | 88 | } |
| 80 | 89 | ||
| ... | @@ -107,13 +116,19 @@ pub const Type = extern union { | ... | @@ -107,13 +116,19 @@ pub const Type = extern union { |
| 107 | return @fieldParentPtr(T, "base", self.ptr_otherwise); | 116 | return @fieldParentPtr(T, "base", self.ptr_otherwise); |
| 108 | } | 117 | } |
| 109 | 118 | ||
| 110 | pub fn castPointer(self: Type) ?*Payload.Pointer { | 119 | pub fn castPointer(self: Type) ?*Payload.PointerSimple { |
| 111 | return switch (self.tag()) { | 120 | return switch (self.tag()) { |
| 112 | .single_const_pointer, | 121 | .single_const_pointer, |
| 113 | .single_mut_pointer, | 122 | .single_mut_pointer, |
| 123 | .many_const_pointer, | ||
| 124 | .many_mut_pointer, | ||
| 125 | .c_const_pointer, | ||
| 126 | .c_mut_pointer, | ||
| 127 | .const_slice, | ||
| 128 | .mut_slice, | ||
| 114 | .optional_single_const_pointer, | 129 | .optional_single_const_pointer, |
| 115 | .optional_single_mut_pointer, | 130 | .optional_single_mut_pointer, |
| 116 | => @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise), | 131 | => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise), |
| 117 | else => null, | 132 | else => null, |
| 118 | }; | 133 | }; |
| 119 | } | 134 | } |
| ... | @@ -127,6 +142,7 @@ pub const Type = extern union { | ... | @@ -127,6 +142,7 @@ pub const Type = extern union { |
| 127 | if (zig_tag_a != zig_tag_b) | 142 | if (zig_tag_a != zig_tag_b) |
| 128 | return false; | 143 | return false; |
| 129 | switch (zig_tag_a) { | 144 | switch (zig_tag_a) { |
| 145 | .EnumLiteral => return true, | ||
| 130 | .Type => return true, | 146 | .Type => return true, |
| 131 | .Void => return true, | 147 | .Void => return true, |
| 132 | .Bool => return true, | 148 | .Bool => return true, |
| ... | @@ -196,8 +212,8 @@ pub const Type = extern union { | ... | @@ -196,8 +212,8 @@ pub const Type = extern union { |
| 196 | return true; | 212 | return true; |
| 197 | }, | 213 | }, |
| 198 | .Optional => { | 214 | .Optional => { |
| 199 | var buf_a: Payload.Pointer = undefined; | 215 | var buf_a: Payload.PointerSimple = undefined; |
| 200 | var buf_b: Payload.Pointer = undefined; | 216 | var buf_b: Payload.PointerSimple = undefined; |
| 201 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b)); | 217 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b)); |
| 202 | }, | 218 | }, |
| 203 | .Float, | 219 | .Float, |
| ... | @@ -211,7 +227,6 @@ pub const Type = extern union { | ... | @@ -211,7 +227,6 @@ pub const Type = extern union { |
| 211 | .Frame, | 227 | .Frame, |
| 212 | .AnyFrame, | 228 | .AnyFrame, |
| 213 | .Vector, | 229 | .Vector, |
| 214 | .EnumLiteral, | ||
| 215 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), | 230 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), |
| 216 | } | 231 | } |
| 217 | } | 232 | } |
| ... | @@ -262,7 +277,7 @@ pub const Type = extern union { | ... | @@ -262,7 +277,7 @@ pub const Type = extern union { |
| 262 | } | 277 | } |
| 263 | }, | 278 | }, |
| 264 | .Optional => { | 279 | .Optional => { |
| 265 | var buf: Payload.Pointer = undefined; | 280 | var buf: Payload.PointerSimple = undefined; |
| 266 | std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); | 281 | std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); |
| 267 | }, | 282 | }, |
| 268 | .Float, | 283 | .Float, |
| ... | @@ -327,9 +342,11 @@ pub const Type = extern union { | ... | @@ -327,9 +342,11 @@ pub const Type = extern union { |
| 327 | .fn_ccc_void_no_args, | 342 | .fn_ccc_void_no_args, |
| 328 | .single_const_pointer_to_comptime_int, | 343 | .single_const_pointer_to_comptime_int, |
| 329 | .const_slice_u8, | 344 | .const_slice_u8, |
| 345 | .enum_literal, | ||
| 330 | => unreachable, | 346 | => unreachable, |
| 331 | 347 | ||
| 332 | .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0), | 348 | .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0), |
| 349 | .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8), | ||
| 333 | .array => { | 350 | .array => { |
| 334 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); | 351 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); |
| 335 | const new_payload = try allocator.create(Payload.Array); | 352 | const new_payload = try allocator.create(Payload.Array); |
| ... | @@ -340,6 +357,17 @@ pub const Type = extern union { | ... | @@ -340,6 +357,17 @@ pub const Type = extern union { |
| 340 | }; | 357 | }; |
| 341 | return Type{ .ptr_otherwise = &new_payload.base }; | 358 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 342 | }, | 359 | }, |
| 360 | .array_sentinel => { | ||
| 361 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); | ||
| 362 | const new_payload = try allocator.create(Payload.ArraySentinel); | ||
| 363 | new_payload.* = .{ | ||
| 364 | .base = payload.base, | ||
| 365 | .len = payload.len, | ||
| 366 | .sentinel = try payload.sentinel.copy(allocator), | ||
| 367 | .elem_type = try payload.elem_type.copy(allocator), | ||
| 368 | }; | ||
| 369 | return Type{ .ptr_otherwise = &new_payload.base }; | ||
| 370 | }, | ||
| 343 | .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned), | 371 | .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned), |
| 344 | .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned), | 372 | .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned), |
| 345 | .function => { | 373 | .function => { |
| ... | @@ -360,9 +388,34 @@ pub const Type = extern union { | ... | @@ -360,9 +388,34 @@ pub const Type = extern union { |
| 360 | .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"), | 388 | .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"), |
| 361 | .single_const_pointer, | 389 | .single_const_pointer, |
| 362 | .single_mut_pointer, | 390 | .single_mut_pointer, |
| 391 | .many_const_pointer, | ||
| 392 | .many_mut_pointer, | ||
| 393 | .c_const_pointer, | ||
| 394 | .c_mut_pointer, | ||
| 395 | .const_slice, | ||
| 396 | .mut_slice, | ||
| 363 | .optional_single_mut_pointer, | 397 | .optional_single_mut_pointer, |
| 364 | .optional_single_const_pointer, | 398 | .optional_single_const_pointer, |
| 365 | => return self.copyPayloadSingleField(allocator, Payload.Pointer, "pointee_type"), | 399 | => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"), |
| 400 | |||
| 401 | .pointer => { | ||
| 402 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | ||
| 403 | const new_payload = try allocator.create(Payload.Pointer); | ||
| 404 | new_payload.* = .{ | ||
| 405 | .base = payload.base, | ||
| 406 | |||
| 407 | .pointee_type = try payload.pointee_type.copy(allocator), | ||
| 408 | .sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null, | ||
| 409 | .@"align" = payload.@"align", | ||
| 410 | .bit_offset = payload.bit_offset, | ||
| 411 | .host_size = payload.host_size, | ||
| 412 | .@"allowzero" = payload.@"allowzero", | ||
| 413 | .mutable = payload.mutable, | ||
| 414 | .@"volatile" = payload.@"volatile", | ||
| 415 | .size = payload.size, | ||
| 416 | }; | ||
| 417 | return Type{ .ptr_otherwise = &new_payload.base }; | ||
| 418 | }, | ||
| 366 | } | 419 | } |
| 367 | } | 420 | } |
| 368 | 421 | ||
| ... | @@ -425,6 +478,7 @@ pub const Type = extern union { | ... | @@ -425,6 +478,7 @@ pub const Type = extern union { |
| 425 | .noreturn, | 478 | .noreturn, |
| 426 | => return out_stream.writeAll(@tagName(t)), | 479 | => return out_stream.writeAll(@tagName(t)), |
| 427 | 480 | ||
| 481 | .enum_literal => return out_stream.writeAll("@TypeOf(.EnumLiteral)"), | ||
| 428 | .@"null" => return out_stream.writeAll("@TypeOf(null)"), | 482 | .@"null" => return out_stream.writeAll("@TypeOf(null)"), |
| 429 | .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"), | 483 | .@"undefined" => return out_stream.writeAll("@TypeOf(undefined)"), |
| 430 | 484 | ||
| ... | @@ -442,9 +496,14 @@ pub const Type = extern union { | ... | @@ -442,9 +496,14 @@ pub const Type = extern union { |
| 442 | try param_type.format("", .{}, out_stream); | 496 | try param_type.format("", .{}, out_stream); |
| 443 | } | 497 | } |
| 444 | try out_stream.writeAll(") "); | 498 | try out_stream.writeAll(") "); |
| 445 | try payload.return_type.format("", .{}, out_stream); | 499 | ty = payload.return_type; |
| 500 | continue; | ||
| 446 | }, | 501 | }, |
| 447 | 502 | ||
| 503 | .array_u8 => { | ||
| 504 | const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise); | ||
| 505 | return out_stream.print("[{}]u8", .{payload.len}); | ||
| 506 | }, | ||
| 448 | .array_u8_sentinel_0 => { | 507 | .array_u8_sentinel_0 => { |
| 449 | const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise); | 508 | const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise); |
| 450 | return out_stream.print("[{}:0]u8", .{payload.len}); | 509 | return out_stream.print("[{}:0]u8", .{payload.len}); |
| ... | @@ -455,18 +514,60 @@ pub const Type = extern union { | ... | @@ -455,18 +514,60 @@ pub const Type = extern union { |
| 455 | ty = payload.elem_type; | 514 | ty = payload.elem_type; |
| 456 | continue; | 515 | continue; |
| 457 | }, | 516 | }, |
| 517 | .array_sentinel => { | ||
| 518 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise); | ||
| 519 | try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel }); | ||
| 520 | ty = payload.elem_type; | ||
| 521 | continue; | ||
| 522 | }, | ||
| 458 | .single_const_pointer => { | 523 | .single_const_pointer => { |
| 459 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | 524 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); |
| 460 | try out_stream.writeAll("*const "); | 525 | try out_stream.writeAll("*const "); |
| 461 | ty = payload.pointee_type; | 526 | ty = payload.pointee_type; |
| 462 | continue; | 527 | continue; |
| 463 | }, | 528 | }, |
| 464 | .single_mut_pointer => { | 529 | .single_mut_pointer => { |
| 465 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | 530 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); |
| 466 | try out_stream.writeAll("*"); | 531 | try out_stream.writeAll("*"); |
| 467 | ty = payload.pointee_type; | 532 | ty = payload.pointee_type; |
| 468 | continue; | 533 | continue; |
| 469 | }, | 534 | }, |
| 535 | .many_const_pointer => { | ||
| 536 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 537 | try out_stream.writeAll("[*]const "); | ||
| 538 | ty = payload.pointee_type; | ||
| 539 | continue; | ||
| 540 | }, | ||
| 541 | .many_mut_pointer => { | ||
| 542 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 543 | try out_stream.writeAll("[*]"); | ||
| 544 | ty = payload.pointee_type; | ||
| 545 | continue; | ||
| 546 | }, | ||
| 547 | .c_const_pointer => { | ||
| 548 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 549 | try out_stream.writeAll("[*c]const "); | ||
| 550 | ty = payload.pointee_type; | ||
| 551 | continue; | ||
| 552 | }, | ||
| 553 | .c_mut_pointer => { | ||
| 554 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 555 | try out_stream.writeAll("[*c]"); | ||
| 556 | ty = payload.pointee_type; | ||
| 557 | continue; | ||
| 558 | }, | ||
| 559 | .const_slice => { | ||
| 560 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 561 | try out_stream.writeAll("[]const "); | ||
| 562 | ty = payload.pointee_type; | ||
| 563 | continue; | ||
| 564 | }, | ||
| 565 | .mut_slice => { | ||
| 566 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | ||
| 567 | try out_stream.writeAll("[]"); | ||
| 568 | ty = payload.pointee_type; | ||
| 569 | continue; | ||
| 570 | }, | ||
| 470 | .int_signed => { | 571 | .int_signed => { |
| 471 | const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise); | 572 | const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise); |
| 472 | return out_stream.print("i{}", .{payload.bits}); | 573 | return out_stream.print("i{}", .{payload.bits}); |
| ... | @@ -482,17 +583,45 @@ pub const Type = extern union { | ... | @@ -482,17 +583,45 @@ pub const Type = extern union { |
| 482 | continue; | 583 | continue; |
| 483 | }, | 584 | }, |
| 484 | .optional_single_const_pointer => { | 585 | .optional_single_const_pointer => { |
| 485 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | 586 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); |
| 486 | try out_stream.writeAll("?*const "); | 587 | try out_stream.writeAll("?*const "); |
| 487 | ty = payload.pointee_type; | 588 | ty = payload.pointee_type; |
| 488 | continue; | 589 | continue; |
| 489 | }, | 590 | }, |
| 490 | .optional_single_mut_pointer => { | 591 | .optional_single_mut_pointer => { |
| 491 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | 592 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); |
| 492 | try out_stream.writeAll("?*"); | 593 | try out_stream.writeAll("?*"); |
| 493 | ty = payload.pointee_type; | 594 | ty = payload.pointee_type; |
| 494 | continue; | 595 | continue; |
| 495 | }, | 596 | }, |
| 597 | |||
| 598 | .pointer => { | ||
| 599 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | ||
| 600 | if (payload.sentinel) |some| switch (payload.size) { | ||
| 601 | .One, .C => unreachable, | ||
| 602 | .Many => try out_stream.writeAll("[*:{}]"), | ||
| 603 | .Slice => try out_stream.writeAll("[:{}]"), | ||
| 604 | } else switch (payload.size) { | ||
| 605 | .One => try out_stream.writeAll("*"), | ||
| 606 | .Many => try out_stream.writeAll("[*]"), | ||
| 607 | .C => try out_stream.writeAll("[*c]"), | ||
| 608 | .Slice => try out_stream.writeAll("[]"), | ||
| 609 | } | ||
| 610 | if (payload.@"align" != 0) { | ||
| 611 | try out_stream.print("align({}", .{payload.@"align"}); | ||
| 612 | |||
| 613 | if (payload.bit_offset != 0) { | ||
| 614 | try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size }); | ||
| 615 | } | ||
| 616 | try out_stream.writeAll(") "); | ||
| 617 | } | ||
| 618 | if (!payload.mutable) try out_stream.writeAll("const "); | ||
| 619 | if (payload.@"volatile") try out_stream.writeAll("volatile "); | ||
| 620 | if (payload.@"allowzero") try out_stream.writeAll("allowzero "); | ||
| 621 | |||
| 622 | ty = payload.pointee_type; | ||
| 623 | continue; | ||
| 624 | }, | ||
| 496 | } | 625 | } |
| 497 | unreachable; | 626 | unreachable; |
| 498 | } | 627 | } |
| ... | @@ -539,6 +668,7 @@ pub const Type = extern union { | ... | @@ -539,6 +668,7 @@ pub const Type = extern union { |
| 539 | .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type), | 668 | .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type), |
| 540 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), | 669 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), |
| 541 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), | 670 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), |
| 671 | .enum_literal => return Value.initTag(.enum_literal_type), | ||
| 542 | else => { | 672 | else => { |
| 543 | const ty_payload = try allocator.create(Value.Payload.Ty); | 673 | const ty_payload = try allocator.create(Value.Payload.Ty); |
| 544 | ty_payload.* = .{ .ty = self }; | 674 | ty_payload.* = .{ .ty = self }; |
| ... | @@ -588,8 +718,8 @@ pub const Type = extern union { | ... | @@ -588,8 +718,8 @@ pub const Type = extern union { |
| 588 | => true, | 718 | => true, |
| 589 | // TODO lazy types | 719 | // TODO lazy types |
| 590 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, | 720 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, |
| 591 | .single_const_pointer => self.elemType().hasCodeGenBits(), | 721 | .array_u8 => self.arrayLen() != 0, |
| 592 | .single_mut_pointer => self.elemType().hasCodeGenBits(), | 722 | .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(), |
| 593 | .int_signed => self.cast(Payload.IntSigned).?.bits == 0, | 723 | .int_signed => self.cast(Payload.IntSigned).?.bits == 0, |
| 594 | .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0, | 724 | .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0, |
| 595 | 725 | ||
| ... | @@ -601,6 +731,7 @@ pub const Type = extern union { | ... | @@ -601,6 +731,7 @@ pub const Type = extern union { |
| 601 | .noreturn, | 731 | .noreturn, |
| 602 | .@"null", | 732 | .@"null", |
| 603 | .@"undefined", | 733 | .@"undefined", |
| 734 | .enum_literal, | ||
| 604 | => false, | 735 | => false, |
| 605 | }; | 736 | }; |
| 606 | } | 737 | } |
| ... | @@ -616,6 +747,7 @@ pub const Type = extern union { | ... | @@ -616,6 +747,7 @@ pub const Type = extern union { |
| 616 | .i8, | 747 | .i8, |
| 617 | .bool, | 748 | .bool, |
| 618 | .array_u8_sentinel_0, | 749 | .array_u8_sentinel_0, |
| 750 | .array_u8, | ||
| 619 | => return 1, | 751 | => return 1, |
| 620 | 752 | ||
| 621 | .fn_noreturn_no_args, // represents machine code; not a pointer | 753 | .fn_noreturn_no_args, // represents machine code; not a pointer |
| ... | @@ -638,10 +770,23 @@ pub const Type = extern union { | ... | @@ -638,10 +770,23 @@ pub const Type = extern union { |
| 638 | .const_slice_u8, | 770 | .const_slice_u8, |
| 639 | .single_const_pointer, | 771 | .single_const_pointer, |
| 640 | .single_mut_pointer, | 772 | .single_mut_pointer, |
| 773 | .many_const_pointer, | ||
| 774 | .many_mut_pointer, | ||
| 775 | .c_const_pointer, | ||
| 776 | .c_mut_pointer, | ||
| 777 | .const_slice, | ||
| 778 | .mut_slice, | ||
| 641 | .optional_single_const_pointer, | 779 | .optional_single_const_pointer, |
| 642 | .optional_single_mut_pointer, | 780 | .optional_single_mut_pointer, |
| 643 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | 781 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 644 | 782 | ||
| 783 | .pointer => { | ||
| 784 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | ||
| 785 | |||
| 786 | if (payload.@"align" != 0) return payload.@"align"; | ||
| 787 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); | ||
| 788 | }, | ||
| 789 | |||
| 645 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), | 790 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| 646 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), | 791 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), |
| 647 | .c_int => return @divExact(CType.int.sizeInBits(target), 8), | 792 | .c_int => return @divExact(CType.int.sizeInBits(target), 8), |
| ... | @@ -659,7 +804,7 @@ pub const Type = extern union { | ... | @@ -659,7 +804,7 @@ pub const Type = extern union { |
| 659 | 804 | ||
| 660 | .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type | 805 | .anyerror => return 2, // TODO revisit this when we have the concept of the error tag type |
| 661 | 806 | ||
| 662 | .array => return self.cast(Payload.Array).?.elem_type.abiAlignment(target), | 807 | .array, .array_sentinel => return self.elemType().abiAlignment(target), |
| 663 | 808 | ||
| 664 | .int_signed, .int_unsigned => { | 809 | .int_signed, .int_unsigned => { |
| 665 | const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| | 810 | const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| |
| ... | @@ -673,7 +818,7 @@ pub const Type = extern union { | ... | @@ -673,7 +818,7 @@ pub const Type = extern union { |
| 673 | }, | 818 | }, |
| 674 | 819 | ||
| 675 | .optional => { | 820 | .optional => { |
| 676 | var buf: Payload.Pointer = undefined; | 821 | var buf: Payload.PointerSimple = undefined; |
| 677 | const child_type = self.optionalChild(&buf); | 822 | const child_type = self.optionalChild(&buf); |
| 678 | if (!child_type.hasCodeGenBits()) return 1; | 823 | if (!child_type.hasCodeGenBits()) return 1; |
| 679 | 824 | ||
| ... | @@ -691,6 +836,7 @@ pub const Type = extern union { | ... | @@ -691,6 +836,7 @@ pub const Type = extern union { |
| 691 | .noreturn, | 836 | .noreturn, |
| 692 | .@"null", | 837 | .@"null", |
| 693 | .@"undefined", | 838 | .@"undefined", |
| 839 | .enum_literal, | ||
| 694 | => unreachable, | 840 | => unreachable, |
| 695 | }; | 841 | }; |
| 696 | } | 842 | } |
| ... | @@ -711,31 +857,55 @@ pub const Type = extern union { | ... | @@ -711,31 +857,55 @@ pub const Type = extern union { |
| 711 | .noreturn => unreachable, | 857 | .noreturn => unreachable, |
| 712 | .@"null" => unreachable, | 858 | .@"null" => unreachable, |
| 713 | .@"undefined" => unreachable, | 859 | .@"undefined" => unreachable, |
| 860 | .enum_literal => unreachable, | ||
| 861 | .single_const_pointer_to_comptime_int => unreachable, | ||
| 714 | 862 | ||
| 715 | .u8, | 863 | .u8, |
| 716 | .i8, | 864 | .i8, |
| 717 | .bool, | 865 | .bool, |
| 718 | => return 1, | 866 | => return 1, |
| 719 | 867 | ||
| 720 | .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len, | 868 | .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len, |
| 869 | .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1, | ||
| 721 | .array => { | 870 | .array => { |
| 722 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); | 871 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); |
| 723 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | 872 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); |
| 724 | return payload.len * elem_size; | 873 | return payload.len * elem_size; |
| 725 | }, | 874 | }, |
| 875 | .array_sentinel => { | ||
| 876 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); | ||
| 877 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | ||
| 878 | return (payload.len + 1) * elem_size; | ||
| 879 | }, | ||
| 726 | .i16, .u16 => return 2, | 880 | .i16, .u16 => return 2, |
| 727 | .i32, .u32 => return 4, | 881 | .i32, .u32 => return 4, |
| 728 | .i64, .u64 => return 8, | 882 | .i64, .u64 => return 8, |
| 729 | 883 | ||
| 730 | .isize, | 884 | .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 731 | .usize, | 885 | |
| 732 | .single_const_pointer_to_comptime_int, | 886 | .const_slice, |
| 887 | .mut_slice, | ||
| 733 | .const_slice_u8, | 888 | .const_slice_u8, |
| 734 | .single_const_pointer, | 889 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8) * 2, |
| 735 | .single_mut_pointer, | 890 | |
| 736 | .optional_single_const_pointer, | 891 | .optional_single_const_pointer, |
| 737 | .optional_single_mut_pointer, | 892 | .optional_single_mut_pointer, |
| 738 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | 893 | => { |
| 894 | if (self.elemType().hasCodeGenBits()) return 1; | ||
| 895 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); | ||
| 896 | }, | ||
| 897 | |||
| 898 | .single_const_pointer, | ||
| 899 | .single_mut_pointer, | ||
| 900 | .many_const_pointer, | ||
| 901 | .many_mut_pointer, | ||
| 902 | .c_const_pointer, | ||
| 903 | .c_mut_pointer, | ||
| 904 | .pointer, | ||
| 905 | => { | ||
| 906 | if (self.elemType().hasCodeGenBits()) return 0; | ||
| 907 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); | ||
| 908 | }, | ||
| 739 | 909 | ||
| 740 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), | 910 | .c_short => return @divExact(CType.short.sizeInBits(target), 8), |
| 741 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), | 911 | .c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8), |
| ... | @@ -766,7 +936,7 @@ pub const Type = extern union { | ... | @@ -766,7 +936,7 @@ pub const Type = extern union { |
| 766 | }, | 936 | }, |
| 767 | 937 | ||
| 768 | .optional => { | 938 | .optional => { |
| 769 | var buf: Payload.Pointer = undefined; | 939 | var buf: Payload.PointerSimple = undefined; |
| 770 | const child_type = self.optionalChild(&buf); | 940 | const child_type = self.optionalChild(&buf); |
| 771 | if (!child_type.hasCodeGenBits()) return 1; | 941 | if (!child_type.hasCodeGenBits()) return 1; |
| 772 | 942 | ||
| ... | @@ -818,6 +988,8 @@ pub const Type = extern union { | ... | @@ -818,6 +988,8 @@ pub const Type = extern union { |
| 818 | .@"null", | 988 | .@"null", |
| 819 | .@"undefined", | 989 | .@"undefined", |
| 820 | .array, | 990 | .array, |
| 991 | .array_sentinel, | ||
| 992 | .array_u8, | ||
| 821 | .array_u8_sentinel_0, | 993 | .array_u8_sentinel_0, |
| 822 | .const_slice_u8, | 994 | .const_slice_u8, |
| 823 | .fn_noreturn_no_args, | 995 | .fn_noreturn_no_args, |
| ... | @@ -830,12 +1002,21 @@ pub const Type = extern union { | ... | @@ -830,12 +1002,21 @@ pub const Type = extern union { |
| 830 | .optional, | 1002 | .optional, |
| 831 | .optional_single_mut_pointer, | 1003 | .optional_single_mut_pointer, |
| 832 | .optional_single_const_pointer, | 1004 | .optional_single_const_pointer, |
| 1005 | .enum_literal, | ||
| 1006 | .many_const_pointer, | ||
| 1007 | .many_mut_pointer, | ||
| 1008 | .c_const_pointer, | ||
| 1009 | .c_mut_pointer, | ||
| 1010 | .const_slice, | ||
| 1011 | .mut_slice, | ||
| 833 | => false, | 1012 | => false, |
| 834 | 1013 | ||
| 835 | .single_const_pointer, | 1014 | .single_const_pointer, |
| 836 | .single_mut_pointer, | 1015 | .single_mut_pointer, |
| 837 | .single_const_pointer_to_comptime_int, | 1016 | .single_const_pointer_to_comptime_int, |
| 838 | => true, | 1017 | => true, |
| 1018 | |||
| 1019 | .pointer => self.cast(Payload.Pointer).?.size == .One, | ||
| 839 | }; | 1020 | }; |
| 840 | } | 1021 | } |
| 841 | 1022 | ||
| ... | @@ -875,9 +1056,15 @@ pub const Type = extern union { | ... | @@ -875,9 +1056,15 @@ pub const Type = extern union { |
| 875 | .@"null", | 1056 | .@"null", |
| 876 | .@"undefined", | 1057 | .@"undefined", |
| 877 | .array, | 1058 | .array, |
| 1059 | .array_sentinel, | ||
| 1060 | .array_u8, | ||
| 878 | .array_u8_sentinel_0, | 1061 | .array_u8_sentinel_0, |
| 879 | .single_const_pointer, | 1062 | .single_const_pointer, |
| 880 | .single_mut_pointer, | 1063 | .single_mut_pointer, |
| 1064 | .many_const_pointer, | ||
| 1065 | .many_mut_pointer, | ||
| 1066 | .c_const_pointer, | ||
| 1067 | .c_mut_pointer, | ||
| 881 | .single_const_pointer_to_comptime_int, | 1068 | .single_const_pointer_to_comptime_int, |
| 882 | .fn_noreturn_no_args, | 1069 | .fn_noreturn_no_args, |
| 883 | .fn_void_no_args, | 1070 | .fn_void_no_args, |
| ... | @@ -889,9 +1076,15 @@ pub const Type = extern union { | ... | @@ -889,9 +1076,15 @@ pub const Type = extern union { |
| 889 | .optional, | 1076 | .optional, |
| 890 | .optional_single_mut_pointer, | 1077 | .optional_single_mut_pointer, |
| 891 | .optional_single_const_pointer, | 1078 | .optional_single_const_pointer, |
| 1079 | .enum_literal, | ||
| 892 | => false, | 1080 | => false, |
| 893 | 1081 | ||
| 894 | .const_slice_u8 => true, | 1082 | .const_slice, |
| 1083 | .mut_slice, | ||
| 1084 | .const_slice_u8, | ||
| 1085 | => true, | ||
| 1086 | |||
| 1087 | .pointer => self.cast(Payload.Pointer).?.size == .Slice, | ||
| 895 | }; | 1088 | }; |
| 896 | } | 1089 | } |
| 897 | 1090 | ||
| ... | @@ -931,6 +1124,8 @@ pub const Type = extern union { | ... | @@ -931,6 +1124,8 @@ pub const Type = extern union { |
| 931 | .@"null", | 1124 | .@"null", |
| 932 | .@"undefined", | 1125 | .@"undefined", |
| 933 | .array, | 1126 | .array, |
| 1127 | .array_sentinel, | ||
| 1128 | .array_u8, | ||
| 934 | .array_u8_sentinel_0, | 1129 | .array_u8_sentinel_0, |
| 935 | .fn_noreturn_no_args, | 1130 | .fn_noreturn_no_args, |
| 936 | .fn_void_no_args, | 1131 | .fn_void_no_args, |
| ... | @@ -940,15 +1135,24 @@ pub const Type = extern union { | ... | @@ -940,15 +1135,24 @@ pub const Type = extern union { |
| 940 | .int_unsigned, | 1135 | .int_unsigned, |
| 941 | .int_signed, | 1136 | .int_signed, |
| 942 | .single_mut_pointer, | 1137 | .single_mut_pointer, |
| 1138 | .many_mut_pointer, | ||
| 1139 | .c_mut_pointer, | ||
| 943 | .optional, | 1140 | .optional, |
| 944 | .optional_single_mut_pointer, | 1141 | .optional_single_mut_pointer, |
| 945 | .optional_single_const_pointer, | 1142 | .optional_single_const_pointer, |
| 1143 | .enum_literal, | ||
| 1144 | .mut_slice, | ||
| 946 | => false, | 1145 | => false, |
| 947 | 1146 | ||
| 948 | .single_const_pointer, | 1147 | .single_const_pointer, |
| 1148 | .many_const_pointer, | ||
| 1149 | .c_const_pointer, | ||
| 949 | .single_const_pointer_to_comptime_int, | 1150 | .single_const_pointer_to_comptime_int, |
| 950 | .const_slice_u8, | 1151 | .const_slice_u8, |
| 1152 | .const_slice, | ||
| 951 | => true, | 1153 | => true, |
| 1154 | |||
| 1155 | .pointer => !self.cast(Payload.Pointer).?.mutable, | ||
| 952 | }; | 1156 | }; |
| 953 | } | 1157 | } |
| 954 | 1158 | ||
| ... | @@ -988,6 +1192,8 @@ pub const Type = extern union { | ... | @@ -988,6 +1192,8 @@ pub const Type = extern union { |
| 988 | .@"null", | 1192 | .@"null", |
| 989 | .@"undefined", | 1193 | .@"undefined", |
| 990 | .array, | 1194 | .array, |
| 1195 | .array_sentinel, | ||
| 1196 | .array_u8, | ||
| 991 | .array_u8_sentinel_0, | 1197 | .array_u8_sentinel_0, |
| 992 | .fn_noreturn_no_args, | 1198 | .fn_noreturn_no_args, |
| 993 | .fn_void_no_args, | 1199 | .fn_void_no_args, |
| ... | @@ -998,12 +1204,24 @@ pub const Type = extern union { | ... | @@ -998,12 +1204,24 @@ pub const Type = extern union { |
| 998 | .int_signed, | 1204 | .int_signed, |
| 999 | .single_mut_pointer, | 1205 | .single_mut_pointer, |
| 1000 | .single_const_pointer, | 1206 | .single_const_pointer, |
| 1207 | .many_const_pointer, | ||
| 1208 | .many_mut_pointer, | ||
| 1209 | .c_const_pointer, | ||
| 1210 | .c_mut_pointer, | ||
| 1211 | .const_slice, | ||
| 1212 | .mut_slice, | ||
| 1001 | .single_const_pointer_to_comptime_int, | 1213 | .single_const_pointer_to_comptime_int, |
| 1002 | .const_slice_u8, | 1214 | .const_slice_u8, |
| 1003 | .optional, | 1215 | .optional, |
| 1004 | .optional_single_mut_pointer, | 1216 | .optional_single_mut_pointer, |
| 1005 | .optional_single_const_pointer, | 1217 | .optional_single_const_pointer, |
| 1218 | .enum_literal, | ||
| 1006 | => false, | 1219 | => false, |
| 1220 | |||
| 1221 | .pointer => { | ||
| 1222 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | ||
| 1223 | return payload.@"volatile"; | ||
| 1224 | }, | ||
| 1007 | }; | 1225 | }; |
| 1008 | } | 1226 | } |
| 1009 | 1227 | ||
| ... | @@ -1012,7 +1230,7 @@ pub const Type = extern union { | ... | @@ -1012,7 +1230,7 @@ pub const Type = extern union { |
| 1012 | switch (self.tag()) { | 1230 | switch (self.tag()) { |
| 1013 | .optional_single_const_pointer, .optional_single_mut_pointer => return true, | 1231 | .optional_single_const_pointer, .optional_single_mut_pointer => return true, |
| 1014 | .optional => { | 1232 | .optional => { |
| 1015 | var buf: Payload.Pointer = undefined; | 1233 | var buf: Payload.PointerSimple = undefined; |
| 1016 | const child_type = self.optionalChild(&buf); | 1234 | const child_type = self.optionalChild(&buf); |
| 1017 | // optionals of zero sized pointers behave like bools | 1235 | // optionals of zero sized pointers behave like bools |
| 1018 | if (!child_type.hasCodeGenBits()) return false; | 1236 | if (!child_type.hasCodeGenBits()) return false; |
| ... | @@ -1023,6 +1241,45 @@ pub const Type = extern union { | ... | @@ -1023,6 +1241,45 @@ pub const Type = extern union { |
| 1023 | } | 1241 | } |
| 1024 | } | 1242 | } |
| 1025 | 1243 | ||
| 1244 | /// Returns if type can be used for a runtime variable | ||
| 1245 | pub fn isValidVarType(self: Type, is_extern: bool) bool { | ||
| 1246 | var ty = self; | ||
| 1247 | while (true) switch (ty.zigTypeTag()) { | ||
| 1248 | .Bool, | ||
| 1249 | .Int, | ||
| 1250 | .Float, | ||
| 1251 | .ErrorSet, | ||
| 1252 | .Enum, | ||
| 1253 | .Frame, | ||
| 1254 | .AnyFrame, | ||
| 1255 | .Vector, | ||
| 1256 | => return true, | ||
| 1257 | |||
| 1258 | .Opaque => return is_extern, | ||
| 1259 | .BoundFn, | ||
| 1260 | .ComptimeFloat, | ||
| 1261 | .ComptimeInt, | ||
| 1262 | .EnumLiteral, | ||
| 1263 | .NoReturn, | ||
| 1264 | .Type, | ||
| 1265 | .Void, | ||
| 1266 | .Undefined, | ||
| 1267 | .Null, | ||
| 1268 | => return false, | ||
| 1269 | |||
| 1270 | .Optional => { | ||
| 1271 | var buf: Payload.PointerSimple = undefined; | ||
| 1272 | return ty.optionalChild(&buf).isValidVarType(is_extern); | ||
| 1273 | }, | ||
| 1274 | .Pointer, .Array => ty = ty.elemType(), | ||
| 1275 | |||
| 1276 | .ErrorUnion => @panic("TODO fn isValidVarType"), | ||
| 1277 | .Fn => @panic("TODO fn isValidVarType"), | ||
| 1278 | .Struct => @panic("TODO struct isValidVarType"), | ||
| 1279 | .Union => @panic("TODO union isValidVarType"), | ||
| 1280 | }; | ||
| 1281 | } | ||
| 1282 | |||
| 1026 | /// Asserts the type is a pointer or array type. | 1283 | /// Asserts the type is a pointer or array type. |
| 1027 | pub fn elemType(self: Type) Type { | 1284 | pub fn elemType(self: Type) Type { |
| 1028 | return switch (self.tag()) { | 1285 | return switch (self.tag()) { |
| ... | @@ -1069,18 +1326,28 @@ pub const Type = extern union { | ... | @@ -1069,18 +1326,28 @@ pub const Type = extern union { |
| 1069 | .optional, | 1326 | .optional, |
| 1070 | .optional_single_const_pointer, | 1327 | .optional_single_const_pointer, |
| 1071 | .optional_single_mut_pointer, | 1328 | .optional_single_mut_pointer, |
| 1329 | .enum_literal, | ||
| 1072 | => unreachable, | 1330 | => unreachable, |
| 1073 | 1331 | ||
| 1074 | .array => self.cast(Payload.Array).?.elem_type, | 1332 | .array => self.cast(Payload.Array).?.elem_type, |
| 1075 | .single_const_pointer => self.castPointer().?.pointee_type, | 1333 | .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type, |
| 1076 | .single_mut_pointer => self.castPointer().?.pointee_type, | 1334 | .single_const_pointer, |
| 1077 | .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), | 1335 | .single_mut_pointer, |
| 1336 | .many_const_pointer, | ||
| 1337 | .many_mut_pointer, | ||
| 1338 | .c_const_pointer, | ||
| 1339 | .c_mut_pointer, | ||
| 1340 | .const_slice, | ||
| 1341 | .mut_slice, | ||
| 1342 | => self.castPointer().?.pointee_type, | ||
| 1343 | .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), | ||
| 1078 | .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), | 1344 | .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), |
| 1345 | .pointer => self.cast(Payload.Pointer).?.pointee_type, | ||
| 1079 | }; | 1346 | }; |
| 1080 | } | 1347 | } |
| 1081 | 1348 | ||
| 1082 | /// Asserts that the type is an optional. | 1349 | /// Asserts that the type is an optional. |
| 1083 | pub fn optionalChild(self: Type, buf: *Payload.Pointer) Type { | 1350 | pub fn optionalChild(self: Type, buf: *Payload.PointerSimple) Type { |
| 1084 | return switch (self.tag()) { | 1351 | return switch (self.tag()) { |
| 1085 | .optional => self.cast(Payload.Optional).?.child_type, | 1352 | .optional => self.cast(Payload.Optional).?.child_type, |
| 1086 | .optional_single_mut_pointer => { | 1353 | .optional_single_mut_pointer => { |
| ... | @@ -1107,7 +1374,7 @@ pub const Type = extern union { | ... | @@ -1107,7 +1374,7 @@ pub const Type = extern union { |
| 1107 | return switch (self.tag()) { | 1374 | return switch (self.tag()) { |
| 1108 | .optional => self.cast(Payload.Optional).?.child_type, | 1375 | .optional => self.cast(Payload.Optional).?.child_type, |
| 1109 | .optional_single_mut_pointer, .optional_single_const_pointer => { | 1376 | .optional_single_mut_pointer, .optional_single_const_pointer => { |
| 1110 | const payload = try allocator.create(Payload.Pointer); | 1377 | const payload = try allocator.create(Payload.PointerSimple); |
| 1111 | payload.* = .{ | 1378 | payload.* = .{ |
| 1112 | .base = .{ | 1379 | .base = .{ |
| 1113 | .tag = if (self.tag() == .optional_single_const_pointer) | 1380 | .tag = if (self.tag() == .optional_single_const_pointer) |
| ... | @@ -1164,8 +1431,15 @@ pub const Type = extern union { | ... | @@ -1164,8 +1431,15 @@ pub const Type = extern union { |
| 1164 | .fn_naked_noreturn_no_args, | 1431 | .fn_naked_noreturn_no_args, |
| 1165 | .fn_ccc_void_no_args, | 1432 | .fn_ccc_void_no_args, |
| 1166 | .function, | 1433 | .function, |
| 1434 | .pointer, | ||
| 1167 | .single_const_pointer, | 1435 | .single_const_pointer, |
| 1168 | .single_mut_pointer, | 1436 | .single_mut_pointer, |
| 1437 | .many_const_pointer, | ||
| 1438 | .many_mut_pointer, | ||
| 1439 | .c_const_pointer, | ||
| 1440 | .c_mut_pointer, | ||
| 1441 | .const_slice, | ||
| 1442 | .mut_slice, | ||
| 1169 | .single_const_pointer_to_comptime_int, | 1443 | .single_const_pointer_to_comptime_int, |
| 1170 | .const_slice_u8, | 1444 | .const_slice_u8, |
| 1171 | .int_unsigned, | 1445 | .int_unsigned, |
| ... | @@ -1173,9 +1447,12 @@ pub const Type = extern union { | ... | @@ -1173,9 +1447,12 @@ pub const Type = extern union { |
| 1173 | .optional, | 1447 | .optional, |
| 1174 | .optional_single_mut_pointer, | 1448 | .optional_single_mut_pointer, |
| 1175 | .optional_single_const_pointer, | 1449 | .optional_single_const_pointer, |
| 1450 | .enum_literal, | ||
| 1176 | => unreachable, | 1451 | => unreachable, |
| 1177 | 1452 | ||
| 1178 | .array => self.cast(Payload.Array).?.len, | 1453 | .array => self.cast(Payload.Array).?.len, |
| 1454 | .array_sentinel => self.cast(Payload.ArraySentinel).?.len, | ||
| 1455 | .array_u8 => self.cast(Payload.Array_u8).?.len, | ||
| 1179 | .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len, | 1456 | .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len, |
| 1180 | }; | 1457 | }; |
| 1181 | } | 1458 | } |
| ... | @@ -1221,8 +1498,15 @@ pub const Type = extern union { | ... | @@ -1221,8 +1498,15 @@ pub const Type = extern union { |
| 1221 | .fn_naked_noreturn_no_args, | 1498 | .fn_naked_noreturn_no_args, |
| 1222 | .fn_ccc_void_no_args, | 1499 | .fn_ccc_void_no_args, |
| 1223 | .function, | 1500 | .function, |
| 1501 | .pointer, | ||
| 1224 | .single_const_pointer, | 1502 | .single_const_pointer, |
| 1225 | .single_mut_pointer, | 1503 | .single_mut_pointer, |
| 1504 | .many_const_pointer, | ||
| 1505 | .many_mut_pointer, | ||
| 1506 | .c_const_pointer, | ||
| 1507 | .c_mut_pointer, | ||
| 1508 | .const_slice, | ||
| 1509 | .mut_slice, | ||
| 1226 | .single_const_pointer_to_comptime_int, | 1510 | .single_const_pointer_to_comptime_int, |
| 1227 | .const_slice_u8, | 1511 | .const_slice_u8, |
| 1228 | .int_unsigned, | 1512 | .int_unsigned, |
| ... | @@ -1230,9 +1514,11 @@ pub const Type = extern union { | ... | @@ -1230,9 +1514,11 @@ pub const Type = extern union { |
| 1230 | .optional, | 1514 | .optional, |
| 1231 | .optional_single_mut_pointer, | 1515 | .optional_single_mut_pointer, |
| 1232 | .optional_single_const_pointer, | 1516 | .optional_single_const_pointer, |
| 1517 | .enum_literal, | ||
| 1233 | => unreachable, | 1518 | => unreachable, |
| 1234 | 1519 | ||
| 1235 | .array => return null, | 1520 | .array, .array_u8 => return null, |
| 1521 | .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel, | ||
| 1236 | .array_u8_sentinel_0 => return Value.initTag(.zero), | 1522 | .array_u8_sentinel_0 => return Value.initTag(.zero), |
| 1237 | }; | 1523 | }; |
| 1238 | } | 1524 | } |
| ... | @@ -1266,10 +1552,19 @@ pub const Type = extern union { | ... | @@ -1266,10 +1552,19 @@ pub const Type = extern union { |
| 1266 | .fn_ccc_void_no_args, | 1552 | .fn_ccc_void_no_args, |
| 1267 | .function, | 1553 | .function, |
| 1268 | .array, | 1554 | .array, |
| 1555 | .array_sentinel, | ||
| 1556 | .array_u8, | ||
| 1557 | .array_u8_sentinel_0, | ||
| 1558 | .pointer, | ||
| 1269 | .single_const_pointer, | 1559 | .single_const_pointer, |
| 1270 | .single_mut_pointer, | 1560 | .single_mut_pointer, |
| 1561 | .many_const_pointer, | ||
| 1562 | .many_mut_pointer, | ||
| 1563 | .c_const_pointer, | ||
| 1564 | .c_mut_pointer, | ||
| 1565 | .const_slice, | ||
| 1566 | .mut_slice, | ||
| 1271 | .single_const_pointer_to_comptime_int, | 1567 | .single_const_pointer_to_comptime_int, |
| 1272 | .array_u8_sentinel_0, | ||
| 1273 | .const_slice_u8, | 1568 | .const_slice_u8, |
| 1274 | .int_unsigned, | 1569 | .int_unsigned, |
| 1275 | .u8, | 1570 | .u8, |
| ... | @@ -1284,6 +1579,7 @@ pub const Type = extern union { | ... | @@ -1284,6 +1579,7 @@ pub const Type = extern union { |
| 1284 | .optional, | 1579 | .optional, |
| 1285 | .optional_single_mut_pointer, | 1580 | .optional_single_mut_pointer, |
| 1286 | .optional_single_const_pointer, | 1581 | .optional_single_const_pointer, |
| 1582 | .enum_literal, | ||
| 1287 | => false, | 1583 | => false, |
| 1288 | 1584 | ||
| 1289 | .int_signed, | 1585 | .int_signed, |
| ... | @@ -1324,10 +1620,19 @@ pub const Type = extern union { | ... | @@ -1324,10 +1620,19 @@ pub const Type = extern union { |
| 1324 | .fn_ccc_void_no_args, | 1620 | .fn_ccc_void_no_args, |
| 1325 | .function, | 1621 | .function, |
| 1326 | .array, | 1622 | .array, |
| 1623 | .array_sentinel, | ||
| 1624 | .array_u8, | ||
| 1625 | .array_u8_sentinel_0, | ||
| 1626 | .pointer, | ||
| 1327 | .single_const_pointer, | 1627 | .single_const_pointer, |
| 1328 | .single_mut_pointer, | 1628 | .single_mut_pointer, |
| 1629 | .many_const_pointer, | ||
| 1630 | .many_mut_pointer, | ||
| 1631 | .c_const_pointer, | ||
| 1632 | .c_mut_pointer, | ||
| 1633 | .const_slice, | ||
| 1634 | .mut_slice, | ||
| 1329 | .single_const_pointer_to_comptime_int, | 1635 | .single_const_pointer_to_comptime_int, |
| 1330 | .array_u8_sentinel_0, | ||
| 1331 | .const_slice_u8, | 1636 | .const_slice_u8, |
| 1332 | .int_signed, | 1637 | .int_signed, |
| 1333 | .i8, | 1638 | .i8, |
| ... | @@ -1342,6 +1647,7 @@ pub const Type = extern union { | ... | @@ -1342,6 +1647,7 @@ pub const Type = extern union { |
| 1342 | .optional, | 1647 | .optional, |
| 1343 | .optional_single_mut_pointer, | 1648 | .optional_single_mut_pointer, |
| 1344 | .optional_single_const_pointer, | 1649 | .optional_single_const_pointer, |
| 1650 | .enum_literal, | ||
| 1345 | => false, | 1651 | => false, |
| 1346 | 1652 | ||
| 1347 | .int_unsigned, | 1653 | .int_unsigned, |
| ... | @@ -1382,14 +1688,24 @@ pub const Type = extern union { | ... | @@ -1382,14 +1688,24 @@ pub const Type = extern union { |
| 1382 | .fn_ccc_void_no_args, | 1688 | .fn_ccc_void_no_args, |
| 1383 | .function, | 1689 | .function, |
| 1384 | .array, | 1690 | .array, |
| 1691 | .array_sentinel, | ||
| 1692 | .array_u8, | ||
| 1693 | .array_u8_sentinel_0, | ||
| 1694 | .pointer, | ||
| 1385 | .single_const_pointer, | 1695 | .single_const_pointer, |
| 1386 | .single_mut_pointer, | 1696 | .single_mut_pointer, |
| 1697 | .many_const_pointer, | ||
| 1698 | .many_mut_pointer, | ||
| 1699 | .c_const_pointer, | ||
| 1700 | .c_mut_pointer, | ||
| 1701 | .const_slice, | ||
| 1702 | .mut_slice, | ||
| 1387 | .single_const_pointer_to_comptime_int, | 1703 | .single_const_pointer_to_comptime_int, |
| 1388 | .array_u8_sentinel_0, | ||
| 1389 | .const_slice_u8, | 1704 | .const_slice_u8, |
| 1390 | .optional, | 1705 | .optional, |
| 1391 | .optional_single_mut_pointer, | 1706 | .optional_single_mut_pointer, |
| 1392 | .optional_single_const_pointer, | 1707 | .optional_single_const_pointer, |
| 1708 | .enum_literal, | ||
| 1393 | => unreachable, | 1709 | => unreachable, |
| 1394 | 1710 | ||
| 1395 | .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, | 1711 | .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, |
| ... | @@ -1438,10 +1754,19 @@ pub const Type = extern union { | ... | @@ -1438,10 +1754,19 @@ pub const Type = extern union { |
| 1438 | .fn_ccc_void_no_args, | 1754 | .fn_ccc_void_no_args, |
| 1439 | .function, | 1755 | .function, |
| 1440 | .array, | 1756 | .array, |
| 1757 | .array_sentinel, | ||
| 1758 | .array_u8, | ||
| 1759 | .array_u8_sentinel_0, | ||
| 1760 | .pointer, | ||
| 1441 | .single_const_pointer, | 1761 | .single_const_pointer, |
| 1442 | .single_mut_pointer, | 1762 | .single_mut_pointer, |
| 1763 | .many_const_pointer, | ||
| 1764 | .many_mut_pointer, | ||
| 1765 | .c_const_pointer, | ||
| 1766 | .c_mut_pointer, | ||
| 1767 | .const_slice, | ||
| 1768 | .mut_slice, | ||
| 1443 | .single_const_pointer_to_comptime_int, | 1769 | .single_const_pointer_to_comptime_int, |
| 1444 | .array_u8_sentinel_0, | ||
| 1445 | .const_slice_u8, | 1770 | .const_slice_u8, |
| 1446 | .int_unsigned, | 1771 | .int_unsigned, |
| 1447 | .int_signed, | 1772 | .int_signed, |
| ... | @@ -1456,6 +1781,7 @@ pub const Type = extern union { | ... | @@ -1456,6 +1781,7 @@ pub const Type = extern union { |
| 1456 | .optional, | 1781 | .optional, |
| 1457 | .optional_single_mut_pointer, | 1782 | .optional_single_mut_pointer, |
| 1458 | .optional_single_const_pointer, | 1783 | .optional_single_const_pointer, |
| 1784 | .enum_literal, | ||
| 1459 | => false, | 1785 | => false, |
| 1460 | 1786 | ||
| 1461 | .usize, | 1787 | .usize, |
| ... | @@ -1523,10 +1849,19 @@ pub const Type = extern union { | ... | @@ -1523,10 +1849,19 @@ pub const Type = extern union { |
| 1523 | .@"null", | 1849 | .@"null", |
| 1524 | .@"undefined", | 1850 | .@"undefined", |
| 1525 | .array, | 1851 | .array, |
| 1852 | .array_sentinel, | ||
| 1853 | .array_u8, | ||
| 1854 | .array_u8_sentinel_0, | ||
| 1855 | .pointer, | ||
| 1526 | .single_const_pointer, | 1856 | .single_const_pointer, |
| 1527 | .single_mut_pointer, | 1857 | .single_mut_pointer, |
| 1858 | .many_const_pointer, | ||
| 1859 | .many_mut_pointer, | ||
| 1860 | .c_const_pointer, | ||
| 1861 | .c_mut_pointer, | ||
| 1862 | .const_slice, | ||
| 1863 | .mut_slice, | ||
| 1528 | .single_const_pointer_to_comptime_int, | 1864 | .single_const_pointer_to_comptime_int, |
| 1529 | .array_u8_sentinel_0, | ||
| 1530 | .const_slice_u8, | 1865 | .const_slice_u8, |
| 1531 | .u8, | 1866 | .u8, |
| 1532 | .i8, | 1867 | .i8, |
| ... | @@ -1551,6 +1886,7 @@ pub const Type = extern union { | ... | @@ -1551,6 +1886,7 @@ pub const Type = extern union { |
| 1551 | .optional, | 1886 | .optional, |
| 1552 | .optional_single_mut_pointer, | 1887 | .optional_single_mut_pointer, |
| 1553 | .optional_single_const_pointer, | 1888 | .optional_single_const_pointer, |
| 1889 | .enum_literal, | ||
| 1554 | => unreachable, | 1890 | => unreachable, |
| 1555 | }; | 1891 | }; |
| 1556 | } | 1892 | } |
| ... | @@ -1584,10 +1920,19 @@ pub const Type = extern union { | ... | @@ -1584,10 +1920,19 @@ pub const Type = extern union { |
| 1584 | .@"null", | 1920 | .@"null", |
| 1585 | .@"undefined", | 1921 | .@"undefined", |
| 1586 | .array, | 1922 | .array, |
| 1923 | .array_sentinel, | ||
| 1924 | .array_u8, | ||
| 1925 | .array_u8_sentinel_0, | ||
| 1926 | .pointer, | ||
| 1587 | .single_const_pointer, | 1927 | .single_const_pointer, |
| 1588 | .single_mut_pointer, | 1928 | .single_mut_pointer, |
| 1929 | .many_const_pointer, | ||
| 1930 | .many_mut_pointer, | ||
| 1931 | .c_const_pointer, | ||
| 1932 | .c_mut_pointer, | ||
| 1933 | .const_slice, | ||
| 1934 | .mut_slice, | ||
| 1589 | .single_const_pointer_to_comptime_int, | 1935 | .single_const_pointer_to_comptime_int, |
| 1590 | .array_u8_sentinel_0, | ||
| 1591 | .const_slice_u8, | 1936 | .const_slice_u8, |
| 1592 | .u8, | 1937 | .u8, |
| 1593 | .i8, | 1938 | .i8, |
| ... | @@ -1612,6 +1957,7 @@ pub const Type = extern union { | ... | @@ -1612,6 +1957,7 @@ pub const Type = extern union { |
| 1612 | .optional, | 1957 | .optional, |
| 1613 | .optional_single_mut_pointer, | 1958 | .optional_single_mut_pointer, |
| 1614 | .optional_single_const_pointer, | 1959 | .optional_single_const_pointer, |
| 1960 | .enum_literal, | ||
| 1615 | => unreachable, | 1961 | => unreachable, |
| 1616 | } | 1962 | } |
| 1617 | } | 1963 | } |
| ... | @@ -1644,10 +1990,19 @@ pub const Type = extern union { | ... | @@ -1644,10 +1990,19 @@ pub const Type = extern union { |
| 1644 | .@"null", | 1990 | .@"null", |
| 1645 | .@"undefined", | 1991 | .@"undefined", |
| 1646 | .array, | 1992 | .array, |
| 1993 | .array_sentinel, | ||
| 1994 | .array_u8, | ||
| 1995 | .array_u8_sentinel_0, | ||
| 1996 | .pointer, | ||
| 1647 | .single_const_pointer, | 1997 | .single_const_pointer, |
| 1648 | .single_mut_pointer, | 1998 | .single_mut_pointer, |
| 1999 | .many_const_pointer, | ||
| 2000 | .many_mut_pointer, | ||
| 2001 | .c_const_pointer, | ||
| 2002 | .c_mut_pointer, | ||
| 2003 | .const_slice, | ||
| 2004 | .mut_slice, | ||
| 1649 | .single_const_pointer_to_comptime_int, | 2005 | .single_const_pointer_to_comptime_int, |
| 1650 | .array_u8_sentinel_0, | ||
| 1651 | .const_slice_u8, | 2006 | .const_slice_u8, |
| 1652 | .u8, | 2007 | .u8, |
| 1653 | .i8, | 2008 | .i8, |
| ... | @@ -1672,6 +2027,7 @@ pub const Type = extern union { | ... | @@ -1672,6 +2027,7 @@ pub const Type = extern union { |
| 1672 | .optional, | 2027 | .optional, |
| 1673 | .optional_single_mut_pointer, | 2028 | .optional_single_mut_pointer, |
| 1674 | .optional_single_const_pointer, | 2029 | .optional_single_const_pointer, |
| 2030 | .enum_literal, | ||
| 1675 | => unreachable, | 2031 | => unreachable, |
| 1676 | } | 2032 | } |
| 1677 | } | 2033 | } |
| ... | @@ -1704,10 +2060,19 @@ pub const Type = extern union { | ... | @@ -1704,10 +2060,19 @@ pub const Type = extern union { |
| 1704 | .@"null", | 2060 | .@"null", |
| 1705 | .@"undefined", | 2061 | .@"undefined", |
| 1706 | .array, | 2062 | .array, |
| 2063 | .array_sentinel, | ||
| 2064 | .array_u8, | ||
| 2065 | .array_u8_sentinel_0, | ||
| 2066 | .pointer, | ||
| 1707 | .single_const_pointer, | 2067 | .single_const_pointer, |
| 1708 | .single_mut_pointer, | 2068 | .single_mut_pointer, |
| 2069 | .many_const_pointer, | ||
| 2070 | .many_mut_pointer, | ||
| 2071 | .c_const_pointer, | ||
| 2072 | .c_mut_pointer, | ||
| 2073 | .const_slice, | ||
| 2074 | .mut_slice, | ||
| 1709 | .single_const_pointer_to_comptime_int, | 2075 | .single_const_pointer_to_comptime_int, |
| 1710 | .array_u8_sentinel_0, | ||
| 1711 | .const_slice_u8, | 2076 | .const_slice_u8, |
| 1712 | .u8, | 2077 | .u8, |
| 1713 | .i8, | 2078 | .i8, |
| ... | @@ -1732,6 +2097,7 @@ pub const Type = extern union { | ... | @@ -1732,6 +2097,7 @@ pub const Type = extern union { |
| 1732 | .optional, | 2097 | .optional, |
| 1733 | .optional_single_mut_pointer, | 2098 | .optional_single_mut_pointer, |
| 1734 | .optional_single_const_pointer, | 2099 | .optional_single_const_pointer, |
| 2100 | .enum_literal, | ||
| 1735 | => unreachable, | 2101 | => unreachable, |
| 1736 | }; | 2102 | }; |
| 1737 | } | 2103 | } |
| ... | @@ -1761,10 +2127,19 @@ pub const Type = extern union { | ... | @@ -1761,10 +2127,19 @@ pub const Type = extern union { |
| 1761 | .@"null", | 2127 | .@"null", |
| 1762 | .@"undefined", | 2128 | .@"undefined", |
| 1763 | .array, | 2129 | .array, |
| 2130 | .array_sentinel, | ||
| 2131 | .array_u8, | ||
| 2132 | .array_u8_sentinel_0, | ||
| 2133 | .pointer, | ||
| 1764 | .single_const_pointer, | 2134 | .single_const_pointer, |
| 1765 | .single_mut_pointer, | 2135 | .single_mut_pointer, |
| 2136 | .many_const_pointer, | ||
| 2137 | .many_mut_pointer, | ||
| 2138 | .c_const_pointer, | ||
| 2139 | .c_mut_pointer, | ||
| 2140 | .const_slice, | ||
| 2141 | .mut_slice, | ||
| 1766 | .single_const_pointer_to_comptime_int, | 2142 | .single_const_pointer_to_comptime_int, |
| 1767 | .array_u8_sentinel_0, | ||
| 1768 | .const_slice_u8, | 2143 | .const_slice_u8, |
| 1769 | .u8, | 2144 | .u8, |
| 1770 | .i8, | 2145 | .i8, |
| ... | @@ -1789,6 +2164,7 @@ pub const Type = extern union { | ... | @@ -1789,6 +2164,7 @@ pub const Type = extern union { |
| 1789 | .optional, | 2164 | .optional, |
| 1790 | .optional_single_mut_pointer, | 2165 | .optional_single_mut_pointer, |
| 1791 | .optional_single_const_pointer, | 2166 | .optional_single_const_pointer, |
| 2167 | .enum_literal, | ||
| 1792 | => unreachable, | 2168 | => unreachable, |
| 1793 | }; | 2169 | }; |
| 1794 | } | 2170 | } |
| ... | @@ -1818,10 +2194,19 @@ pub const Type = extern union { | ... | @@ -1818,10 +2194,19 @@ pub const Type = extern union { |
| 1818 | .@"null", | 2194 | .@"null", |
| 1819 | .@"undefined", | 2195 | .@"undefined", |
| 1820 | .array, | 2196 | .array, |
| 2197 | .array_sentinel, | ||
| 2198 | .array_u8, | ||
| 2199 | .array_u8_sentinel_0, | ||
| 2200 | .pointer, | ||
| 1821 | .single_const_pointer, | 2201 | .single_const_pointer, |
| 1822 | .single_mut_pointer, | 2202 | .single_mut_pointer, |
| 2203 | .many_const_pointer, | ||
| 2204 | .many_mut_pointer, | ||
| 2205 | .c_const_pointer, | ||
| 2206 | .c_mut_pointer, | ||
| 2207 | .const_slice, | ||
| 2208 | .mut_slice, | ||
| 1823 | .single_const_pointer_to_comptime_int, | 2209 | .single_const_pointer_to_comptime_int, |
| 1824 | .array_u8_sentinel_0, | ||
| 1825 | .const_slice_u8, | 2210 | .const_slice_u8, |
| 1826 | .u8, | 2211 | .u8, |
| 1827 | .i8, | 2212 | .i8, |
| ... | @@ -1846,6 +2231,7 @@ pub const Type = extern union { | ... | @@ -1846,6 +2231,7 @@ pub const Type = extern union { |
| 1846 | .optional, | 2231 | .optional, |
| 1847 | .optional_single_mut_pointer, | 2232 | .optional_single_mut_pointer, |
| 1848 | .optional_single_const_pointer, | 2233 | .optional_single_const_pointer, |
| 2234 | .enum_literal, | ||
| 1849 | => unreachable, | 2235 | => unreachable, |
| 1850 | }; | 2236 | }; |
| 1851 | } | 2237 | } |
| ... | @@ -1895,14 +2281,24 @@ pub const Type = extern union { | ... | @@ -1895,14 +2281,24 @@ pub const Type = extern union { |
| 1895 | .fn_ccc_void_no_args, | 2281 | .fn_ccc_void_no_args, |
| 1896 | .function, | 2282 | .function, |
| 1897 | .array, | 2283 | .array, |
| 2284 | .array_sentinel, | ||
| 2285 | .array_u8, | ||
| 2286 | .array_u8_sentinel_0, | ||
| 2287 | .pointer, | ||
| 1898 | .single_const_pointer, | 2288 | .single_const_pointer, |
| 1899 | .single_mut_pointer, | 2289 | .single_mut_pointer, |
| 2290 | .many_const_pointer, | ||
| 2291 | .many_mut_pointer, | ||
| 2292 | .c_const_pointer, | ||
| 2293 | .c_mut_pointer, | ||
| 2294 | .const_slice, | ||
| 2295 | .mut_slice, | ||
| 1900 | .single_const_pointer_to_comptime_int, | 2296 | .single_const_pointer_to_comptime_int, |
| 1901 | .array_u8_sentinel_0, | ||
| 1902 | .const_slice_u8, | 2297 | .const_slice_u8, |
| 1903 | .optional, | 2298 | .optional, |
| 1904 | .optional_single_mut_pointer, | 2299 | .optional_single_mut_pointer, |
| 1905 | .optional_single_const_pointer, | 2300 | .optional_single_const_pointer, |
| 2301 | .enum_literal, | ||
| 1906 | => false, | 2302 | => false, |
| 1907 | }; | 2303 | }; |
| 1908 | } | 2304 | } |
| ... | @@ -1944,12 +2340,16 @@ pub const Type = extern union { | ... | @@ -1944,12 +2340,16 @@ pub const Type = extern union { |
| 1944 | .fn_ccc_void_no_args, | 2340 | .fn_ccc_void_no_args, |
| 1945 | .function, | 2341 | .function, |
| 1946 | .single_const_pointer_to_comptime_int, | 2342 | .single_const_pointer_to_comptime_int, |
| 2343 | .array_sentinel, | ||
| 1947 | .array_u8_sentinel_0, | 2344 | .array_u8_sentinel_0, |
| 1948 | .const_slice_u8, | 2345 | .const_slice_u8, |
| 2346 | .const_slice, | ||
| 2347 | .mut_slice, | ||
| 1949 | .c_void, | 2348 | .c_void, |
| 1950 | .optional, | 2349 | .optional, |
| 1951 | .optional_single_mut_pointer, | 2350 | .optional_single_mut_pointer, |
| 1952 | .optional_single_const_pointer, | 2351 | .optional_single_const_pointer, |
| 2352 | .enum_literal, | ||
| 1953 | => return null, | 2353 | => return null, |
| 1954 | 2354 | ||
| 1955 | .void => return Value.initTag(.void_value), | 2355 | .void => return Value.initTag(.void_value), |
| ... | @@ -1971,18 +2371,27 @@ pub const Type = extern union { | ... | @@ -1971,18 +2371,27 @@ pub const Type = extern union { |
| 1971 | return null; | 2371 | return null; |
| 1972 | } | 2372 | } |
| 1973 | }, | 2373 | }, |
| 1974 | .array => { | 2374 | .array, .array_u8 => { |
| 1975 | const array = ty.cast(Payload.Array).?; | 2375 | if (ty.arrayLen() == 0) |
| 1976 | if (array.len == 0) | ||
| 1977 | return Value.initTag(.empty_array); | 2376 | return Value.initTag(.empty_array); |
| 1978 | ty = array.elem_type; | 2377 | ty = ty.elemType(); |
| 1979 | continue; | 2378 | continue; |
| 1980 | }, | 2379 | }, |
| 1981 | .single_const_pointer, .single_mut_pointer => { | 2380 | .many_const_pointer, |
| 2381 | .many_mut_pointer, | ||
| 2382 | .c_const_pointer, | ||
| 2383 | .c_mut_pointer, | ||
| 2384 | .single_const_pointer, | ||
| 2385 | .single_mut_pointer, | ||
| 2386 | => { | ||
| 1982 | const ptr = ty.castPointer().?; | 2387 | const ptr = ty.castPointer().?; |
| 1983 | ty = ptr.pointee_type; | 2388 | ty = ptr.pointee_type; |
| 1984 | continue; | 2389 | continue; |
| 1985 | }, | 2390 | }, |
| 2391 | .pointer => { | ||
| 2392 | ty = ty.cast(Payload.Pointer).?.pointee_type; | ||
| 2393 | continue; | ||
| 2394 | }, | ||
| 1986 | }; | 2395 | }; |
| 1987 | } | 2396 | } |
| 1988 | 2397 | ||
| ... | @@ -2022,7 +2431,6 @@ pub const Type = extern union { | ... | @@ -2022,7 +2431,6 @@ pub const Type = extern union { |
| 2022 | .fn_ccc_void_no_args, | 2431 | .fn_ccc_void_no_args, |
| 2023 | .function, | 2432 | .function, |
| 2024 | .single_const_pointer_to_comptime_int, | 2433 | .single_const_pointer_to_comptime_int, |
| 2025 | .array_u8_sentinel_0, | ||
| 2026 | .const_slice_u8, | 2434 | .const_slice_u8, |
| 2027 | .c_void, | 2435 | .c_void, |
| 2028 | .void, | 2436 | .void, |
| ... | @@ -2032,12 +2440,26 @@ pub const Type = extern union { | ... | @@ -2032,12 +2440,26 @@ pub const Type = extern union { |
| 2032 | .int_unsigned, | 2440 | .int_unsigned, |
| 2033 | .int_signed, | 2441 | .int_signed, |
| 2034 | .array, | 2442 | .array, |
| 2443 | .array_sentinel, | ||
| 2444 | .array_u8, | ||
| 2445 | .array_u8_sentinel_0, | ||
| 2035 | .single_const_pointer, | 2446 | .single_const_pointer, |
| 2036 | .single_mut_pointer, | 2447 | .single_mut_pointer, |
| 2448 | .many_const_pointer, | ||
| 2449 | .many_mut_pointer, | ||
| 2450 | .const_slice, | ||
| 2451 | .mut_slice, | ||
| 2037 | .optional, | 2452 | .optional, |
| 2038 | .optional_single_mut_pointer, | 2453 | .optional_single_mut_pointer, |
| 2039 | .optional_single_const_pointer, | 2454 | .optional_single_const_pointer, |
| 2455 | .enum_literal, | ||
| 2040 | => return false, | 2456 | => return false, |
| 2457 | |||
| 2458 | .c_const_pointer, | ||
| 2459 | .c_mut_pointer, | ||
| 2460 | => return true, | ||
| 2461 | |||
| 2462 | .pointer => self.cast(Payload.Pointer).?.size == .C, | ||
| 2041 | }; | 2463 | }; |
| 2042 | } | 2464 | } |
| 2043 | 2465 | ||
| ... | @@ -2080,6 +2502,7 @@ pub const Type = extern union { | ... | @@ -2080,6 +2502,7 @@ pub const Type = extern union { |
| 2080 | comptime_int, | 2502 | comptime_int, |
| 2081 | comptime_float, | 2503 | comptime_float, |
| 2082 | noreturn, | 2504 | noreturn, |
| 2505 | enum_literal, | ||
| 2083 | @"null", | 2506 | @"null", |
| 2084 | @"undefined", | 2507 | @"undefined", |
| 2085 | fn_noreturn_no_args, | 2508 | fn_noreturn_no_args, |
| ... | @@ -2090,10 +2513,19 @@ pub const Type = extern union { | ... | @@ -2090,10 +2513,19 @@ pub const Type = extern union { |
| 2090 | const_slice_u8, // See last_no_payload_tag below. | 2513 | const_slice_u8, // See last_no_payload_tag below. |
| 2091 | // After this, the tag requires a payload. | 2514 | // After this, the tag requires a payload. |
| 2092 | 2515 | ||
| 2516 | array_u8, | ||
| 2093 | array_u8_sentinel_0, | 2517 | array_u8_sentinel_0, |
| 2094 | array, | 2518 | array, |
| 2519 | array_sentinel, | ||
| 2520 | pointer, | ||
| 2095 | single_const_pointer, | 2521 | single_const_pointer, |
| 2096 | single_mut_pointer, | 2522 | single_mut_pointer, |
| 2523 | many_const_pointer, | ||
| 2524 | many_mut_pointer, | ||
| 2525 | c_const_pointer, | ||
| 2526 | c_mut_pointer, | ||
| 2527 | const_slice, | ||
| 2528 | mut_slice, | ||
| 2097 | int_signed, | 2529 | int_signed, |
| 2098 | int_unsigned, | 2530 | int_unsigned, |
| 2099 | function, | 2531 | function, |
| ... | @@ -2114,14 +2546,28 @@ pub const Type = extern union { | ... | @@ -2114,14 +2546,28 @@ pub const Type = extern union { |
| 2114 | len: u64, | 2546 | len: u64, |
| 2115 | }; | 2547 | }; |
| 2116 | 2548 | ||
| 2549 | pub const Array_u8 = struct { | ||
| 2550 | base: Payload = Payload{ .tag = .array_u8 }, | ||
| 2551 | |||
| 2552 | len: u64, | ||
| 2553 | }; | ||
| 2554 | |||
| 2117 | pub const Array = struct { | 2555 | pub const Array = struct { |
| 2118 | base: Payload = Payload{ .tag = .array }, | 2556 | base: Payload = Payload{ .tag = .array }, |
| 2119 | 2557 | ||
| 2558 | len: u64, | ||
| 2120 | elem_type: Type, | 2559 | elem_type: Type, |
| 2560 | }; | ||
| 2561 | |||
| 2562 | pub const ArraySentinel = struct { | ||
| 2563 | base: Payload = Payload{ .tag = .array_sentinel }, | ||
| 2564 | |||
| 2121 | len: u64, | 2565 | len: u64, |
| 2566 | sentinel: Value, | ||
| 2567 | elem_type: Type, | ||
| 2122 | }; | 2568 | }; |
| 2123 | 2569 | ||
| 2124 | pub const Pointer = struct { | 2570 | pub const PointerSimple = struct { |
| 2125 | base: Payload, | 2571 | base: Payload, |
| 2126 | 2572 | ||
| 2127 | pointee_type: Type, | 2573 | pointee_type: Type, |
| ... | @@ -2152,6 +2598,21 @@ pub const Type = extern union { | ... | @@ -2152,6 +2598,21 @@ pub const Type = extern union { |
| 2152 | 2598 | ||
| 2153 | child_type: Type, | 2599 | child_type: Type, |
| 2154 | }; | 2600 | }; |
| 2601 | |||
| 2602 | pub const Pointer = struct { | ||
| 2603 | base: Payload = .{ .tag = .pointer }, | ||
| 2604 | |||
| 2605 | pointee_type: Type, | ||
| 2606 | sentinel: ?Value, | ||
| 2607 | /// If zero use pointee_type.AbiAlign() | ||
| 2608 | @"align": u32, | ||
| 2609 | bit_offset: u16, | ||
| 2610 | host_size: u16, | ||
| 2611 | @"allowzero": bool, | ||
| 2612 | mutable: bool, | ||
| 2613 | @"volatile": bool, | ||
| 2614 | size: std.builtin.TypeInfo.Pointer.Size, | ||
| 2615 | }; | ||
| 2155 | }; | 2616 | }; |
| 2156 | }; | 2617 | }; |
| 2157 | 2618 |
src-self-hosted/value.zig+60-1| ... | @@ -60,6 +60,7 @@ pub const Value = extern union { | ... | @@ -60,6 +60,7 @@ pub const Value = extern union { |
| 60 | fn_ccc_void_no_args_type, | 60 | fn_ccc_void_no_args_type, |
| 61 | single_const_pointer_to_comptime_int_type, | 61 | single_const_pointer_to_comptime_int_type, |
| 62 | const_slice_u8_type, | 62 | const_slice_u8_type, |
| 63 | enum_literal_type, | ||
| 63 | 64 | ||
| 64 | undef, | 65 | undef, |
| 65 | zero, | 66 | zero, |
| ... | @@ -78,6 +79,7 @@ pub const Value = extern union { | ... | @@ -78,6 +79,7 @@ pub const Value = extern union { |
| 78 | int_big_positive, | 79 | int_big_positive, |
| 79 | int_big_negative, | 80 | int_big_negative, |
| 80 | function, | 81 | function, |
| 82 | variable, | ||
| 81 | ref_val, | 83 | ref_val, |
| 82 | decl_ref, | 84 | decl_ref, |
| 83 | elem_ptr, | 85 | elem_ptr, |
| ... | @@ -87,6 +89,7 @@ pub const Value = extern union { | ... | @@ -87,6 +89,7 @@ pub const Value = extern union { |
| 87 | float_32, | 89 | float_32, |
| 88 | float_64, | 90 | float_64, |
| 89 | float_128, | 91 | float_128, |
| 92 | enum_literal, | ||
| 90 | 93 | ||
| 91 | pub const last_no_payload_tag = Tag.bool_false; | 94 | pub const last_no_payload_tag = Tag.bool_false; |
| 92 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 95 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | @@ -164,6 +167,7 @@ pub const Value = extern union { | ... | @@ -164,6 +167,7 @@ pub const Value = extern union { |
| 164 | .fn_ccc_void_no_args_type, | 167 | .fn_ccc_void_no_args_type, |
| 165 | .single_const_pointer_to_comptime_int_type, | 168 | .single_const_pointer_to_comptime_int_type, |
| 166 | .const_slice_u8_type, | 169 | .const_slice_u8_type, |
| 170 | .enum_literal_type, | ||
| 167 | .undef, | 171 | .undef, |
| 168 | .zero, | 172 | .zero, |
| 169 | .void_value, | 173 | .void_value, |
| ... | @@ -193,6 +197,7 @@ pub const Value = extern union { | ... | @@ -193,6 +197,7 @@ pub const Value = extern union { |
| 193 | @panic("TODO implement copying of big ints"); | 197 | @panic("TODO implement copying of big ints"); |
| 194 | }, | 198 | }, |
| 195 | .function => return self.copyPayloadShallow(allocator, Payload.Function), | 199 | .function => return self.copyPayloadShallow(allocator, Payload.Function), |
| 200 | .variable => return self.copyPayloadShallow(allocator, Payload.Variable), | ||
| 196 | .ref_val => { | 201 | .ref_val => { |
| 197 | const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise); | 202 | const payload = @fieldParentPtr(Payload.RefVal, "base", self.ptr_otherwise); |
| 198 | const new_payload = try allocator.create(Payload.RefVal); | 203 | const new_payload = try allocator.create(Payload.RefVal); |
| ... | @@ -227,6 +232,15 @@ pub const Value = extern union { | ... | @@ -227,6 +232,15 @@ pub const Value = extern union { |
| 227 | .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32), | 232 | .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32), |
| 228 | .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64), | 233 | .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64), |
| 229 | .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128), | 234 | .float_128 => return self.copyPayloadShallow(allocator, Payload.Float_128), |
| 235 | .enum_literal => { | ||
| 236 | const payload = @fieldParentPtr(Payload.Bytes, "base", self.ptr_otherwise); | ||
| 237 | const new_payload = try allocator.create(Payload.Bytes); | ||
| 238 | new_payload.* = .{ | ||
| 239 | .base = payload.base, | ||
| 240 | .data = try allocator.dupe(u8, payload.data), | ||
| 241 | }; | ||
| 242 | return Value{ .ptr_otherwise = &new_payload.base }; | ||
| 243 | }, | ||
| 230 | } | 244 | } |
| 231 | } | 245 | } |
| 232 | 246 | ||
| ... | @@ -285,6 +299,7 @@ pub const Value = extern union { | ... | @@ -285,6 +299,7 @@ pub const Value = extern union { |
| 285 | .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"), | 299 | .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"), |
| 286 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), | 300 | .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), |
| 287 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), | 301 | .const_slice_u8_type => return out_stream.writeAll("[]const u8"), |
| 302 | .enum_literal_type => return out_stream.writeAll("@TypeOf(.EnumLiteral)"), | ||
| 288 | 303 | ||
| 289 | .null_value => return out_stream.writeAll("null"), | 304 | .null_value => return out_stream.writeAll("null"), |
| 290 | .undef => return out_stream.writeAll("undefined"), | 305 | .undef => return out_stream.writeAll("undefined"), |
| ... | @@ -306,6 +321,7 @@ pub const Value = extern union { | ... | @@ -306,6 +321,7 @@ pub const Value = extern union { |
| 306 | .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}), | 321 | .int_big_positive => return out_stream.print("{}", .{val.cast(Payload.IntBigPositive).?.asBigInt()}), |
| 307 | .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}), | 322 | .int_big_negative => return out_stream.print("{}", .{val.cast(Payload.IntBigNegative).?.asBigInt()}), |
| 308 | .function => return out_stream.writeAll("(function)"), | 323 | .function => return out_stream.writeAll("(function)"), |
| 324 | .variable => return out_stream.writeAll("(variable)"), | ||
| 309 | .ref_val => { | 325 | .ref_val => { |
| 310 | const ref_val = val.cast(Payload.RefVal).?; | 326 | const ref_val = val.cast(Payload.RefVal).?; |
| 311 | try out_stream.writeAll("&const "); | 327 | try out_stream.writeAll("&const "); |
| ... | @@ -318,7 +334,7 @@ pub const Value = extern union { | ... | @@ -318,7 +334,7 @@ pub const Value = extern union { |
| 318 | val = elem_ptr.array_ptr; | 334 | val = elem_ptr.array_ptr; |
| 319 | }, | 335 | }, |
| 320 | .empty_array => return out_stream.writeAll(".{}"), | 336 | .empty_array => return out_stream.writeAll(".{}"), |
| 321 | .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream), | 337 | .enum_literal, .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream), |
| 322 | .repeated => { | 338 | .repeated => { |
| 323 | try out_stream.writeAll("(repeated) "); | 339 | try out_stream.writeAll("(repeated) "); |
| 324 | val = val.cast(Payload.Repeated).?.val; | 340 | val = val.cast(Payload.Repeated).?.val; |
| ... | @@ -391,6 +407,7 @@ pub const Value = extern union { | ... | @@ -391,6 +407,7 @@ pub const Value = extern union { |
| 391 | .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args), | 407 | .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args), |
| 392 | .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), | 408 | .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), |
| 393 | .const_slice_u8_type => Type.initTag(.const_slice_u8), | 409 | .const_slice_u8_type => Type.initTag(.const_slice_u8), |
| 410 | .enum_literal_type => Type.initTag(.enum_literal), | ||
| 394 | 411 | ||
| 395 | .undef, | 412 | .undef, |
| 396 | .zero, | 413 | .zero, |
| ... | @@ -405,6 +422,7 @@ pub const Value = extern union { | ... | @@ -405,6 +422,7 @@ pub const Value = extern union { |
| 405 | .int_big_positive, | 422 | .int_big_positive, |
| 406 | .int_big_negative, | 423 | .int_big_negative, |
| 407 | .function, | 424 | .function, |
| 425 | .variable, | ||
| 408 | .ref_val, | 426 | .ref_val, |
| 409 | .decl_ref, | 427 | .decl_ref, |
| 410 | .elem_ptr, | 428 | .elem_ptr, |
| ... | @@ -414,6 +432,7 @@ pub const Value = extern union { | ... | @@ -414,6 +432,7 @@ pub const Value = extern union { |
| 414 | .float_32, | 432 | .float_32, |
| 415 | .float_64, | 433 | .float_64, |
| 416 | .float_128, | 434 | .float_128, |
| 435 | .enum_literal, | ||
| 417 | => unreachable, | 436 | => unreachable, |
| 418 | }; | 437 | }; |
| 419 | } | 438 | } |
| ... | @@ -462,8 +481,10 @@ pub const Value = extern union { | ... | @@ -462,8 +481,10 @@ pub const Value = extern union { |
| 462 | .fn_ccc_void_no_args_type, | 481 | .fn_ccc_void_no_args_type, |
| 463 | .single_const_pointer_to_comptime_int_type, | 482 | .single_const_pointer_to_comptime_int_type, |
| 464 | .const_slice_u8_type, | 483 | .const_slice_u8_type, |
| 484 | .enum_literal_type, | ||
| 465 | .null_value, | 485 | .null_value, |
| 466 | .function, | 486 | .function, |
| 487 | .variable, | ||
| 467 | .ref_val, | 488 | .ref_val, |
| 468 | .decl_ref, | 489 | .decl_ref, |
| 469 | .elem_ptr, | 490 | .elem_ptr, |
| ... | @@ -476,6 +497,7 @@ pub const Value = extern union { | ... | @@ -476,6 +497,7 @@ pub const Value = extern union { |
| 476 | .void_value, | 497 | .void_value, |
| 477 | .unreachable_value, | 498 | .unreachable_value, |
| 478 | .empty_array, | 499 | .empty_array, |
| 500 | .enum_literal, | ||
| 479 | => unreachable, | 501 | => unreachable, |
| 480 | 502 | ||
| 481 | .undef => unreachable, | 503 | .undef => unreachable, |
| ... | @@ -537,8 +559,10 @@ pub const Value = extern union { | ... | @@ -537,8 +559,10 @@ pub const Value = extern union { |
| 537 | .fn_ccc_void_no_args_type, | 559 | .fn_ccc_void_no_args_type, |
| 538 | .single_const_pointer_to_comptime_int_type, | 560 | .single_const_pointer_to_comptime_int_type, |
| 539 | .const_slice_u8_type, | 561 | .const_slice_u8_type, |
| 562 | .enum_literal_type, | ||
| 540 | .null_value, | 563 | .null_value, |
| 541 | .function, | 564 | .function, |
| 565 | .variable, | ||
| 542 | .ref_val, | 566 | .ref_val, |
| 543 | .decl_ref, | 567 | .decl_ref, |
| 544 | .elem_ptr, | 568 | .elem_ptr, |
| ... | @@ -551,6 +575,7 @@ pub const Value = extern union { | ... | @@ -551,6 +575,7 @@ pub const Value = extern union { |
| 551 | .void_value, | 575 | .void_value, |
| 552 | .unreachable_value, | 576 | .unreachable_value, |
| 553 | .empty_array, | 577 | .empty_array, |
| 578 | .enum_literal, | ||
| 554 | => unreachable, | 579 | => unreachable, |
| 555 | 580 | ||
| 556 | .undef => unreachable, | 581 | .undef => unreachable, |
| ... | @@ -612,8 +637,10 @@ pub const Value = extern union { | ... | @@ -612,8 +637,10 @@ pub const Value = extern union { |
| 612 | .fn_ccc_void_no_args_type, | 637 | .fn_ccc_void_no_args_type, |
| 613 | .single_const_pointer_to_comptime_int_type, | 638 | .single_const_pointer_to_comptime_int_type, |
| 614 | .const_slice_u8_type, | 639 | .const_slice_u8_type, |
| 640 | .enum_literal_type, | ||
| 615 | .null_value, | 641 | .null_value, |
| 616 | .function, | 642 | .function, |
| 643 | .variable, | ||
| 617 | .ref_val, | 644 | .ref_val, |
| 618 | .decl_ref, | 645 | .decl_ref, |
| 619 | .elem_ptr, | 646 | .elem_ptr, |
| ... | @@ -626,6 +653,7 @@ pub const Value = extern union { | ... | @@ -626,6 +653,7 @@ pub const Value = extern union { |
| 626 | .void_value, | 653 | .void_value, |
| 627 | .unreachable_value, | 654 | .unreachable_value, |
| 628 | .empty_array, | 655 | .empty_array, |
| 656 | .enum_literal, | ||
| 629 | => unreachable, | 657 | => unreachable, |
| 630 | 658 | ||
| 631 | .undef => unreachable, | 659 | .undef => unreachable, |
| ... | @@ -713,8 +741,10 @@ pub const Value = extern union { | ... | @@ -713,8 +741,10 @@ pub const Value = extern union { |
| 713 | .fn_ccc_void_no_args_type, | 741 | .fn_ccc_void_no_args_type, |
| 714 | .single_const_pointer_to_comptime_int_type, | 742 | .single_const_pointer_to_comptime_int_type, |
| 715 | .const_slice_u8_type, | 743 | .const_slice_u8_type, |
| 744 | .enum_literal_type, | ||
| 716 | .null_value, | 745 | .null_value, |
| 717 | .function, | 746 | .function, |
| 747 | .variable, | ||
| 718 | .ref_val, | 748 | .ref_val, |
| 719 | .decl_ref, | 749 | .decl_ref, |
| 720 | .elem_ptr, | 750 | .elem_ptr, |
| ... | @@ -728,6 +758,7 @@ pub const Value = extern union { | ... | @@ -728,6 +758,7 @@ pub const Value = extern union { |
| 728 | .void_value, | 758 | .void_value, |
| 729 | .unreachable_value, | 759 | .unreachable_value, |
| 730 | .empty_array, | 760 | .empty_array, |
| 761 | .enum_literal, | ||
| 731 | => unreachable, | 762 | => unreachable, |
| 732 | 763 | ||
| 733 | .zero, | 764 | .zero, |
| ... | @@ -793,8 +824,10 @@ pub const Value = extern union { | ... | @@ -793,8 +824,10 @@ pub const Value = extern union { |
| 793 | .fn_ccc_void_no_args_type, | 824 | .fn_ccc_void_no_args_type, |
| 794 | .single_const_pointer_to_comptime_int_type, | 825 | .single_const_pointer_to_comptime_int_type, |
| 795 | .const_slice_u8_type, | 826 | .const_slice_u8_type, |
| 827 | .enum_literal_type, | ||
| 796 | .null_value, | 828 | .null_value, |
| 797 | .function, | 829 | .function, |
| 830 | .variable, | ||
| 798 | .ref_val, | 831 | .ref_val, |
| 799 | .decl_ref, | 832 | .decl_ref, |
| 800 | .elem_ptr, | 833 | .elem_ptr, |
| ... | @@ -807,6 +840,7 @@ pub const Value = extern union { | ... | @@ -807,6 +840,7 @@ pub const Value = extern union { |
| 807 | .void_value, | 840 | .void_value, |
| 808 | .unreachable_value, | 841 | .unreachable_value, |
| 809 | .empty_array, | 842 | .empty_array, |
| 843 | .enum_literal, | ||
| 810 | => unreachable, | 844 | => unreachable, |
| 811 | 845 | ||
| 812 | .zero, | 846 | .zero, |
| ... | @@ -953,10 +987,12 @@ pub const Value = extern union { | ... | @@ -953,10 +987,12 @@ pub const Value = extern union { |
| 953 | .fn_ccc_void_no_args_type, | 987 | .fn_ccc_void_no_args_type, |
| 954 | .single_const_pointer_to_comptime_int_type, | 988 | .single_const_pointer_to_comptime_int_type, |
| 955 | .const_slice_u8_type, | 989 | .const_slice_u8_type, |
| 990 | .enum_literal_type, | ||
| 956 | .bool_true, | 991 | .bool_true, |
| 957 | .bool_false, | 992 | .bool_false, |
| 958 | .null_value, | 993 | .null_value, |
| 959 | .function, | 994 | .function, |
| 995 | .variable, | ||
| 960 | .ref_val, | 996 | .ref_val, |
| 961 | .decl_ref, | 997 | .decl_ref, |
| 962 | .elem_ptr, | 998 | .elem_ptr, |
| ... | @@ -970,6 +1006,7 @@ pub const Value = extern union { | ... | @@ -970,6 +1006,7 @@ pub const Value = extern union { |
| 970 | .empty_array, | 1006 | .empty_array, |
| 971 | .void_value, | 1007 | .void_value, |
| 972 | .unreachable_value, | 1008 | .unreachable_value, |
| 1009 | .enum_literal, | ||
| 973 | => unreachable, | 1010 | => unreachable, |
| 974 | 1011 | ||
| 975 | .zero => false, | 1012 | .zero => false, |
| ... | @@ -1025,8 +1062,10 @@ pub const Value = extern union { | ... | @@ -1025,8 +1062,10 @@ pub const Value = extern union { |
| 1025 | .fn_ccc_void_no_args_type, | 1062 | .fn_ccc_void_no_args_type, |
| 1026 | .single_const_pointer_to_comptime_int_type, | 1063 | .single_const_pointer_to_comptime_int_type, |
| 1027 | .const_slice_u8_type, | 1064 | .const_slice_u8_type, |
| 1065 | .enum_literal_type, | ||
| 1028 | .null_value, | 1066 | .null_value, |
| 1029 | .function, | 1067 | .function, |
| 1068 | .variable, | ||
| 1030 | .ref_val, | 1069 | .ref_val, |
| 1031 | .decl_ref, | 1070 | .decl_ref, |
| 1032 | .elem_ptr, | 1071 | .elem_ptr, |
| ... | @@ -1036,6 +1075,7 @@ pub const Value = extern union { | ... | @@ -1036,6 +1075,7 @@ pub const Value = extern union { |
| 1036 | .void_value, | 1075 | .void_value, |
| 1037 | .unreachable_value, | 1076 | .unreachable_value, |
| 1038 | .empty_array, | 1077 | .empty_array, |
| 1078 | .enum_literal, | ||
| 1039 | => unreachable, | 1079 | => unreachable, |
| 1040 | 1080 | ||
| 1041 | .zero, | 1081 | .zero, |
| ... | @@ -1102,6 +1142,11 @@ pub const Value = extern union { | ... | @@ -1102,6 +1142,11 @@ pub const Value = extern union { |
| 1102 | } | 1142 | } |
| 1103 | 1143 | ||
| 1104 | pub fn eql(a: Value, b: Value) bool { | 1144 | pub fn eql(a: Value, b: Value) bool { |
| 1145 | if (a.tag() == b.tag() and a.tag() == .enum_literal) { | ||
| 1146 | const a_name = @fieldParentPtr(Payload.Bytes, "base", a.ptr_otherwise).data; | ||
| 1147 | const b_name = @fieldParentPtr(Payload.Bytes, "base", b.ptr_otherwise).data; | ||
| 1148 | return std.mem.eql(u8, a_name, b_name); | ||
| 1149 | } | ||
| 1105 | // TODO non numerical comparisons | 1150 | // TODO non numerical comparisons |
| 1106 | return compare(a, .eq, b); | 1151 | return compare(a, .eq, b); |
| 1107 | } | 1152 | } |
| ... | @@ -1151,11 +1196,13 @@ pub const Value = extern union { | ... | @@ -1151,11 +1196,13 @@ pub const Value = extern union { |
| 1151 | .fn_ccc_void_no_args_type, | 1196 | .fn_ccc_void_no_args_type, |
| 1152 | .single_const_pointer_to_comptime_int_type, | 1197 | .single_const_pointer_to_comptime_int_type, |
| 1153 | .const_slice_u8_type, | 1198 | .const_slice_u8_type, |
| 1199 | .enum_literal_type, | ||
| 1154 | .zero, | 1200 | .zero, |
| 1155 | .bool_true, | 1201 | .bool_true, |
| 1156 | .bool_false, | 1202 | .bool_false, |
| 1157 | .null_value, | 1203 | .null_value, |
| 1158 | .function, | 1204 | .function, |
| 1205 | .variable, | ||
| 1159 | .int_u64, | 1206 | .int_u64, |
| 1160 | .int_i64, | 1207 | .int_i64, |
| 1161 | .int_big_positive, | 1208 | .int_big_positive, |
| ... | @@ -1170,6 +1217,7 @@ pub const Value = extern union { | ... | @@ -1170,6 +1217,7 @@ pub const Value = extern union { |
| 1170 | .void_value, | 1217 | .void_value, |
| 1171 | .unreachable_value, | 1218 | .unreachable_value, |
| 1172 | .empty_array, | 1219 | .empty_array, |
| 1220 | .enum_literal, | ||
| 1173 | => unreachable, | 1221 | => unreachable, |
| 1174 | 1222 | ||
| 1175 | .ref_val => self.cast(Payload.RefVal).?.val, | 1223 | .ref_val => self.cast(Payload.RefVal).?.val, |
| ... | @@ -1227,11 +1275,13 @@ pub const Value = extern union { | ... | @@ -1227,11 +1275,13 @@ pub const Value = extern union { |
| 1227 | .fn_ccc_void_no_args_type, | 1275 | .fn_ccc_void_no_args_type, |
| 1228 | .single_const_pointer_to_comptime_int_type, | 1276 | .single_const_pointer_to_comptime_int_type, |
| 1229 | .const_slice_u8_type, | 1277 | .const_slice_u8_type, |
| 1278 | .enum_literal_type, | ||
| 1230 | .zero, | 1279 | .zero, |
| 1231 | .bool_true, | 1280 | .bool_true, |
| 1232 | .bool_false, | 1281 | .bool_false, |
| 1233 | .null_value, | 1282 | .null_value, |
| 1234 | .function, | 1283 | .function, |
| 1284 | .variable, | ||
| 1235 | .int_u64, | 1285 | .int_u64, |
| 1236 | .int_i64, | 1286 | .int_i64, |
| 1237 | .int_big_positive, | 1287 | .int_big_positive, |
| ... | @@ -1246,6 +1296,7 @@ pub const Value = extern union { | ... | @@ -1246,6 +1296,7 @@ pub const Value = extern union { |
| 1246 | .float_128, | 1296 | .float_128, |
| 1247 | .void_value, | 1297 | .void_value, |
| 1248 | .unreachable_value, | 1298 | .unreachable_value, |
| 1299 | .enum_literal, | ||
| 1249 | => unreachable, | 1300 | => unreachable, |
| 1250 | 1301 | ||
| 1251 | .empty_array => unreachable, // out of bounds array index | 1302 | .empty_array => unreachable, // out of bounds array index |
| ... | @@ -1320,11 +1371,13 @@ pub const Value = extern union { | ... | @@ -1320,11 +1371,13 @@ pub const Value = extern union { |
| 1320 | .fn_ccc_void_no_args_type, | 1371 | .fn_ccc_void_no_args_type, |
| 1321 | .single_const_pointer_to_comptime_int_type, | 1372 | .single_const_pointer_to_comptime_int_type, |
| 1322 | .const_slice_u8_type, | 1373 | .const_slice_u8_type, |
| 1374 | .enum_literal_type, | ||
| 1323 | .zero, | 1375 | .zero, |
| 1324 | .empty_array, | 1376 | .empty_array, |
| 1325 | .bool_true, | 1377 | .bool_true, |
| 1326 | .bool_false, | 1378 | .bool_false, |
| 1327 | .function, | 1379 | .function, |
| 1380 | .variable, | ||
| 1328 | .int_u64, | 1381 | .int_u64, |
| 1329 | .int_i64, | 1382 | .int_i64, |
| 1330 | .int_big_positive, | 1383 | .int_big_positive, |
| ... | @@ -1339,6 +1392,7 @@ pub const Value = extern union { | ... | @@ -1339,6 +1392,7 @@ pub const Value = extern union { |
| 1339 | .float_64, | 1392 | .float_64, |
| 1340 | .float_128, | 1393 | .float_128, |
| 1341 | .void_value, | 1394 | .void_value, |
| 1395 | .enum_literal, | ||
| 1342 | => false, | 1396 | => false, |
| 1343 | 1397 | ||
| 1344 | .undef => unreachable, | 1398 | .undef => unreachable, |
| ... | @@ -1398,6 +1452,11 @@ pub const Value = extern union { | ... | @@ -1398,6 +1452,11 @@ pub const Value = extern union { |
| 1398 | func: *Module.Fn, | 1452 | func: *Module.Fn, |
| 1399 | }; | 1453 | }; |
| 1400 | 1454 | ||
| 1455 | pub const Variable = struct { | ||
| 1456 | base: Payload = Payload{ .tag = .variable }, | ||
| 1457 | variable: *Module.Var, | ||
| 1458 | }; | ||
| 1459 | |||
| 1401 | pub const ArraySentinel0_u8_Type = struct { | 1460 | pub const ArraySentinel0_u8_Type = struct { |
| 1402 | base: Payload = Payload{ .tag = .array_sentinel_0_u8_type }, | 1461 | base: Payload = Payload{ .tag = .array_sentinel_0_u8_type }, |
| 1403 | len: u64, | 1462 | len: u64, |
src-self-hosted/zir.zig+146-9| ... | @@ -47,6 +47,10 @@ pub const Inst = struct { | ... | @@ -47,6 +47,10 @@ pub const Inst = struct { |
| 47 | array_cat, | 47 | array_cat, |
| 48 | /// Array multiplication `a ** b` | 48 | /// Array multiplication `a ** b` |
| 49 | array_mul, | 49 | array_mul, |
| 50 | /// Create an array type | ||
| 51 | array_type, | ||
| 52 | /// Create an array type with sentinel | ||
| 53 | array_type_sentinel, | ||
| 50 | /// Function parameter value. These must be first in a function's main block, | 54 | /// Function parameter value. These must be first in a function's main block, |
| 51 | /// in respective order with the parameters. | 55 | /// in respective order with the parameters. |
| 52 | arg, | 56 | arg, |
| ... | @@ -58,11 +62,11 @@ pub const Inst = struct { | ... | @@ -58,11 +62,11 @@ pub const Inst = struct { |
| 58 | bitand, | 62 | bitand, |
| 59 | /// TODO delete this instruction, it has no purpose. | 63 | /// TODO delete this instruction, it has no purpose. |
| 60 | bitcast, | 64 | bitcast, |
| 61 | /// An arbitrary typed pointer, which is to be used as an L-Value, is pointer-casted | 65 | /// An arbitrary typed pointer is pointer-casted to a new Pointer. |
| 62 | /// to a new L-Value. The destination type is given by LHS. The cast is to be evaluated | 66 | /// The destination type is given by LHS. The cast is to be evaluated |
| 63 | /// as if it were a bit-cast operation from the operand pointer element type to the | 67 | /// as if it were a bit-cast operation from the operand pointer element type to the |
| 64 | /// provided destination type. | 68 | /// provided destination type. |
| 65 | bitcast_lvalue, | 69 | bitcast_ref, |
| 66 | /// A typed result location pointer is bitcasted to a new result location pointer. | 70 | /// A typed result location pointer is bitcasted to a new result location pointer. |
| 67 | /// The new result location pointer has an inferred type. | 71 | /// The new result location pointer has an inferred type. |
| 68 | bitcast_result_ptr, | 72 | bitcast_result_ptr, |
| ... | @@ -190,10 +194,22 @@ pub const Inst = struct { | ... | @@ -190,10 +194,22 @@ pub const Inst = struct { |
| 190 | shl, | 194 | shl, |
| 191 | /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type. | 195 | /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type. |
| 192 | shr, | 196 | shr, |
| 193 | /// Create a const pointer type based on the element type. `*const T` | 197 | /// Create a const pointer type with element type T. `*const T` |
| 194 | single_const_ptr_type, | 198 | single_const_ptr_type, |
| 195 | /// Create a mutable pointer type based on the element type. `*T` | 199 | /// Create a mutable pointer type with element type T. `*T` |
| 196 | single_mut_ptr_type, | 200 | single_mut_ptr_type, |
| 201 | /// Create a const pointer type with element type T. `[*]const T` | ||
| 202 | many_const_ptr_type, | ||
| 203 | /// Create a mutable pointer type with element type T. `[*]T` | ||
| 204 | many_mut_ptr_type, | ||
| 205 | /// Create a const pointer type with element type T. `[*c]const T` | ||
| 206 | c_const_ptr_type, | ||
| 207 | /// Create a mutable pointer type with element type T. `[*c]T` | ||
| 208 | c_mut_ptr_type, | ||
| 209 | /// Create a mutable slice type with element type T. `[]T` | ||
| 210 | mut_slice_type, | ||
| 211 | /// Create a const slice type with element type T. `[]T` | ||
| 212 | const_slice_type, | ||
| 197 | /// Create a pointer type with attributes | 213 | /// Create a pointer type with attributes |
| 198 | ptr_type, | 214 | ptr_type, |
| 199 | /// Write a value to a pointer. For loading, see `deref`. | 215 | /// Write a value to a pointer. For loading, see `deref`. |
| ... | @@ -225,6 +241,10 @@ pub const Inst = struct { | ... | @@ -225,6 +241,10 @@ pub const Inst = struct { |
| 225 | unwrap_err_safe, | 241 | unwrap_err_safe, |
| 226 | /// Same as previous, but without safety checks. Used for orelse, if and while | 242 | /// Same as previous, but without safety checks. Used for orelse, if and while |
| 227 | unwrap_err_unsafe, | 243 | unwrap_err_unsafe, |
| 244 | /// Takes a *E!T and raises a compiler error if T != void | ||
| 245 | ensure_err_payload_void, | ||
| 246 | /// Enum literal | ||
| 247 | enum_literal, | ||
| 228 | 248 | ||
| 229 | pub fn Type(tag: Tag) type { | 249 | pub fn Type(tag: Tag) type { |
| 230 | return switch (tag) { | 250 | return switch (tag) { |
| ... | @@ -250,21 +270,29 @@ pub const Inst = struct { | ... | @@ -250,21 +270,29 @@ pub const Inst = struct { |
| 250 | .ensure_result_non_error, | 270 | .ensure_result_non_error, |
| 251 | .bitcast_result_ptr, | 271 | .bitcast_result_ptr, |
| 252 | .ref, | 272 | .ref, |
| 253 | .bitcast_lvalue, | 273 | .bitcast_ref, |
| 254 | .typeof, | 274 | .typeof, |
| 255 | .single_const_ptr_type, | 275 | .single_const_ptr_type, |
| 256 | .single_mut_ptr_type, | 276 | .single_mut_ptr_type, |
| 277 | .many_const_ptr_type, | ||
| 278 | .many_mut_ptr_type, | ||
| 279 | .c_const_ptr_type, | ||
| 280 | .c_mut_ptr_type, | ||
| 281 | .mut_slice_type, | ||
| 282 | .const_slice_type, | ||
| 257 | .optional_type, | 283 | .optional_type, |
| 258 | .unwrap_optional_safe, | 284 | .unwrap_optional_safe, |
| 259 | .unwrap_optional_unsafe, | 285 | .unwrap_optional_unsafe, |
| 260 | .unwrap_err_safe, | 286 | .unwrap_err_safe, |
| 261 | .unwrap_err_unsafe, | 287 | .unwrap_err_unsafe, |
| 288 | .ensure_err_payload_void, | ||
| 262 | => UnOp, | 289 | => UnOp, |
| 263 | 290 | ||
| 264 | .add, | 291 | .add, |
| 265 | .addwrap, | 292 | .addwrap, |
| 266 | .array_cat, | 293 | .array_cat, |
| 267 | .array_mul, | 294 | .array_mul, |
| 295 | .array_type, | ||
| 268 | .bitand, | 296 | .bitand, |
| 269 | .bitor, | 297 | .bitor, |
| 270 | .div, | 298 | .div, |
| ... | @@ -291,6 +319,7 @@ pub const Inst = struct { | ... | @@ -291,6 +319,7 @@ pub const Inst = struct { |
| 291 | => BinOp, | 319 | => BinOp, |
| 292 | 320 | ||
| 293 | .arg => Arg, | 321 | .arg => Arg, |
| 322 | .array_type_sentinel => ArrayTypeSentinel, | ||
| 294 | .block => Block, | 323 | .block => Block, |
| 295 | .@"break" => Break, | 324 | .@"break" => Break, |
| 296 | .breakvoid => BreakVoid, | 325 | .breakvoid => BreakVoid, |
| ... | @@ -317,6 +346,7 @@ pub const Inst = struct { | ... | @@ -317,6 +346,7 @@ pub const Inst = struct { |
| 317 | .elemptr => ElemPtr, | 346 | .elemptr => ElemPtr, |
| 318 | .condbr => CondBr, | 347 | .condbr => CondBr, |
| 319 | .ptr_type => PtrType, | 348 | .ptr_type => PtrType, |
| 349 | .enum_literal => EnumLiteral, | ||
| 320 | }; | 350 | }; |
| 321 | } | 351 | } |
| 322 | 352 | ||
| ... | @@ -330,12 +360,14 @@ pub const Inst = struct { | ... | @@ -330,12 +360,14 @@ pub const Inst = struct { |
| 330 | .alloc_inferred, | 360 | .alloc_inferred, |
| 331 | .array_cat, | 361 | .array_cat, |
| 332 | .array_mul, | 362 | .array_mul, |
| 363 | .array_type, | ||
| 364 | .array_type_sentinel, | ||
| 333 | .arg, | 365 | .arg, |
| 334 | .as, | 366 | .as, |
| 335 | .@"asm", | 367 | .@"asm", |
| 336 | .bitand, | 368 | .bitand, |
| 337 | .bitcast, | 369 | .bitcast, |
| 338 | .bitcast_lvalue, | 370 | .bitcast_ref, |
| 339 | .bitcast_result_ptr, | 371 | .bitcast_result_ptr, |
| 340 | .bitor, | 372 | .bitor, |
| 341 | .block, | 373 | .block, |
| ... | @@ -386,6 +418,12 @@ pub const Inst = struct { | ... | @@ -386,6 +418,12 @@ pub const Inst = struct { |
| 386 | .shr, | 418 | .shr, |
| 387 | .single_const_ptr_type, | 419 | .single_const_ptr_type, |
| 388 | .single_mut_ptr_type, | 420 | .single_mut_ptr_type, |
| 421 | .many_const_ptr_type, | ||
| 422 | .many_mut_ptr_type, | ||
| 423 | .c_const_ptr_type, | ||
| 424 | .c_mut_ptr_type, | ||
| 425 | .mut_slice_type, | ||
| 426 | .const_slice_type, | ||
| 389 | .store, | 427 | .store, |
| 390 | .str, | 428 | .str, |
| 391 | .sub, | 429 | .sub, |
| ... | @@ -398,6 +436,8 @@ pub const Inst = struct { | ... | @@ -398,6 +436,8 @@ pub const Inst = struct { |
| 398 | .unwrap_err_safe, | 436 | .unwrap_err_safe, |
| 399 | .unwrap_err_unsafe, | 437 | .unwrap_err_unsafe, |
| 400 | .ptr_type, | 438 | .ptr_type, |
| 439 | .ensure_err_payload_void, | ||
| 440 | .enum_literal, | ||
| 401 | => false, | 441 | => false, |
| 402 | 442 | ||
| 403 | .@"break", | 443 | .@"break", |
| ... | @@ -840,11 +880,34 @@ pub const Inst = struct { | ... | @@ -840,11 +880,34 @@ pub const Inst = struct { |
| 840 | @"align": ?*Inst = null, | 880 | @"align": ?*Inst = null, |
| 841 | align_bit_start: ?*Inst = null, | 881 | align_bit_start: ?*Inst = null, |
| 842 | align_bit_end: ?*Inst = null, | 882 | align_bit_end: ?*Inst = null, |
| 843 | @"const": bool = true, | 883 | mutable: bool = true, |
| 844 | @"volatile": bool = false, | 884 | @"volatile": bool = false, |
| 845 | sentinel: ?*Inst = null, | 885 | sentinel: ?*Inst = null, |
| 886 | size: std.builtin.TypeInfo.Pointer.Size = .One, | ||
| 846 | }, | 887 | }, |
| 847 | }; | 888 | }; |
| 889 | |||
| 890 | pub const ArrayTypeSentinel = struct { | ||
| 891 | pub const base_tag = Tag.array_type_sentinel; | ||
| 892 | base: Inst, | ||
| 893 | |||
| 894 | positionals: struct { | ||
| 895 | len: *Inst, | ||
| 896 | sentinel: *Inst, | ||
| 897 | elem_type: *Inst, | ||
| 898 | }, | ||
| 899 | kw_args: struct {}, | ||
| 900 | }; | ||
| 901 | |||
| 902 | pub const EnumLiteral = struct { | ||
| 903 | pub const base_tag = Tag.enum_literal; | ||
| 904 | base: Inst, | ||
| 905 | |||
| 906 | positionals: struct { | ||
| 907 | name: []const u8, | ||
| 908 | }, | ||
| 909 | kw_args: struct {}, | ||
| 910 | }; | ||
| 848 | }; | 911 | }; |
| 849 | 912 | ||
| 850 | pub const ErrorMsg = struct { | 913 | pub const ErrorMsg = struct { |
| ... | @@ -1714,6 +1777,9 @@ const EmitZIR = struct { | ... | @@ -1714,6 +1777,9 @@ const EmitZIR = struct { |
| 1714 | const decl_ref = try self.emitDeclRef(inst.src, declref.decl); | 1777 | const decl_ref = try self.emitDeclRef(inst.src, declref.decl); |
| 1715 | try new_body.instructions.append(decl_ref); | 1778 | try new_body.instructions.append(decl_ref); |
| 1716 | break :blk decl_ref; | 1779 | break :blk decl_ref; |
| 1780 | } else if (const_inst.val.cast(Value.Payload.Variable)) |var_pl| blk: { | ||
| 1781 | const owner_decl = var_pl.variable.owner_decl; | ||
| 1782 | break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name)); | ||
| 1717 | } else blk: { | 1783 | } else blk: { |
| 1718 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; | 1784 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; |
| 1719 | }; | 1785 | }; |
| ... | @@ -1837,6 +1903,11 @@ const EmitZIR = struct { | ... | @@ -1837,6 +1903,11 @@ const EmitZIR = struct { |
| 1837 | if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| { | 1903 | if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| { |
| 1838 | const decl = decl_ref.decl; | 1904 | const decl = decl_ref.decl; |
| 1839 | return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl)); | 1905 | return try self.emitUnnamedDecl(try self.emitDeclRef(src, decl)); |
| 1906 | } else if (typed_value.val.cast(Value.Payload.Variable)) |variable| { | ||
| 1907 | return self.emitTypedValue(src, .{ | ||
| 1908 | .ty = typed_value.ty, | ||
| 1909 | .val = variable.variable.init, | ||
| 1910 | }); | ||
| 1840 | } | 1911 | } |
| 1841 | if (typed_value.val.isUndef()) { | 1912 | if (typed_value.val.isUndef()) { |
| 1842 | const as_inst = try self.arena.allocator.create(Inst.BinOp); | 1913 | const as_inst = try self.arena.allocator.create(Inst.BinOp); |
| ... | @@ -1922,6 +1993,25 @@ const EmitZIR = struct { | ... | @@ -1922,6 +1993,25 @@ const EmitZIR = struct { |
| 1922 | return self.emitUnnamedDecl(&str_inst.base); | 1993 | return self.emitUnnamedDecl(&str_inst.base); |
| 1923 | }, | 1994 | }, |
| 1924 | .Void => return self.emitPrimitive(src, .void_value), | 1995 | .Void => return self.emitPrimitive(src, .void_value), |
| 1996 | .Bool => if (typed_value.val.toBool()) | ||
| 1997 | return self.emitPrimitive(src, .@"true") | ||
| 1998 | else | ||
| 1999 | return self.emitPrimitive(src, .@"false"), | ||
| 2000 | .EnumLiteral => { | ||
| 2001 | const enum_literal = @fieldParentPtr(Value.Payload.Bytes, "base", typed_value.val.ptr_otherwise); | ||
| 2002 | const inst = try self.arena.allocator.create(Inst.Str); | ||
| 2003 | inst.* = .{ | ||
| 2004 | .base = .{ | ||
| 2005 | .src = src, | ||
| 2006 | .tag = .enum_literal, | ||
| 2007 | }, | ||
| 2008 | .positionals = .{ | ||
| 2009 | .bytes = enum_literal.data, | ||
| 2010 | }, | ||
| 2011 | .kw_args = .{}, | ||
| 2012 | }; | ||
| 2013 | return self.emitUnnamedDecl(&inst.base); | ||
| 2014 | }, | ||
| 1925 | else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}), | 2015 | else => |t| std.debug.panic("TODO implement emitTypedValue for {}", .{@tagName(t)}), |
| 1926 | } | 2016 | } |
| 1927 | } | 2017 | } |
| ... | @@ -2269,6 +2359,8 @@ const EmitZIR = struct { | ... | @@ -2269,6 +2359,8 @@ const EmitZIR = struct { |
| 2269 | }; | 2359 | }; |
| 2270 | break :blk &new_inst.base; | 2360 | break :blk &new_inst.base; |
| 2271 | }, | 2361 | }, |
| 2362 | |||
| 2363 | .varptr => @panic("TODO"), | ||
| 2272 | }; | 2364 | }; |
| 2273 | try self.metadata.put(new_inst, .{ .deaths = inst.deaths }); | 2365 | try self.metadata.put(new_inst, .{ .deaths = inst.deaths }); |
| 2274 | try instructions.append(new_inst); | 2366 | try instructions.append(new_inst); |
| ... | @@ -2376,7 +2468,7 @@ const EmitZIR = struct { | ... | @@ -2376,7 +2468,7 @@ const EmitZIR = struct { |
| 2376 | } | 2468 | } |
| 2377 | }, | 2469 | }, |
| 2378 | .Optional => { | 2470 | .Optional => { |
| 2379 | var buf: Type.Payload.Pointer = undefined; | 2471 | var buf: Type.Payload.PointerSimple = undefined; |
| 2380 | const inst = try self.arena.allocator.create(Inst.UnOp); | 2472 | const inst = try self.arena.allocator.create(Inst.UnOp); |
| 2381 | inst.* = .{ | 2473 | inst.* = .{ |
| 2382 | .base = .{ | 2474 | .base = .{ |
| ... | @@ -2390,6 +2482,51 @@ const EmitZIR = struct { | ... | @@ -2390,6 +2482,51 @@ const EmitZIR = struct { |
| 2390 | }; | 2482 | }; |
| 2391 | return self.emitUnnamedDecl(&inst.base); | 2483 | return self.emitUnnamedDecl(&inst.base); |
| 2392 | }, | 2484 | }, |
| 2485 | .Array => { | ||
| 2486 | var len_pl = Value.Payload.Int_u64{ .int = ty.arrayLen() }; | ||
| 2487 | const len = Value.initPayload(&len_pl.base); | ||
| 2488 | |||
| 2489 | const inst = if (ty.arraySentinel()) |sentinel| blk: { | ||
| 2490 | const inst = try self.arena.allocator.create(Inst.ArrayTypeSentinel); | ||
| 2491 | inst.* = .{ | ||
| 2492 | .base = .{ | ||
| 2493 | .src = src, | ||
| 2494 | .tag = .array_type, | ||
| 2495 | }, | ||
| 2496 | .positionals = .{ | ||
| 2497 | .len = (try self.emitTypedValue(src, .{ | ||
| 2498 | .ty = Type.initTag(.usize), | ||
| 2499 | .val = len, | ||
| 2500 | })).inst, | ||
| 2501 | .sentinel = (try self.emitTypedValue(src, .{ | ||
| 2502 | .ty = ty.elemType(), | ||
| 2503 | .val = sentinel, | ||
| 2504 | })).inst, | ||
| 2505 | .elem_type = (try self.emitType(src, ty.elemType())).inst, | ||
| 2506 | }, | ||
| 2507 | .kw_args = .{}, | ||
| 2508 | }; | ||
| 2509 | break :blk &inst.base; | ||
| 2510 | } else blk: { | ||
| 2511 | const inst = try self.arena.allocator.create(Inst.BinOp); | ||
| 2512 | inst.* = .{ | ||
| 2513 | .base = .{ | ||
| 2514 | .src = src, | ||
| 2515 | .tag = .array_type, | ||
| 2516 | }, | ||
| 2517 | .positionals = .{ | ||
| 2518 | .lhs = (try self.emitTypedValue(src, .{ | ||
| 2519 | .ty = Type.initTag(.usize), | ||
| 2520 | .val = len, | ||
| 2521 | })).inst, | ||
| 2522 | .rhs = (try self.emitType(src, ty.elemType())).inst, | ||
| 2523 | }, | ||
| 2524 | .kw_args = .{}, | ||
| 2525 | }; | ||
| 2526 | break :blk &inst.base; | ||
| 2527 | }; | ||
| 2528 | return self.emitUnnamedDecl(inst); | ||
| 2529 | }, | ||
| 2393 | else => std.debug.panic("TODO implement emitType for {}", .{ty}), | 2530 | else => std.debug.panic("TODO implement emitType for {}", .{ty}), |
| 2394 | }, | 2531 | }, |
| 2395 | } | 2532 | } |
src-self-hosted/zir_sema.zig+112-46| ... | @@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 29 | .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?), | 29 | .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?), |
| 30 | .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?), | 30 | .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?), |
| 31 | .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?), | 31 | .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?), |
| 32 | .bitcast_lvalue => return analyzeInstBitCastLValue(mod, scope, old_inst.castTag(.bitcast_lvalue).?), | 32 | .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?), |
| 33 | .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?), | 33 | .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?), |
| 34 | .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?), | 34 | .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?), |
| 35 | .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?), | 35 | .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?), |
| ... | @@ -51,8 +51,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -51,8 +51,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 51 | .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), | 51 | .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), |
| 52 | .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), | 52 | .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), |
| 53 | .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), | 53 | .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), |
| 54 | .single_const_ptr_type => return analyzeInstSingleConstPtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?), | 54 | .single_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One), |
| 55 | .single_mut_ptr_type => return analyzeInstSingleMutPtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?), | 55 | .single_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One), |
| 56 | .many_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many), | ||
| 57 | .many_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_mut_ptr_type).?, true, .Many), | ||
| 58 | .c_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_const_ptr_type).?, false, .C), | ||
| 59 | .c_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.c_mut_ptr_type).?, true, .C), | ||
| 60 | .const_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.const_slice_type).?, false, .Slice), | ||
| 61 | .mut_slice_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.mut_slice_type).?, true, .Slice), | ||
| 56 | .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?), | 62 | .ptr_type => return analyzeInstPtrType(mod, scope, old_inst.castTag(.ptr_type).?), |
| 57 | .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?), | 63 | .store => return analyzeInstStore(mod, scope, old_inst.castTag(.store).?), |
| 58 | .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?), | 64 | .str => return analyzeInstStr(mod, scope, old_inst.castTag(.str).?), |
| ... | @@ -112,6 +118,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -112,6 +118,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 112 | .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false), | 118 | .unwrap_optional_unsafe => return analyzeInstUnwrapOptional(mod, scope, old_inst.castTag(.unwrap_optional_unsafe).?, false), |
| 113 | .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true), | 119 | .unwrap_err_safe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_safe).?, true), |
| 114 | .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false), | 120 | .unwrap_err_unsafe => return analyzeInstUnwrapErr(mod, scope, old_inst.castTag(.unwrap_err_unsafe).?, false), |
| 121 | .ensure_err_payload_void => return analyzeInstEnsureErrPayloadVoid(mod, scope, old_inst.castTag(.ensure_err_payload_void).?), | ||
| 122 | .array_type => return analyzeInstArrayType(mod, scope, old_inst.castTag(.array_type).?), | ||
| 123 | .array_type_sentinel => return analyzeInstArrayTypeSentinel(mod, scope, old_inst.castTag(.array_type_sentinel).?), | ||
| 124 | .enum_literal => return analyzeInstEnumLiteral(mod, scope, old_inst.castTag(.enum_literal).?), | ||
| 115 | } | 125 | } |
| 116 | } | 126 | } |
| 117 | 127 | ||
| ... | @@ -263,6 +273,14 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type { | ... | @@ -263,6 +273,14 @@ fn resolveType(mod: *Module, scope: *Scope, old_inst: *zir.Inst) !Type { |
| 263 | return val.toType(); | 273 | return val.toType(); |
| 264 | } | 274 | } |
| 265 | 275 | ||
| 276 | fn resolveInt(mod: *Module, scope: *Scope, old_inst: *zir.Inst, dest_type: Type) !u64 { | ||
| 277 | const new_inst = try resolveInst(mod, scope, old_inst); | ||
| 278 | const coerced = try mod.coerce(scope, dest_type, new_inst); | ||
| 279 | const val = try mod.resolveConstValue(scope, coerced); | ||
| 280 | |||
| 281 | return val.toUnsignedInt(); | ||
| 282 | } | ||
| 283 | |||
| 266 | pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue { | 284 | pub fn resolveInstConst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!TypedValue { |
| 267 | const new_inst = try resolveInst(mod, scope, old_inst); | 285 | const new_inst = try resolveInst(mod, scope, old_inst); |
| 268 | const val = try mod.resolveConstValue(scope, new_inst); | 286 | const val = try mod.resolveConstValue(scope, new_inst); |
| ... | @@ -295,8 +313,8 @@ fn analyzeInstCoerceResultBlockPtr( | ... | @@ -295,8 +313,8 @@ fn analyzeInstCoerceResultBlockPtr( |
| 295 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{}); | 313 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{}); |
| 296 | } | 314 | } |
| 297 | 315 | ||
| 298 | fn analyzeInstBitCastLValue(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 316 | fn analyzeInstBitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 299 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastLValue", .{}); | 317 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastRef", .{}); |
| 300 | } | 318 | } |
| 301 | 319 | ||
| 302 | fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 320 | fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| ... | @@ -320,7 +338,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr | ... | @@ -320,7 +338,7 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr |
| 320 | 338 | ||
| 321 | fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 339 | fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 322 | const operand = try resolveInst(mod, scope, inst.positionals.operand); | 340 | const operand = try resolveInst(mod, scope, inst.positionals.operand); |
| 323 | const ptr_type = try mod.singlePtrType(scope, inst.base.src, false, operand.ty); | 341 | const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One); |
| 324 | 342 | ||
| 325 | if (operand.value()) |val| { | 343 | if (operand.value()) |val| { |
| 326 | const ref_payload = try scope.arena().create(Value.Payload.RefVal); | 344 | const ref_payload = try scope.arena().create(Value.Payload.RefVal); |
| ... | @@ -361,7 +379,11 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst. | ... | @@ -361,7 +379,11 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst. |
| 361 | 379 | ||
| 362 | fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 380 | fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 363 | const var_type = try resolveType(mod, scope, inst.positionals.operand); | 381 | const var_type = try resolveType(mod, scope, inst.positionals.operand); |
| 364 | const ptr_type = try mod.singlePtrType(scope, inst.base.src, true, var_type); | 382 | // TODO this should happen only for var allocs |
| 383 | if (!var_type.isValidVarType(false)) { | ||
| 384 | return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type}); | ||
| 385 | } | ||
| 386 | const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One); | ||
| 365 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); | 387 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); |
| 366 | return mod.addNoOp(b, inst.base.src, ptr_type, .alloc); | 388 | return mod.addNoOp(b, inst.base.src, ptr_type, .alloc); |
| 367 | } | 389 | } |
| ... | @@ -573,8 +595,7 @@ fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inne | ... | @@ -573,8 +595,7 @@ fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) Inne |
| 573 | 595 | ||
| 574 | fn analyzeInstDeclValInModule(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst { | 596 | fn analyzeInstDeclValInModule(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclValInModule) InnerError!*Inst { |
| 575 | const decl = inst.positionals.decl; | 597 | const decl = inst.positionals.decl; |
| 576 | const ptr = try mod.analyzeDeclRef(scope, inst.base.src, decl); | 598 | return mod.analyzeDeclRef(scope, inst.base.src, decl); |
| 577 | return mod.analyzeDeref(scope, inst.base.src, ptr, inst.base.src); | ||
| 578 | } | 599 | } |
| 579 | 600 | ||
| 580 | fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { | 601 | fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst { |
| ... | @@ -675,31 +696,36 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I | ... | @@ -675,31 +696,36 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I |
| 675 | fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst { | 696 | fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst { |
| 676 | const child_type = try resolveType(mod, scope, optional.positionals.operand); | 697 | const child_type = try resolveType(mod, scope, optional.positionals.operand); |
| 677 | 698 | ||
| 678 | return mod.constType(scope, optional.base.src, Type.initPayload(switch (child_type.tag()) { | 699 | return mod.constType(scope, optional.base.src, try mod.optionalType(scope, child_type)); |
| 679 | .single_const_pointer => blk: { | 700 | } |
| 680 | const payload = try scope.arena().create(Type.Payload.Pointer); | 701 | |
| 681 | payload.* = .{ | 702 | fn analyzeInstArrayType(mod: *Module, scope: *Scope, array: *zir.Inst.BinOp) InnerError!*Inst { |
| 682 | .base = .{ .tag = .optional_single_const_pointer }, | 703 | // TODO these should be lazily evaluated |
| 683 | .pointee_type = child_type.elemType(), | 704 | const len = try resolveInstConst(mod, scope, array.positionals.lhs); |
| 684 | }; | 705 | const elem_type = try resolveType(mod, scope, array.positionals.rhs); |
| 685 | break :blk &payload.base; | 706 | |
| 686 | }, | 707 | return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), null, elem_type)); |
| 687 | .single_mut_pointer => blk: { | 708 | } |
| 688 | const payload = try scope.arena().create(Type.Payload.Pointer); | 709 | |
| 689 | payload.* = .{ | 710 | fn analyzeInstArrayTypeSentinel(mod: *Module, scope: *Scope, array: *zir.Inst.ArrayTypeSentinel) InnerError!*Inst { |
| 690 | .base = .{ .tag = .optional_single_mut_pointer }, | 711 | // TODO these should be lazily evaluated |
| 691 | .pointee_type = child_type.elemType(), | 712 | const len = try resolveInstConst(mod, scope, array.positionals.len); |
| 692 | }; | 713 | const sentinel = try resolveInstConst(mod, scope, array.positionals.sentinel); |
| 693 | break :blk &payload.base; | 714 | const elem_type = try resolveType(mod, scope, array.positionals.elem_type); |
| 694 | }, | 715 | |
| 695 | else => blk: { | 716 | return mod.constType(scope, array.base.src, try mod.arrayType(scope, len.val.toUnsignedInt(), sentinel.val, elem_type)); |
| 696 | const payload = try scope.arena().create(Type.Payload.Optional); | 717 | } |
| 697 | payload.* = .{ | 718 | |
| 698 | .child_type = child_type, | 719 | fn analyzeInstEnumLiteral(mod: *Module, scope: *Scope, inst: *zir.Inst.EnumLiteral) InnerError!*Inst { |
| 699 | }; | 720 | const payload = try scope.arena().create(Value.Payload.Bytes); |
| 700 | break :blk &payload.base; | 721 | payload.* = .{ |
| 701 | }, | 722 | .base = .{ .tag = .enum_literal }, |
| 702 | })); | 723 | .data = try scope.arena().dupe(u8, inst.positionals.name), |
| 724 | }; | ||
| 725 | return mod.constInst(scope, inst.base.src, .{ | ||
| 726 | .ty = Type.initTag(.enum_literal), | ||
| 727 | .val = Value.initPayload(&payload.base), | ||
| 728 | }); | ||
| 703 | } | 729 | } |
| 704 | 730 | ||
| 705 | fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst { | 731 | fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, safety_check: bool) InnerError!*Inst { |
| ... | @@ -711,7 +737,7 @@ fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp | ... | @@ -711,7 +737,7 @@ fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp |
| 711 | } | 737 | } |
| 712 | 738 | ||
| 713 | const child_type = try operand.ty.elemType().optionalChildAlloc(scope.arena()); | 739 | const child_type = try operand.ty.elemType().optionalChildAlloc(scope.arena()); |
| 714 | const child_pointer = try mod.singlePtrType(scope, unwrap.base.src, operand.ty.isConstPtr(), child_type); | 740 | const child_pointer = try mod.simplePtrType(scope, unwrap.base.src, child_type, operand.ty.isConstPtr(), .One); |
| 715 | 741 | ||
| 716 | if (operand.value()) |val| { | 742 | if (operand.value()) |val| { |
| 717 | if (val.isNull()) { | 743 | if (val.isNull()) { |
| ... | @@ -735,6 +761,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf | ... | @@ -735,6 +761,10 @@ fn analyzeInstUnwrapErr(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp, saf |
| 735 | return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{}); | 761 | return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstUnwrapErr", .{}); |
| 736 | } | 762 | } |
| 737 | 763 | ||
| 764 | fn analyzeInstEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 765 | return mod.fail(scope, unwrap.base.src, "TODO implement analyzeInstEnsureErrPayloadVoid", .{}); | ||
| 766 | } | ||
| 767 | |||
| 738 | fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { | 768 | fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { |
| 739 | const return_type = try resolveType(mod, scope, fntype.positionals.return_type); | 769 | const return_type = try resolveType(mod, scope, fntype.positionals.return_type); |
| 740 | 770 | ||
| ... | @@ -760,7 +790,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne | ... | @@ -760,7 +790,12 @@ fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) Inne |
| 760 | const arena = scope.arena(); | 790 | const arena = scope.arena(); |
| 761 | const param_types = try arena.alloc(Type, fntype.positionals.param_types.len); | 791 | const param_types = try arena.alloc(Type, fntype.positionals.param_types.len); |
| 762 | for (fntype.positionals.param_types) |param_type, i| { | 792 | for (fntype.positionals.param_types) |param_type, i| { |
| 763 | param_types[i] = try resolveType(mod, scope, param_type); | 793 | const resolved = try resolveType(mod, scope, param_type); |
| 794 | // TODO skip for comptime params | ||
| 795 | if (!resolved.isValidVarType(false)) { | ||
| 796 | return mod.fail(scope, param_type.src, "parameter of type '{}' must be declared comptime", .{resolved}); | ||
| 797 | } | ||
| 798 | param_types[i] = resolved; | ||
| 764 | } | 799 | } |
| 765 | 800 | ||
| 766 | const payload = try arena.create(Type.Payload.Function); | 801 | const payload = try arena.create(Type.Payload.Function); |
| ... | @@ -919,7 +954,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne | ... | @@ -919,7 +954,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne |
| 919 | // required a larger index. | 954 | // required a larger index. |
| 920 | const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64)); | 955 | const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64)); |
| 921 | 956 | ||
| 922 | const type_payload = try scope.arena().create(Type.Payload.Pointer); | 957 | const type_payload = try scope.arena().create(Type.Payload.PointerSimple); |
| 923 | type_payload.* = .{ | 958 | type_payload.* = .{ |
| 924 | .base = .{ .tag = .single_const_pointer }, | 959 | .base = .{ .tag = .single_const_pointer }, |
| 925 | .pointee_type = array_ptr.ty.elemType().elemType(), | 960 | .pointee_type = array_ptr.ty.elemType().elemType(), |
| ... | @@ -1290,18 +1325,49 @@ fn analyzeDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerErr | ... | @@ -1290,18 +1325,49 @@ fn analyzeDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerErr |
| 1290 | return decl; | 1325 | return decl; |
| 1291 | } | 1326 | } |
| 1292 | 1327 | ||
| 1293 | fn analyzeInstSingleConstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 1328 | fn analyzeInstSimplePtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*Inst { |
| 1294 | const elem_type = try resolveType(mod, scope, inst.positionals.operand); | 1329 | const elem_type = try resolveType(mod, scope, inst.positionals.operand); |
| 1295 | const ty = try mod.singlePtrType(scope, inst.base.src, false, elem_type); | 1330 | const ty = try mod.simplePtrType(scope, inst.base.src, elem_type, mutable, size); |
| 1296 | return mod.constType(scope, inst.base.src, ty); | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | fn analyzeInstSingleMutPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1300 | const elem_type = try resolveType(mod, scope, inst.positionals.operand); | ||
| 1301 | const ty = try mod.singlePtrType(scope, inst.base.src, true, elem_type); | ||
| 1302 | return mod.constType(scope, inst.base.src, ty); | 1331 | return mod.constType(scope, inst.base.src, ty); |
| 1303 | } | 1332 | } |
| 1304 | 1333 | ||
| 1305 | fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst { | 1334 | fn analyzeInstPtrType(mod: *Module, scope: *Scope, inst: *zir.Inst.PtrType) InnerError!*Inst { |
| 1306 | return mod.fail(scope, inst.base.src, "TODO implement ptr_type", .{}); | 1335 | // TODO lazy values |
| 1336 | const @"align" = if (inst.kw_args.@"align") |some| | ||
| 1337 | @truncate(u32, try resolveInt(mod, scope, some, Type.initTag(.u32))) | ||
| 1338 | else | ||
| 1339 | 0; | ||
| 1340 | const bit_offset = if (inst.kw_args.align_bit_start) |some| | ||
| 1341 | @truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16))) | ||
| 1342 | else | ||
| 1343 | 0; | ||
| 1344 | const host_size = if (inst.kw_args.align_bit_end) |some| | ||
| 1345 | @truncate(u16, try resolveInt(mod, scope, some, Type.initTag(.u16))) | ||
| 1346 | else | ||
| 1347 | 0; | ||
| 1348 | |||
| 1349 | if (host_size != 0 and bit_offset >= host_size * 8) | ||
| 1350 | return mod.fail(scope, inst.base.src, "bit offset starts after end of host integer", .{}); | ||
| 1351 | |||
| 1352 | const sentinel = if (inst.kw_args.sentinel) |some| | ||
| 1353 | (try resolveInstConst(mod, scope, some)).val | ||
| 1354 | else | ||
| 1355 | null; | ||
| 1356 | |||
| 1357 | const elem_type = try resolveType(mod, scope, inst.positionals.child_type); | ||
| 1358 | |||
| 1359 | const ty = try mod.ptrType( | ||
| 1360 | scope, | ||
| 1361 | inst.base.src, | ||
| 1362 | elem_type, | ||
| 1363 | sentinel, | ||
| 1364 | @"align", | ||
| 1365 | bit_offset, | ||
| 1366 | host_size, | ||
| 1367 | inst.kw_args.mutable, | ||
| 1368 | inst.kw_args.@"allowzero", | ||
| 1369 | inst.kw_args.@"volatile", | ||
| 1370 | inst.kw_args.size, | ||
| 1371 | ); | ||
| 1372 | return mod.constType(scope, inst.base.src, ty); | ||
| 1307 | } | 1373 | } |
src/all_types.hpp+1| ... | @@ -1420,6 +1420,7 @@ struct ZigTypeStruct { | ... | @@ -1420,6 +1420,7 @@ struct ZigTypeStruct { |
| 1420 | bool requires_comptime; | 1420 | bool requires_comptime; |
| 1421 | bool resolve_loop_flag_zero_bits; | 1421 | bool resolve_loop_flag_zero_bits; |
| 1422 | bool resolve_loop_flag_other; | 1422 | bool resolve_loop_flag_other; |
| 1423 | bool created_by_at_type; | ||
| 1423 | }; | 1424 | }; |
| 1424 | 1425 | ||
| 1425 | struct ZigTypeOptional { | 1426 | struct ZigTypeOptional { |
src/analyze.cpp+5-5| ... | @@ -138,7 +138,7 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope | ... | @@ -138,7 +138,7 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope |
| 138 | dest->parent = parent; | 138 | dest->parent = parent; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, | 141 | ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, |
| 142 | ZigType *import, Buf *bare_name) | 142 | ZigType *import, Buf *bare_name) |
| 143 | { | 143 | { |
| 144 | ScopeDecls *scope = heap::c_allocator.create<ScopeDecls>(); | 144 | ScopeDecls *scope = heap::c_allocator.create<ScopeDecls>(); |
| ... | @@ -2821,7 +2821,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2821,7 +2821,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2821 | 2821 | ||
| 2822 | src_assert(struct_type->data.structure.fields == nullptr, decl_node); | 2822 | src_assert(struct_type->data.structure.fields == nullptr, decl_node); |
| 2823 | struct_type->data.structure.fields = alloc_type_struct_fields(field_count); | 2823 | struct_type->data.structure.fields = alloc_type_struct_fields(field_count); |
| 2824 | } else if (is_anon_container(struct_type)) { | 2824 | } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) { |
| 2825 | field_count = struct_type->data.structure.src_field_count; | 2825 | field_count = struct_type->data.structure.src_field_count; |
| 2826 | 2826 | ||
| 2827 | src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node); | 2827 | src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node); |
| ... | @@ -2856,7 +2856,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2856,7 +2856,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2856 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2856 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2857 | return ErrorSemanticAnalyzeFail; | 2857 | return ErrorSemanticAnalyzeFail; |
| 2858 | } | 2858 | } |
| 2859 | } else if (is_anon_container(struct_type)) { | 2859 | } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) { |
| 2860 | field_node = type_struct_field->decl_node; | 2860 | field_node = type_struct_field->decl_node; |
| 2861 | 2861 | ||
| 2862 | src_assert(type_struct_field->type_entry != nullptr, field_node); | 2862 | src_assert(type_struct_field->type_entry != nullptr, field_node); |
| ... | @@ -2883,7 +2883,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -2883,7 +2883,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 2883 | type_struct_field->type_val = field_type_val; | 2883 | type_struct_field->type_val = field_type_val; |
| 2884 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) | 2884 | if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) |
| 2885 | return ErrorSemanticAnalyzeFail; | 2885 | return ErrorSemanticAnalyzeFail; |
| 2886 | } else if (is_anon_container(struct_type)) { | 2886 | } else if (is_anon_container(struct_type) || struct_type->data.structure.created_by_at_type) { |
| 2887 | field_type_val = type_struct_field->type_val; | 2887 | field_type_val = type_struct_field->type_val; |
| 2888 | } else zig_unreachable(); | 2888 | } else zig_unreachable(); |
| 2889 | 2889 | ||
| ... | @@ -8331,7 +8331,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS | ... | @@ -8331,7 +8331,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 8331 | ZigLLVMDIFile *di_file; | 8331 | ZigLLVMDIFile *di_file; |
| 8332 | ZigLLVMDIScope *di_scope; | 8332 | ZigLLVMDIScope *di_scope; |
| 8333 | unsigned line; | 8333 | unsigned line; |
| 8334 | if (decl_node != nullptr) { | 8334 | if (decl_node != nullptr && !struct_type->data.structure.created_by_at_type) { |
| 8335 | Scope *scope = &struct_type->data.structure.decls_scope->base; | 8335 | Scope *scope = &struct_type->data.structure.decls_scope->base; |
| 8336 | ZigType *import = get_scope_import(scope); | 8336 | ZigType *import = get_scope_import(scope); |
| 8337 | di_file = import->data.structure.root_struct->di_file; | 8337 | di_file = import->data.structure.root_struct->di_file; |
src/analyze.hpp+1| ... | @@ -116,6 +116,7 @@ void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool | ... | @@ -116,6 +116,7 @@ void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool |
| 116 | 116 | ||
| 117 | void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val); | 117 | void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val); |
| 118 | 118 | ||
| 119 | ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name); | ||
| 119 | ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent); | 120 | ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent); |
| 120 | ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent); | 121 | ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent); |
| 121 | ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent); | 122 | ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent); |
src/codegen.cpp+5-4| ... | @@ -293,13 +293,14 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { | ... | @@ -293,13 +293,14 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { |
| 293 | } | 293 | } |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | 296 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id, bool is_extern) { |
| 297 | switch (id) { | 297 | switch (id) { |
| 298 | case GlobalLinkageIdInternal: | 298 | case GlobalLinkageIdInternal: |
| 299 | return LLVMInternalLinkage; | 299 | return LLVMInternalLinkage; |
| 300 | case GlobalLinkageIdStrong: | 300 | case GlobalLinkageIdStrong: |
| 301 | return LLVMExternalLinkage; | 301 | return LLVMExternalLinkage; |
| 302 | case GlobalLinkageIdWeak: | 302 | case GlobalLinkageIdWeak: |
| 303 | if (is_extern) return LLVMExternalWeakLinkage; | ||
| 303 | return LLVMWeakODRLinkage; | 304 | return LLVMWeakODRLinkage; |
| 304 | case GlobalLinkageIdLinkOnce: | 305 | case GlobalLinkageIdLinkOnce: |
| 305 | return LLVMLinkOnceODRLinkage; | 306 | return LLVMLinkOnceODRLinkage; |
| ... | @@ -522,7 +523,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -522,7 +523,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 522 | } | 523 | } |
| 523 | 524 | ||
| 524 | 525 | ||
| 525 | LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage)); | 526 | LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage, fn->body_node == nullptr)); |
| 526 | 527 | ||
| 527 | if (linkage == GlobalLinkageIdInternal) { | 528 | if (linkage == GlobalLinkageIdInternal) { |
| 528 | LLVMSetUnnamedAddr(llvm_fn, true); | 529 | LLVMSetUnnamedAddr(llvm_fn, true); |
| ... | @@ -7963,7 +7964,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -7963,7 +7964,7 @@ static void do_code_gen(CodeGen *g) { |
| 7963 | global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); | 7964 | global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); |
| 7964 | // TODO debug info for the extern variable | 7965 | // TODO debug info for the extern variable |
| 7965 | 7966 | ||
| 7966 | LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); | 7967 | LLVMSetLinkage(global_value, to_llvm_linkage(linkage, true)); |
| 7967 | maybe_import_dll(g, global_value, GlobalLinkageIdStrong); | 7968 | maybe_import_dll(g, global_value, GlobalLinkageIdStrong); |
| 7968 | LLVMSetAlignment(global_value, var->align_bytes); | 7969 | LLVMSetAlignment(global_value, var->align_bytes); |
| 7969 | LLVMSetGlobalConstant(global_value, var->gen_is_const); | 7970 | LLVMSetGlobalConstant(global_value, var->gen_is_const); |
| ... | @@ -7976,7 +7977,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -7976,7 +7977,7 @@ static void do_code_gen(CodeGen *g) { |
| 7976 | global_value = var->const_value->llvm_global; | 7977 | global_value = var->const_value->llvm_global; |
| 7977 | 7978 | ||
| 7978 | if (exported) { | 7979 | if (exported) { |
| 7979 | LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); | 7980 | LLVMSetLinkage(global_value, to_llvm_linkage(linkage, false)); |
| 7980 | maybe_export_dll(g, global_value, GlobalLinkageIdStrong); | 7981 | maybe_export_dll(g, global_value, GlobalLinkageIdStrong); |
| 7981 | } | 7982 | } |
| 7982 | if (var->section_name) { | 7983 | if (var->section_name) { |
src/ir.cpp+120-50| ... | @@ -25679,37 +25679,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy | ... | @@ -25679,37 +25679,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25679 | struct_field_val->type = type_info_struct_field_type; | 25679 | struct_field_val->type = type_info_struct_field_type; |
| 25680 | 25680 | ||
| 25681 | ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4); | 25681 | ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4); |
| 25682 | inner_fields[1]->special = ConstValSpecialStatic; | ||
| 25683 | inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); | ||
| 25684 | |||
| 25685 | ZigType *field_type = resolve_struct_field_type(ira->codegen, struct_field); | ||
| 25686 | if (field_type == nullptr) | ||
| 25687 | return ErrorSemanticAnalyzeFail; | ||
| 25688 | if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown))) | ||
| 25689 | return err; | ||
| 25690 | if (!type_has_bits(ira->codegen, struct_field->type_entry)) { | ||
| 25691 | inner_fields[1]->data.x_optional = nullptr; | ||
| 25692 | } else { | ||
| 25693 | size_t byte_offset = struct_field->offset; | ||
| 25694 | inner_fields[1]->data.x_optional = ira->codegen->pass1_arena->create<ZigValue>(); | ||
| 25695 | inner_fields[1]->data.x_optional->special = ConstValSpecialStatic; | ||
| 25696 | inner_fields[1]->data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; | ||
| 25697 | bigint_init_unsigned(&inner_fields[1]->data.x_optional->data.x_bigint, byte_offset); | ||
| 25698 | } | ||
| 25699 | 25682 | ||
| 25700 | inner_fields[2]->special = ConstValSpecialStatic; | 25683 | inner_fields[1]->special = ConstValSpecialStatic; |
| 25701 | inner_fields[2]->type = ira->codegen->builtin_types.entry_type; | 25684 | inner_fields[1]->type = ira->codegen->builtin_types.entry_type; |
| 25702 | inner_fields[2]->data.x_type = struct_field->type_entry; | 25685 | inner_fields[1]->data.x_type = struct_field->type_entry; |
| 25703 | 25686 | ||
| 25704 | // default_value: anytype | 25687 | // default_value: anytype |
| 25705 | inner_fields[3]->special = ConstValSpecialStatic; | 25688 | inner_fields[2]->special = ConstValSpecialStatic; |
| 25706 | inner_fields[3]->type = get_optional_type2(ira->codegen, struct_field->type_entry); | 25689 | inner_fields[2]->type = get_optional_type2(ira->codegen, struct_field->type_entry); |
| 25707 | if (inner_fields[3]->type == nullptr) return ErrorSemanticAnalyzeFail; | 25690 | if (inner_fields[2]->type == nullptr) return ErrorSemanticAnalyzeFail; |
| 25708 | memoize_field_init_val(ira->codegen, type_entry, struct_field); | 25691 | memoize_field_init_val(ira->codegen, type_entry, struct_field); |
| 25709 | if(struct_field->init_val != nullptr && type_is_invalid(struct_field->init_val->type)){ | 25692 | if(struct_field->init_val != nullptr && type_is_invalid(struct_field->init_val->type)){ |
| 25710 | return ErrorSemanticAnalyzeFail; | 25693 | return ErrorSemanticAnalyzeFail; |
| 25711 | } | 25694 | } |
| 25712 | set_optional_payload(inner_fields[3], struct_field->init_val); | 25695 | set_optional_payload(inner_fields[2], struct_field->init_val); |
| 25713 | 25696 | ||
| 25714 | ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; | 25697 | ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; |
| 25715 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); | 25698 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); |
| ... | @@ -25960,6 +25943,36 @@ static ZigType *get_const_field_meta_type_optional(IrAnalyze *ira, AstNode *sour | ... | @@ -25960,6 +25943,36 @@ static ZigType *get_const_field_meta_type_optional(IrAnalyze *ira, AstNode *sour |
| 25960 | return value->data.x_optional->data.x_type; | 25943 | return value->data.x_optional->data.x_type; |
| 25961 | } | 25944 | } |
| 25962 | 25945 | ||
| 25946 | static Error get_const_field_buf(IrAnalyze *ira, AstNode *source_node, ZigValue *struct_value, | ||
| 25947 | const char *name, size_t field_index, Buf *out) | ||
| 25948 | { | ||
| 25949 | ZigValue *slice = get_const_field(ira, source_node, struct_value, name, field_index); | ||
| 25950 | ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index]; | ||
| 25951 | ZigValue *len = slice->data.x_struct.fields[slice_len_index]; | ||
| 25952 | assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); | ||
| 25953 | assert(ptr->data.x_ptr.data.base_array.elem_index == 0); | ||
| 25954 | ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val; | ||
| 25955 | assert(arr->special == ConstValSpecialStatic); | ||
| 25956 | switch (arr->data.x_array.special) { | ||
| 25957 | case ConstArraySpecialUndef: | ||
| 25958 | return ErrorSemanticAnalyzeFail; | ||
| 25959 | case ConstArraySpecialNone: { | ||
| 25960 | buf_resize(out, 0); | ||
| 25961 | size_t count = bigint_as_usize(&len->data.x_bigint); | ||
| 25962 | for (size_t j = 0; j < count; j++) { | ||
| 25963 | ZigValue *ch_val = &arr->data.x_array.data.s_none.elements[j]; | ||
| 25964 | unsigned ch = bigint_as_u32(&ch_val->data.x_bigint); | ||
| 25965 | buf_append_char(out, ch); | ||
| 25966 | } | ||
| 25967 | break; | ||
| 25968 | } | ||
| 25969 | case ConstArraySpecialBuf: | ||
| 25970 | buf_init_from_buf(out, arr->data.x_array.data.s_buf); | ||
| 25971 | break; | ||
| 25972 | } | ||
| 25973 | return ErrorNone; | ||
| 25974 | } | ||
| 25975 | |||
| 25963 | static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeId tagTypeId, ZigValue *payload) { | 25976 | static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeId tagTypeId, ZigValue *payload) { |
| 25964 | Error err; | 25977 | Error err; |
| 25965 | switch (tagTypeId) { | 25978 | switch (tagTypeId) { |
| ... | @@ -26163,30 +26176,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26163,30 +26176,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26163 | assert(error->type == ir_type_info_get_type(ira, "Error", nullptr)); | 26176 | assert(error->type == ir_type_info_get_type(ira, "Error", nullptr)); |
| 26164 | ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>(); | 26177 | ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>(); |
| 26165 | err_entry->decl_node = source_instr->source_node; | 26178 | err_entry->decl_node = source_instr->source_node; |
| 26166 | ZigValue *name_slice = get_const_field(ira, source_instr->source_node, error, "name", 0); | 26179 | Error err; |
| 26167 | ZigValue *name_ptr = name_slice->data.x_struct.fields[slice_ptr_index]; | 26180 | if ((err = get_const_field_buf(ira, source_instr->source_node, error, "name", 0, &err_entry->name))) |
| 26168 | ZigValue *name_len = name_slice->data.x_struct.fields[slice_len_index]; | 26181 | return ira->codegen->invalid_inst_gen->value->type; |
| 26169 | assert(name_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); | ||
| 26170 | assert(name_ptr->data.x_ptr.data.base_array.elem_index == 0); | ||
| 26171 | ZigValue *name_arr = name_ptr->data.x_ptr.data.base_array.array_val; | ||
| 26172 | assert(name_arr->special == ConstValSpecialStatic); | ||
| 26173 | switch (name_arr->data.x_array.special) { | ||
| 26174 | case ConstArraySpecialUndef: | ||
| 26175 | return ira->codegen->invalid_inst_gen->value->type; | ||
| 26176 | case ConstArraySpecialNone: { | ||
| 26177 | buf_resize(&err_entry->name, 0); | ||
| 26178 | size_t name_count = bigint_as_usize(&name_len->data.x_bigint); | ||
| 26179 | for (size_t j = 0; j < name_count; j++) { | ||
| 26180 | ZigValue *ch_val = &name_arr->data.x_array.data.s_none.elements[j]; | ||
| 26181 | unsigned ch = bigint_as_u32(&ch_val->data.x_bigint); | ||
| 26182 | buf_append_char(&err_entry->name, ch); | ||
| 26183 | } | ||
| 26184 | break; | ||
| 26185 | } | ||
| 26186 | case ConstArraySpecialBuf: | ||
| 26187 | buf_init_from_buf(&err_entry->name, name_arr->data.x_array.data.s_buf); | ||
| 26188 | break; | ||
| 26189 | } | ||
| 26190 | auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry); | 26182 | auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry); |
| 26191 | if (existing_entry) { | 26183 | if (existing_entry) { |
| 26192 | err_entry->value = existing_entry->value->value; | 26184 | err_entry->value = existing_entry->value->value; |
| ... | @@ -26206,14 +26198,92 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26206,14 +26198,92 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26206 | } | 26198 | } |
| 26207 | return err_set_type; | 26199 | return err_set_type; |
| 26208 | } | 26200 | } |
| 26201 | case ZigTypeIdStruct: { | ||
| 26202 | assert(payload->special == ConstValSpecialStatic); | ||
| 26203 | assert(payload->type == ir_type_info_get_type(ira, "Struct", nullptr)); | ||
| 26204 | |||
| 26205 | ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0); | ||
| 26206 | assert(layout_value->special == ConstValSpecialStatic); | ||
| 26207 | assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr)); | ||
| 26208 | ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag); | ||
| 26209 | |||
| 26210 | ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 1); | ||
| 26211 | assert(fields_value->special == ConstValSpecialStatic); | ||
| 26212 | assert(is_slice(fields_value->type)); | ||
| 26213 | ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index]; | ||
| 26214 | ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index]; | ||
| 26215 | size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint); | ||
| 26216 | |||
| 26217 | ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 2); | ||
| 26218 | assert(decls_value->special == ConstValSpecialStatic); | ||
| 26219 | assert(is_slice(decls_value->type)); | ||
| 26220 | ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index]; | ||
| 26221 | size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint); | ||
| 26222 | if (decls_len != 0) { | ||
| 26223 | ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Struct.decls must be empty for @Type")); | ||
| 26224 | return ira->codegen->invalid_inst_gen->value->type; | ||
| 26225 | } | ||
| 26226 | |||
| 26227 | bool is_tuple; | ||
| 26228 | get_const_field_bool(ira, source_instr->source_node, payload, "is_tuple", 3, &is_tuple); | ||
| 26229 | |||
| 26230 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); | ||
| 26231 | buf_init_from_buf(&entry->name, | ||
| 26232 | get_anon_type_name(ira->codegen, ira->old_irb.exec, "struct", source_instr->scope, source_instr->source_node, &entry->name)); | ||
| 26233 | entry->data.structure.decl_node = source_instr->source_node; | ||
| 26234 | entry->data.structure.fields = alloc_type_struct_fields(fields_len); | ||
| 26235 | entry->data.structure.fields_by_name.init(fields_len); | ||
| 26236 | entry->data.structure.src_field_count = fields_len; | ||
| 26237 | entry->data.structure.layout = layout; | ||
| 26238 | entry->data.structure.special = is_tuple ? StructSpecialInferredTuple : StructSpecialNone; | ||
| 26239 | entry->data.structure.created_by_at_type = true; | ||
| 26240 | entry->data.structure.decls_scope = create_decls_scope(ira->codegen, nullptr, nullptr, entry, entry, &entry->name); | ||
| 26241 | |||
| 26242 | assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); | ||
| 26243 | assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0); | ||
| 26244 | ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val; | ||
| 26245 | assert(fields_arr->special == ConstValSpecialStatic); | ||
| 26246 | assert(fields_arr->data.x_array.special == ConstArraySpecialNone); | ||
| 26247 | for (size_t i = 0; i < fields_len; i++) { | ||
| 26248 | ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i]; | ||
| 26249 | assert(field_value->type == ir_type_info_get_type(ira, "StructField", nullptr)); | ||
| 26250 | TypeStructField *field = entry->data.structure.fields[i]; | ||
| 26251 | field->name = buf_alloc(); | ||
| 26252 | if ((err = get_const_field_buf(ira, source_instr->source_node, field_value, "name", 0, field->name))) | ||
| 26253 | return ira->codegen->invalid_inst_gen->value->type; | ||
| 26254 | field->decl_node = source_instr->source_node; | ||
| 26255 | ZigValue *type_value = get_const_field(ira, source_instr->source_node, field_value, "field_type", 1); | ||
| 26256 | field->type_val = type_value; | ||
| 26257 | field->type_entry = type_value->data.x_type; | ||
| 26258 | if (entry->data.structure.fields_by_name.put_unique(field->name, field) != nullptr) { | ||
| 26259 | ir_add_error(ira, source_instr, buf_sprintf("duplicate struct field '%s'", buf_ptr(field->name))); | ||
| 26260 | return ira->codegen->invalid_inst_gen->value->type; | ||
| 26261 | } | ||
| 26262 | ZigValue *default_value = get_const_field(ira, source_instr->source_node, field_value, "default_value", 2); | ||
| 26263 | if (default_value->type->id == ZigTypeIdNull) { | ||
| 26264 | field->init_val = nullptr; | ||
| 26265 | } else if (default_value->type->id == ZigTypeIdOptional && default_value->type->data.maybe.child_type == field->type_entry) { | ||
| 26266 | field->init_val = default_value->data.x_optional; | ||
| 26267 | } else if (default_value->type == field->type_entry) { | ||
| 26268 | field->init_val = default_value; | ||
| 26269 | } else { | ||
| 26270 | ir_add_error(ira, source_instr, | ||
| 26271 | buf_sprintf("default_value of field '%s' is of type '%s', expected '%s' or '?%s'", | ||
| 26272 | buf_ptr(field->name), buf_ptr(&default_value->type->name), | ||
| 26273 | buf_ptr(&field->type_entry->name), buf_ptr(&field->type_entry->name))); | ||
| 26274 | return ira->codegen->invalid_inst_gen->value->type; | ||
| 26275 | } | ||
| 26276 | } | ||
| 26277 | |||
| 26278 | return entry; | ||
| 26279 | } | ||
| 26209 | case ZigTypeIdEnum: | 26280 | case ZigTypeIdEnum: |
| 26281 | case ZigTypeIdUnion: | ||
| 26210 | ir_add_error(ira, source_instr, buf_sprintf( | 26282 | ir_add_error(ira, source_instr, buf_sprintf( |
| 26211 | "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); | 26283 | "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); |
| 26212 | return ira->codegen->invalid_inst_gen->value->type; | 26284 | return ira->codegen->invalid_inst_gen->value->type; |
| 26213 | case ZigTypeIdUnion: | ||
| 26214 | case ZigTypeIdFn: | 26285 | case ZigTypeIdFn: |
| 26215 | case ZigTypeIdBoundFn: | 26286 | case ZigTypeIdBoundFn: |
| 26216 | case ZigTypeIdStruct: | ||
| 26217 | ir_add_error(ira, source_instr, buf_sprintf( | 26287 | ir_add_error(ira, source_instr, buf_sprintf( |
| 26218 | "@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId))); | 26288 | "@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId))); |
| 26219 | return ira->codegen->invalid_inst_gen->value->type; | 26289 | return ira->codegen->invalid_inst_gen->value->type; |
src/parser.cpp+3| ... | @@ -680,6 +680,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -680,6 +680,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 680 | AstNode *var_decl = ast_parse_var_decl(pc); | 680 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 681 | if (var_decl != nullptr) { | 681 | if (var_decl != nullptr) { |
| 682 | assert(var_decl->type == NodeTypeVariableDeclaration); | 682 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 683 | if (first->id == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) { | ||
| 684 | ast_error(pc, first, "extern variables have no initializers"); | ||
| 685 | } | ||
| 683 | var_decl->line = first->start_line; | 686 | var_decl->line = first->start_line; |
| 684 | var_decl->column = first->start_column; | 687 | var_decl->column = first->start_column; |
| 685 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; | 688 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; |
test/compile_errors.zig+9-3| ... | @@ -2,6 +2,12 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,12 @@ const tests = @import("tests.zig"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("reject extern variables with initializers", | ||
| 6 | \\extern var foo: int = 2; | ||
| 7 | , &[_][]const u8{ | ||
| 8 | "tmp.zig:1:1: error: extern variables have no initializers", | ||
| 9 | }); | ||
| 10 | |||
| 5 | cases.addTest("duplicate/unused labels", | 11 | cases.addTest("duplicate/unused labels", |
| 6 | \\comptime { | 12 | \\comptime { |
| 7 | \\ blk: { blk: while (false) {} } | 13 | \\ blk: { blk: while (false) {} } |
| ... | @@ -1395,12 +1401,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -1395,12 +1401,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1395 | "tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'", | 1401 | "tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'", |
| 1396 | }); | 1402 | }); |
| 1397 | 1403 | ||
| 1398 | cases.add("Struct unavailable for @Type", | 1404 | cases.add("struct with declarations unavailable for @Type", |
| 1399 | \\export fn entry() void { | 1405 | \\export fn entry() void { |
| 1400 | \\ _ = @Type(@typeInfo(struct { })); | 1406 | \\ _ = @Type(@typeInfo(struct { const foo = 1; })); |
| 1401 | \\} | 1407 | \\} |
| 1402 | , &[_][]const u8{ | 1408 | , &[_][]const u8{ |
| 1403 | "tmp.zig:2:15: error: @Type not available for 'TypeInfo.Struct'", | 1409 | "tmp.zig:2:15: error: TypeInfo.Struct.decls must be empty for @Type", |
| 1404 | }); | 1410 | }); |
| 1405 | 1411 | ||
| 1406 | cases.add("wrong type for argument tuple to @asyncCall", | 1412 | cases.add("wrong type for argument tuple to @asyncCall", |
test/run_translated_c.zig+14| ... | @@ -3,6 +3,20 @@ const tests = @import("tests.zig"); | ... | @@ -3,6 +3,20 @@ const tests = @import("tests.zig"); |
| 3 | const nl = std.cstr.line_sep; | 3 | const nl = std.cstr.line_sep; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.RunTranslatedCContext) void { | 5 | pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 6 | cases.add("static variable in block scope", | ||
| 7 | \\#include <stdlib.h> | ||
| 8 | \\int foo() { | ||
| 9 | \\ static int bar; | ||
| 10 | \\ bar += 1; | ||
| 11 | \\ return bar; | ||
| 12 | \\} | ||
| 13 | \\int main() { | ||
| 14 | \\ foo(); | ||
| 15 | \\ foo(); | ||
| 16 | \\ if (foo() != 3) abort(); | ||
| 17 | \\} | ||
| 18 | , ""); | ||
| 19 | |||
| 6 | cases.add("array initializer", | 20 | cases.add("array initializer", |
| 7 | \\#include <stdlib.h> | 21 | \\#include <stdlib.h> |
| 8 | \\int main(int argc, char **argv) { | 22 | \\int main(int argc, char **argv) { |
test/stack_traces.zig+3-3| ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 282 | \\source.zig:10:8: [address] in main (test) | 282 | \\source.zig:10:8: [address] in main (test) |
| 283 | \\ foo(); | 283 | \\ foo(); |
| 284 | \\ ^ | 284 | \\ ^ |
| 285 | \\start.zig:249:29: [address] in std.start.posixCallMainAndExit (test) | 285 | \\start.zig:254:29: [address] in std.start.posixCallMainAndExit (test) |
| 286 | \\ return root.main(); | 286 | \\ return root.main(); |
| 287 | \\ ^ | 287 | \\ ^ |
| 288 | \\start.zig:123:5: [address] in std.start._start (test) | 288 | \\start.zig:128:5: [address] in std.start._start (test) |
| 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); | 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 290 | \\ ^ | 290 | \\ ^ |
| 291 | \\ | 291 | \\ |
| ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 294 | switch (std.Target.current.cpu.arch) { | 294 | switch (std.Target.current.cpu.arch) { |
| 295 | .aarch64 => "", // TODO disabled; results in segfault | 295 | .aarch64 => "", // TODO disabled; results in segfault |
| 296 | else => | 296 | else => |
| 297 | \\start.zig:123:5: [address] in std.start._start (test) | 297 | \\start.zig:128:5: [address] in std.start._start (test) |
| 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); | 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 299 | \\ ^ | 299 | \\ ^ |
| 300 | \\ | 300 | \\ |
test/stage1/behavior/type.zig+44| ... | @@ -236,3 +236,47 @@ test "Type.ErrorSet" { | ... | @@ -236,3 +236,47 @@ test "Type.ErrorSet" { |
| 236 | _ = @Type(@typeInfo(error{A})); | 236 | _ = @Type(@typeInfo(error{A})); |
| 237 | _ = @Type(@typeInfo(error{ A, B, C })); | 237 | _ = @Type(@typeInfo(error{ A, B, C })); |
| 238 | } | 238 | } |
| 239 | |||
| 240 | test "Type.Struct" { | ||
| 241 | const A = @Type(@typeInfo(struct { x: u8, y: u32 })); | ||
| 242 | const infoA = @typeInfo(A).Struct; | ||
| 243 | testing.expectEqual(TypeInfo.ContainerLayout.Auto, infoA.layout); | ||
| 244 | testing.expectEqualSlices(u8, "x", infoA.fields[0].name); | ||
| 245 | testing.expectEqual(u8, infoA.fields[0].field_type); | ||
| 246 | testing.expectEqual(@as(?u8, null), infoA.fields[0].default_value); | ||
| 247 | testing.expectEqualSlices(u8, "y", infoA.fields[1].name); | ||
| 248 | testing.expectEqual(u32, infoA.fields[1].field_type); | ||
| 249 | testing.expectEqual(@as(?u32, null), infoA.fields[1].default_value); | ||
| 250 | testing.expectEqualSlices(TypeInfo.Declaration, &[_]TypeInfo.Declaration{}, infoA.decls); | ||
| 251 | testing.expectEqual(@as(bool, false), infoA.is_tuple); | ||
| 252 | |||
| 253 | var a = A{ .x = 0, .y = 1 }; | ||
| 254 | testing.expectEqual(@as(u8, 0), a.x); | ||
| 255 | testing.expectEqual(@as(u32, 1), a.y); | ||
| 256 | a.y += 1; | ||
| 257 | testing.expectEqual(@as(u32, 2), a.y); | ||
| 258 | |||
| 259 | const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 })); | ||
| 260 | const infoB = @typeInfo(B).Struct; | ||
| 261 | testing.expectEqual(TypeInfo.ContainerLayout.Extern, infoB.layout); | ||
| 262 | testing.expectEqualSlices(u8, "x", infoB.fields[0].name); | ||
| 263 | testing.expectEqual(u8, infoB.fields[0].field_type); | ||
| 264 | testing.expectEqual(@as(?u8, null), infoB.fields[0].default_value); | ||
| 265 | testing.expectEqualSlices(u8, "y", infoB.fields[1].name); | ||
| 266 | testing.expectEqual(u32, infoB.fields[1].field_type); | ||
| 267 | testing.expectEqual(@as(?u32, 5), infoB.fields[1].default_value); | ||
| 268 | testing.expectEqual(@as(usize, 0), infoB.decls.len); | ||
| 269 | testing.expectEqual(@as(bool, false), infoB.is_tuple); | ||
| 270 | |||
| 271 | const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 })); | ||
| 272 | const infoC = @typeInfo(C).Struct; | ||
| 273 | testing.expectEqual(TypeInfo.ContainerLayout.Packed, infoC.layout); | ||
| 274 | testing.expectEqualSlices(u8, "x", infoC.fields[0].name); | ||
| 275 | testing.expectEqual(u8, infoC.fields[0].field_type); | ||
| 276 | testing.expectEqual(@as(?u8, 3), infoC.fields[0].default_value); | ||
| 277 | testing.expectEqualSlices(u8, "y", infoC.fields[1].name); | ||
| 278 | testing.expectEqual(u32, infoC.fields[1].field_type); | ||
| 279 | testing.expectEqual(@as(?u32, 5), infoC.fields[1].default_value); | ||
| 280 | testing.expectEqual(@as(usize, 0), infoC.decls.len); | ||
| 281 | testing.expectEqual(@as(bool, false), infoC.is_tuple); | ||
| 282 | } |
test/stage1/behavior/type_info.zig-11| ... | @@ -238,7 +238,6 @@ fn testStruct() void { | ... | @@ -238,7 +238,6 @@ fn testStruct() void { |
| 238 | expect(struct_info == .Struct); | 238 | expect(struct_info == .Struct); |
| 239 | expect(struct_info.Struct.layout == .Packed); | 239 | expect(struct_info.Struct.layout == .Packed); |
| 240 | expect(struct_info.Struct.fields.len == 4); | 240 | expect(struct_info.Struct.fields.len == 4); |
| 241 | expect(struct_info.Struct.fields[1].offset == null); | ||
| 242 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); | 241 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); |
| 243 | expect(struct_info.Struct.fields[2].default_value == null); | 242 | expect(struct_info.Struct.fields[2].default_value == null); |
| 244 | expect(struct_info.Struct.fields[3].default_value.? == 4); | 243 | expect(struct_info.Struct.fields[3].default_value.? == 4); |
| ... | @@ -320,16 +319,6 @@ fn testAnyFrame() void { | ... | @@ -320,16 +319,6 @@ fn testAnyFrame() void { |
| 320 | } | 319 | } |
| 321 | } | 320 | } |
| 322 | 321 | ||
| 323 | test "type info: optional field unwrapping" { | ||
| 324 | const Struct = struct { | ||
| 325 | cdOffset: u32, | ||
| 326 | }; | ||
| 327 | |||
| 328 | const field = @typeInfo(Struct).Struct.fields[0]; | ||
| 329 | |||
| 330 | _ = field.offset orelse 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | test "type info: pass to function" { | 322 | test "type info: pass to function" { |
| 334 | _ = passTypeInfo(@typeInfo(void)); | 323 | _ = passTypeInfo(@typeInfo(void)); |
| 335 | _ = comptime passTypeInfo(@typeInfo(void)); | 324 | _ = comptime passTypeInfo(@typeInfo(void)); |
test/stage2/compare_output.zig deleted-578| ... | @@ -1,578 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; | ||
| 3 | // self-hosted does not yet support PE executable files / COFF object files | ||
| 4 | // or mach-o files. So we do these test cases cross compiling for x86_64-linux. | ||
| 5 | const linux_x64 = std.zig.CrossTarget{ | ||
| 6 | .cpu_arch = .x86_64, | ||
| 7 | .os_tag = .linux, | ||
| 8 | }; | ||
| 9 | |||
| 10 | const linux_riscv64 = std.zig.CrossTarget{ | ||
| 11 | .cpu_arch = .riscv64, | ||
| 12 | .os_tag = .linux, | ||
| 13 | }; | ||
| 14 | |||
| 15 | const wasi = std.zig.CrossTarget{ | ||
| 16 | .cpu_arch = .wasm32, | ||
| 17 | .os_tag = .wasi, | ||
| 18 | }; | ||
| 19 | |||
| 20 | pub fn addCases(ctx: *TestContext) !void { | ||
| 21 | { | ||
| 22 | var case = ctx.exe("hello world with updates", linux_x64); | ||
| 23 | |||
| 24 | case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); | ||
| 25 | |||
| 26 | case.addError( | ||
| 27 | \\export fn _start() noreturn { | ||
| 28 | \\} | ||
| 29 | , &[_][]const u8{":2:1: error: expected noreturn, found void"}); | ||
| 30 | |||
| 31 | // Regular old hello world | ||
| 32 | case.addCompareOutput( | ||
| 33 | \\export fn _start() noreturn { | ||
| 34 | \\ print(); | ||
| 35 | \\ | ||
| 36 | \\ exit(); | ||
| 37 | \\} | ||
| 38 | \\ | ||
| 39 | \\fn print() void { | ||
| 40 | \\ asm volatile ("syscall" | ||
| 41 | \\ : | ||
| 42 | \\ : [number] "{rax}" (1), | ||
| 43 | \\ [arg1] "{rdi}" (1), | ||
| 44 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 45 | \\ [arg3] "{rdx}" (14) | ||
| 46 | \\ : "rcx", "r11", "memory" | ||
| 47 | \\ ); | ||
| 48 | \\ return; | ||
| 49 | \\} | ||
| 50 | \\ | ||
| 51 | \\fn exit() noreturn { | ||
| 52 | \\ asm volatile ("syscall" | ||
| 53 | \\ : | ||
| 54 | \\ : [number] "{rax}" (231), | ||
| 55 | \\ [arg1] "{rdi}" (0) | ||
| 56 | \\ : "rcx", "r11", "memory" | ||
| 57 | \\ ); | ||
| 58 | \\ unreachable; | ||
| 59 | \\} | ||
| 60 | , | ||
| 61 | "Hello, World!\n", | ||
| 62 | ); | ||
| 63 | // Now change the message only | ||
| 64 | case.addCompareOutput( | ||
| 65 | \\export fn _start() noreturn { | ||
| 66 | \\ print(); | ||
| 67 | \\ | ||
| 68 | \\ exit(); | ||
| 69 | \\} | ||
| 70 | \\ | ||
| 71 | \\fn print() void { | ||
| 72 | \\ asm volatile ("syscall" | ||
| 73 | \\ : | ||
| 74 | \\ : [number] "{rax}" (1), | ||
| 75 | \\ [arg1] "{rdi}" (1), | ||
| 76 | \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")), | ||
| 77 | \\ [arg3] "{rdx}" (104) | ||
| 78 | \\ : "rcx", "r11", "memory" | ||
| 79 | \\ ); | ||
| 80 | \\ return; | ||
| 81 | \\} | ||
| 82 | \\ | ||
| 83 | \\fn exit() noreturn { | ||
| 84 | \\ asm volatile ("syscall" | ||
| 85 | \\ : | ||
| 86 | \\ : [number] "{rax}" (231), | ||
| 87 | \\ [arg1] "{rdi}" (0) | ||
| 88 | \\ : "rcx", "r11", "memory" | ||
| 89 | \\ ); | ||
| 90 | \\ unreachable; | ||
| 91 | \\} | ||
| 92 | , | ||
| 93 | "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n", | ||
| 94 | ); | ||
| 95 | // Now we print it twice. | ||
| 96 | case.addCompareOutput( | ||
| 97 | \\export fn _start() noreturn { | ||
| 98 | \\ print(); | ||
| 99 | \\ print(); | ||
| 100 | \\ | ||
| 101 | \\ exit(); | ||
| 102 | \\} | ||
| 103 | \\ | ||
| 104 | \\fn print() void { | ||
| 105 | \\ asm volatile ("syscall" | ||
| 106 | \\ : | ||
| 107 | \\ : [number] "{rax}" (1), | ||
| 108 | \\ [arg1] "{rdi}" (1), | ||
| 109 | \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")), | ||
| 110 | \\ [arg3] "{rdx}" (104) | ||
| 111 | \\ : "rcx", "r11", "memory" | ||
| 112 | \\ ); | ||
| 113 | \\ return; | ||
| 114 | \\} | ||
| 115 | \\ | ||
| 116 | \\fn exit() noreturn { | ||
| 117 | \\ asm volatile ("syscall" | ||
| 118 | \\ : | ||
| 119 | \\ : [number] "{rax}" (231), | ||
| 120 | \\ [arg1] "{rdi}" (0) | ||
| 121 | \\ : "rcx", "r11", "memory" | ||
| 122 | \\ ); | ||
| 123 | \\ unreachable; | ||
| 124 | \\} | ||
| 125 | , | ||
| 126 | \\What is up? This is a longer message that will force the data to be relocated in virtual address space. | ||
| 127 | \\What is up? This is a longer message that will force the data to be relocated in virtual address space. | ||
| 128 | \\ | ||
| 129 | ); | ||
| 130 | } | ||
| 131 | |||
| 132 | { | ||
| 133 | var case = ctx.exe("hello world", linux_riscv64); | ||
| 134 | // Regular old hello world | ||
| 135 | case.addCompareOutput( | ||
| 136 | \\export fn _start() noreturn { | ||
| 137 | \\ print(); | ||
| 138 | \\ | ||
| 139 | \\ exit(); | ||
| 140 | \\} | ||
| 141 | \\ | ||
| 142 | \\fn print() void { | ||
| 143 | \\ asm volatile ("ecall" | ||
| 144 | \\ : | ||
| 145 | \\ : [number] "{a7}" (64), | ||
| 146 | \\ [arg1] "{a0}" (1), | ||
| 147 | \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")), | ||
| 148 | \\ [arg3] "{a2}" ("Hello, World!\n".len) | ||
| 149 | \\ : "rcx", "r11", "memory" | ||
| 150 | \\ ); | ||
| 151 | \\ return; | ||
| 152 | \\} | ||
| 153 | \\ | ||
| 154 | \\fn exit() noreturn { | ||
| 155 | \\ asm volatile ("ecall" | ||
| 156 | \\ : | ||
| 157 | \\ : [number] "{a7}" (94), | ||
| 158 | \\ [arg1] "{a0}" (0) | ||
| 159 | \\ : "rcx", "r11", "memory" | ||
| 160 | \\ ); | ||
| 161 | \\ unreachable; | ||
| 162 | \\} | ||
| 163 | , | ||
| 164 | "Hello, World!\n", | ||
| 165 | ); | ||
| 166 | } | ||
| 167 | |||
| 168 | { | ||
| 169 | var case = ctx.exe("adding numbers at comptime", linux_x64); | ||
| 170 | case.addCompareOutput( | ||
| 171 | \\export fn _start() noreturn { | ||
| 172 | \\ asm volatile ("syscall" | ||
| 173 | \\ : | ||
| 174 | \\ : [number] "{rax}" (1), | ||
| 175 | \\ [arg1] "{rdi}" (1), | ||
| 176 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 177 | \\ [arg3] "{rdx}" (10 + 4) | ||
| 178 | \\ : "rcx", "r11", "memory" | ||
| 179 | \\ ); | ||
| 180 | \\ asm volatile ("syscall" | ||
| 181 | \\ : | ||
| 182 | \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)), | ||
| 183 | \\ [arg1] "{rdi}" (0) | ||
| 184 | \\ : "rcx", "r11", "memory" | ||
| 185 | \\ ); | ||
| 186 | \\ unreachable; | ||
| 187 | \\} | ||
| 188 | , | ||
| 189 | "Hello, World!\n", | ||
| 190 | ); | ||
| 191 | } | ||
| 192 | |||
| 193 | { | ||
| 194 | var case = ctx.exe("adding numbers at runtime", linux_x64); | ||
| 195 | case.addCompareOutput( | ||
| 196 | \\export fn _start() noreturn { | ||
| 197 | \\ add(3, 4); | ||
| 198 | \\ | ||
| 199 | \\ exit(); | ||
| 200 | \\} | ||
| 201 | \\ | ||
| 202 | \\fn add(a: u32, b: u32) void { | ||
| 203 | \\ if (a + b != 7) unreachable; | ||
| 204 | \\} | ||
| 205 | \\ | ||
| 206 | \\fn exit() noreturn { | ||
| 207 | \\ asm volatile ("syscall" | ||
| 208 | \\ : | ||
| 209 | \\ : [number] "{rax}" (231), | ||
| 210 | \\ [arg1] "{rdi}" (0) | ||
| 211 | \\ : "rcx", "r11", "memory" | ||
| 212 | \\ ); | ||
| 213 | \\ unreachable; | ||
| 214 | \\} | ||
| 215 | , | ||
| 216 | "", | ||
| 217 | ); | ||
| 218 | } | ||
| 219 | |||
| 220 | { | ||
| 221 | var case = ctx.exe("substracting numbers at runtime", linux_x64); | ||
| 222 | case.addCompareOutput( | ||
| 223 | \\export fn _start() noreturn { | ||
| 224 | \\ sub(7, 4); | ||
| 225 | \\ | ||
| 226 | \\ exit(); | ||
| 227 | \\} | ||
| 228 | \\ | ||
| 229 | \\fn sub(a: u32, b: u32) void { | ||
| 230 | \\ if (a - b != 3) unreachable; | ||
| 231 | \\} | ||
| 232 | \\ | ||
| 233 | \\fn exit() noreturn { | ||
| 234 | \\ asm volatile ("syscall" | ||
| 235 | \\ : | ||
| 236 | \\ : [number] "{rax}" (231), | ||
| 237 | \\ [arg1] "{rdi}" (0) | ||
| 238 | \\ : "rcx", "r11", "memory" | ||
| 239 | \\ ); | ||
| 240 | \\ unreachable; | ||
| 241 | \\} | ||
| 242 | , | ||
| 243 | "", | ||
| 244 | ); | ||
| 245 | } | ||
| 246 | |||
| 247 | { | ||
| 248 | var case = ctx.exe("assert function", linux_x64); | ||
| 249 | case.addCompareOutput( | ||
| 250 | \\export fn _start() noreturn { | ||
| 251 | \\ add(3, 4); | ||
| 252 | \\ | ||
| 253 | \\ exit(); | ||
| 254 | \\} | ||
| 255 | \\ | ||
| 256 | \\fn add(a: u32, b: u32) void { | ||
| 257 | \\ assert(a + b == 7); | ||
| 258 | \\} | ||
| 259 | \\ | ||
| 260 | \\pub fn assert(ok: bool) void { | ||
| 261 | \\ if (!ok) unreachable; // assertion failure | ||
| 262 | \\} | ||
| 263 | \\ | ||
| 264 | \\fn exit() noreturn { | ||
| 265 | \\ asm volatile ("syscall" | ||
| 266 | \\ : | ||
| 267 | \\ : [number] "{rax}" (231), | ||
| 268 | \\ [arg1] "{rdi}" (0) | ||
| 269 | \\ : "rcx", "r11", "memory" | ||
| 270 | \\ ); | ||
| 271 | \\ unreachable; | ||
| 272 | \\} | ||
| 273 | , | ||
| 274 | "", | ||
| 275 | ); | ||
| 276 | |||
| 277 | // Tests copying a register. For the `c = a + b`, it has to | ||
| 278 | // preserve both a and b, because they are both used later. | ||
| 279 | case.addCompareOutput( | ||
| 280 | \\export fn _start() noreturn { | ||
| 281 | \\ add(3, 4); | ||
| 282 | \\ | ||
| 283 | \\ exit(); | ||
| 284 | \\} | ||
| 285 | \\ | ||
| 286 | \\fn add(a: u32, b: u32) void { | ||
| 287 | \\ const c = a + b; // 7 | ||
| 288 | \\ const d = a + c; // 10 | ||
| 289 | \\ const e = d + b; // 14 | ||
| 290 | \\ assert(e == 14); | ||
| 291 | \\} | ||
| 292 | \\ | ||
| 293 | \\pub fn assert(ok: bool) void { | ||
| 294 | \\ if (!ok) unreachable; // assertion failure | ||
| 295 | \\} | ||
| 296 | \\ | ||
| 297 | \\fn exit() noreturn { | ||
| 298 | \\ asm volatile ("syscall" | ||
| 299 | \\ : | ||
| 300 | \\ : [number] "{rax}" (231), | ||
| 301 | \\ [arg1] "{rdi}" (0) | ||
| 302 | \\ : "rcx", "r11", "memory" | ||
| 303 | \\ ); | ||
| 304 | \\ unreachable; | ||
| 305 | \\} | ||
| 306 | , | ||
| 307 | "", | ||
| 308 | ); | ||
| 309 | |||
| 310 | // More stress on the liveness detection. | ||
| 311 | case.addCompareOutput( | ||
| 312 | \\export fn _start() noreturn { | ||
| 313 | \\ add(3, 4); | ||
| 314 | \\ | ||
| 315 | \\ exit(); | ||
| 316 | \\} | ||
| 317 | \\ | ||
| 318 | \\fn add(a: u32, b: u32) void { | ||
| 319 | \\ const c = a + b; // 7 | ||
| 320 | \\ const d = a + c; // 10 | ||
| 321 | \\ const e = d + b; // 14 | ||
| 322 | \\ const f = d + e; // 24 | ||
| 323 | \\ const g = e + f; // 38 | ||
| 324 | \\ const h = f + g; // 62 | ||
| 325 | \\ const i = g + h; // 100 | ||
| 326 | \\ assert(i == 100); | ||
| 327 | \\} | ||
| 328 | \\ | ||
| 329 | \\pub fn assert(ok: bool) void { | ||
| 330 | \\ if (!ok) unreachable; // assertion failure | ||
| 331 | \\} | ||
| 332 | \\ | ||
| 333 | \\fn exit() noreturn { | ||
| 334 | \\ asm volatile ("syscall" | ||
| 335 | \\ : | ||
| 336 | \\ : [number] "{rax}" (231), | ||
| 337 | \\ [arg1] "{rdi}" (0) | ||
| 338 | \\ : "rcx", "r11", "memory" | ||
| 339 | \\ ); | ||
| 340 | \\ unreachable; | ||
| 341 | \\} | ||
| 342 | , | ||
| 343 | "", | ||
| 344 | ); | ||
| 345 | |||
| 346 | // Requires a second move. The register allocator should figure out to re-use rax. | ||
| 347 | case.addCompareOutput( | ||
| 348 | \\export fn _start() noreturn { | ||
| 349 | \\ add(3, 4); | ||
| 350 | \\ | ||
| 351 | \\ exit(); | ||
| 352 | \\} | ||
| 353 | \\ | ||
| 354 | \\fn add(a: u32, b: u32) void { | ||
| 355 | \\ const c = a + b; // 7 | ||
| 356 | \\ const d = a + c; // 10 | ||
| 357 | \\ const e = d + b; // 14 | ||
| 358 | \\ const f = d + e; // 24 | ||
| 359 | \\ const g = e + f; // 38 | ||
| 360 | \\ const h = f + g; // 62 | ||
| 361 | \\ const i = g + h; // 100 | ||
| 362 | \\ const j = i + d; // 110 | ||
| 363 | \\ assert(j == 110); | ||
| 364 | \\} | ||
| 365 | \\ | ||
| 366 | \\pub fn assert(ok: bool) void { | ||
| 367 | \\ if (!ok) unreachable; // assertion failure | ||
| 368 | \\} | ||
| 369 | \\ | ||
| 370 | \\fn exit() noreturn { | ||
| 371 | \\ asm volatile ("syscall" | ||
| 372 | \\ : | ||
| 373 | \\ : [number] "{rax}" (231), | ||
| 374 | \\ [arg1] "{rdi}" (0) | ||
| 375 | \\ : "rcx", "r11", "memory" | ||
| 376 | \\ ); | ||
| 377 | \\ unreachable; | ||
| 378 | \\} | ||
| 379 | , | ||
| 380 | "", | ||
| 381 | ); | ||
| 382 | |||
| 383 | // Now we test integer return values. | ||
| 384 | case.addCompareOutput( | ||
| 385 | \\export fn _start() noreturn { | ||
| 386 | \\ assert(add(3, 4) == 7); | ||
| 387 | \\ assert(add(20, 10) == 30); | ||
| 388 | \\ | ||
| 389 | \\ exit(); | ||
| 390 | \\} | ||
| 391 | \\ | ||
| 392 | \\fn add(a: u32, b: u32) u32 { | ||
| 393 | \\ return a + b; | ||
| 394 | \\} | ||
| 395 | \\ | ||
| 396 | \\pub fn assert(ok: bool) void { | ||
| 397 | \\ if (!ok) unreachable; // assertion failure | ||
| 398 | \\} | ||
| 399 | \\ | ||
| 400 | \\fn exit() noreturn { | ||
| 401 | \\ asm volatile ("syscall" | ||
| 402 | \\ : | ||
| 403 | \\ : [number] "{rax}" (231), | ||
| 404 | \\ [arg1] "{rdi}" (0) | ||
| 405 | \\ : "rcx", "r11", "memory" | ||
| 406 | \\ ); | ||
| 407 | \\ unreachable; | ||
| 408 | \\} | ||
| 409 | , | ||
| 410 | "", | ||
| 411 | ); | ||
| 412 | |||
| 413 | // Local mutable variables. | ||
| 414 | case.addCompareOutput( | ||
| 415 | \\export fn _start() noreturn { | ||
| 416 | \\ assert(add(3, 4) == 7); | ||
| 417 | \\ assert(add(20, 10) == 30); | ||
| 418 | \\ | ||
| 419 | \\ exit(); | ||
| 420 | \\} | ||
| 421 | \\ | ||
| 422 | \\fn add(a: u32, b: u32) u32 { | ||
| 423 | \\ var x: u32 = undefined; | ||
| 424 | \\ x = 0; | ||
| 425 | \\ x += a; | ||
| 426 | \\ x += b; | ||
| 427 | \\ return x; | ||
| 428 | \\} | ||
| 429 | \\ | ||
| 430 | \\pub fn assert(ok: bool) void { | ||
| 431 | \\ if (!ok) unreachable; // assertion failure | ||
| 432 | \\} | ||
| 433 | \\ | ||
| 434 | \\fn exit() noreturn { | ||
| 435 | \\ asm volatile ("syscall" | ||
| 436 | \\ : | ||
| 437 | \\ : [number] "{rax}" (231), | ||
| 438 | \\ [arg1] "{rdi}" (0) | ||
| 439 | \\ : "rcx", "r11", "memory" | ||
| 440 | \\ ); | ||
| 441 | \\ unreachable; | ||
| 442 | \\} | ||
| 443 | , | ||
| 444 | "", | ||
| 445 | ); | ||
| 446 | |||
| 447 | // Optionals | ||
| 448 | case.addCompareOutput( | ||
| 449 | \\export fn _start() noreturn { | ||
| 450 | \\ const a: u32 = 2; | ||
| 451 | \\ const b: ?u32 = a; | ||
| 452 | \\ const c = b.?; | ||
| 453 | \\ if (c != 2) unreachable; | ||
| 454 | \\ | ||
| 455 | \\ exit(); | ||
| 456 | \\} | ||
| 457 | \\ | ||
| 458 | \\fn exit() noreturn { | ||
| 459 | \\ asm volatile ("syscall" | ||
| 460 | \\ : | ||
| 461 | \\ : [number] "{rax}" (231), | ||
| 462 | \\ [arg1] "{rdi}" (0) | ||
| 463 | \\ : "rcx", "r11", "memory" | ||
| 464 | \\ ); | ||
| 465 | \\ unreachable; | ||
| 466 | \\} | ||
| 467 | , | ||
| 468 | "", | ||
| 469 | ); | ||
| 470 | |||
| 471 | // While loops | ||
| 472 | case.addCompareOutput( | ||
| 473 | \\export fn _start() noreturn { | ||
| 474 | \\ var i: u32 = 0; | ||
| 475 | \\ while (i < 4) : (i += 1) print(); | ||
| 476 | \\ assert(i == 4); | ||
| 477 | \\ | ||
| 478 | \\ exit(); | ||
| 479 | \\} | ||
| 480 | \\ | ||
| 481 | \\fn print() void { | ||
| 482 | \\ asm volatile ("syscall" | ||
| 483 | \\ : | ||
| 484 | \\ : [number] "{rax}" (1), | ||
| 485 | \\ [arg1] "{rdi}" (1), | ||
| 486 | \\ [arg2] "{rsi}" (@ptrToInt("hello\n")), | ||
| 487 | \\ [arg3] "{rdx}" (6) | ||
| 488 | \\ : "rcx", "r11", "memory" | ||
| 489 | \\ ); | ||
| 490 | \\ return; | ||
| 491 | \\} | ||
| 492 | \\ | ||
| 493 | \\pub fn assert(ok: bool) void { | ||
| 494 | \\ if (!ok) unreachable; // assertion failure | ||
| 495 | \\} | ||
| 496 | \\ | ||
| 497 | \\fn exit() noreturn { | ||
| 498 | \\ asm volatile ("syscall" | ||
| 499 | \\ : | ||
| 500 | \\ : [number] "{rax}" (231), | ||
| 501 | \\ [arg1] "{rdi}" (0) | ||
| 502 | \\ : "rcx", "r11", "memory" | ||
| 503 | \\ ); | ||
| 504 | \\ unreachable; | ||
| 505 | \\} | ||
| 506 | , | ||
| 507 | "hello\nhello\nhello\nhello\n", | ||
| 508 | ); | ||
| 509 | |||
| 510 | // Labeled blocks (no conditional branch) | ||
| 511 | case.addCompareOutput( | ||
| 512 | \\export fn _start() noreturn { | ||
| 513 | \\ assert(add(3, 4) == 20); | ||
| 514 | \\ | ||
| 515 | \\ exit(); | ||
| 516 | \\} | ||
| 517 | \\ | ||
| 518 | \\fn add(a: u32, b: u32) u32 { | ||
| 519 | \\ const x: u32 = blk: { | ||
| 520 | \\ const c = a + b; // 7 | ||
| 521 | \\ const d = a + c; // 10 | ||
| 522 | \\ const e = d + b; // 14 | ||
| 523 | \\ break :blk e; | ||
| 524 | \\ }; | ||
| 525 | \\ const y = x + a; // 17 | ||
| 526 | \\ const z = y + a; // 20 | ||
| 527 | \\ return z; | ||
| 528 | \\} | ||
| 529 | \\ | ||
| 530 | \\pub fn assert(ok: bool) void { | ||
| 531 | \\ if (!ok) unreachable; // assertion failure | ||
| 532 | \\} | ||
| 533 | \\ | ||
| 534 | \\fn exit() noreturn { | ||
| 535 | \\ asm volatile ("syscall" | ||
| 536 | \\ : | ||
| 537 | \\ : [number] "{rax}" (231), | ||
| 538 | \\ [arg1] "{rdi}" (0) | ||
| 539 | \\ : "rcx", "r11", "memory" | ||
| 540 | \\ ); | ||
| 541 | \\ unreachable; | ||
| 542 | \\} | ||
| 543 | , | ||
| 544 | "", | ||
| 545 | ); | ||
| 546 | } | ||
| 547 | |||
| 548 | { | ||
| 549 | var case = ctx.exe("wasm returns", wasi); | ||
| 550 | |||
| 551 | case.addCompareOutput( | ||
| 552 | \\export fn _start() u32 { | ||
| 553 | \\ return 42; | ||
| 554 | \\} | ||
| 555 | , | ||
| 556 | "42\n", | ||
| 557 | ); | ||
| 558 | |||
| 559 | case.addCompareOutput( | ||
| 560 | \\export fn _start() i64 { | ||
| 561 | \\ return 42; | ||
| 562 | \\} | ||
| 563 | , | ||
| 564 | "42\n", | ||
| 565 | ); | ||
| 566 | |||
| 567 | case.addCompareOutput( | ||
| 568 | \\export fn _start() f32 { | ||
| 569 | \\ return 42.0; | ||
| 570 | \\} | ||
| 571 | , | ||
| 572 | // This is what you get when you take the bits of the IEE-754 | ||
| 573 | // representation of 42.0 and reinterpret them as an unsigned | ||
| 574 | // integer. Guess that's a bug in wasmtime. | ||
| 575 | "1109917696\n", | ||
| 576 | ); | ||
| 577 | } | ||
| 578 | } | ||
test/stage2/compile_errors.zig deleted-135| ... | @@ -1,135 +0,0 @@ | ||
| 1 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; | ||
| 2 | const std = @import("std"); | ||
| 3 | |||
| 4 | const ErrorMsg = @import("../../src-self-hosted/Module.zig").ErrorMsg; | ||
| 5 | |||
| 6 | const linux_x64 = std.zig.CrossTarget{ | ||
| 7 | .cpu_arch = .x86_64, | ||
| 8 | .os_tag = .linux, | ||
| 9 | }; | ||
| 10 | |||
| 11 | pub fn addCases(ctx: *TestContext) !void { | ||
| 12 | ctx.compileErrorZIR("call undefined local", linux_x64, | ||
| 13 | \\@noreturn = primitive(noreturn) | ||
| 14 | \\ | ||
| 15 | \\@start_fnty = fntype([], @noreturn, cc=Naked) | ||
| 16 | \\@start = fn(@start_fnty, { | ||
| 17 | \\ %0 = call(%test, []) | ||
| 18 | \\}) | ||
| 19 | // TODO: address inconsistency in this message and the one in the next test | ||
| 20 | , &[_][]const u8{":5:13: error: unrecognized identifier: %test"}); | ||
| 21 | |||
| 22 | ctx.compileErrorZIR("call with non-existent target", linux_x64, | ||
| 23 | \\@noreturn = primitive(noreturn) | ||
| 24 | \\ | ||
| 25 | \\@start_fnty = fntype([], @noreturn, cc=Naked) | ||
| 26 | \\@start = fn(@start_fnty, { | ||
| 27 | \\ %0 = call(@notafunc, []) | ||
| 28 | \\}) | ||
| 29 | \\@0 = str("_start") | ||
| 30 | \\@1 = export(@0, "start") | ||
| 31 | , &[_][]const u8{":5:13: error: decl 'notafunc' not found"}); | ||
| 32 | |||
| 33 | // TODO: this error should occur at the call site, not the fntype decl | ||
| 34 | ctx.compileErrorZIR("call naked function", linux_x64, | ||
| 35 | \\@noreturn = primitive(noreturn) | ||
| 36 | \\ | ||
| 37 | \\@start_fnty = fntype([], @noreturn, cc=Naked) | ||
| 38 | \\@s = fn(@start_fnty, {}) | ||
| 39 | \\@start = fn(@start_fnty, { | ||
| 40 | \\ %0 = call(@s, []) | ||
| 41 | \\}) | ||
| 42 | \\@0 = str("_start") | ||
| 43 | \\@1 = export(@0, "start") | ||
| 44 | , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"}); | ||
| 45 | |||
| 46 | ctx.incrementalFailureZIR("exported symbol collision", linux_x64, | ||
| 47 | \\@noreturn = primitive(noreturn) | ||
| 48 | \\ | ||
| 49 | \\@start_fnty = fntype([], @noreturn) | ||
| 50 | \\@start = fn(@start_fnty, {}) | ||
| 51 | \\ | ||
| 52 | \\@0 = str("_start") | ||
| 53 | \\@1 = export(@0, "start") | ||
| 54 | \\@2 = export(@0, "start") | ||
| 55 | , &[_][]const u8{":8:13: error: exported symbol collision: _start"}, | ||
| 56 | \\@noreturn = primitive(noreturn) | ||
| 57 | \\ | ||
| 58 | \\@start_fnty = fntype([], @noreturn) | ||
| 59 | \\@start = fn(@start_fnty, {}) | ||
| 60 | \\ | ||
| 61 | \\@0 = str("_start") | ||
| 62 | \\@1 = export(@0, "start") | ||
| 63 | ); | ||
| 64 | |||
| 65 | ctx.compileError("function redefinition", linux_x64, | ||
| 66 | \\fn entry() void {} | ||
| 67 | \\fn entry() void {} | ||
| 68 | , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); | ||
| 69 | |||
| 70 | //ctx.incrementalFailure("function redefinition", linux_x64, | ||
| 71 | // \\fn entry() void {} | ||
| 72 | // \\fn entry() void {} | ||
| 73 | //, &[_][]const u8{":2:4: error: redefinition of 'entry'"}, | ||
| 74 | // \\fn entry() void {} | ||
| 75 | //); | ||
| 76 | |||
| 77 | //// TODO: need to make sure this works with other variants of export. | ||
| 78 | //ctx.incrementalFailure("exported symbol collision", linux_x64, | ||
| 79 | // \\export fn entry() void {} | ||
| 80 | // \\export fn entry() void {} | ||
| 81 | //, &[_][]const u8{":2:11: error: redefinition of 'entry'"}, | ||
| 82 | // \\export fn entry() void {} | ||
| 83 | //); | ||
| 84 | |||
| 85 | // ctx.incrementalFailure("missing function name", linux_x64, | ||
| 86 | // \\fn() void {} | ||
| 87 | // , &[_][]const u8{":1:3: error: missing function name"}, | ||
| 88 | // \\fn a() void {} | ||
| 89 | // ); | ||
| 90 | |||
| 91 | // TODO: re-enable these tests. | ||
| 92 | // https://github.com/ziglang/zig/issues/1364 | ||
| 93 | |||
| 94 | //ctx.testCompileError( | ||
| 95 | // \\comptime { | ||
| 96 | // \\ return; | ||
| 97 | // \\} | ||
| 98 | //, "1.zig", 2, 5, "return expression outside function definition"); | ||
| 99 | |||
| 100 | //ctx.testCompileError( | ||
| 101 | // \\export fn entry() void { | ||
| 102 | // \\ defer return; | ||
| 103 | // \\} | ||
| 104 | //, "1.zig", 2, 11, "cannot return from defer expression"); | ||
| 105 | |||
| 106 | //ctx.testCompileError( | ||
| 107 | // \\export fn entry() c_int { | ||
| 108 | // \\ return 36893488147419103232; | ||
| 109 | // \\} | ||
| 110 | //, "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'"); | ||
| 111 | |||
| 112 | //ctx.testCompileError( | ||
| 113 | // \\comptime { | ||
| 114 | // \\ var a: *align(4) align(4) i32 = 0; | ||
| 115 | // \\} | ||
| 116 | //, "1.zig", 2, 22, "Extra align qualifier"); | ||
| 117 | |||
| 118 | //ctx.testCompileError( | ||
| 119 | // \\comptime { | ||
| 120 | // \\ var b: *const const i32 = 0; | ||
| 121 | // \\} | ||
| 122 | //, "1.zig", 2, 19, "Extra align qualifier"); | ||
| 123 | |||
| 124 | //ctx.testCompileError( | ||
| 125 | // \\comptime { | ||
| 126 | // \\ var c: *volatile volatile i32 = 0; | ||
| 127 | // \\} | ||
| 128 | //, "1.zig", 2, 22, "Extra align qualifier"); | ||
| 129 | |||
| 130 | //ctx.testCompileError( | ||
| 131 | // \\comptime { | ||
| 132 | // \\ var d: *allowzero allowzero i32 = 0; | ||
| 133 | // \\} | ||
| 134 | //, "1.zig", 2, 23, "Extra align qualifier"); | ||
| 135 | } | ||
test/stage2/test.zig+730-2| ... | @@ -1,8 +1,736 @@ | ... | @@ -1,8 +1,736 @@ |
| 1 | const std = @import("std"); | ||
| 1 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; | 2 | const TestContext = @import("../../src-self-hosted/test.zig").TestContext; |
| 2 | 3 | ||
| 4 | // self-hosted does not yet support PE executable files / COFF object files | ||
| 5 | // or mach-o files. So we do these test cases cross compiling for x86_64-linux. | ||
| 6 | const linux_x64 = std.zig.CrossTarget{ | ||
| 7 | .cpu_arch = .x86_64, | ||
| 8 | .os_tag = .linux, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const macosx_x64 = std.zig.CrossTarget{ | ||
| 12 | .cpu_arch = .x86_64, | ||
| 13 | .os_tag = .macosx, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const linux_riscv64 = std.zig.CrossTarget{ | ||
| 17 | .cpu_arch = .riscv64, | ||
| 18 | .os_tag = .linux, | ||
| 19 | }; | ||
| 20 | |||
| 21 | const wasi = std.zig.CrossTarget{ | ||
| 22 | .cpu_arch = .wasm32, | ||
| 23 | .os_tag = .wasi, | ||
| 24 | }; | ||
| 25 | |||
| 3 | pub fn addCases(ctx: *TestContext) !void { | 26 | pub fn addCases(ctx: *TestContext) !void { |
| 4 | try @import("compile_errors.zig").addCases(ctx); | ||
| 5 | try @import("compare_output.zig").addCases(ctx); | ||
| 6 | try @import("zir.zig").addCases(ctx); | 27 | try @import("zir.zig").addCases(ctx); |
| 7 | try @import("cbe.zig").addCases(ctx); | 28 | try @import("cbe.zig").addCases(ctx); |
| 29 | { | ||
| 30 | var case = ctx.exe("hello world with updates", linux_x64); | ||
| 31 | |||
| 32 | case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); | ||
| 33 | |||
| 34 | // Incorrect return type | ||
| 35 | case.addError( | ||
| 36 | \\export fn _start() noreturn { | ||
| 37 | \\} | ||
| 38 | , &[_][]const u8{":2:1: error: expected noreturn, found void"}); | ||
| 39 | |||
| 40 | // Regular old hello world | ||
| 41 | case.addCompareOutput( | ||
| 42 | \\export fn _start() noreturn { | ||
| 43 | \\ print(); | ||
| 44 | \\ | ||
| 45 | \\ exit(); | ||
| 46 | \\} | ||
| 47 | \\ | ||
| 48 | \\fn print() void { | ||
| 49 | \\ asm volatile ("syscall" | ||
| 50 | \\ : | ||
| 51 | \\ : [number] "{rax}" (1), | ||
| 52 | \\ [arg1] "{rdi}" (1), | ||
| 53 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 54 | \\ [arg3] "{rdx}" (14) | ||
| 55 | \\ : "rcx", "r11", "memory" | ||
| 56 | \\ ); | ||
| 57 | \\ return; | ||
| 58 | \\} | ||
| 59 | \\ | ||
| 60 | \\fn exit() noreturn { | ||
| 61 | \\ asm volatile ("syscall" | ||
| 62 | \\ : | ||
| 63 | \\ : [number] "{rax}" (231), | ||
| 64 | \\ [arg1] "{rdi}" (0) | ||
| 65 | \\ : "rcx", "r11", "memory" | ||
| 66 | \\ ); | ||
| 67 | \\ unreachable; | ||
| 68 | \\} | ||
| 69 | , | ||
| 70 | "Hello, World!\n", | ||
| 71 | ); | ||
| 72 | // Now change the message only | ||
| 73 | case.addCompareOutput( | ||
| 74 | \\export fn _start() noreturn { | ||
| 75 | \\ print(); | ||
| 76 | \\ | ||
| 77 | \\ exit(); | ||
| 78 | \\} | ||
| 79 | \\ | ||
| 80 | \\fn print() void { | ||
| 81 | \\ asm volatile ("syscall" | ||
| 82 | \\ : | ||
| 83 | \\ : [number] "{rax}" (1), | ||
| 84 | \\ [arg1] "{rdi}" (1), | ||
| 85 | \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")), | ||
| 86 | \\ [arg3] "{rdx}" (104) | ||
| 87 | \\ : "rcx", "r11", "memory" | ||
| 88 | \\ ); | ||
| 89 | \\ return; | ||
| 90 | \\} | ||
| 91 | \\ | ||
| 92 | \\fn exit() noreturn { | ||
| 93 | \\ asm volatile ("syscall" | ||
| 94 | \\ : | ||
| 95 | \\ : [number] "{rax}" (231), | ||
| 96 | \\ [arg1] "{rdi}" (0) | ||
| 97 | \\ : "rcx", "r11", "memory" | ||
| 98 | \\ ); | ||
| 99 | \\ unreachable; | ||
| 100 | \\} | ||
| 101 | , | ||
| 102 | "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n", | ||
| 103 | ); | ||
| 104 | // Now we print it twice. | ||
| 105 | case.addCompareOutput( | ||
| 106 | \\export fn _start() noreturn { | ||
| 107 | \\ print(); | ||
| 108 | \\ print(); | ||
| 109 | \\ | ||
| 110 | \\ exit(); | ||
| 111 | \\} | ||
| 112 | \\ | ||
| 113 | \\fn print() void { | ||
| 114 | \\ asm volatile ("syscall" | ||
| 115 | \\ : | ||
| 116 | \\ : [number] "{rax}" (1), | ||
| 117 | \\ [arg1] "{rdi}" (1), | ||
| 118 | \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")), | ||
| 119 | \\ [arg3] "{rdx}" (104) | ||
| 120 | \\ : "rcx", "r11", "memory" | ||
| 121 | \\ ); | ||
| 122 | \\ return; | ||
| 123 | \\} | ||
| 124 | \\ | ||
| 125 | \\fn exit() noreturn { | ||
| 126 | \\ asm volatile ("syscall" | ||
| 127 | \\ : | ||
| 128 | \\ : [number] "{rax}" (231), | ||
| 129 | \\ [arg1] "{rdi}" (0) | ||
| 130 | \\ : "rcx", "r11", "memory" | ||
| 131 | \\ ); | ||
| 132 | \\ unreachable; | ||
| 133 | \\} | ||
| 134 | , | ||
| 135 | \\What is up? This is a longer message that will force the data to be relocated in virtual address space. | ||
| 136 | \\What is up? This is a longer message that will force the data to be relocated in virtual address space. | ||
| 137 | \\ | ||
| 138 | ); | ||
| 139 | } | ||
| 140 | |||
| 141 | { | ||
| 142 | var case = ctx.exe("hello world", macosx_x64); | ||
| 143 | case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); | ||
| 144 | } | ||
| 145 | |||
| 146 | { | ||
| 147 | var case = ctx.exe("hello world", linux_riscv64); | ||
| 148 | // Regular old hello world | ||
| 149 | case.addCompareOutput( | ||
| 150 | \\export fn _start() noreturn { | ||
| 151 | \\ print(); | ||
| 152 | \\ | ||
| 153 | \\ exit(); | ||
| 154 | \\} | ||
| 155 | \\ | ||
| 156 | \\fn print() void { | ||
| 157 | \\ asm volatile ("ecall" | ||
| 158 | \\ : | ||
| 159 | \\ : [number] "{a7}" (64), | ||
| 160 | \\ [arg1] "{a0}" (1), | ||
| 161 | \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")), | ||
| 162 | \\ [arg3] "{a2}" ("Hello, World!\n".len) | ||
| 163 | \\ : "rcx", "r11", "memory" | ||
| 164 | \\ ); | ||
| 165 | \\ return; | ||
| 166 | \\} | ||
| 167 | \\ | ||
| 168 | \\fn exit() noreturn { | ||
| 169 | \\ asm volatile ("ecall" | ||
| 170 | \\ : | ||
| 171 | \\ : [number] "{a7}" (94), | ||
| 172 | \\ [arg1] "{a0}" (0) | ||
| 173 | \\ : "rcx", "r11", "memory" | ||
| 174 | \\ ); | ||
| 175 | \\ unreachable; | ||
| 176 | \\} | ||
| 177 | , | ||
| 178 | "Hello, World!\n", | ||
| 179 | ); | ||
| 180 | } | ||
| 181 | |||
| 182 | { | ||
| 183 | var case = ctx.exe("adding numbers at comptime", linux_x64); | ||
| 184 | case.addCompareOutput( | ||
| 185 | \\export fn _start() noreturn { | ||
| 186 | \\ asm volatile ("syscall" | ||
| 187 | \\ : | ||
| 188 | \\ : [number] "{rax}" (1), | ||
| 189 | \\ [arg1] "{rdi}" (1), | ||
| 190 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 191 | \\ [arg3] "{rdx}" (10 + 4) | ||
| 192 | \\ : "rcx", "r11", "memory" | ||
| 193 | \\ ); | ||
| 194 | \\ asm volatile ("syscall" | ||
| 195 | \\ : | ||
| 196 | \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)), | ||
| 197 | \\ [arg1] "{rdi}" (0) | ||
| 198 | \\ : "rcx", "r11", "memory" | ||
| 199 | \\ ); | ||
| 200 | \\ unreachable; | ||
| 201 | \\} | ||
| 202 | , | ||
| 203 | "Hello, World!\n", | ||
| 204 | ); | ||
| 205 | } | ||
| 206 | |||
| 207 | { | ||
| 208 | var case = ctx.exe("adding numbers at runtime", linux_x64); | ||
| 209 | case.addCompareOutput( | ||
| 210 | \\export fn _start() noreturn { | ||
| 211 | \\ add(3, 4); | ||
| 212 | \\ | ||
| 213 | \\ exit(); | ||
| 214 | \\} | ||
| 215 | \\ | ||
| 216 | \\fn add(a: u32, b: u32) void { | ||
| 217 | \\ if (a + b != 7) unreachable; | ||
| 218 | \\} | ||
| 219 | \\ | ||
| 220 | \\fn exit() noreturn { | ||
| 221 | \\ asm volatile ("syscall" | ||
| 222 | \\ : | ||
| 223 | \\ : [number] "{rax}" (231), | ||
| 224 | \\ [arg1] "{rdi}" (0) | ||
| 225 | \\ : "rcx", "r11", "memory" | ||
| 226 | \\ ); | ||
| 227 | \\ unreachable; | ||
| 228 | \\} | ||
| 229 | , | ||
| 230 | "", | ||
| 231 | ); | ||
| 232 | } | ||
| 233 | |||
| 234 | { | ||
| 235 | var case = ctx.exe("substracting numbers at runtime", linux_x64); | ||
| 236 | case.addCompareOutput( | ||
| 237 | \\export fn _start() noreturn { | ||
| 238 | \\ sub(7, 4); | ||
| 239 | \\ | ||
| 240 | \\ exit(); | ||
| 241 | \\} | ||
| 242 | \\ | ||
| 243 | \\fn sub(a: u32, b: u32) void { | ||
| 244 | \\ if (a - b != 3) unreachable; | ||
| 245 | \\} | ||
| 246 | \\ | ||
| 247 | \\fn exit() noreturn { | ||
| 248 | \\ asm volatile ("syscall" | ||
| 249 | \\ : | ||
| 250 | \\ : [number] "{rax}" (231), | ||
| 251 | \\ [arg1] "{rdi}" (0) | ||
| 252 | \\ : "rcx", "r11", "memory" | ||
| 253 | \\ ); | ||
| 254 | \\ unreachable; | ||
| 255 | \\} | ||
| 256 | , | ||
| 257 | "", | ||
| 258 | ); | ||
| 259 | } | ||
| 260 | |||
| 261 | { | ||
| 262 | var case = ctx.exe("assert function", linux_x64); | ||
| 263 | case.addCompareOutput( | ||
| 264 | \\export fn _start() noreturn { | ||
| 265 | \\ add(3, 4); | ||
| 266 | \\ | ||
| 267 | \\ exit(); | ||
| 268 | \\} | ||
| 269 | \\ | ||
| 270 | \\fn add(a: u32, b: u32) void { | ||
| 271 | \\ assert(a + b == 7); | ||
| 272 | \\} | ||
| 273 | \\ | ||
| 274 | \\pub fn assert(ok: bool) void { | ||
| 275 | \\ if (!ok) unreachable; // assertion failure | ||
| 276 | \\} | ||
| 277 | \\ | ||
| 278 | \\fn exit() noreturn { | ||
| 279 | \\ asm volatile ("syscall" | ||
| 280 | \\ : | ||
| 281 | \\ : [number] "{rax}" (231), | ||
| 282 | \\ [arg1] "{rdi}" (0) | ||
| 283 | \\ : "rcx", "r11", "memory" | ||
| 284 | \\ ); | ||
| 285 | \\ unreachable; | ||
| 286 | \\} | ||
| 287 | , | ||
| 288 | "", | ||
| 289 | ); | ||
| 290 | |||
| 291 | // Tests copying a register. For the `c = a + b`, it has to | ||
| 292 | // preserve both a and b, because they are both used later. | ||
| 293 | case.addCompareOutput( | ||
| 294 | \\export fn _start() noreturn { | ||
| 295 | \\ add(3, 4); | ||
| 296 | \\ | ||
| 297 | \\ exit(); | ||
| 298 | \\} | ||
| 299 | \\ | ||
| 300 | \\fn add(a: u32, b: u32) void { | ||
| 301 | \\ const c = a + b; // 7 | ||
| 302 | \\ const d = a + c; // 10 | ||
| 303 | \\ const e = d + b; // 14 | ||
| 304 | \\ assert(e == 14); | ||
| 305 | \\} | ||
| 306 | \\ | ||
| 307 | \\pub fn assert(ok: bool) void { | ||
| 308 | \\ if (!ok) unreachable; // assertion failure | ||
| 309 | \\} | ||
| 310 | \\ | ||
| 311 | \\fn exit() noreturn { | ||
| 312 | \\ asm volatile ("syscall" | ||
| 313 | \\ : | ||
| 314 | \\ : [number] "{rax}" (231), | ||
| 315 | \\ [arg1] "{rdi}" (0) | ||
| 316 | \\ : "rcx", "r11", "memory" | ||
| 317 | \\ ); | ||
| 318 | \\ unreachable; | ||
| 319 | \\} | ||
| 320 | , | ||
| 321 | "", | ||
| 322 | ); | ||
| 323 | |||
| 324 | // More stress on the liveness detection. | ||
| 325 | case.addCompareOutput( | ||
| 326 | \\export fn _start() noreturn { | ||
| 327 | \\ add(3, 4); | ||
| 328 | \\ | ||
| 329 | \\ exit(); | ||
| 330 | \\} | ||
| 331 | \\ | ||
| 332 | \\fn add(a: u32, b: u32) void { | ||
| 333 | \\ const c = a + b; // 7 | ||
| 334 | \\ const d = a + c; // 10 | ||
| 335 | \\ const e = d + b; // 14 | ||
| 336 | \\ const f = d + e; // 24 | ||
| 337 | \\ const g = e + f; // 38 | ||
| 338 | \\ const h = f + g; // 62 | ||
| 339 | \\ const i = g + h; // 100 | ||
| 340 | \\ assert(i == 100); | ||
| 341 | \\} | ||
| 342 | \\ | ||
| 343 | \\pub fn assert(ok: bool) void { | ||
| 344 | \\ if (!ok) unreachable; // assertion failure | ||
| 345 | \\} | ||
| 346 | \\ | ||
| 347 | \\fn exit() noreturn { | ||
| 348 | \\ asm volatile ("syscall" | ||
| 349 | \\ : | ||
| 350 | \\ : [number] "{rax}" (231), | ||
| 351 | \\ [arg1] "{rdi}" (0) | ||
| 352 | \\ : "rcx", "r11", "memory" | ||
| 353 | \\ ); | ||
| 354 | \\ unreachable; | ||
| 355 | \\} | ||
| 356 | , | ||
| 357 | "", | ||
| 358 | ); | ||
| 359 | |||
| 360 | // Requires a second move. The register allocator should figure out to re-use rax. | ||
| 361 | case.addCompareOutput( | ||
| 362 | \\export fn _start() noreturn { | ||
| 363 | \\ add(3, 4); | ||
| 364 | \\ | ||
| 365 | \\ exit(); | ||
| 366 | \\} | ||
| 367 | \\ | ||
| 368 | \\fn add(a: u32, b: u32) void { | ||
| 369 | \\ const c = a + b; // 7 | ||
| 370 | \\ const d = a + c; // 10 | ||
| 371 | \\ const e = d + b; // 14 | ||
| 372 | \\ const f = d + e; // 24 | ||
| 373 | \\ const g = e + f; // 38 | ||
| 374 | \\ const h = f + g; // 62 | ||
| 375 | \\ const i = g + h; // 100 | ||
| 376 | \\ const j = i + d; // 110 | ||
| 377 | \\ assert(j == 110); | ||
| 378 | \\} | ||
| 379 | \\ | ||
| 380 | \\pub fn assert(ok: bool) void { | ||
| 381 | \\ if (!ok) unreachable; // assertion failure | ||
| 382 | \\} | ||
| 383 | \\ | ||
| 384 | \\fn exit() noreturn { | ||
| 385 | \\ asm volatile ("syscall" | ||
| 386 | \\ : | ||
| 387 | \\ : [number] "{rax}" (231), | ||
| 388 | \\ [arg1] "{rdi}" (0) | ||
| 389 | \\ : "rcx", "r11", "memory" | ||
| 390 | \\ ); | ||
| 391 | \\ unreachable; | ||
| 392 | \\} | ||
| 393 | , | ||
| 394 | "", | ||
| 395 | ); | ||
| 396 | |||
| 397 | // Now we test integer return values. | ||
| 398 | case.addCompareOutput( | ||
| 399 | \\export fn _start() noreturn { | ||
| 400 | \\ assert(add(3, 4) == 7); | ||
| 401 | \\ assert(add(20, 10) == 30); | ||
| 402 | \\ | ||
| 403 | \\ exit(); | ||
| 404 | \\} | ||
| 405 | \\ | ||
| 406 | \\fn add(a: u32, b: u32) u32 { | ||
| 407 | \\ return a + b; | ||
| 408 | \\} | ||
| 409 | \\ | ||
| 410 | \\pub fn assert(ok: bool) void { | ||
| 411 | \\ if (!ok) unreachable; // assertion failure | ||
| 412 | \\} | ||
| 413 | \\ | ||
| 414 | \\fn exit() noreturn { | ||
| 415 | \\ asm volatile ("syscall" | ||
| 416 | \\ : | ||
| 417 | \\ : [number] "{rax}" (231), | ||
| 418 | \\ [arg1] "{rdi}" (0) | ||
| 419 | \\ : "rcx", "r11", "memory" | ||
| 420 | \\ ); | ||
| 421 | \\ unreachable; | ||
| 422 | \\} | ||
| 423 | , | ||
| 424 | "", | ||
| 425 | ); | ||
| 426 | |||
| 427 | // Local mutable variables. | ||
| 428 | case.addCompareOutput( | ||
| 429 | \\export fn _start() noreturn { | ||
| 430 | \\ assert(add(3, 4) == 7); | ||
| 431 | \\ assert(add(20, 10) == 30); | ||
| 432 | \\ | ||
| 433 | \\ exit(); | ||
| 434 | \\} | ||
| 435 | \\ | ||
| 436 | \\fn add(a: u32, b: u32) u32 { | ||
| 437 | \\ var x: u32 = undefined; | ||
| 438 | \\ x = 0; | ||
| 439 | \\ x += a; | ||
| 440 | \\ x += b; | ||
| 441 | \\ return x; | ||
| 442 | \\} | ||
| 443 | \\ | ||
| 444 | \\pub fn assert(ok: bool) void { | ||
| 445 | \\ if (!ok) unreachable; // assertion failure | ||
| 446 | \\} | ||
| 447 | \\ | ||
| 448 | \\fn exit() noreturn { | ||
| 449 | \\ asm volatile ("syscall" | ||
| 450 | \\ : | ||
| 451 | \\ : [number] "{rax}" (231), | ||
| 452 | \\ [arg1] "{rdi}" (0) | ||
| 453 | \\ : "rcx", "r11", "memory" | ||
| 454 | \\ ); | ||
| 455 | \\ unreachable; | ||
| 456 | \\} | ||
| 457 | , | ||
| 458 | "", | ||
| 459 | ); | ||
| 460 | |||
| 461 | // Optionals | ||
| 462 | case.addCompareOutput( | ||
| 463 | \\export fn _start() noreturn { | ||
| 464 | \\ const a: u32 = 2; | ||
| 465 | \\ const b: ?u32 = a; | ||
| 466 | \\ const c = b.?; | ||
| 467 | \\ if (c != 2) unreachable; | ||
| 468 | \\ | ||
| 469 | \\ exit(); | ||
| 470 | \\} | ||
| 471 | \\ | ||
| 472 | \\fn exit() noreturn { | ||
| 473 | \\ asm volatile ("syscall" | ||
| 474 | \\ : | ||
| 475 | \\ : [number] "{rax}" (231), | ||
| 476 | \\ [arg1] "{rdi}" (0) | ||
| 477 | \\ : "rcx", "r11", "memory" | ||
| 478 | \\ ); | ||
| 479 | \\ unreachable; | ||
| 480 | \\} | ||
| 481 | , | ||
| 482 | "", | ||
| 483 | ); | ||
| 484 | |||
| 485 | // While loops | ||
| 486 | case.addCompareOutput( | ||
| 487 | \\export fn _start() noreturn { | ||
| 488 | \\ var i: u32 = 0; | ||
| 489 | \\ while (i < 4) : (i += 1) print(); | ||
| 490 | \\ assert(i == 4); | ||
| 491 | \\ | ||
| 492 | \\ exit(); | ||
| 493 | \\} | ||
| 494 | \\ | ||
| 495 | \\fn print() void { | ||
| 496 | \\ asm volatile ("syscall" | ||
| 497 | \\ : | ||
| 498 | \\ : [number] "{rax}" (1), | ||
| 499 | \\ [arg1] "{rdi}" (1), | ||
| 500 | \\ [arg2] "{rsi}" (@ptrToInt("hello\n")), | ||
| 501 | \\ [arg3] "{rdx}" (6) | ||
| 502 | \\ : "rcx", "r11", "memory" | ||
| 503 | \\ ); | ||
| 504 | \\ return; | ||
| 505 | \\} | ||
| 506 | \\ | ||
| 507 | \\pub fn assert(ok: bool) void { | ||
| 508 | \\ if (!ok) unreachable; // assertion failure | ||
| 509 | \\} | ||
| 510 | \\ | ||
| 511 | \\fn exit() noreturn { | ||
| 512 | \\ asm volatile ("syscall" | ||
| 513 | \\ : | ||
| 514 | \\ : [number] "{rax}" (231), | ||
| 515 | \\ [arg1] "{rdi}" (0) | ||
| 516 | \\ : "rcx", "r11", "memory" | ||
| 517 | \\ ); | ||
| 518 | \\ unreachable; | ||
| 519 | \\} | ||
| 520 | , | ||
| 521 | "hello\nhello\nhello\nhello\n", | ||
| 522 | ); | ||
| 523 | |||
| 524 | // Labeled blocks (no conditional branch) | ||
| 525 | case.addCompareOutput( | ||
| 526 | \\export fn _start() noreturn { | ||
| 527 | \\ assert(add(3, 4) == 20); | ||
| 528 | \\ | ||
| 529 | \\ exit(); | ||
| 530 | \\} | ||
| 531 | \\ | ||
| 532 | \\fn add(a: u32, b: u32) u32 { | ||
| 533 | \\ const x: u32 = blk: { | ||
| 534 | \\ const c = a + b; // 7 | ||
| 535 | \\ const d = a + c; // 10 | ||
| 536 | \\ const e = d + b; // 14 | ||
| 537 | \\ break :blk e; | ||
| 538 | \\ }; | ||
| 539 | \\ const y = x + a; // 17 | ||
| 540 | \\ const z = y + a; // 20 | ||
| 541 | \\ return z; | ||
| 542 | \\} | ||
| 543 | \\ | ||
| 544 | \\pub fn assert(ok: bool) void { | ||
| 545 | \\ if (!ok) unreachable; // assertion failure | ||
| 546 | \\} | ||
| 547 | \\ | ||
| 548 | \\fn exit() noreturn { | ||
| 549 | \\ asm volatile ("syscall" | ||
| 550 | \\ : | ||
| 551 | \\ : [number] "{rax}" (231), | ||
| 552 | \\ [arg1] "{rdi}" (0) | ||
| 553 | \\ : "rcx", "r11", "memory" | ||
| 554 | \\ ); | ||
| 555 | \\ unreachable; | ||
| 556 | \\} | ||
| 557 | , | ||
| 558 | "", | ||
| 559 | ); | ||
| 560 | |||
| 561 | // This catches a possible bug in the logic for re-using dying operands. | ||
| 562 | case.addCompareOutput( | ||
| 563 | \\export fn _start() noreturn { | ||
| 564 | \\ assert(add(3, 4) == 116); | ||
| 565 | \\ | ||
| 566 | \\ exit(); | ||
| 567 | \\} | ||
| 568 | \\ | ||
| 569 | \\fn add(a: u32, b: u32) u32 { | ||
| 570 | \\ const x: u32 = blk: { | ||
| 571 | \\ const c = a + b; // 7 | ||
| 572 | \\ const d = a + c; // 10 | ||
| 573 | \\ const e = d + b; // 14 | ||
| 574 | \\ const f = d + e; // 24 | ||
| 575 | \\ const g = e + f; // 38 | ||
| 576 | \\ const h = f + g; // 62 | ||
| 577 | \\ const i = g + h; // 100 | ||
| 578 | \\ const j = i + d; // 110 | ||
| 579 | \\ break :blk j; | ||
| 580 | \\ }; | ||
| 581 | \\ const y = x + a; // 113 | ||
| 582 | \\ const z = y + a; // 116 | ||
| 583 | \\ return z; | ||
| 584 | \\} | ||
| 585 | \\ | ||
| 586 | \\pub fn assert(ok: bool) void { | ||
| 587 | \\ if (!ok) unreachable; // assertion failure | ||
| 588 | \\} | ||
| 589 | \\ | ||
| 590 | \\fn exit() noreturn { | ||
| 591 | \\ asm volatile ("syscall" | ||
| 592 | \\ : | ||
| 593 | \\ : [number] "{rax}" (231), | ||
| 594 | \\ [arg1] "{rdi}" (0) | ||
| 595 | \\ : "rcx", "r11", "memory" | ||
| 596 | \\ ); | ||
| 597 | \\ unreachable; | ||
| 598 | \\} | ||
| 599 | , | ||
| 600 | "", | ||
| 601 | ); | ||
| 602 | |||
| 603 | // Character literals and multiline strings. | ||
| 604 | case.addCompareOutput( | ||
| 605 | \\export fn _start() noreturn { | ||
| 606 | \\ const ignore = | ||
| 607 | \\ \\ cool thx | ||
| 608 | \\ \\ | ||
| 609 | \\ ; | ||
| 610 | \\ add('ぁ', '\x03'); | ||
| 611 | \\ | ||
| 612 | \\ exit(); | ||
| 613 | \\} | ||
| 614 | \\ | ||
| 615 | \\fn add(a: u32, b: u32) void { | ||
| 616 | \\ assert(a + b == 12356); | ||
| 617 | \\} | ||
| 618 | \\ | ||
| 619 | \\pub fn assert(ok: bool) void { | ||
| 620 | \\ if (!ok) unreachable; // assertion failure | ||
| 621 | \\} | ||
| 622 | \\ | ||
| 623 | \\fn exit() noreturn { | ||
| 624 | \\ asm volatile ("syscall" | ||
| 625 | \\ : | ||
| 626 | \\ : [number] "{rax}" (231), | ||
| 627 | \\ [arg1] "{rdi}" (0) | ||
| 628 | \\ : "rcx", "r11", "memory" | ||
| 629 | \\ ); | ||
| 630 | \\ unreachable; | ||
| 631 | \\} | ||
| 632 | , | ||
| 633 | "", | ||
| 634 | ); | ||
| 635 | |||
| 636 | // Global const. | ||
| 637 | case.addCompareOutput( | ||
| 638 | \\export fn _start() noreturn { | ||
| 639 | \\ add(aa, bb); | ||
| 640 | \\ | ||
| 641 | \\ exit(); | ||
| 642 | \\} | ||
| 643 | \\ | ||
| 644 | \\const aa = 'ぁ'; | ||
| 645 | \\const bb = '\x03'; | ||
| 646 | \\ | ||
| 647 | \\fn add(a: u32, b: u32) void { | ||
| 648 | \\ assert(a + b == 12356); | ||
| 649 | \\} | ||
| 650 | \\ | ||
| 651 | \\pub fn assert(ok: bool) void { | ||
| 652 | \\ if (!ok) unreachable; // assertion failure | ||
| 653 | \\} | ||
| 654 | \\ | ||
| 655 | \\fn exit() noreturn { | ||
| 656 | \\ asm volatile ("syscall" | ||
| 657 | \\ : | ||
| 658 | \\ : [number] "{rax}" (231), | ||
| 659 | \\ [arg1] "{rdi}" (0) | ||
| 660 | \\ : "rcx", "r11", "memory" | ||
| 661 | \\ ); | ||
| 662 | \\ unreachable; | ||
| 663 | \\} | ||
| 664 | , | ||
| 665 | "", | ||
| 666 | ); | ||
| 667 | } | ||
| 668 | |||
| 669 | { | ||
| 670 | var case = ctx.exe("wasm function calls", wasi); | ||
| 671 | |||
| 672 | case.addCompareOutput( | ||
| 673 | \\export fn _start() u32 { | ||
| 674 | \\ foo(); | ||
| 675 | \\ bar(); | ||
| 676 | \\ return 42; | ||
| 677 | \\} | ||
| 678 | \\fn foo() void { | ||
| 679 | \\ bar(); | ||
| 680 | \\ bar(); | ||
| 681 | \\} | ||
| 682 | \\fn bar() void {} | ||
| 683 | , | ||
| 684 | "42\n", | ||
| 685 | ); | ||
| 686 | |||
| 687 | case.addCompareOutput( | ||
| 688 | \\export fn _start() i64 { | ||
| 689 | \\ bar(); | ||
| 690 | \\ foo(); | ||
| 691 | \\ foo(); | ||
| 692 | \\ bar(); | ||
| 693 | \\ foo(); | ||
| 694 | \\ bar(); | ||
| 695 | \\ return 42; | ||
| 696 | \\} | ||
| 697 | \\fn foo() void { | ||
| 698 | \\ bar(); | ||
| 699 | \\} | ||
| 700 | \\fn bar() void {} | ||
| 701 | , | ||
| 702 | "42\n", | ||
| 703 | ); | ||
| 704 | |||
| 705 | case.addCompareOutput( | ||
| 706 | \\export fn _start() f32 { | ||
| 707 | \\ bar(); | ||
| 708 | \\ foo(); | ||
| 709 | \\ return 42.0; | ||
| 710 | \\} | ||
| 711 | \\fn foo() void { | ||
| 712 | \\ bar(); | ||
| 713 | \\ bar(); | ||
| 714 | \\ bar(); | ||
| 715 | \\} | ||
| 716 | \\fn bar() void {} | ||
| 717 | , | ||
| 718 | // This is what you get when you take the bits of the IEE-754 | ||
| 719 | // representation of 42.0 and reinterpret them as an unsigned | ||
| 720 | // integer. Guess that's a bug in wasmtime. | ||
| 721 | "1109917696\n", | ||
| 722 | ); | ||
| 723 | } | ||
| 724 | |||
| 725 | ctx.compileError("function redefinition", linux_x64, | ||
| 726 | \\fn entry() void {} | ||
| 727 | \\fn entry() void {} | ||
| 728 | , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); | ||
| 729 | |||
| 730 | ctx.compileError("extern variable has no type", linux_x64, | ||
| 731 | \\comptime { | ||
| 732 | \\ _ = foo; | ||
| 733 | \\} | ||
| 734 | \\extern var foo; | ||
| 735 | , &[_][]const u8{":4:1: error: unable to infer variable type"}); | ||
| 8 | } | 736 | } |
test/standalone/global_linkage/obj1.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | extern var internal_integer: usize = 1; | 1 | var internal_integer: usize = 1; |
| 2 | extern var obj1_integer: usize = 421; | 2 | var obj1_integer: usize = 421; |
| 3 | 3 | ||
| 4 | comptime { | 4 | comptime { |
| 5 | @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal }); | 5 | @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal }); |
test/standalone/global_linkage/obj2.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | extern var internal_integer: usize = 2; | 1 | var internal_integer: usize = 2; |
| 2 | extern var obj2_integer: usize = 422; | 2 | var obj2_integer: usize = 422; |
| 3 | 3 | ||
| 4 | comptime { | 4 | comptime { |
| 5 | @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal }); | 5 | @export(internal_integer, .{ .name = "internal_integer", .linkage = .Internal }); |
test/translate_c.zig+18-3| ... | @@ -3,6 +3,20 @@ const std = @import("std"); | ... | @@ -3,6 +3,20 @@ const std = @import("std"); |
| 3 | const CrossTarget = std.zig.CrossTarget; | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.TranslateCContext) void { | 5 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 6 | cases.add("extern variable in block scope", | ||
| 7 | \\float bar; | ||
| 8 | \\int foo() { | ||
| 9 | \\ _Thread_local static int bar = 2; | ||
| 10 | \\} | ||
| 11 | , &[_][]const u8{ | ||
| 12 | \\pub export var bar: f32 = @import("std").mem.zeroes(f32); | ||
| 13 | \\threadlocal var bar_1: c_int = 2; | ||
| 14 | \\pub export fn foo() c_int { | ||
| 15 | \\ _ = bar_1; | ||
| 16 | \\ return 0; | ||
| 17 | \\} | ||
| 18 | }); | ||
| 19 | |||
| 6 | cases.add("missing return stmt", | 20 | cases.add("missing return stmt", |
| 7 | \\int foo() {} | 21 | \\int foo() {} |
| 8 | \\int bar() { | 22 | \\int bar() { |
| ... | @@ -466,7 +480,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -466,7 +480,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 466 | , &[_][]const u8{ | 480 | , &[_][]const u8{ |
| 467 | \\pub extern var extern_var: c_int; | 481 | \\pub extern var extern_var: c_int; |
| 468 | \\pub const int_var: c_int = 13; | 482 | \\pub const int_var: c_int = 13; |
| 469 | \\pub export var foo: c_int = undefined; | 483 | \\pub export var foo: c_int = @import("std").mem.zeroes(c_int); |
| 470 | }); | 484 | }); |
| 471 | 485 | ||
| 472 | cases.add("const ptr initializer", | 486 | cases.add("const ptr initializer", |
| ... | @@ -480,8 +494,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -480,8 +494,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 480 | \\ static const char v2[] = "2.2.2"; | 494 | \\ static const char v2[] = "2.2.2"; |
| 481 | \\} | 495 | \\} |
| 482 | , &[_][]const u8{ | 496 | , &[_][]const u8{ |
| 497 | \\const v2: [*c]const u8 = "2.2.2"; | ||
| 483 | \\pub export fn foo() void { | 498 | \\pub export fn foo() void { |
| 484 | \\ const v2: [*c]const u8 = "2.2.2"; | 499 | \\ _ = v2; |
| 485 | \\} | 500 | \\} |
| 486 | }); | 501 | }); |
| 487 | 502 | ||
| ... | @@ -1327,7 +1342,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1327,7 +1342,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1327 | \\static char arr1[] = "hello"; | 1342 | \\static char arr1[] = "hello"; |
| 1328 | \\char arr2[] = "hello"; | 1343 | \\char arr2[] = "hello"; |
| 1329 | , &[_][]const u8{ | 1344 | , &[_][]const u8{ |
| 1330 | \\pub extern var arr0: [*c]u8 = "hello"; | 1345 | \\pub export var arr0: [*c]u8 = "hello"; |
| 1331 | \\pub var arr1: [*c]u8 = "hello"; | 1346 | \\pub var arr1: [*c]u8 = "hello"; |
| 1332 | \\pub export var arr2: [*c]u8 = "hello"; | 1347 | \\pub export var arr2: [*c]u8 = "hello"; |
| 1333 | }); | 1348 | }); |
tools/process_headers.zig+1-1| ... | @@ -313,7 +313,7 @@ pub fn main() !void { | ... | @@ -313,7 +313,7 @@ pub fn main() !void { |
| 313 | var max_bytes_saved: usize = 0; | 313 | var max_bytes_saved: usize = 0; |
| 314 | var total_bytes: usize = 0; | 314 | var total_bytes: usize = 0; |
| 315 | 315 | ||
| 316 | var hasher = std.crypto.Sha256.init(); | 316 | var hasher = std.crypto.hash.sha2.Sha256.init(.{}); |
| 317 | 317 | ||
| 318 | for (libc_targets) |libc_target| { | 318 | for (libc_targets) |libc_target| { |
| 319 | const dest_target = DestTarget{ | 319 | const dest_target = DestTarget{ |